summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mongo/db/repl/topology_coordinator.cpp9
-rw-r--r--src/mongo/db/repl/topology_coordinator_v1_test.cpp16
2 files changed, 25 insertions, 0 deletions
diff --git a/src/mongo/db/repl/topology_coordinator.cpp b/src/mongo/db/repl/topology_coordinator.cpp
index 841b3d42b7b..24abcf15c68 100644
--- a/src/mongo/db/repl/topology_coordinator.cpp
+++ b/src/mongo/db/repl/topology_coordinator.cpp
@@ -287,6 +287,15 @@ HostAndPort TopologyCoordinator::chooseNewSyncSource(Date_t now,
<< "Cannot select a sync source because chaining is not allowed and we are primary";
_syncSource = HostAndPort();
return _syncSource;
+ } else if (_memberData.at(_currentPrimaryIndex).getLastAppliedOpTime() <
+ lastOpTimeFetched) {
+ LOG(1) << "Cannot select a sync source because chaining is not allowed and the primary "
+ "is behind me. Last oplog optime of primary "
+ << _currentPrimaryMember()->getHostAndPort() << ": "
+ << _memberData.at(_currentPrimaryIndex).getLastAppliedOpTime().toBSON()
+ << ", my last fetched oplog optime: " << lastOpTimeFetched.toBSON();
+ _syncSource = HostAndPort();
+ return _syncSource;
} else {
_syncSource = _currentPrimaryMember()->getHostAndPort();
log() << "chaining not allowed, choosing primary as sync source candidate: "
diff --git a/src/mongo/db/repl/topology_coordinator_v1_test.cpp b/src/mongo/db/repl/topology_coordinator_v1_test.cpp
index c3d88099458..249b59f1eea 100644
--- a/src/mongo/db/repl/topology_coordinator_v1_test.cpp
+++ b/src/mongo/db/repl/topology_coordinator_v1_test.cpp
@@ -633,6 +633,22 @@ TEST_F(TopoCoordTest, ChooseOnlyPrimaryAsSyncSourceWhenChainingIsDisallowed) {
Milliseconds(300));
ASSERT_EQUALS(2, getCurrentPrimaryIndex());
+ // h3 is primary, but its last applied isn't as up-to-date as ours, so it cannot be chosen
+ // as the sync source.
+ ASSERT_EQUALS(HostAndPort(),
+ getTopoCoord().chooseNewSyncSource(
+ now()++,
+ OpTime(Timestamp(10, 0), 0),
+ TopologyCoordinator::ChainingPreference::kUseConfiguration));
+ ASSERT_EQUALS(HostAndPort(), getTopoCoord().getSyncSourceAddress());
+
+ // Update the primary's position.
+ heartbeatFromMember(HostAndPort("h3"),
+ "rs0",
+ MemberState::RS_PRIMARY,
+ OpTime(Timestamp(10, 0), 0),
+ Milliseconds(300));
+
// h3 is primary and should be chosen as the sync source when we are not in catch-up mode,
// despite being further away than h2 and the primary (h3) being behind our most recently
// applied optime.