diff options
author | Luke Chen <luke.chen@mongodb.com> | 2019-04-01 14:44:54 +1100 |
---|---|---|
committer | Luke Chen <luke.chen@mongodb.com> | 2019-04-01 14:44:54 +1100 |
commit | d1beb371c96a7ad961eb8bb6e81d8c4fc0617f17 (patch) | |
tree | aead1c88928db8282ed83b39ece5b37d034d7a13 /src/third_party/wiredtiger/src/txn/txn_timestamp.c | |
parent | 78a00318d39bc35c2091775e74bf0dde780d950f (diff) | |
download | mongo-d1beb371c96a7ad961eb8bb6e81d8c4fc0617f17.tar.gz |
Import wiredtiger: bb8086c4ed645854f19554198f391ea8c821f603 from branch mongodb-4.2
ref: 67066a329d..bb8086c4ed
for: 4.1.10
WT-4614 Trigger sweep immediately to reclaim space after a table drop
WT-4631 Always clear the read timestamp for transactions
WT-4636 Fix strace in syscall test
WT-4650 Coverity complaint: Constant expression result (CONSTANT_EXPRESSION_RESULT)
WT-4668 lint
Diffstat (limited to 'src/third_party/wiredtiger/src/txn/txn_timestamp.c')
-rw-r--r-- | src/third_party/wiredtiger/src/txn/txn_timestamp.c | 86 |
1 files changed, 55 insertions, 31 deletions
diff --git a/src/third_party/wiredtiger/src/txn/txn_timestamp.c b/src/third_party/wiredtiger/src/txn/txn_timestamp.c index 594be12e6b1..f4e340535ef 100644 --- a/src/third_party/wiredtiger/src/txn/txn_timestamp.c +++ b/src/third_party/wiredtiger/src/txn/txn_timestamp.c @@ -150,6 +150,20 @@ __wt_txn_parse_timestamp(WT_SESSION_IMPL *session, const char *name, } /* + * __txn_get_read_timestamp -- + * Get the read timestamp from the transaction. Additionally + * return bool to specify whether the transaction has set + * clear read queue flag. + */ +static bool +__txn_get_read_timestamp( + WT_TXN *txn, wt_timestamp_t *read_timestampp) +{ + WT_ORDERED_READ(*read_timestampp, txn->read_timestamp); + return (!txn->clear_read_q); +} + +/* * __txn_get_pinned_timestamp -- * Calculate the current pinned timestamp. */ @@ -160,7 +174,7 @@ __txn_get_pinned_timestamp( WT_CONNECTION_IMPL *conn; WT_TXN *txn; WT_TXN_GLOBAL *txn_global; - wt_timestamp_t tmp_ts; + wt_timestamp_t tmp_read_ts, tmp_ts; bool include_oldest, txn_has_write_lock; conn = S2C(session); @@ -189,15 +203,18 @@ __txn_get_pinned_timestamp( TAILQ_FOREACH(txn, &txn_global->read_timestamph, read_timestampq) { /* * Skip any transactions on the queue that are not active. + * Copy out value of read timestamp to prevent possible + * race where a transaction resets its read timestamp while + * we traverse the queue. */ - if (txn->clear_read_q) + if (!__txn_get_read_timestamp(txn, &tmp_read_ts)) continue; /* * A zero timestamp is possible here only when the oldest * timestamp is not accounted for. */ - if (tmp_ts == 0 || txn->read_timestamp < tmp_ts) - tmp_ts = txn->read_timestamp; + if (tmp_ts == 0 || tmp_read_ts < tmp_ts) + tmp_ts = tmp_read_ts; /* * We break on the first active txn on the list. */ @@ -638,22 +655,18 @@ __wt_txn_commit_timestamp_validate(WT_SESSION_IMPL *session, const char *name, * Compare against the prepare timestamp of the current transaction. * Return an error if the given timestamp is older than the prepare * timestamp. + * + * If roundup timestamps is configured, the commit timestamp will be + * rounded up to the prepare timestamp. */ - if (F_ISSET(txn, WT_TXN_PREPARE) && ts < txn->prepare_timestamp) { - /* - * If roundup timestamps is configured, the commit timestamp - * will be rounded up to the prepare timestamp. - */ - if (F_ISSET(txn, WT_TXN_TS_ROUND_PREPARED)) - ts = txn->prepare_timestamp; - else { - __wt_timestamp_to_string( - txn->prepare_timestamp, ts_string[0]); - WT_RET_MSG(session, EINVAL, - "%s timestamp %.*s older than the prepare " - "timestamp %s for this transaction", - name, (int)cval->len, cval->str, ts_string[0]); - } + if (F_ISSET(txn, WT_TXN_PREPARE) && + !F_ISSET(txn, WT_TXN_TS_ROUND_PREPARED) && + ts < txn->prepare_timestamp) { + __wt_timestamp_to_string(txn->prepare_timestamp, ts_string[0]); + WT_RET_MSG(session, EINVAL, + "%s timestamp %.*s older than the prepare " + "timestamp %s for this transaction", + name, (int)cval->len, cval->str, ts_string[0]); } if (F_ISSET(txn, WT_TXN_HAS_TS_DURABLE) && @@ -754,7 +767,7 @@ __wt_txn_parse_prepare_timestamp( WT_CONFIG_ITEM cval; WT_TXN *prev, *txn; WT_TXN_GLOBAL *txn_global; - wt_timestamp_t oldest_ts, timestamp; + wt_timestamp_t oldest_ts, timestamp, tmp_timestamp; char ts_string[2][WT_TS_INT_STRING_SIZE]; txn = &session->txn; @@ -779,18 +792,23 @@ __wt_txn_parse_prepare_timestamp( prev = TAILQ_LAST( &txn_global->read_timestamph, __wt_txn_rts_qh); while (prev != NULL) { - /* Skip self and non-active transactions. */ - if (prev->clear_read_q || prev == txn) { + /* + * Skip self and non-active transactions. Copy out value of + * read timestamp to prevent possible race where a transaction + * resets its read timestamp while we traverse the queue. + */ + if (!__txn_get_read_timestamp(prev, &tmp_timestamp) || + prev == txn) { prev = TAILQ_PREV( prev, __wt_txn_rts_qh, read_timestampq); continue; } - if (prev->read_timestamp >= timestamp) { + if (tmp_timestamp >= timestamp) { __wt_readunlock(session, &txn_global->read_timestamp_rwlock); __wt_timestamp_to_string( - prev->read_timestamp, ts_string[0]); + tmp_timestamp, ts_string[0]); WT_RET_MSG(session, EINVAL, "prepare timestamp %.*s must be greater than the " "latest active read timestamp %s ", @@ -1076,6 +1094,7 @@ __wt_txn_set_read_timestamp(WT_SESSION_IMPL *session) { WT_TXN *qtxn, *txn, *txn_tmp; WT_TXN_GLOBAL *txn_global; + wt_timestamp_t tmp_timestamp; uint64_t walked; txn = &session->txn; @@ -1127,11 +1146,14 @@ __wt_txn_set_read_timestamp(WT_SESSION_IMPL *session) */ qtxn = TAILQ_LAST( &txn_global->read_timestamph, __wt_txn_rts_qh); - while (qtxn != NULL && - qtxn->read_timestamp > txn->read_timestamp) { - ++walked; - qtxn = TAILQ_PREV( - qtxn, __wt_txn_rts_qh, read_timestampq); + while (qtxn != NULL) { + if (!__txn_get_read_timestamp(qtxn, &tmp_timestamp) || + tmp_timestamp > txn->read_timestamp) { + ++walked; + qtxn = TAILQ_PREV(qtxn, + __wt_txn_rts_qh, read_timestampq); + } else + break; } if (qtxn == NULL) { TAILQ_INSERT_HEAD(&txn_global->read_timestamph, @@ -1165,9 +1187,10 @@ __wt_txn_clear_read_timestamp(WT_SESSION_IMPL *session) txn = &session->txn; - if (!F_ISSET(txn, WT_TXN_PUBLIC_TS_READ)) + if (!F_ISSET(txn, WT_TXN_PUBLIC_TS_READ)) { + txn->read_timestamp = WT_TS_NONE; return; - + } #ifdef HAVE_DIAGNOSTIC { WT_TXN_GLOBAL *txn_global; @@ -1188,6 +1211,7 @@ __wt_txn_clear_read_timestamp(WT_SESSION_IMPL *session) */ WT_PUBLISH(txn->clear_read_q, true); WT_PUBLISH(txn->flags, flags); + txn->read_timestamp = WT_TS_NONE; } /* |