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 17:48:14 -0400 |
commit | 7f3e69a63c3ab61bfea2a563ded9d555fb017c8a (patch) | |
tree | b4336275d47cc49909d1a7aa0a860bb5f6ee7ce3 | |
parent | 85bedb96ec711af3d583c7204b032d266de2c54b (diff) | |
download | mongo-7f3e69a63c3ab61bfea2a563ded9d555fb017c8a.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 | 39 |
2 files changed, 44 insertions, 2 deletions
diff --git a/src/mongo/db/repl/vote_requester.cpp b/src/mongo/db/repl/vote_requester.cpp index bac35602398..861b7b4b9e5 100644 --- a/src/mongo/db/repl/vote_requester.cpp +++ b/src/mongo/db/repl/vote_requester.cpp @@ -99,9 +99,14 @@ void VoteRequester::Algorithm::processResponse(const RemoteCommandRequest& reque } _responders.insert(request.target); 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 1dd97c456ea..02adb0a919a 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/replication_executor.h" @@ -109,7 +110,17 @@ protected: } void processResponse(const RemoteCommandRequest& request, const ResponseStatus& response) { - _requester->processResponse(request, response); + if (!response.isOK()) { + _requester->processResponse(request, response); + return; + } + BSONObjBuilder builder; + builder.appendElements(response.data); + // Appends ok:1.0 (status ok) to response data if 'ok' field is missing. + Command::appendCommandStatus(builder, Status::OK()); + ResponseStatus responseWithCmdStatus = response; + responseWithCmdStatus.data = builder.obj(); + _requester->processResponse(request, responseWithCmdStatus); } int getNumResponders() { @@ -140,6 +151,19 @@ protected: NetworkInterfaceMock::Response(response.toBSON(), BSONObj(), Milliseconds(10))); } + ResponseStatus votedYesStatusNotOkBecauseFailedToStoreLastVote() { + ReplSetRequestVotesResponse response; + BSONObjBuilder result; + response.setVoteGranted(true); + response.setTerm(1); + response.addToBSON(&result); + auto status = + Status(ErrorCodes::InterruptedDueToReplStateChange, "operation was interrupted"); + Command::appendCommandStatus(result, status); + return ResponseStatus( + NetworkInterfaceMock::Response(result.obj(), BSONObj(), Milliseconds(10))); + } + ResponseStatus votedNoBecauseConfigVersionDoesNotMatch() { ReplSetRequestVotesResponse response; response.setVoteGranted(false); @@ -236,6 +260,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()); |