diff options
author | Xuerui Fa <xuerui.fa@mongodb.com> | 2020-02-10 15:15:42 -0500 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-02-18 17:07:55 +0000 |
commit | 99e7754701d5be6fafb567296540df36cb26ab87 (patch) | |
tree | 62a554d041a22c716ca07c9fa09e6aea913178a2 /src | |
parent | 19f7a856c0b1c80c378191d5ae3451cdd09e5c61 (diff) | |
download | mongo-99e7754701d5be6fafb567296540df36cb26ab87.tar.gz |
SERVER-28680: Fix naming of lastCommittedOp field in replSetRequestVotes
Diffstat (limited to 'src')
-rw-r--r-- | src/mongo/db/repl/repl_set_request_votes_args.cpp | 60 | ||||
-rw-r--r-- | src/mongo/db/repl/repl_set_request_votes_args.h | 10 | ||||
-rw-r--r-- | src/mongo/db/repl/replication_coordinator_impl_elect_v1.cpp | 10 | ||||
-rw-r--r-- | src/mongo/db/repl/replication_coordinator_impl_test.cpp | 8 | ||||
-rw-r--r-- | src/mongo/db/repl/topology_coordinator.cpp | 4 | ||||
-rw-r--r-- | src/mongo/db/repl/topology_coordinator_v1_test.cpp | 84 | ||||
-rw-r--r-- | src/mongo/db/repl/vote_requester.cpp | 20 | ||||
-rw-r--r-- | src/mongo/db/repl/vote_requester.h | 6 |
8 files changed, 145 insertions, 57 deletions
diff --git a/src/mongo/db/repl/repl_set_request_votes_args.cpp b/src/mongo/db/repl/repl_set_request_votes_args.cpp index e72af47af64..d5a3b5b22a3 100644 --- a/src/mongo/db/repl/repl_set_request_votes_args.cpp +++ b/src/mongo/db/repl/repl_set_request_votes_args.cpp @@ -44,9 +44,9 @@ const std::string kCommandName = "replSetRequestVotes"; const std::string kConfigVersionFieldName = "configVersion"; const std::string kConfigTermFieldName = "configTerm"; const std::string kDryRunFieldName = "dryRun"; -// The underlying field name is inaccurate, but changing it requires a fair amount of cross -// compatibility work for no real benefit. +// TODO: Remove references to the "lastCommittedOp" field name (SERVER-46090). const std::string kLastDurableOpTimeFieldName = "lastCommittedOp"; +const std::string kLastAppliedOpTimeFieldName = "lastAppliedOpTime"; const std::string kOkFieldName = "ok"; const std::string kReasonFieldName = "reason"; const std::string kSetNameFieldName = "setName"; @@ -54,7 +54,8 @@ const std::string kTermFieldName = "term"; const std::string kVoteGrantedFieldName = "voteGranted"; const std::string kOperationTime = "operationTime"; -const std::string kLegalArgsFieldNames[] = { +// TODO: `kLegalArgsFieldNamesFCV42` should be removed after upgrading to 4.6 (SERVER-46090). +const std::string kLegalArgsFieldNamesFCV42[] = { kCandidateIndexFieldName, kCommandName, kConfigVersionFieldName, @@ -66,14 +67,42 @@ const std::string kLegalArgsFieldNames[] = { kOperationTime, }; +const std::string kLegalArgsFieldNames[] = { + kCandidateIndexFieldName, + kCommandName, + kConfigVersionFieldName, + kConfigTermFieldName, + kDryRunFieldName, + kLastAppliedOpTimeFieldName, + kSetNameFieldName, + kTermFieldName, + kOperationTime, +}; + } // namespace Status ReplSetRequestVotesArgs::initialize(const BSONObj& argsObj) { Status status = bsonCheckOnlyHasFieldsForCommand("ReplSetRequestVotes", argsObj, kLegalArgsFieldNames); - if (!status.isOK()) - return status; + // TODO: Remove this logic once we branch to 4.6 and can always assume + // _usingLastAppliedOptimeFieldName to be true (SERVER-46090). + // Since nodes in the replica set may have different values for FCV, we check that the legal + // field names of either FCV 4.2 or 4.4 are present in the args obj. + if (!status.isOK()) { + status = bsonCheckOnlyHasFieldsForCommand( + "ReplSetRequestVotes", argsObj, kLegalArgsFieldNamesFCV42); + if (!status.isOK()) + return status; + + // If we successfully parsed with the FCV 4.2 field names, use 'lastCommittedOp' as the + // correct field name. + _usingLastAppliedOpTimeFieldName = false; + } else { + // If we successfully parsed with the FCV 4.4 field names, use 'lastAppliedOpTime' as the + // correct field name. + _usingLastAppliedOpTimeFieldName = true; + } status = bsonExtractIntegerField(argsObj, kTermFieldName, &_term); if (!status.isOK()) @@ -102,9 +131,16 @@ Status ReplSetRequestVotesArgs::initialize(const BSONObj& argsObj) { if (!status.isOK()) return status; - status = bsonExtractOpTimeField(argsObj, kLastDurableOpTimeFieldName, &_lastDurableOpTime); - if (!status.isOK()) + // If we successfully parsed with the FCV 4.4 field names, use 'lastAppliedOpTime' to extract + // the data. Else, use 'lastCommittedOp' as the field name. + if (_usingLastAppliedOpTimeFieldName) { + status = bsonExtractOpTimeField(argsObj, kLastAppliedOpTimeFieldName, &_lastAppliedOpTime); + } else { + status = bsonExtractOpTimeField(argsObj, kLastDurableOpTimeFieldName, &_lastAppliedOpTime); + } + if (!status.isOK()) { return status; + } return Status::OK(); } @@ -133,8 +169,8 @@ ConfigVersionAndTerm ReplSetRequestVotesArgs::getConfigVersionAndTerm() const { return ConfigVersionAndTerm(_cfgVer, _cfgTerm); } -OpTime ReplSetRequestVotesArgs::getLastDurableOpTime() const { - return _lastDurableOpTime; +OpTime ReplSetRequestVotesArgs::getLastAppliedOpTime() const { + return _lastAppliedOpTime; } bool ReplSetRequestVotesArgs::isADryRun() const { @@ -149,7 +185,11 @@ void ReplSetRequestVotesArgs::addToBSON(BSONObjBuilder* builder) const { builder->appendIntOrLL(kCandidateIndexFieldName, _candidateIndex); builder->appendIntOrLL(kConfigVersionFieldName, _cfgVer); builder->appendIntOrLL(kConfigTermFieldName, _cfgTerm); - _lastDurableOpTime.append(builder, kLastDurableOpTimeFieldName); + if (_usingLastAppliedOpTimeFieldName) { + _lastAppliedOpTime.append(builder, kLastAppliedOpTimeFieldName); + } else { + _lastAppliedOpTime.append(builder, kLastDurableOpTimeFieldName); + } } std::string ReplSetRequestVotesArgs::toString() const { diff --git a/src/mongo/db/repl/repl_set_request_votes_args.h b/src/mongo/db/repl/repl_set_request_votes_args.h index c86429e79ed..3e91de7ad56 100644 --- a/src/mongo/db/repl/repl_set_request_votes_args.h +++ b/src/mongo/db/repl/repl_set_request_votes_args.h @@ -50,7 +50,7 @@ public: long long getConfigVersion() const; long long getConfigTerm() const; ConfigVersionAndTerm getConfigVersionAndTerm() const; - OpTime getLastDurableOpTime() const; + OpTime getLastAppliedOpTime() const; bool isADryRun() const; void addToBSON(BSONObjBuilder* builder) const; @@ -64,8 +64,14 @@ private: long long _cfgVer = -1; // replSet config version known to the command issuer. // replSet config term known to the command issuer. long long _cfgTerm = OpTime::kUninitializedTerm; - OpTime _lastDurableOpTime; // The last known durable op of the command issuer. + OpTime _lastAppliedOpTime; // The OpTime of the last known applied op of the command issuer. bool _dryRun = false; // Indicates this is a pre-election check when true. + + // TODO: Remove this field once references to 'lastCommittedOp' can be removed in 4.6 and we can + // assume _usingLastAppliedOpTimeFieldName to always be true (SERVER-46090). + // When true, indicates that we should use the 'lastAppliedOpTime' field for logging the last + // applied OpTime. Else, use 'lastCommittedOp'. + bool _usingLastAppliedOpTimeFieldName = true; }; class ReplSetRequestVotesResponse { diff --git a/src/mongo/db/repl/replication_coordinator_impl_elect_v1.cpp b/src/mongo/db/repl/replication_coordinator_impl_elect_v1.cpp index 61910c41c1e..5488b9a68f7 100644 --- a/src/mongo/db/repl/replication_coordinator_impl_elect_v1.cpp +++ b/src/mongo/db/repl/replication_coordinator_impl_elect_v1.cpp @@ -136,9 +136,9 @@ void ReplicationCoordinatorImpl::_startElectSelfV1_inlock(StartElectionReasonEnu invariant(_rsConfig.getMemberAt(_selfIndex).isElectable()); - const auto lastOpTime = _getMyLastAppliedOpTime_inlock(); + const auto lastAppliedOpTime = _getMyLastAppliedOpTime_inlock(); - if (lastOpTime == OpTime()) { + if (lastAppliedOpTime == OpTime()) { LOGV2(21436, "not trying to elect self, " "do not yet have a complete set of data from any point in time"); @@ -173,7 +173,7 @@ void ReplicationCoordinatorImpl::_startElectSelfV1_inlock(StartElectionReasonEnu _selfIndex, term, true, // dry run - lastOpTime, + lastAppliedOpTime, primaryIndex); if (nextPhaseEvh.getStatus() == ErrorCodes::ShutdownInProgress) { return; @@ -328,11 +328,11 @@ void ReplicationCoordinatorImpl::_writeLastVoteForMyElection( void ReplicationCoordinatorImpl::_startVoteRequester_inlock(long long newTerm, StartElectionReasonEnum reason) { - const auto lastOpTime = _getMyLastAppliedOpTime_inlock(); + const auto lastAppliedOpTime = _getMyLastAppliedOpTime_inlock(); _voteRequester.reset(new VoteRequester); StatusWith<executor::TaskExecutor::EventHandle> nextPhaseEvh = _voteRequester->start( - _replExecutor.get(), _rsConfig, _selfIndex, newTerm, false, lastOpTime, -1); + _replExecutor.get(), _rsConfig, _selfIndex, newTerm, false, lastAppliedOpTime, -1); if (nextPhaseEvh.getStatus() == ErrorCodes::ShutdownInProgress) { return; } diff --git a/src/mongo/db/repl/replication_coordinator_impl_test.cpp b/src/mongo/db/repl/replication_coordinator_impl_test.cpp index b7fba917f79..35c002d78b4 100644 --- a/src/mongo/db/repl/replication_coordinator_impl_test.cpp +++ b/src/mongo/db/repl/replication_coordinator_impl_test.cpp @@ -6895,7 +6895,7 @@ TEST_F(ReplCoordTest, NodeStoresElectionVotes) { << "mySet" << "term" << 7LL << "candidateIndex" << 2LL << "configVersion" << 2LL << "dryRun" - << false << "lastCommittedOp" + << false << "lastAppliedOpTime" << time.asOpTime().toBSON()))); ReplSetRequestVotesResponse response; @@ -6938,7 +6938,7 @@ TEST_F(ReplCoordTest, NodeDoesNotStoreDryRunVotes) { << "mySet" << "term" << 7LL << "candidateIndex" << 2LL << "configVersion" << 2LL << "dryRun" - << true << "lastCommittedOp" + << true << "lastAppliedOpTime" << time.asOpTime().toBSON()))); ReplSetRequestVotesResponse response; @@ -6985,7 +6985,7 @@ TEST_F(ReplCoordTest, NodeFailsVoteRequestIfItFailsToStoreLastVote) { << "mySet" << "term" << initTerm + 1 // term of new candidate. << "candidateIndex" << 1LL << "configVersion" << 2LL << "dryRun" - << false << "lastCommittedOp" << time.asOpTime().toBSON()))); + << false << "lastAppliedOpTime" << time.asOpTime().toBSON()))); ReplSetRequestVotesResponse response; // Simulate a failure to write the 'last vote' document. The specific error code isn't @@ -7036,7 +7036,7 @@ TEST_F(ReplCoordTest, NodeNodesNotGrantVoteIfInTerminalShutdown) { << "mySet" << "term" << initTerm + 1 // term of new candidate. << "candidateIndex" << 1LL << "configVersion" << 2LL << "dryRun" - << false << "lastCommittedOp" << time.asOpTime().toBSON()))); + << false << "lastAppliedOpTime" << time.asOpTime().toBSON()))); ReplSetRequestVotesResponse response; getReplCoord()->enterTerminalShutdown(); diff --git a/src/mongo/db/repl/topology_coordinator.cpp b/src/mongo/db/repl/topology_coordinator.cpp index 2b329b0f0d6..7160264baac 100644 --- a/src/mongo/db/repl/topology_coordinator.cpp +++ b/src/mongo/db/repl/topology_coordinator.cpp @@ -2931,12 +2931,12 @@ void TopologyCoordinator::processReplSetRequestVotes(const ReplSetRequestVotesAr response->setReason(str::stream() << "candidate's set name ({}) differs from mine ({})"_format( args.getSetName(), _rsConfig.getReplSetName())); - } else if (args.getLastDurableOpTime() < getMyLastAppliedOpTime()) { + } else if (args.getLastAppliedOpTime() < getMyLastAppliedOpTime()) { response->setVoteGranted(false); response->setReason(str::stream() << "candidate's data is staler than mine. candidate's last applied " "OpTime: {}, my last applied OpTime: {}"_format( - args.getLastDurableOpTime().toString(), + args.getLastAppliedOpTime().toString(), getMyLastAppliedOpTime().toString())); } else if (!args.isADryRun() && _lastVote.getTerm() == args.getTerm()) { response->setVoteGranted(false); diff --git a/src/mongo/db/repl/topology_coordinator_v1_test.cpp b/src/mongo/db/repl/topology_coordinator_v1_test.cpp index cf41b85b78d..cd3cd98643f 100644 --- a/src/mongo/db/repl/topology_coordinator_v1_test.cpp +++ b/src/mongo/db/repl/topology_coordinator_v1_test.cpp @@ -2563,7 +2563,7 @@ TEST_F(TopoCoordTest, NodeDoesNotGrantVotesToTwoDifferentNodesInTheSameTerm) { << "rs0" << "term" << 1LL << "candidateIndex" << 0LL << "configVersion" << 1LL << "configTerm" << 1LL - << "lastCommittedOp" + << "lastAppliedOpTime" << BSON("ts" << Timestamp(10, 0) << "term" << 0LL))) .transitional_ignore(); ReplSetRequestVotesResponse response; @@ -2578,7 +2578,7 @@ TEST_F(TopoCoordTest, NodeDoesNotGrantVotesToTwoDifferentNodesInTheSameTerm) { << "rs0" << "term" << 1LL << "candidateIndex" << 1LL << "configVersion" << 1LL << "configTerm" << 1LL - << "lastCommittedOp" + << "lastAppliedOpTime" << BSON("ts" << Timestamp(10, 0) << "term" << 0LL))) .transitional_ignore(); ReplSetRequestVotesResponse response2; @@ -2642,7 +2642,7 @@ TEST_F(TopoCoordTest, DryRunVoteRequestShouldNotPreventSubsequentDryRunsForThatT << "rs0" << "dryRun" << true << "term" << 1LL << "candidateIndex" << 0LL << "configVersion" << 1LL - << "configTerm" << 1LL << "lastCommittedOp" + << "configTerm" << 1LL << "lastAppliedOpTime" << BSON("ts" << Timestamp(10, 0) << "term" << 0LL))) .transitional_ignore(); ReplSetRequestVotesResponse response; @@ -2658,7 +2658,7 @@ TEST_F(TopoCoordTest, DryRunVoteRequestShouldNotPreventSubsequentDryRunsForThatT << "rs0" << "dryRun" << true << "term" << 1LL << "candidateIndex" << 0LL << "configVersion" << 1LL - << "configTerm" << 1LL << "lastCommittedOp" + << "configTerm" << 1LL << "lastAppliedOpTime" << BSON("ts" << Timestamp(10, 0) << "term" << 0LL))) .transitional_ignore(); ReplSetRequestVotesResponse response2; @@ -2674,7 +2674,7 @@ TEST_F(TopoCoordTest, DryRunVoteRequestShouldNotPreventSubsequentDryRunsForThatT << "rs0" << "dryRun" << false << "term" << 1LL << "candidateIndex" << 0LL << "configVersion" << 1LL - << "configTerm" << 1LL << "lastCommittedOp" + << "configTerm" << 1LL << "lastAppliedOpTime" << BSON("ts" << Timestamp(10, 0) << "term" << 0LL))) .transitional_ignore(); ReplSetRequestVotesResponse response3; @@ -2690,7 +2690,7 @@ TEST_F(TopoCoordTest, DryRunVoteRequestShouldNotPreventSubsequentDryRunsForThatT << "rs0" << "dryRun" << false << "term" << 1LL << "candidateIndex" << 0LL << "configVersion" << 1LL - << "configTerm" << 1LL << "lastCommittedOp" + << "configTerm" << 1LL << "lastAppliedOpTime" << BSON("ts" << Timestamp(10, 0) << "term" << 0LL))) .transitional_ignore(); ReplSetRequestVotesResponse response4; @@ -2720,7 +2720,7 @@ TEST_F(TopoCoordTest, VoteRequestShouldNotPreventDryRunsForThatTerm) { << "rs0" << "dryRun" << false << "term" << 1LL << "candidateIndex" << 0LL << "configVersion" << 1LL - << "configTerm" << 1LL << "lastCommittedOp" + << "configTerm" << 1LL << "lastAppliedOpTime" << BSON("ts" << Timestamp(10, 0) << "term" << 0LL))) .transitional_ignore(); ReplSetRequestVotesResponse response; @@ -2736,7 +2736,7 @@ TEST_F(TopoCoordTest, VoteRequestShouldNotPreventDryRunsForThatTerm) { << "rs0" << "dryRun" << false << "term" << 1LL << "candidateIndex" << 0LL << "configVersion" << 1LL - << "configTerm" << 1LL << "lastCommittedOp" + << "configTerm" << 1LL << "lastAppliedOpTime" << BSON("ts" << Timestamp(10, 0) << "term" << 0LL))) .transitional_ignore(); ReplSetRequestVotesResponse response2; @@ -2766,7 +2766,7 @@ TEST_F(TopoCoordTest, NodeDoesNotGrantVoteWhenReplSetNameDoesNotMatch) { << "wrongName" << "term" << 1LL << "candidateIndex" << 0LL << "configVersion" << 1LL << "configTerm" << 1LL - << "lastCommittedOp" + << "lastAppliedOpTime" << BSON("ts" << Timestamp(10, 0) << "term" << 0LL))) .transitional_ignore(); ReplSetRequestVotesResponse response; @@ -2795,7 +2795,7 @@ TEST_F(TopoCoordTest, NodeDoesNotGrantVoteWhenConfigVersionIsLower) { << "rs0" << "term" << 1LL << "candidateIndex" << 1LL << "configVersion" << 0LL << "configTerm" << 1LL - << "lastCommittedOp" + << "lastAppliedOpTime" << BSON("ts" << Timestamp(10, 0) << "term" << 0LL))) .transitional_ignore(); ReplSetRequestVotesResponse response; @@ -2827,7 +2827,7 @@ TEST_F(TopoCoordTest, NodeDoesNotGrantVoteWhenConfigTermIsLower) { << "rs0" << "term" << 1LL << "candidateIndex" << 1LL << "configVersion" << 1LL << "configTerm" << 1LL - << "lastCommittedOp" + << "lastAppliedOpTime" << BSON("ts" << Timestamp(10, 0) << "term" << 0LL))) .transitional_ignore(); ReplSetRequestVotesResponse response; @@ -2863,7 +2863,7 @@ TEST_F(TopoCoordTest, NodeDoesNotGrantVoteWhenTermIsStale) { << "rs0" << "term" << 1LL << "candidateIndex" << 1LL << "configVersion" << 1LL << "configTerm" << 1LL - << "lastCommittedOp" + << "lastAppliedOpTime" << BSON("ts" << Timestamp(10, 0) << "term" << 0LL))) .transitional_ignore(); ReplSetRequestVotesResponse response; @@ -2894,7 +2894,7 @@ TEST_F(TopoCoordTest, NodeDoesNotGrantVoteWhenOpTimeIsStale) { << "rs0" << "term" << 3LL << "candidateIndex" << 1LL << "configVersion" << 1LL << "configTerm" << 1LL - << "lastCommittedOp" + << "lastAppliedOpTime" << BSON("ts" << Timestamp(10, 0) << "term" << 0LL))) .transitional_ignore(); ReplSetRequestVotesResponse response; @@ -2931,7 +2931,7 @@ TEST_F(TopoCoordTest, NodeDoesNotGrantDryRunVoteWhenReplSetNameDoesNotMatch) { << "rs0" << "term" << 1LL << "candidateIndex" << 0LL << "configVersion" << 1LL << "configTerm" << 1LL - << "lastCommittedOp" + << "lastAppliedOpTime" << BSON("ts" << Timestamp(10, 0) << "term" << 0LL))) .transitional_ignore(); ReplSetRequestVotesResponse responseForRealVote; @@ -2947,7 +2947,7 @@ TEST_F(TopoCoordTest, NodeDoesNotGrantDryRunVoteWhenReplSetNameDoesNotMatch) { << "wrongName" << "dryRun" << true << "term" << 2LL << "candidateIndex" << 0LL << "configVersion" << 1LL - << "configTerm" << 1LL << "lastCommittedOp" + << "configTerm" << 1LL << "lastAppliedOpTime" << BSON("ts" << Timestamp(10, 0) << "term" << 0LL))) .transitional_ignore(); ReplSetRequestVotesResponse response; @@ -2980,7 +2980,7 @@ TEST_F(TopoCoordTest, NodeDoesNotGrantDryRunVoteWhenConfigVersionIsLower) { << "rs0" << "term" << 1LL << "candidateIndex" << 0LL << "configVersion" << 1LL << "configTerm" << 1LL - << "lastCommittedOp" + << "lastAppliedOpTime" << BSON("ts" << Timestamp(10, 0) << "term" << 0LL))) .transitional_ignore(); ReplSetRequestVotesResponse responseForRealVote; @@ -2996,7 +2996,7 @@ TEST_F(TopoCoordTest, NodeDoesNotGrantDryRunVoteWhenConfigVersionIsLower) { << "rs0" << "dryRun" << true << "term" << 2LL << "candidateIndex" << 1LL << "configVersion" << 0LL - << "configTerm" << 1LL << "lastCommittedOp" + << "configTerm" << 1LL << "lastAppliedOpTime" << BSON("ts" << Timestamp(10, 0) << "term" << 0LL))) .transitional_ignore(); ReplSetRequestVotesResponse response; @@ -3032,7 +3032,7 @@ TEST_F(TopoCoordTest, NodeDoesNotGrantDryRunVoteWhenTermIsStale) { << "rs0" << "term" << 1LL << "candidateIndex" << 0LL << "configVersion" << 1LL << "configTerm" << 1LL - << "lastCommittedOp" + << "lastAppliedOpTime" << BSON("ts" << Timestamp(10, 0) << "term" << 0LL))) .transitional_ignore(); ReplSetRequestVotesResponse responseForRealVote; @@ -3047,7 +3047,7 @@ TEST_F(TopoCoordTest, NodeDoesNotGrantDryRunVoteWhenTermIsStale) { << "rs0" << "dryRun" << true << "term" << 0LL << "candidateIndex" << 1LL << "configVersion" << 1LL - << "configTerm" << 1LL << "lastCommittedOp" + << "configTerm" << 1LL << "lastAppliedOpTime" << BSON("ts" << Timestamp(10, 0) << "term" << 0LL))) .transitional_ignore(); ReplSetRequestVotesResponse response; @@ -3081,7 +3081,7 @@ TEST_F(TopoCoordTest, NodeGrantsVoteWhenTermIsHigherButConfigVersionIsLower) { << "rs0" << "term" << 2LL << "candidateIndex" << 1LL << "configVersion" << 1LL << "configTerm" << 2LL - << "lastCommittedOp" + << "lastAppliedOpTime" << BSON("ts" << Timestamp(10, 0) << "term" << 0LL))) .transitional_ignore(); ReplSetRequestVotesResponse response; @@ -3114,7 +3114,7 @@ TEST_F(TopoCoordTest, GrantDryRunVoteEvenWhenTermHasBeenSeen) { << "rs0" << "term" << 1LL << "candidateIndex" << 0LL << "configVersion" << 1LL << "configTerm" << 1LL - << "lastCommittedOp" + << "lastAppliedOpTime" << BSON("ts" << Timestamp(10, 0) << "term" << 0LL))) .transitional_ignore(); ReplSetRequestVotesResponse responseForRealVote; @@ -3130,7 +3130,7 @@ TEST_F(TopoCoordTest, GrantDryRunVoteEvenWhenTermHasBeenSeen) { << "rs0" << "dryRun" << true << "term" << 1LL << "candidateIndex" << 1LL << "configVersion" << 1LL - << "configTerm" << 1LL << "lastCommittedOp" + << "configTerm" << 1LL << "lastAppliedOpTime" << BSON("ts" << Timestamp(10, 0) << "term" << 0LL))) .transitional_ignore(); ReplSetRequestVotesResponse response; @@ -3163,7 +3163,7 @@ TEST_F(TopoCoordTest, DoNotGrantDryRunVoteWhenOpTimeIsStale) { << "rs0" << "term" << 1LL << "candidateIndex" << 0LL << "configVersion" << 1LL << "configTerm" << 1LL - << "lastCommittedOp" + << "lastAppliedOpTime" << BSON("ts" << Timestamp(10, 0) << "term" << 0LL))) .transitional_ignore(); ReplSetRequestVotesResponse responseForRealVote; @@ -3179,7 +3179,7 @@ TEST_F(TopoCoordTest, DoNotGrantDryRunVoteWhenOpTimeIsStale) { << "rs0" << "dryRun" << true << "term" << 3LL << "candidateIndex" << 1LL << "configVersion" << 1LL - << "configTerm" << 1LL << "lastCommittedOp" + << "configTerm" << 1LL << "lastAppliedOpTime" << BSON("ts" << Timestamp(10, 0) << "term" << 0LL))) .transitional_ignore(); ReplSetRequestVotesResponse response; @@ -3195,6 +3195,42 @@ TEST_F(TopoCoordTest, DoNotGrantDryRunVoteWhenOpTimeIsStale) { ASSERT_FALSE(response.getVoteGranted()); } +// TODO: Remove this test in 4.6 when we can remove references to "lastCommittedOp" (SERVER-46090). +TEST_F(TopoCoordTest, ParseLastAppliedOpTimeWithCorrectFieldName) { + const OpTime lastOpTimeApplied = OpTime(Timestamp(4, 0), 0); + + const auto reqVotesObjWithLastAppliedOpTimeField = + BSON("replSetRequestVotes" << 1 << "setName" + << "rs0" + << "dryRun" << true << "term" << 1LL << "candidateIndex" << 1LL + << "configVersion" << 1LL << "configTerm" << 1LL + << "lastAppliedOpTime" << lastOpTimeApplied); + ReplSetRequestVotesArgs reqVotesArgsWithLastAppliedOpTimeField; + ASSERT_OK( + reqVotesArgsWithLastAppliedOpTimeField.initialize(reqVotesObjWithLastAppliedOpTimeField)); + + // Verify we successfully parse the args with 'lastAppliedOpTime' as the field name. + ASSERT_EQUALS(lastOpTimeApplied, reqVotesArgsWithLastAppliedOpTimeField.getLastAppliedOpTime()); + // Verify that the request serializes correctly. + ASSERT_EQUALS(reqVotesObjWithLastAppliedOpTimeField.toString(), + reqVotesObjWithLastAppliedOpTimeField.toString()); + + const auto reqVotesObjWithLastCommittedOpField = + BSON("replSetRequestVotes" << 1 << "setName" + << "rs1" + << "dryRun" << true << "term" << 1LL << "candidateIndex" << 1LL + << "configVersion" << 1LL << "configTerm" << 1LL + << "lastCommittedOp" << lastOpTimeApplied); + ReplSetRequestVotesArgs reqVotesArgsWithLastCommittedOpField; + ASSERT_OK(reqVotesArgsWithLastCommittedOpField.initialize(reqVotesObjWithLastCommittedOpField)); + + // Verify we successfully parse the args with 'lastCommittedOp' as the field name. + ASSERT_EQUALS(lastOpTimeApplied, reqVotesArgsWithLastCommittedOpField.getLastAppliedOpTime()); + // Verify that the request serializes correctly. + ASSERT_EQUALS(reqVotesObjWithLastCommittedOpField.toString(), + reqVotesArgsWithLastCommittedOpField.toString()); +} + TEST_F(TopoCoordTest, NodeTransitionsToRemovedIfCSRSButHaveNoReadCommittedSupport) { ON_BLOCK_EXIT([]() { serverGlobalParams.clusterRole = ClusterRole::None; }); serverGlobalParams.clusterRole = ClusterRole::ConfigServer; diff --git a/src/mongo/db/repl/vote_requester.cpp b/src/mongo/db/repl/vote_requester.cpp index 64f0d5c172b..27b79ca43bb 100644 --- a/src/mongo/db/repl/vote_requester.cpp +++ b/src/mongo/db/repl/vote_requester.cpp @@ -59,13 +59,13 @@ VoteRequester::Algorithm::Algorithm(const ReplSetConfig& rsConfig, long long candidateIndex, long long term, bool dryRun, - OpTime lastDurableOpTime, + OpTime lastAppliedOpTime, int primaryIndex) : _rsConfig(rsConfig), _candidateIndex(candidateIndex), _term(term), _dryRun(dryRun), - _lastDurableOpTime(lastDurableOpTime) { + _lastAppliedOpTime(lastAppliedOpTime) { // populate targets with all voting members that aren't this node long long index = 0; for (auto member = _rsConfig.membersBegin(); member != _rsConfig.membersEnd(); member++) { @@ -89,15 +89,21 @@ std::vector<RemoteCommandRequest> VoteRequester::Algorithm::getRequests() const requestVotesCmdBuilder.append("term", _term); requestVotesCmdBuilder.append("candidateIndex", _candidateIndex); requestVotesCmdBuilder.append("configVersion", _rsConfig.getConfigVersion()); - // Only append the config term field to the VoteRequester if we are in FCV 4.4 + + // TODO: Remove this check when we upgrade to 4.6 and can remove references to "lastCommittedOp" + // (SERVER-46090). + // Only append the config term field to the VoteRequester and use "lastAppliedOpTime" as the + // field name for _lastAppliedOpTime if we are in FCV 4.4. if (serverGlobalParams.featureCompatibility.isVersionInitialized() && serverGlobalParams.featureCompatibility.getVersion() == ServerGlobalParams::FeatureCompatibility::Version::kFullyUpgradedTo44) { requestVotesCmdBuilder.append("configTerm", _rsConfig.getConfigTerm()); + _lastAppliedOpTime.append(&requestVotesCmdBuilder, "lastAppliedOpTime"); + } else { + // If we are not in FCV 4.4, use "lastCommittedOp" as the field name instead. + _lastAppliedOpTime.append(&requestVotesCmdBuilder, "lastCommittedOp"); } - _lastDurableOpTime.append(&requestVotesCmdBuilder, "lastCommittedOp"); - const BSONObj requestVotesCmd = requestVotesCmdBuilder.obj(); std::vector<RemoteCommandRequest> requests; @@ -219,10 +225,10 @@ StatusWith<executor::TaskExecutor::EventHandle> VoteRequester::start( long long candidateIndex, long long term, bool dryRun, - OpTime lastDurableOpTime, + OpTime lastAppliedOpTime, int primaryIndex) { _algorithm = std::make_shared<Algorithm>( - rsConfig, candidateIndex, term, dryRun, lastDurableOpTime, primaryIndex); + rsConfig, candidateIndex, term, dryRun, lastAppliedOpTime, primaryIndex); _runner = std::make_unique<ScatterGatherRunner>(_algorithm, executor, "vote request"); return _runner->start(); } diff --git a/src/mongo/db/repl/vote_requester.h b/src/mongo/db/repl/vote_requester.h index 6eed65bc1e3..14a13f1f465 100644 --- a/src/mongo/db/repl/vote_requester.h +++ b/src/mongo/db/repl/vote_requester.h @@ -59,7 +59,7 @@ public: long long candidateIndex, long long term, bool dryRun, - OpTime lastDurableOpTime, + OpTime lastAppliedOpTime, int primaryIndex); virtual ~Algorithm(); virtual std::vector<executor::RemoteCommandRequest> getRequests() const; @@ -86,7 +86,7 @@ public: const long long _candidateIndex; const long long _term; bool _dryRun = false; // this bool indicates this is a mock election when true - const OpTime _lastDurableOpTime; + const OpTime _lastAppliedOpTime; std::vector<HostAndPort> _targets; stdx::unordered_set<HostAndPort> _responders; bool _staleTerm = false; @@ -113,7 +113,7 @@ public: long long candidateIndex, long long term, bool dryRun, - OpTime lastDurableOpTime, + OpTime lastAppliedOpTime, int primaryIndex); /** |