summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamy Lanka <samy.lanka@mongodb.com>2019-07-11 10:44:27 -0400
committerSamy Lanka <samy.lanka@mongodb.com>2019-08-08 11:35:32 -0400
commit77967c90b1a521108c052af235ce7de9742aa95e (patch)
tree22809f1433ab3b2b3f85359400a36a7d7f8050c4
parent321201823455e1c648b7c6bd4ae0a59d1b7115b8 (diff)
downloadmongo-77967c90b1a521108c052af235ce7de9742aa95e.tar.gz
SERVER-40466 Unify checks for being in a multi-document transaction
-rw-r--r--src/mongo/db/catalog/index_catalog_entry_impl.cpp16
-rw-r--r--src/mongo/db/catalog_raii.cpp11
-rw-r--r--src/mongo/db/commands/distinct.cpp4
-rw-r--r--src/mongo/db/commands/find_and_modify.cpp17
-rw-r--r--src/mongo/db/commands/find_cmd.cpp3
-rw-r--r--src/mongo/db/commands/run_aggregate.cpp8
-rw-r--r--src/mongo/db/commands/txn_cmds.cpp4
-rw-r--r--src/mongo/db/commands/write_commands/write_commands.cpp4
-rw-r--r--src/mongo/db/db_raii.cpp2
-rw-r--r--src/mongo/db/initialize_operation_session_info.cpp1
-rw-r--r--src/mongo/db/kill_sessions_local.cpp4
-rw-r--r--src/mongo/db/op_observer_impl.cpp17
-rw-r--r--src/mongo/db/operation_context.h17
-rw-r--r--src/mongo/db/ops/write_ops_exec.cpp37
-rw-r--r--src/mongo/db/pipeline/process_interface_shardsvr.cpp4
-rw-r--r--src/mongo/db/query/get_executor.cpp19
-rw-r--r--src/mongo/db/query/get_executor.h4
-rw-r--r--src/mongo/db/read_concern_mongod.cpp7
-rw-r--r--src/mongo/db/repl/oplog.cpp3
-rw-r--r--src/mongo/db/repl/replication_coordinator_impl.cpp7
-rw-r--r--src/mongo/db/s/txn_two_phase_commit_cmds.cpp4
-rw-r--r--src/mongo/db/service_entry_point_common.cpp16
-rw-r--r--src/mongo/db/session_catalog_mongod.cpp7
-rw-r--r--src/mongo/db/transaction_participant.cpp4
-rw-r--r--src/mongo/db/transaction_participant.h24
-rw-r--r--src/mongo/db/transaction_participant_test.cpp22
-rw-r--r--src/mongo/dbtests/storage_timestamp_tests.cpp2
27 files changed, 127 insertions, 141 deletions
diff --git a/src/mongo/db/catalog/index_catalog_entry_impl.cpp b/src/mongo/db/catalog/index_catalog_entry_impl.cpp
index 5b5523ce7c1..f6e19d9942a 100644
--- a/src/mongo/db/catalog/index_catalog_entry_impl.cpp
+++ b/src/mongo/db/catalog/index_catalog_entry_impl.cpp
@@ -125,12 +125,11 @@ void IndexCatalogEntryImpl::init(std::unique_ptr<IndexAccessMethod> accessMethod
}
bool IndexCatalogEntryImpl::isReady(OperationContext* opCtx) const {
- auto txnParticipant = TransactionParticipant::get(opCtx);
// For multi-document transactions, we can open a snapshot prior to checking the
// minimumSnapshotVersion on a collection. This means we are unprotected from reading
// out-of-sync index catalog entries. To fix this, we uassert if we detect that the
// in-memory catalog is out-of-sync with the on-disk catalog.
- if (txnParticipant && txnParticipant.inMultiDocumentTransaction()) {
+ if (opCtx->inMultiDocumentTransaction()) {
if (!_catalogIsPresent(opCtx) || _catalogIsReady(opCtx) != _isReady) {
uasserted(ErrorCodes::SnapshotUnavailable,
str::stream() << "Unable to read from a snapshot due to pending collection"
@@ -156,10 +155,12 @@ bool IndexCatalogEntryImpl::isMultikey(OperationContext* opCtx) const {
// and the read-path will query this state before determining there is no interesting multikey
// state. Note, it's always legal, though potentially wasteful, to return `true`.
auto txnParticipant = TransactionParticipant::get(opCtx);
- if (!txnParticipant || !txnParticipant.inMultiDocumentTransaction()) {
+ if (!txnParticipant || !txnParticipant.transactionIsOpen()) {
return false;
}
+ invariant(txnParticipant);
+
for (const MultikeyPathInfo& path : txnParticipant.getUncommittedMultikeyPathInfos()) {
if (path.nss == ns() && path.indexName == _descriptor->indexName()) {
return true;
@@ -173,10 +174,12 @@ MultikeyPaths IndexCatalogEntryImpl::getMultikeyPaths(OperationContext* opCtx) c
stdx::lock_guard<stdx::mutex> lk(_indexMultikeyPathsMutex);
auto txnParticipant = TransactionParticipant::get(opCtx);
- if (!txnParticipant || !txnParticipant.inMultiDocumentTransaction()) {
+ if (!txnParticipant || !txnParticipant.transactionIsOpen()) {
return _indexMultikeyPaths;
}
+ invariant(txnParticipant);
+
MultikeyPaths ret = _indexMultikeyPaths;
for (const MultikeyPathInfo& path : txnParticipant.getUncommittedMultikeyPathInfos()) {
if (path.nss == ns() && path.indexName == _descriptor->indexName()) {
@@ -296,7 +299,7 @@ void IndexCatalogEntryImpl::setMultikey(OperationContext* opCtx,
// multikey flag write and the parent transaction. We can do this write separately and commit it
// before the parent transaction commits.
auto txnParticipant = TransactionParticipant::get(opCtx);
- if (txnParticipant && txnParticipant.inMultiDocumentTransaction()) {
+ if (opCtx->inMultiDocumentTransaction()) {
TransactionParticipant::SideTransactionBlock sideTxn(opCtx);
writeConflictRetry(opCtx, "set index multikey", ns().ns(), [&] {
WriteUnitOfWork wuow(opCtx);
@@ -344,7 +347,8 @@ void IndexCatalogEntryImpl::setMultikey(OperationContext* opCtx,
// multikey flag until after the transaction commits, we track extra information here to let
// subsequent readers within the same transaction know if this index was set as multikey by a
// previous write in the transaction.
- if (txnParticipant && txnParticipant.inMultiDocumentTransaction()) {
+ if (opCtx->inMultiDocumentTransaction()) {
+ invariant(txnParticipant);
txnParticipant.addUncommittedMultikeyPathInfo(
MultikeyPathInfo{ns(), _descriptor->indexName(), std::move(paths)});
}
diff --git a/src/mongo/db/catalog_raii.cpp b/src/mongo/db/catalog_raii.cpp
index e00052a7ddc..86599eff65c 100644
--- a/src/mongo/db/catalog_raii.cpp
+++ b/src/mongo/db/catalog_raii.cpp
@@ -107,11 +107,12 @@ AutoGetCollection::AutoGetCollection(OperationContext* opCtx,
<< nsOrUUID.toString());
if (_coll) {
- // Unlike read concern majority, read concern snapshot cannot yield and wait when there are
- // pending catalog changes. Instead, we must return an error in such situations. We ignore
- // this restriction for the oplog, since it never has pending catalog changes.
- auto readConcernLevel = repl::ReadConcernArgs::get(opCtx).getLevel();
- if (readConcernLevel == repl::ReadConcernLevel::kSnapshotReadConcern &&
+ // If we are in a transaction and have a read timestamp, we cannot yield and wait when there
+ // are pending catalog changes. Instead, we must return an error in such situations. We
+ // ignore this restriction for the oplog, since it never has pending catalog changes.
+ if (opCtx->inMultiDocumentTransaction() &&
+ opCtx->recoveryUnit()->getTimestampReadSource() !=
+ RecoveryUnit::ReadSource::kNoTimestamp &&
_resolvedNss != NamespaceString::kRsOplogNamespace) {
auto mySnapshot = opCtx->recoveryUnit()->getPointInTimeReadTimestamp();
if (mySnapshot) {
diff --git a/src/mongo/db/commands/distinct.cpp b/src/mongo/db/commands/distinct.cpp
index cb84a6e71d9..b3cd929d5b2 100644
--- a/src/mongo/db/commands/distinct.cpp
+++ b/src/mongo/db/commands/distinct.cpp
@@ -56,7 +56,6 @@
#include "mongo/db/query/query_planner_common.h"
#include "mongo/db/query/view_response_formatter.h"
#include "mongo/db/s/collection_sharding_state.h"
-#include "mongo/db/transaction_participant.h"
#include "mongo/db/views/resolved_view.h"
#include "mongo/util/log.h"
@@ -185,12 +184,11 @@ public:
// Distinct doesn't filter orphan documents so it is not allowed to run on sharded
// collections in multi-document transactions.
- auto txnParticipant = TransactionParticipant::get(opCtx);
uassert(ErrorCodes::OperationNotSupportedInTransaction,
"Cannot run 'distinct' on a sharded collection in a multi-document transaction. "
"Please see http://dochub.mongodb.org/core/transaction-distinct for a recommended "
"alternative.",
- !txnParticipant || !txnParticipant.inMultiDocumentTransaction() ||
+ !opCtx->inMultiDocumentTransaction() ||
!CollectionShardingState::get(opCtx, nss)->getCurrentMetadata()->isSharded());
const ExtensionsCallbackReal extensionsCallback(opCtx, &nss);
diff --git a/src/mongo/db/commands/find_and_modify.cpp b/src/mongo/db/commands/find_and_modify.cpp
index 6c8fde275fb..0a30fd49293 100644
--- a/src/mongo/db/commands/find_and_modify.cpp
+++ b/src/mongo/db/commands/find_and_modify.cpp
@@ -128,11 +128,8 @@ void makeUpdateRequest(OperationContext* opCtx,
requestOut->setMulti(false);
requestOut->setExplain(explain);
- const auto& readConcernArgs = repl::ReadConcernArgs::get(opCtx);
- requestOut->setYieldPolicy(readConcernArgs.getLevel() ==
- repl::ReadConcernLevel::kSnapshotReadConcern
- ? PlanExecutor::INTERRUPT_ONLY
- : PlanExecutor::YIELD_AUTO);
+ requestOut->setYieldPolicy(opCtx->inMultiDocumentTransaction() ? PlanExecutor::INTERRUPT_ONLY
+ : PlanExecutor::YIELD_AUTO);
}
void makeDeleteRequest(OperationContext* opCtx,
@@ -149,11 +146,8 @@ void makeDeleteRequest(OperationContext* opCtx,
requestOut->setReturnDeleted(true); // Always return the old value.
requestOut->setExplain(explain);
- const auto& readConcernArgs = repl::ReadConcernArgs::get(opCtx);
- requestOut->setYieldPolicy(readConcernArgs.getLevel() ==
- repl::ReadConcernLevel::kSnapshotReadConcern
- ? PlanExecutor::INTERRUPT_ONLY
- : PlanExecutor::YIELD_AUTO);
+ requestOut->setYieldPolicy(opCtx->inMultiDocumentTransaction() ? PlanExecutor::INTERRUPT_ONLY
+ : PlanExecutor::YIELD_AUTO);
}
void appendCommandResponse(const PlanExecutor* exec,
@@ -330,8 +324,7 @@ public:
maybeDisableValidation.emplace(opCtx);
}
- const auto txnParticipant = TransactionParticipant::get(opCtx);
- const auto inTransaction = txnParticipant && txnParticipant.inMultiDocumentTransaction();
+ const auto inTransaction = opCtx->inMultiDocumentTransaction();
uassert(50781,
str::stream() << "Cannot write to system collection " << nsString.ns()
<< " within a transaction.",
diff --git a/src/mongo/db/commands/find_cmd.cpp b/src/mongo/db/commands/find_cmd.cpp
index 88705768bcc..bb8dfc793bd 100644
--- a/src/mongo/db/commands/find_cmd.cpp
+++ b/src/mongo/db/commands/find_cmd.cpp
@@ -272,8 +272,7 @@ public:
const auto txnParticipant = TransactionParticipant::get(opCtx);
uassert(ErrorCodes::InvalidOptions,
"It is illegal to open a tailable cursor in a transaction",
- !txnParticipant ||
- !(txnParticipant.inMultiDocumentTransaction() && qr->isTailable()));
+ !(opCtx->inMultiDocumentTransaction() && qr->isTailable()));
uassert(ErrorCodes::OperationNotSupportedInTransaction,
"The 'readOnce' option is not supported within a transaction.",
diff --git a/src/mongo/db/commands/run_aggregate.cpp b/src/mongo/db/commands/run_aggregate.cpp
index 5189946cd36..1ce0b3d1439 100644
--- a/src/mongo/db/commands/run_aggregate.cpp
+++ b/src/mongo/db/commands/run_aggregate.cpp
@@ -70,7 +70,6 @@
#include "mongo/db/s/sharding_state.h"
#include "mongo/db/service_context.h"
#include "mongo/db/storage/storage_options.h"
-#include "mongo/db/transaction_participant.h"
#include "mongo/db/views/view.h"
#include "mongo/db/views/view_catalog.h"
#include "mongo/util/log.h"
@@ -386,9 +385,7 @@ boost::intrusive_ptr<ExpressionContext> makeExpressionContext(
uassertStatusOK(resolveInvolvedNamespaces(opCtx, request)),
uuid);
expCtx->tempDir = storageGlobalParams.dbpath + "/_tmp";
- auto txnParticipant = TransactionParticipant::get(opCtx);
- expCtx->inMultiDocumentTransaction =
- txnParticipant && txnParticipant.inMultiDocumentTransaction();
+ expCtx->inMultiDocumentTransaction = opCtx->inMultiDocumentTransaction();
return expCtx;
}
@@ -523,10 +520,9 @@ Status runAggregate(OperationContext* opCtx,
liteParsedPipeline.assertSupportsReadConcern(
opCtx, request.getExplain(), serverGlobalParams.enableMajorityReadConcern);
} catch (const DBException& ex) {
- auto txnParticipant = TransactionParticipant::get(opCtx);
// If we are in a multi-document transaction, we intercept the 'readConcern'
// assertion in order to provide a more descriptive error message and code.
- if (txnParticipant && txnParticipant.inMultiDocumentTransaction()) {
+ if (opCtx->inMultiDocumentTransaction()) {
return {ErrorCodes::OperationNotSupportedInTransaction,
ex.toStatus("Operation not permitted in transaction").reason()};
}
diff --git a/src/mongo/db/commands/txn_cmds.cpp b/src/mongo/db/commands/txn_cmds.cpp
index d18a85a4064..ecb756b67d6 100644
--- a/src/mongo/db/commands/txn_cmds.cpp
+++ b/src/mongo/db/commands/txn_cmds.cpp
@@ -114,7 +114,7 @@ public:
uassert(ErrorCodes::NoSuchTransaction,
"Transaction isn't in progress",
- txnParticipant.inMultiDocumentTransaction());
+ txnParticipant.transactionIsOpen());
CurOpFailpointHelpers::waitWhileFailPointEnabled(
&hangBeforeCommitingTxn, opCtx, "hangBeforeCommitingTxn");
@@ -184,7 +184,7 @@ public:
uassert(ErrorCodes::NoSuchTransaction,
"Transaction isn't in progress",
- txnParticipant.inMultiDocumentTransaction());
+ txnParticipant.transactionIsOpen());
CurOpFailpointHelpers::waitWhileFailPointEnabled(
&hangBeforeAbortingTxn, opCtx, "hangBeforeAbortingTxn");
diff --git a/src/mongo/db/commands/write_commands/write_commands.cpp b/src/mongo/db/commands/write_commands/write_commands.cpp
index 7fa3bb3c82b..e321fb3cfa6 100644
--- a/src/mongo/db/commands/write_commands/write_commands.cpp
+++ b/src/mongo/db/commands/write_commands/write_commands.cpp
@@ -51,7 +51,6 @@
#include "mongo/db/repl/replication_coordinator.h"
#include "mongo/db/stats/counters.h"
#include "mongo/db/storage/duplicate_key_error_info.h"
-#include "mongo/db/transaction_participant.h"
#include "mongo/db/write_concern.h"
#include "mongo/s/stale_exception.h"
@@ -261,8 +260,7 @@ private:
}
void _transactionChecks(OperationContext* opCtx) const {
- auto txnParticipant = TransactionParticipant::get(opCtx);
- if (!txnParticipant || !txnParticipant.inMultiDocumentTransaction())
+ if (!opCtx->inMultiDocumentTransaction())
return;
uassert(50791,
str::stream() << "Cannot write to system collection " << ns().toString()
diff --git a/src/mongo/db/db_raii.cpp b/src/mongo/db/db_raii.cpp
index 854b02fbdf6..350a32c3dd6 100644
--- a/src/mongo/db/db_raii.cpp
+++ b/src/mongo/db/db_raii.cpp
@@ -378,7 +378,7 @@ LockMode getLockModeForQuery(OperationContext* opCtx, const boost::optional<Name
invariant(opCtx);
// Use IX locks for multi-statement transactions; otherwise, use IS locks.
- if (opCtx->getWriteUnitOfWork()) {
+ if (opCtx->inMultiDocumentTransaction()) {
uassert(51071,
"Cannot query system.views within a transaction",
!nss || !nss->isSystemDotViews());
diff --git a/src/mongo/db/initialize_operation_session_info.cpp b/src/mongo/db/initialize_operation_session_info.cpp
index 0257878e145..2059dae0623 100644
--- a/src/mongo/db/initialize_operation_session_info.cpp
+++ b/src/mongo/db/initialize_operation_session_info.cpp
@@ -130,6 +130,7 @@ OperationSessionInfoFromClient initializeOperationSessionInfo(OperationContext*
uassert(ErrorCodes::InvalidOptions,
"Specifying autocommit=true is not allowed.",
!osi.getAutocommit().value());
+ opCtx->setInMultiDocumentTransaction();
} else {
uassert(ErrorCodes::InvalidOptions,
"'startTransaction' field requires 'autocommit' field to also be specified",
diff --git a/src/mongo/db/kill_sessions_local.cpp b/src/mongo/db/kill_sessions_local.cpp
index 6f297922cc1..0e5c13a964d 100644
--- a/src/mongo/db/kill_sessions_local.cpp
+++ b/src/mongo/db/kill_sessions_local.cpp
@@ -91,7 +91,7 @@ void killSessionsAbortUnpreparedTransactions(OperationContext* opCtx,
matcher,
[](const ObservableSession& session) {
auto participant = TransactionParticipant::get(session);
- return participant.inMultiDocumentTransaction() && !participant.transactionIsPrepared();
+ return participant.transactionIsOpen() && !participant.transactionIsPrepared();
},
[](OperationContext* opCtx, const SessionToKill& session) {
TransactionParticipant::get(session).abortTransactionIfNotPrepared(opCtx);
@@ -138,7 +138,7 @@ void killSessionsLocalShutdownAllTransactions(OperationContext* opCtx) {
killSessionsAction(opCtx,
matcherAllSessions,
[](const ObservableSession& session) {
- return TransactionParticipant::get(session).inMultiDocumentTransaction();
+ return TransactionParticipant::get(session).transactionIsOpen();
},
[](OperationContext* opCtx, const SessionToKill& session) {
TransactionParticipant::get(session).shutdown(opCtx);
diff --git a/src/mongo/db/op_observer_impl.cpp b/src/mongo/db/op_observer_impl.cpp
index ad9c5c2b2b1..9be2ec5c89b 100644
--- a/src/mongo/db/op_observer_impl.cpp
+++ b/src/mongo/db/op_observer_impl.cpp
@@ -339,8 +339,8 @@ void OpObserverImpl::onInserts(OperationContext* opCtx,
std::vector<InsertStatement>::const_iterator last,
bool fromMigrate) {
auto txnParticipant = TransactionParticipant::get(opCtx);
- const bool inMultiDocumentTransaction = txnParticipant && opCtx->writesAreReplicated() &&
- txnParticipant.inMultiDocumentTransaction();
+ const bool inMultiDocumentTransaction =
+ txnParticipant && opCtx->writesAreReplicated() && txnParticipant.transactionIsOpen();
Date_t lastWriteDate;
@@ -349,11 +349,13 @@ void OpObserverImpl::onInserts(OperationContext* opCtx,
if (inMultiDocumentTransaction) {
// Do not add writes to the profile collection to the list of transaction operations, since
- // these are done outside the transaction.
+ // these are done outside the transaction. There is no top-level WriteUnitOfWork when we are
+ // in a SideTransactionBlock.
if (!opCtx->getWriteUnitOfWork()) {
invariant(nss.isSystemDotProfile());
return;
}
+
for (auto iter = first; iter != last; iter++) {
auto operation = MutableOplogEntry::makeInsertOperation(nss, uuid, iter->doc);
txnParticipant.addTransactionOperation(opCtx, operation);
@@ -428,8 +430,8 @@ void OpObserverImpl::onUpdate(OperationContext* opCtx, const OplogUpdateEntryArg
}
auto txnParticipant = TransactionParticipant::get(opCtx);
- const bool inMultiDocumentTransaction = txnParticipant && opCtx->writesAreReplicated() &&
- txnParticipant.inMultiDocumentTransaction();
+ const bool inMultiDocumentTransaction =
+ txnParticipant && opCtx->writesAreReplicated() && txnParticipant.transactionIsOpen();
OpTimeBundle opTime;
if (inMultiDocumentTransaction) {
@@ -489,8 +491,8 @@ void OpObserverImpl::onDelete(OperationContext* opCtx,
invariant(!documentKey.isEmpty());
auto txnParticipant = TransactionParticipant::get(opCtx);
- const bool inMultiDocumentTransaction = txnParticipant && opCtx->writesAreReplicated() &&
- txnParticipant.inMultiDocumentTransaction();
+ const bool inMultiDocumentTransaction =
+ txnParticipant && opCtx->writesAreReplicated() && txnParticipant.transactionIsOpen();
OpTimeBundle opTime;
if (inMultiDocumentTransaction) {
@@ -951,7 +953,6 @@ void logCommitOrAbortForPreparedTransaction(OperationContext* opCtx,
// There should not be a parent WUOW outside of this one. This guarantees the safety of the
// write conflict retry loop.
- invariant(!opCtx->getWriteUnitOfWork());
invariant(!opCtx->lockState()->inAWriteUnitOfWork());
// We must not have a maximum lock timeout, since writing the commit or abort oplog entry for a
diff --git a/src/mongo/db/operation_context.h b/src/mongo/db/operation_context.h
index 5723bc1dac7..26dc7a7723c 100644
--- a/src/mongo/db/operation_context.h
+++ b/src/mongo/db/operation_context.h
@@ -358,6 +358,22 @@ public:
bool isIgnoringInterrupts() const;
+ /**
+ * Returns whether this operation is part of a multi-document transaction. Specifically, it
+ * indicates whether the user asked for a multi-document transaction.
+ */
+ bool inMultiDocumentTransaction() const {
+ return _inMultiDocumentTransaction;
+ }
+
+ /**
+ * Sets that this operation is part of a multi-document transaction. Once this is set, it cannot
+ * be unset.
+ */
+ void setInMultiDocumentTransaction() {
+ _inMultiDocumentTransaction = true;
+ }
+
private:
IgnoreInterruptsState pushIgnoreInterrupts() override {
IgnoreInterruptsState iis{_ignoreInterrupts,
@@ -482,6 +498,7 @@ private:
bool _writesAreReplicated = true;
bool _shouldParticipateInFlowControl = true;
+ bool _inMultiDocumentTransaction = false;
};
namespace repl {
diff --git a/src/mongo/db/ops/write_ops_exec.cpp b/src/mongo/db/ops/write_ops_exec.cpp
index f5b9791cf00..d648e60239f 100644
--- a/src/mongo/db/ops/write_ops_exec.cpp
+++ b/src/mongo/db/ops/write_ops_exec.cpp
@@ -202,8 +202,7 @@ void assertCanWrite_inlock(OperationContext* opCtx, const NamespaceString& ns, b
}
void makeCollection(OperationContext* opCtx, const NamespaceString& ns) {
- auto txnParticipant = TransactionParticipant::get(opCtx);
- auto inTransaction = txnParticipant && txnParticipant.inMultiDocumentTransaction();
+ auto inTransaction = opCtx->inMultiDocumentTransaction();
uassert(ErrorCodes::OperationNotSupportedInTransaction,
str::stream() << "Cannot create namespace " << ns.ns()
<< " in multi-document transaction.",
@@ -303,8 +302,7 @@ void insertDocuments(OperationContext* opCtx,
auto batchSize = std::distance(begin, end);
if (supportsDocLocking()) {
auto replCoord = repl::ReplicationCoordinator::get(opCtx);
- auto txnParticipant = TransactionParticipant::get(opCtx);
- auto inTransaction = txnParticipant && txnParticipant.inMultiDocumentTransaction();
+ auto inTransaction = opCtx->inMultiDocumentTransaction();
if (!inTransaction && !replCoord->isOplogDisabledFor(opCtx, collection->ns())) {
// Populate 'slots' with new optimes for each insert.
@@ -334,8 +332,7 @@ void insertDocuments(OperationContext* opCtx,
* collection lock, which we cannot hold in transactions.
*/
Status checkIfTransactionOnCappedColl(OperationContext* opCtx, Collection* collection) {
- auto txnParticipant = TransactionParticipant::get(opCtx);
- if (txnParticipant && txnParticipant.inMultiDocumentTransaction() && collection->isCapped()) {
+ if (opCtx->inMultiDocumentTransaction() && collection->isCapped()) {
return {ErrorCodes::OperationNotSupportedInTransaction,
str::stream() << "Collection '" << collection->ns()
<< "' is a capped collection. Writes in transactions are not allowed "
@@ -543,7 +540,7 @@ WriteResult performInserts(OperationContext* opCtx,
} else {
const auto stmtId = getStmtIdForWriteOp(opCtx, wholeOp, stmtIdIndex++);
if (opCtx->getTxnNumber()) {
- if (!txnParticipant.inMultiDocumentTransaction() &&
+ if (!opCtx->inMultiDocumentTransaction() &&
txnParticipant.checkStatementExecutedNoOplogEntryFetch(stmtId)) {
containsRetry = true;
RetryableWritesStats::get(opCtx)->incrementRetriedStatementsCount();
@@ -696,11 +693,9 @@ static SingleWriteResult performSingleUpdateOpWithDupKeyRetry(OperationContext*
curOp.ensureStarted();
}
- auto txnParticipant = TransactionParticipant::get(opCtx);
uassert(ErrorCodes::InvalidOptions,
"Cannot use (or request) retryable writes with multi=true",
- (txnParticipant && txnParticipant.inMultiDocumentTransaction()) ||
- !opCtx->getTxnNumber() || !op.getMulti());
+ opCtx->inMultiDocumentTransaction() || !opCtx->getTxnNumber() || !op.getMulti());
UpdateRequest request(ns);
request.setQuery(op.getQ());
@@ -714,11 +709,8 @@ static SingleWriteResult performSingleUpdateOpWithDupKeyRetry(OperationContext*
request.setUpsert(op.getUpsert());
request.setHint(op.getHint());
- auto readConcernArgs = repl::ReadConcernArgs::get(opCtx);
- request.setYieldPolicy(readConcernArgs.getLevel() ==
- repl::ReadConcernLevel::kSnapshotReadConcern
- ? PlanExecutor::INTERRUPT_ONLY
- : PlanExecutor::YIELD_AUTO);
+ request.setYieldPolicy(opCtx->inMultiDocumentTransaction() ? PlanExecutor::INTERRUPT_ONLY
+ : PlanExecutor::YIELD_AUTO);
size_t numAttempts = 0;
while (true) {
@@ -779,7 +771,7 @@ WriteResult performUpdates(OperationContext* opCtx, const write_ops::Update& who
for (auto&& singleOp : wholeOp.getUpdates()) {
const auto stmtId = getStmtIdForWriteOp(opCtx, wholeOp, stmtIdIndex++);
if (opCtx->getTxnNumber()) {
- if (!txnParticipant.inMultiDocumentTransaction()) {
+ if (!opCtx->inMultiDocumentTransaction()) {
if (auto entry = txnParticipant.checkStatementExecuted(opCtx, stmtId)) {
containsRetry = true;
RetryableWritesStats::get(opCtx)->incrementRetriedStatementsCount();
@@ -819,11 +811,9 @@ static SingleWriteResult performSingleDeleteOp(OperationContext* opCtx,
const NamespaceString& ns,
StmtId stmtId,
const write_ops::DeleteOpEntry& op) {
- auto txnParticipant = TransactionParticipant::get(opCtx);
uassert(ErrorCodes::InvalidOptions,
"Cannot use (or request) retryable writes with limit=0",
- (txnParticipant && txnParticipant.inMultiDocumentTransaction()) ||
- !opCtx->getTxnNumber() || !op.getMulti());
+ opCtx->inMultiDocumentTransaction() || !opCtx->getTxnNumber() || !op.getMulti());
globalOpCounters.gotDelete();
ServerWriteConcernMetrics::get(opCtx)->recordWriteConcernForDelete(opCtx->getWriteConcern());
@@ -841,11 +831,8 @@ static SingleWriteResult performSingleDeleteOp(OperationContext* opCtx,
request.setQuery(op.getQ());
request.setCollation(write_ops::collationOf(op));
request.setMulti(op.getMulti());
- auto readConcernArgs = repl::ReadConcernArgs::get(opCtx);
- request.setYieldPolicy(readConcernArgs.getLevel() ==
- repl::ReadConcernLevel::kSnapshotReadConcern
- ? PlanExecutor::INTERRUPT_ONLY
- : PlanExecutor::YIELD_AUTO);
+ request.setYieldPolicy(opCtx->inMultiDocumentTransaction() ? PlanExecutor::INTERRUPT_ONLY
+ : PlanExecutor::YIELD_AUTO);
request.setStmtId(stmtId);
ParsedDelete parsedDelete(opCtx, &request);
@@ -930,7 +917,7 @@ WriteResult performDeletes(OperationContext* opCtx, const write_ops::Delete& who
for (auto&& singleOp : wholeOp.getDeletes()) {
const auto stmtId = getStmtIdForWriteOp(opCtx, wholeOp, stmtIdIndex++);
if (opCtx->getTxnNumber()) {
- if (!txnParticipant.inMultiDocumentTransaction() &&
+ if (!opCtx->inMultiDocumentTransaction() &&
txnParticipant.checkStatementExecutedNoOplogEntryFetch(stmtId)) {
containsRetry = true;
RetryableWritesStats::get(opCtx)->incrementRetriedStatementsCount();
diff --git a/src/mongo/db/pipeline/process_interface_shardsvr.cpp b/src/mongo/db/pipeline/process_interface_shardsvr.cpp
index b9b69d4e9d9..896de887cb7 100644
--- a/src/mongo/db/pipeline/process_interface_shardsvr.cpp
+++ b/src/mongo/db/pipeline/process_interface_shardsvr.cpp
@@ -49,7 +49,6 @@
#include "mongo/db/query/query_knobs_gen.h"
#include "mongo/db/s/collection_sharding_state.h"
#include "mongo/db/s/sharding_state.h"
-#include "mongo/db/transaction_participant.h"
#include "mongo/s/catalog_cache.h"
#include "mongo/s/cluster_commands_helpers.h"
#include "mongo/s/grid.h"
@@ -167,8 +166,7 @@ unique_ptr<Pipeline, PipelineDeleter> MongoInterfaceShardServer::attachCursorSou
// a transaction, the foreign collection is unsharded. Otherwise, we may access the catalog
// cache, and attempt to do a network request while holding locks.
// TODO: SERVER-39162 allow $lookup in sharded transactions.
- auto txnParticipant = TransactionParticipant::get(expCtx->opCtx);
- const bool inTxn = txnParticipant && txnParticipant.inMultiDocumentTransaction();
+ const bool inTxn = expCtx->opCtx->inMultiDocumentTransaction();
const bool isSharded = [&]() {
if (inTxn || !ShardingState::get(expCtx->opCtx)->enabled()) {
diff --git a/src/mongo/db/query/get_executor.cpp b/src/mongo/db/query/get_executor.cpp
index 804baeb123d..9c33a86a6bd 100644
--- a/src/mongo/db/query/get_executor.cpp
+++ b/src/mongo/db/query/get_executor.cpp
@@ -612,10 +612,7 @@ StatusWith<unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getExecutorFind(
unique_ptr<CanonicalQuery> canonicalQuery,
bool permitYield,
size_t plannerOptions) {
- const auto& readConcernArgs = repl::ReadConcernArgs::get(opCtx);
- auto yieldPolicy =
- (permitYield &&
- (readConcernArgs.getLevel() != repl::ReadConcernLevel::kSnapshotReadConcern))
+ auto yieldPolicy = (permitYield && !opCtx->inMultiDocumentTransaction())
? PlanExecutor::YIELD_AUTO
: PlanExecutor::INTERRUPT_ONLY;
return _getExecutorFind(
@@ -1099,11 +1096,8 @@ StatusWith<unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getExecutorCount(
}
unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
- const auto readConcernArgs = repl::ReadConcernArgs::get(opCtx);
- const auto yieldPolicy =
- readConcernArgs.getLevel() == repl::ReadConcernLevel::kSnapshotReadConcern
- ? PlanExecutor::INTERRUPT_ONLY
- : PlanExecutor::YIELD_AUTO;
+ const auto yieldPolicy = opCtx->inMultiDocumentTransaction() ? PlanExecutor::INTERRUPT_ONLY
+ : PlanExecutor::YIELD_AUTO;
const auto skip = request.getSkip().value_or(0);
const auto limit = request.getLimit().value_or(0);
@@ -1556,11 +1550,8 @@ StatusWith<unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getExecutorDistinct(
Collection* collection,
size_t plannerOptions,
ParsedDistinct* parsedDistinct) {
- const auto readConcernArgs = repl::ReadConcernArgs::get(opCtx);
- const auto yieldPolicy =
- readConcernArgs.getLevel() == repl::ReadConcernLevel::kSnapshotReadConcern
- ? PlanExecutor::INTERRUPT_ONLY
- : PlanExecutor::YIELD_AUTO;
+ const auto yieldPolicy = opCtx->inMultiDocumentTransaction() ? PlanExecutor::INTERRUPT_ONLY
+ : PlanExecutor::YIELD_AUTO;
if (!collection) {
// Treat collections that do not exist as empty collections.
diff --git a/src/mongo/db/query/get_executor.h b/src/mongo/db/query/get_executor.h
index 78fec8c6a45..51fd3b008af 100644
--- a/src/mongo/db/query/get_executor.h
+++ b/src/mongo/db/query/get_executor.h
@@ -115,8 +115,8 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getExecutor(
/**
* Get a plan executor for a .find() operation. The executor will have a 'YIELD_AUTO' yield policy
- * unless a false value for 'permitYield' or a snapshot read concern (according to the
- * OperationContext) forces it to have a 'NO_INTERRUPT' yield policy.
+ * unless a false value for 'permitYield' or being part of a multi-document transaction forces it to
+ * have a 'NO_INTERRUPT' yield policy.
*
* If the query is valid and an executor could be created, returns a StatusWith with the
* PlanExecutor.
diff --git a/src/mongo/db/read_concern_mongod.cpp b/src/mongo/db/read_concern_mongod.cpp
index ea270fef283..b5ce3b2fdb9 100644
--- a/src/mongo/db/read_concern_mongod.cpp
+++ b/src/mongo/db/read_concern_mongod.cpp
@@ -237,10 +237,9 @@ MONGO_REGISTER_SHIM(waitForReadConcern)
->Status {
// If we are in a direct client within a transaction, then we may be holding locks, so it is
// illegal to wait for read concern. This is fine, since the outer operation should have handled
- // waiting for read concern. We don't want to ignore prepare conflicts because snapshot reads
- // should block on prepared transactions.
- if (opCtx->getClient()->isInDirectClient() &&
- readConcernArgs.getLevel() == repl::ReadConcernLevel::kSnapshotReadConcern) {
+ // waiting for read concern. We don't want to ignore prepare conflicts because reads in
+ // transactions should block on prepared transactions.
+ if (opCtx->getClient()->isInDirectClient() && opCtx->inMultiDocumentTransaction()) {
return Status::OK();
}
diff --git a/src/mongo/db/repl/oplog.cpp b/src/mongo/db/repl/oplog.cpp
index cc063d8f010..0d93b3387cd 100644
--- a/src/mongo/db/repl/oplog.cpp
+++ b/src/mongo/db/repl/oplog.cpp
@@ -1349,8 +1349,7 @@ Status applyOperation_inlock(OperationContext* opCtx,
// [2] This upsert behavior exists to support idempotency guarantees outside
// steady-state replication and existing users of applyOps.
- const auto txnParticipant = TransactionParticipant::get(opCtx);
- const bool inTxn = txnParticipant && txnParticipant.inMultiDocumentTransaction();
+ const bool inTxn = opCtx->inMultiDocumentTransaction();
bool needToDoUpsert = haveWrappingWriteUnitOfWork && !inTxn;
Timestamp timestamp;
diff --git a/src/mongo/db/repl/replication_coordinator_impl.cpp b/src/mongo/db/repl/replication_coordinator_impl.cpp
index b23082ecb55..9d6dea7eaa0 100644
--- a/src/mongo/db/repl/replication_coordinator_impl.cpp
+++ b/src/mongo/db/repl/replication_coordinator_impl.cpp
@@ -78,7 +78,6 @@
#include "mongo/db/repl/update_position_args.h"
#include "mongo/db/repl/vote_requester.h"
#include "mongo/db/server_options.h"
-#include "mongo/db/transaction_participant.h"
#include "mongo/db/write_concern.h"
#include "mongo/db/write_concern_options.h"
#include "mongo/executor/connection_pool_stats.h"
@@ -1515,8 +1514,7 @@ Status ReplicationCoordinatorImpl::_waitUntilClusterTimeForRead(OperationContext
Status ReplicationCoordinatorImpl::_waitUntilOpTimeForReadDeprecated(
OperationContext* opCtx, const ReadConcernArgs& readConcern) {
const bool isMajorityCommittedRead =
- readConcern.getLevel() == ReadConcernLevel::kMajorityReadConcern ||
- readConcern.getLevel() == ReadConcernLevel::kSnapshotReadConcern;
+ readConcern.getLevel() == ReadConcernLevel::kMajorityReadConcern;
const auto targetOpTime = readConcern.getArgsOpTime().value_or(OpTime());
return _waitUntilOpTime(opCtx, isMajorityCommittedRead, targetOpTime);
@@ -2273,8 +2271,7 @@ Status ReplicationCoordinatorImpl::checkCanServeReadsFor_UNSAFE(OperationContext
return Status::OK();
}
- auto txnParticipant = TransactionParticipant::get(opCtx);
- if (txnParticipant && txnParticipant.inMultiDocumentTransaction()) {
+ if (opCtx->inMultiDocumentTransaction()) {
if (!_readWriteAbility->canAcceptNonLocalWrites_UNSAFE()) {
return Status(ErrorCodes::NotMaster,
"Multi-document transactions are only allowed on replica set primaries.");
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 7329b8d46a3..cbf6e0e0256 100644
--- a/src/mongo/db/s/txn_two_phase_commit_cmds.cpp
+++ b/src/mongo/db/s/txn_two_phase_commit_cmds.cpp
@@ -105,7 +105,7 @@ public:
uassert(ErrorCodes::NoSuchTransaction,
"Transaction isn't in progress",
- txnParticipant.inMultiDocumentTransaction());
+ txnParticipant.transactionIsOpen());
if (txnParticipant.transactionIsPrepared()) {
auto& replClient = repl::ReplClientInfo::forClient(opCtx->getClient());
@@ -308,7 +308,7 @@ public:
false /* autocommit */,
boost::none /* startTransaction */);
- invariant(!txnParticipant.inMultiDocumentTransaction(),
+ invariant(!txnParticipant.transactionIsOpen(),
"The participant should not be in progress after we waited for the "
"participant to complete");
uassert(ErrorCodes::NoSuchTransaction,
diff --git a/src/mongo/db/service_entry_point_common.cpp b/src/mongo/db/service_entry_point_common.cpp
index 82ae8328337..a671f97e4cd 100644
--- a/src/mongo/db/service_entry_point_common.cpp
+++ b/src/mongo/db/service_entry_point_common.cpp
@@ -400,7 +400,7 @@ void invokeWithSessionCheckedOut(OperationContext* opCtx,
if (sessionOptions.getCoordinator() == boost::optional<bool>(true)) {
createTransactionCoordinator(opCtx, *sessionOptions.getTxnNumber());
}
- } else if (txnParticipant.inMultiDocumentTransaction()) {
+ } else if (txnParticipant.transactionIsOpen()) {
const auto& readConcernArgs = repl::ReadConcernArgs::get(opCtx);
uassert(ErrorCodes::InvalidOptions,
"Only the first command in a transaction may specify a readConcern",
@@ -783,9 +783,10 @@ void execCommandDatabase(OperationContext* opCtx,
}
auto& readConcernArgs = repl::ReadConcernArgs::get(opCtx);
- // If the parent operation runs in snapshot isolation, we don't override the read concern.
- auto skipReadConcern = opCtx->getClient()->isInDirectClient() &&
- readConcernArgs.getLevel() == repl::ReadConcernLevel::kSnapshotReadConcern;
+
+ // If the parent operation runs in a transaction, we don't override the read concern.
+ auto skipReadConcern =
+ opCtx->getClient()->isInDirectClient() && opCtx->inMultiDocumentTransaction();
if (!skipReadConcern) {
// If "startTransaction" is present, it must be true due to the parsing above.
const bool upconvertToSnapshot(sessionOptions.getStartTransaction());
@@ -1262,10 +1263,9 @@ DbResponse ServiceEntryPointCommon::handleRequest(OperationContext* opCtx,
Client& c = *opCtx->getClient();
if (c.isInDirectClient()) {
- if (!opCtx->getLogicalSessionId() || !opCtx->getTxnNumber() ||
- repl::ReadConcernArgs::get(opCtx).getLevel() !=
- repl::ReadConcernLevel::kSnapshotReadConcern) {
- invariant(!opCtx->lockState()->inAWriteUnitOfWork());
+ if (!opCtx->getLogicalSessionId() || !opCtx->getTxnNumber()) {
+ invariant(!opCtx->inMultiDocumentTransaction() &&
+ !opCtx->lockState()->inAWriteUnitOfWork());
}
} else {
LastError::get(c).startRequest();
diff --git a/src/mongo/db/session_catalog_mongod.cpp b/src/mongo/db/session_catalog_mongod.cpp
index 2f6145f0287..24e6bf62bee 100644
--- a/src/mongo/db/session_catalog_mongod.cpp
+++ b/src/mongo/db/session_catalog_mongod.cpp
@@ -229,7 +229,7 @@ void MongoDSessionCatalog::onStepUp(OperationContext* opCtx) {
KillAllSessionsByPatternSet{makeKillAllSessionsByPattern(opCtx)});
catalog->scanSessions(matcher, [&](const ObservableSession& session) {
const auto txnParticipant = TransactionParticipant::get(session);
- if (!txnParticipant.inMultiDocumentTransaction()) {
+ if (!txnParticipant.transactionIsOpen()) {
sessionKillTokens.emplace_back(session.kill());
}
@@ -351,7 +351,7 @@ int MongoDSessionCatalog::reapSessionsOlderThan(OperationContext* opCtx,
for (const auto& lsid : expiredSessionIds) {
catalog->scanSession(lsid, [](ObservableSession& session) {
const auto participant = TransactionParticipant::get(session);
- if (!participant.inMultiDocumentTransaction()) {
+ if (!participant.transactionIsOpen()) {
session.markForReap();
}
});
@@ -437,8 +437,7 @@ MongoDOperationContextSessionWithoutRefresh::~MongoDOperationContextSessionWitho
const auto txnParticipant = TransactionParticipant::get(_opCtx);
// A session on secondaries should never be checked back in with a TransactionParticipant that
// isn't prepared, aborted, or committed.
- invariant(!txnParticipant.inMultiDocumentTransaction() ||
- txnParticipant.transactionIsPrepared());
+ invariant(!txnParticipant.transactionIsInProgress());
}
} // namespace mongo
diff --git a/src/mongo/db/transaction_participant.cpp b/src/mongo/db/transaction_participant.cpp
index a7993bc3e96..56f063aa784 100644
--- a/src/mongo/db/transaction_participant.cpp
+++ b/src/mongo/db/transaction_participant.cpp
@@ -770,6 +770,8 @@ void TransactionParticipant::TxnResources::release(OperationContext* opCtx) {
TransactionParticipant::SideTransactionBlock::SideTransactionBlock(OperationContext* opCtx)
: _opCtx(opCtx) {
+ // Do nothing if we are already in a SideTransactionBlock. We can tell we are already in a
+ // SideTransactionBlock because there is no top level write unit of work.
if (!_opCtx->getWriteUnitOfWork()) {
return;
}
@@ -835,7 +837,7 @@ void TransactionParticipant::Participant::stashTransactionResources(OperationCon
}
invariant(opCtx->getTxnNumber());
- if (o().txnState.inMultiDocumentTransaction()) {
+ if (o().txnState.isOpen()) {
_stashActiveTransaction(opCtx);
}
}
diff --git a/src/mongo/db/transaction_participant.h b/src/mongo/db/transaction_participant.h
index dc62783d028..caa0027a6b9 100644
--- a/src/mongo/db/transaction_participant.h
+++ b/src/mongo/db/transaction_participant.h
@@ -114,7 +114,7 @@ class TransactionParticipant {
StateFlag newState,
TransitionValidation shouldValidate = TransitionValidation::kValidateTransition);
- bool inMultiDocumentTransaction() const {
+ bool isOpen() const {
return _state == kInProgress || _state == kPrepared;
}
@@ -288,13 +288,13 @@ public:
bool expiredAsOf(Date_t when) const;
/**
- * Returns whether we are in a multi-document transaction, which means we have an active
- * transaction which has autocommit:false and has not been committed or aborted. It is
- * possible that the current transaction is stashed onto the stack via a
+ * Returns whether we are in an open multi-document transaction, which means we have an
+ * active transaction which has autocommit:false and has not been committed or aborted. It
+ * is possible that the current transaction is stashed onto the stack via a
* `SideTransactionBlock`.
*/
- bool inMultiDocumentTransaction() const {
- return o().txnState.inMultiDocumentTransaction();
+ bool transactionIsOpen() const {
+ return o().txnState.isOpen();
};
bool transactionIsCommitted() const {
@@ -309,13 +309,17 @@ public:
return o().txnState.isPrepared();
}
+ bool transactionIsInProgress() const {
+ return o().txnState.isInProgress();
+ }
+
/**
* Returns true if we are in an active multi-document transaction or if the transaction has
* been aborted. This is used to cover the case where a transaction has been aborted, but
* the OperationContext state has not been cleared yet.
*/
bool inActiveOrKilledMultiDocumentTransaction() const {
- return o().txnState.inMultiDocumentTransaction() || o().txnState.isAborted();
+ return o().txnState.isOpen() || o().txnState.isAborted();
}
/**
@@ -558,16 +562,16 @@ public:
* multi-key path info to the set of path infos to be updated at commit time.
*/
void addUncommittedMultikeyPathInfo(MultikeyPathInfo info) {
- invariant(inMultiDocumentTransaction());
+ invariant(transactionIsOpen());
p().multikeyPathInfo.emplace_back(std::move(info));
}
/**
- * May only be called while a mutil-document transaction is not committed and returns the
+ * May only be called while a multi-document transaction is not committed and returns the
* path infos which have been added so far.
*/
const std::vector<MultikeyPathInfo>& getUncommittedMultikeyPathInfos() const {
- invariant(inMultiDocumentTransaction());
+ invariant(transactionIsOpen());
return p().multikeyPathInfo;
}
diff --git a/src/mongo/db/transaction_participant_test.cpp b/src/mongo/db/transaction_participant_test.cpp
index 58ecad234af..0947c8580ae 100644
--- a/src/mongo/db/transaction_participant_test.cpp
+++ b/src/mongo/db/transaction_participant_test.cpp
@@ -414,7 +414,7 @@ TEST_F(TxnParticipantTest, CannotSpecifyStartTransactionOnInProgressTxn) {
// Must specify startTransaction=true and autocommit=false to start a transaction.
auto sessionCheckout = checkOutSession();
auto txnParticipant = TransactionParticipant::get(opCtx());
- ASSERT_TRUE(txnParticipant.inMultiDocumentTransaction());
+ ASSERT_TRUE(txnParticipant.transactionIsOpen());
// Cannot try to start a transaction that already started.
ASSERT_THROWS_CODE(
@@ -1115,7 +1115,7 @@ TEST_F(TxnParticipantTest, CannotContinueTransactionIfNotPrimary) {
// Will start the transaction.
auto sessionCheckout = checkOutSession();
auto txnParticipant = TransactionParticipant::get(opCtx());
- ASSERT_TRUE(txnParticipant.inMultiDocumentTransaction());
+ ASSERT_TRUE(txnParticipant.transactionIsOpen());
ASSERT_OK(repl::ReplicationCoordinator::get(opCtx())->setFollowerMode(
repl::MemberState::RS_SECONDARY));
@@ -1318,7 +1318,7 @@ protected:
auto sessionCheckout = checkOutSession();
auto txnParticipant = TransactionParticipant::get(opCtx());
- ASSERT(txnParticipant.inMultiDocumentTransaction());
+ ASSERT(txnParticipant.transactionIsOpen());
ASSERT_THROWS_CODE(txnParticipant.beginOrContinue(
opCtx(), *opCtx()->getTxnNumber(), autocommit, startTransaction),
@@ -1332,14 +1332,14 @@ protected:
auto sessionCheckout = checkOutSession();
auto txnParticipant = TransactionParticipant::get(opCtx());
- ASSERT(txnParticipant.inMultiDocumentTransaction());
+ ASSERT(txnParticipant.transactionIsOpen());
txnParticipant.abortActiveTransaction(opCtx());
ASSERT(txnParticipant.transactionIsAborted());
txnParticipant.beginOrContinue(
opCtx(), *opCtx()->getTxnNumber(), autocommit, startTransaction);
- ASSERT(txnParticipant.inMultiDocumentTransaction());
+ ASSERT(txnParticipant.transactionIsOpen());
}
void cannotSpecifyStartTransactionOnCommittedTxn() {
@@ -1348,7 +1348,7 @@ protected:
auto sessionCheckout = checkOutSession();
auto txnParticipant = TransactionParticipant::get(opCtx());
- ASSERT(txnParticipant.inMultiDocumentTransaction());
+ ASSERT(txnParticipant.transactionIsOpen());
txnParticipant.unstashTransactionResources(opCtx(), "commitTransaction");
txnParticipant.commitUnpreparedTransaction(opCtx());
@@ -1365,7 +1365,7 @@ protected:
auto sessionCheckout = checkOutSession();
auto txnParticipant = TransactionParticipant::get(opCtx());
- ASSERT(txnParticipant.inMultiDocumentTransaction());
+ ASSERT(txnParticipant.transactionIsOpen());
txnParticipant.unstashTransactionResources(opCtx(), "insert");
auto operation = repl::OplogEntry::makeInsertOperation(kNss, _uuid, BSON("TestValue" << 0));
@@ -1384,7 +1384,7 @@ protected:
auto sessionCheckout = checkOutSession();
auto txnParticipant = TransactionParticipant::get(opCtx());
- ASSERT(txnParticipant.inMultiDocumentTransaction());
+ ASSERT(txnParticipant.transactionIsOpen());
txnParticipant.unstashTransactionResources(opCtx(), "prepareTransaction");
txnParticipant.prepareTransaction(opCtx(), {});
@@ -1405,7 +1405,7 @@ protected:
auto txnParticipant = TransactionParticipant::get(opCtx());
txnParticipant.beginOrContinue(opCtx(), *opCtx()->getTxnNumber(), boost::none, boost::none);
- ASSERT_FALSE(txnParticipant.inMultiDocumentTransaction());
+ ASSERT_FALSE(txnParticipant.transactionIsOpen());
auto autocommit = false;
auto startTransaction = true;
@@ -1413,7 +1413,7 @@ protected:
txnParticipant.beginOrContinue(
opCtx(), *opCtx()->getTxnNumber(), autocommit, startTransaction);
- ASSERT(txnParticipant.inMultiDocumentTransaction());
+ ASSERT(txnParticipant.transactionIsOpen());
}
};
@@ -3724,7 +3724,7 @@ TEST_F(TxnParticipantTest, AbortTransactionOnSessionCheckoutWithoutRefresh) {
MongoDOperationContextSessionWithoutRefresh sessionCheckout(opCtx());
auto txnParticipant = TransactionParticipant::get(opCtx());
- ASSERT(txnParticipant.inMultiDocumentTransaction());
+ ASSERT(txnParticipant.transactionIsOpen());
ASSERT_EQ(txnParticipant.getActiveTxnNumber(), txnNumber);
txnParticipant.unstashTransactionResources(opCtx(), "abortTransaction");
diff --git a/src/mongo/dbtests/storage_timestamp_tests.cpp b/src/mongo/dbtests/storage_timestamp_tests.cpp
index 6e79c1b8ae3..bf5deafc338 100644
--- a/src/mongo/dbtests/storage_timestamp_tests.cpp
+++ b/src/mongo/dbtests/storage_timestamp_tests.cpp
@@ -1512,6 +1512,7 @@ public:
const auto sessionId = makeLogicalSessionIdForTest();
_opCtx->setLogicalSessionId(sessionId);
_opCtx->setTxnNumber(1);
+ _opCtx->setInMultiDocumentTransaction();
// Check out the session.
MongoDOperationContextSession ocs(_opCtx);
@@ -2680,6 +2681,7 @@ public:
const auto sessionId = makeLogicalSessionIdForTest();
_opCtx->setLogicalSessionId(sessionId);
_opCtx->setTxnNumber(26);
+ _opCtx->setInMultiDocumentTransaction();
ocs.emplace(_opCtx);