diff options
author | Judah Schvimer <judah@mongodb.com> | 2018-07-03 14:45:31 -0400 |
---|---|---|
committer | Judah Schvimer <judah@mongodb.com> | 2018-07-03 14:45:31 -0400 |
commit | cc39290b6580d638da957506ca8660ef0d015d91 (patch) | |
tree | fcc6987c1cd4f5dd20a9e060cf67538350ef0c1f /src/mongo/db/session.h | |
parent | 57d7938c49da06122d4d43054ff89e1881d0209f (diff) | |
download | mongo-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.h | 104 |
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. |