diff options
Diffstat (limited to 'src/mongo/db/repl/topology_coordinator_v1_test.cpp')
-rw-r--r-- | src/mongo/db/repl/topology_coordinator_v1_test.cpp | 95 |
1 files changed, 93 insertions, 2 deletions
diff --git a/src/mongo/db/repl/topology_coordinator_v1_test.cpp b/src/mongo/db/repl/topology_coordinator_v1_test.cpp index dc403532871..f6a8adaa65b 100644 --- a/src/mongo/db/repl/topology_coordinator_v1_test.cpp +++ b/src/mongo/db/repl/topology_coordinator_v1_test.cpp @@ -221,9 +221,14 @@ protected: OplogQueryMetadata makeOplogQueryMetadata(OpTime lastAppliedOpTime = OpTime(), int primaryIndex = -1, int syncSourceIndex = -1, + std::string syncSourceHost = "", Date_t lastCommittedWall = Date_t()) { - return OplogQueryMetadata( - {OpTime(), lastCommittedWall}, lastAppliedOpTime, -1, primaryIndex, syncSourceIndex); + return OplogQueryMetadata({OpTime(), lastCommittedWall}, + lastAppliedOpTime, + -1, + primaryIndex, + syncSourceIndex, + syncSourceHost); } HeartbeatResponseAction receiveUpHeartbeat(const HostAndPort& member, @@ -3764,6 +3769,92 @@ TEST_F(HeartbeatResponseTestV1, HostAndPort("host2"), makeReplSetMetadata(newerThanLastOpTimeApplied), boost::none, now())); } +TEST_F(HeartbeatResponseTestV1, ShouldChangeSyncSourceWhenSyncSourceFormsCycleAndWeArePrimary) { + // In this test, the TopologyCoordinator will tell us change our sync source away from "host2" + // when it is not ahead of us and it selects us to be its sync source, forming a sync source + // cycle and we are currently in primary catchup. + setSelfMemberState(MemberState::RS_PRIMARY); + OpTime election = OpTime(); + OpTime syncSourceOpTime = OpTime(Timestamp(400, 0), 0); + + // Set lastOpTimeFetched to be same as the sync source's OpTime. + OpTime lastOpTimeFetched = OpTime(Timestamp(400, 0), 0); + setMyOpTime(lastOpTimeFetched); + + // Show we like host2 while it is not syncing from us. + HeartbeatResponseAction nextAction = receiveUpHeartbeat( + HostAndPort("host2"), "rs0", MemberState::RS_SECONDARY, election, syncSourceOpTime); + ASSERT_NO_ACTION(nextAction.getAction()); + ASSERT_FALSE(getTopoCoord().shouldChangeSyncSource( + HostAndPort("host2"), + makeReplSetMetadata(OpTime() /* visibleOpTime */, false /* isPrimary */), + makeOplogQueryMetadata(syncSourceOpTime, + -1 /* primaryIndex */, + 2 /* syncSourceIndex */, + "host3:27017" /* syncSourceHost */), + now())); + + // Show that we also like host2 while we are not primary. + nextAction = receiveUpHeartbeat( + HostAndPort("host2"), "rs0", MemberState::RS_SECONDARY, election, syncSourceOpTime); + ASSERT_NO_ACTION(nextAction.getAction()); + getTopoCoord().setPrimaryIndex(2); + ASSERT_FALSE(getTopoCoord().shouldChangeSyncSource( + HostAndPort("host2"), + makeReplSetMetadata(OpTime() /* visibleOpTime */, false /* isPrimary */), + // Sync source is also syncing from us. + makeOplogQueryMetadata(syncSourceOpTime, + -1 /* primaryIndex */, + 0 /* syncSourceIndex */, + "host1:27017" /* syncSourceHost */), + now())); + + // Show that we also like host2 while it has some progress beyond our own. + getTopoCoord().setPrimaryIndex(0); + OpTime olderThanSyncSourceOpTime = OpTime(Timestamp(300, 0), 0); + topoCoordSetMyLastAppliedOpTime(olderThanSyncSourceOpTime, now(), true); + nextAction = receiveUpHeartbeat( + HostAndPort("host2"), "rs0", MemberState::RS_SECONDARY, election, syncSourceOpTime); + ASSERT_NO_ACTION(nextAction.getAction()); + ASSERT_FALSE(getTopoCoord().shouldChangeSyncSource( + HostAndPort("host2"), + makeReplSetMetadata(OpTime() /* visibleOpTime */, false /* isPrimary */), + // Sync source is also syncing from us. + makeOplogQueryMetadata(syncSourceOpTime, + -1 /* primaryIndex */, + 0 /* syncSourceIndex */, + "host1:27017" /* syncSourceHost */), + now())); + + // Show that we do not like host2 it forms a sync source selection cycle with us and we + // are primary and it lacks progress beyond our own. + setMyOpTime(lastOpTimeFetched); + nextAction = receiveUpHeartbeat( + HostAndPort("host2"), "rs0", MemberState::RS_SECONDARY, election, syncSourceOpTime); + ASSERT_NO_ACTION(nextAction.getAction()); + ASSERT_TRUE(getTopoCoord().shouldChangeSyncSource( + HostAndPort("host2"), + makeReplSetMetadata(OpTime() /* visibleOpTime */, false /* isPrimary */), + // Sync source is also syncing from us. + makeOplogQueryMetadata(syncSourceOpTime, + -1 /* primaryIndex */, + 0 /* syncSourceIndex */, + "host1:27017" /* syncSourceHost */), + now())); + + // Show that we still do not like it when syncSourceHost is not set, but we can rely on + // syncSourceIndex to decide if a sync source selection cycle has been formed. + nextAction = receiveUpHeartbeat( + HostAndPort("host2"), "rs0", MemberState::RS_SECONDARY, election, syncSourceOpTime); + ASSERT_NO_ACTION(nextAction.getAction()); + ASSERT_TRUE(getTopoCoord().shouldChangeSyncSource( + HostAndPort("host2"), + makeReplSetMetadata(OpTime() /* visibleOpTime */, false /* isPrimary */), + // Sync source is also syncing from us. + makeOplogQueryMetadata(syncSourceOpTime, -1 /* primaryIndex */, 0 /* syncSourceIndex */), + now())); +} + TEST_F(HeartbeatResponseTestV1, ShouldNotChangeSyncSourceWhenFresherMemberIsDown) { // In this test, the TopologyCoordinator should not tell us to change sync sources away from // "host2" and to "host3" despite "host2" being more than maxSyncSourceLagSecs(30) behind |