summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSuganthi Mani <suganthi.mani@mongodb.com>2018-05-14 13:41:11 -0400
committerSuganthi Mani <suganthi.mani@mongodb.com>2018-05-23 17:48:14 -0400
commit7f3e69a63c3ab61bfea2a563ded9d555fb017c8a (patch)
treeb4336275d47cc49909d1a7aa0a860bb5f6ee7ce3
parent85bedb96ec711af3d583c7204b032d266de2c54b (diff)
downloadmongo-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.cpp7
-rw-r--r--src/mongo/db/repl/vote_requester_test.cpp39
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());