summaryrefslogtreecommitdiff
path: root/src/third_party/wiredtiger/src/txn/txn.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/third_party/wiredtiger/src/txn/txn.c')
-rw-r--r--src/third_party/wiredtiger/src/txn/txn.c135
1 files changed, 105 insertions, 30 deletions
diff --git a/src/third_party/wiredtiger/src/txn/txn.c b/src/third_party/wiredtiger/src/txn/txn.c
index 191f7e0ba0f..09efb2924bf 100644
--- a/src/third_party/wiredtiger/src/txn/txn.c
+++ b/src/third_party/wiredtiger/src/txn/txn.c
@@ -445,12 +445,11 @@ __wt_txn_config(WT_SESSION_IMPL *session, const char *cfg[])
WT_RET(__wt_txn_parse_timestamp(
session, "read", &txn->read_timestamp, &cval));
- __wt_readlock(session, &txn_global->rwlock);
- __wt_timestamp_set(
- &oldest_timestamp, &txn_global->oldest_timestamp);
- __wt_timestamp_set(
- &stable_timestamp, &txn_global->stable_timestamp);
- __wt_readunlock(session, &txn_global->rwlock);
+ WT_WITH_TIMESTAMP_READLOCK(session, &txn_global->rwlock,
+ __wt_timestamp_set(
+ &oldest_timestamp, &txn_global->oldest_timestamp);
+ __wt_timestamp_set(
+ &stable_timestamp, &txn_global->stable_timestamp));
if (__wt_timestamp_cmp(
&txn->read_timestamp, &oldest_timestamp) < 0)
WT_RET_MSG(session, EINVAL,
@@ -568,18 +567,20 @@ __wt_txn_commit(WT_SESSION_IMPL *session, const char *cfg[])
WT_CONNECTION_IMPL *conn;
WT_DECL_RET;
WT_TXN *txn;
+ WT_TXN_GLOBAL *txn_global;
WT_TXN_OP *op;
+ u_int i;
+ bool did_update, locked;
#ifdef HAVE_TIMESTAMPS
- WT_TXN_GLOBAL *txn_global = &S2C(session)->txn_global;
wt_timestamp_t prev_commit_timestamp;
bool update_timestamp;
#endif
- u_int i;
- bool did_update;
txn = &session->txn;
conn = S2C(session);
+ txn_global = &conn->txn_global;
did_update = txn->mod_count != 0;
+ locked = false;
WT_ASSERT(session, F_ISSET(txn, WT_TXN_RUNNING));
WT_ASSERT(session, !F_ISSET(txn, WT_TXN_ERROR) || !did_update);
@@ -665,6 +666,14 @@ __wt_txn_commit(WT_SESSION_IMPL *session, const char *cfg[])
* This is particularly important for checkpoints.
*/
__wt_txn_release_snapshot(session);
+ /*
+ * We hold the visibility lock for reading from the time
+ * we write our log record until the time we release our
+ * transaction so that the LSN any checkpoint gets will
+ * always reflect visible data.
+ */
+ __wt_readlock(session, &txn_global->visibility_rwlock);
+ locked = true;
WT_ERR(__wt_txn_log_commit(session, cfg));
}
@@ -687,9 +696,12 @@ __wt_txn_commit(WT_SESSION_IMPL *session, const char *cfg[])
#ifdef HAVE_TIMESTAMPS
if (F_ISSET(txn, WT_TXN_HAS_TS_COMMIT) &&
- op->type != WT_TXN_OP_BASIC_TS)
+ op->type != WT_TXN_OP_BASIC_TS) {
+ WT_ASSERT(session,
+ op->fileid != WT_METAFILE_ID);
__wt_timestamp_set(&op->u.upd->timestamp,
&txn->commit_timestamp);
+ }
#endif
break;
@@ -724,14 +736,15 @@ __wt_txn_commit(WT_SESSION_IMPL *session, const char *cfg[])
#endif
__wt_txn_release(session);
+ if (locked)
+ __wt_readunlock(session, &txn_global->visibility_rwlock);
#ifdef HAVE_TIMESTAMPS
/* First check if we've already committed something in the future. */
if (update_timestamp) {
- __wt_readlock(session, &txn_global->rwlock);
- __wt_timestamp_set(
- &prev_commit_timestamp, &txn_global->commit_timestamp);
- __wt_readunlock(session, &txn_global->rwlock);
+ WT_WITH_TIMESTAMP_READLOCK(session, &txn_global->rwlock,
+ __wt_timestamp_set(
+ &prev_commit_timestamp, &txn_global->commit_timestamp));
update_timestamp = __wt_timestamp_cmp(
&txn->commit_timestamp, &prev_commit_timestamp) > 0;
}
@@ -760,6 +773,8 @@ err: /*
* !!!
* Nothing can fail after this point.
*/
+ if (locked)
+ __wt_readunlock(session, &txn_global->visibility_rwlock);
WT_TRET(__wt_txn_rollback(session, cfg));
return (ret);
}
@@ -930,6 +945,7 @@ __wt_txn_global_init(WT_SESSION_IMPL *session, const char *cfg[])
WT_RET(__wt_spin_init(
session, &txn_global->id_lock, "transaction id lock"));
WT_RET(__wt_rwlock_init(session, &txn_global->rwlock));
+ WT_RET(__wt_rwlock_init(session, &txn_global->visibility_rwlock));
WT_RET(__wt_rwlock_init(session, &txn_global->commit_timestamp_rwlock));
TAILQ_INIT(&txn_global->commit_timestamph);
@@ -971,6 +987,7 @@ __wt_txn_global_destroy(WT_SESSION_IMPL *session)
__wt_rwlock_destroy(session, &txn_global->commit_timestamp_rwlock);
__wt_rwlock_destroy(session, &txn_global->read_timestamp_rwlock);
__wt_rwlock_destroy(session, &txn_global->nsnap_rwlock);
+ __wt_rwlock_destroy(session, &txn_global->visibility_rwlock);
__wt_free(session, txn_global->states);
}
@@ -981,10 +998,7 @@ __wt_txn_global_destroy(WT_SESSION_IMPL *session)
int
__wt_txn_global_shutdown(WT_SESSION_IMPL *session)
{
- WT_DECL_RET;
- WT_TXN_GLOBAL *txn_global;
-
- txn_global = &S2C(session)->txn_global;
+ bool txn_active;
/*
* We're shutting down. Make sure everything gets freed.
@@ -995,10 +1009,8 @@ __wt_txn_global_shutdown(WT_SESSION_IMPL *session)
* transaction ID will catch up with the current ID.
*/
for (;;) {
- WT_TRET(__wt_txn_update_oldest(session,
- WT_TXN_OLDEST_STRICT | WT_TXN_OLDEST_WAIT));
- if (txn_global->oldest_id == txn_global->current &&
- txn_global->metadata_pinned == txn_global->current)
+ WT_RET(__wt_txn_activity_check(session, &txn_active));
+ if (!txn_active)
break;
WT_STAT_CONN_INCR(session, txn_release_blocked);
@@ -1010,10 +1022,10 @@ __wt_txn_global_shutdown(WT_SESSION_IMPL *session)
* Now that all transactions have completed, no timestamps should be
* pinned.
*/
- __wt_timestamp_set_inf(&txn_global->pinned_timestamp);
+ __wt_timestamp_set_inf(&S2C(session)->txn_global.pinned_timestamp);
#endif
- return (ret);
+ return (0);
}
#if defined(HAVE_DIAGNOSTIC) || defined(HAVE_VERBOSE)
@@ -1031,7 +1043,9 @@ __wt_verbose_dump_txn(WT_SESSION_IMPL *session)
const char *iso_tag;
uint64_t id;
uint32_t i, session_cnt;
-
+#ifdef HAVE_TIMESTAMPS
+ char hex_timestamp[3][2 * WT_TIMESTAMP_SIZE + 1];
+#endif
conn = S2C(session);
txn_global = &conn->txn_global;
@@ -1042,10 +1056,35 @@ __wt_verbose_dump_txn(WT_SESSION_IMPL *session)
WT_RET(__wt_msg(session,
"last running ID: %" PRIu64, txn_global->last_running));
WT_RET(__wt_msg(session, "oldest ID: %" PRIu64, txn_global->oldest_id));
- WT_RET(__wt_msg(session,
- "oldest named snapshot ID: %" PRIu64, txn_global->nsnap_oldest_id));
- WT_RET(__wt_msg(session, "checkpoint running? %s",
+#ifdef HAVE_TIMESTAMPS
+ WT_RET(__wt_timestamp_to_hex_string(
+ session, hex_timestamp[0], &txn_global->commit_timestamp));
+ WT_RET(__wt_msg(session, "commit timestamp: %s", hex_timestamp[0]));
+ WT_RET(__wt_timestamp_to_hex_string(
+ session, hex_timestamp[0], &txn_global->oldest_timestamp));
+ WT_RET(__wt_msg(session, "oldest timestamp: %s", hex_timestamp[0]));
+ WT_RET(__wt_timestamp_to_hex_string(
+ session, hex_timestamp[0], &txn_global->pinned_timestamp));
+ WT_RET(__wt_msg(session, "pinned timestamp: %s", hex_timestamp[0]));
+ WT_RET(__wt_timestamp_to_hex_string(
+ session, hex_timestamp[0], &txn_global->stable_timestamp));
+ WT_RET(__wt_msg(session, "stable timestamp: %s", hex_timestamp[0]));
+ WT_RET(__wt_msg(session, "has_commit_timestamp: %s",
+ txn_global->has_commit_timestamp ? "yes" : "no"));
+ WT_RET(__wt_msg(session, "has_oldest_timestamp: %s",
+ txn_global->has_oldest_timestamp ? "yes" : "no"));
+ WT_RET(__wt_msg(session, "has_pinned_timestamp: %s",
+ txn_global->has_pinned_timestamp ? "yes" : "no"));
+ WT_RET(__wt_msg(session, "has_stable_timestamp: %s",
+ txn_global->has_stable_timestamp ? "yes" : "no"));
+ WT_RET(__wt_msg(session, "oldest_is_pinned: %s",
+ txn_global->oldest_is_pinned ? "yes" : "no"));
+ WT_RET(__wt_msg(session, "stable_is_pinned: %s",
+ txn_global->stable_is_pinned ? "yes" : "no"));
+#endif
+
+ WT_RET(__wt_msg(session, "checkpoint running: %s",
txn_global->checkpoint_running ? "yes" : "no"));
WT_RET(__wt_msg(session, "checkpoint generation: %" PRIu64,
__wt_gen(session, WT_GEN_CHECKPOINT)));
@@ -1054,9 +1093,11 @@ __wt_verbose_dump_txn(WT_SESSION_IMPL *session)
WT_RET(__wt_msg(session, "checkpoint txn ID: %" PRIu64,
txn_global->checkpoint_state.id));
+ WT_RET(__wt_msg(session,
+ "oldest named snapshot ID: %" PRIu64, txn_global->nsnap_oldest_id));
+
WT_ORDERED_READ(session_cnt, conn->session_cnt);
WT_RET(__wt_msg(session, "session count: %" PRIu32, session_cnt));
-
WT_RET(__wt_msg(session, "Transaction state of active sessions:"));
/*
@@ -1083,7 +1124,40 @@ __wt_verbose_dump_txn(WT_SESSION_IMPL *session)
iso_tag = "WT_ISO_SNAPSHOT";
break;
}
-
+#ifdef HAVE_TIMESTAMPS
+ WT_RET(__wt_timestamp_to_hex_string(
+ session, hex_timestamp[0], &txn->commit_timestamp));
+ WT_RET(__wt_timestamp_to_hex_string(
+ session, hex_timestamp[1], &txn->first_commit_timestamp));
+ WT_RET(__wt_timestamp_to_hex_string(
+ session, hex_timestamp[2], &txn->read_timestamp));
+ WT_RET(__wt_msg(session,
+ "ID: %8" PRIu64
+ ", mod count: %u"
+ ", pinned ID: %8" PRIu64
+ ", snap min: %" PRIu64
+ ", snap max: %" PRIu64
+ ", commit_timestamp: %s"
+ ", first_commit_timestamp: %s"
+ ", read_timestamp: %s"
+ ", metadata pinned ID: %" PRIu64
+ ", flags: 0x%08" PRIx32
+ ", name: %s"
+ ", isolation: %s",
+ id,
+ txn->mod_count,
+ s->pinned_id,
+ txn->snap_min,
+ txn->snap_max,
+ hex_timestamp[0],
+ hex_timestamp[1],
+ hex_timestamp[2],
+ s->metadata_pinned,
+ txn->flags,
+ conn->sessions[i].name == NULL ?
+ "EMPTY" : conn->sessions[i].name,
+ iso_tag));
+#else
WT_RET(__wt_msg(session,
"ID: %6" PRIu64
", mod count: %u"
@@ -1104,6 +1178,7 @@ __wt_verbose_dump_txn(WT_SESSION_IMPL *session)
conn->sessions[i].name == NULL ?
"EMPTY" : conn->sessions[i].name,
iso_tag));
+#endif
}
WT_RET(__wt_msg(session, "%s", WT_DIVIDER));