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 12:18:04 -0400
commit65cd5579b5bde734eaba0d97a7e285f705d78b92 (patch)
tree1952d97ca5ebfa5cdcd8336c39df71282aacb3a7
parent7921691ab57de8899f4db2cdbee8d9ea78e1a2fb (diff)
downloadmongo-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.cpp7
-rw-r--r--src/mongo/db/repl/vote_requester_test.cpp37
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());