summaryrefslogtreecommitdiff
path: root/src/third_party/wiredtiger/src/txn/txn_timestamp.c
diff options
context:
space:
mode:
authorLuke Chen <luke.chen@mongodb.com>2019-04-01 14:44:54 +1100
committerLuke Chen <luke.chen@mongodb.com>2019-04-01 14:44:54 +1100
commitd1beb371c96a7ad961eb8bb6e81d8c4fc0617f17 (patch)
treeaead1c88928db8282ed83b39ece5b37d034d7a13 /src/third_party/wiredtiger/src/txn/txn_timestamp.c
parent78a00318d39bc35c2091775e74bf0dde780d950f (diff)
downloadmongo-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.c86
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;
}
/*