summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorKaloian Manassiev <kaloian.manassiev@mongodb.com>2018-11-14 09:00:30 -0500
committerKaloian Manassiev <kaloian.manassiev@mongodb.com>2018-11-16 03:26:19 -0500
commit943b0f7294b1f30483cc9d0fa4e870b00a68465d (patch)
tree8673dae5e032f4abf6aaba537acaf0a88f54bfeb /src/mongo
parent72789f5739982af1cbdb1dd4fa181c4924f657b3 (diff)
downloadmongo-943b0f7294b1f30483cc9d0fa4e870b00a68465d.tar.gz
SERVER-37665 Get rid of the 'checkOutSession' parameter of OperationContextSession
This simplifies the behaviour of the class and moves all the check-out decision taking to happen in the only consumer - the endpoint. Also renames OperationContextSessionMongoD to MongoDOperationContextSession in order to be in sync with the naming nomenclature of SessionCatalog and MongoDSessionCatalog.
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/db/SConscript1
-rw-r--r--src/mongo/db/op_observer_impl_test.cpp6
-rw-r--r--src/mongo/db/operation_context_session_mongod.cpp58
-rw-r--r--src/mongo/db/operation_context_session_mongod.h69
-rw-r--r--src/mongo/db/repl/apply_ops.cpp4
-rw-r--r--src/mongo/db/repl/do_txn_test.cpp5
-rw-r--r--src/mongo/db/repl/transaction_oplog_application.cpp10
-rw-r--r--src/mongo/db/s/session_catalog_migration_destination_test.cpp4
-rw-r--r--src/mongo/db/s/txn_two_phase_commit_cmds.cpp2
-rw-r--r--src/mongo/db/service_entry_point_common.cpp10
-rw-r--r--src/mongo/db/session_catalog.cpp61
-rw-r--r--src/mongo/db/session_catalog.h2
-rw-r--r--src/mongo/db/session_catalog_mongod.cpp19
-rw-r--r--src/mongo/db/session_catalog_mongod.h28
-rw-r--r--src/mongo/db/session_catalog_test.cpp52
-rw-r--r--src/mongo/db/transaction_participant_test.cpp24
-rw-r--r--src/mongo/dbtests/storage_timestamp_tests.cpp6
17 files changed, 127 insertions, 234 deletions
diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript
index c3c544a7cce..909faaaab47 100644
--- a/src/mongo/db/SConscript
+++ b/src/mongo/db/SConscript
@@ -680,7 +680,6 @@ env.Library(
target='catalog_raii',
source=[
'catalog_raii.cpp',
- 'operation_context_session_mongod.cpp',
'retryable_writes_stats.cpp',
'server_transactions_metrics.cpp',
'session_catalog_mongod.cpp',
diff --git a/src/mongo/db/op_observer_impl_test.cpp b/src/mongo/db/op_observer_impl_test.cpp
index 0c2501cd6f0..6bfd5a8ec48 100644
--- a/src/mongo/db/op_observer_impl_test.cpp
+++ b/src/mongo/db/op_observer_impl_test.cpp
@@ -40,7 +40,6 @@
#include "mongo/db/logical_clock.h"
#include "mongo/db/logical_time_validator.h"
#include "mongo/db/op_observer_impl.h"
-#include "mongo/db/operation_context_session_mongod.h"
#include "mongo/db/repl/oplog.h"
#include "mongo/db/repl/oplog_interface_local.h"
#include "mongo/db/repl/repl_client_info.h"
@@ -540,7 +539,8 @@ public:
_times.emplace(opCtx());
opCtx()->setLogicalSessionId(session()->getSessionId());
opCtx()->setTxnNumber(txnNum());
- _sessionCheckout = std::make_unique<OperationContextSessionMongod>(opCtx(), true);
+
+ _sessionCheckout = std::make_unique<MongoDOperationContextSession>(opCtx());
auto txnParticipant = TransactionParticipant::get(opCtx());
txnParticipant->beginOrContinue(*opCtx()->getTxnNumber(), false, true);
}
@@ -627,7 +627,7 @@ private:
boost::optional<ScopedSession> _session;
ServiceContext::UniqueOperationContext _opCtx;
boost::optional<ExposeOpObserverTimes::ReservedTimes> _times;
- std::unique_ptr<OperationContextSessionMongod> _sessionCheckout;
+ std::unique_ptr<MongoDOperationContextSession> _sessionCheckout;
TxnNumber _txnNum = 0;
};
diff --git a/src/mongo/db/operation_context_session_mongod.cpp b/src/mongo/db/operation_context_session_mongod.cpp
deleted file mode 100644
index 6622a5f4e0d..00000000000
--- a/src/mongo/db/operation_context_session_mongod.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-
-/**
- * Copyright (C) 2018-present MongoDB, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the Server Side Public License, version 1,
- * as published by MongoDB, Inc.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * Server Side Public License for more details.
- *
- * You should have received a copy of the Server Side Public License
- * along with this program. If not, see
- * <http://www.mongodb.com/licensing/server-side-public-license>.
- *
- * As a special exception, the copyright holders give permission to link the
- * code of portions of this program with the OpenSSL library under certain
- * conditions as described in each individual source file and distribute
- * linked combinations including the program with the OpenSSL library. You
- * must comply with the Server Side Public License in all respects for
- * all of the code used other than as permitted herein. If you modify file(s)
- * with this exception, you may extend this exception to your version of the
- * file(s), but you are not obligated to do so. If you do not wish to do so,
- * delete this exception statement from your version. If you delete this
- * exception statement from all source files in the program, then also delete
- * it in the license file.
- */
-
-#include "mongo/platform/basic.h"
-
-#include "mongo/db/operation_context_session_mongod.h"
-
-#include "mongo/db/transaction_participant.h"
-
-namespace mongo {
-
-OperationContextSessionMongod::OperationContextSessionMongod(OperationContext* opCtx,
- bool shouldCheckOutSession)
- : _operationContextSession(opCtx, shouldCheckOutSession) {
- if (shouldCheckOutSession && !opCtx->getClient()->isInDirectClient()) {
- const auto txnParticipant = TransactionParticipant::get(opCtx);
- txnParticipant->refreshFromStorageIfNeeded(opCtx);
- }
-}
-
-OperationContextSessionMongodWithoutRefresh::OperationContextSessionMongodWithoutRefresh(
- OperationContext* opCtx)
- : _operationContextSession(opCtx, true /* checkout */) {
- invariant(!opCtx->getClient()->isInDirectClient());
- const auto clientTxnNumber = *opCtx->getTxnNumber();
-
- const auto txnParticipant = TransactionParticipant::get(opCtx);
- txnParticipant->beginOrContinueTransactionUnconditionally(clientTxnNumber);
-}
-
-} // namespace mongo
diff --git a/src/mongo/db/operation_context_session_mongod.h b/src/mongo/db/operation_context_session_mongod.h
deleted file mode 100644
index bdbea720dbf..00000000000
--- a/src/mongo/db/operation_context_session_mongod.h
+++ /dev/null
@@ -1,69 +0,0 @@
-
-/**
- * Copyright (C) 2018-present MongoDB, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the Server Side Public License, version 1,
- * as published by MongoDB, Inc.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * Server Side Public License for more details.
- *
- * You should have received a copy of the Server Side Public License
- * along with this program. If not, see
- * <http://www.mongodb.com/licensing/server-side-public-license>.
- *
- * As a special exception, the copyright holders give permission to link the
- * code of portions of this program with the OpenSSL library under certain
- * conditions as described in each individual source file and distribute
- * linked combinations including the program with the OpenSSL library. You
- * must comply with the Server Side Public License in all respects for
- * all of the code used other than as permitted herein. If you modify file(s)
- * with this exception, you may extend this exception to your version of the
- * file(s), but you are not obligated to do so. If you do not wish to do so,
- * delete this exception statement from your version. If you delete this
- * exception statement from all source files in the program, then also delete
- * it in the license file.
- */
-
-#pragma once
-
-#include <boost/optional.hpp>
-
-#include "mongo/db/session_catalog.h"
-
-namespace mongo {
-
-class OperationContext;
-
-/**
- * Scoped object, which checks out the session specified in the passed operation context and stores
- * it for later access by the command. The session is installed at construction time and is removed
- * at destruction.
- */
-class OperationContextSessionMongod {
-public:
- OperationContextSessionMongod(OperationContext* opCtx, bool shouldCheckOutSession);
-
-private:
- OperationContextSession _operationContextSession;
-};
-
-/**
- * Similar to OperationContextSessionMongod, but marks the TransactionParticipant as valid without
- * refreshing from disk and starts a new transaction unconditionally.
- *
- * NOTE: Only used by the replication oplog application logic on secondaries in order to replay
- * prepared transactions.
- */
-class OperationContextSessionMongodWithoutRefresh {
-public:
- OperationContextSessionMongodWithoutRefresh(OperationContext* opCtx);
-
-private:
- OperationContextSession _operationContextSession;
-};
-
-} // namespace mongo
diff --git a/src/mongo/db/repl/apply_ops.cpp b/src/mongo/db/repl/apply_ops.cpp
index ea7e62763a0..9edb6be9bc8 100644
--- a/src/mongo/db/repl/apply_ops.cpp
+++ b/src/mongo/db/repl/apply_ops.cpp
@@ -49,10 +49,10 @@
#include "mongo/db/matcher/matcher.h"
#include "mongo/db/op_observer.h"
#include "mongo/db/operation_context.h"
-#include "mongo/db/operation_context_session_mongod.h"
#include "mongo/db/query/collation/collation_spec.h"
#include "mongo/db/repl/replication_coordinator.h"
#include "mongo/db/service_context.h"
+#include "mongo/db/session_catalog_mongod.h"
#include "mongo/db/transaction_participant.h"
#include "mongo/rpc/get_status_from_command_result.h"
#include "mongo/util/fail_point_service.h"
@@ -313,7 +313,7 @@ Status _applyPrepareTransaction(OperationContext* opCtx,
// The write on transaction table may be applied concurrently, so refreshing state
// from disk may read that write, causing starting a new transaction on an existing
// txnNumber. Thus, we start a new transaction without refreshing state from disk.
- OperationContextSessionMongodWithoutRefresh sessionCheckout(opCtx);
+ MongoDOperationContextSessionWithoutRefresh sessionCheckout(opCtx);
auto transaction = TransactionParticipant::get(opCtx);
transaction->unstashTransactionResources(opCtx, "prepareTransaction");
diff --git a/src/mongo/db/repl/do_txn_test.cpp b/src/mongo/db/repl/do_txn_test.cpp
index 1820b17e78d..66d3017b415 100644
--- a/src/mongo/db/repl/do_txn_test.cpp
+++ b/src/mongo/db/repl/do_txn_test.cpp
@@ -35,7 +35,6 @@
#include "mongo/db/client.h"
#include "mongo/db/op_observer_noop.h"
#include "mongo/db/op_observer_registry.h"
-#include "mongo/db/operation_context_session_mongod.h"
#include "mongo/db/repl/do_txn.h"
#include "mongo/db/repl/oplog_interface_local.h"
#include "mongo/db/repl/repl_client_info.h"
@@ -117,7 +116,7 @@ protected:
OpObserverMock* _opObserver = nullptr;
std::unique_ptr<StorageInterface> _storage;
ServiceContext::UniqueOperationContext _opCtx;
- boost::optional<OperationContextSessionMongod> _ocs;
+ boost::optional<MongoDOperationContextSession> _ocs;
};
void DoTxnTest::setUp() {
@@ -156,7 +155,7 @@ void DoTxnTest::setUp() {
// Set up the transaction and session.
_opCtx->setLogicalSessionId(makeLogicalSessionIdForTest());
_opCtx->setTxnNumber(0); // TxnNumber can always be 0 because we have a new session.
- _ocs.emplace(_opCtx.get(), true /* checkOutSession */);
+ _ocs.emplace(_opCtx.get());
auto txnParticipant = TransactionParticipant::get(opCtx());
txnParticipant->beginOrContinue(*opCtx()->getTxnNumber(), false, true);
diff --git a/src/mongo/db/repl/transaction_oplog_application.cpp b/src/mongo/db/repl/transaction_oplog_application.cpp
index 00460ed68f2..52f99c6fdbf 100644
--- a/src/mongo/db/repl/transaction_oplog_application.cpp
+++ b/src/mongo/db/repl/transaction_oplog_application.cpp
@@ -28,13 +28,13 @@
* it in the license file.
*/
-#include "mongo/db/repl/transaction_oplog_application.h"
-
#include "mongo/platform/basic.h"
+#include "mongo/db/repl/transaction_oplog_application.h"
+
#include "mongo/db/commands/txn_cmds_gen.h"
-#include "mongo/db/operation_context_session_mongod.h"
#include "mongo/db/repl/apply_ops.h"
+#include "mongo/db/session_catalog_mongod.h"
#include "mongo/db/transaction_history_iterator.h"
#include "mongo/db/transaction_participant.h"
@@ -89,7 +89,7 @@ Status applyCommitTransaction(OperationContext* opCtx,
// The write on transaction table may be applied concurrently, so refreshing state
// from disk may read that write, causing starting a new transaction on an existing
// txnNumber. Thus, we start a new transaction without refreshing state from disk.
- OperationContextSessionMongodWithoutRefresh sessionCheckout(opCtx);
+ MongoDOperationContextSessionWithoutRefresh sessionCheckout(opCtx);
auto transaction = TransactionParticipant::get(opCtx);
invariant(transaction);
@@ -123,7 +123,7 @@ Status applyAbortTransaction(OperationContext* opCtx,
// The write on transaction table may be applied concurrently, so refreshing state
// from disk may read that write, causing starting a new transaction on an existing
// txnNumber. Thus, we start a new transaction without refreshing state from disk.
- OperationContextSessionMongodWithoutRefresh sessionCheckout(opCtx);
+ MongoDOperationContextSessionWithoutRefresh sessionCheckout(opCtx);
auto transaction = TransactionParticipant::get(opCtx);
transaction->unstashTransactionResources(opCtx, "abortTransaction");
diff --git a/src/mongo/db/s/session_catalog_migration_destination_test.cpp b/src/mongo/db/s/session_catalog_migration_destination_test.cpp
index f929156353a..95e806a0afd 100644
--- a/src/mongo/db/s/session_catalog_migration_destination_test.cpp
+++ b/src/mongo/db/s/session_catalog_migration_destination_test.cpp
@@ -37,14 +37,12 @@
#include "mongo/db/initialize_operation_session_info.h"
#include "mongo/db/logical_session_cache_noop.h"
#include "mongo/db/logical_session_id.h"
-#include "mongo/db/operation_context_session_mongod.h"
#include "mongo/db/ops/write_ops_exec.h"
#include "mongo/db/ops/write_ops_gen.h"
#include "mongo/db/repl/oplog_entry.h"
#include "mongo/db/s/migration_session_id.h"
#include "mongo/db/s/session_catalog_migration_destination.h"
#include "mongo/db/server_options.h"
-#include "mongo/db/session_catalog.h"
#include "mongo/db/session_catalog_mongod.h"
#include "mongo/db/session_txn_record_gen.h"
#include "mongo/db/transaction_history_iterator.h"
@@ -250,7 +248,7 @@ public:
// requests with txnNumbers aren't allowed. To get around this, we have to manually set
// up the session state and perform the insert.
initializeOperationSessionInfo(innerOpCtx.get(), insertBuilder.obj(), true, true, true);
- OperationContextSessionMongod sessionTxnState(innerOpCtx.get(), true);
+ MongoDOperationContextSession sessionTxnState(innerOpCtx.get());
auto txnParticipant = TransactionParticipant::get(innerOpCtx.get());
txnParticipant->beginOrContinue(*sessionInfo.getTxnNumber(), boost::none, boost::none);
diff --git a/src/mongo/db/s/txn_two_phase_commit_cmds.cpp b/src/mongo/db/s/txn_two_phase_commit_cmds.cpp
index 7edb6c2ee4a..270d3a31cf8 100644
--- a/src/mongo/db/s/txn_two_phase_commit_cmds.cpp
+++ b/src/mongo/db/s/txn_two_phase_commit_cmds.cpp
@@ -35,9 +35,9 @@
#include "mongo/client/remote_command_targeter.h"
#include "mongo/db/commands.h"
#include "mongo/db/commands/txn_two_phase_commit_cmds_gen.h"
-#include "mongo/db/operation_context_session_mongod.h"
#include "mongo/db/repl/repl_client_info.h"
#include "mongo/db/s/sharding_state.h"
+#include "mongo/db/session_catalog_mongod.h"
#include "mongo/db/transaction_coordinator_service.h"
#include "mongo/db/transaction_participant.h"
#include "mongo/executor/task_executor.h"
diff --git a/src/mongo/db/service_entry_point_common.cpp b/src/mongo/db/service_entry_point_common.cpp
index 292bbf6db7b..c695741d003 100644
--- a/src/mongo/db/service_entry_point_common.cpp
+++ b/src/mongo/db/service_entry_point_common.cpp
@@ -57,7 +57,6 @@
#include "mongo/db/logical_session_id.h"
#include "mongo/db/logical_session_id_helpers.h"
#include "mongo/db/logical_time_validator.h"
-#include "mongo/db/operation_context_session_mongod.h"
#include "mongo/db/ops/write_ops.h"
#include "mongo/db/ops/write_ops_exec.h"
#include "mongo/db/query/find.h"
@@ -70,6 +69,7 @@
#include "mongo/db/s/sharded_connection_info.h"
#include "mongo/db/s/sharding_state.h"
#include "mongo/db/service_entry_point_common.h"
+#include "mongo/db/session_catalog_mongod.h"
#include "mongo/db/snapshot_window_util.h"
#include "mongo/db/stats/counters.h"
#include "mongo/db/stats/top.h"
@@ -576,9 +576,11 @@ void execCommandDatabase(OperationContext* opCtx,
// handles the appropriate state management for both multi-statement transactions and
// retryable writes. Currently, only requests with a transaction number will check out the
// session.
- const bool shouldCheckOutSession = static_cast<bool>(sessionOptions.getTxnNumber()) &&
- !shouldCommandSkipSessionCheckout(command->getName());
- OperationContextSessionMongod sessionTxnState(opCtx, shouldCheckOutSession);
+ boost::optional<MongoDOperationContextSession> sessionTxnState;
+ const bool shouldCheckOutSession =
+ sessionOptions.getTxnNumber() && !shouldCommandSkipSessionCheckout(command->getName());
+ if (shouldCheckOutSession)
+ sessionTxnState.emplace(opCtx);
std::unique_ptr<MaintenanceModeSetter> mmSetter;
diff --git a/src/mongo/db/session_catalog.cpp b/src/mongo/db/session_catalog.cpp
index 70049de30a4..bc6d09710a5 100644
--- a/src/mongo/db/session_catalog.cpp
+++ b/src/mongo/db/session_catalog.cpp
@@ -186,55 +186,44 @@ void SessionCatalog::_releaseSession(const LogicalSessionId& lsid,
}
}
-OperationContextSession::OperationContextSession(OperationContext* opCtx, bool checkOutSession)
- : _opCtx(opCtx) {
- if (!opCtx->getLogicalSessionId()) {
- return;
- }
-
- if (!checkOutSession) {
- return;
- }
-
+OperationContextSession::OperationContextSession(OperationContext* opCtx) : _opCtx(opCtx) {
auto& checkedOutSession = operationSessionDecoration(opCtx);
- if (!checkedOutSession) {
- auto sessionTransactionTable = SessionCatalog::get(opCtx);
- auto scopedCheckedOutSession = sessionTransactionTable->checkOutSession(opCtx);
- // We acquire a Client lock here to guard the construction of this session so that
- // references to this session are safe to use while the lock is held.
- stdx::lock_guard<Client> lk(*opCtx->getClient());
- checkedOutSession.emplace(std::move(scopedCheckedOutSession));
- } else {
- // The only reason to be trying to check out a session when you already have a session
- // checked out is if you're in DBDirectClient.
+ if (checkedOutSession) {
+ // The only case where a session can be checked-out more than once is due to DBDirectClient
+ // reentrancy
invariant(opCtx->getClient()->isInDirectClient());
return;
}
- const auto session = checkedOutSession->get();
- invariant(opCtx->getLogicalSessionId() == session->getSessionId());
+ const auto catalog = SessionCatalog::get(opCtx);
+ auto scopedCheckedOutSession = catalog->checkOutSession(opCtx);
+
+ // We acquire a Client lock here to guard the construction of this session so that references to
+ // this session are safe to use while the lock is held
+ stdx::lock_guard<Client> lk(*opCtx->getClient());
+ checkedOutSession.emplace(std::move(scopedCheckedOutSession));
}
OperationContextSession::~OperationContextSession() {
- // Only release the checked out session at the end of the top-level request from the client,
- // not at the end of a nested DBDirectClient call.
+ // Only release the checked out session at the end of the top-level request from the client, not
+ // at the end of a nested DBDirectClient call
if (_opCtx->getClient()->isInDirectClient()) {
return;
}
auto& checkedOutSession = operationSessionDecoration(_opCtx);
- if (checkedOutSession) {
- // Removing the checkedOutSession from the OperationContext must be done under the Client
- // lock, but destruction of the checkedOutSession must not be, as it takes the
- // SessionCatalog mutex, and other code may take the Client lock while holding that mutex.
- stdx::unique_lock<Client> lk(*_opCtx->getClient());
- ScopedCheckedOutSession sessionToDelete(std::move(checkedOutSession.get()));
-
- // This destroys the moved-from ScopedCheckedOutSession, and must be done within the client
- // lock.
- checkedOutSession = boost::none;
- lk.unlock();
- }
+ if (!checkedOutSession)
+ return;
+
+ // Removing the checkedOutSession from the OperationContext must be done under the Client lock,
+ // but destruction of the checkedOutSession must not be, as it takes the SessionCatalog mutex,
+ // and other code may take the Client lock while holding that mutex.
+ stdx::unique_lock<Client> lk(*_opCtx->getClient());
+ ScopedCheckedOutSession sessionToDelete(std::move(checkedOutSession.get()));
+
+ // This destroys the moved-from ScopedCheckedOutSession, and must be done within the client lock
+ checkedOutSession = boost::none;
+ lk.unlock();
}
Session* OperationContextSession::get(OperationContext* opCtx) {
diff --git a/src/mongo/db/session_catalog.h b/src/mongo/db/session_catalog.h
index 8e2a35d8b8d..020d1fa5c06 100644
--- a/src/mongo/db/session_catalog.h
+++ b/src/mongo/db/session_catalog.h
@@ -250,7 +250,7 @@ class OperationContextSession {
MONGO_DISALLOW_COPYING(OperationContextSession);
public:
- OperationContextSession(OperationContext* opCtx, bool checkOutSession);
+ OperationContextSession(OperationContext* opCtx);
~OperationContextSession();
/**
diff --git a/src/mongo/db/session_catalog_mongod.cpp b/src/mongo/db/session_catalog_mongod.cpp
index 1c844bd78f0..5ea8173ca05 100644
--- a/src/mongo/db/session_catalog_mongod.cpp
+++ b/src/mongo/db/session_catalog_mongod.cpp
@@ -171,4 +171,23 @@ void MongoDSessionCatalog::invalidateSessions(OperationContext* opCtx,
}));
}
+
+MongoDOperationContextSession::MongoDOperationContextSession(OperationContext* opCtx)
+ : _operationContextSession(opCtx) {
+ if (!opCtx->getClient()->isInDirectClient()) {
+ const auto txnParticipant = TransactionParticipant::get(opCtx);
+ txnParticipant->refreshFromStorageIfNeeded(opCtx);
+ }
+}
+
+MongoDOperationContextSessionWithoutRefresh::MongoDOperationContextSessionWithoutRefresh(
+ OperationContext* opCtx)
+ : _operationContextSession(opCtx) {
+ invariant(!opCtx->getClient()->isInDirectClient());
+ const auto clientTxnNumber = *opCtx->getTxnNumber();
+
+ const auto txnParticipant = TransactionParticipant::get(opCtx);
+ txnParticipant->beginOrContinueTransactionUnconditionally(clientTxnNumber);
+}
+
} // namespace mongo
diff --git a/src/mongo/db/session_catalog_mongod.h b/src/mongo/db/session_catalog_mongod.h
index 4496c8b17f3..c71e0dce076 100644
--- a/src/mongo/db/session_catalog_mongod.h
+++ b/src/mongo/db/session_catalog_mongod.h
@@ -65,4 +65,32 @@ public:
boost::optional<BSONObj> singleSessionDoc);
};
+/**
+ * Scoped object, which checks out the session specified in the passed operation context and stores
+ * it for later access by the command. The session is installed at construction time and is removed
+ * at destruction.
+ */
+class MongoDOperationContextSession {
+public:
+ MongoDOperationContextSession(OperationContext* opCtx);
+
+private:
+ OperationContextSession _operationContextSession;
+};
+
+/**
+ * Similar to MongoDOperationContextSession, but marks the TransactionParticipant as valid without
+ * refreshing from disk and starts a new transaction unconditionally.
+ *
+ * NOTE: Only used by the replication oplog application logic on secondaries in order to replay
+ * prepared transactions.
+ */
+class MongoDOperationContextSessionWithoutRefresh {
+public:
+ MongoDOperationContextSessionWithoutRefresh(OperationContext* opCtx);
+
+private:
+ OperationContextSession _operationContextSession;
+};
+
} // namespace mongo
diff --git a/src/mongo/db/session_catalog_test.cpp b/src/mongo/db/session_catalog_test.cpp
index 1f8312b6e69..09bf4c7e878 100644
--- a/src/mongo/db/session_catalog_test.cpp
+++ b/src/mongo/db/session_catalog_test.cpp
@@ -92,21 +92,12 @@ TEST_F(SessionCatalogTestWithDefaultOpCtx, OperationContextCheckedOutSession) {
const TxnNumber txnNum = 20;
_opCtx->setTxnNumber(txnNum);
- OperationContextSession ocs(_opCtx, true);
+ OperationContextSession ocs(_opCtx);
auto session = OperationContextSession::get(_opCtx);
ASSERT(session);
ASSERT_EQ(*_opCtx->getLogicalSessionId(), session->getSessionId());
}
-TEST_F(SessionCatalogTestWithDefaultOpCtx, OperationContextNonCheckedOutSession) {
- _opCtx->setLogicalSessionId(makeLogicalSessionIdForTest());
-
- OperationContextSession ocs(_opCtx, false);
- auto session = OperationContextSession::get(_opCtx);
-
- ASSERT(!session);
-}
-
TEST_F(SessionCatalogTestWithDefaultOpCtx, GetOrCreateNonExistentSession) {
const auto lsid = makeLogicalSessionIdForTest();
auto scopedSession = catalog()->getOrCreateSession(_opCtx, lsid);
@@ -120,7 +111,7 @@ TEST_F(SessionCatalogTestWithDefaultOpCtx, GetOrCreateSessionAfterCheckOutSessio
_opCtx->setLogicalSessionId(lsid);
boost::optional<OperationContextSession> ocs;
- ocs.emplace(_opCtx, true);
+ ocs.emplace(_opCtx);
stdx::async(stdx::launch::async, [&] {
ThreadClient tc(getGlobalServiceContext());
@@ -149,11 +140,11 @@ TEST_F(SessionCatalogTestWithDefaultOpCtx, NestedOperationContextSession) {
_opCtx->setLogicalSessionId(makeLogicalSessionIdForTest());
{
- OperationContextSession outerScopedSession(_opCtx, true);
+ OperationContextSession outerScopedSession(_opCtx);
{
DirectClientSetter inDirectClient(_opCtx);
- OperationContextSession innerScopedSession(_opCtx, true);
+ OperationContextSession innerScopedSession(_opCtx);
auto session = OperationContextSession::get(_opCtx);
ASSERT(session);
@@ -214,7 +205,7 @@ TEST_F(SessionCatalogTest, KillSessionWhenSessionIsNotCheckedOut) {
{
auto opCtx = makeOperationContext();
opCtx->setLogicalSessionId(lsid);
- OperationContextSession unusedOperationContextSession(opCtx.get(), true);
+ OperationContextSession unusedOperationContextSession(opCtx.get());
}
auto killToken = catalog()->killSession(lsid);
@@ -224,9 +215,8 @@ TEST_F(SessionCatalogTest, KillSessionWhenSessionIsNotCheckedOut) {
auto opCtx = makeOperationContext();
opCtx->setLogicalSessionId(lsid);
opCtx->setDeadlineAfterNowBy(Milliseconds(10), ErrorCodes::MaxTimeMSExpired);
- ASSERT_THROWS_CODE(OperationContextSession(opCtx.get(), true),
- AssertionException,
- ErrorCodes::MaxTimeMSExpired);
+ ASSERT_THROWS_CODE(
+ OperationContextSession(opCtx.get()), AssertionException, ErrorCodes::MaxTimeMSExpired);
}
// Schedule a separate "regular operation" thread, which will block on checking-out the session,
@@ -236,7 +226,7 @@ TEST_F(SessionCatalogTest, KillSessionWhenSessionIsNotCheckedOut) {
auto sideOpCtx = Client::getCurrent()->makeOperationContext();
sideOpCtx->setLogicalSessionId(lsid);
- OperationContextSession unusedOperationContextSession(sideOpCtx.get(), true);
+ OperationContextSession unusedOperationContextSession(sideOpCtx.get());
});
ASSERT(stdx::future_status::ready != future.wait_for(Milliseconds(10).toSystemDuration()));
@@ -251,7 +241,7 @@ TEST_F(SessionCatalogTest, KillSessionWhenSessionIsNotCheckedOut) {
{
auto opCtx = makeOperationContext();
opCtx->setLogicalSessionId(lsid);
- OperationContextSession unusedOperationContextSession(opCtx.get(), true);
+ OperationContextSession unusedOperationContextSession(opCtx.get());
}
// Make sure the "regular operation" eventually is able to proceed and use the just killed
@@ -266,7 +256,7 @@ TEST_F(SessionCatalogTest, KillSessionWhenSessionIsCheckedOut) {
// Create the session so there is something to kill
auto opCtx = makeOperationContext();
opCtx->setLogicalSessionId(lsid);
- OperationContextSession operationContextSession(opCtx.get(), true);
+ OperationContextSession operationContextSession(opCtx.get());
auto killToken = catalog()->killSession(lsid);
@@ -281,7 +271,7 @@ TEST_F(SessionCatalogTest, KillSessionWhenSessionIsCheckedOut) {
sideOpCtx->setLogicalSessionId(lsid);
sideOpCtx->setDeadlineAfterNowBy(Milliseconds(10), ErrorCodes::MaxTimeMSExpired);
- OperationContextSession unusedOperationContextSession(sideOpCtx.get(), true);
+ OperationContextSession unusedOperationContextSession(sideOpCtx.get());
});
ASSERT_THROWS_CODE(future.get(), AssertionException, ErrorCodes::MaxTimeMSExpired);
@@ -294,9 +284,8 @@ TEST_F(SessionCatalogTest, KillSessionWhenSessionIsCheckedOut) {
auto opCtx = makeOperationContext();
opCtx->setLogicalSessionId(lsid);
opCtx->setDeadlineAfterNowBy(Milliseconds(10), ErrorCodes::MaxTimeMSExpired);
- ASSERT_THROWS_CODE(OperationContextSession(opCtx.get(), true),
- AssertionException,
- ErrorCodes::MaxTimeMSExpired);
+ ASSERT_THROWS_CODE(
+ OperationContextSession(opCtx.get()), AssertionException, ErrorCodes::MaxTimeMSExpired);
}
// Schedule a separate "regular operation" thread, which will block on checking-out the session,
@@ -306,7 +295,7 @@ TEST_F(SessionCatalogTest, KillSessionWhenSessionIsCheckedOut) {
auto sideOpCtx = Client::getCurrent()->makeOperationContext();
sideOpCtx->setLogicalSessionId(lsid);
- OperationContextSession unusedOperationContextSession(sideOpCtx.get(), true);
+ OperationContextSession unusedOperationContextSession(sideOpCtx.get());
});
ASSERT(stdx::future_status::ready != future.wait_for(Milliseconds(10).toSystemDuration()));
@@ -321,7 +310,7 @@ TEST_F(SessionCatalogTest, KillSessionWhenSessionIsCheckedOut) {
{
auto opCtx = makeOperationContext();
opCtx->setLogicalSessionId(lsid);
- OperationContextSession unusedOperationContextSession(opCtx.get(), true);
+ OperationContextSession unusedOperationContextSession(opCtx.get());
}
// Make sure the "regular operation" eventually is able to proceed and use the just killed
@@ -336,7 +325,7 @@ TEST_F(SessionCatalogTest, MarkSessionAsKilledThrowsWhenCalledTwice) {
{
auto opCtx = makeOperationContext();
opCtx->setLogicalSessionId(lsid);
- OperationContextSession unusedOperationContextSession(opCtx.get(), true);
+ OperationContextSession unusedOperationContextSession(opCtx.get());
}
auto killToken = catalog()->killSession(lsid);
@@ -351,9 +340,8 @@ TEST_F(SessionCatalogTest, MarkSessionAsKilledThrowsWhenCalledTwice) {
auto opCtx = makeOperationContext();
opCtx->setLogicalSessionId(lsid);
opCtx->setDeadlineAfterNowBy(Milliseconds(10), ErrorCodes::MaxTimeMSExpired);
- ASSERT_THROWS_CODE(OperationContextSession(opCtx.get(), true),
- AssertionException,
- ErrorCodes::MaxTimeMSExpired);
+ ASSERT_THROWS_CODE(
+ OperationContextSession(opCtx.get()), AssertionException, ErrorCodes::MaxTimeMSExpired);
}
// Finish "killing" the session so the SessionCatalog destructor doesn't complain
@@ -388,7 +376,7 @@ TEST_F(SessionCatalogTestWithDefaultOpCtx, KillSessionsThroughScanSessions) {
auto sideOpCtx = Client::getCurrent()->makeOperationContext();
sideOpCtx->setLogicalSessionId(lsid);
- OperationContextSession unusedOperationContextSession(sideOpCtx.get(), true);
+ OperationContextSession unusedOperationContextSession(sideOpCtx.get());
firstUseOfTheSessionReachedBarrier.countDownAndWait();
ASSERT_THROWS_CODE(sideOpCtx->sleepFor(Hours{6}),
@@ -400,7 +388,7 @@ TEST_F(SessionCatalogTestWithDefaultOpCtx, KillSessionsThroughScanSessions) {
auto sideOpCtx = Client::getCurrent()->makeOperationContext();
sideOpCtx->setLogicalSessionId(lsid);
- OperationContextSession unusedOperationContextSession(sideOpCtx.get(), true);
+ OperationContextSession unusedOperationContextSession(sideOpCtx.get());
}
}));
}
diff --git a/src/mongo/db/transaction_participant_test.cpp b/src/mongo/db/transaction_participant_test.cpp
index d6b64bc960b..1518edff739 100644
--- a/src/mongo/db/transaction_participant_test.cpp
+++ b/src/mongo/db/transaction_participant_test.cpp
@@ -36,7 +36,6 @@
#include "mongo/db/op_observer_noop.h"
#include "mongo/db/op_observer_registry.h"
#include "mongo/db/operation_context.h"
-#include "mongo/db/operation_context_session_mongod.h"
#include "mongo/db/repl/mock_repl_coord_server_fixture.h"
#include "mongo/db/repl/oplog.h"
#include "mongo/db/repl/oplog_entry.h"
@@ -272,8 +271,8 @@ protected:
runFunctionFromDifferentOpCtx(func);
}
- std::unique_ptr<OperationContextSessionMongod> checkOutSession() {
- auto opCtxSession = std::make_unique<OperationContextSessionMongod>(opCtx(), true);
+ std::unique_ptr<MongoDOperationContextSession> checkOutSession() {
+ auto opCtxSession = std::make_unique<MongoDOperationContextSession>(opCtx());
auto txnParticipant = TransactionParticipant::get(opCtx());
txnParticipant->beginOrContinue(*opCtx()->getTxnNumber(), false, true);
return opCtxSession;
@@ -318,7 +317,7 @@ TEST_F(TxnParticipantTest, TransactionThrowsLockTimeoutIfLockIsUnavailable) {
newOpCtx.get()->setLogicalSessionId(newSessionId);
newOpCtx.get()->setTxnNumber(newTxnNum);
- OperationContextSessionMongod newOpCtxSession(newOpCtx.get(), true);
+ MongoDOperationContextSession newOpCtxSession(newOpCtx.get());
auto newTxnParticipant = TransactionParticipant::get(newOpCtx.get());
newTxnParticipant->beginOrContinue(newTxnNum, false, true);
newTxnParticipant->unstashTransactionResources(newOpCtx.get(), "insert");
@@ -1077,7 +1076,7 @@ TEST_F(TxnParticipantTest, ContinuingATransactionWithNoResourcesAborts) {
checkOutSession();
// Check out the session again for a new operation.
- OperationContextSessionMongod sessionCheckout(opCtx(), true);
+ MongoDOperationContextSession sessionCheckout(opCtx());
auto txnParticipant = TransactionParticipant::get(opCtx());
ASSERT_THROWS_CODE(
@@ -1278,7 +1277,7 @@ DEATH_TEST_F(TxnParticipantTest, AbortIsIllegalDuringCommittingPreparedTransacti
}
TEST_F(TxnParticipantTest, CannotContinueNonExistentTransaction) {
- OperationContextSessionMongod opCtxSession(opCtx(), true);
+ MongoDOperationContextSession opCtxSession(opCtx());
auto txnParticipant = TransactionParticipant::get(opCtx());
ASSERT_THROWS_CODE(
txnParticipant->beginOrContinue(*opCtx()->getTxnNumber(), false, boost::none),
@@ -1333,7 +1332,7 @@ TEST_F(TxnParticipantTest, StashInNestedSessionIsANoop) {
{
// Make it look like we're in a DBDirectClient running a nested operation.
DirectClientSetter inDirectClient(opCtx());
- OperationContextSessionMongod innerScopedSession(opCtx(), true);
+ MongoDOperationContextSession innerScopedSession(opCtx());
txnParticipant->stashTransactionResources(opCtx());
@@ -1346,7 +1345,6 @@ TEST_F(TxnParticipantTest, StashInNestedSessionIsANoop) {
}
TEST_F(TxnParticipantTest, UnstashInNestedSessionIsANoop) {
-
auto outerScopedSession = checkOutSession();
Locker* originalLocker = opCtx()->lockState();
@@ -1366,7 +1364,7 @@ TEST_F(TxnParticipantTest, UnstashInNestedSessionIsANoop) {
{
// Make it look like we're in a DBDirectClient running a nested operation.
DirectClientSetter inDirectClient(opCtx());
- OperationContextSessionMongod innerScopedSession(opCtx(), true);
+ MongoDOperationContextSession innerScopedSession(opCtx());
auto txnParticipant = TransactionParticipant::get(opCtx());
txnParticipant->unstashTransactionResources(opCtx(), "find");
@@ -1451,7 +1449,7 @@ protected:
}
void cannotSpecifyStartTransactionOnStartedRetryableWrite() {
- OperationContextSessionMongod opCtxSession(opCtx(), true);
+ MongoDOperationContextSession opCtxSession(opCtx());
auto txnParticipant = TransactionParticipant::get(opCtx());
txnParticipant->beginOrContinue(*opCtx()->getTxnNumber(), boost::none, boost::none);
@@ -2895,7 +2893,7 @@ TEST_F(TransactionsMetricsTest, ReportUnstashedResourcesForARetryableWrite) {
ASSERT(opCtx()->lockState());
ASSERT(opCtx()->recoveryUnit());
- OperationContextSessionMongod opCtxSession(opCtx(), true);
+ MongoDOperationContextSession opCtxSession(opCtx());
auto txnParticipant = TransactionParticipant::get(opCtx());
txnParticipant->beginOrContinue(*opCtx()->getTxnNumber(), boost::none, boost::none);
txnParticipant->unstashTransactionResources(opCtx(), "find");
@@ -3571,7 +3569,7 @@ TEST_F(TxnParticipantTest, WhenOldestTSRemovedNextOldestBecomesNewOldest) {
newOpCtx.get()->setLogicalSessionId(newSessionId);
newOpCtx.get()->setTxnNumber(newTxnNum);
- OperationContextSessionMongod newOpCtxSession(newOpCtx.get(), true);
+ MongoDOperationContextSession newOpCtxSession(newOpCtx.get());
auto newTxnParticipant = TransactionParticipant::get(newOpCtx.get());
newTxnParticipant->beginOrContinue(newTxnNum, false, true);
newTxnParticipant->unstashTransactionResources(newOpCtx.get(), "prepareTransaction");
@@ -3633,7 +3631,7 @@ TEST_F(TxnParticipantTest, ReturnNullTimestampIfNoOldestActiveTimestamp) {
newOpCtx.get()->setLogicalSessionId(newSessionId);
newOpCtx.get()->setTxnNumber(newTxnNum);
- OperationContextSessionMongod newOpCtxSession(newOpCtx.get(), true);
+ MongoDOperationContextSession newOpCtxSession(newOpCtx.get());
auto newTxnParticipant = TransactionParticipant::get(newOpCtx.get());
newTxnParticipant->beginOrContinue(newTxnNum, false, true);
newTxnParticipant->unstashTransactionResources(newOpCtx.get(), "prepareTransaction");
diff --git a/src/mongo/dbtests/storage_timestamp_tests.cpp b/src/mongo/dbtests/storage_timestamp_tests.cpp
index 468474393a1..7688df65a5c 100644
--- a/src/mongo/dbtests/storage_timestamp_tests.cpp
+++ b/src/mongo/dbtests/storage_timestamp_tests.cpp
@@ -53,7 +53,6 @@
#include "mongo/db/logical_clock.h"
#include "mongo/db/multi_key_path_tracker.h"
#include "mongo/db/op_observer_registry.h"
-#include "mongo/db/operation_context_session_mongod.h"
#include "mongo/db/repl/apply_ops.h"
#include "mongo/db/repl/drop_pending_collection_reaper.h"
#include "mongo/db/repl/multiapplier.h"
@@ -2498,7 +2497,7 @@ public:
_opCtx->setLogicalSessionId(sessionId);
_opCtx->setTxnNumber(26);
- ocs = std::make_unique<OperationContextSessionMongod>(_opCtx, true);
+ ocs.emplace(_opCtx);
auto txnParticipant = TransactionParticipant::get(_opCtx);
ASSERT(txnParticipant);
@@ -2539,7 +2538,8 @@ protected:
Timestamp presentTs;
Timestamp beforeTxnTs;
Timestamp commitEntryTs;
- std::unique_ptr<OperationContextSessionMongod> ocs;
+
+ boost::optional<MongoDOperationContextSession> ocs;
};
class MultiDocumentTransaction : public MultiDocumentTransactionTest {