summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTess Avitabile <tess.avitabile@mongodb.com>2018-05-07 14:15:52 -0400
committerTess Avitabile <tess.avitabile@mongodb.com>2018-05-08 13:52:43 -0400
commit98f28d452b9b330d6c1696d6d8207b582a5870fc (patch)
treea99763113d3c804ed7a8a0f41b1e522d0d0e1721 /src
parent13e636974a37588232ff33a422b94bbe77f351cc (diff)
downloadmongo-98f28d452b9b330d6c1696d6d8207b582a5870fc.tar.gz
SERVER-34811 Forbid reads and writes to the config, admin, and local databases within transactions
Diffstat (limited to 'src')
-rw-r--r--src/mongo/db/op_observer_impl_test.cpp6
-rw-r--r--src/mongo/db/repl/do_txn_test.cpp4
-rw-r--r--src/mongo/db/s/session_catalog_migration_destination_test.cpp2
-rw-r--r--src/mongo/db/service_entry_point_common.cpp52
-rw-r--r--src/mongo/db/session.cpp36
-rw-r--r--src/mongo/db/session.h4
-rw-r--r--src/mongo/db/session_catalog.cpp6
-rw-r--r--src/mongo/db/session_catalog.h4
-rw-r--r--src/mongo/db/session_catalog_test.cpp24
-rw-r--r--src/mongo/db/session_test.cpp85
10 files changed, 124 insertions, 99 deletions
diff --git a/src/mongo/db/op_observer_impl_test.cpp b/src/mongo/db/op_observer_impl_test.cpp
index 0479e8198e5..3ca215f7133 100644
--- a/src/mongo/db/op_observer_impl_test.cpp
+++ b/src/mongo/db/op_observer_impl_test.cpp
@@ -307,7 +307,7 @@ public:
NamespaceString nss,
TxnNumber txnNum,
StmtId stmtId) {
- session->beginOrContinueTxn(opCtx, txnNum, boost::none, boost::none);
+ session->beginOrContinueTxn(opCtx, txnNum, boost::none, boost::none, "testDB", "insert");
{
AutoGetCollection autoColl(opCtx, nss, MODE_IX);
@@ -407,7 +407,9 @@ TEST_F(OpObserverLargeTransactionTest, TransactionTooLargeWhileCommitting) {
OperationContextSession opSession(opCtx.get(),
true /* checkOutSession */,
false /* autocommit */,
- true /* startTransaction*/);
+ true /* startTransaction */,
+ "testDB" /* dbName */,
+ "insert" /* cmdName */);
session->unstashTransactionResources(opCtx.get(), "insert");
diff --git a/src/mongo/db/repl/do_txn_test.cpp b/src/mongo/db/repl/do_txn_test.cpp
index d6dde975452..17ea4dc6d21 100644
--- a/src/mongo/db/repl/do_txn_test.cpp
+++ b/src/mongo/db/repl/do_txn_test.cpp
@@ -148,7 +148,9 @@ void DoTxnTest::setUp() {
_ocs.emplace(_opCtx.get(),
true /* checkOutSession */,
false /* autocommit */,
- true /* startTransaction */);
+ true /* startTransaction */,
+ "admin" /* dbName */,
+ "doTxn" /* cmdName */);
OperationContextSession::get(opCtx())->unstashTransactionResources(opCtx(), "doTxn");
}
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 fdbe9167c58..010ae23f768 100644
--- a/src/mongo/db/s/session_catalog_migration_destination_test.cpp
+++ b/src/mongo/db/s/session_catalog_migration_destination_test.cpp
@@ -243,7 +243,7 @@ public:
// up the session state and perform the insert.
initializeOperationSessionInfo(innerOpCtx.get(), insertBuilder.obj(), true, true, true);
OperationContextSession sessionTxnState(
- innerOpCtx.get(), true, boost::none, boost::none);
+ innerOpCtx.get(), true, boost::none, boost::none, "testDB", "insert");
const auto reply = performInserts(innerOpCtx.get(), insertRequest);
ASSERT(reply.results.size() == 1);
diff --git a/src/mongo/db/service_entry_point_common.cpp b/src/mongo/db/service_entry_point_common.cpp
index 46554839027..10f26c5be5f 100644
--- a/src/mongo/db/service_entry_point_common.cpp
+++ b/src/mongo/db/service_entry_point_common.cpp
@@ -132,23 +132,6 @@ const StringMap<int> sessionCheckoutWhitelist = {{"abortTransaction", 1},
{"refreshLogicalSessionCacheNow", 1},
{"update", 1}};
-// The command names that are allowed in a multi-document transaction.
-const StringMap<int> txnCmdWhitelist = {{"abortTransaction", 1},
- {"aggregate", 1},
- {"commitTransaction", 1},
- {"count", 1},
- {"delete", 1},
- {"distinct", 1},
- {"doTxn", 1},
- {"find", 1},
- {"findandmodify", 1},
- {"findAndModify", 1},
- {"geoSearch", 1},
- {"getMore", 1},
- {"insert", 1},
- {"prepareTransaction", 1},
- {"update", 1}};
-
// The command names that are ignored by the 'failCommand' failpoint.
const StringMap<int> failCommandIgnoreList = {
{"buildInfo", 1}, {"configureFailPoint", 1}, {"isMaster", 1}, {"ping", 1}};
@@ -602,6 +585,12 @@ void execCommandDatabase(OperationContext* opCtx,
replCoord->getReplicationMode() == repl::ReplicationCoordinator::modeReplSet,
opCtx->getServiceContext()->getStorageEngine()->supportsDocLocking());
+ const auto dbname = request.getDatabase().toString();
+ uassert(
+ ErrorCodes::InvalidNamespace,
+ str::stream() << "Invalid database name: '" << dbname << "'",
+ NamespaceString::validDBName(dbname, NamespaceString::DollarInDbNameBehavior::Allow));
+
// Session ids are forwarded in requests, so commands that require roundtrips between
// servers may result in a deadlock when a server tries to check out a session it is already
// using to service an earlier operation in the command's chain. To avoid this, only check
@@ -624,12 +613,6 @@ void execCommandDatabase(OperationContext* opCtx,
}
}
- uassert(50767,
- str::stream() << "Cannot run '" << command->getName()
- << "' in a multi-document transaction.",
- !autocommitVal ||
- txnCmdWhitelist.find(command->getName()) != txnCmdWhitelist.cend());
-
// Reject commands with 'txnNumber' that do not check out the Session, since no retryable
// writes or transaction machinery will be used to execute commands that do not check out
// the Session. Do not check this if we are in DBDirectClient because the outer command is
@@ -644,23 +627,12 @@ void execCommandDatabase(OperationContext* opCtx,
// This constructor will check out the session and start a transaction, if necessary. It
// handles the appropriate state management for both multi-statement transactions and
// retryable writes.
- OperationContextSession sessionTxnState(
- opCtx, shouldCheckoutSession, autocommitVal, startMultiDocTxn);
-
- // If we are in a multi-document transaction, ensure the command is allowed in this context.
- // We do not check this in DBDirectClient, since 'aggregate' is allowed in transactions, but
- // 'geoNear' is not, and 'aggregate' can run 'geoNear' in DBDirectClient.
- if (!opCtx->getClient()->isInDirectClient()) {
- auto session = OperationContextSession::get(opCtx);
- invariant(!session || !session->inMultiDocumentTransaction() ||
- txnCmdWhitelist.find(command->getName()) != txnCmdWhitelist.cend());
- }
-
- const auto dbname = request.getDatabase().toString();
- uassert(
- ErrorCodes::InvalidNamespace,
- str::stream() << "Invalid database name: '" << dbname << "'",
- NamespaceString::validDBName(dbname, NamespaceString::DollarInDbNameBehavior::Allow));
+ OperationContextSession sessionTxnState(opCtx,
+ shouldCheckoutSession,
+ autocommitVal,
+ startMultiDocTxn,
+ dbname,
+ command->getName());
std::unique_ptr<MaintenanceModeSetter> mmSetter;
diff --git a/src/mongo/db/session.cpp b/src/mongo/db/session.cpp
index fa04cc871de..db85322dcb1 100644
--- a/src/mongo/db/session.cpp
+++ b/src/mongo/db/session.cpp
@@ -97,6 +97,27 @@ public:
namespace {
+// The command names that are allowed in a multi-document transaction.
+const StringMap<int> txnCmdWhitelist = {{"abortTransaction", 1},
+ {"aggregate", 1},
+ {"commitTransaction", 1},
+ {"count", 1},
+ {"delete", 1},
+ {"distinct", 1},
+ {"doTxn", 1},
+ {"find", 1},
+ {"findandmodify", 1},
+ {"findAndModify", 1},
+ {"geoSearch", 1},
+ {"getMore", 1},
+ {"insert", 1},
+ {"prepareTransaction", 1},
+ {"update", 1}};
+
+// The commands that can be run on the 'admin' database in multi-document transactions.
+const StringMap<int> txnAdminCommands = {
+ {"abortTransaction", 1}, {"commitTransaction", 1}, {"doTxn", 1}, {"prepareTransaction", 1}};
+
void fassertOnRepeatedExecution(const LogicalSessionId& lsid,
TxnNumber txnNumber,
StmtId stmtId,
@@ -319,13 +340,26 @@ void Session::refreshFromStorageIfNeeded(OperationContext* opCtx) {
void Session::beginOrContinueTxn(OperationContext* opCtx,
TxnNumber txnNumber,
boost::optional<bool> autocommit,
- boost::optional<bool> startTransaction) {
+ boost::optional<bool> startTransaction,
+ StringData dbName,
+ StringData cmdName) {
if (opCtx->getClient()->isInDirectClient()) {
return;
}
invariant(!opCtx->lockState()->isLocked());
+ uassert(50767,
+ str::stream() << "Cannot run '" << cmdName << "' in a multi-document transaction.",
+ !autocommit || txnCmdWhitelist.find(cmdName) != txnCmdWhitelist.cend());
+
+ uassert(50844,
+ str::stream() << "Cannot run command against the '" << dbName
+ << "' database in a transaction",
+ !autocommit || (dbName != "config"_sd && dbName != "local"_sd &&
+ (dbName != "admin"_sd ||
+ txnAdminCommands.find(cmdName) != txnAdminCommands.cend())));
+
TxnNumber txnNumberAtStart;
bool canKillCursors = false;
{
diff --git a/src/mongo/db/session.h b/src/mongo/db/session.h
index 3ed07c8c470..38858c3a162 100644
--- a/src/mongo/db/session.h
+++ b/src/mongo/db/session.h
@@ -152,7 +152,9 @@ public:
void beginOrContinueTxn(OperationContext* opCtx,
TxnNumber txnNumber,
boost::optional<bool> autocommit,
- boost::optional<bool> startTransaction);
+ boost::optional<bool> startTransaction,
+ StringData dbName,
+ StringData cmdName);
/**
* Similar to beginOrContinueTxn except it is used specifically for shard migrations and does
* not check or modify the autocommit parameter.
diff --git a/src/mongo/db/session_catalog.cpp b/src/mongo/db/session_catalog.cpp
index d70b68da890..6dd27f2f501 100644
--- a/src/mongo/db/session_catalog.cpp
+++ b/src/mongo/db/session_catalog.cpp
@@ -238,7 +238,9 @@ void SessionCatalog::_releaseSession(const LogicalSessionId& lsid) {
OperationContextSession::OperationContextSession(OperationContext* opCtx,
bool checkOutSession,
boost::optional<bool> autocommit,
- boost::optional<bool> startTransaction)
+ boost::optional<bool> startTransaction,
+ StringData dbName,
+ StringData cmdName)
: _opCtx(opCtx) {
if (!opCtx->getLogicalSessionId()) {
@@ -267,7 +269,7 @@ OperationContextSession::OperationContextSession(OperationContext* opCtx,
if (opCtx->getTxnNumber()) {
checkedOutSession->get()->beginOrContinueTxn(
- opCtx, *opCtx->getTxnNumber(), autocommit, startTransaction);
+ opCtx, *opCtx->getTxnNumber(), autocommit, startTransaction, dbName, cmdName);
}
}
diff --git a/src/mongo/db/session_catalog.h b/src/mongo/db/session_catalog.h
index fcc2164ca18..18e33d8b385 100644
--- a/src/mongo/db/session_catalog.h
+++ b/src/mongo/db/session_catalog.h
@@ -250,7 +250,9 @@ public:
OperationContextSession(OperationContext* opCtx,
bool checkOutSession,
boost::optional<bool> autocommit,
- boost::optional<bool> startTransaction);
+ boost::optional<bool> startTransaction,
+ StringData dbName,
+ StringData cmdName);
~OperationContextSession();
diff --git a/src/mongo/db/session_catalog_test.cpp b/src/mongo/db/session_catalog_test.cpp
index 922e4143130..2dd8279a1c7 100644
--- a/src/mongo/db/session_catalog_test.cpp
+++ b/src/mongo/db/session_catalog_test.cpp
@@ -89,7 +89,7 @@ TEST_F(SessionCatalogTest, OperationContextCheckedOutSession) {
const TxnNumber txnNum = 20;
opCtx()->setTxnNumber(txnNum);
- OperationContextSession ocs(opCtx(), true, boost::none, boost::none);
+ OperationContextSession ocs(opCtx(), true, boost::none, boost::none, "testDB", "insert");
auto session = OperationContextSession::get(opCtx());
ASSERT(session);
ASSERT_EQ(*opCtx()->getLogicalSessionId(), session->getSessionId());
@@ -98,7 +98,7 @@ TEST_F(SessionCatalogTest, OperationContextCheckedOutSession) {
TEST_F(SessionCatalogTest, OperationContextNonCheckedOutSession) {
opCtx()->setLogicalSessionId(makeLogicalSessionIdForTest());
- OperationContextSession ocs(opCtx(), false, boost::none, boost::none);
+ OperationContextSession ocs(opCtx(), false, boost::none, boost::none, "testDB", "insert");
auto session = OperationContextSession::get(opCtx());
ASSERT(!session);
@@ -117,7 +117,7 @@ TEST_F(SessionCatalogTest, GetOrCreateSessionAfterCheckOutSession) {
opCtx()->setLogicalSessionId(lsid);
boost::optional<OperationContextSession> ocs;
- ocs.emplace(opCtx(), true, boost::none, false);
+ ocs.emplace(opCtx(), true, boost::none, false, "testDB", "insert");
stdx::async(stdx::launch::async, [&] {
Client::initThreadIfNotAlready();
@@ -146,11 +146,13 @@ TEST_F(SessionCatalogTest, NestedOperationContextSession) {
opCtx()->setLogicalSessionId(makeLogicalSessionIdForTest());
{
- OperationContextSession outerScopedSession(opCtx(), true, boost::none, boost::none);
+ OperationContextSession outerScopedSession(
+ opCtx(), true, boost::none, boost::none, "testDB", "insert");
{
DirectClientSetter inDirectClient(opCtx());
- OperationContextSession innerScopedSession(opCtx(), true, boost::none, boost::none);
+ OperationContextSession innerScopedSession(
+ opCtx(), true, boost::none, boost::none, "testDB", "insert");
auto session = OperationContextSession::get(opCtx());
ASSERT(session);
@@ -173,7 +175,8 @@ TEST_F(SessionCatalogTest, StashInNestedSessionIsANoop) {
opCtx()->setTxnNumber(1);
{
- OperationContextSession outerScopedSession(opCtx(), true, boost::none, boost::none);
+ OperationContextSession outerScopedSession(
+ opCtx(), true, boost::none, boost::none, "testDB", "find");
Locker* originalLocker = opCtx()->lockState();
RecoveryUnit* originalRecoveryUnit = opCtx()->recoveryUnit();
@@ -198,7 +201,8 @@ TEST_F(SessionCatalogTest, StashInNestedSessionIsANoop) {
{
// Make it look like we're in a DBDirectClient running a nested operation.
DirectClientSetter inDirectClient(opCtx());
- OperationContextSession innerScopedSession(opCtx(), true, boost::none, boost::none);
+ OperationContextSession innerScopedSession(
+ opCtx(), true, boost::none, boost::none, "testDB", "find");
// Report to Session that there is a stashed cursor. If we were not in a nested session,
// this would ensure that stashing is not a noop.
@@ -220,7 +224,8 @@ TEST_F(SessionCatalogTest, UnstashInNestedSessionIsANoop) {
opCtx()->setTxnNumber(1);
{
- OperationContextSession outerScopedSession(opCtx(), true, boost::none, boost::none);
+ OperationContextSession outerScopedSession(
+ opCtx(), true, boost::none, boost::none, "testDB", "find");
Locker* originalLocker = opCtx()->lockState();
RecoveryUnit* originalRecoveryUnit = opCtx()->recoveryUnit();
@@ -239,7 +244,8 @@ TEST_F(SessionCatalogTest, UnstashInNestedSessionIsANoop) {
{
// Make it look like we're in a DBDirectClient running a nested operation.
DirectClientSetter inDirectClient(opCtx());
- OperationContextSession innerScopedSession(opCtx(), true, boost::none, boost::none);
+ OperationContextSession innerScopedSession(
+ opCtx(), true, boost::none, boost::none, "testDB", "find");
OperationContextSession::get(opCtx())->unstashTransactionResources(opCtx(), "find");
diff --git a/src/mongo/db/session_test.cpp b/src/mongo/db/session_test.cpp
index fc07d137576..9b55555a2f6 100644
--- a/src/mongo/db/session_test.cpp
+++ b/src/mongo/db/session_test.cpp
@@ -176,7 +176,7 @@ TEST_F(SessionTest, SessionEntryNotWrittenOnBegin) {
session.refreshFromStorageIfNeeded(opCtx());
const TxnNumber txnNum = 20;
- session.beginOrContinueTxn(opCtx(), txnNum, boost::none, boost::none);
+ session.beginOrContinueTxn(opCtx(), txnNum, boost::none, boost::none, "testDB", "insert");
ASSERT_EQ(sessionId, session.getSessionId());
ASSERT(session.getLastWriteOpTime(txnNum).isNull());
@@ -194,7 +194,7 @@ TEST_F(SessionTest, SessionEntryWrittenAtFirstWrite) {
session.refreshFromStorageIfNeeded(opCtx());
const TxnNumber txnNum = 21;
- session.beginOrContinueTxn(opCtx(), txnNum, boost::none, boost::none);
+ session.beginOrContinueTxn(opCtx(), txnNum, boost::none, boost::none, "testDB", "insert");
const auto opTime = [&] {
AutoGetCollection autoColl(opCtx(), kNss, MODE_IX);
@@ -227,7 +227,7 @@ TEST_F(SessionTest, StartingNewerTransactionUpdatesThePersistedSession) {
session.refreshFromStorageIfNeeded(opCtx());
const auto writeTxnRecordFn = [&](TxnNumber txnNum, StmtId stmtId, repl::OpTime prevOpTime) {
- session.beginOrContinueTxn(opCtx(), txnNum, boost::none, boost::none);
+ session.beginOrContinueTxn(opCtx(), txnNum, boost::none, boost::none, "testDB", "insert");
AutoGetCollection autoColl(opCtx(), kNss, MODE_IX);
WriteUnitOfWork wuow(opCtx());
@@ -266,9 +266,10 @@ TEST_F(SessionTest, StartingOldTxnShouldAssert) {
session.refreshFromStorageIfNeeded(opCtx());
const TxnNumber txnNum = 20;
- session.beginOrContinueTxn(opCtx(), txnNum, boost::none, boost::none);
+ session.beginOrContinueTxn(opCtx(), txnNum, boost::none, boost::none, "testDB", "insert");
- ASSERT_THROWS_CODE(session.beginOrContinueTxn(opCtx(), txnNum - 1, boost::none, boost::none),
+ ASSERT_THROWS_CODE(session.beginOrContinueTxn(
+ opCtx(), txnNum - 1, boost::none, boost::none, "testDB", "insert"),
AssertionException,
ErrorCodes::TransactionTooOld);
ASSERT(session.getLastWriteOpTime(txnNum).isNull());
@@ -286,7 +287,7 @@ TEST_F(SessionTest, SessionTransactionsCollectionNotDefaultCreated) {
ASSERT(client.runCommand(nss.db().toString(), BSON("drop" << nss.coll()), dropResult));
const TxnNumber txnNum = 21;
- session.beginOrContinueTxn(opCtx(), txnNum, boost::none, boost::none);
+ session.beginOrContinueTxn(opCtx(), txnNum, boost::none, boost::none, "testDB", "insert");
AutoGetCollection autoColl(opCtx(), kNss, MODE_IX);
WriteUnitOfWork wuow(opCtx());
@@ -301,7 +302,7 @@ TEST_F(SessionTest, CheckStatementExecuted) {
session.refreshFromStorageIfNeeded(opCtx());
const TxnNumber txnNum = 100;
- session.beginOrContinueTxn(opCtx(), txnNum, boost::none, boost::none);
+ session.beginOrContinueTxn(opCtx(), txnNum, boost::none, boost::none, "testDB", "insert");
const auto writeTxnRecordFn = [&](StmtId stmtId, repl::OpTime prevOpTime) {
AutoGetCollection autoColl(opCtx(), kNss, MODE_IX);
@@ -342,7 +343,7 @@ TEST_F(SessionTest, CheckStatementExecutedForOldTransactionThrows) {
session.refreshFromStorageIfNeeded(opCtx());
const TxnNumber txnNum = 100;
- session.beginOrContinueTxn(opCtx(), txnNum, boost::none, boost::none);
+ session.beginOrContinueTxn(opCtx(), txnNum, boost::none, boost::none, "testDB", "insert");
ASSERT_THROWS_CODE(session.checkStatementExecuted(opCtx(), txnNum - 1, 0),
AssertionException,
@@ -365,7 +366,7 @@ TEST_F(SessionTest, WriteOpCompletedOnPrimaryForOldTransactionThrows) {
session.refreshFromStorageIfNeeded(opCtx());
const TxnNumber txnNum = 100;
- session.beginOrContinueTxn(opCtx(), txnNum, boost::none, boost::none);
+ session.beginOrContinueTxn(opCtx(), txnNum, boost::none, boost::none, "testDB", "insert");
{
AutoGetCollection autoColl(opCtx(), kNss, MODE_IX);
@@ -392,7 +393,7 @@ TEST_F(SessionTest, WriteOpCompletedOnPrimaryForInvalidatedTransactionThrows) {
session.refreshFromStorageIfNeeded(opCtx());
const TxnNumber txnNum = 100;
- session.beginOrContinueTxn(opCtx(), txnNum, boost::none, boost::none);
+ session.beginOrContinueTxn(opCtx(), txnNum, boost::none, boost::none, "testDB", "insert");
AutoGetCollection autoColl(opCtx(), kNss, MODE_IX);
WriteUnitOfWork wuow(opCtx());
@@ -412,7 +413,7 @@ TEST_F(SessionTest, WriteOpCompletedOnPrimaryCommitIgnoresInvalidation) {
session.refreshFromStorageIfNeeded(opCtx());
const TxnNumber txnNum = 100;
- session.beginOrContinueTxn(opCtx(), txnNum, boost::none, boost::none);
+ session.beginOrContinueTxn(opCtx(), txnNum, boost::none, boost::none, "testDB", "insert");
{
AutoGetCollection autoColl(opCtx(), kNss, MODE_IX);
@@ -507,7 +508,7 @@ TEST_F(SessionTest, ErrorOnlyWhenStmtIdBeingCheckedIsNotInCache) {
Session session(sessionId);
session.refreshFromStorageIfNeeded(opCtx());
- session.beginOrContinueTxn(opCtx(), txnNum, boost::none, boost::none);
+ session.beginOrContinueTxn(opCtx(), txnNum, boost::none, boost::none, "testDB", "insert");
auto firstOpTime = ([&]() {
AutoGetCollection autoColl(opCtx(), kNss, MODE_IX);
@@ -588,7 +589,7 @@ DEATH_TEST_F(SessionTest, CommitWithoutCursorKillFunctionInvariants, "_cursorKil
const TxnNumber txnNum = 26;
opCtx()->setLogicalSessionId(sessionId);
opCtx()->setTxnNumber(txnNum);
- session.beginOrContinueTxn(opCtx(), txnNum, false, true);
+ session.beginOrContinueTxn(opCtx(), txnNum, false, true, "testDB", "find");
session.unstashTransactionResources(opCtx(), "find");
session.commitTransaction(opCtx());
@@ -610,7 +611,7 @@ TEST_F(SessionTest, StashAndUnstashResources) {
Session session(sessionId);
session.refreshFromStorageIfNeeded(opCtx());
- session.beginOrContinueTxn(opCtx(), txnNum, false, true);
+ session.beginOrContinueTxn(opCtx(), txnNum, false, true, "testDB", "find");
repl::ReadConcernArgs readConcernArgs;
ASSERT_OK(readConcernArgs.initialize(BSON("find"
@@ -664,7 +665,7 @@ TEST_F(SessionTest, ReportStashedResources) {
Session session(sessionId);
session.refreshFromStorageIfNeeded(opCtx());
- session.beginOrContinueTxn(opCtx(), txnNum, false, true);
+ session.beginOrContinueTxn(opCtx(), txnNum, false, true, "testDB", "find");
repl::ReadConcernArgs readConcernArgs;
ASSERT_OK(readConcernArgs.initialize(BSON("find"
@@ -734,14 +735,14 @@ TEST_F(SessionTest, CannotSpecifyStartTransactionOnInProgressTxn) {
const TxnNumber txnNum = 100;
// Must specify startTransaction=true and autocommit=false to start a transaction.
- session.beginOrContinueTxn(opCtx(), txnNum, false, true);
+ session.beginOrContinueTxn(opCtx(), txnNum, false, true, "testDB", "insert");
// Autocommit should be set to false and we should be in a mult-doc transaction.
ASSERT_FALSE(session.getAutocommit());
ASSERT_TRUE(session.inSnapshotReadOrMultiDocumentTransaction());
// Cannot try to start a transaction that already started.
- ASSERT_THROWS_CODE(session.beginOrContinueTxn(opCtx(), txnNum, false, true),
+ ASSERT_THROWS_CODE(session.beginOrContinueTxn(opCtx(), txnNum, false, true, "testDB", "insert"),
AssertionException,
ErrorCodes::ConflictingOperationInProgress);
}
@@ -757,7 +758,7 @@ TEST_F(SessionTest, AutocommitRequiredOnEveryTxnOp) {
const TxnNumber txnNum = 100;
opCtx()->setLogicalSessionId(sessionId);
opCtx()->setTxnNumber(txnNum);
- session.beginOrContinueTxn(opCtx(), txnNum, false, true);
+ session.beginOrContinueTxn(opCtx(), txnNum, false, true, "testDB", "insert");
// We must have stashed transaction resources to do a second operation on the transaction.
session.unstashTransactionResources(opCtx(), "insert");
@@ -769,17 +770,19 @@ TEST_F(SessionTest, AutocommitRequiredOnEveryTxnOp) {
ASSERT_FALSE(session.getAutocommit());
// Omitting 'autocommit' after the first statement of a transaction should throw an error.
- ASSERT_THROWS_CODE(session.beginOrContinueTxn(opCtx(), txnNum, boost::none, boost::none),
- AssertionException,
- ErrorCodes::InvalidOptions);
+ ASSERT_THROWS_CODE(
+ session.beginOrContinueTxn(opCtx(), txnNum, boost::none, boost::none, "testDB", "insert"),
+ AssertionException,
+ ErrorCodes::InvalidOptions);
// Setting 'autocommit=true' should throw an error.
- ASSERT_THROWS_CODE(session.beginOrContinueTxn(opCtx(), txnNum, true, boost::none),
- AssertionException,
- ErrorCodes::InvalidOptions);
+ ASSERT_THROWS_CODE(
+ session.beginOrContinueTxn(opCtx(), txnNum, true, boost::none, "testDB", "insert"),
+ AssertionException,
+ ErrorCodes::InvalidOptions);
// Including autocommit=false should succeed.
- session.beginOrContinueTxn(opCtx(), txnNum, false, boost::none);
+ session.beginOrContinueTxn(opCtx(), txnNum, false, boost::none, "testDB", "insert");
}
TEST_F(SessionTest, SameTransactionPreservesStoredStatements) {
@@ -792,7 +795,7 @@ TEST_F(SessionTest, SameTransactionPreservesStoredStatements) {
const TxnNumber txnNum = 22;
opCtx()->setLogicalSessionId(sessionId);
opCtx()->setTxnNumber(txnNum);
- session.beginOrContinueTxn(opCtx(), txnNum, false, true);
+ session.beginOrContinueTxn(opCtx(), txnNum, false, true, "testDB", "insert");
// We must have stashed transaction resources to re-open the transaction.
session.unstashTransactionResources(opCtx(), "insert");
@@ -807,7 +810,7 @@ TEST_F(SessionTest, SameTransactionPreservesStoredStatements) {
ASSERT_BSONOBJ_EQ(operation.toBSON(), session.transactionOperationsForTest()[0].toBSON());
// Re-opening the same transaction should have no effect.
- session.beginOrContinueTxn(opCtx(), txnNum, false, boost::none);
+ session.beginOrContinueTxn(opCtx(), txnNum, false, boost::none, "testDB", "insert");
ASSERT_BSONOBJ_EQ(operation.toBSON(), session.transactionOperationsForTest()[0].toBSON());
}
@@ -821,7 +824,7 @@ TEST_F(SessionTest, AbortClearsStoredStatements) {
const TxnNumber txnNum = 24;
opCtx()->setLogicalSessionId(sessionId);
opCtx()->setTxnNumber(txnNum);
- session.beginOrContinueTxn(opCtx(), txnNum, false, true);
+ session.beginOrContinueTxn(opCtx(), txnNum, false, true, "testDB", "insert");
session.unstashTransactionResources(opCtx(), "insert");
auto operation = repl::OplogEntry::makeInsertOperation(kNss, kUUID, BSON("TestValue" << 0));
session.addTransactionOperation(opCtx(), operation);
@@ -846,7 +849,7 @@ TEST_F(SessionTest, EmptyTransactionCommit) {
const TxnNumber txnNum = 25;
opCtx()->setLogicalSessionId(sessionId);
opCtx()->setTxnNumber(txnNum);
- session.beginOrContinueTxn(opCtx(), txnNum, false, true);
+ session.beginOrContinueTxn(opCtx(), txnNum, false, true, "admin", "commitTransaction");
session.unstashTransactionResources(opCtx(), "commitTransaction");
// The transaction machinery cannot store an empty locker.
Lock::GlobalLock lk(opCtx(), MODE_IX, Date_t::now(), Lock::InterruptBehavior::kThrow);
@@ -867,7 +870,7 @@ TEST_F(SessionTest, EmptyTransactionAbort) {
const TxnNumber txnNum = 26;
opCtx()->setLogicalSessionId(sessionId);
opCtx()->setTxnNumber(txnNum);
- session.beginOrContinueTxn(opCtx(), txnNum, false, true);
+ session.beginOrContinueTxn(opCtx(), txnNum, false, true, "admin", "abortTransaction");
session.unstashTransactionResources(opCtx(), "abortTransaction");
// The transaction machinery cannot store an empty locker.
{ Lock::GlobalLock lk(opCtx(), MODE_IX, Date_t::now(), Lock::InterruptBehavior::kThrow); }
@@ -886,7 +889,7 @@ TEST_F(SessionTest, ConcurrencyOfUnstashAndAbort) {
const TxnNumber txnNum = 26;
opCtx()->setLogicalSessionId(sessionId);
opCtx()->setTxnNumber(txnNum);
- session.beginOrContinueTxn(opCtx(), txnNum, false, true);
+ session.beginOrContinueTxn(opCtx(), txnNum, false, true, "testDB", "find");
// The transaction may be aborted without checking out the session.
session.abortArbitraryTransaction(opCtx(), kKillCursors);
@@ -907,7 +910,7 @@ TEST_F(SessionTest, ConcurrencyOfUnstashAndMigration) {
const TxnNumber txnNum = 26;
opCtx()->setLogicalSessionId(sessionId);
opCtx()->setTxnNumber(txnNum);
- session.beginOrContinueTxn(opCtx(), txnNum, false, true);
+ session.beginOrContinueTxn(opCtx(), txnNum, false, true, "testDB", "insert");
session.unstashTransactionResources(opCtx(), "insert");
// The transaction machinery cannot store an empty locker.
@@ -936,7 +939,7 @@ TEST_F(SessionTest, ConcurrencyOfStashAndAbort) {
const TxnNumber txnNum = 26;
opCtx()->setLogicalSessionId(sessionId);
opCtx()->setTxnNumber(txnNum);
- session.beginOrContinueTxn(opCtx(), txnNum, false, true);
+ session.beginOrContinueTxn(opCtx(), txnNum, false, true, "testDB", "find");
session.unstashTransactionResources(opCtx(), "find");
@@ -957,7 +960,7 @@ TEST_F(SessionTest, ConcurrencyOfStashAndMigration) {
const TxnNumber txnNum = 26;
opCtx()->setLogicalSessionId(sessionId);
opCtx()->setTxnNumber(txnNum);
- session.beginOrContinueTxn(opCtx(), txnNum, false, true);
+ session.beginOrContinueTxn(opCtx(), txnNum, false, true, "testDB", "insert");
session.unstashTransactionResources(opCtx(), "insert");
auto operation = repl::OplogEntry::makeInsertOperation(kNss, kUUID, BSON("TestValue" << 0));
@@ -983,7 +986,7 @@ TEST_F(SessionTest, ConcurrencyOfAddTransactionOperationAndAbort) {
const TxnNumber txnNum = 26;
opCtx()->setLogicalSessionId(sessionId);
opCtx()->setTxnNumber(txnNum);
- session.beginOrContinueTxn(opCtx(), txnNum, false, true);
+ session.beginOrContinueTxn(opCtx(), txnNum, false, true, "testDB", "insert");
session.unstashTransactionResources(opCtx(), "insert");
@@ -1007,7 +1010,7 @@ TEST_F(SessionTest, ConcurrencyOfAddTransactionOperationAndMigration) {
const TxnNumber txnNum = 26;
opCtx()->setLogicalSessionId(sessionId);
opCtx()->setTxnNumber(txnNum);
- session.beginOrContinueTxn(opCtx(), txnNum, false, true);
+ session.beginOrContinueTxn(opCtx(), txnNum, false, true, "testDB", "find");
session.unstashTransactionResources(opCtx(), "find");
auto operation = repl::OplogEntry::makeInsertOperation(kNss, kUUID, BSON("TestValue" << 0));
@@ -1034,7 +1037,7 @@ TEST_F(SessionTest, ConcurrencyOfEndTransactionAndRetrieveOperationsAndAbort) {
const TxnNumber txnNum = 26;
opCtx()->setLogicalSessionId(sessionId);
opCtx()->setTxnNumber(txnNum);
- session.beginOrContinueTxn(opCtx(), txnNum, false, true);
+ session.beginOrContinueTxn(opCtx(), txnNum, false, true, "testDB", "insert");
session.unstashTransactionResources(opCtx(), "insert");
@@ -1057,7 +1060,7 @@ TEST_F(SessionTest, ConcurrencyOfEndTransactionAndRetrieveOperationsAndMigration
const TxnNumber txnNum = 26;
opCtx()->setLogicalSessionId(sessionId);
opCtx()->setTxnNumber(txnNum);
- session.beginOrContinueTxn(opCtx(), txnNum, false, true);
+ session.beginOrContinueTxn(opCtx(), txnNum, false, true, "testDB", "insert");
session.unstashTransactionResources(opCtx(), "insert");
auto operation = repl::OplogEntry::makeInsertOperation(kNss, kUUID, BSON("TestValue" << 0));
@@ -1084,7 +1087,7 @@ TEST_F(SessionTest, ConcurrencyOfCommitTransactionAndAbort) {
const TxnNumber txnNum = 26;
opCtx()->setLogicalSessionId(sessionId);
opCtx()->setTxnNumber(txnNum);
- session.beginOrContinueTxn(opCtx(), txnNum, false, true);
+ session.beginOrContinueTxn(opCtx(), txnNum, false, true, "admin", "commitTransaction");
session.unstashTransactionResources(opCtx(), "commitTransaction");
@@ -1106,7 +1109,7 @@ TEST_F(SessionTest, ConcurrencyOfCommitTransactionAndMigration) {
const TxnNumber txnNum = 26;
opCtx()->setLogicalSessionId(sessionId);
opCtx()->setTxnNumber(txnNum);
- session.beginOrContinueTxn(opCtx(), txnNum, false, true);
+ session.beginOrContinueTxn(opCtx(), txnNum, false, true, "testDB", "insert");
session.unstashTransactionResources(opCtx(), "insert");
auto operation = repl::OplogEntry::makeInsertOperation(kNss, kUUID, BSON("TestValue" << 0));
@@ -1132,7 +1135,7 @@ TEST_F(SessionTest, TransactionTooLargeWhileBuilding) {
const TxnNumber txnNum = 28;
opCtx()->setLogicalSessionId(sessionId);
opCtx()->setTxnNumber(txnNum);
- session.beginOrContinueTxn(opCtx(), txnNum, false, true);
+ session.beginOrContinueTxn(opCtx(), txnNum, false, true, "testDB", "insert");
session.unstashTransactionResources(opCtx(), "insert");