From e05ffdc10eb680dfbbf043678779aa4aac92bb0c Mon Sep 17 00:00:00 2001 From: Gregory Wlodarek Date: Wed, 30 Jan 2019 17:53:29 -0500 Subject: SERVER-37639 Add checkIfCommitQuorumCanBeSatisfied() and checkIfCommitQuorumIsSatisfied() to the replication interface --- src/mongo/db/repl/topology_coordinator_v1_test.cpp | 149 +++++++++++++++++++++ 1 file changed, 149 insertions(+) (limited to 'src/mongo/db/repl/topology_coordinator_v1_test.cpp') diff --git a/src/mongo/db/repl/topology_coordinator_v1_test.cpp b/src/mongo/db/repl/topology_coordinator_v1_test.cpp index c44f572fe3b..57fcabefdee 100644 --- a/src/mongo/db/repl/topology_coordinator_v1_test.cpp +++ b/src/mongo/db/repl/topology_coordinator_v1_test.cpp @@ -33,6 +33,7 @@ #include #include "mongo/bson/json.h" +#include "mongo/db/catalog/commit_quorum_options.h" #include "mongo/db/repl/heartbeat_response_action.h" #include "mongo/db/repl/repl_set_heartbeat_args_v1.h" #include "mongo/db/repl/repl_set_heartbeat_response.h" @@ -5101,6 +5102,154 @@ TEST_F(TopoCoordTest, ArbitersNotIncludedInW2WriteInPSSAAReplSet) { caughtUpOpTime, 2 /* numNodes */, false /* durablyWritten */)); } +TEST_F(TopoCoordTest, CheckIfCommitQuorumCanBeSatisfied) { + ReplSetConfig configA; + ASSERT_OK(configA.initialize(BSON("_id" + << "rs0" + << "version" + << 1 + << "protocolVersion" + << 1 + << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "node0" + << "tags" + << BSON("dc" + << "NA" + << "rack" + << "rackNA1")) + << BSON("_id" << 1 << "host" + << "node1" + << "tags" + << BSON("dc" + << "NA" + << "rack" + << "rackNA2")) + << BSON("_id" << 2 << "host" + << "node2" + << "tags" + << BSON("dc" + << "NA" + << "rack" + << "rackNA3")) + << BSON("_id" << 3 << "host" + << "node3" + << "tags" + << BSON("dc" + << "EU" + << "rack" + << "rackEU1")) + << BSON("_id" << 4 << "host" + << "node4" + << "tags" + << BSON("dc" + << "EU" + << "rack" + << "rackEU2")) + << BSON("_id" << 5 << "host" + << "node5" + << "arbiterOnly" + << true)) + << "settings" + << BSON("getLastErrorModes" + << BSON("valid" << BSON("dc" << 2 << "rack" << 3) + << "invalidNotEnoughValues" + << BSON("dc" << 3) + << "invalidNotEnoughNodes" + << BSON("rack" << 6)))))); + getTopoCoord().updateConfig(configA, -1, Date_t()); + + std::vector memberConfig; + for (auto it = configA.membersBegin(); it != configA.membersEnd(); it++) { + memberConfig.push_back(*it); + } + + // Consider all the replica set members. + { + CommitQuorumOptions validNumberWC; + validNumberWC.numNodes = 5; + ASSERT_TRUE(getTopoCoord().checkIfCommitQuorumCanBeSatisfied(validNumberWC, memberConfig)); + + CommitQuorumOptions invalidNumberWC; + invalidNumberWC.numNodes = 6; + ASSERT_FALSE( + getTopoCoord().checkIfCommitQuorumCanBeSatisfied(invalidNumberWC, memberConfig)); + + CommitQuorumOptions majorityWC; + majorityWC.mode = "majority"; + ASSERT_TRUE(getTopoCoord().checkIfCommitQuorumCanBeSatisfied(majorityWC, memberConfig)); + + CommitQuorumOptions validModeWC; + validModeWC.mode = "valid"; + ASSERT_TRUE(getTopoCoord().checkIfCommitQuorumCanBeSatisfied(validModeWC, memberConfig)); + + CommitQuorumOptions invalidModeWC; + invalidModeWC.mode = "invalidNotEnoughNodes"; + ASSERT_FALSE(getTopoCoord().checkIfCommitQuorumCanBeSatisfied(invalidModeWC, memberConfig)); + + CommitQuorumOptions fakeModeWC; + fakeModeWC.mode = "fake"; + ASSERT_FALSE(getTopoCoord().checkIfCommitQuorumCanBeSatisfied(fakeModeWC, memberConfig)); + } + + // Use a list of commit ready members that is not a majority. + { + std::vector commitReadyMembersNoMajority; + commitReadyMembersNoMajority.push_back(*configA.findMemberByID(0)); + commitReadyMembersNoMajority.push_back(*configA.findMemberByID(1)); + commitReadyMembersNoMajority.push_back(*configA.findMemberByID(2)); + + CommitQuorumOptions validNumberWC; + validNumberWC.numNodes = 3; + ASSERT_TRUE(getTopoCoord().checkIfCommitQuorumCanBeSatisfied(validNumberWC, + commitReadyMembersNoMajority)); + + CommitQuorumOptions invalidNumberWC; + invalidNumberWC.numNodes = 4; + ASSERT_FALSE(getTopoCoord().checkIfCommitQuorumCanBeSatisfied( + invalidNumberWC, commitReadyMembersNoMajority)); + + CommitQuorumOptions majorityWC; + majorityWC.mode = "majority"; + ASSERT_FALSE(getTopoCoord().checkIfCommitQuorumCanBeSatisfied( + majorityWC, commitReadyMembersNoMajority)); + + CommitQuorumOptions invalidModeWC; + invalidModeWC.mode = "valid"; + ASSERT_FALSE(getTopoCoord().checkIfCommitQuorumCanBeSatisfied( + invalidModeWC, commitReadyMembersNoMajority)); + } + + // Use a list of commit ready members that is a majority. + { + std::vector commitReadyMembersMajority; + commitReadyMembersMajority.push_back(*configA.findMemberByID(0)); + commitReadyMembersMajority.push_back(*configA.findMemberByID(1)); + commitReadyMembersMajority.push_back(*configA.findMemberByID(2)); + commitReadyMembersMajority.push_back(*configA.findMemberByID(3)); + + CommitQuorumOptions validNumberWC; + validNumberWC.numNodes = 4; + ASSERT_TRUE(getTopoCoord().checkIfCommitQuorumCanBeSatisfied(validNumberWC, + commitReadyMembersMajority)); + + CommitQuorumOptions invalidNumberWC; + invalidNumberWC.numNodes = 5; + ASSERT_FALSE(getTopoCoord().checkIfCommitQuorumCanBeSatisfied(invalidNumberWC, + commitReadyMembersMajority)); + + CommitQuorumOptions majorityWC; + majorityWC.mode = "majority"; + ASSERT_TRUE(getTopoCoord().checkIfCommitQuorumCanBeSatisfied(majorityWC, + commitReadyMembersMajority)); + + CommitQuorumOptions invalidModeWC; + invalidModeWC.mode = "valid"; + ASSERT_TRUE(getTopoCoord().checkIfCommitQuorumCanBeSatisfied(invalidModeWC, + commitReadyMembersMajority)); + } +} + TEST_F(HeartbeatResponseTestV1, ScheduleACatchupTakeoverWhenElectableAndReceiveHeartbeatFromPrimaryInCatchup) { updateConfig(BSON("_id" -- cgit v1.2.1