summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorA. Jesse Jiryu Davis <jesse@mongodb.com>2020-04-21 18:43:41 -0400
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-04-25 02:22:46 +0000
commitbe0eb178a1c599497a307a5b114d112343fab9c1 (patch)
tree0892ecd512337e15f42a28647738ba85f20e1ccb
parent7bffc86bd02fb992f14bcce7bf686ca67adbf6a7 (diff)
downloadmongo-be0eb178a1c599497a307a5b114d112343fab9c1.tar.gz
SERVER-47613 Fix invariant when a removed member votes
(cherry picked from commit cc814e4c87c1ae20ef7c0840344496043dbdf18d)
-rw-r--r--src/mongo/db/repl/replication_coordinator_impl.cpp5
-rw-r--r--src/mongo/db/repl/replication_coordinator_impl_test.cpp42
2 files changed, 46 insertions, 1 deletions
diff --git a/src/mongo/db/repl/replication_coordinator_impl.cpp b/src/mongo/db/repl/replication_coordinator_impl.cpp
index ebf06782013..6f6394c43eb 100644
--- a/src/mongo/db/repl/replication_coordinator_impl.cpp
+++ b/src/mongo/db/repl/replication_coordinator_impl.cpp
@@ -3506,6 +3506,11 @@ Status ReplicationCoordinatorImpl::processReplSetRequestVotes(
return Status(ErrorCodes::ShutdownInProgress, "In the process of shutting down");
}
+ if (_selfIndex == -1) {
+ return Status(ErrorCodes::InvalidReplicaSetConfig,
+ "Invalid replica set config, or this node is not a member");
+ }
+
_topCoord->processReplSetRequestVotes(args, response);
}
diff --git a/src/mongo/db/repl/replication_coordinator_impl_test.cpp b/src/mongo/db/repl/replication_coordinator_impl_test.cpp
index e4f6bca7fed..987f38392a2 100644
--- a/src/mongo/db/repl/replication_coordinator_impl_test.cpp
+++ b/src/mongo/db/repl/replication_coordinator_impl_test.cpp
@@ -6138,7 +6138,7 @@ TEST_F(ReplCoordTest, NodeFailsVoteRequestIfItFailsToStoreLastVote) {
ASSERT_EQUALS(lastVote.getCandidateIndex(), 0);
}
-TEST_F(ReplCoordTest, NodeNodesNotGrantVoteIfInTerminalShutdown) {
+TEST_F(ReplCoordTest, NodeDoesNotGrantVoteIfInTerminalShutdown) {
// Set up a 2-node replica set config.
assertStartSuccess(BSON("_id"
<< "mySet"
@@ -6190,6 +6190,46 @@ TEST_F(ReplCoordTest, NodeNodesNotGrantVoteIfInTerminalShutdown) {
ASSERT_EQUALS(ErrorCodes::ShutdownInProgress, r.code());
}
+TEST_F(ReplCoordTest, RemovedNodeDoesNotGrantVote) {
+ // A 1-node set. This node is not a member.
+ assertStartSuccess(BSON("_id"
+ << "mySet"
+ << "version"
+ << 1
+ << "members"
+ << BSON_ARRAY(BSON("host"
+ << "node1:12345"
+ << "_id"
+ << 0))),
+ HostAndPort("node2", 12345));
+
+ ASSERT_OK(getReplCoord()->setFollowerMode(MemberState::RS_REMOVED));
+ ReplSetRequestVotesArgs args;
+ ASSERT_OK(args.initialize(BSON("replSetRequestVotes" << 1 << "setName"
+ << "mySet"
+ << "term"
+ << 2
+ << "candidateIndex"
+ << 0LL
+ << "configVersion"
+ << 1LL
+ << "dryRun"
+ << false
+ << "lastCommittedOp"
+ << OpTime().toBSON())));
+
+ ReplSetRequestVotesResponse response;
+ auto opCtx = makeOperationContext();
+ auto r = getReplCoord()->processReplSetRequestVotes(opCtx.get(), args, &response);
+ ASSERT_NOT_OK(r);
+ ASSERT_EQUALS("Invalid replica set config, or this node is not a member", r.reason());
+ ASSERT_EQUALS(ErrorCodes::InvalidReplicaSetConfig, r.code());
+
+ // Vote was not recorded.
+ ServiceContext* svcCtx = getServiceContext();
+ ASSERT(ReplicationMetrics::get(svcCtx).getElectionParticipantMetricsBSON().isEmpty());
+}
+
// TODO(schwerin): Unit test election id updating
} // namespace
} // namespace repl