diff options
author | Suganthi Mani <suganthi.mani@mongodb.com> | 2018-05-14 13:41:11 -0400 |
---|---|---|
committer | Suganthi Mani <suganthi.mani@mongodb.com> | 2018-05-23 12:18:04 -0400 |
commit | 65cd5579b5bde734eaba0d97a7e285f705d78b92 (patch) | |
tree | 1952d97ca5ebfa5cdcd8336c39df71282aacb3a7 | |
parent | 7921691ab57de8899f4db2cdbee8d9ea78e1a2fb (diff) | |
download | mongo-65cd5579b5bde734eaba0d97a7e285f705d78b92.tar.gz |
SERVER-34661 Return early when the vote request response has an error.
Fixed by making VoteRequester::Algorithm::processResponseto to check ok field in the vote response message.
(cherry picked from commit e4e2162c489c1faa569463f51058ebc09368a5f9)
-rw-r--r-- | src/mongo/db/repl/vote_requester.cpp | 7 | ||||
-rw-r--r-- | src/mongo/db/repl/vote_requester_test.cpp | 37 |
2 files changed, 42 insertions, 2 deletions
diff --git a/src/mongo/db/repl/vote_requester.cpp b/src/mongo/db/repl/vote_requester.cpp index 019c545a544..aed7cca6049 100644 --- a/src/mongo/db/repl/vote_requester.cpp +++ b/src/mongo/db/repl/vote_requester.cpp @@ -119,9 +119,14 @@ void VoteRequester::Algorithm::processResponse(const RemoteCommandRequest& reque _primaryVote = PrimaryVote::No; } ReplSetRequestVotesResponse voteResponse; - const auto status = voteResponse.initialize(response.data); + auto status = getStatusFromCommandResult(response.data); + if (status.isOK()) { + status = voteResponse.initialize(response.data); + } if (!status.isOK()) { logLine << "received an invalid response from " << request.target << ": " << status; + logLine << "; response message: " << response.data; + return; } if (voteResponse.getVoteGranted()) { diff --git a/src/mongo/db/repl/vote_requester_test.cpp b/src/mongo/db/repl/vote_requester_test.cpp index 5d3cd98749e..ad7501440a9 100644 --- a/src/mongo/db/repl/vote_requester_test.cpp +++ b/src/mongo/db/repl/vote_requester_test.cpp @@ -31,6 +31,7 @@ #include <memory> #include "mongo/base/status.h" +#include "mongo/db/commands.h" #include "mongo/db/jsobj.h" #include "mongo/db/repl/repl_set_request_votes_args.h" #include "mongo/db/repl/vote_requester.h" @@ -112,7 +113,16 @@ protected: void processResponse(const RemoteCommandRequest& request, const RemoteCommandResponse& response) { - _requester->processResponse(request, response); + if (!response.isOK()) { + _requester->processResponse(request, response); + return; + } + BSONObjBuilder builder(response.data); + // Appends ok:1.0 (status ok) to response data if 'ok' field is missing. + CommandHelpers::appendCommandStatusNoThrow(builder, Status::OK()); + RemoteCommandResponse responseWithCmdStatus = response; + responseWithCmdStatus.data = builder.obj(); + _requester->processResponse(request, responseWithCmdStatus); } int getNumResponders() { @@ -142,6 +152,18 @@ protected: return RemoteCommandResponse(response.toBSON(), BSONObj(), Milliseconds(10)); } + RemoteCommandResponse votedYesStatusNotOkBecauseFailedToStoreLastVote() { + ReplSetRequestVotesResponse response; + BSONObjBuilder result; + response.setVoteGranted(true); + response.setTerm(1); + response.addToBSON(&result); + auto status = + Status(ErrorCodes::InterruptedDueToReplStateChange, "operation was interrupted"); + CommandHelpers::appendCommandStatusNoThrow(result, status); + return RemoteCommandResponse(result.obj(), BSONObj(), Milliseconds(10)); + } + RemoteCommandResponse votedNoBecauseConfigVersionDoesNotMatch() { ReplSetRequestVotesResponse response; response.setVoteGranted(false); @@ -272,6 +294,19 @@ TEST_F(VoteRequesterTest, ImmediateGoodResponseWinElection) { ASSERT_EQUALS(1, getNumResponders()); } +TEST_F(VoteRequesterTest, VoterFailedToStoreLastVote) { + startCapturingLogMessages(); + ASSERT_FALSE(hasReceivedSufficientResponses()); + processResponse(requestFrom("host1"), votedYesStatusNotOkBecauseFailedToStoreLastVote()); + ASSERT_FALSE(hasReceivedSufficientResponses()); + ASSERT_EQUALS(1, countLogLinesContaining("received an invalid response from host1:27017")); + processResponse(requestFrom("host2"), votedYes()); + ASSERT_TRUE(hasReceivedSufficientResponses()); + ASSERT(VoteRequester::Result::kSuccessfullyElected == getResult()); + ASSERT_EQUALS(2, getNumResponders()); + stopCapturingLogMessages(); +} + TEST_F(VoteRequesterTest, BadConfigVersionWinElection) { startCapturingLogMessages(); ASSERT_FALSE(hasReceivedSufficientResponses()); |