diff options
-rw-r--r-- | src/mongo/db/service_context.cpp | 66 | ||||
-rw-r--r-- | src/mongo/db/service_context.h | 29 | ||||
-rw-r--r-- | src/mongo/db/service_context_d.cpp | 74 | ||||
-rw-r--r-- | src/mongo/db/service_context_d.h | 26 | ||||
-rw-r--r-- | src/mongo/db/service_context_noop.cpp | 17 | ||||
-rw-r--r-- | src/mongo/db/service_context_noop.h | 12 |
6 files changed, 92 insertions, 132 deletions
diff --git a/src/mongo/db/service_context.cpp b/src/mongo/db/service_context.cpp index 6f42a4a547b..894d08c3fd9 100644 --- a/src/mongo/db/service_context.cpp +++ b/src/mongo/db/service_context.cpp @@ -276,4 +276,70 @@ BSONArray storageEngineList() { void appendStorageEngineList(BSONObjBuilder* result) { result->append("storageEngines", storageEngineList()); } + +void ServiceContext::setKillAllOperations() { + stdx::lock_guard<stdx::mutex> clientLock(_mutex); + _globalKill.store(true); + for (const auto listener : _killOpListeners) { + try { + listener->interruptAll(); + } catch (...) { + std::terminate(); + } + } +} + +void ServiceContext::_killOperation_inlock(OperationContext* opCtx, ErrorCodes::Error killCode) { + opCtx->markKilled(killCode); + + for (const auto listener : _killOpListeners) { + try { + listener->interrupt(opCtx->getOpID()); + } catch (...) { + std::terminate(); + } + } +} + +bool ServiceContext::killOperation(unsigned int opId) { + for (LockedClientsCursor cursor(this); Client* client = cursor.next();) { + stdx::lock_guard<Client> lk(*client); + + OperationContext* opCtx = client->getOperationContext(); + if (opCtx && opCtx->getOpID() == opId) { + _killOperation_inlock(opCtx, ErrorCodes::Interrupted); + return true; + } + } + + return false; +} + +void ServiceContext::killAllUserOperations(const OperationContext* txn, + ErrorCodes::Error killCode) { + for (LockedClientsCursor cursor(this); Client* client = cursor.next();) { + if (!client->isFromUserConnection()) { + // Don't kill system operations. + continue; + } + + stdx::lock_guard<Client> lk(*client); + OperationContext* toKill = client->getOperationContext(); + + // Don't kill ourself. + if (toKill && toKill->getOpID() != txn->getOpID()) { + _killOperation_inlock(toKill, killCode); + } + } +} + +void ServiceContext::unsetKillAllOperations() { + _globalKill.store(false); +} + +void ServiceContext::registerKillOpListener(KillOpListenerInterface* listener) { + stdx::lock_guard<stdx::mutex> clientLock(_mutex); + _killOpListeners.push_back(listener); +} + } // namespace mongo diff --git a/src/mongo/db/service_context.h b/src/mongo/db/service_context.h index 1cba9bdb05d..a27a799efd2 100644 --- a/src/mongo/db/service_context.h +++ b/src/mongo/db/service_context.h @@ -33,6 +33,7 @@ #include "mongo/base/disallow_copying.h" #include "mongo/db/storage/storage_engine.h" +#include "mongo/platform/atomic_word.h" #include "mongo/platform/unordered_set.h" #include "mongo/stdx/functional.h" #include "mongo/stdx/mutex.h" @@ -262,30 +263,32 @@ public: /** * Signal all OperationContext(s) that they have been killed. */ - virtual void setKillAllOperations() = 0; + void setKillAllOperations(); /** * Reset the operation kill state after a killAllOperations. * Used for testing. */ - virtual void unsetKillAllOperations() = 0; + void unsetKillAllOperations(); /** * Get the state for killing all operations. */ - virtual bool getKillAllOperations() = 0; + bool getKillAllOperations() { + return _globalKill.loadRelaxed(); + } /** * @param i opid of operation to kill * @return if operation was found **/ - virtual bool killOperation(unsigned int opId) = 0; + bool killOperation(unsigned int opId); /** * Kills all operations that have a Client that is associated with an incoming user * connection, except for the one associated with txn. */ - virtual void killAllUserOperations(const OperationContext* txn, ErrorCodes::Error killCode) = 0; + void killAllUserOperations(const OperationContext* txn, ErrorCodes::Error killCode); /** * Registers a listener to be notified each time an op is killed. @@ -293,7 +296,7 @@ public: * listener does not become owned by the environment. As there is currently no way to * unregister, the listener object must outlive this ServiceContext object. */ - virtual void registerKillOpListener(KillOpListenerInterface* listener) = 0; + void registerKillOpListener(KillOpListenerInterface* listener); // // Global OpObserver. @@ -359,6 +362,14 @@ private: virtual std::unique_ptr<OperationContext> _newOpCtx(Client* client) = 0; /** + * Kills the given operation. + * + * Caller must own the service context's _mutex. + */ + void _killOperation_inlock(OperationContext* opCtx, ErrorCodes::Error killCode); + + + /** * Vector of registered observers. */ std::vector<std::unique_ptr<ClientObserver>> _clientObservers; @@ -376,6 +387,12 @@ private: * A ClockSource implementation that is very precise but may be expensive to call. */ std::unique_ptr<ClockSource> _preciseClockSource; + + // Flag set to indicate that all operations are to be interrupted ASAP. + AtomicWord<bool> _globalKill{false}; + + // protected by _mutex + std::vector<KillOpListenerInterface*> _killOpListeners; }; /** diff --git a/src/mongo/db/service_context_d.cpp b/src/mongo/db/service_context_d.cpp index b82f89c4c05..aac7296a5a4 100644 --- a/src/mongo/db/service_context_d.cpp +++ b/src/mongo/db/service_context_d.cpp @@ -66,9 +66,9 @@ MONGO_INITIALIZER(SetGlobalEnvironment)(InitializerContext* context) { return Status::OK(); } -ServiceContextMongoD::ServiceContextMongoD() : _globalKill(false), _storageEngine(NULL) {} +ServiceContextMongoD::ServiceContextMongoD() = default; -ServiceContextMongoD::~ServiceContextMongoD() {} +ServiceContextMongoD::~ServiceContextMongoD() = default; StorageEngine* ServiceContextMongoD::getGlobalStorageEngine() { // We don't check that globalStorageEngine is not-NULL here intentionally. We can encounter @@ -252,76 +252,6 @@ const StorageEngine::Factory* StorageFactoriesIteratorMongoD::next() { return _curr++->second; } -void ServiceContextMongoD::setKillAllOperations() { - stdx::lock_guard<stdx::mutex> clientLock(_mutex); - _globalKill = true; - for (const auto listener : _killOpListeners) { - try { - listener->interruptAll(); - } catch (...) { - std::terminate(); - } - } -} - -bool ServiceContextMongoD::getKillAllOperations() { - return _globalKill; -} - -void ServiceContextMongoD::_killOperation_inlock(OperationContext* opCtx, - ErrorCodes::Error killCode) { - opCtx->markKilled(killCode); - - for (const auto listener : _killOpListeners) { - try { - listener->interrupt(opCtx->getOpID()); - } catch (...) { - std::terminate(); - } - } -} - -bool ServiceContextMongoD::killOperation(unsigned int opId) { - for (LockedClientsCursor cursor(this); Client* client = cursor.next();) { - stdx::lock_guard<Client> lk(*client); - - OperationContext* opCtx = client->getOperationContext(); - if (opCtx && opCtx->getOpID() == opId) { - _killOperation_inlock(opCtx, ErrorCodes::Interrupted); - return true; - } - } - - return false; -} - -void ServiceContextMongoD::killAllUserOperations(const OperationContext* txn, - ErrorCodes::Error killCode) { - for (LockedClientsCursor cursor(this); Client* client = cursor.next();) { - if (!client->isFromUserConnection()) { - // Don't kill system operations. - continue; - } - - stdx::lock_guard<Client> lk(*client); - OperationContext* toKill = client->getOperationContext(); - - // Don't kill ourself. - if (toKill && toKill->getOpID() != txn->getOpID()) { - _killOperation_inlock(toKill, killCode); - } - } -} - -void ServiceContextMongoD::unsetKillAllOperations() { - _globalKill = false; -} - -void ServiceContextMongoD::registerKillOpListener(KillOpListenerInterface* listener) { - stdx::lock_guard<stdx::mutex> clientLock(_mutex); - _killOpListeners.push_back(listener); -} - std::unique_ptr<OperationContext> ServiceContextMongoD::_newOpCtx(Client* client) { invariant(&cc() == client); return std::unique_ptr<OperationContextImpl>(new OperationContextImpl()); diff --git a/src/mongo/db/service_context_d.h b/src/mongo/db/service_context_d.h index ce806a80240..a773fab2b61 100644 --- a/src/mongo/db/service_context_d.h +++ b/src/mongo/db/service_context_d.h @@ -61,18 +61,6 @@ public: StorageFactoriesIterator* makeStorageFactoriesIterator() override; - void setKillAllOperations() override; - - void unsetKillAllOperations() override; - - bool getKillAllOperations() override; - - bool killOperation(unsigned int opId) override; - - void killAllUserOperations(const OperationContext* txn, ErrorCodes::Error killCode) override; - - void registerKillOpListener(KillOpListenerInterface* listener) override; - void setOpObserver(std::unique_ptr<OpObserver> opObserver) override; OpObserver* getOpObserver() override; @@ -80,22 +68,10 @@ public: private: std::unique_ptr<OperationContext> _newOpCtx(Client* client) override; - /** - * Kills the given operation. - * - * Caller must own the service context's _mutex. - */ - void _killOperation_inlock(OperationContext* opCtx, ErrorCodes::Error killCode); - - bool _globalKill; - - // protected by parent class's _mutex - std::vector<KillOpListenerInterface*> _killOpListeners; - std::unique_ptr<StorageEngineLockFile> _lockFile; // logically owned here, but never deleted by anyone. - StorageEngine* _storageEngine; + StorageEngine* _storageEngine = nullptr; // logically owned here. std::unique_ptr<OpObserver> _opObserver; diff --git a/src/mongo/db/service_context_noop.cpp b/src/mongo/db/service_context_noop.cpp index fd94b35db89..0280d1b4742 100644 --- a/src/mongo/db/service_context_noop.cpp +++ b/src/mongo/db/service_context_noop.cpp @@ -67,23 +67,6 @@ StorageFactoriesIterator* ServiceContextNoop::makeStorageFactoriesIterator() { return new EmptySFI(); } -void ServiceContextNoop::setKillAllOperations() {} - -void ServiceContextNoop::unsetKillAllOperations() {} - -bool ServiceContextNoop::getKillAllOperations() { - return false; -} - -bool ServiceContextNoop::killOperation(unsigned int opId) { - return false; -} - -void ServiceContextNoop::killAllUserOperations(const OperationContext* txn, - ErrorCodes::Error killCode) {} - -void ServiceContextNoop::registerKillOpListener(KillOpListenerInterface* listener) {} - std::unique_ptr<OperationContext> ServiceContextNoop::_newOpCtx(Client* client) { return stdx::make_unique<OperationContextNoop>(client, _nextOpId.fetchAndAdd(1)); } diff --git a/src/mongo/db/service_context_noop.h b/src/mongo/db/service_context_noop.h index 7fce23a6a4a..8e80509df10 100644 --- a/src/mongo/db/service_context_noop.h +++ b/src/mongo/db/service_context_noop.h @@ -49,18 +49,6 @@ public: StorageFactoriesIterator* makeStorageFactoriesIterator() override; - bool killOperation(unsigned int opId) override; - - void killAllUserOperations(const OperationContext* txn, ErrorCodes::Error killCode) override; - - void setKillAllOperations() override; - - void unsetKillAllOperations() override; - - bool getKillAllOperations() override; - - void registerKillOpListener(KillOpListenerInterface* listener) override; - void setOpObserver(std::unique_ptr<OpObserver> opObserver) override; OpObserver* getOpObserver() override; |