diff options
author | matt dannenberg <matt.dannenberg@10gen.com> | 2015-05-18 13:04:00 -0400 |
---|---|---|
committer | matt dannenberg <matt.dannenberg@10gen.com> | 2015-05-21 12:05:05 -0400 |
commit | 2d52cff7ee8fbff257698c334da85fa9115d35c0 (patch) | |
tree | 43b5fbdea3489eace0acc4e0a1794f05a51e05da | |
parent | 365f1d98a600472c1494e69ad0c2bf5f102df8da (diff) | |
download | mongo-2d52cff7ee8fbff257698c334da85fa9115d35c0.tar.gz |
SERVER-18511 report upstream progress when initial sync completes
3 files changed, 73 insertions, 8 deletions
diff --git a/jstests/replsets/initial_sync_report_progress.js b/jstests/replsets/initial_sync_report_progress.js new file mode 100644 index 00000000000..302f5ce4537 --- /dev/null +++ b/jstests/replsets/initial_sync_report_progress.js @@ -0,0 +1,42 @@ +// Ensure replication progress is sent upstream when initial sync completes +load("jstests/replsets/rslib.js"); +(function() { + "use strict"; + // start 2 node set + var name = "initialSyncReportProgress"; + var ports = allocatePorts(3); + var hostname = getHostName(); + + var replSet = new ReplSetTest({name: name, nodes: 2}); + replSet.startSet(); + + replSet.initiate({ + _id: name, + members: [ + {_id: 0, host: hostname + ":" + ports[0]}, + {_id: 1, host: hostname + ":" + ports[1]}, + ]}); + + var primary = replSet.getPrimary(); + var secondary = replSet.getSecondary(); + + // do a single insert + assert.writeOK(primary.getDB(name).foo.insert({x: 13})); + var optime = primary.getDB(name).getLastErrorObj(1)["lastOp"]; + + // start a new node and add it to the replset + var secondary2 = startMongodTest(ports[2], name, false, {replSet: name, oplogSize: 25}); + var config = replSet.getReplSetConfig(); + config.version = 2; + config.members.push({_id: 2, host: hostname + ":" + ports[2]}); + reconfig(replSet, config); + reconnect(secondary); + reconnect(secondary2); + + // confirm that the primary becomes aware of the new node's progress + assert.commandWorked(primary.getDB(name).runCommand({getLastError: 1, + w: 3, + wOpTime: optime, + wTimeout: 30*1000})); + replSet.stopSet(); +})(); diff --git a/src/mongo/db/repl/replication_coordinator_impl_heartbeat.cpp b/src/mongo/db/repl/replication_coordinator_impl_heartbeat.cpp index f80d2a5c1a7..0aeba145a60 100644 --- a/src/mongo/db/repl/replication_coordinator_impl_heartbeat.cpp +++ b/src/mongo/db/repl/replication_coordinator_impl_heartbeat.cpp @@ -182,10 +182,7 @@ namespace { invariant(targetIndex >= 0); SlaveInfo& slaveInfo = _slaveInfo[targetIndex]; - if (optime > slaveInfo.opTime && slaveInfo.rid.isSet()) { - // TODO(spencer): The second part of the above if-statement can be removed after 3.0 - // but for now, to maintain compatibility with 2.6, we can't record optimes for any - // nodes we haven't heard from via replSetUpdatePosition yet to associate an RID. + if (optime > slaveInfo.opTime) { _updateSlaveInfoOptime_inlock(&slaveInfo, optime); } } diff --git a/src/mongo/db/repl/replication_coordinator_impl_heartbeat_test.cpp b/src/mongo/db/repl/replication_coordinator_impl_heartbeat_test.cpp index 9008dbb9854..76561b75005 100644 --- a/src/mongo/db/repl/replication_coordinator_impl_heartbeat_test.cpp +++ b/src/mongo/db/repl/replication_coordinator_impl_heartbeat_test.cpp @@ -85,8 +85,7 @@ namespace { BSON("_id" << "mySet" << "version" << 3 << "members" << BSON_ARRAY(BSON("_id" << 1 << "host" << "h1:1") << - BSON("_id" << 2 << "host" << "h2:1") << - BSON("_id" << 3 << "host" << "h3:1")))); + BSON("_id" << 2 << "host" << "h2:1")))); init("mySet"); addSelf(HostAndPort("h2", 1)); const Date_t startDate = getNet()->now(); @@ -132,8 +131,35 @@ namespace { unittest::assertGet(getExternalState()->loadLocalConfigDocument(&txn)))); ASSERT_OK(storedConfig.validate()); ASSERT_EQUALS(3, storedConfig.getConfigVersion()); - ASSERT_EQUALS(3, storedConfig.getNumMembers()); - exitNetwork(); + ASSERT_EQUALS(2, storedConfig.getNumMembers()); + + // confirm heartbeats update replication progress map + const ReplicationExecutor::RemoteCommandRequest& request2 = noi->getRequest(); + ASSERT_EQUALS(HostAndPort("h1", 1), request2.target); + ReplSetHeartbeatArgs hbArgs2; + ASSERT_OK(hbArgs2.initialize(request2.cmdObj)); + + // process heartbeat response, updating optime + ReplSetHeartbeatResponse hbResp2; + hbResp2.setSetName("mySet"); + hbResp2.setState(MemberState::RS_SECONDARY); + hbResp2.noteReplSet(); + hbResp2.setVersion(rsConfig.getConfigVersion()); + hbResp2.setOpTime(OpTime(100,0)); + BSONObjBuilder responseBuilder2; + responseBuilder2 << "ok" << 1; + hbResp2.addToBSON(&responseBuilder2); + net->scheduleResponse(noi, startDate + 201, makeResponseStatus(responseBuilder2.obj())); + assertRunUntil(startDate + 201); + + // confirm replication progress has been updated by preparing an update position command + BSONObjBuilder updatePositionBuilder; + getReplCoord()->prepareReplSetUpdatePositionCommand(&updatePositionBuilder); + BSONObj updatePositionCommand = updatePositionBuilder.obj(); + log() << updatePositionCommand.toString(); + ASSERT_EQ(OpTime(100,0), + updatePositionCommand["optimes"].Array()[0].Obj()["optime"]._opTime()); + ASSERT_EQ(1, updatePositionCommand["optimes"].Array()[0].Obj()["memberId"].numberInt()); } TEST_F(ReplCoordHBTest, DoNotJoinReplSetIfNotAMember) { |