summaryrefslogtreecommitdiff
path: root/src/mongo/db/transaction_api.cpp
diff options
context:
space:
mode:
authorJack Mulrow <jack.mulrow@mongodb.com>2022-02-07 15:46:37 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-02-07 19:21:55 +0000
commitcebfa751cb5db526fcba92dc2c1a69ed507a075b (patch)
tree9d5a8f9cd6ea0e0c4b21adf20737fe6e7cd01551 /src/mongo/db/transaction_api.cpp
parent7a2d86c376488cc756c0325e6edaf3406a86ec5d (diff)
downloadmongo-cebfa751cb5db526fcba92dc2c1a69ed507a075b.tar.gz
SERVER-63364 Use transaction API to handle WCOS errors for findAndModify without retryability
Diffstat (limited to 'src/mongo/db/transaction_api.cpp')
-rw-r--r--src/mongo/db/transaction_api.cpp49
1 files changed, 20 insertions, 29 deletions
diff --git a/src/mongo/db/transaction_api.cpp b/src/mongo/db/transaction_api.cpp
index 0d6a7637541..8c4fe8c114c 100644
--- a/src/mongo/db/transaction_api.cpp
+++ b/src/mongo/db/transaction_api.cpp
@@ -48,6 +48,7 @@
#include "mongo/rpc/factory.h"
#include "mongo/rpc/get_status_from_command_result.h"
#include "mongo/rpc/reply_interface.h"
+#include "mongo/s/is_mongos.h"
#include "mongo/stdx/future.h"
#include "mongo/transport/service_entry_point.h"
@@ -297,7 +298,7 @@ SemiFuture<BSONObj> Transaction::_commitOrAbort(StringData dbName, StringData cm
BSONObjBuilder cmdBuilder;
cmdBuilder.append(cmdName, 1);
- cmdBuilder.append(WriteConcernOptions::kWriteConcernField, _writeConcern.toBSON());
+ cmdBuilder.append(WriteConcernOptions::kWriteConcernField, _writeConcern);
auto cmdObj = cmdBuilder.obj();
return _txnClient->runCommand(dbName, cmdObj).semi();
@@ -363,7 +364,7 @@ void Transaction::prepareRequest(BSONObjBuilder* cmdBuilder) {
if (_state == TransactionState::kInit) {
_state = TransactionState::kStarted;
_sessionInfo.setStartTransaction(boost::none);
- cmdBuilder->append(_readConcern.toBSON().firstElement());
+ cmdBuilder->append(repl::ReadConcernArgs::kReadConcernFieldName, _readConcern);
}
_latestResponseHasTransientTransactionErrorLabel = false;
@@ -379,32 +380,19 @@ void Transaction::processResponse(const BSONObj& reply) {
}
}
-void Transaction::_setSessionInfo(LogicalSessionId lsid,
- TxnNumber txnNumber,
- boost::optional<TxnRetryCounter> txnRetryCounter) {
+void Transaction::_setSessionInfo(LogicalSessionId lsid, TxnNumber txnNumber) {
_sessionInfo.setSessionId(lsid);
_sessionInfo.setTxnNumber(txnNumber);
- _sessionInfo.setTxnRetryCounter(txnRetryCounter ? *txnRetryCounter : 0);
}
void Transaction::primeForTransactionRetry() {
_latestResponseHasTransientTransactionErrorLabel = false;
switch (_execContext) {
case ExecutionContext::kOwnSession:
- // Advance txnNumber.
- _sessionInfo.setTxnNumber(*_sessionInfo.getTxnNumber() + 1);
- _sessionInfo.setStartTransaction(true);
- _state = TransactionState::kInit;
- return;
case ExecutionContext::kClientSession:
- // Advance txnRetryCounter.
- _sessionInfo.setTxnRetryCounter(*_sessionInfo.getTxnRetryCounter() + 1);
- _sessionInfo.setStartTransaction(true);
- _state = TransactionState::kInit;
- return;
case ExecutionContext::kClientRetryableWrite:
- // Advance txnRetryCounter.
- _sessionInfo.setTxnRetryCounter(*_sessionInfo.getTxnRetryCounter() + 1);
+ // Advance txnNumber.
+ _sessionInfo.setTxnNumber(*_sessionInfo.getTxnNumber() + 1);
_sessionInfo.setStartTransaction(true);
_state = TransactionState::kInit;
return;
@@ -431,27 +419,27 @@ void Transaction::_primeTransaction(OperationContext* opCtx) {
auto clientSession = opCtx->getLogicalSessionId();
auto clientTxnNumber = opCtx->getTxnNumber();
auto clientInMultiDocumentTransaction = opCtx->inMultiDocumentTransaction();
- auto clientTxnRetryCounter = opCtx->getTxnRetryCounter();
if (!clientSession) {
// TODO SERVER-61783: Integrate session pool.
- _setSessionInfo(makeLogicalSessionId(opCtx), 0, 0);
+ _setSessionInfo(makeLogicalSessionId(opCtx), 0 /* txnNumber */);
_execContext = ExecutionContext::kOwnSession;
} else if (!clientTxnNumber) {
- _setSessionInfo(makeLogicalSessionIdWithTxnUUID(*clientSession), 0, 0);
+ _setSessionInfo(makeLogicalSessionIdWithTxnUUID(*clientSession), 0 /* txnNumber */);
_execContext = ExecutionContext::kClientSession;
// TODO SERVER-59186: Handle client session case.
MONGO_UNREACHABLE;
} else if (!clientInMultiDocumentTransaction) {
- _setSessionInfo(
- makeLogicalSessionIdWithTxnNumberAndUUID(*clientSession, *clientTxnNumber), 0, 0);
+ _setSessionInfo(makeLogicalSessionIdWithTxnNumberAndUUID(*clientSession, *clientTxnNumber),
+ 0 /* txnNumber */);
_execContext = ExecutionContext::kClientRetryableWrite;
- // TODO SERVER-59186: Handle client retryable write case.
- MONGO_UNREACHABLE;
+ // TODO SERVER-59186: Handle client retryable write case on mongod. This is different from
+ // mongos because only mongod checks out a transaction session for retryable writes.
+ invariant(isMongos(), "This case is not yet supported on a mongod");
} else {
- _setSessionInfo(*clientSession, *clientTxnNumber, clientTxnRetryCounter);
+ _setSessionInfo(*clientSession, *clientTxnNumber);
_execContext = ExecutionContext::kClientTransaction;
// TODO SERVER-59186: Handle client transaction case.
@@ -460,9 +448,12 @@ void Transaction::_primeTransaction(OperationContext* opCtx) {
_sessionInfo.setStartTransaction(true);
_sessionInfo.setAutocommit(false);
- // Extract non-session options.
- _readConcern = repl::ReadConcernArgs::get(opCtx);
- _writeConcern = opCtx->getWriteConcern();
+ // Extract non-session options. Strip provenance so it can be correctly inferred for the
+ // generated commands as if it came from an external client.
+ _readConcern = repl::ReadConcernArgs::get(opCtx).toBSONInner().removeField(
+ ReadWriteConcernProvenanceBase::kSourceFieldName);
+ _writeConcern = opCtx->getWriteConcern().toBSON().removeField(
+ ReadWriteConcernProvenanceBase::kSourceFieldName);
LOGV2_DEBUG(5875901,
0, // TODO SERVER-61781: Raise verbosity.