diff options
author | Eric Milkie <milkie@10gen.com> | 2016-05-31 12:10:45 -0400 |
---|---|---|
committer | Eric Milkie <milkie@10gen.com> | 2016-06-01 09:52:41 -0400 |
commit | b360d5833b6c20ddc64b8a18456b359aa718e3fe (patch) | |
tree | 04f75f6b4c858031726e28d6742f533eb40fc6d6 | |
parent | b02759c687efcde72a0343532ae4c1b896d1db64 (diff) | |
download | mongo-b360d5833b6c20ddc64b8a18456b359aa718e3fe.tar.gz |
SERVER-24318 change BackgroundSync to one owned object by the Repl ExternalState, to simplify lifetime issues
32 files changed, 201 insertions, 207 deletions
diff --git a/src/mongo/db/mongod_options_init.cpp b/src/mongo/db/mongod_options_init.cpp index cb9bbcc0cac..1c5d78a8da7 100644 --- a/src/mongo/db/mongod_options_init.cpp +++ b/src/mongo/db/mongod_options_init.cpp @@ -30,6 +30,7 @@ #include <iostream> +#include "mongo/util/exit_code.h" #include "mongo/util/options_parser/startup_option_init.h" #include "mongo/util/options_parser/startup_options.h" #include "mongo/util/quick_exit.h" diff --git a/src/mongo/db/prefetch.cpp b/src/mongo/db/prefetch.cpp index 732e230741e..572ddf4d716 100644 --- a/src/mongo/db/prefetch.cpp +++ b/src/mongo/db/prefetch.cpp @@ -38,7 +38,7 @@ #include "mongo/db/dbhelpers.h" #include "mongo/db/index/index_access_method.h" #include "mongo/db/jsobj.h" -#include "mongo/db/repl/bgsync.h" +#include "mongo/db/repl/repl_settings.h" #include "mongo/db/repl/replication_coordinator.h" #include "mongo/db/repl/replication_coordinator_global.h" #include "mongo/db/server_parameters.h" @@ -67,15 +67,15 @@ ServerStatusMetricField<TimerStats> displayPrefetchDocPages("repl.preload.docs", // page in pages needed for all index lookups on a given object void prefetchIndexPages(OperationContext* txn, Collection* collection, - const BackgroundSync::IndexPrefetchConfig& prefetchConfig, + const ReplSettings::IndexPrefetchConfig& prefetchConfig, const BSONObj& obj) { // do we want prefetchConfig to be (1) as-is, (2) for update ops only, or (3) configured per op // type? One might want PREFETCH_NONE for updates, but it's more rare that it is a bad idea for // inserts. #3 (per op), a big issue would be "too many knobs". switch (prefetchConfig) { - case BackgroundSync::PREFETCH_NONE: + case ReplSettings::IndexPrefetchConfig::PREFETCH_NONE: return; - case BackgroundSync::PREFETCH_ID_ONLY: { + case ReplSettings::IndexPrefetchConfig::PREFETCH_ID_ONLY: { TimerHolder timer(&prefetchIndexStats); // on the update op case, the call to prefetchRecordPages will touch the _id index. // thus perhaps this option isn't very useful? @@ -91,7 +91,7 @@ void prefetchIndexPages(OperationContext* txn, } break; } - case BackgroundSync::PREFETCH_ALL: { + case ReplSettings::IndexPrefetchConfig::PREFETCH_ALL: { // indexCount includes all indexes, including ones // in the process of being built IndexCatalog::IndexIterator ii = @@ -145,8 +145,8 @@ void prefetchRecordPages(OperationContext* txn, Database* db, const char* ns, co // prefetch for an oplog operation void prefetchPagesForReplicatedOp(OperationContext* txn, Database* db, const BSONObj& op) { invariant(db); - const BackgroundSync::IndexPrefetchConfig prefetchConfig = - BackgroundSync::get()->getIndexPrefetchConfig(); + const ReplSettings::IndexPrefetchConfig prefetchConfig = + getGlobalReplicationCoordinator()->getIndexPrefetchConfig(); const char* opField; const char* opType = op.getStringField("op"); switch (*opType) { @@ -219,13 +219,14 @@ public: ReplicationCoordinator::modeReplSet) { return "uninitialized"; } - BackgroundSync::IndexPrefetchConfig ip = BackgroundSync::get()->getIndexPrefetchConfig(); + ReplSettings::IndexPrefetchConfig ip = + getGlobalReplicationCoordinator()->getIndexPrefetchConfig(); switch (ip) { - case BackgroundSync::PREFETCH_NONE: + case ReplSettings::IndexPrefetchConfig::PREFETCH_NONE: return "none"; - case BackgroundSync::PREFETCH_ID_ONLY: + case ReplSettings::IndexPrefetchConfig::PREFETCH_ID_ONLY: return "_id_only"; - case BackgroundSync::PREFETCH_ALL: + case ReplSettings::IndexPrefetchConfig::PREFETCH_ALL: return "all"; default: return "invalid"; @@ -249,20 +250,20 @@ public: virtual Status setFromString(const string& prefetch) { log() << "changing replication index prefetch behavior to " << prefetch << endl; - BackgroundSync::IndexPrefetchConfig prefetchConfig; + ReplSettings::IndexPrefetchConfig prefetchConfig; if (prefetch == "none") - prefetchConfig = BackgroundSync::PREFETCH_NONE; + prefetchConfig = ReplSettings::IndexPrefetchConfig::PREFETCH_NONE; else if (prefetch == "_id_only") - prefetchConfig = BackgroundSync::PREFETCH_ID_ONLY; + prefetchConfig = ReplSettings::IndexPrefetchConfig::PREFETCH_ID_ONLY; else if (prefetch == "all") - prefetchConfig = BackgroundSync::PREFETCH_ALL; + prefetchConfig = ReplSettings::IndexPrefetchConfig::PREFETCH_ALL; else { return Status(ErrorCodes::BadValue, str::stream() << "unrecognized indexPrefetch setting: " << prefetch); } - BackgroundSync::get()->setIndexPrefetchConfig(prefetchConfig); + getGlobalReplicationCoordinator()->setIndexPrefetchConfig(prefetchConfig); return Status::OK(); } diff --git a/src/mongo/db/repl/bgsync.cpp b/src/mongo/db/repl/bgsync.cpp index 3701e77cdda..5146e0ea1bc 100644 --- a/src/mongo/db/repl/bgsync.cpp +++ b/src/mongo/db/repl/bgsync.cpp @@ -127,9 +127,6 @@ size_t getSize(const BSONObj& o) { MONGO_FP_DECLARE(rsBgSyncProduce); -BackgroundSync* BackgroundSync::s_instance = 0; -stdx::mutex BackgroundSync::s_mutex; - // The number and time spent reading batches off the network static TimerStats getmoreReplStats; static ServerStatusMetricField<TimerStats> displayBatchesRecieved("repl.network.getmores", @@ -155,8 +152,6 @@ static ServerStatusMetricField<int> displayBufferMaxSize("repl.buffer.maxSizeByt &bufferMaxSizeGauge); -BackgroundSyncInterface::~BackgroundSyncInterface() {} - BackgroundSync::BackgroundSync() : _buffer(bufferMaxSizeGauge, &getSize), _threadPoolTaskExecutor(makeThreadPool(), @@ -166,14 +161,6 @@ BackgroundSync::BackgroundSync() _lastOpTimeFetched(Timestamp(std::numeric_limits<int>::max(), 0), std::numeric_limits<long long>::max()) {} -BackgroundSync* BackgroundSync::get() { - stdx::unique_lock<stdx::mutex> lock(s_mutex); - if (s_instance == NULL && !inShutdown()) { - s_instance = new BackgroundSync(); - } - return s_instance; -} - void BackgroundSync::shutdown() { stdx::lock_guard<stdx::mutex> lock(_mutex); @@ -666,26 +653,6 @@ long long BackgroundSync::_readLastAppliedHash(OperationContext* txn) { return hash; } -bool BackgroundSync::getInitialSyncRequestedFlag() const { - stdx::lock_guard<stdx::mutex> lock(_initialSyncMutex); - return _initialSyncRequestedFlag; -} - -void BackgroundSync::setInitialSyncRequestedFlag(bool value) { - stdx::lock_guard<stdx::mutex> lock(_initialSyncMutex); - _initialSyncRequestedFlag = value; -} - -BackgroundSync::IndexPrefetchConfig BackgroundSync::getIndexPrefetchConfig() const { - stdx::lock_guard<stdx::mutex> lock(_indexPrefetchMutex); - return _indexPrefetchConfig; -} - -void BackgroundSync::setIndexPrefetchConfig(const IndexPrefetchConfig cfg) { - stdx::lock_guard<stdx::mutex> lock(_indexPrefetchMutex); - _indexPrefetchConfig = cfg; -} - bool BackgroundSync::shouldStopFetching() const { if (inShutdown()) { LOG(2) << "Interrupted by shutdown while checking sync source."; diff --git a/src/mongo/db/repl/bgsync.h b/src/mongo/db/repl/bgsync.h index 40d44ae8f93..14d1432aa31 100644 --- a/src/mongo/db/repl/bgsync.h +++ b/src/mongo/db/repl/bgsync.h @@ -30,6 +30,7 @@ #include <memory> +#include "mongo/base/disallow_copying.h" #include "mongo/base/status_with.h" #include "mongo/db/jsobj.h" #include "mongo/db/repl/data_replicator_external_state.h" @@ -50,59 +51,27 @@ class OperationContext; namespace repl { -class Member; class ReplicationCoordinator; class ReplicationCoordinatorExternalState; -// This interface exists to facilitate easier testing; -// the test infrastructure implements these functions with stubs. -class BackgroundSyncInterface { -public: - virtual ~BackgroundSyncInterface(); - - // Gets the head of the buffer, but does not remove it. - // Returns true if an element was present at the head; - // false if the queue was empty. - virtual bool peek(BSONObj* op) = 0; - - // Deletes objects in the queue; - // called by sync thread after it has applied an op - virtual void consume() = 0; - - // wait up to 1 second for more ops to appear - virtual void waitForMore() = 0; -}; - - /** * Lock order: * 1. rslock * 2. rwlock * 3. BackgroundSync::_mutex */ -class BackgroundSync : public BackgroundSyncInterface { +class BackgroundSync { public: - // Allow index prefetching to be turned on/off - enum IndexPrefetchConfig { - UNINITIALIZED = 0, - PREFETCH_NONE = 1, - PREFETCH_ID_ONLY = 2, - PREFETCH_ALL = 3 - }; - - // TODO: remove, once initialSyncRequestedFlag and indexPrefetchConfig go somewhere else. - static BackgroundSync* get(); + BackgroundSync(); + MONGO_DISALLOW_COPYING(BackgroundSync); // stop syncing (when this node becomes a primary, e.g.) void stop(); - void shutdown(); bool isStopped() const; - virtual ~BackgroundSync() {} - /** * Starts the producer thread which runs until shutdown. Upon resolving the current sync source * the producer thread uses the OplogFetcher (which requires the replication coordinator @@ -117,10 +86,10 @@ public: // Interface implementation - virtual bool peek(BSONObj* op); - virtual void consume(); - virtual void clearSyncTarget(); - virtual void waitForMore(); + bool peek(BSONObj* op); + void consume(); + void clearSyncTarget(); + void waitForMore(); // For monitoring BSONObj getCounters(); @@ -133,12 +102,6 @@ public: */ void cancelFetcher(); - bool getInitialSyncRequestedFlag() const; - void setInitialSyncRequestedFlag(bool value); - - IndexPrefetchConfig getIndexPrefetchConfig() const; - void setIndexPrefetchConfig(const IndexPrefetchConfig cfg); - /** * Returns true if any of the following is true: * 1) We are shutting down; @@ -152,10 +115,6 @@ public: void pushTestOpToBuffer(const BSONObj& op); private: - BackgroundSync(); - BackgroundSync(const BackgroundSync& s); - BackgroundSync operator=(const BackgroundSync& s); - // Production thread void _producerThread(ReplicationCoordinatorExternalState* replicationCoordinatorExternalState); void _produce(OperationContext* txn, @@ -196,25 +155,12 @@ private: long long _readLastAppliedHash(OperationContext* txn); - static BackgroundSync* s_instance; - // protects creation of s_instance - static stdx::mutex s_mutex; - // Production thread BlockingQueue<BSONObj> _buffer; // Task executor used to run find/getMore commands on sync source. executor::ThreadPoolTaskExecutor _threadPoolTaskExecutor; - // bool for indicating resync need on this node and the mutex that protects it - // The resync command sets this flag; the Applier thread observes and clears it. - mutable stdx::mutex _initialSyncMutex; - bool _initialSyncRequestedFlag = false; - - // This setting affects the Applier prefetcher behavior. - mutable stdx::mutex _indexPrefetchMutex; - IndexPrefetchConfig _indexPrefetchConfig = PREFETCH_ALL; - // A pointer to the replication coordinator running the show. ReplicationCoordinator* _replCoord; diff --git a/src/mongo/db/repl/initial_sync.cpp b/src/mongo/db/repl/initial_sync.cpp index c1e9c9269ce..61cbe8e0d6a 100644 --- a/src/mongo/db/repl/initial_sync.cpp +++ b/src/mongo/db/repl/initial_sync.cpp @@ -46,7 +46,7 @@ namespace repl { unsigned replSetForceInitialSyncFailure = 0; -InitialSync::InitialSync(BackgroundSyncInterface* q, MultiSyncApplyFunc func) : SyncTail(q, func) {} +InitialSync::InitialSync(BackgroundSync* q, MultiSyncApplyFunc func) : SyncTail(q, func) {} InitialSync::~InitialSync() {} diff --git a/src/mongo/db/repl/initial_sync.h b/src/mongo/db/repl/initial_sync.h index aee7c79beab..167038363a7 100644 --- a/src/mongo/db/repl/initial_sync.h +++ b/src/mongo/db/repl/initial_sync.h @@ -33,7 +33,7 @@ namespace mongo { namespace repl { -class BackgroundSyncInterface; +class BackgroundSync; /** * Initial clone and sync @@ -41,7 +41,7 @@ class BackgroundSyncInterface; class InitialSync : public SyncTail { public: virtual ~InitialSync(); - InitialSync(BackgroundSyncInterface* q, MultiSyncApplyFunc func); + InitialSync(BackgroundSync* q, MultiSyncApplyFunc func); /** diff --git a/src/mongo/db/repl/repl_settings.cpp b/src/mongo/db/repl/repl_settings.cpp index b2049ba8776..c31f8bc5012 100644 --- a/src/mongo/db/repl/repl_settings.cpp +++ b/src/mongo/db/repl/repl_settings.cpp @@ -29,9 +29,12 @@ #define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kReplication #include "mongo/db/repl/repl_settings.h" -#include "mongo/util/log.h" + #include <string> +#include "mongo/db/repl/bgsync.h" +#include "mongo/util/log.h" + namespace mongo { namespace repl { @@ -93,12 +96,12 @@ std::string ReplSettings::getReplSetString() const { return _replSetString; } -BackgroundSync::IndexPrefetchConfig ReplSettings::getPrefetchIndexMode() const { +ReplSettings::IndexPrefetchConfig ReplSettings::getPrefetchIndexMode() const { return _prefetchIndexMode; } bool ReplSettings::isPrefetchIndexModeSet() const { - return _prefetchIndexMode != BackgroundSync::UNINITIALIZED; + return _prefetchIndexMode != IndexPrefetchConfig::UNINITIALIZED; } /** @@ -150,16 +153,16 @@ void ReplSettings::setReplSetString(std::string replSetString) { void ReplSettings::setPrefetchIndexMode(std::string prefetchIndexModeString) { if (prefetchIndexModeString.empty()) { - _prefetchIndexMode = BackgroundSync::UNINITIALIZED; + _prefetchIndexMode = IndexPrefetchConfig::UNINITIALIZED; } else { if (prefetchIndexModeString == "none") - _prefetchIndexMode = BackgroundSync::PREFETCH_NONE; + _prefetchIndexMode = IndexPrefetchConfig::PREFETCH_NONE; else if (prefetchIndexModeString == "_id_only") - _prefetchIndexMode = BackgroundSync::PREFETCH_ID_ONLY; + _prefetchIndexMode = IndexPrefetchConfig::PREFETCH_ID_ONLY; else if (prefetchIndexModeString == "all") - _prefetchIndexMode = BackgroundSync::PREFETCH_ALL; + _prefetchIndexMode = IndexPrefetchConfig::PREFETCH_ALL; else { - _prefetchIndexMode = BackgroundSync::PREFETCH_ALL; + _prefetchIndexMode = IndexPrefetchConfig::PREFETCH_ALL; warning() << "unrecognized indexPrefetchMode setting \"" << prefetchIndexModeString << "\", defaulting to \"all\""; } diff --git a/src/mongo/db/repl/repl_settings.h b/src/mongo/db/repl/repl_settings.h index b7c6918d75d..fe0e9ff03b6 100644 --- a/src/mongo/db/repl/repl_settings.h +++ b/src/mongo/db/repl/repl_settings.h @@ -32,7 +32,6 @@ #include <string> #include "mongo/db/jsobj.h" -#include "mongo/db/repl/bgsync.h" #include "mongo/util/concurrency/mutex.h" namespace mongo { @@ -43,6 +42,14 @@ extern double replElectionTimeoutOffsetLimitFraction; class ReplSettings { public: + // Allow index prefetching to be turned on/off + enum class IndexPrefetchConfig { + UNINITIALIZED = 0, + PREFETCH_NONE = 1, + PREFETCH_ID_ONLY = 2, + PREFETCH_ALL = 3 + }; + std::string ourSetName() const; bool usingReplSets() const; @@ -62,11 +69,11 @@ public: std::string getReplSetString() const; /** - * Note: _prefetchIndexMode is initialized to BackgroundSync::UNINITIALIZED by default. + * Note: _prefetchIndexMode is initialized to UNINITIALIZED by default. * To check whether _prefetchIndexMode has been set to a valid value, call * isPrefetchIndexModeSet(). */ - BackgroundSync::IndexPrefetchConfig getPrefetchIndexMode() const; + IndexPrefetchConfig getPrefetchIndexMode() const; /** * Checks that _prefetchIndexMode has been set. @@ -119,7 +126,7 @@ private: std::string _replSetString; // --replSet[/<seedlist>] // --indexPrefetch - BackgroundSync::IndexPrefetchConfig _prefetchIndexMode = BackgroundSync::UNINITIALIZED; + IndexPrefetchConfig _prefetchIndexMode = IndexPrefetchConfig::UNINITIALIZED; }; } // namespace repl diff --git a/src/mongo/db/repl/replication_coordinator.h b/src/mongo/db/repl/replication_coordinator.h index 952b0738258..0f226a6b13b 100644 --- a/src/mongo/db/repl/replication_coordinator.h +++ b/src/mongo/db/repl/replication_coordinator.h @@ -780,6 +780,12 @@ public: virtual WriteConcernOptions populateUnsetWriteConcernOptionsSyncMode( WriteConcernOptions wc) = 0; + virtual bool getInitialSyncRequestedFlag() const = 0; + virtual void setInitialSyncRequestedFlag(bool value) = 0; + + virtual ReplSettings::IndexPrefetchConfig getIndexPrefetchConfig() const = 0; + virtual void setIndexPrefetchConfig(const ReplSettings::IndexPrefetchConfig cfg) = 0; + protected: ReplicationCoordinator(); }; diff --git a/src/mongo/db/repl/replication_coordinator_external_state_impl.cpp b/src/mongo/db/repl/replication_coordinator_external_state_impl.cpp index 292f0ef9ae4..8c35effae54 100644 --- a/src/mongo/db/repl/replication_coordinator_external_state_impl.cpp +++ b/src/mongo/db/repl/replication_coordinator_external_state_impl.cpp @@ -104,13 +104,12 @@ void ReplicationCoordinatorExternalStateImpl::startInitialSync(OnInitialSyncFini log() << "Starting replication fetcher thread"; // Start bgsync. - BackgroundSync* bgsync = BackgroundSync::get(); - invariant(!(bgsync == nullptr && !inShutdownStrict())); // bgsync can be null @shutdown. + _bgSync.reset(new BackgroundSync()); invariant(!_producerThread); // The producer thread should not be init'd before this. _producerThread.reset( - new stdx::thread(stdx::bind(&BackgroundSync::producerThread, bgsync, this))); + new stdx::thread(stdx::bind(&BackgroundSync::producerThread, _bgSync.get(), this))); // Do initial sync. - syncDoInitialSync(); + syncDoInitialSync(_bgSync.get()); finished(); }}); } @@ -118,17 +117,17 @@ void ReplicationCoordinatorExternalStateImpl::startInitialSync(OnInitialSyncFini void ReplicationCoordinatorExternalStateImpl::startSteadyStateReplication() { if (!_producerThread) { log() << "Starting replication fetcher thread"; - BackgroundSync* bgsync = BackgroundSync::get(); + _bgSync.reset(new BackgroundSync()); _producerThread.reset( - new stdx::thread(stdx::bind(&BackgroundSync::producerThread, bgsync, this))); + new stdx::thread(stdx::bind(&BackgroundSync::producerThread, _bgSync.get(), this))); } log() << "Starting replication applier threads"; invariant(!_applierThread); - _applierThread.reset(new stdx::thread(runSyncThread)); + _applierThread.reset(new stdx::thread(stdx::bind(&runSyncThread, _bgSync.get()))); log() << "Starting replication reporter thread"; invariant(!_syncSourceFeedbackThread); - _syncSourceFeedbackThread.reset( - new stdx::thread(stdx::bind(&SyncSourceFeedback::run, &_syncSourceFeedback))); + _syncSourceFeedbackThread.reset(new stdx::thread( + stdx::bind(&SyncSourceFeedback::run, &_syncSourceFeedback, _bgSync.get()))); } void ReplicationCoordinatorExternalStateImpl::startThreads(const ReplSettings& settings) { @@ -168,10 +167,7 @@ void ReplicationCoordinatorExternalStateImpl::shutdown() { } if (_producerThread) { - BackgroundSync* bgsync = BackgroundSync::get(); - if (bgsync) { - bgsync->shutdown(); - } + _bgSync->shutdown(); _producerThread->join(); } if (_snapshotThread) @@ -423,17 +419,14 @@ void ReplicationCoordinatorExternalStateImpl::updateShardIdentityConfigString( } void ReplicationCoordinatorExternalStateImpl::signalApplierToChooseNewSyncSource() { - auto bgsync = BackgroundSync::get(); - if (bgsync) { - bgsync->clearSyncTarget(); + if (_bgSync) { + _bgSync->clearSyncTarget(); } } void ReplicationCoordinatorExternalStateImpl::signalApplierToCancelFetcher() { - auto bgsync = BackgroundSync::get(); - if (bgsync) { - bgsync->cancelFetcher(); - } + invariant(_bgSync); + _bgSync->cancelFetcher(); } void ReplicationCoordinatorExternalStateImpl::dropAllTempCollections(OperationContext* txn) { diff --git a/src/mongo/db/repl/replication_coordinator_external_state_impl.h b/src/mongo/db/repl/replication_coordinator_external_state_impl.h index 4ddac22d4a1..4e524e4c67a 100644 --- a/src/mongo/db/repl/replication_coordinator_external_state_impl.h +++ b/src/mongo/db/repl/replication_coordinator_external_state_impl.h @@ -32,6 +32,7 @@ #include "mongo/base/disallow_copying.h" #include "mongo/db/concurrency/d_concurrency.h" +#include "mongo/db/repl/bgsync.h" #include "mongo/db/repl/replication_coordinator_external_state.h" #include "mongo/db/repl/sync_source_feedback.h" #include "mongo/db/repl/sync_tail.h" @@ -111,6 +112,13 @@ private: // replication. SyncSourceFeedback _syncSourceFeedback; + // The BackgroundSync class is responsible for pulling ops off the network from the sync source + // and into a BlockingQueue. + // We can't create it on construction because it needs a fully constructed + // ReplicationCoordinator, but this ExternalState object is constructed prior to the + // ReplicationCoordinator. + std::unique_ptr<BackgroundSync> _bgSync; + // Thread running SyncSourceFeedback::run(). std::unique_ptr<stdx::thread> _syncSourceFeedbackThread; diff --git a/src/mongo/db/repl/replication_coordinator_impl.cpp b/src/mongo/db/repl/replication_coordinator_impl.cpp index 2ef097d1f76..36d10aae018 100644 --- a/src/mongo/db/repl/replication_coordinator_impl.cpp +++ b/src/mongo/db/repl/replication_coordinator_impl.cpp @@ -484,8 +484,11 @@ void ReplicationCoordinatorImpl::_stopDataReplication() {} void ReplicationCoordinatorImpl::_startDataReplication(OperationContext* txn) { // When initial sync is done, callback. OnInitialSyncFinishedFn callback{[this]() { - log() << "Initial sync done, starting steady state replication."; - _externalState->startSteadyStateReplication(); + stdx::lock_guard<stdx::mutex> lk(_mutex); + if (!_inShutdown) { + log() << "Initial sync done, starting steady state replication."; + _externalState->startSteadyStateReplication(); + } }}; const auto lastApplied = getMyLastAppliedOpTime(); @@ -3518,5 +3521,27 @@ CallbackFn ReplicationCoordinatorImpl::_wrapAsCallbackFn(const stdx::function<vo } +bool ReplicationCoordinatorImpl::getInitialSyncRequestedFlag() const { + stdx::lock_guard<stdx::mutex> lock(_initialSyncMutex); + return _initialSyncRequestedFlag; +} + +void ReplicationCoordinatorImpl::setInitialSyncRequestedFlag(bool value) { + stdx::lock_guard<stdx::mutex> lock(_initialSyncMutex); + _initialSyncRequestedFlag = value; +} + +ReplSettings::IndexPrefetchConfig ReplicationCoordinatorImpl::getIndexPrefetchConfig() const { + stdx::lock_guard<stdx::mutex> lock(_indexPrefetchMutex); + return _indexPrefetchConfig; +} + +void ReplicationCoordinatorImpl::setIndexPrefetchConfig( + const ReplSettings::IndexPrefetchConfig cfg) { + stdx::lock_guard<stdx::mutex> lock(_indexPrefetchMutex); + _indexPrefetchConfig = cfg; +} + + } // namespace repl } // namespace mongo diff --git a/src/mongo/db/repl/replication_coordinator_impl.h b/src/mongo/db/repl/replication_coordinator_impl.h index 8e525c934e3..93979a0dd9c 100644 --- a/src/mongo/db/repl/replication_coordinator_impl.h +++ b/src/mongo/db/repl/replication_coordinator_impl.h @@ -326,6 +326,14 @@ public: virtual WriteConcernOptions populateUnsetWriteConcernOptionsSyncMode( WriteConcernOptions wc) override; + + virtual bool getInitialSyncRequestedFlag() const override; + virtual void setInitialSyncRequestedFlag(bool value) override; + + virtual ReplSettings::IndexPrefetchConfig getIndexPrefetchConfig() const override; + virtual void setIndexPrefetchConfig(const ReplSettings::IndexPrefetchConfig cfg) override; + + // ================== Test support API =================== /** @@ -1320,6 +1328,16 @@ private: // Lambda indicating durability of storageEngine. stdx::function<bool()> _isDurableStorageEngine; // (R) + + // bool for indicating resync need on this node and the mutex that protects it + // The resync command sets this flag; the Applier thread observes and clears it. + mutable stdx::mutex _initialSyncMutex; + bool _initialSyncRequestedFlag = false; // (I) + + // This setting affects the Applier prefetcher behavior. + mutable stdx::mutex _indexPrefetchMutex; + ReplSettings::IndexPrefetchConfig _indexPrefetchConfig = + ReplSettings::IndexPrefetchConfig::PREFETCH_ALL; // (I) }; } // namespace repl diff --git a/src/mongo/db/repl/replication_coordinator_mock.cpp b/src/mongo/db/repl/replication_coordinator_mock.cpp index 48fe98a6299..706a5cd6747 100644 --- a/src/mongo/db/repl/replication_coordinator_mock.cpp +++ b/src/mongo/db/repl/replication_coordinator_mock.cpp @@ -438,5 +438,18 @@ WriteConcernOptions ReplicationCoordinatorMock::populateUnsetWriteConcernOptions return wc; } +bool ReplicationCoordinatorMock::getInitialSyncRequestedFlag() const { + return false; +} + +void ReplicationCoordinatorMock::setInitialSyncRequestedFlag(bool value) {} + +ReplSettings::IndexPrefetchConfig ReplicationCoordinatorMock::getIndexPrefetchConfig() const { + return ReplSettings::IndexPrefetchConfig(); +} + +void ReplicationCoordinatorMock::setIndexPrefetchConfig( + const ReplSettings::IndexPrefetchConfig cfg) {} + } // namespace repl } // namespace mongo diff --git a/src/mongo/db/repl/replication_coordinator_mock.h b/src/mongo/db/repl/replication_coordinator_mock.h index 5fdf319306d..15e7c513727 100644 --- a/src/mongo/db/repl/replication_coordinator_mock.h +++ b/src/mongo/db/repl/replication_coordinator_mock.h @@ -252,6 +252,12 @@ public: virtual WriteConcernOptions populateUnsetWriteConcernOptionsSyncMode( WriteConcernOptions wc) override; + virtual bool getInitialSyncRequestedFlag() const override; + virtual void setInitialSyncRequestedFlag(bool value) override; + + virtual ReplSettings::IndexPrefetchConfig getIndexPrefetchConfig() const override; + virtual void setIndexPrefetchConfig(const ReplSettings::IndexPrefetchConfig cfg) override; + private: AtomicUInt64 _snapshotNameGenerator; const ReplSettings _settings; diff --git a/src/mongo/db/repl/resync.cpp b/src/mongo/db/repl/resync.cpp index 86797724eed..a5b5928b273 100644 --- a/src/mongo/db/repl/resync.cpp +++ b/src/mongo/db/repl/resync.cpp @@ -29,9 +29,9 @@ #include "mongo/db/commands.h" #include "mongo/db/concurrency/d_concurrency.h" #include "mongo/db/operation_context.h" -#include "mongo/db/repl/bgsync.h" #include "mongo/db/repl/master_slave.h" // replSettings #include "mongo/db/repl/replication_coordinator_global.h" +#include "mongo/db/repl/replication_coordinator_impl.h" namespace mongo { @@ -85,7 +85,7 @@ public: return appendCommandStatus( result, Status(ErrorCodes::NotSecondary, "primaries cannot resync")); } - BackgroundSync::get()->setInitialSyncRequestedFlag(true); + replCoord->setInitialSyncRequestedFlag(true); return true; } diff --git a/src/mongo/db/repl/rs_initialsync.cpp b/src/mongo/db/repl/rs_initialsync.cpp index fe25036f399..8f93fe54b9b 100644 --- a/src/mongo/db/repl/rs_initialsync.cpp +++ b/src/mongo/db/repl/rs_initialsync.cpp @@ -214,14 +214,17 @@ bool _initialSyncClone(OperationContext* txn, * @param r the oplog reader. * @return if applying the oplog succeeded. */ -bool _initialSyncApplyOplog(OperationContext* ctx, repl::InitialSync* syncer, OplogReader* r) { +bool _initialSyncApplyOplog(OperationContext* ctx, + repl::InitialSync* syncer, + OplogReader* r, + BackgroundSync* bgsync) { const OpTime startOpTime = getGlobalReplicationCoordinator()->getMyLastAppliedOpTime(); BSONObj lastOp; // If the fail point is set, exit failing. if (MONGO_FAIL_POINT(failInitSyncWithBufferedEntriesLeft)) { log() << "adding fake oplog entry to buffer."; - BackgroundSync::get()->pushTestOpToBuffer(BSON( + bgsync->pushTestOpToBuffer(BSON( "ts" << startOpTime.getTimestamp() << "t" << startOpTime.getTerm() << "v" << 1 << "op" << "n")); return false; @@ -307,10 +310,9 @@ const auto kConnectRetryLimit = 10; * ErrorCode::InitialSyncOplogSourceMissing if the node fails to find an sync source, Status::OK * if everything worked, and ErrorCode::InitialSyncFailure for all other error cases. */ -Status _initialSync() { +Status _initialSync(BackgroundSync* bgsync) { log() << "initial sync pending"; - BackgroundSync* bgsync(BackgroundSync::get()); const ServiceContext::UniqueOperationContext txnPtr = cc().makeOperationContext(); OperationContext& txn = *txnPtr; txn.setReplicatedWrites(false); @@ -424,7 +426,7 @@ Status _initialSync() { std::string msg = "oplog sync 1 of 3"; log() << msg; - if (!_initialSyncApplyOplog(&txn, &init, &r)) { + if (!_initialSyncApplyOplog(&txn, &init, &r, bgsync)) { return Status(ErrorCodes::InitialSyncFailure, str::stream() << "initial sync failed: " << msg); } @@ -435,7 +437,7 @@ Status _initialSync() { // TODO: replace with "tail" instance below, since we don't need to retry/reclone missing docs. msg = "oplog sync 2 of 3"; log() << msg; - if (!_initialSyncApplyOplog(&txn, &init, &r)) { + if (!_initialSyncApplyOplog(&txn, &init, &r, bgsync)) { return Status(ErrorCodes::InitialSyncFailure, str::stream() << "initial sync failed: " << msg); } @@ -462,7 +464,7 @@ Status _initialSync() { log() << msg; InitialSync tail(bgsync, multiSyncApply); // Use the non-initial sync apply code - if (!_initialSyncApplyOplog(&txn, &tail, &r)) { + if (!_initialSyncApplyOplog(&txn, &tail, &r, bgsync)) { return Status(ErrorCodes::InitialSyncFailure, str::stream() << "initial sync failed: " << msg); } @@ -485,7 +487,7 @@ Status _initialSync() { // Initial sync is now complete. Flag this by setting minValid to the last thing we synced. StorageInterface::get(&txn)->setMinValid(&txn, lastOpTimeWritten, DurableRequirement::None); - BackgroundSync::get()->setInitialSyncRequestedFlag(false); + getGlobalReplicationCoordinator()->setInitialSyncRequestedFlag(false); } // Clear the initial sync flag -- cannot be done under a db lock, or recursive. @@ -505,7 +507,7 @@ const auto kMaxFailedAttempts = 10; const auto kInitialSyncRetrySleepDuration = Seconds{5}; } // namespace -void syncDoInitialSync() { +void syncDoInitialSync(BackgroundSync* bgsync) { stdx::unique_lock<stdx::mutex> lk(_initialSyncMutex, stdx::defer_lock); if (!lk.try_lock()) { uasserted(34474, "Initial Sync Already Active."); @@ -521,7 +523,7 @@ void syncDoInitialSync() { while (failedAttempts < kMaxFailedAttempts) { try { // leave loop when successful - Status status = _initialSync(); + Status status = _initialSync(bgsync); if (status.isOK()) { break; } else { diff --git a/src/mongo/db/repl/rs_initialsync.h b/src/mongo/db/repl/rs_initialsync.h index 7add22b9a37..1f5416453e0 100644 --- a/src/mongo/db/repl/rs_initialsync.h +++ b/src/mongo/db/repl/rs_initialsync.h @@ -30,10 +30,14 @@ namespace mongo { namespace repl { + +class BackgroundSync; + /** * Begins an initial sync of a node. This drops all data, chooses a sync source, * and runs the cloner from that sync source. The node's state is not changed. */ -void syncDoInitialSync(); -} -} +void syncDoInitialSync(BackgroundSync* bgsync); + +} // namespace repl +} // namespace mongo diff --git a/src/mongo/db/repl/rs_sync.cpp b/src/mongo/db/repl/rs_sync.cpp index 455235e519c..df71177ce6d 100644 --- a/src/mongo/db/repl/rs_sync.cpp +++ b/src/mongo/db/repl/rs_sync.cpp @@ -60,7 +60,7 @@ namespace mongo { namespace repl { -void runSyncThread() { +void runSyncThread(BackgroundSync* bgsync) { Client::initThread("rsSync"); AuthorizationSession::get(cc())->grantInternalAuthorization(); ReplicationCoordinator* replCoord = getGlobalReplicationCoordinator(); @@ -68,7 +68,7 @@ void runSyncThread() { // Overwrite prefetch index mode in BackgroundSync if ReplSettings has a mode set. ReplSettings replSettings = replCoord->getSettings(); if (replSettings.isPrefetchIndexModeSet()) - BackgroundSync::get()->setIndexPrefetchConfig(replSettings.getPrefetchIndexMode()); + replCoord->setIndexPrefetchConfig(replSettings.getPrefetchIndexMode()); while (!inShutdown()) { // After a reconfig, we may not be in the replica set anymore, so @@ -105,7 +105,7 @@ void runSyncThread() { } /* we have some data. continue tailing. */ - SyncTail tail(BackgroundSync::get(), multiSyncApply); + SyncTail tail(bgsync, multiSyncApply); tail.oplogApplication(); } catch (...) { std::terminate(); diff --git a/src/mongo/db/repl/rs_sync.h b/src/mongo/db/repl/rs_sync.h index 513c6265657..047fdc3d9a6 100644 --- a/src/mongo/db/repl/rs_sync.h +++ b/src/mongo/db/repl/rs_sync.h @@ -40,8 +40,10 @@ namespace mongo { namespace repl { +class BackgroundSync; + // Body of the thread that will do the background sync. -void runSyncThread(); +void runSyncThread(BackgroundSync* bgsync); } // namespace repl } // namespace mongo diff --git a/src/mongo/db/repl/storage_interface_impl_test.cpp b/src/mongo/db/repl/storage_interface_impl_test.cpp index 9b8cdabd32a..3ecf5be0711 100644 --- a/src/mongo/db/repl/storage_interface_impl_test.cpp +++ b/src/mongo/db/repl/storage_interface_impl_test.cpp @@ -41,6 +41,7 @@ #include "mongo/db/repl/storage_interface_impl.h" #include "mongo/db/service_context_d_test_fixture.h" #include "mongo/db/storage/recovery_unit_noop.h" +#include "mongo/stdx/memory.h" #include "mongo/unittest/unittest.h" #include "mongo/util/assert_util.h" diff --git a/src/mongo/db/repl/sync_source_feedback.cpp b/src/mongo/db/repl/sync_source_feedback.cpp index ed05b1fc48b..8739cd4969c 100644 --- a/src/mongo/db/repl/sync_source_feedback.cpp +++ b/src/mongo/db/repl/sync_source_feedback.cpp @@ -74,10 +74,13 @@ Milliseconds calculateKeepAliveInterval(OperationContext* txn, stdx::mutex& mtx) * Returns function to prepare update command */ Reporter::PrepareReplSetUpdatePositionCommandFn makePrepareReplSetUpdatePositionCommandFn( - OperationContext* txn, stdx::mutex& mtx, const HostAndPort& syncTarget) { - return [&mtx, syncTarget, txn](ReplicationCoordinator::ReplSetUpdatePositionCommandStyle - commandStyle) -> StatusWith<BSONObj> { - auto currentSyncTarget = BackgroundSync::get()->getSyncTarget(); + OperationContext* txn, + stdx::mutex& mtx, + const HostAndPort& syncTarget, + BackgroundSync* bgsync) { + return [&mtx, syncTarget, txn, bgsync](ReplicationCoordinator::ReplSetUpdatePositionCommandStyle + commandStyle) -> StatusWith<BSONObj> { + auto currentSyncTarget = bgsync->getSyncTarget(); if (currentSyncTarget != syncTarget) { // Change in sync target return Status(ErrorCodes::InvalidSyncSource, "Sync target is no longer valid"); @@ -112,7 +115,7 @@ void SyncSourceFeedback::forwardSlaveProgress() { } } -Status SyncSourceFeedback::_updateUpstream(OperationContext* txn) { +Status SyncSourceFeedback::_updateUpstream(OperationContext* txn, BackgroundSync* bgsync) { Reporter* reporter; { stdx::lock_guard<stdx::mutex> lock(_mtx); @@ -143,7 +146,7 @@ Status SyncSourceFeedback::_updateUpstream(OperationContext* txn) { stdx::lock_guard<stdx::mutex> lock(_mtx); auto replCoord = repl::ReplicationCoordinator::get(txn); replCoord->blacklistSyncSource(syncTarget, Date_t::now() + Milliseconds(500)); - BackgroundSync::get()->clearSyncTarget(); + bgsync->clearSyncTarget(); } } @@ -159,7 +162,7 @@ void SyncSourceFeedback::shutdown() { _cond.notify_all(); } -void SyncSourceFeedback::run() { +void SyncSourceFeedback::run(BackgroundSync* bgsync) { Client::initThread("SyncSourceFeedback"); // Task executor used to run replSetUpdatePosition command on sync source. @@ -214,7 +217,7 @@ void SyncSourceFeedback::run() { } } - const HostAndPort target = BackgroundSync::get()->getSyncTarget(); + const HostAndPort target = bgsync->getSyncTarget(); // Log sync source changes. if (target.empty()) { if (syncTarget != target) { @@ -237,10 +240,11 @@ void SyncSourceFeedback::run() { } } - Reporter reporter(&executor, - makePrepareReplSetUpdatePositionCommandFn(txn.get(), _mtx, syncTarget), - syncTarget, - keepAliveInterval); + Reporter reporter( + &executor, + makePrepareReplSetUpdatePositionCommandFn(txn.get(), _mtx, syncTarget, bgsync), + syncTarget, + keepAliveInterval); { stdx::lock_guard<stdx::mutex> lock(_mtx); _reporter = &reporter; @@ -250,7 +254,7 @@ void SyncSourceFeedback::run() { _reporter = nullptr; }); - auto status = _updateUpstream(txn.get()); + auto status = _updateUpstream(txn.get(), bgsync); if (!status.isOK()) { LOG(1) << "The replication progress command (replSetUpdatePosition) failed and will be " "retried: " diff --git a/src/mongo/db/repl/sync_source_feedback.h b/src/mongo/db/repl/sync_source_feedback.h index 3d3ea0e4747..a0233707bbf 100644 --- a/src/mongo/db/repl/sync_source_feedback.h +++ b/src/mongo/db/repl/sync_source_feedback.h @@ -38,6 +38,7 @@ struct HostAndPort; class OperationContext; namespace repl { +class BackgroundSync; class Reporter; class SyncSourceFeedback { @@ -51,7 +52,7 @@ public: * update occurs within the _keepAliveInterval, progress is forwarded to let the upstream node * know that this node, along with the alive nodes chaining through it, are still alive. */ - void run(); + void run(BackgroundSync* bgsync); /// Signals the run() method to terminate. void shutdown(); @@ -60,7 +61,7 @@ private: /* Inform the sync target of our current position in the oplog, as well as the positions * of all secondaries chained through us. */ - Status _updateUpstream(OperationContext* txn); + Status _updateUpstream(OperationContext* txn, BackgroundSync* bgsync); // protects cond, _shutdownSignaled, _keepAliveInterval, and _positionChanged. stdx::mutex _mtx; diff --git a/src/mongo/db/repl/sync_source_selector.h b/src/mongo/db/repl/sync_source_selector.h index 812944420a9..eb1b19f3764 100644 --- a/src/mongo/db/repl/sync_source_selector.h +++ b/src/mongo/db/repl/sync_source_selector.h @@ -34,6 +34,7 @@ namespace mongo { +class OperationContext; class Timestamp; namespace repl { diff --git a/src/mongo/db/repl/sync_tail.cpp b/src/mongo/db/repl/sync_tail.cpp index d8bcb020c50..c1bc186284c 100644 --- a/src/mongo/db/repl/sync_tail.cpp +++ b/src/mongo/db/repl/sync_tail.cpp @@ -275,7 +275,7 @@ void ApplyBatchFinalizerForJournal::_run() { } } // anonymous namespace containing ApplyBatchFinalizer definitions. -SyncTail::SyncTail(BackgroundSyncInterface* q, MultiSyncApplyFunc func) +SyncTail::SyncTail(BackgroundSync* q, MultiSyncApplyFunc func) : _networkQueue(q), _applyFunc(func), _writerPool(replWriterThreadCount, "repl writer worker ") {} @@ -706,7 +706,7 @@ void SyncTail::oplogApplication() { OpQueue ops; do { - if (BackgroundSync::get()->getInitialSyncRequestedFlag()) { + if (replCoord->getInitialSyncRequestedFlag()) { // got a resync command return; } diff --git a/src/mongo/db/repl/sync_tail.h b/src/mongo/db/repl/sync_tail.h index 41311d3242f..9480542e966 100644 --- a/src/mongo/db/repl/sync_tail.h +++ b/src/mongo/db/repl/sync_tail.h @@ -44,7 +44,7 @@ class Database; class OperationContext; namespace repl { -class BackgroundSyncInterface; +class BackgroundSync; class ReplicationCoordinator; class OpTime; @@ -83,7 +83,7 @@ public: */ using ApplyCommandInLockFn = stdx::function<Status(OperationContext*, const BSONObj&)>; - SyncTail(BackgroundSyncInterface* q, MultiSyncApplyFunc func); + SyncTail(BackgroundSync* q, MultiSyncApplyFunc func); virtual ~SyncTail(); /** @@ -174,7 +174,7 @@ private: std::string _hostname; - BackgroundSyncInterface* _networkQueue; + BackgroundSync* _networkQueue; // Function to use during applyOps MultiSyncApplyFunc _applyFunc; diff --git a/src/mongo/db/repl/sync_tail_test.cpp b/src/mongo/db/repl/sync_tail_test.cpp index 087889ed5ac..9fee7c0958f 100644 --- a/src/mongo/db/repl/sync_tail_test.cpp +++ b/src/mongo/db/repl/sync_tail_test.cpp @@ -50,19 +50,6 @@ namespace { using namespace mongo; using namespace mongo::repl; -class BackgroundSyncMock : public BackgroundSyncInterface { -public: - bool peek(BSONObj* op) override; - void consume() override; - void waitForMore() override; -}; - -bool BackgroundSyncMock::peek(BSONObj* op) { - return false; -} -void BackgroundSyncMock::consume() {} -void BackgroundSyncMock::waitForMore() {} - class SyncTailTest : public ServiceContextMongoDTest { protected: void _testSyncApplyInsertDocument(LockMode expectedMode); @@ -107,13 +94,6 @@ void SyncTailTest::tearDown() { setGlobalReplicationCoordinator(nullptr); } -TEST_F(SyncTailTest, Peek) { - BackgroundSyncMock bgsync; - SyncTail syncTail(&bgsync, [](const std::vector<OplogEntry>& ops, SyncTail* st) {}); - BSONObj obj; - ASSERT_FALSE(syncTail.peek(&obj)); -} - TEST_F(SyncTailTest, SyncApplyNoNamespaceBadOp) { const BSONObj op = BSON("op" << "x"); diff --git a/src/mongo/db/repl/topology_coordinator_impl.h b/src/mongo/db/repl/topology_coordinator_impl.h index 74d7368d552..6ae0b62788d 100644 --- a/src/mongo/db/repl/topology_coordinator_impl.h +++ b/src/mongo/db/repl/topology_coordinator_impl.h @@ -39,6 +39,7 @@ #include "mongo/db/repl/replica_set_config.h" #include "mongo/db/repl/replication_coordinator.h" #include "mongo/db/repl/topology_coordinator.h" +#include "mongo/db/server_options.h" #include "mongo/s/catalog/catalog_manager.h" #include "mongo/util/time_support.h" diff --git a/src/mongo/db/s/collection_sharding_state.cpp b/src/mongo/db/s/collection_sharding_state.cpp index bccdf9cf009..185b8bab56e 100644 --- a/src/mongo/db/s/collection_sharding_state.cpp +++ b/src/mongo/db/s/collection_sharding_state.cpp @@ -43,6 +43,7 @@ #include "mongo/db/s/sharded_connection_info.h" #include "mongo/db/s/sharding_state.h" #include "mongo/db/s/type_shard_identity.h" +#include "mongo/db/server_options.h" #include "mongo/s/chunk_version.h" #include "mongo/s/stale_exception.h" diff --git a/src/mongo/db/s/config/configsvr_add_shard_command.cpp b/src/mongo/db/s/config/configsvr_add_shard_command.cpp index bedff1e0532..27031c5a4e9 100644 --- a/src/mongo/db/s/config/configsvr_add_shard_command.cpp +++ b/src/mongo/db/s/config/configsvr_add_shard_command.cpp @@ -36,6 +36,7 @@ #include "mongo/db/auth/privilege.h" #include "mongo/db/commands.h" #include "mongo/db/namespace_string.h" +#include "mongo/db/repl/replica_set_config.h" #include "mongo/db/repl/replication_coordinator.h" #include "mongo/s/catalog/catalog_manager.h" #include "mongo/s/catalog/type_shard.h" diff --git a/src/mongo/s/client/shard_local.cpp b/src/mongo/s/client/shard_local.cpp index 78baa872cf0..26f17aaa029 100644 --- a/src/mongo/s/client/shard_local.cpp +++ b/src/mongo/s/client/shard_local.cpp @@ -38,6 +38,7 @@ #include "mongo/db/curop.h" #include "mongo/db/dbdirectclient.h" #include "mongo/db/repl/repl_client_info.h" +#include "mongo/db/repl/replica_set_config.h" #include "mongo/db/repl/replication_coordinator_global.h" #include "mongo/rpc/get_status_from_command_result.h" #include "mongo/rpc/unique_message.h" diff --git a/src/mongo/s/client/shard_local_test.cpp b/src/mongo/s/client/shard_local_test.cpp index f6e3009f97e..45faebc4a9e 100644 --- a/src/mongo/s/client/shard_local_test.cpp +++ b/src/mongo/s/client/shard_local_test.cpp @@ -39,6 +39,7 @@ #include "mongo/db/repl/replication_coordinator_mock.h" #include "mongo/db/service_context_d_test_fixture.h" #include "mongo/db/write_concern_options.h" +#include "mongo/stdx/memory.h" namespace mongo { namespace { |