summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXuerui Fa <xuerui.fa@mongodb.com>2020-02-10 15:15:42 -0500
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-02-18 17:07:55 +0000
commit99e7754701d5be6fafb567296540df36cb26ab87 (patch)
tree62a554d041a22c716ca07c9fa09e6aea913178a2
parent19f7a856c0b1c80c378191d5ae3451cdd09e5c61 (diff)
downloadmongo-99e7754701d5be6fafb567296540df36cb26ab87.tar.gz
SERVER-28680: Fix naming of lastCommittedOp field in replSetRequestVotes
-rw-r--r--jstests/replsets/last_vote.js12
-rw-r--r--src/mongo/db/repl/repl_set_request_votes_args.cpp60
-rw-r--r--src/mongo/db/repl/repl_set_request_votes_args.h10
-rw-r--r--src/mongo/db/repl/replication_coordinator_impl_elect_v1.cpp10
-rw-r--r--src/mongo/db/repl/replication_coordinator_impl_test.cpp8
-rw-r--r--src/mongo/db/repl/topology_coordinator.cpp4
-rw-r--r--src/mongo/db/repl/topology_coordinator_v1_test.cpp84
-rw-r--r--src/mongo/db/repl/vote_requester.cpp20
-rw-r--r--src/mongo/db/repl/vote_requester.h6
9 files changed, 151 insertions, 63 deletions
diff --git a/jstests/replsets/last_vote.js b/jstests/replsets/last_vote.js
index edf46b27a8b..0a3a5a8848f 100644
--- a/jstests/replsets/last_vote.js
+++ b/jstests/replsets/last_vote.js
@@ -8,7 +8,7 @@
// other node. It then restarts the first node as a replicaset and manually runs
// replSetRequestVotes commands against it and checks that its response is correct.
//
-// @tags: [requires_persistence]
+// @tags: [requires_persistence, requires_fcv_44]
(function() {
"use strict";
@@ -122,7 +122,7 @@ var response = assert.commandWorked(node0.adminCommand({
term: term - 1,
candidateIndex: 1,
configVersion: conf.version,
- lastCommittedOp: getLatestOp(node0)
+ lastAppliedOpTime: getLatestOp(node0)
}));
assert.eq(
response.term, term, "replSetRequestVotes response had the wrong term: " + tojson(response));
@@ -140,7 +140,7 @@ response = assert.commandWorked(node0.adminCommand({
term: term,
candidateIndex: 1,
configVersion: conf.version,
- lastCommittedOp: getLatestOp(node0)
+ lastAppliedOpTime: getLatestOp(node0)
}));
assert.eq(
response.term, term, "replSetRequestVotes response had the wrong term: " + tojson(response));
@@ -159,7 +159,7 @@ response = assert.commandWorked(node0.adminCommand({
term: term,
candidateIndex: 1,
configVersion: conf.version,
- lastCommittedOp: getLatestOp(node0)
+ lastAppliedOpTime: getLatestOp(node0)
}));
assert.eq(
response.term, term, "replSetRequestVotes response had the wrong term: " + tojson(response));
@@ -176,7 +176,7 @@ response = assert.commandWorked(node0.adminCommand({
term: term + 1,
candidateIndex: 1,
configVersion: conf.version,
- lastCommittedOp: getLatestOp(node0)
+ lastAppliedOpTime: getLatestOp(node0)
}));
assert.eq(response.term,
term + 1,
@@ -197,7 +197,7 @@ response = assert.commandWorked(node0.adminCommand({
term: term + 2,
candidateIndex: 1,
configVersion: conf.version,
- lastCommittedOp: getLatestOp(node0)
+ lastAppliedOpTime: getLatestOp(node0)
}));
assert.eq(response.term,
term + 2,
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);
/**