summaryrefslogtreecommitdiff
path: root/src/mongo/db/service_context.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/service_context.h')
-rw-r--r--src/mongo/db/service_context.h168
1 files changed, 128 insertions, 40 deletions
diff --git a/src/mongo/db/service_context.h b/src/mongo/db/service_context.h
index 73b272470e6..24905f2fc4d 100644
--- a/src/mongo/db/service_context.h
+++ b/src/mongo/db/service_context.h
@@ -28,14 +28,17 @@
#pragma once
+#include <boost/optional.hpp>
#include <vector>
#include "mongo/base/disallow_copying.h"
+#include "mongo/base/global_initializer_registerer.h"
#include "mongo/db/logical_session_id.h"
#include "mongo/db/storage/storage_engine.h"
#include "mongo/platform/atomic_word.h"
#include "mongo/stdx/condition_variable.h"
#include "mongo/stdx/functional.h"
+#include "mongo/stdx/list.h"
#include "mongo/stdx/memory.h"
#include "mongo/stdx/mutex.h"
#include "mongo/stdx/unordered_set.h"
@@ -89,20 +92,11 @@ protected:
* A ServiceContext is the root of a hierarchy of contexts. A ServiceContext owns
* zero or more Clients, which in turn each own OperationContexts.
*/
-class ServiceContext : public Decorable<ServiceContext> {
+class ServiceContext final : public Decorable<ServiceContext> {
MONGO_DISALLOW_COPYING(ServiceContext);
public:
/**
- * Special deleter used for cleaning up Client objects owned by a ServiceContext.
- * See UniqueClient, below.
- */
- class ClientDeleter {
- public:
- void operator()(Client* client) const;
- };
-
- /**
* Observer interface implemented to hook client and operation context creation and
* destruction.
*/
@@ -172,12 +166,23 @@ public:
};
/**
- * Special deleter used for cleaning up OperationContext objects owned by a ServiceContext.
- * See UniqueOperationContext, below.
+ * Special deleter used for cleaning up ServiceContext objects.
+ * See UniqueServiceContext, below.
*/
- class OperationContextDeleter {
+ class ServiceContextDeleter {
public:
- void operator()(OperationContext* opCtx) const;
+ void operator()(ServiceContext* service) const;
+ };
+
+ using UniqueServiceContext = std::unique_ptr<ServiceContext, ServiceContextDeleter>;
+
+ /**
+ * Special deleter used for cleaning up Client objects owned by a ServiceContext.
+ * See UniqueClient, below.
+ */
+ class ClientDeleter {
+ public:
+ void operator()(Client* client) const;
};
/**
@@ -186,11 +191,96 @@ public:
using UniqueClient = std::unique_ptr<Client, ClientDeleter>;
/**
+ * Special deleter used for cleaning up OperationContext objects owned by a ServiceContext.
+ * See UniqueOperationContext, below.
+ */
+ class OperationContextDeleter {
+ public:
+ void operator()(OperationContext* opCtx) const;
+ };
+
+ /**
* This is the unique handle type for OperationContexts created by a ServiceContext.
*/
using UniqueOperationContext = std::unique_ptr<OperationContext, OperationContextDeleter>;
- virtual ~ServiceContext();
+ /**
+ * Register a function of this type using an instance of ConstructorActionRegisterer,
+ * below, to cause the function to be executed on new ServiceContext instances.
+ */
+ using ConstructorAction = stdx::function<void(ServiceContext*)>;
+
+ /**
+ * Register a function of this type using an instance of ConstructorActionRegisterer,
+ * below, to cause the function to be executed on ServiceContext instances before they
+ * are destroyed.
+ */
+ using DestructorAction = stdx::function<void(ServiceContext*) noexcept>;
+
+ /**
+ * Representation of a paired ConstructorAction and DestructorAction.
+ */
+ class ConstructorDestructorActions {
+ public:
+ ConstructorDestructorActions(ConstructorAction constructor, DestructorAction destructor)
+ : _constructor(std::move(constructor)), _destructor(std::move(destructor)) {}
+
+ void onCreate(ServiceContext* service) const {
+ _constructor(service);
+ }
+ void onDestroy(ServiceContext* service) const {
+ _destructor(service);
+ }
+
+ private:
+ ConstructorAction _constructor;
+ DestructorAction _destructor;
+ };
+
+ /**
+ * Registers a function to execute on new service contexts when they are created, and optionally
+ * also register a function to execute before those contexts are destroyed.
+ *
+ * Construct instances of this type during static initialization only, as they register
+ * MONGO_INITIALIZERS.
+ */
+ class ConstructorActionRegisterer {
+ public:
+ /**
+ * This constructor registers a constructor and optional destructor with the given
+ * "name" and no prerequisite constructors or mongo initializers.
+ */
+ ConstructorActionRegisterer(std::string name,
+ ConstructorAction constructor,
+ DestructorAction destructor = {});
+
+ /**
+ * This constructor registers a constructor and optional destructor with the given
+ * "name", and a list of names of prerequisites, "prereqs".
+ *
+ * The named constructor will run after all of its prereqs successfully complete,
+ * and the corresponding destructor, if provided, will run before any of its
+ * prerequisites execute.
+ */
+ ConstructorActionRegisterer(std::string name,
+ std::vector<std::string> prereqs,
+ ConstructorAction constructor,
+ DestructorAction destructor = {});
+
+ private:
+ using ConstructorActionListIterator = stdx::list<ConstructorDestructorActions>::iterator;
+ ConstructorActionListIterator _iter;
+ boost::optional<GlobalInitializerRegisterer> _registerer;
+ };
+
+ /**
+ * Factory function for making instances of ServiceContext. It is the only means by which they
+ * should be created.
+ */
+ static UniqueServiceContext make();
+
+ ServiceContext();
+ ~ServiceContext();
/**
* Registers an observer of lifecycle events on Clients created by this ServiceContext.
@@ -411,20 +501,29 @@ public:
*/
void setServiceExecutor(std::unique_ptr<transport::ServiceExecutor> exec);
-protected:
- ServiceContext();
+private:
+ class ClientObserverHolder {
+ public:
+ explicit ClientObserverHolder(std::unique_ptr<ClientObserver> observer)
+ : _observer(std::move(observer)) {}
+ void onCreate(Client* client) const {
+ _observer->onCreateClient(client);
+ }
+ void onDestroy(Client* client) const {
+ _observer->onDestroyClient(client);
+ }
+ void onCreate(OperationContext* opCtx) const {
+ _observer->onCreateOperationContext(opCtx);
+ }
+ void onDestroy(OperationContext* opCtx) const {
+ _observer->onDestroyOperationContext(opCtx);
+ }
- /**
- * Mutex used to synchronize access to mutable state of this ServiceContext instance,
- * including possibly by its subclasses.
- */
- stdx::mutex _mutex;
+ private:
+ std::unique_ptr<ClientObserver> _observer;
+ };
-private:
- /**
- * Returns a new OperationContext. Private, for use by makeOperationContext.
- */
- virtual std::unique_ptr<OperationContext> _newOpCtx(Client* client, unsigned opId) = 0;
+ stdx::mutex _mutex;
/**
* The storage engine, if any.
@@ -454,7 +553,7 @@ private:
/**
* Vector of registered observers.
*/
- std::vector<std::unique_ptr<ClientObserver>> _clientObservers;
+ std::vector<ClientObserverHolder> _clientObservers;
ClientSet _clients;
/**
@@ -503,23 +602,12 @@ bool hasGlobalServiceContext();
ServiceContext* getGlobalServiceContext();
/**
- * Warning - This function is temporary. Do not introduce new uses of this API.
- *
- * Returns the singleton ServiceContext for this server process.
- *
- * Waits until there is a valid global ServiceContext.
- *
- * Caller does not own pointer.
- */
-ServiceContext* waitAndGetGlobalServiceContext();
-
-/**
* Sets the global ServiceContext. If 'serviceContext' is NULL, un-sets and deletes
* the current global ServiceContext.
*
* Takes ownership of 'serviceContext'.
*/
-void setGlobalServiceContext(std::unique_ptr<ServiceContext>&& serviceContext);
+void setGlobalServiceContext(ServiceContext::UniqueServiceContext&& serviceContext);
/**
* Shortcut for querying the storage engine about whether it supports document-level locking.