diff options
author | William Schultz <william.schultz@mongodb.com> | 2017-06-02 16:58:37 -0400 |
---|---|---|
committer | Benety Goh <benety@mongodb.com> | 2017-06-27 16:09:17 -0400 |
commit | d915259708b79fd7394aa8de9779520710d2bbe7 (patch) | |
tree | 4d606c93c16e070ceb0b2d226e8a24ac81a60c6f | |
parent | c55eb86ef46ee7aede3b1e2a5d184a7df4bfb5b5 (diff) | |
download | mongo-d915259708b79fd7394aa8de9779520710d2bbe7.tar.gz |
SERVER-28677 InitialSyncer should reset optimes on every attempt
(cherry picked from commit 1c56f5dd262111f921203d403f54fedb18772792)
-rw-r--r-- | src/mongo/db/repl/initial_syncer.cpp | 5 | ||||
-rw-r--r-- | src/mongo/db/repl/initial_syncer.h | 4 | ||||
-rw-r--r-- | src/mongo/db/repl/initial_syncer_test.cpp | 26 | ||||
-rw-r--r-- | src/mongo/db/repl/replication_coordinator_impl.cpp | 1 |
4 files changed, 36 insertions, 0 deletions
diff --git a/src/mongo/db/repl/initial_syncer.cpp b/src/mongo/db/repl/initial_syncer.cpp index 1131719c13c..e9a920bb37b 100644 --- a/src/mongo/db/repl/initial_syncer.cpp +++ b/src/mongo/db/repl/initial_syncer.cpp @@ -230,6 +230,7 @@ InitialSyncer::InitialSyncer( uassert(ErrorCodes::BadValue, "invalid storage interface", _storage); uassert(ErrorCodes::BadValue, "invalid getMyLastOptime function", _opts.getMyLastOptime); uassert(ErrorCodes::BadValue, "invalid setMyLastOptime function", _opts.setMyLastOptime); + uassert(ErrorCodes::BadValue, "invalid resetOptimes function", _opts.resetOptimes); uassert(ErrorCodes::BadValue, "invalid getSlaveDelay function", _opts.getSlaveDelay); uassert(ErrorCodes::BadValue, "invalid sync source selector", _opts.syncSourceSelector); uassert(ErrorCodes::BadValue, "callback function cannot be null", _onCompletion); @@ -460,8 +461,12 @@ void InitialSyncer::_startInitialSyncAttemptCallback( LOG(2) << "Resetting sync source so a new one can be chosen for this initial sync attempt."; _syncSource = HostAndPort(); + // Reset all optimes before a new initial sync attempt. + _opts.resetOptimes(); _lastApplied = {}; _lastFetched = {}; + + // Clear the oplog buffer. _oplogBuffer->clear(makeOpCtx().get()); // Get sync source. diff --git a/src/mongo/db/repl/initial_syncer.h b/src/mongo/db/repl/initial_syncer.h index 0f3ac5857ce..6faeddb385e 100644 --- a/src/mongo/db/repl/initial_syncer.h +++ b/src/mongo/db/repl/initial_syncer.h @@ -92,6 +92,9 @@ struct InitialSyncerOptions { /** Function to update optime of last operation applied on this node */ using SetMyLastOptimeFn = stdx::function<void(const OpTime&)>; + /** Function to reset all optimes on this node (e.g. applied & durable). */ + using ResetOptimesFn = stdx::function<void()>; + /** Function to sets this node into a specific follower mode. */ using SetFollowerModeFn = stdx::function<bool(const MemberState&)>; @@ -120,6 +123,7 @@ struct InitialSyncerOptions { GetMyLastOptimeFn getMyLastOptime; SetMyLastOptimeFn setMyLastOptime; + ResetOptimesFn resetOptimes; GetSlaveDelayFn getSlaveDelay; SyncSourceSelector* syncSourceSelector = nullptr; diff --git a/src/mongo/db/repl/initial_syncer_test.cpp b/src/mongo/db/repl/initial_syncer_test.cpp index 9c5049fc024..77be70c3bfe 100644 --- a/src/mongo/db/repl/initial_syncer_test.cpp +++ b/src/mongo/db/repl/initial_syncer_test.cpp @@ -331,6 +331,7 @@ protected: options.initialSyncRetryWait = Milliseconds(1); options.getMyLastOptime = [this]() { return _myLastOpTime; }; options.setMyLastOptime = [this](const OpTime& opTime) { _setMyLastOptime(opTime); }; + options.resetOptimes = [this]() { _setMyLastOptime(OpTime()); }; options.getSlaveDelay = [this]() { return Seconds(0); }; options.syncSourceSelector = this; @@ -550,6 +551,7 @@ TEST_F(InitialSyncerTest, InvalidConstruction) { InitialSyncerOptions options; options.getMyLastOptime = []() { return OpTime(); }; options.setMyLastOptime = [](const OpTime&) {}; + options.resetOptimes = []() {}; options.getSlaveDelay = []() { return Seconds(0); }; options.syncSourceSelector = this; auto callback = [](const StatusWith<OpTimeWithHash>&) {}; @@ -725,6 +727,30 @@ TEST_F(InitialSyncerTest, << progress; } +TEST_F(InitialSyncerTest, InitialSyncerResetsOptimesOnNewAttempt) { + auto initialSyncer = &getInitialSyncer(); + auto opCtx = makeOpCtx(); + + _syncSourceSelector->setChooseNewSyncSourceResult_forTest(HostAndPort()); + + const std::uint32_t initialSyncMaxAttempts = 1U; + ASSERT_OK(initialSyncer->startup(opCtx.get(), initialSyncMaxAttempts)); + + auto net = getNet(); + auto origOptime = OpTime(Timestamp(1000, 1), 1); + + _setMyLastOptime(origOptime); + + // Simulate a failed initial sync attempt + _simulateChooseSyncSourceFailure(net, _options.syncSourceRetryWait); + advanceClock(net, _options.initialSyncRetryWait); + + initialSyncer->join(); + + // Make sure the initial sync attempt reset optimes. + ASSERT_EQUALS(OpTime(), _options.getMyLastOptime()); +} + TEST_F(InitialSyncerTest, InitialSyncerReturnsCallbackCanceledIfShutdownWhileRetryingSyncSourceSelection) { auto initialSyncer = &getInitialSyncer(); diff --git a/src/mongo/db/repl/replication_coordinator_impl.cpp b/src/mongo/db/repl/replication_coordinator_impl.cpp index aab8106d2e6..e06c0d8eb60 100644 --- a/src/mongo/db/repl/replication_coordinator_impl.cpp +++ b/src/mongo/db/repl/replication_coordinator_impl.cpp @@ -285,6 +285,7 @@ InitialSyncerOptions createInitialSyncerOptions( replCoord->setMyLastAppliedOpTime(opTime); externalState->setGlobalTimestamp(opTime.getTimestamp()); }; + options.resetOptimes = [replCoord]() { replCoord->resetMyLastOpTimes(); }; options.getSlaveDelay = [replCoord]() { return replCoord->getSlaveDelaySecs(); }; options.syncSourceSelector = replCoord; options.replBatchLimitBytes = dur::UncommittedBytesLimit; |