diff options
author | Luke Chen <luke.chen@mongodb.com> | 2019-07-19 17:41:16 +1000 |
---|---|---|
committer | Luke Chen <luke.chen@mongodb.com> | 2019-07-19 17:41:16 +1000 |
commit | 1883b014d6be5929082a1ddd5b5b8a6a8f9facef (patch) | |
tree | f6940c7e8f3914bd8cbaff9d859aae1a0d9c6eb9 /src/third_party/wiredtiger/src/btree/row_modify.c | |
parent | ffdb59938db0dfc8ec48e8b74df7a54d07b3a128 (diff) | |
download | mongo-1883b014d6be5929082a1ddd5b5b8a6a8f9facef.tar.gz |
Import wiredtiger: 6746e5e700b75903480a57a9d77b72df46dbc944 from branch mongodb-4.2
ref: 3f68638211..6746e5e700
for: 4.3.1
WT-4899 Fix bugs that could allow more than one birthmark in an update chain
WT-4900 Implement all_durable timestamp
WT-4908 Add verbose failure messages during the metadata recovery phase
WT-4930 Fix likely coding errors of error returns after jump to error
WT-4931 Fix clang testing in Jenkins Pull Request testing
WT-4932 Add logging files to WiredTiger big/little-endian testing
WT-4934 Fix and update clang-tidy testing
WT-4936 Update clang-scan expected output
WT-4937 Fix verify_wt_datafiles.sh to run if no LD_LIBRARY_PATH variable set
WT-4939 Fix a test for skipping checkpoints which never returns success
WT-4940 Reconciliation should set prepared/uncommitted for each update
WT-4943 Fix a bug where uncommitted updates could be discarded
Diffstat (limited to 'src/third_party/wiredtiger/src/btree/row_modify.c')
-rw-r--r-- | src/third_party/wiredtiger/src/btree/row_modify.c | 46 |
1 files changed, 32 insertions, 14 deletions
diff --git a/src/third_party/wiredtiger/src/btree/row_modify.c b/src/third_party/wiredtiger/src/btree/row_modify.c index 9cd2d4df2c3..efa6433c9b2 100644 --- a/src/third_party/wiredtiger/src/btree/row_modify.c +++ b/src/third_party/wiredtiger/src/btree/row_modify.c @@ -308,11 +308,12 @@ __wt_update_alloc(WT_SESSION_IMPL *session, const WT_ITEM *value, * Check for obsolete updates. */ WT_UPDATE * -__wt_update_obsolete_check( - WT_SESSION_IMPL *session, WT_PAGE *page, WT_UPDATE *upd) +__wt_update_obsolete_check(WT_SESSION_IMPL *session, + WT_PAGE *page, WT_UPDATE *upd, bool update_accounting) { WT_TXN_GLOBAL *txn_global; - WT_UPDATE *first, *next; + WT_UPDATE *first, *next, *prev; + size_t size; uint64_t oldest, stable; u_int count, upd_seen, upd_unstable; @@ -333,28 +334,34 @@ __wt_update_obsolete_check( * * Only updates with globally visible, self-contained data can terminate * update chains. + * + * Birthmarks are a special case: once a birthmark becomes obsolete, it + * can be discarded and subsequent reads will see the on-page value (as + * expected). Inserting updates into the lookaside table relies on + * this behavior to avoid creating update chains with multiple + * birthmarks. */ - for (first = NULL, count = 0; upd != NULL; upd = upd->next, count++) { + for (first = prev = NULL, count = 0; + upd != NULL; + prev = upd, upd = upd->next, count++) { if (upd->txnid == WT_TXN_ABORTED) continue; - /* - * If the update isn't visible, it is not obsolete. - */ ++upd_seen; if (!__wt_txn_upd_visible_all(session, upd)) { first = NULL; /* - * While we're here, also check for the update - * being kept only for timestamp history to - * gauge updates being kept due to history. + * While we're here, also check for the update being + * kept only for timestamp history to gauge updates + * being kept due to history. */ if (upd->start_ts != WT_TS_NONE && upd->start_ts >= oldest && upd->start_ts < stable) ++upd_unstable; - } else if (first == NULL && (WT_UPDATE_DATA_VALUE(upd) || - upd->type == WT_UPDATE_BIRTHMARK)) - first = upd; + } else if (first == NULL && upd->type == WT_UPDATE_BIRTHMARK) + first = prev; + else if (first == NULL && WT_UPDATE_DATA_VALUE(upd)) + first = upd; } __wt_cache_update_lookaside_score(session, upd_seen, upd_unstable); @@ -367,8 +374,19 @@ __wt_update_obsolete_check( */ if (first != NULL && (next = first->next) != NULL && - __wt_atomic_cas_ptr(&first->next, next, NULL)) + __wt_atomic_cas_ptr(&first->next, next, NULL)) { + /* + * Decrement the dirty byte count while holding the page lock, + * else we can race with checkpoints cleaning a page. + */ + if (update_accounting) { + for (size = 0, upd = next; upd != NULL; upd = upd->next) + size += WT_UPDATE_MEMSIZE(upd); + if (size != 0) + __wt_cache_page_inmem_decr(session, page, size); + } return (next); + } /* * If the list is long, don't retry checks on this page until the |