summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorBenety Goh <benety@mongodb.com>2015-10-16 15:40:39 -0400
committerBenety Goh <benety@mongodb.com>2015-10-22 15:27:17 -0400
commitfd6d4f03054ccc1f6df634d7a9d5060186070e98 (patch)
treec2441c3ecdfc3c1822ba5d535f9dc3138a6da1d8 /src/mongo
parent38f16626e9f161672ebad8ad4a18e23b7e57de87 (diff)
downloadmongo-fd6d4f03054ccc1f6df634d7a9d5060186070e98.tar.gz
SERVER-20977 added test for processing metadata in heartbeat
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/db/repl/replication_coordinator_impl.cpp9
-rw-r--r--src/mongo/db/repl/replication_coordinator_impl.h9
-rw-r--r--src/mongo/db/repl/replication_coordinator_impl_elect_v1.cpp14
-rw-r--r--src/mongo/db/repl/replication_coordinator_impl_test.cpp53
-rw-r--r--src/mongo/db/repl/replication_coordinator_test_fixture.cpp11
-rw-r--r--src/mongo/db/repl/replication_coordinator_test_fixture.h8
6 files changed, 94 insertions, 10 deletions
diff --git a/src/mongo/db/repl/replication_coordinator_impl.cpp b/src/mongo/db/repl/replication_coordinator_impl.cpp
index 683777454e6..82617ff73c4 100644
--- a/src/mongo/db/repl/replication_coordinator_impl.cpp
+++ b/src/mongo/db/repl/replication_coordinator_impl.cpp
@@ -3308,6 +3308,15 @@ CallbackHandle ReplicationCoordinatorImpl::_wrapAndScheduleWork(ScheduleFn sched
return cbh.getValue();
}
+EventHandle ReplicationCoordinatorImpl::_makeEvent() {
+ auto eventResult = this->_replExecutor.makeEvent();
+ if (eventResult.getStatus() == ErrorCodes::ShutdownInProgress) {
+ return EventHandle();
+ }
+ fassert(28825, eventResult.getStatus());
+ return eventResult.getValue();
+}
+
void ReplicationCoordinatorImpl::_scheduleElectionWinNotification() {
auto electionWinNotificationCallback = [this](const CallbackArgs& cbData) {
if (cbData.status == ErrorCodes::CallbackCanceled) {
diff --git a/src/mongo/db/repl/replication_coordinator_impl.h b/src/mongo/db/repl/replication_coordinator_impl.h
index e4f9a50e5c1..80757b7ba8e 100644
--- a/src/mongo/db/repl/replication_coordinator_impl.h
+++ b/src/mongo/db/repl/replication_coordinator_impl.h
@@ -386,6 +386,8 @@ private:
using CallbackHandle = executor::TaskExecutor::CallbackHandle;
+ using EventHandle = executor::TaskExecutor::EventHandle;
+
using ScheduleFn = stdx::function<StatusWith<executor::TaskExecutor::CallbackHandle>(
const executor::TaskExecutor::CallbackFn& work)>;
@@ -1143,6 +1145,13 @@ private:
static CallbackHandle _wrapAndScheduleWork(ScheduleFn scheduleFn, const CallbackFn& work);
/**
+ * Creates an event.
+ * Returns invalid event handle if the executor is shutting down.
+ * Otherwise aborts on non-shutdown error.
+ */
+ EventHandle _makeEvent();
+
+ /**
* Schedule notification of election win.
*/
void _scheduleElectionWinNotification();
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 337a9ce3ff6..a1b53badd44 100644
--- a/src/mongo/db/repl/replication_coordinator_impl_elect_v1.cpp
+++ b/src/mongo/db/repl/replication_coordinator_impl_elect_v1.cpp
@@ -108,19 +108,17 @@ void ReplicationCoordinatorImpl::_startElectSelfV1() {
fassertFailed(28641);
}
- const StatusWith<ReplicationExecutor::EventHandle> finishEvh = _replExecutor.makeEvent();
- if (finishEvh.getStatus() == ErrorCodes::ShutdownInProgress) {
+ auto finishedEvent = _makeEvent();
+ if (!finishedEvent) {
return;
}
- fassert(28642, finishEvh.getStatus());
- _electionFinishedEvent = finishEvh.getValue();
+ _electionFinishedEvent = finishedEvent;
- const StatusWith<ReplicationExecutor::EventHandle> dryRunFinishEvh = _replExecutor.makeEvent();
- if (dryRunFinishEvh.getStatus() == ErrorCodes::ShutdownInProgress) {
+ auto dryRunFinishedEvent = _makeEvent();
+ if (!dryRunFinishedEvent) {
return;
}
- fassert(28767, dryRunFinishEvh.getStatus());
- _electionDryRunFinishedEvent = dryRunFinishEvh.getValue();
+ _electionDryRunFinishedEvent = dryRunFinishedEvent;
LoseElectionDryRunGuardV1 lossGuard(this);
diff --git a/src/mongo/db/repl/replication_coordinator_impl_test.cpp b/src/mongo/db/repl/replication_coordinator_impl_test.cpp
index 3e1adc2ac88..b2582d33946 100644
--- a/src/mongo/db/repl/replication_coordinator_impl_test.cpp
+++ b/src/mongo/db/repl/replication_coordinator_impl_test.cpp
@@ -2798,6 +2798,59 @@ TEST_F(ReplCoordTest, MetadataUpdatesTermAndPrimaryId) {
ASSERT_EQUALS(-1, getTopoCoord().getCurrentPrimaryIndex());
}
+TEST_F(ReplCoordTest,
+ TermAndLastCommittedOpTimeUpdateWhenHeartbeatResponseWithMetadataHasFresherValues) {
+ // Ensure that the metadata is processed if it is contained in a heartbeat response.
+ assertStartSuccess(BSON("_id"
+ << "mySet"
+ << "version" << 2 << "members" << BSON_ARRAY(BSON("host"
+ << "node1:12345"
+ << "_id" << 0)
+ << BSON("host"
+ << "node2:12345"
+ << "_id" << 1))
+ << "protocolVersion" << 1),
+ HostAndPort("node1", 12345));
+ ASSERT_EQUALS(OpTime(Timestamp(0, 0), 0), getReplCoord()->getLastCommittedOpTime());
+ getReplCoord()->updateTerm(1);
+ ASSERT_EQUALS(1, getReplCoord()->getTerm());
+
+ auto replCoord = getReplCoord();
+ auto config = replCoord->getConfig();
+
+ // Higher term - should update term and lastCommittedOpTime.
+ StatusWith<rpc::ReplSetMetadata> metadata = rpc::ReplSetMetadata::readFromMetadata(BSON(
+ rpc::kReplSetMetadataFieldName
+ << BSON("lastOpCommitted" << BSON("ts" << Timestamp(10, 0) << "t" << 3) << "lastOpVisible"
+ << BSON("ts" << Timestamp(10, 0) << "t" << 3) << "configVersion"
+ << config.getConfigVersion() << "primaryIndex" << 1 << "term" << 3
+ << "syncSourceIndex" << 1)));
+ BSONObjBuilder metadataBuilder;
+ ASSERT_OK(metadata.getValue().writeToMetadata(&metadataBuilder));
+ auto metadataObj = metadataBuilder.obj();
+
+ auto net = getNet();
+ net->enterNetwork();
+
+ ASSERT_TRUE(net->hasReadyRequests());
+ auto noi = net->getNextReadyRequest();
+ const auto& request = noi->getRequest();
+ ASSERT_EQUALS(HostAndPort("node2", 12345), request.target);
+ ASSERT_EQUALS("replSetHeartbeat", request.cmdObj.firstElement().fieldNameStringData());
+
+ ReplSetHeartbeatResponse hbResp;
+ hbResp.setConfigVersion(config.getConfigVersion());
+ hbResp.setSetName(config.getReplSetName());
+ hbResp.setState(MemberState::RS_SECONDARY);
+ net->scheduleResponse(noi, net->now(), makeResponseStatus(hbResp.toBSON(true), metadataObj));
+ net->runReadyNetworkOperations();
+ net->exitNetwork();
+
+ ASSERT_EQUALS(OpTime(Timestamp(10, 0), 3), getReplCoord()->getLastCommittedOpTime());
+ ASSERT_EQUALS(3, getReplCoord()->getTerm());
+ ASSERT_EQUALS(-1, getTopoCoord().getCurrentPrimaryIndex());
+}
+
TEST_F(ReplCoordTest, CancelAndRescheduleElectionTimeout) {
assertStartSuccess(BSON("_id"
<< "mySet"
diff --git a/src/mongo/db/repl/replication_coordinator_test_fixture.cpp b/src/mongo/db/repl/replication_coordinator_test_fixture.cpp
index c0bc9096c14..539c06d97f0 100644
--- a/src/mongo/db/repl/replication_coordinator_test_fixture.cpp
+++ b/src/mongo/db/repl/replication_coordinator_test_fixture.cpp
@@ -172,8 +172,15 @@ void ReplCoordTest::assertStartSuccess(const BSONObj& configDoc, const HostAndPo
}
ResponseStatus ReplCoordTest::makeResponseStatus(const BSONObj& doc, Milliseconds millis) {
- log() << "Responding with " << doc;
- return ResponseStatus(RemoteCommandResponse(doc, BSONObj(), millis));
+ return makeResponseStatus(doc, BSONObj(), millis);
+}
+
+ResponseStatus ReplCoordTest::makeResponseStatus(const BSONObj& doc,
+ const BSONObj& metadata,
+ Milliseconds millis) {
+ log() << "Responding with " << doc << " (metadata: " << metadata << "; elapsed: " << millis
+ << ")";
+ return ResponseStatus(RemoteCommandResponse(doc, metadata, millis));
}
void ReplCoordTest::simulateSuccessfulDryRun(
diff --git a/src/mongo/db/repl/replication_coordinator_test_fixture.h b/src/mongo/db/repl/replication_coordinator_test_fixture.h
index a4023857091..b6b40d6f090 100644
--- a/src/mongo/db/repl/replication_coordinator_test_fixture.h
+++ b/src/mongo/db/repl/replication_coordinator_test_fixture.h
@@ -64,6 +64,14 @@ public:
Milliseconds millis = Milliseconds(0));
/**
+ * Makes a ResponseStatus with the given "doc" response, metadata and optional elapsed time
+ * "millis".
+ */
+ static ResponseStatus makeResponseStatus(const BSONObj& doc,
+ const BSONObj& metadata,
+ Milliseconds millis = Milliseconds(0));
+
+ /**
* Constructs a ReplicaSetConfig from the given BSON, or raises a test failure exception.
*/
static ReplicaSetConfig assertMakeRSConfig(const BSONObj& configBSON);