summaryrefslogtreecommitdiff
path: root/src/mongo/db/session_catalog.cpp
diff options
context:
space:
mode:
authorAndy Schwerin <schwerin@mongodb.com>2019-02-15 11:48:14 -0500
committerAndy Schwerin <schwerin@mongodb.com>2019-02-15 11:48:50 -0500
commit1d246814a058073f0c26981fff5fe67c16af3593 (patch)
treec107be594a1391c59a327e0a6d0d99a986bd3553 /src/mongo/db/session_catalog.cpp
parent77d9948209153dbbc3c654109583e5ebc5e57307 (diff)
downloadmongo-1d246814a058073f0c26981fff5fe67c16af3593.tar.gz
SERVER-38810 Use Session's concurrency control rules instead of internal mutexes in TransactionParticipant
This type simplifies and clarifies concurrency control in TransactionParticipant by: (1) Removing TP's own mutexes and using the Session concurrency control rules, instead. That is, certain state is only accessible when the Session is checked out, and requires no further locking. Other state is observable either while holding the client lock or while having checked out the Session. The latter type of state is modifiable only when having checked out the session and locked the client. (2) Separating the two types of state in (1) into separate sub-structures in TransactionParticipant, to make it clear who can access what state, (3) Putting all methods formerly on TransactionParticipant onto new member classes, TransactionParticipant::Participant and TransactionParticipant::Observer. The latter can only read the observable state from (1) above, and the participant may read or modify all of the state. The two types introduced by (3) are designed to enforce proper concurrency control by limiting access of their methods to the underlying TransactionParticipant member variables. The observer type has a private o() method which its other methods are required by convention to use in order to obtain read-only access to the Observable state of the TransactionParticipant. The participant type has the o() method plus an o(WithLock) method that allows mutation of the state while holding the client lock, and a p() method which allows reading and writing of the private state with no other locks. Please see the implementation in transaction_participant.cpp for examples. It is worth noting that with this change, locking the Client is not needed often and never for long, and there is no need for separate mutexes for participant state and monitoring state.
Diffstat (limited to 'src/mongo/db/session_catalog.cpp')
-rw-r--r--src/mongo/db/session_catalog.cpp20
1 files changed, 5 insertions, 15 deletions
diff --git a/src/mongo/db/session_catalog.cpp b/src/mongo/db/session_catalog.cpp
index 2ea94f9d5c6..cade0e53405 100644
--- a/src/mongo/db/session_catalog.cpp
+++ b/src/mongo/db/session_catalog.cpp
@@ -89,10 +89,7 @@ SessionCatalog::ScopedCheckedOutSession SessionCatalog::_checkOutSession(Operati
return !osession.currentOperation() && !osession._killed();
});
- {
- stdx::lock_guard<Client> lockClient(*opCtx->getClient());
- sri->session._checkoutOpCtx = opCtx;
- }
+ sri->session._checkoutOpCtx = opCtx;
return ScopedCheckedOutSession(
*this, std::move(sri), boost::none /* Not checked out for kill */);
@@ -114,10 +111,7 @@ SessionCatalog::SessionToKill SessionCatalog::checkOutSessionForKill(OperationCo
return !ObservableSession(ul, sri->session).currentOperation();
});
- {
- stdx::lock_guard<Client> lockClient(*opCtx->getClient());
- sri->session._checkoutOpCtx = opCtx;
- }
+ sri->session._checkoutOpCtx = opCtx;
return SessionToKill(ScopedCheckedOutSession(*this, std::move(sri), std::move(killToken)));
}
@@ -162,10 +156,7 @@ void SessionCatalog::_releaseSession(std::shared_ptr<SessionCatalog::SessionRunt
// operation context (meaning checked-out)
invariant(_sessions[sri->session.getSessionId()] == sri);
invariant(sri->session._checkoutOpCtx);
- {
- stdx::lock_guard<Client> lockClient(*sri->session._checkoutOpCtx->getClient());
- sri->session._checkoutOpCtx = nullptr;
- }
+ sri->session._checkoutOpCtx = nullptr;
sri->availableCondVar.notify_all();
if (killToken) {
@@ -185,10 +176,9 @@ SessionCatalog::KillToken ObservableSession::kill(ErrorCodes::Error reason) cons
// For currently checked-out sessions, interrupt the operation context so that the current owner
// can release the session
if (firstKiller && _session->_checkoutOpCtx) {
- stdx::lock_guard<Client> lg(*_session->_checkoutOpCtx->getClient());
-
+ invariant(_clientLock);
const auto serviceContext = _session->_checkoutOpCtx->getServiceContext();
- serviceContext->killOperation(lg, _session->_checkoutOpCtx, reason);
+ serviceContext->killOperation(_clientLock, _session->_checkoutOpCtx, reason);
}
return SessionCatalog::KillToken(getSessionId());