summaryrefslogtreecommitdiff
path: root/src/mongo/db/session_catalog_mongod.cpp
diff options
context:
space:
mode:
authorAndy Schwerin <schwerin@mongodb.com>2019-01-10 15:01:36 -0500
committerAndy Schwerin <schwerin@mongodb.com>2019-01-10 15:01:36 -0500
commitfacdcf14cfec192876a373fc49163769215327d8 (patch)
treee461394175313e947f950b8b968e57afb808ff70 /src/mongo/db/session_catalog_mongod.cpp
parente276f7d9b5262f99ec374018c3d29c53b8f757e4 (diff)
downloadmongo-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.cpp32
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);