summaryrefslogtreecommitdiff
path: root/src/mongo/db/session.h
diff options
context:
space:
mode:
authorJudah Schvimer <judah@mongodb.com>2018-07-03 14:45:31 -0400
committerJudah Schvimer <judah@mongodb.com>2018-07-03 14:45:31 -0400
commitcc39290b6580d638da957506ca8660ef0d015d91 (patch)
treefcc6987c1cd4f5dd20a9e060cf67538350ef0c1f /src/mongo/db/session.h
parent57d7938c49da06122d4d43054ff89e1881d0209f (diff)
downloadmongo-cc39290b6580d638da957506ca8660ef0d015d91.tar.gz
SERVER-35729 Create explicit Session state transition table
Diffstat (limited to 'src/mongo/db/session.h')
-rw-r--r--src/mongo/db/session.h104
1 files changed, 83 insertions, 21 deletions
diff --git a/src/mongo/db/session.h b/src/mongo/db/session.h
index 53a22f0cc82..4e39a5295ed 100644
--- a/src/mongo/db/session.h
+++ b/src/mongo/db/session.h
@@ -315,17 +315,17 @@ public:
*/
bool inMultiDocumentTransaction() const {
stdx::lock_guard<stdx::mutex> lk(_mutex);
- return _inMultiDocumentTransaction(lk);
+ return _txnState.inMultiDocumentTransaction(lk);
};
bool transactionIsCommitted() const {
stdx::lock_guard<stdx::mutex> lk(_mutex);
- return _txnState == MultiDocumentTransactionState::kCommitted;
+ return _txnState.isCommitted(lk);
}
bool transactionIsAborted() const {
stdx::lock_guard<stdx::mutex> lk(_mutex);
- return _txnState == MultiDocumentTransactionState::kAborted;
+ return _txnState.isAborted(lk);
}
/**
@@ -385,6 +385,16 @@ public:
static boost::optional<repl::OplogEntry> createMatchingTransactionTableUpdate(
const repl::OplogEntry& entry);
+ void transitionToPreparedforTest() {
+ stdx::lock_guard<stdx::mutex> lk(_mutex);
+ _txnState.transitionTo(lk, TransitionTable::State::kPrepared);
+ }
+
+ void transitionToCommittingforTest() {
+ stdx::lock_guard<stdx::mutex> lk(_mutex);
+ _txnState.transitionTo(lk, TransitionTable::State::kCommitting);
+ }
+
private:
// Holds function which determines whether the CursorManager has client cursor references for a
// given transaction.
@@ -400,11 +410,6 @@ private:
// Checks if there is a conflicting operation on the current Session
void _checkValid(WithLock) const;
- bool _inMultiDocumentTransaction(WithLock) const {
- return _txnState == MultiDocumentTransactionState::kInProgress ||
- _txnState == MultiDocumentTransactionState::kPrepared;
- }
-
// Checks that a new txnNumber is higher than the activeTxnNumber so
// we don't start a txn that is too old.
void _checkTxnValid(WithLock, TxnNumber txnNumber) const;
@@ -433,6 +438,74 @@ private:
std::vector<StmtId> stmtIdsWritten,
const repl::OpTime& lastStmtIdWriteTs);
+ /**
+ * Indicates the state of the current multi-document transaction, if any. If the transaction is
+ * in any state but kInProgress, no more operations can be collected. Once the transaction is in
+ * kPrepared, the transaction is not allowed to abort outside of an 'abortTransaction' command.
+ * At this point, aborting the transaction must log an 'abortTransaction' oplog entry.
+ */
+ class TransitionTable {
+ public:
+ enum class State { kNone, kInProgress, kPrepared, kCommitting, kCommitted, kAborted };
+
+ /**
+ * Transitions the session from the current state to the new state. If transition validation
+ * is not relaxed, invariants if the transition is illegal.
+ */
+ enum class TransitionValidation { kValidateTransition, kRelaxTransitionValidation };
+ void transitionTo(
+ WithLock,
+ State newState,
+ TransitionValidation shouldValidate = TransitionValidation::kValidateTransition);
+
+ bool inMultiDocumentTransaction(WithLock) const {
+ return _state == State::kInProgress || _state == State::kPrepared;
+ }
+
+ bool isNone(WithLock) const {
+ return _state == State::kNone;
+ }
+
+ bool isInProgress(WithLock) const {
+ return _state == State::kInProgress;
+ }
+
+ bool isPrepared(WithLock) const {
+ return _state == State::kPrepared;
+ }
+
+ bool isCommitting(WithLock) const {
+ return _state == State::kCommitting;
+ }
+
+ bool isCommitted(WithLock) const {
+ return _state == State::kCommitted;
+ }
+
+ bool isAborted(WithLock) const {
+ return _state == State::kAborted;
+ }
+
+ std::string toString() const {
+ return toString(_state);
+ }
+
+ static std::string toString(State state);
+
+ private:
+ static bool _isLegalTransition(State oldState, State newState);
+
+ State _state = State::kNone;
+ };
+
+ friend std::ostream& operator<<(std::ostream& s, TransitionTable txnState) {
+ return (s << txnState.toString());
+ }
+
+ friend StringBuilder& operator<<(StringBuilder& s, TransitionTable txnState) {
+ return (s << txnState.toString());
+ }
+
void _abortArbitraryTransaction(WithLock);
// Releases stashed transaction resources to abort the transaction.
@@ -479,19 +552,8 @@ private:
// Holds transaction resources between network operations.
boost::optional<TxnResources> _txnResourceStash;
- // Indicates the state of the current multi-document transaction or snapshot read, if any. If
- // the transaction is in any state but kInProgress, no more operations can be collected. Once
- // the transaction is in kPrepared, the transaction is not allowed to abort outside of an
- // 'abortTransaction' command. At this point, aborting the transaction must log an
- // 'abortTransaction' oplog entry.
- enum class MultiDocumentTransactionState {
- kNone,
- kInProgress,
- kPrepared,
- kCommitting,
- kCommitted,
- kAborted
- } _txnState = MultiDocumentTransactionState::kNone;
+ // Maintains the transaction state and the transition table for legal state transitions.
+ TransitionTable _txnState;
// Holds oplog data for operations which have been applied in the current multi-document
// transaction. Not used for retryable writes.