diff options
-rw-r--r-- | src/mongo/db/repl/member_heartbeat_data.h | 3 | ||||
-rw-r--r-- | src/mongo/db/repl/replication_coordinator_impl.cpp | 1 | ||||
-rw-r--r-- | src/mongo/db/repl/topology_coordinator.h | 1 | ||||
-rw-r--r-- | src/mongo/db/repl/topology_coordinator_impl.cpp | 51 | ||||
-rw-r--r-- | src/mongo/db/repl/topology_coordinator_impl_test.cpp | 28 | ||||
-rw-r--r-- | src/mongo/db/repl/topology_coordinator_impl_v1_test.cpp | 28 | ||||
-rw-r--r-- | src/mongo/shell/replsettest.js | 4 |
7 files changed, 72 insertions, 44 deletions
diff --git a/src/mongo/db/repl/member_heartbeat_data.h b/src/mongo/db/repl/member_heartbeat_data.h index e64dcb4ef67..0f5dacd9081 100644 --- a/src/mongo/db/repl/member_heartbeat_data.h +++ b/src/mongo/db/repl/member_heartbeat_data.h @@ -71,6 +71,9 @@ public: OpTime getAppliedOpTime() const { return _lastResponse.getAppliedOpTime(); } + OpTime getDurableOpTime() const { + return _lastResponse.hasDurableOpTime() ? _lastResponse.getDurableOpTime() : OpTime(); + } int getConfigVersion() const { return _lastResponse.getConfigVersion(); } diff --git a/src/mongo/db/repl/replication_coordinator_impl.cpp b/src/mongo/db/repl/replication_coordinator_impl.cpp index 6e2b63bb1da..1157a7b07fb 100644 --- a/src/mongo/db/repl/replication_coordinator_impl.cpp +++ b/src/mongo/db/repl/replication_coordinator_impl.cpp @@ -1933,6 +1933,7 @@ Status ReplicationCoordinatorImpl::processReplSetGetStatus(BSONObjBuilder* respo _replExecutor.now(), static_cast<unsigned>(time(0) - serverGlobalParams.started), getMyLastAppliedOpTime(), + getMyLastDurableOpTime(), getLastCommittedOpTime(), getCurrentCommittedSnapshotOpTime()}, response, diff --git a/src/mongo/db/repl/topology_coordinator.h b/src/mongo/db/repl/topology_coordinator.h index b0462f9e838..e6217295b95 100644 --- a/src/mongo/db/repl/topology_coordinator.h +++ b/src/mongo/db/repl/topology_coordinator.h @@ -248,6 +248,7 @@ public: Date_t now; unsigned selfUptime; const OpTime& lastOpApplied; + const OpTime& lastOpDurable; const OpTime& lastCommittedOpTime; const OpTime& readConcernMajorityOpTime; }; diff --git a/src/mongo/db/repl/topology_coordinator_impl.cpp b/src/mongo/db/repl/topology_coordinator_impl.cpp index 9f754840b8e..c03a883010d 100644 --- a/src/mongo/db/repl/topology_coordinator_impl.cpp +++ b/src/mongo/db/repl/topology_coordinator_impl.cpp @@ -96,6 +96,16 @@ bool _hasOnlyAuthErrorUpHeartbeats(const std::vector<MemberHeartbeatData>& hbdat return foundAuthError; } +void appendOpTime(BSONObjBuilder* bob, + const char* elemName, + const OpTime& opTime, + const long long pv) { + if (pv == 1) { + opTime.append(bob, elemName); + } else { + bob->append(elemName, opTime.getTimestamp()); + } +} } // namespace void PingStats::start(Date_t now) { @@ -1511,6 +1521,7 @@ void TopologyCoordinatorImpl::prepareStatusResponse(const ReplicationExecutor::C const MemberState myState = getMemberState(); const Date_t now = rsStatusArgs.now; const OpTime& lastOpApplied = rsStatusArgs.lastOpApplied; + const OpTime& lastOpDurable = rsStatusArgs.lastOpDurable; if (_selfIndex == -1) { // We're REMOVED or have an invalid config @@ -1518,14 +1529,7 @@ void TopologyCoordinatorImpl::prepareStatusResponse(const ReplicationExecutor::C response->append("stateStr", myState.toString()); response->append("uptime", rsStatusArgs.selfUptime); - if (_rsConfig.getProtocolVersion() == 1) { - BSONObjBuilder opTime(response->subobjStart("optime")); - opTime.append("ts", lastOpApplied.getTimestamp()); - opTime.append("t", lastOpApplied.getTerm()); - opTime.done(); - } else { - response->append("optime", lastOpApplied.getTimestamp()); - } + appendOpTime(response, "optime", lastOpApplied, _rsConfig.getProtocolVersion()); response->appendDate("optimeDate", Date_t::fromDurationSinceEpoch(Seconds(lastOpApplied.getSecs()))); @@ -1553,15 +1557,7 @@ void TopologyCoordinatorImpl::prepareStatusResponse(const ReplicationExecutor::C bb.append("stateStr", myState.toString()); bb.append("uptime", rsStatusArgs.selfUptime); if (!_selfConfig().isArbiter()) { - if (_rsConfig.getProtocolVersion() == 1) { - BSONObjBuilder opTime(bb.subobjStart("optime")); - opTime.append("ts", lastOpApplied.getTimestamp()); - opTime.append("t", lastOpApplied.getTerm()); - opTime.done(); - } else { - bb.append("optime", lastOpApplied.getTimestamp()); - } - + appendOpTime(&bb, "optime", lastOpApplied, _rsConfig.getProtocolVersion()); bb.appendDate("optimeDate", Date_t::fromDurationSinceEpoch(Seconds(lastOpApplied.getSecs()))); } @@ -1608,18 +1604,16 @@ void TopologyCoordinatorImpl::prepareStatusResponse(const ReplicationExecutor::C it->getUpSince() != Date_t() ? durationCount<Seconds>(now - it->getUpSince()) : 0)); bb.append("uptime", uptime); if (!itConfig.isArbiter()) { - if (_rsConfig.getProtocolVersion() == 1) { - BSONObjBuilder opTime(bb.subobjStart("optime")); - opTime.append("ts", it->getAppliedOpTime().getTimestamp()); - opTime.append("t", it->getAppliedOpTime().getTerm()); - opTime.done(); - } else { - bb.append("optime", it->getAppliedOpTime().getTimestamp()); - } + appendOpTime(&bb, "optime", it->getAppliedOpTime(), _rsConfig.getProtocolVersion()); + appendOpTime( + &bb, "optimeDurable", it->getDurableOpTime(), _rsConfig.getProtocolVersion()); bb.appendDate( "optimeDate", Date_t::fromDurationSinceEpoch(Seconds(it->getAppliedOpTime().getSecs()))); + bb.appendDate( + "optimeDurableDate", + Date_t::fromDurationSinceEpoch(Seconds(it->getDurableOpTime().getSecs()))); } bb.appendDate("lastHeartbeat", it->getLastHeartbeat()); bb.appendDate("lastHeartbeatRecv", it->getLastHeartbeatRecv()); @@ -1669,12 +1663,17 @@ void TopologyCoordinatorImpl::prepareStatusResponse(const ReplicationExecutor::C response->append("heartbeatIntervalMillis", durationCount<Milliseconds>(_rsConfig.getHeartbeatInterval())); + // New optimes, to hold them all. BSONObjBuilder optimes; rsStatusArgs.lastCommittedOpTime.append(&optimes, "lastCommittedOpTime"); if (!rsStatusArgs.readConcernMajorityOpTime.isNull()) { rsStatusArgs.readConcernMajorityOpTime.append(&optimes, "readConcernMajorityOpTime"); } - response->append("OpTimes", optimes.obj()); + + appendOpTime(&optimes, "appliedOpTime", lastOpApplied, _rsConfig.getProtocolVersion()); + appendOpTime(&optimes, "durableOpTime", lastOpDurable, _rsConfig.getProtocolVersion()); + response->append("optimes", optimes.obj()); + response->append("members", membersOut); *result = Status::OK(); diff --git a/src/mongo/db/repl/topology_coordinator_impl_test.cpp b/src/mongo/db/repl/topology_coordinator_impl_test.cpp index 1a3916c77ae..27711e3fcf7 100644 --- a/src/mongo/db/repl/topology_coordinator_impl_test.cpp +++ b/src/mongo/db/repl/topology_coordinator_impl_test.cpp @@ -1321,6 +1321,7 @@ TEST_F(TopoCoordTest, ReplSetGetStatus) { Date_t curTime = heartbeatTime + uptimeSecs; Timestamp electionTime(1, 2); OpTime oplogProgress(Timestamp(3, 4), 0); + OpTime oplogDurable(Timestamp(3, 4), 1); OpTime lastCommittedOpTime(Timestamp(2, 3), -1); OpTime readConcernMajorityOpTime(Timestamp(4, 5), -1); std::string setName = "mySet"; @@ -1331,7 +1332,7 @@ TEST_F(TopoCoordTest, ReplSetGetStatus) { hb.setElectionTime(electionTime); hb.setHbMsg("READY"); hb.setAppliedOpTime(oplogProgress); - hb.setDurableOpTime(oplogProgress); + hb.setDurableOpTime(oplogDurable); StatusWith<ReplSetHeartbeatResponse> hbResponseGood = StatusWith<ReplSetHeartbeatResponse>(hb); updateConfig( @@ -1376,6 +1377,7 @@ TEST_F(TopoCoordTest, ReplSetGetStatus) { curTime, static_cast<unsigned>(durationCount<Seconds>(uptimeSecs)), oplogProgress, + oplogDurable, lastCommittedOpTime, readConcernMajorityOpTime}, &statusBuilder, @@ -1386,9 +1388,14 @@ TEST_F(TopoCoordTest, ReplSetGetStatus) { // Test results for all non-self members ASSERT_EQUALS(setName, rsStatus["set"].String()); ASSERT_EQUALS(curTime.asInt64(), rsStatus["date"].Date().asInt64()); - ASSERT_EQUALS(lastCommittedOpTime.toBSON(), rsStatus["OpTimes"]["lastCommittedOpTime"].Obj()); - ASSERT_EQUALS(readConcernMajorityOpTime.toBSON(), - rsStatus["OpTimes"]["readConcernMajorityOpTime"].Obj()); + ASSERT_EQUALS(lastCommittedOpTime.toBSON(), rsStatus["optimes"]["lastCommittedOpTime"].Obj()); + { + const auto optimes = rsStatus["optimes"].Obj(); + ASSERT_EQUALS(readConcernMajorityOpTime.toBSON(), + optimes["readConcernMajorityOpTime"].Obj()); + ASSERT_EQUALS(oplogProgress.getTimestamp(), optimes["appliedOpTime"].timestamp()); + ASSERT_EQUALS((oplogDurable).getTimestamp(), optimes["durableOpTime"].timestamp()); + } std::vector<BSONElement> memberArray = rsStatus["members"].Array(); ASSERT_EQUALS(4U, memberArray.size()); BSONObj member0Status = memberArray[0].Obj(); @@ -1486,6 +1493,7 @@ TEST_F(TopoCoordTest, NodeReturnsInvalidReplicaSetConfigInResponseToGetStatusWhe curTime, static_cast<unsigned>(durationCount<Seconds>(uptimeSecs)), oplogProgress, + oplogProgress, OpTime(), OpTime()}, &statusBuilder, @@ -2183,6 +2191,7 @@ public: TopologyCoordinator::ReplSetStatusArgs{_firstRequestDate + Milliseconds(4000), 10, OpTime(Timestamp(100, 0), 0), + OpTime(Timestamp(100, 0), 0), OpTime(), OpTime()}, &statusBuilder, @@ -2196,9 +2205,9 @@ public: ASSERT_EQUALS(1, member1Status["health"].Double()); ASSERT_EQUALS(Timestamp(0, 0), - Timestamp(rsStatus["OpTimes"]["lastCommittedOpTime"]["ts"].timestampValue())); - ASSERT_EQUALS(-1LL, rsStatus["OpTimes"]["lastCommittedOpTime"]["t"].numberLong()); - ASSERT_FALSE(rsStatus["OpTimes"].Obj().hasField("readConcernMajorityOpTime")); + Timestamp(rsStatus["optimes"]["lastCommittedOpTime"]["ts"].timestampValue())); + ASSERT_EQUALS(-1LL, rsStatus["optimes"]["lastCommittedOpTime"]["t"].numberLong()); + ASSERT_FALSE(rsStatus["optimes"].Obj().hasField("readConcernMajorityOpTime")); } Date_t firstRequestDate() { @@ -2246,6 +2255,7 @@ public: TopologyCoordinator::ReplSetStatusArgs{firstRequestDate() + Seconds(4), 10, OpTime(Timestamp(100, 0), 0), + OpTime(Timestamp(100, 0), 0), OpTime(), OpTime()}, &statusBuilder, @@ -2562,6 +2572,7 @@ TEST_F(HeartbeatResponseTestTwoRetries, NodeDoesNotRetryHeartbeatsAfterFailingTw TopologyCoordinator::ReplSetStatusArgs{firstRequestDate() + Milliseconds(4900), 10, OpTime(Timestamp(100, 0), 0), + OpTime(Timestamp(100, 0), 0), OpTime(), OpTime()}, &statusBuilder, @@ -2803,6 +2814,7 @@ TEST_F(HeartbeatResponseTestTwoRetries, TopologyCoordinator::ReplSetStatusArgs{firstRequestDate() + Milliseconds(7000), 600, OpTime(Timestamp(100, 0), 0), + OpTime(Timestamp(100, 0), 0), OpTime(), OpTime()}, &statusBuilder, @@ -4255,7 +4267,7 @@ TEST_F(ShutdownInProgressTest, NodeReturnsShutDownInProgressWhenGetReplSetStatus BSONObjBuilder response; getTopoCoord().prepareStatusResponse( cbData(), - TopologyCoordinator::ReplSetStatusArgs{Date_t(), 0, OpTime(), OpTime(), OpTime()}, + TopologyCoordinator::ReplSetStatusArgs{Date_t(), 0, OpTime(), OpTime(), OpTime(), OpTime()}, &response, &result); ASSERT_EQUALS(ErrorCodes::ShutdownInProgress, result); diff --git a/src/mongo/db/repl/topology_coordinator_impl_v1_test.cpp b/src/mongo/db/repl/topology_coordinator_impl_v1_test.cpp index 8307fea5318..70cbf8b97aa 100644 --- a/src/mongo/db/repl/topology_coordinator_impl_v1_test.cpp +++ b/src/mongo/db/repl/topology_coordinator_impl_v1_test.cpp @@ -1314,6 +1314,7 @@ TEST_F(TopoCoordTest, ReplSetGetStatus) { Date_t curTime = heartbeatTime + uptimeSecs; Timestamp electionTime(1, 2); OpTime oplogProgress(Timestamp(3, 4), 2); + OpTime oplogDurable(Timestamp(3, 4), 1); OpTime lastCommittedOpTime(Timestamp(2, 3), 6); OpTime readConcernMajorityOpTime(Timestamp(4, 5), 7); std::string setName = "mySet"; @@ -1323,7 +1324,7 @@ TEST_F(TopoCoordTest, ReplSetGetStatus) { hb.setState(MemberState::RS_SECONDARY); hb.setElectionTime(electionTime); hb.setHbMsg("READY"); - hb.setDurableOpTime(oplogProgress); + hb.setDurableOpTime(oplogDurable); hb.setAppliedOpTime(oplogProgress); StatusWith<ReplSetHeartbeatResponse> hbResponseGood = StatusWith<ReplSetHeartbeatResponse>(hb); @@ -1369,6 +1370,7 @@ TEST_F(TopoCoordTest, ReplSetGetStatus) { curTime, static_cast<unsigned>(durationCount<Seconds>(uptimeSecs)), oplogProgress, + oplogDurable, lastCommittedOpTime, readConcernMajorityOpTime}, &statusBuilder, @@ -1379,9 +1381,14 @@ TEST_F(TopoCoordTest, ReplSetGetStatus) { // Test results for all non-self members ASSERT_EQUALS(setName, rsStatus["set"].String()); ASSERT_EQUALS(curTime.asInt64(), rsStatus["date"].Date().asInt64()); - ASSERT_EQUALS(lastCommittedOpTime.toBSON(), rsStatus["OpTimes"]["lastCommittedOpTime"].Obj()); - ASSERT_EQUALS(readConcernMajorityOpTime.toBSON(), - rsStatus["OpTimes"]["readConcernMajorityOpTime"].Obj()); + ASSERT_EQUALS(lastCommittedOpTime.toBSON(), rsStatus["optimes"]["lastCommittedOpTime"].Obj()); + { + const auto optimes = rsStatus["optimes"].Obj(); + ASSERT_EQUALS(readConcernMajorityOpTime.toBSON(), + optimes["readConcernMajorityOpTime"].Obj()); + ASSERT_EQUALS(oplogProgress.toBSON(), optimes["appliedOpTime"].Obj()); + ASSERT_EQUALS((oplogDurable).toBSON(), optimes["durableOpTime"].Obj()); + } std::vector<BSONElement> memberArray = rsStatus["members"].Array(); ASSERT_EQUALS(4U, memberArray.size()); BSONObj member0Status = memberArray[0].Obj(); @@ -1479,6 +1486,7 @@ TEST_F(TopoCoordTest, NodeReturnsInvalidReplicaSetConfigInResponseToGetStatusWhe curTime, static_cast<unsigned>(durationCount<Seconds>(uptimeSecs)), oplogProgress, + oplogProgress, OpTime(), OpTime()}, &statusBuilder, @@ -1539,7 +1547,7 @@ TEST_F(ShutdownInProgressTest, NodeReturnsShutDownInProgressWhenGetReplSetStatus BSONObjBuilder response; getTopoCoord().prepareStatusResponse( cbData(), - TopologyCoordinator::ReplSetStatusArgs{Date_t(), 0, OpTime(), OpTime(), OpTime()}, + TopologyCoordinator::ReplSetStatusArgs{Date_t(), 0, OpTime(), OpTime(), OpTime(), OpTime()}, &response, &result); ASSERT_EQUALS(ErrorCodes::ShutdownInProgress, result); @@ -4047,6 +4055,7 @@ public: TopologyCoordinator::ReplSetStatusArgs{_firstRequestDate + Milliseconds(4000), 10, OpTime(Timestamp(100, 0), 0), + OpTime(Timestamp(100, 0), 0), OpTime(), OpTime()}, &statusBuilder, @@ -4060,9 +4069,9 @@ public: ASSERT_EQUALS(1, member1Status["health"].Double()); ASSERT_EQUALS(Timestamp(0, 0), - Timestamp(rsStatus["OpTimes"]["lastCommittedOpTime"]["ts"].timestampValue())); - ASSERT_EQUALS(-1LL, rsStatus["OpTimes"]["lastCommittedOpTime"]["t"].numberLong()); - ASSERT_FALSE(rsStatus["OpTimes"].Obj().hasField("readConcernMajorityOpTime")); + Timestamp(rsStatus["optimes"]["lastCommittedOpTime"]["ts"].timestampValue())); + ASSERT_EQUALS(-1LL, rsStatus["optimes"]["lastCommittedOpTime"]["t"].numberLong()); + ASSERT_FALSE(rsStatus["optimes"].Obj().hasField("readConcernMajorityOpTime")); } Date_t firstRequestDate() { @@ -4130,6 +4139,7 @@ public: TopologyCoordinator::ReplSetStatusArgs{firstRequestDate() + Seconds(4), 10, OpTime(Timestamp(100, 0), 0), + OpTime(Timestamp(100, 0), 0), OpTime(), OpTime()}, &statusBuilder, @@ -4178,6 +4188,7 @@ TEST_F(HeartbeatResponseTestTwoRetriesV1, NodeDoesNotRetryHeartbeatsAfterFailing TopologyCoordinator::ReplSetStatusArgs{firstRequestDate() + Milliseconds(4900), 10, OpTime(Timestamp(100, 0), 0), + OpTime(Timestamp(100, 0), 0), OpTime(), OpTime()}, &statusBuilder, @@ -4238,6 +4249,7 @@ TEST_F(HeartbeatResponseTestTwoRetriesV1, HeartbeatThreeNonconsecutiveFailures) TopologyCoordinator::ReplSetStatusArgs{firstRequestDate() + Milliseconds(7000), 600, OpTime(Timestamp(100, 0), 0), + OpTime(Timestamp(100, 0), 0), OpTime(), OpTime()}, &statusBuilder, diff --git a/src/mongo/shell/replsettest.js b/src/mongo/shell/replsettest.js index c9a232924e2..9fc699a1ca1 100644 --- a/src/mongo/shell/replsettest.js +++ b/src/mongo/shell/replsettest.js @@ -311,7 +311,7 @@ var ReplSetTest = function(opts) { function _getLastCommittedOpTime(conn) { var replSetStatus = assert.commandWorked(conn.getDB("admin").runCommand({replSetGetStatus: 1})); - return replSetStatus.OpTimes.lastCommittedOpTime || { + return (replSetStatus.OpTimes || replSetStatus.optimes).lastCommittedOpTime || { ts: Timestamp(0, 0), t: NumberLong(0) }; @@ -326,7 +326,7 @@ var ReplSetTest = function(opts) { function _getReadConcernMajorityOpTime(conn) { var replSetStatus = assert.commandWorked(conn.getDB("admin").runCommand({replSetGetStatus: 1})); - return replSetStatus.OpTimes.readConcernMajorityOpTime || { + return (replSetStatus.OpTimes || replSetStatus.optimes).readConcernMajorityOpTime || { ts: Timestamp(0, 0), t: NumberLong(0) }; |