summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam Schultz <william.schultz@mongodb.com>2017-06-02 16:58:37 -0400
committerBenety Goh <benety@mongodb.com>2017-06-27 16:09:17 -0400
commitd915259708b79fd7394aa8de9779520710d2bbe7 (patch)
tree4d606c93c16e070ceb0b2d226e8a24ac81a60c6f
parentc55eb86ef46ee7aede3b1e2a5d184a7df4bfb5b5 (diff)
downloadmongo-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.cpp5
-rw-r--r--src/mongo/db/repl/initial_syncer.h4
-rw-r--r--src/mongo/db/repl/initial_syncer_test.cpp26
-rw-r--r--src/mongo/db/repl/replication_coordinator_impl.cpp1
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;