summaryrefslogtreecommitdiff
path: root/src/mongo/s/transaction_router.cpp
diff options
context:
space:
mode:
authorEsha Maharishi <esha.maharishi@mongodb.com>2018-12-10 16:14:59 -0500
committerEsha Maharishi <esha.maharishi@mongodb.com>2018-12-11 18:42:05 -0500
commitf948fbcf86d104d70889d7d6a1caa83b4d78a6a8 (patch)
tree9765fb007e9bd29e12cdd0e62cea6264625e696b /src/mongo/s/transaction_router.cpp
parent4f5cb3722dce75ceb77cd705c683f2bbf25b9048 (diff)
downloadmongo-f948fbcf86d104d70889d7d6a1caa83b4d78a6a8.tar.gz
SERVER-36853 Coordinator should resume coordinating commit for unfinished transactions on stepup
Diffstat (limited to 'src/mongo/s/transaction_router.cpp')
-rw-r--r--src/mongo/s/transaction_router.cpp37
1 files changed, 37 insertions, 0 deletions
diff --git a/src/mongo/s/transaction_router.cpp b/src/mongo/s/transaction_router.cpp
index 3af5fe824ff..44658b473c3 100644
--- a/src/mongo/s/transaction_router.cpp
+++ b/src/mongo/s/transaction_router.cpp
@@ -47,11 +47,16 @@
#include "mongo/s/cluster_commands_helpers.h"
#include "mongo/s/grid.h"
#include "mongo/util/assert_util.h"
+#include "mongo/util/fail_point_service.h"
#include "mongo/util/log.h"
namespace mongo {
namespace {
+// TODO (SERVER-37886): Remove this failpoint once failover can be tested on coordinators that
+// have a local participant.
+MONGO_FAIL_POINT_DEFINE(sendCoordinateCommitToConfigServer);
+
const char kCoordinatorField[] = "coordinator";
const char kReadConcernLevelSnapshotName[] = "snapshot";
@@ -566,6 +571,38 @@ Shard::CommandResponse TransactionRouter::_commitMultiShardTransaction(Operation
auto coordinatorShard =
uassertStatusOK(Grid::get(opCtx)->shardRegistry()->getShard(opCtx, *_coordinatorId));
+ if (MONGO_FAIL_POINT(sendCoordinateCommitToConfigServer)) {
+ LOG(0) << "Sending coordinateCommit for transaction " << *opCtx->getTxnNumber()
+ << " on session " << opCtx->getLogicalSessionId()->toBSON()
+ << " to config server rather than actual coordinator because failpoint is active";
+
+ coordinatorShard = Grid::get(opCtx)->shardRegistry()->getConfigShard();
+
+ // Send a fake transaction statement to the config server primary so that the config server
+ // primary sets up state in memory to receive coordinateCommit.
+ auto cmdResponse = coordinatorShard->runCommandWithFixedRetryAttempts(
+ opCtx,
+ ReadPreferenceSetting{ReadPreference::PrimaryOnly},
+ "dummy",
+ coordinatorIter->second.attachTxnFieldsIfNeeded(BSON("distinct"
+ << "dummy"
+ << "key"
+ << "dummy"),
+ true),
+ Shard::RetryPolicy::kIdempotent);
+ uassertStatusOK(Shard::CommandResponse::getEffectiveStatus(cmdResponse));
+
+ // Abort the fake transaction on the config server to release the actual transaction's
+ // resources.
+ cmdResponse = coordinatorShard->runCommandWithFixedRetryAttempts(
+ opCtx,
+ ReadPreferenceSetting{ReadPreference::PrimaryOnly},
+ "admin",
+ coordinatorIter->second.attachTxnFieldsIfNeeded(BSON("abortTransaction" << 1), false),
+ Shard::RetryPolicy::kIdempotent);
+ uassertStatusOK(Shard::CommandResponse::getEffectiveStatus(cmdResponse));
+ }
+
CoordinateCommitTransaction coordinateCommitCmd;
coordinateCommitCmd.setDbName("admin");
coordinateCommitCmd.setParticipants(participantList);