diff options
author | Andy Schwerin <schwerin@mongodb.com> | 2019-01-10 15:01:36 -0500 |
---|---|---|
committer | Andy Schwerin <schwerin@mongodb.com> | 2019-01-10 15:01:36 -0500 |
commit | facdcf14cfec192876a373fc49163769215327d8 (patch) | |
tree | e461394175313e947f950b8b968e57afb808ff70 /src/mongo/db/session_catalog_mongod.cpp | |
parent | e276f7d9b5262f99ec374018c3d29c53b8f757e4 (diff) | |
download | mongo-facdcf14cfec192876a373fc49163769215327d8.tar.gz |
SERVER-38810 Simplify correct usage of locking in Session/SessionCatalog.
This patch introduces two new types for gaining access to sessions in
the session catalog, based on the context of the access. It leaves a
third way to access sessions, which is via
OperationContextSession::get().
The new types are ObservableSession and SessionToKill. With this
change, a thread may access a session in one of three ways:
(1) by binding the session to an OperationContext for regular use, by
instantiation of OperationContextSession or
MongoDOperationContextSession, as before.
(2) In the callback passed to SessionCatalog::scanSessions, in which
case the callback is passed an ObservableSession that represents
looking at a Session while the SessionCatalog mutex is locked and
while the bound OperationContext's client mutex is held, if the
session is currently checked out via methods (1) or (3).
(3) By calling SessionCatalog::checkOutSessionForKill, which returns a
KillableSession. This is used for cleaning a session up after it is
marked for kill.
This patch eliminates Session::_mutex, which is no longer required, as
the SessionCatalog::_mutex and the Client provide all necessary mutual
exclusion for the Session type itself.
Diffstat (limited to 'src/mongo/db/session_catalog_mongod.cpp')
-rw-r--r-- | src/mongo/db/session_catalog_mongod.cpp | 32 |
1 files changed, 17 insertions, 15 deletions
diff --git a/src/mongo/db/session_catalog_mongod.cpp b/src/mongo/db/session_catalog_mongod.cpp index c5fae50fe9c..dd6072af24e 100644 --- a/src/mongo/db/session_catalog_mongod.cpp +++ b/src/mongo/db/session_catalog_mongod.cpp @@ -74,8 +74,9 @@ auto getThreadPool(OperationContext* opCtx) { return &sessionTasksExecutor(opCtx->getServiceContext()).threadPool; } -void killSessionTokensFunction(OperationContext* opCtx, - std::shared_ptr<std::vector<Session::KillToken>> sessionKillTokens) { +void killSessionTokensFunction( + OperationContext* opCtx, + std::shared_ptr<std::vector<SessionCatalog::KillToken>> sessionKillTokens) { if (sessionKillTokens->empty()) return; @@ -105,7 +106,7 @@ void MongoDSessionCatalog::onStepUp(OperationContext* opCtx) { const auto catalog = SessionCatalog::get(opCtx); // The use of shared_ptr here is in order to work around the limitation of stdx::function that // the functor must be copyable. - auto sessionKillTokens = std::make_shared<std::vector<Session::KillToken>>(); + auto sessionKillTokens = std::make_shared<std::vector<SessionCatalog::KillToken>>(); // Scan all sessions and reacquire locks for prepared transactions. // There may be sessions that are checked out during this scan, but none of them @@ -115,14 +116,14 @@ void MongoDSessionCatalog::onStepUp(OperationContext* opCtx) { SessionKiller::Matcher matcher( KillAllSessionsByPatternSet{makeKillAllSessionsByPattern(opCtx)}); - catalog->scanSessions(matcher, [&](WithLock sessionCatalogLock, Session* session) { - const auto txnParticipant = TransactionParticipant::get(session); + catalog->scanSessions(matcher, [&](const ObservableSession& session) { + const auto txnParticipant = TransactionParticipant::get(session.get()); if (!txnParticipant->inMultiDocumentTransaction()) { - sessionKillTokens->emplace_back(session->kill(sessionCatalogLock)); + sessionKillTokens->emplace_back(session.kill()); } if (txnParticipant->transactionIsPrepared()) { - sessionIdToReacquireLocks.emplace_back(session->getSessionId()); + sessionIdToReacquireLocks.emplace_back(session.getSessionId()); } }); killSessionTokensFunction(opCtx, sessionKillTokens); @@ -131,10 +132,12 @@ void MongoDSessionCatalog::onStepUp(OperationContext* opCtx) { // Create a new opCtx because we need an empty locker to refresh the locks. auto newClient = opCtx->getServiceContext()->makeClient("restore-prepared-txn"); AlternativeClientRegion acr(newClient); - auto newOpCtx = cc().makeOperationContext(); for (const auto& sessionId : sessionIdToReacquireLocks) { - auto scopedSessionCheckOut = catalog->checkOutSession(newOpCtx.get(), sessionId); - auto txnParticipant = TransactionParticipant::get(scopedSessionCheckOut.get()); + auto newOpCtx = cc().makeOperationContext(); + newOpCtx->setLogicalSessionId(sessionId); + MongoDOperationContextSession ocs(newOpCtx.get()); + auto txnParticipant = + TransactionParticipant::get(OperationContextSession::get(newOpCtx.get())); txnParticipant->refreshLocksForPreparedTransaction(newOpCtx.get(), false); } } @@ -195,7 +198,7 @@ void MongoDSessionCatalog::invalidateSessions(OperationContext* opCtx, // The use of shared_ptr here is in order to work around the limitation of stdx::function that // the functor must be copyable. - auto sessionKillTokens = std::make_shared<std::vector<Session::KillToken>>(); + auto sessionKillTokens = std::make_shared<std::vector<SessionCatalog::KillToken>>(); if (singleSessionDoc) { sessionKillTokens->emplace_back(catalog->killSession(LogicalSessionId::parse( @@ -203,10 +206,9 @@ void MongoDSessionCatalog::invalidateSessions(OperationContext* opCtx, } else { SessionKiller::Matcher matcher( KillAllSessionsByPatternSet{makeKillAllSessionsByPattern(opCtx)}); - catalog->scanSessions( - matcher, [&sessionKillTokens](WithLock sessionCatalogLock, Session* session) { - sessionKillTokens->emplace_back(session->kill(sessionCatalogLock)); - }); + catalog->scanSessions(matcher, [&sessionKillTokens](const ObservableSession& session) { + sessionKillTokens->emplace_back(session.kill()); + }); } killSessionTokensFunction(opCtx, sessionKillTokens); |