summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXuerui Fa <xuerui.fa@mongodb.com>2020-05-18 18:06:04 -0400
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-05-18 22:29:48 +0000
commitb3148d848547358244f055b25cbabe147f244a43 (patch)
tree03813b26ee13aaa1d1b10e097f34bf6bb2dc464b
parent2153f72a96906ec4ca30e45fc21f68008aa08d73 (diff)
downloadmongo-b3148d848547358244f055b25cbabe147f244a43.tar.gz
SERVER-47454: Stop re-evaluting sync source if max num changes was exceeded
-rw-r--r--src/mongo/db/repl/topology_coordinator.cpp17
-rw-r--r--src/mongo/db/repl/topology_coordinator.h2
-rw-r--r--src/mongo/db/repl/topology_coordinator_v1_test.cpp51
3 files changed, 63 insertions, 7 deletions
diff --git a/src/mongo/db/repl/topology_coordinator.cpp b/src/mongo/db/repl/topology_coordinator.cpp
index bbe49703822..5159d57b1f7 100644
--- a/src/mongo/db/repl/topology_coordinator.cpp
+++ b/src/mongo/db/repl/topology_coordinator.cpp
@@ -3033,12 +3033,11 @@ bool TopologyCoordinator::shouldChangeSyncSource(const HostAndPort& currentSourc
return false;
}
-bool TopologyCoordinator::shouldChangeSyncSourceDueToPingTime(
- const HostAndPort& currentSource,
- const MemberState& memberState,
- const OpTime& lastOpTimeFetched,
- Date_t now,
- const ReadPreference readPreference) const {
+bool TopologyCoordinator::shouldChangeSyncSourceDueToPingTime(const HostAndPort& currentSource,
+ const MemberState& memberState,
+ const OpTime& lastOpTimeFetched,
+ Date_t now,
+ const ReadPreference readPreference) {
// If the ping time for currentSource is longer than 'changeSyncSourceThresholdMillis' and we
// find an eligible sync source that has a ping time shorter than
// 'changeSyncSourceThresholdMillis', return true.
@@ -3054,6 +3053,12 @@ bool TopologyCoordinator::shouldChangeSyncSourceDueToPingTime(
return false;
}
+ // If we have already changed sync sources more than 'maxNumSyncSourceChangesPerHour' in the
+ // past hour, do not re-evaluate our sync source.
+ if (_recentSyncSourceChanges.changedTooOftenRecently(now)) {
+ return false;
+ }
+
const bool primaryOnly = (readPreference == ReadPreference::PrimaryOnly);
const bool primaryPreferredAndAlreadySyncing =
(readPreference == ReadPreference::PrimaryPreferred &&
diff --git a/src/mongo/db/repl/topology_coordinator.h b/src/mongo/db/repl/topology_coordinator.h
index 56ec2fd881b..87aacd5aa12 100644
--- a/src/mongo/db/repl/topology_coordinator.h
+++ b/src/mongo/db/repl/topology_coordinator.h
@@ -279,7 +279,7 @@ public:
const MemberState& memberState,
const OpTime& lastOpTimeFetched,
Date_t now,
- const ReadPreference readPreference) const;
+ const ReadPreference readPreference);
/**
* Sets the reported mode of this node to one of RS_SECONDARY, RS_STARTUP2, RS_ROLLBACK or
diff --git a/src/mongo/db/repl/topology_coordinator_v1_test.cpp b/src/mongo/db/repl/topology_coordinator_v1_test.cpp
index 302de461df1..d28062c4fb6 100644
--- a/src/mongo/db/repl/topology_coordinator_v1_test.cpp
+++ b/src/mongo/db/repl/topology_coordinator_v1_test.cpp
@@ -4362,6 +4362,57 @@ TEST_F(ReevalSyncSourceTest, NoChangeWhenNodeNotFoundInConfig) {
ReadPreference::Nearest));
}
+TEST_F(ReevalSyncSourceTest, NoChangeWhenChangedTooManyTimesRecently) {
+ getTopoCoord().setPing_forTest(HostAndPort("host2"), pingTimeAboveThreshold);
+ getTopoCoord().setPing_forTest(HostAndPort("host3"), pingTimeBelowThreshold);
+
+ auto recentSyncSourceChanges = getTopoCoord().getRecentSyncSourceChanges_forTest();
+
+ auto first = Date_t::now();
+ recentSyncSourceChanges->addNewEntry(first);
+
+ auto second = Date_t::now();
+ recentSyncSourceChanges->addNewEntry(second);
+
+ auto third = Date_t::now();
+ recentSyncSourceChanges->addNewEntry(third);
+
+ assertTimesEqual({first, second, third}, recentSyncSourceChanges->getChanges_forTest());
+ ASSERT_TRUE(recentSyncSourceChanges->changedTooOftenRecently(now()));
+
+ // We should not change sync sources because we have already changed sync sources more than
+ // 'maxNumSyncSourceChangesPerHour' in the past hour.
+ ASSERT_FALSE(getTopoCoord().shouldChangeSyncSourceDueToPingTime(HostAndPort("host2"),
+ MemberState::RS_SECONDARY,
+ lastOpTimeFetched,
+ now(),
+ ReadPreference::Nearest));
+}
+
+TEST_F(ReevalSyncSourceTest, ChangeWhenHaveNotChangedTooManyTimesRecently) {
+ getTopoCoord().setPing_forTest(HostAndPort("host2"), pingTimeAboveThreshold);
+ getTopoCoord().setPing_forTest(HostAndPort("host3"), pingTimeBelowThreshold);
+
+ auto recentSyncSourceChanges = getTopoCoord().getRecentSyncSourceChanges_forTest();
+
+ auto first = Date_t::now();
+ recentSyncSourceChanges->addNewEntry(first);
+
+ auto second = Date_t::now();
+ recentSyncSourceChanges->addNewEntry(second);
+
+ assertTimesEqual({first, second}, recentSyncSourceChanges->getChanges_forTest());
+ ASSERT_FALSE(recentSyncSourceChanges->changedTooOftenRecently(now()));
+
+ // We should allow changing sync sources because we have not yet changed sync sources more times
+ // than 'maxNumSyncSourceChangesPerHour' in the past hour.
+ ASSERT_TRUE(getTopoCoord().shouldChangeSyncSourceDueToPingTime(HostAndPort("host2"),
+ MemberState::RS_SECONDARY,
+ lastOpTimeFetched,
+ now(),
+ ReadPreference::Nearest));
+}
+
class HeartbeatResponseReconfigTestV1 : public TopoCoordTest {
public:
virtual void setUp() {