summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorHenrik Edin <henrik.edin@mongodb.com>2018-03-12 11:14:15 -0400
committerHenrik Edin <henrik.edin@mongodb.com>2018-03-26 15:54:16 -0400
commitaf600c3876a26f62d8dde93bf769fc4ca3054072 (patch)
treeecef32a9b3c6c54501651168cce48093e76e9858 /src/mongo
parent2676a176759359c8614c0e37b267198259b6789f (diff)
downloadmongo-af600c3876a26f62d8dde93bf769fc4ca3054072.tar.gz
SERVER-30170 Embedded can now shutdown and re-initialize.
- ServiceContext* is now closer to be an instance context for the database. We still don't support multiple instances but I wrote the new code with this in mind. Teardown and reinitialize then becomes a matter of being able to delete and re-create the ServiceContext*. - Use the new MONGO_INITIALIZER that supports deinit/reinit to be able to re-initialize global systems that are decorations on ServiceContext. - Move creation/destruction of ServiceContext* out of MONGO_INITIALIZER. This so we can hold an exclusive lock during as much as possible of the shutdown (like how mongod does) - New ServiceContext registrer where we can link in different implementations of ServiceContext (replaces the SetGlobalEnvironment MONGO_INITIALIZER) - As a result the SetGlobalEnvironment prerequisite for MONGO_INITIALIZERs is gone. - The ServiceContext is passed to runGlobalInitializers, put in InitializationContext/DeinitializationContext so the initializers know which context they operate on.
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/SConscript2
-rw-r--r--src/mongo/base/deinitializer_context.h16
-rw-r--r--src/mongo/base/init.h1
-rw-r--r--src/mongo/base/initializer.cpp32
-rw-r--r--src/mongo/base/initializer.h20
-rw-r--r--src/mongo/base/initializer_context.cpp35
-rw-r--r--src/mongo/base/initializer_context.h16
-rw-r--r--src/mongo/base/initializer_test.cpp7
-rw-r--r--src/mongo/client/embedded/embedded.cpp111
-rw-r--r--src/mongo/client/embedded/embedded.h6
-rw-r--r--src/mongo/client/embedded/libmongodbcapi.cpp74
-rw-r--r--src/mongo/client/embedded/libmongodbcapi.h4
-rw-r--r--src/mongo/client/embedded/libmongodbcapi_test.cpp9
-rw-r--r--src/mongo/client/embedded/service_context_embedded.cpp38
-rw-r--r--src/mongo/client/embedded/service_context_embedded.h5
-rw-r--r--src/mongo/db/SConscript1
-rw-r--r--src/mongo/db/auth/auth_decorations.cpp5
-rw-r--r--src/mongo/db/auth/authorization_manager_global.cpp34
-rw-r--r--src/mongo/db/auth/sasl_mechanism_registry.cpp28
-rw-r--r--src/mongo/db/catalog/database_holder_impl.cpp22
-rw-r--r--src/mongo/db/db.cpp7
-rw-r--r--src/mongo/db/pipeline/document_source_sample_test.cpp1
-rw-r--r--src/mongo/db/query/collation/collator_factory_icu_decoration.cpp2
-rw-r--r--src/mongo/db/query/datetime/init_timezone_data.cpp4
-rw-r--r--src/mongo/db/repl/service_context_repl_mock_init.cpp11
-rw-r--r--src/mongo/db/service_context.cpp10
-rw-r--r--src/mongo/db/service_context_d.cpp20
-rw-r--r--src/mongo/db/service_context_fwd.h (renamed from src/mongo/base/deinitializer_context.cpp)25
-rw-r--r--src/mongo/db/service_context_noop_init.cpp8
-rw-r--r--src/mongo/db/service_context_registrar.cpp54
-rw-r--r--src/mongo/db/service_context_registrar.h48
-rw-r--r--src/mongo/db/sorter/sorter_test.cpp11
-rw-r--r--src/mongo/db/storage/devnull/devnull_init.cpp4
-rw-r--r--src/mongo/db/storage/encryption_hooks.cpp2
-rw-r--r--src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_init.cpp2
-rw-r--r--src/mongo/db/storage/mmap_v1/mmap_v1_init.cpp2
-rw-r--r--src/mongo/db/storage/mobile/mobile_init.cpp12
-rw-r--r--src/mongo/db/storage/storage_engine.h11
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_customization_hooks.cpp2
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_extensions.cpp2
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_init.cpp2
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_record_store_mock.cpp11
-rw-r--r--src/mongo/dbtests/dbtests.cpp5
-rw-r--r--src/mongo/executor/connection_pool.cpp4
-rw-r--r--src/mongo/s/server.cpp19
-rw-r--r--src/mongo/shell/dbshell.cpp4
-rw-r--r--src/mongo/tools/bridge.cpp11
-rw-r--r--src/mongo/transport/transport_layer_egress_init.cpp2
-rw-r--r--src/mongo/unittest/SConscript2
-rw-r--r--src/mongo/unittest/benchmark_main.cpp10
-rw-r--r--src/mongo/unittest/integration_test_main.cpp9
-rw-r--r--src/mongo/unittest/unittest_main.cpp10
52 files changed, 472 insertions, 321 deletions
diff --git a/src/mongo/SConscript b/src/mongo/SConscript
index a2451a9cb54..c5d91a883b6 100644
--- a/src/mongo/SConscript
+++ b/src/mongo/SConscript
@@ -56,14 +56,12 @@ env.Library(
'base/data_type.cpp',
'base/data_type_string_data.cpp',
'base/data_type_terminated.cpp',
- 'base/deinitializer_context.cpp',
'base/error_codes.cpp',
'base/error_extra_info.cpp',
'base/global_initializer.cpp',
'base/global_initializer_registerer.cpp',
'base/init.cpp',
'base/initializer.cpp',
- 'base/initializer_context.cpp',
'base/initializer_dependency_graph.cpp',
'base/make_string_vector.cpp',
'base/parse_number.cpp',
diff --git a/src/mongo/base/deinitializer_context.h b/src/mongo/base/deinitializer_context.h
index 0e8edc32066..0db3d773c05 100644
--- a/src/mongo/base/deinitializer_context.h
+++ b/src/mongo/base/deinitializer_context.h
@@ -27,14 +27,14 @@
#pragma once
+#include "mongo/base/disallow_copying.h"
+#include "mongo/db/service_context_fwd.h"
+
#include <map>
#include <string>
#include <vector>
-#include "mongo/base/disallow_copying.h"
-
namespace mongo {
-
/**
* Context of a deinitialization process. Passed as a parameter to deinitialization functions.
*
@@ -42,10 +42,18 @@ namespace mongo {
*/
class DeinitializerContext {
public:
- DeinitializerContext() = default;
+ explicit DeinitializerContext(ServiceContext* serviceContext)
+ : _serviceContext(serviceContext) {}
DeinitializerContext(DeinitializerContext const&) = delete;
DeinitializerContext& operator=(DeinitializerContext const&) = delete;
+
+ ServiceContext* serviceContext() const {
+ return _serviceContext;
+ }
+
+private:
+ ServiceContext* _serviceContext;
};
} // namespace mongo
diff --git a/src/mongo/base/init.h b/src/mongo/base/init.h
index 5fc8aed2c86..1d6595592aa 100644
--- a/src/mongo/base/init.h
+++ b/src/mongo/base/init.h
@@ -40,6 +40,7 @@
#pragma once
+#include "mongo/base/deinitializer_context.h"
#include "mongo/base/global_initializer.h"
#include "mongo/base/global_initializer_registerer.h"
#include "mongo/base/initializer.h"
diff --git a/src/mongo/base/initializer.cpp b/src/mongo/base/initializer.cpp
index 9939057b070..34625b7cd65 100644
--- a/src/mongo/base/initializer.cpp
+++ b/src/mongo/base/initializer.cpp
@@ -39,13 +39,14 @@ Initializer::Initializer() {}
Initializer::~Initializer() {}
Status Initializer::executeInitializers(const InitializerContext::ArgumentVector& args,
- const InitializerContext::EnvironmentMap& env) {
+ const InitializerContext::EnvironmentMap& env,
+ ServiceContext* serviceContext) {
std::vector<std::string> sortedNodes;
Status status = _graph.topSort(&sortedNodes);
if (Status::OK() != status)
return status;
- InitializerContext context(args, env);
+ InitializerContext context(args, env, serviceContext);
for (size_t i = 0; i < sortedNodes.size(); ++i) {
InitializerDependencyNode* node = _graph.getInitializerNode(sortedNodes[i]);
@@ -75,13 +76,13 @@ Status Initializer::executeInitializers(const InitializerContext::ArgumentVector
return Status::OK();
}
-Status Initializer::executeDeinitializers() {
+Status Initializer::executeDeinitializers(ServiceContext* serviceContext) {
std::vector<std::string> sortedNodes;
Status status = _graph.topSort(&sortedNodes);
if (Status::OK() != status)
return status;
- DeinitializerContext context;
+ DeinitializerContext context(serviceContext);
// Execute deinitialization in reverse order from initialization.
for (auto it = sortedNodes.rbegin(), end = sortedNodes.rend(); it != end; ++it) {
@@ -104,11 +105,15 @@ Status Initializer::executeDeinitializers() {
}
Status runGlobalInitializers(const InitializerContext::ArgumentVector& args,
- const InitializerContext::EnvironmentMap& env) {
- return getGlobalInitializer().executeInitializers(args, env);
+ const InitializerContext::EnvironmentMap& env,
+ ServiceContext* serviceContext) {
+ return getGlobalInitializer().executeInitializers(args, env, serviceContext);
}
-Status runGlobalInitializers(int argc, const char* const* argv, const char* const* envp) {
+Status runGlobalInitializers(int argc,
+ const char* const* argv,
+ const char* const* envp,
+ ServiceContext* serviceContext) {
InitializerContext::ArgumentVector args(argc);
std::copy(argv, argv + argc, args.begin());
@@ -124,15 +129,18 @@ Status runGlobalInitializers(int argc, const char* const* argv, const char* cons
}
}
- return runGlobalInitializers(args, env);
+ return runGlobalInitializers(args, env, serviceContext);
}
-Status runGlobalDeinitializers() {
- return getGlobalInitializer().executeDeinitializers();
+Status runGlobalDeinitializers(ServiceContext* serviceContext) {
+ return getGlobalInitializer().executeDeinitializers(serviceContext);
}
-void runGlobalInitializersOrDie(int argc, const char* const* argv, const char* const* envp) {
- Status status = runGlobalInitializers(argc, argv, envp);
+void runGlobalInitializersOrDie(int argc,
+ const char* const* argv,
+ const char* const* envp,
+ ServiceContext* serviceContext) {
+ Status status = runGlobalInitializers(argc, argv, envp, serviceContext);
if (!status.isOK()) {
std::cerr << "Failed global initialization: " << status << std::endl;
quickExit(1);
diff --git a/src/mongo/base/initializer.h b/src/mongo/base/initializer.h
index 904356fdbef..924569ab138 100644
--- a/src/mongo/base/initializer.h
+++ b/src/mongo/base/initializer.h
@@ -66,9 +66,10 @@ public:
* and the thing being initialized should be considered dead in the water.
*/
Status executeInitializers(const InitializerContext::ArgumentVector& args,
- const InitializerContext::EnvironmentMap& env);
+ const InitializerContext::EnvironmentMap& env,
+ ServiceContext* serviceContext);
- Status executeDeinitializers();
+ Status executeDeinitializers(ServiceContext* serviceContext);
private:
InitializerDependencyGraph _graph;
@@ -84,15 +85,22 @@ private:
* should probably arrange to terminate the process themselves.
*/
Status runGlobalInitializers(const InitializerContext::ArgumentVector& args,
- const InitializerContext::EnvironmentMap& env);
+ const InitializerContext::EnvironmentMap& env,
+ ServiceContext* serviceContext);
-Status runGlobalInitializers(int argc, const char* const* argv, const char* const* envp);
+Status runGlobalInitializers(int argc,
+ const char* const* argv,
+ const char* const* envp,
+ ServiceContext* serviceContext);
/**
* Same as runGlobalInitializers(), except prints a brief message to std::cerr
* and terminates the process on failure.
*/
-void runGlobalInitializersOrDie(int argc, const char* const* argv, const char* const* envp);
+void runGlobalInitializersOrDie(int argc,
+ const char* const* argv,
+ const char* const* envp,
+ ServiceContext* serviceContext);
/**
* Run the global deinitializers. They will execute in reverse order from initialization.
@@ -103,6 +111,6 @@ void runGlobalInitializersOrDie(int argc, const char* const* argv, const char* c
* This means that the few initializers that might want to terminate the program by failing
* should probably arrange to terminate the process themselves.
*/
-Status runGlobalDeinitializers();
+Status runGlobalDeinitializers(ServiceContext* serviceContext);
} // namespace mongo
diff --git a/src/mongo/base/initializer_context.cpp b/src/mongo/base/initializer_context.cpp
deleted file mode 100644
index 40299c134ba..00000000000
--- a/src/mongo/base/initializer_context.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-/* Copyright 2012 10gen Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- * As a special exception, the copyright holders give permission to link the
- * code of portions of this program with the OpenSSL library under certain
- * conditions as described in each individual source file and distribute
- * linked combinations including the program with the OpenSSL library. You
- * must comply with the GNU Affero General Public License in all respects
- * for all of the code used other than as permitted herein. If you modify
- * file(s) with this exception, you may extend this exception to your
- * version of the file(s), but you are not obligated to do so. If you do not
- * wish to do so, delete this exception statement from your version. If you
- * delete this exception statement from all source files in the program,
- * then also delete it in the license file.
- */
-
-#include "mongo/base/initializer_context.h"
-
-namespace mongo {
-
-InitializerContext::InitializerContext(const ArgumentVector& args, const EnvironmentMap& env)
- : _args(args), _env(env) {}
-
-} // namespace mongo
diff --git a/src/mongo/base/initializer_context.h b/src/mongo/base/initializer_context.h
index 4414439065d..b1a9ab329e9 100644
--- a/src/mongo/base/initializer_context.h
+++ b/src/mongo/base/initializer_context.h
@@ -27,14 +27,14 @@
#pragma once
+#include "mongo/base/disallow_copying.h"
+#include "mongo/db/service_context_fwd.h"
+
#include <map>
#include <string>
#include <vector>
-#include "mongo/base/disallow_copying.h"
-
namespace mongo {
-
/**
* Context of an initialization process. Passed as a parameter to initialization functions.
*
@@ -47,7 +47,10 @@ public:
typedef std::vector<std::string> ArgumentVector;
typedef std::map<std::string, std::string> EnvironmentMap;
- InitializerContext(const ArgumentVector& args, const EnvironmentMap& env);
+ InitializerContext(const ArgumentVector& args,
+ const EnvironmentMap& env,
+ ServiceContext* serviceContext)
+ : _args(args), _env(env), _serviceContext(serviceContext) {}
const ArgumentVector& args() const {
return _args;
@@ -56,9 +59,14 @@ public:
return _env;
}
+ ServiceContext* serviceContext() const {
+ return _serviceContext;
+ }
+
private:
ArgumentVector _args;
EnvironmentMap _env;
+ ServiceContext* _serviceContext;
};
} // namespace mongo
diff --git a/src/mongo/base/initializer_test.cpp b/src/mongo/base/initializer_test.cpp
index 9be5f0eb6f5..31b87f5771d 100644
--- a/src/mongo/base/initializer_test.cpp
+++ b/src/mongo/base/initializer_test.cpp
@@ -160,8 +160,8 @@ TEST(InitializerTest, SuccessfulInitialization) {
set7,
set8);
clearCounts();
- ASSERT_OK(initializer.executeInitializers(InitializerContext::ArgumentVector(),
- InitializerContext::EnvironmentMap()));
+ ASSERT_OK(initializer.executeInitializers(
+ InitializerContext::ArgumentVector(), InitializerContext::EnvironmentMap(), nullptr));
for (int i = 0; i < 9; ++i)
ASSERT_EQUALS(1, globalCounts[i]);
}
@@ -181,7 +181,8 @@ TEST(InitializerTest, Step5Misimplemented) {
clearCounts();
ASSERT_EQUALS(ErrorCodes::UnknownError,
initializer.executeInitializers(InitializerContext::ArgumentVector(),
- InitializerContext::EnvironmentMap()));
+ InitializerContext::EnvironmentMap(),
+ nullptr));
ASSERT_EQUALS(1, globalCounts[0]);
ASSERT_EQUALS(1, globalCounts[1]);
ASSERT_EQUALS(1, globalCounts[2]);
diff --git a/src/mongo/client/embedded/embedded.cpp b/src/mongo/client/embedded/embedded.cpp
index 9e1c71ec791..fdcf98975b9 100644
--- a/src/mongo/client/embedded/embedded.cpp
+++ b/src/mongo/client/embedded/embedded.cpp
@@ -38,6 +38,7 @@
#include "mongo/client/embedded/service_context_embedded.h"
#include "mongo/client/embedded/service_entry_point_embedded.h"
#include "mongo/config.h"
+#include "mongo/db/catalog/database_holder.h"
#include "mongo/db/catalog/health_log.h"
#include "mongo/db/catalog/uuid_catalog.h"
#include "mongo/db/client.h"
@@ -53,6 +54,7 @@
#include "mongo/db/op_observer_registry.h"
#include "mongo/db/repair_database_and_check_version.h"
#include "mongo/db/repl/storage_interface_impl.h"
+#include "mongo/db/service_context_registrar.h"
#include "mongo/db/session_catalog.h"
#include "mongo/db/session_killer.h"
#include "mongo/db/startup_warnings_mongod.h"
@@ -97,17 +99,26 @@ MONGO_INITIALIZER_GENERAL(ForkServer, ("EndStartupOptionHandling"), ("default"))
// Create a minimalistic replication coordinator to provide a limited interface for users. Not
// functional to provide any replication logic.
-MONGO_INITIALIZER_WITH_PREREQUISITES(CreateReplicationManager,
- ("SetGlobalEnvironment", "SSLManager", "default"))
-(InitializerContext* context) {
- auto serviceContext = getGlobalServiceContext();
- repl::StorageInterface::set(serviceContext, stdx::make_unique<repl::StorageInterfaceImpl>());
-
- auto replCoord = stdx::make_unique<ReplicationCoordinatorEmbedded>(serviceContext);
- repl::ReplicationCoordinator::set(serviceContext, std::move(replCoord));
- repl::setOplogCollectionName(serviceContext);
- return Status::OK();
-}
+GlobalInitializerRegisterer replicationManagerInitializer(
+ "CreateReplicationManager",
+ {"SSLManager", "default"},
+ [](InitializerContext* context) {
+ auto serviceContext = context->serviceContext();
+ repl::StorageInterface::set(serviceContext, std::make_unique<repl::StorageInterfaceImpl>());
+
+ auto replCoord = std::make_unique<ReplicationCoordinatorEmbedded>(serviceContext);
+ repl::ReplicationCoordinator::set(serviceContext, std::move(replCoord));
+ repl::setOplogCollectionName(serviceContext);
+ return Status::OK();
+ },
+ [](DeinitializerContext* context) {
+ auto serviceContext = context->serviceContext();
+
+ repl::ReplicationCoordinator::set(serviceContext, nullptr);
+ repl::StorageInterface::set(serviceContext, nullptr);
+
+ return Status::OK();
+ });
MONGO_INITIALIZER(fsyncLockedForWriting)(InitializerContext* context) {
setLockedForWritingImpl([]() { return false; });
@@ -118,56 +129,52 @@ MONGO_INITIALIZER(fsyncLockedForWriting)(InitializerContext* context) {
using logger::LogComponent;
using std::endl;
-void shutdown() {
- Client::initThreadIfNotAlready();
+void shutdown(ServiceContext* srvContext) {
+ Client::initThreadIfNotAlready();
auto const client = Client::getCurrent();
auto const serviceContext = client->getServiceContext();
+ invariant(srvContext == serviceContext);
serviceContext->setKillAllOperations();
- // Shut down the background periodic task runner
- if (auto runner = serviceContext->getPeriodicRunner()) {
- runner->shutdown();
- }
-
// We should always be able to acquire the global lock at shutdown.
- //
- // TODO: This call chain uses the locker directly, because we do not want to start an
- // operation context, which also instantiates a recovery unit. Also, using the
- // lockGlobalBegin/lockGlobalComplete sequence, we avoid taking the flush lock.
- //
- // For a Windows service, dbexit does not call exit(), so we must leak the lock outside
- // of this function to prevent any operations from running that need a lock.
- //
- DefaultLockerImpl* globalLocker = new DefaultLockerImpl();
- LockResult result = globalLocker->lockGlobalBegin(MODE_X, Date_t::max());
- if (result == LOCK_WAITING) {
- result = globalLocker->lockGlobalComplete(Date_t::max());
- }
+ // Close all open databases, shutdown storage engine and run all deinitializers.
+ auto shutdownOpCtx = serviceContext->makeOperationContext(client);
+ {
+ Lock::GlobalLock lk(shutdownOpCtx.get(), MODE_X, Date_t::max());
+ dbHolder().closeAll(shutdownOpCtx.get(), "shutdown");
- invariant(LOCK_OK == result);
+ // Shut down the background periodic task runner
+ if (auto runner = serviceContext->getPeriodicRunner()) {
+ runner->shutdown();
+ }
- // Global storage engine may not be started in all cases before we exit
- if (serviceContext->getGlobalStorageEngine()) {
- serviceContext->shutdownGlobalStorageEngineCleanly();
+ // Global storage engine may not be started in all cases before we exit
+ if (serviceContext->getGlobalStorageEngine()) {
+ serviceContext->shutdownGlobalStorageEngineCleanly();
+ }
+
+ Status status = mongo::runGlobalDeinitializers(serviceContext);
+ uassertStatusOKWithContext(status, "Global deinitilization failed");
}
+ shutdownOpCtx.reset();
+
+ if (Client::getCurrent())
+ Client::destroy();
+
+ setGlobalServiceContext(nullptr);
log(LogComponent::kControl) << "now exiting";
}
-int initialize(int argc, char* argv[], char** envp) {
- registerShutdownTask(shutdown);
-
+ServiceContext* initialize(int argc, char* argv[], char** envp) {
srand(static_cast<unsigned>(curTimeMicros64()));
- //
- Status status = mongo::runGlobalInitializers(argc, argv, envp);
- if (!status.isOK()) {
- severe(LogComponent::kControl) << "Failed global initializations: " << status;
- return EXIT_FAILURE;
- }
+ setGlobalServiceContext(createServiceContext());
+ Status status = mongo::runGlobalInitializers(argc, argv, envp, getGlobalServiceContext());
+ uassertStatusOKWithContext(status, "Global initilization failed");
Client::initThread("initandlisten");
@@ -175,9 +182,9 @@ int initialize(int argc, char* argv[], char** envp) {
auto serviceContext = checked_cast<ServiceContextMongoEmbedded*>(getGlobalServiceContext());
- auto opObserverRegistry = stdx::make_unique<OpObserverRegistry>();
- opObserverRegistry->addObserver(stdx::make_unique<OpObserverImpl>());
- opObserverRegistry->addObserver(stdx::make_unique<UUIDCatalogObserver>());
+ auto opObserverRegistry = std::make_unique<OpObserverRegistry>();
+ opObserverRegistry->addObserver(std::make_unique<OpObserverImpl>());
+ opObserverRegistry->addObserver(std::make_unique<UUIDCatalogObserver>());
serviceContext->setOpObserver(std::move(opObserverRegistry));
DBDirectClientFactory::get(serviceContext).registerImplementation([](OperationContext* opCtx) {
@@ -201,16 +208,10 @@ int initialize(int argc, char* argv[], char** envp) {
serviceContext->createLockFile();
serviceContext->setServiceEntryPoint(
- stdx::make_unique<ServiceEntryPointEmbedded>(serviceContext));
+ std::make_unique<ServiceEntryPointEmbedded>(serviceContext));
serviceContext->initializeGlobalStorageEngine();
-#ifdef MONGO_CONFIG_WIREDTIGER_ENABLED
- if (EncryptionHooks::get(serviceContext)->restartRequired()) {
- quickExit(EXIT_CLEAN);
- }
-#endif
-
// Warn if we detect configurations for multiple registered storage engines in the same
// configuration file/environment.
if (serverGlobalParams.parsedOpts.hasField("storage")) {
@@ -313,7 +314,7 @@ int initialize(int argc, char* argv[], char** envp) {
serviceContext->notifyStartupComplete();
- return 0;
+ return serviceContext;
}
} // namespace embedded
} // namespace mongo
diff --git a/src/mongo/client/embedded/embedded.h b/src/mongo/client/embedded/embedded.h
index b3e91953e04..714c6c1c90a 100644
--- a/src/mongo/client/embedded/embedded.h
+++ b/src/mongo/client/embedded/embedded.h
@@ -31,8 +31,10 @@
#include "mongo/platform/basic.h"
namespace mongo {
+class ServiceContext;
+
namespace embedded {
-int initialize(int argc, char* argv[], char** envp);
-void shutdown();
+ServiceContext* initialize(int argc, char* argv[], char** envp);
+void shutdown(ServiceContext* serviceContext);
} // namespace embedded
} // namespace mongo
diff --git a/src/mongo/client/embedded/libmongodbcapi.cpp b/src/mongo/client/embedded/libmongodbcapi.cpp
index a58b36c5f01..3309a06f544 100644
--- a/src/mongo/client/embedded/libmongodbcapi.cpp
+++ b/src/mongo/client/embedded/libmongodbcapi.cpp
@@ -82,7 +82,6 @@ namespace {
bool libraryInitialized_ = false;
libmongodbcapi_db* global_db = nullptr;
thread_local int last_error = LIBMONGODB_CAPI_SUCCESS;
-bool run_setup = false;
libmongodbcapi_db* db_new(int argc, const char** argv, const char** envp) noexcept try {
last_error = LIBMONGODB_CAPI_SUCCESS;
@@ -93,40 +92,33 @@ libmongodbcapi_db* db_new(int argc, const char** argv, const char** envp) noexce
}
global_db = new libmongodbcapi_db;
- if (!run_setup) {
- // iterate over argv and copy them to argvStorage
- for (int i = 0; i < argc; i++) {
- // allocate space for the null terminator
- auto s = mongo::stdx::make_unique<char[]>(std::strlen(argv[i]) + 1);
- // copy the string + null terminator
- std::strncpy(s.get(), argv[i], std::strlen(argv[i]) + 1);
- global_db->argvPointers.push_back(s.get());
- global_db->argvStorage.push_back(std::move(s));
- }
- global_db->argvPointers.push_back(nullptr);
-
- // iterate over envp and copy them to envpStorage
- while (envp != nullptr && *envp != nullptr) {
- auto s = mongo::stdx::make_unique<char[]>(std::strlen(*envp) + 1);
- std::strncpy(s.get(), *envp, std::strlen(*envp) + 1);
- global_db->envpPointers.push_back(s.get());
- global_db->envpStorage.push_back(std::move(s));
- envp++;
- }
- global_db->envpPointers.push_back(nullptr);
+ // iterate over argv and copy them to argvStorage
+ for (int i = 0; i < argc; i++) {
+ // allocate space for the null terminator
+ auto s = mongo::stdx::make_unique<char[]>(std::strlen(argv[i]) + 1);
+ // copy the string + null terminator
+ std::strncpy(s.get(), argv[i], std::strlen(argv[i]) + 1);
+ global_db->argvPointers.push_back(s.get());
+ global_db->argvStorage.push_back(std::move(s));
+ }
+ global_db->argvPointers.push_back(nullptr);
+
+ // iterate over envp and copy them to envpStorage
+ while (envp != nullptr && *envp != nullptr) {
+ auto s = mongo::stdx::make_unique<char[]>(std::strlen(*envp) + 1);
+ std::strncpy(s.get(), *envp, std::strlen(*envp) + 1);
+ global_db->envpPointers.push_back(s.get());
+ global_db->envpStorage.push_back(std::move(s));
+ envp++;
+ }
+ global_db->envpPointers.push_back(nullptr);
+ global_db->serviceContext =
embedded::initialize(argc, global_db->argvPointers.data(), global_db->envpPointers.data());
-
- // wait until the global service context is not null
- global_db->serviceContext = waitAndGetGlobalServiceContext();
-
- // block until the global service context is initialized
- global_db->serviceContext->waitForStartupComplete();
-
- run_setup = true;
- } else {
- // wait until the global service context is not null
- global_db->serviceContext = waitAndGetGlobalServiceContext();
+ if (!global_db->serviceContext) {
+ delete global_db;
+ global_db = nullptr;
+ throw std::runtime_error("Initialization failed");
}
// creating mock transport layer to be able to create sessions
@@ -138,12 +130,13 @@ libmongodbcapi_db* db_new(int argc, const char** argv, const char** envp) noexce
return nullptr;
}
-void db_destroy(libmongodbcapi_db* db) noexcept {
- // todo, we can't teardown and re-initialize yet.
- /*if (run_setup) {
- embedded::shutdown();
- run_setup = false;
- }*/
+int db_destroy(libmongodbcapi_db* db) noexcept {
+ if (!db->open_clients.empty()) {
+ last_error = LIBMONGODB_CAPI_ERROR_UNKNOWN;
+ return last_error;
+ }
+
+ embedded::shutdown(global_db->serviceContext);
delete db;
invariant(!db || db == global_db);
@@ -151,6 +144,7 @@ void db_destroy(libmongodbcapi_db* db) noexcept {
global_db = nullptr;
}
last_error = LIBMONGODB_CAPI_SUCCESS;
+ return last_error;
}
int db_pump(libmongodbcapi_db* db) noexcept try {
@@ -239,7 +233,7 @@ libmongodbcapi_db* libmongodbcapi_db_new(int argc, const char** argv, const char
return mongo::db_new(argc, argv, envp);
}
-void libmongodbcapi_db_destroy(libmongodbcapi_db* db) {
+int libmongodbcapi_db_destroy(libmongodbcapi_db* db) {
return mongo::db_destroy(db);
}
diff --git a/src/mongo/client/embedded/libmongodbcapi.h b/src/mongo/client/embedded/libmongodbcapi.h
index a3763978e12..8c1646dd9b6 100644
--- a/src/mongo/client/embedded/libmongodbcapi.h
+++ b/src/mongo/client/embedded/libmongodbcapi.h
@@ -95,8 +95,10 @@ libmongodbcapi_db* libmongodbcapi_db_new(int argc, const char** argv, const char
*
* @param
* A pointer to a db handle to be destroyed
+*
+* @return A libmongo error code
*/
-void libmongodbcapi_db_destroy(libmongodbcapi_db* db);
+int libmongodbcapi_db_destroy(libmongodbcapi_db* db);
/**
* Let the database do background work. Returns an int from the error enum
diff --git a/src/mongo/client/embedded/libmongodbcapi_test.cpp b/src/mongo/client/embedded/libmongodbcapi_test.cpp
index f1087e4f849..967b59b1acd 100644
--- a/src/mongo/client/embedded/libmongodbcapi_test.cpp
+++ b/src/mongo/client/embedded/libmongodbcapi_test.cpp
@@ -138,10 +138,10 @@ TEST_F(MongodbCAPITest, CreateAndDestroyDBAndClient) {
auto client = createClient();
}
-// This test is to make sure that destroying the db will destroy all of its clients
-// This test will only fail under ASAN
+// This test is to make sure that destroying the db will fail if there's remaining clients left.
TEST_F(MongodbCAPITest, DoNotDestroyClient) {
- createClient().release();
+ auto client = createClient();
+ ASSERT(libmongodbcapi_db_destroy(getDB()) != LIBMONGODB_CAPI_SUCCESS);
}
TEST_F(MongodbCAPITest, CreateMultipleClients) {
@@ -415,7 +415,7 @@ int main(int argc, char** argv, char** envp) {
return EXIT_FAILURE;
}
- auto result = ::mongo::unittest::Suite::run(std::vector<std::string>(), "", 1);
+ ::mongo::unittest::Suite::run(std::vector<std::string>(), "", 1);
int fini = libmongodbcapi_fini();
if (fini != LIBMONGODB_CAPI_SUCCESS) {
@@ -424,5 +424,4 @@ int main(int argc, char** argv, char** envp) {
}
globalTempDir.reset();
- mongo::quickExit(result);
}
diff --git a/src/mongo/client/embedded/service_context_embedded.cpp b/src/mongo/client/embedded/service_context_embedded.cpp
index 597792a7846..6558ea3b897 100644
--- a/src/mongo/client/embedded/service_context_embedded.cpp
+++ b/src/mongo/client/embedded/service_context_embedded.cpp
@@ -37,6 +37,7 @@
#include "mongo/db/client.h"
#include "mongo/db/concurrency/lock_state.h"
#include "mongo/db/operation_context.h"
+#include "mongo/db/service_context_registrar.h"
#include "mongo/db/storage/storage_engine.h"
#include "mongo/db/storage/storage_engine_lock_file.h"
#include "mongo/db/storage/storage_engine_metadata.h"
@@ -51,19 +52,14 @@
namespace mongo {
namespace {
-auto makeMongoEmbeddedServiceContext() {
- auto service = stdx::make_unique<ServiceContextMongoEmbedded>();
- service->setServiceEntryPoint(stdx::make_unique<ServiceEntryPointEmbedded>(service.get()));
- service->setTickSource(stdx::make_unique<SystemTickSource>());
- service->setFastClockSource(stdx::make_unique<SystemClockSource>());
- service->setPreciseClockSource(stdx::make_unique<SystemClockSource>());
+ServiceContextRegistrar serviceContextCreator([]() {
+ auto service = std::make_unique<ServiceContextMongoEmbedded>();
+ service->setServiceEntryPoint(std::make_unique<ServiceEntryPointEmbedded>(service.get()));
+ service->setTickSource(std::make_unique<SystemTickSource>());
+ service->setFastClockSource(std::make_unique<SystemClockSource>());
+ service->setPreciseClockSource(std::make_unique<SystemClockSource>());
return service;
-}
-
-MONGO_INITIALIZER(SetGlobalEnvironment)(InitializerContext* context) {
- setGlobalServiceContext(makeMongoEmbeddedServiceContext());
- return Status::OK();
-}
+});
} // namespace
extern bool _supportsDocLocking;
@@ -76,7 +72,7 @@ StorageEngine* ServiceContextMongoEmbedded::getGlobalStorageEngine() {
// We don't check that globalStorageEngine is not-NULL here intentionally. We can encounter
// an error before it's initialized and proceed to exitCleanly which is equipped to deal
// with a NULL storage engine.
- return _storageEngine;
+ return _storageEngine.get();
}
void ServiceContextMongoEmbedded::createLockFile() {
@@ -134,10 +130,10 @@ void ServiceContextMongoEmbedded::initializeGlobalStorageEngine() {
if (storageGlobalParams.engineSetByUser) {
// Verify that the name of the user-supplied storage engine matches the contents of
// the metadata file.
- const StorageEngine::Factory* factory =
- mapFindWithDefault(_storageFactories,
- storageGlobalParams.engine,
- static_cast<const StorageEngine::Factory*>(nullptr));
+ const StorageEngine::Factory* factory = nullptr;
+ auto it = _storageFactories.find(storageGlobalParams.engine);
+ if (it != _storageFactories.end())
+ factory = it->second.get();
if (factory) {
uassert(50667,
@@ -185,7 +181,7 @@ void ServiceContextMongoEmbedded::initializeGlobalStorageEngine() {
<< " is only supported by the mmapv1 storage engine",
repairpath.empty() || repairpath == dbpath || storageGlobalParams.engine == "mmapv1");
- const StorageEngine::Factory* factory = _storageFactories[storageGlobalParams.engine];
+ const auto& factory = _storageFactories[storageGlobalParams.engine];
uassert(50681,
str::stream() << "Cannot start server with an unknown storage engine: "
@@ -221,7 +217,7 @@ void ServiceContextMongoEmbedded::initializeGlobalStorageEngine() {
}
});
- _storageEngine = factory->create(storageGlobalParams, _lockFile.get());
+ _storageEngine.reset(factory->create(storageGlobalParams, _lockFile.get()));
_storageEngine->finishInit();
if (_lockFile) {
@@ -261,7 +257,7 @@ void ServiceContextMongoEmbedded::registerStorageEngine(const std::string& name,
// and all factories should be added before we pick a storage engine.
invariant(NULL == _storageEngine);
- _storageFactories[name] = factory;
+ _storageFactories[name].reset(factory);
}
bool ServiceContextMongoEmbedded::isRegisteredStorageEngine(const std::string& name) {
@@ -282,7 +278,7 @@ bool StorageFactoriesIteratorMongoEmbedded::more() const {
}
const StorageEngine::Factory* StorageFactoriesIteratorMongoEmbedded::next() {
- return _curr++->second;
+ return _curr++->second.get();
}
std::unique_ptr<OperationContext> ServiceContextMongoEmbedded::_newOpCtx(Client* client,
diff --git a/src/mongo/client/embedded/service_context_embedded.h b/src/mongo/client/embedded/service_context_embedded.h
index 661c96d4677..5954060cd0e 100644
--- a/src/mongo/client/embedded/service_context_embedded.h
+++ b/src/mongo/client/embedded/service_context_embedded.h
@@ -39,7 +39,7 @@ class StorageEngineLockFile;
class ServiceContextMongoEmbedded final : public ServiceContext {
public:
- using FactoryMap = std::map<std::string, const StorageEngine::Factory*>;
+ using FactoryMap = std::map<std::string, std::unique_ptr<const StorageEngine::Factory>>;
ServiceContextMongoEmbedded();
@@ -65,8 +65,7 @@ private:
std::unique_ptr<StorageEngineLockFile> _lockFile;
- // logically owned here, but never deleted by anyone.
- StorageEngine* _storageEngine = nullptr;
+ std::unique_ptr<StorageEngine> _storageEngine;
// All possible storage engines are registered here through MONGO_INIT.
FactoryMap _storageFactories;
diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript
index 99287b19945..1cc6e1ba889 100644
--- a/src/mongo/db/SConscript
+++ b/src/mongo/db/SConscript
@@ -470,6 +470,7 @@ env.Library(
'operation_context_group.cpp',
'service_context.cpp',
'service_context_noop.cpp',
+ 'service_context_registrar.cpp',
'unclean_shutdown.cpp',
],
LIBDEPS=[
diff --git a/src/mongo/db/auth/auth_decorations.cpp b/src/mongo/db/auth/auth_decorations.cpp
index bf1b31ca148..b0c1e79f4a9 100644
--- a/src/mongo/db/auth/auth_decorations.cpp
+++ b/src/mongo/db/auth/auth_decorations.cpp
@@ -86,10 +86,7 @@ AuthorizationManager* AuthorizationManager::get(ServiceContext& service) {
void AuthorizationManager::set(ServiceContext* service,
std::unique_ptr<AuthorizationManager> authzManager) {
- auto& manager = getAuthorizationManager(service);
- invariant(authzManager);
- invariant(!manager);
- manager = std::move(authzManager);
+ getAuthorizationManager(service) = std::move(authzManager);
service->registerClientObserver(stdx::make_unique<AuthzClientObserver>());
}
diff --git a/src/mongo/db/auth/authorization_manager_global.cpp b/src/mongo/db/auth/authorization_manager_global.cpp
index 3172d7e1626..39505fab014 100644
--- a/src/mongo/db/auth/authorization_manager_global.cpp
+++ b/src/mongo/db/auth/authorization_manager_global.cpp
@@ -90,20 +90,24 @@ AuthorizationManager* getGlobalAuthorizationManager() {
MONGO_EXPORT_STARTUP_SERVER_PARAMETER(startupAuthSchemaValidation, bool, true);
-MONGO_INITIALIZER_WITH_PREREQUISITES(CreateAuthorizationManager,
- ("SetupInternalSecurityUser",
- "OIDGeneration",
- "SetGlobalEnvironment",
- "CreateAuthorizationExternalStateFactory",
- "EndStartupOptionStorage"))
-(InitializerContext* context) {
- auto authzManager =
- stdx::make_unique<AuthorizationManager>(AuthzManagerExternalState::create());
- authzManager->setAuthEnabled(serverGlobalParams.authState ==
- ServerGlobalParams::AuthState::kEnabled);
- authzManager->setShouldValidateAuthSchemaOnStartup(startupAuthSchemaValidation);
- AuthorizationManager::set(getGlobalServiceContext(), std::move(authzManager));
- return Status::OK();
-}
+GlobalInitializerRegisterer authorizationManagerInitializer(
+ "CreateAuthorizationManager",
+ {"SetupInternalSecurityUser",
+ "OIDGeneration",
+ "CreateAuthorizationExternalStateFactory",
+ "EndStartupOptionStorage"},
+ [](InitializerContext* context) {
+ auto authzManager =
+ stdx::make_unique<AuthorizationManager>(AuthzManagerExternalState::create());
+ authzManager->setAuthEnabled(serverGlobalParams.authState ==
+ ServerGlobalParams::AuthState::kEnabled);
+ authzManager->setShouldValidateAuthSchemaOnStartup(startupAuthSchemaValidation);
+ AuthorizationManager::set(context->serviceContext(), std::move(authzManager));
+ return Status::OK();
+ },
+ [](DeinitializerContext* context) {
+ AuthorizationManager::set(context->serviceContext(), nullptr);
+ return Status::OK();
+ });
} // namespace mongo
diff --git a/src/mongo/db/auth/sasl_mechanism_registry.cpp b/src/mongo/db/auth/sasl_mechanism_registry.cpp
index b46ba9978f3..1572acb2794 100644
--- a/src/mongo/db/auth/sasl_mechanism_registry.cpp
+++ b/src/mongo/db/auth/sasl_mechanism_registry.cpp
@@ -164,16 +164,22 @@ bool SASLServerMechanismRegistry::_mechanismSupportedByConfig(StringData mechNam
return sequenceContains(saslGlobalParams.authenticationMechanisms, mechName);
}
-MONGO_INITIALIZER_WITH_PREREQUISITES(CreateSASLServerMechanismRegistry, ("SetGlobalEnvironment"))
-(::mongo::InitializerContext* context) {
- if (saslGlobalParams.hostName.empty())
- saslGlobalParams.hostName = getHostNameCached();
- if (saslGlobalParams.serviceName.empty())
- saslGlobalParams.serviceName = "mongodb";
-
- auto registry = stdx::make_unique<SASLServerMechanismRegistry>();
- SASLServerMechanismRegistry::set(getGlobalServiceContext(), std::move(registry));
- return Status::OK();
-}
+GlobalInitializerRegisterer SASLServerMechanismRegistryInitializer(
+ "CreateSASLServerMechanismRegistry",
+ [](InitializerContext* context) {
+ if (saslGlobalParams.hostName.empty())
+ saslGlobalParams.hostName = getHostNameCached();
+ if (saslGlobalParams.serviceName.empty())
+ saslGlobalParams.serviceName = "mongodb";
+
+ auto registry = stdx::make_unique<SASLServerMechanismRegistry>();
+ SASLServerMechanismRegistry::set(context->serviceContext(), std::move(registry));
+ return Status::OK();
+ },
+ [](DeinitializerContext* context) {
+ SASLServerMechanismRegistry::set(context->serviceContext(), nullptr);
+
+ return Status::OK();
+ });
} // namespace mongo
diff --git a/src/mongo/db/catalog/database_holder_impl.cpp b/src/mongo/db/catalog/database_holder_impl.cpp
index 1c999013e33..d5b5560df67 100644
--- a/src/mongo/db/catalog/database_holder_impl.cpp
+++ b/src/mongo/db/catalog/database_holder_impl.cpp
@@ -51,16 +51,24 @@
namespace mongo {
namespace {
+DatabaseHolder* _dbHolder = nullptr;
+
DatabaseHolder& dbHolderImpl() {
- static DatabaseHolder _dbHolder;
- return _dbHolder;
+ return *_dbHolder;
}
-MONGO_INITIALIZER_WITH_PREREQUISITES(InitializeDbHolderimpl, ("InitializeDatabaseHolderFactory"))
-(InitializerContext* const) {
- registerDbHolderImpl(dbHolderImpl);
- return Status::OK();
-}
+GlobalInitializerRegisterer dbHolderImplInitializer("InitializeDbHolderimpl",
+ {"InitializeDatabaseHolderFactory"},
+ [](InitializerContext* const) {
+ _dbHolder = new DatabaseHolder();
+ registerDbHolderImpl(dbHolderImpl);
+ return Status::OK();
+ },
+ [](DeinitializerContext* const) {
+ delete _dbHolder;
+ _dbHolder = nullptr;
+ return Status::OK();
+ });
MONGO_INITIALIZER(InitializeDatabaseHolderFactory)(InitializerContext* const) {
DatabaseHolder::registerFactory([] { return stdx::make_unique<DatabaseHolderImpl>(); });
diff --git a/src/mongo/db/db.cpp b/src/mongo/db/db.cpp
index cacb7f941a3..beb87a5d086 100644
--- a/src/mongo/db/db.cpp
+++ b/src/mongo/db/db.cpp
@@ -118,6 +118,7 @@
#include "mongo/db/server_parameters.h"
#include "mongo/db/service_context.h"
#include "mongo/db/service_context_d.h"
+#include "mongo/db/service_context_registrar.h"
#include "mongo/db/service_entry_point_mongod.h"
#include "mongo/db/session_catalog.h"
#include "mongo/db/session_killer.h"
@@ -757,8 +758,7 @@ auto makeReplicationExecutor(ServiceContext* serviceContext) {
"NetworkInterfaceASIO-Replication", nullptr, std::move(hookList)));
}
-MONGO_INITIALIZER_WITH_PREREQUISITES(CreateReplicationManager,
- ("SetGlobalEnvironment", "SSLManager", "default"))
+MONGO_INITIALIZER_WITH_PREREQUISITES(CreateReplicationManager, ("SSLManager", "default"))
(InitializerContext* context) {
auto serviceContext = getGlobalServiceContext();
repl::StorageInterface::set(serviceContext, stdx::make_unique<repl::StorageInterfaceImpl>());
@@ -958,7 +958,8 @@ int mongoDbMain(int argc, char* argv[], char** envp) {
srand(static_cast<unsigned>(curTimeMicros64()));
- Status status = mongo::runGlobalInitializers(argc, argv, envp);
+ setGlobalServiceContext(createServiceContext());
+ Status status = mongo::runGlobalInitializers(argc, argv, envp, getGlobalServiceContext());
if (!status.isOK()) {
severe(LogComponent::kControl) << "Failed global initialization: " << status;
quickExit(EXIT_FAILURE);
diff --git a/src/mongo/db/pipeline/document_source_sample_test.cpp b/src/mongo/db/pipeline/document_source_sample_test.cpp
index c1c85924c50..439e0ce3e36 100644
--- a/src/mongo/db/pipeline/document_source_sample_test.cpp
+++ b/src/mongo/db/pipeline/document_source_sample_test.cpp
@@ -40,7 +40,6 @@
#include "mongo/db/pipeline/document_source_sample_from_random_cursor.h"
#include "mongo/db/pipeline/document_value_test_util.h"
#include "mongo/db/pipeline/expression_context.h"
-#include "mongo/db/service_context.h"
#include "mongo/stdx/memory.h"
#include "mongo/unittest/death_test.h"
#include "mongo/unittest/unittest.h"
diff --git a/src/mongo/db/query/collation/collator_factory_icu_decoration.cpp b/src/mongo/db/query/collation/collator_factory_icu_decoration.cpp
index 46ddbf54d8b..e37ce036511 100644
--- a/src/mongo/db/query/collation/collator_factory_icu_decoration.cpp
+++ b/src/mongo/db/query/collation/collator_factory_icu_decoration.cpp
@@ -37,7 +37,7 @@ namespace mongo {
namespace {
-MONGO_INITIALIZER_WITH_PREREQUISITES(CreateCollatorFactory, ("SetGlobalEnvironment", "LoadICUData"))
+MONGO_INITIALIZER_WITH_PREREQUISITES(CreateCollatorFactory, ("LoadICUData"))
(InitializerContext* context) {
CollatorFactoryInterface::set(getGlobalServiceContext(),
stdx::make_unique<CollatorFactoryICU>());
diff --git a/src/mongo/db/query/datetime/init_timezone_data.cpp b/src/mongo/db/query/datetime/init_timezone_data.cpp
index b86159e3976..0c17cca0457 100644
--- a/src/mongo/db/query/datetime/init_timezone_data.cpp
+++ b/src/mongo/db/query/datetime/init_timezone_data.cpp
@@ -39,8 +39,8 @@
namespace mongo {
-MONGO_INITIALIZER_WITH_PREREQUISITES(
- LoadTimeZoneDB, ("GlobalLogManager", "SetGlobalEnvironment", "EndStartupOptionStorage"))
+MONGO_INITIALIZER_WITH_PREREQUISITES(LoadTimeZoneDB,
+ ("GlobalLogManager", "EndStartupOptionStorage"))
(InitializerContext* context) {
auto serviceContext = getGlobalServiceContext();
if (!serverGlobalParams.timeZoneInfoPath.empty()) {
diff --git a/src/mongo/db/repl/service_context_repl_mock_init.cpp b/src/mongo/db/repl/service_context_repl_mock_init.cpp
index 720457b3469..c35b47f61d7 100644
--- a/src/mongo/db/repl/service_context_repl_mock_init.cpp
+++ b/src/mongo/db/repl/service_context_repl_mock_init.cpp
@@ -31,17 +31,18 @@
#include "mongo/base/init.h"
#include "mongo/db/repl/service_context_repl_mock.h"
#include "mongo/db/service_context.h"
-#include "mongo/stdx/memory.h"
+#include "mongo/db/service_context_registrar.h"
#include "mongo/util/clock_source_mock.h"
+#include <memory>
+
namespace mongo {
namespace repl {
namespace {
-MONGO_INITIALIZER(SetGlobalEnvironment)(InitializerContext* context) {
- setGlobalServiceContext(stdx::make_unique<ServiceContextReplMock>());
- return Status::OK();
-}
+ServiceContextRegistrar serviceContextCreator([]() {
+ return std::make_unique<ServiceContextReplMock>();
+});
} // namespace
} // namespace repl
diff --git a/src/mongo/db/service_context.cpp b/src/mongo/db/service_context.cpp
index 48004bf0174..b3392b684bc 100644
--- a/src/mongo/db/service_context.cpp
+++ b/src/mongo/db/service_context.cpp
@@ -69,9 +69,13 @@ ServiceContext* waitAndGetGlobalServiceContext() {
}
void setGlobalServiceContext(std::unique_ptr<ServiceContext>&& serviceContext) {
- fassert(17509, serviceContext.get());
-
- delete globalServiceContext;
+ if (globalServiceContext) {
+ // Make sure that calling getGlobalServiceContext() during the destructor results in
+ // nullptr. Decorations might try and do this.
+ auto oldServiceContext = globalServiceContext;
+ globalServiceContext = nullptr;
+ delete oldServiceContext;
+ }
stdx::lock_guard<stdx::mutex> lk(globalServiceContextMutex);
diff --git a/src/mongo/db/service_context_d.cpp b/src/mongo/db/service_context_d.cpp
index 3dad551125c..95459a6e41e 100644
--- a/src/mongo/db/service_context_d.cpp
+++ b/src/mongo/db/service_context_d.cpp
@@ -37,6 +37,7 @@
#include "mongo/db/client.h"
#include "mongo/db/concurrency/lock_state.h"
#include "mongo/db/operation_context.h"
+#include "mongo/db/service_context_registrar.h"
#include "mongo/db/service_entry_point_mongod.h"
#include "mongo/db/storage/storage_engine.h"
#include "mongo/db/storage/storage_engine_lock_file.h"
@@ -53,19 +54,14 @@
namespace mongo {
namespace {
-auto makeMongoDServiceContext() {
- auto service = stdx::make_unique<ServiceContextMongoD>();
- service->setServiceEntryPoint(stdx::make_unique<ServiceEntryPointMongod>(service.get()));
- service->setTickSource(stdx::make_unique<SystemTickSource>());
- service->setFastClockSource(stdx::make_unique<SystemClockSource>());
- service->setPreciseClockSource(stdx::make_unique<SystemClockSource>());
+ServiceContextRegistrar serviceContextCreator([]() {
+ auto service = std::make_unique<ServiceContextMongoD>();
+ service->setServiceEntryPoint(std::make_unique<ServiceEntryPointMongod>(service.get()));
+ service->setTickSource(std::make_unique<SystemTickSource>());
+ service->setFastClockSource(std::make_unique<SystemClockSource>());
+ service->setPreciseClockSource(std::make_unique<SystemClockSource>());
return service;
-}
-
-MONGO_INITIALIZER(SetGlobalEnvironment)(InitializerContext* context) {
- setGlobalServiceContext(makeMongoDServiceContext());
- return Status::OK();
-}
+});
} // namespace
extern bool _supportsDocLocking;
diff --git a/src/mongo/base/deinitializer_context.cpp b/src/mongo/db/service_context_fwd.h
index 1708587da36..48c36da674f 100644
--- a/src/mongo/base/deinitializer_context.cpp
+++ b/src/mongo/db/service_context_fwd.h
@@ -1,4 +1,5 @@
-/* Copyright 2018 MongoDB Inc.
+/**
+ * Copyright (C) 2018 MongoDB Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
@@ -16,15 +17,19 @@
* code of portions of this program with the OpenSSL library under certain
* conditions as described in each individual source file and distribute
* linked combinations including the program with the OpenSSL library. You
- * must comply with the GNU Affero General Public License in all respects
- * for all of the code used other than as permitted herein. If you modify
- * file(s) with this exception, you may extend this exception to your
- * version of the file(s), but you are not obligated to do so. If you do not
- * wish to do so, delete this exception statement from your version. If you
- * delete this exception statement from all source files in the program,
- * then also delete it in the license file.
+ * must comply with the GNU Affero General Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
*/
-#include "mongo/base/deinitializer_context.h"
+#pragma once
-namespace mongo {} // namespace mongo
+namespace mongo {
+
+class ServiceContext;
+
+} // namespace mongo
diff --git a/src/mongo/db/service_context_noop_init.cpp b/src/mongo/db/service_context_noop_init.cpp
index 8c66da1bd5a..27e4306ad49 100644
--- a/src/mongo/db/service_context_noop_init.cpp
+++ b/src/mongo/db/service_context_noop_init.cpp
@@ -31,16 +31,16 @@
#include "mongo/base/init.h"
#include "mongo/db/service_context.h"
#include "mongo/db/service_context_noop.h"
+#include "mongo/db/service_context_registrar.h"
#include "mongo/stdx/memory.h"
namespace mongo {
namespace {
-MONGO_INITIALIZER(SetGlobalEnvironment)(InitializerContext* context) {
- setGlobalServiceContext(stdx::make_unique<ServiceContextNoop>());
- return Status::OK();
-}
+ServiceContextRegistrar serviceContextEmbeddedFactory([]() {
+ return std::make_unique<ServiceContextNoop>();
+});
} // namespace
} // namespace mongo
diff --git a/src/mongo/db/service_context_registrar.cpp b/src/mongo/db/service_context_registrar.cpp
new file mode 100644
index 00000000000..26aa48ac15b
--- /dev/null
+++ b/src/mongo/db/service_context_registrar.cpp
@@ -0,0 +1,54 @@
+/**
+* Copyright (C) 2018 MongoDB Inc.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Affero General Public License, version 3,
+* as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Affero General Public License for more details.
+*
+* You should have received a copy of the GNU Affero General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+* As a special exception, the copyright holders give permission to link the
+* code of portions of this program with the OpenSSL library under certain
+* conditions as described in each individual source file and distribute
+* linked combinations including the program with the OpenSSL library. You
+* must comply with the GNU Affero General Public License in all respects for
+* all of the code used other than as permitted herein. If you modify file(s)
+* with this exception, you may extend this exception to your version of the
+* file(s), but you are not obligated to do so. If you do not wish to do so,
+* delete this exception statement from your version. If you delete this
+* exception statement from all source files in the program, then also delete
+* it in the license file.
+*/
+
+#include "mongo/db/service_context_registrar.h"
+
+#include "mongo/db/service_context.h"
+
+namespace mongo {
+namespace {
+std::function<std::unique_ptr<ServiceContext>()>& getServiceContextFactory() {
+ static std::function<std::unique_ptr<ServiceContext>()> factory;
+ return factory;
+}
+}
+
+ServiceContextRegistrar::ServiceContextRegistrar(
+ std::function<std::unique_ptr<ServiceContext>()> fn) {
+ invariant(!hasServiceContextFactory());
+ getServiceContextFactory() = std::move(fn);
+}
+
+bool hasServiceContextFactory() {
+ return getServiceContextFactory() ? true : false;
+}
+
+std::unique_ptr<ServiceContext> createServiceContext() {
+ return getServiceContextFactory()();
+}
+} // namespace mongo
diff --git a/src/mongo/db/service_context_registrar.h b/src/mongo/db/service_context_registrar.h
new file mode 100644
index 00000000000..2317d8862f6
--- /dev/null
+++ b/src/mongo/db/service_context_registrar.h
@@ -0,0 +1,48 @@
+/**
+* Copyright (C) 2018 MongoDB Inc.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Affero General Public License, version 3,
+* as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Affero General Public License for more details.
+*
+* You should have received a copy of the GNU Affero General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+* As a special exception, the copyright holders give permission to link the
+* code of portions of this program with the OpenSSL library under certain
+* conditions as described in each individual source file and distribute
+* linked combinations including the program with the OpenSSL library. You
+* must comply with the GNU Affero General Public License in all respects for
+* all of the code used other than as permitted herein. If you modify file(s)
+* with this exception, you may extend this exception to your version of the
+* file(s), but you are not obligated to do so. If you do not wish to do so,
+* delete this exception statement from your version. If you delete this
+* exception statement from all source files in the program, then also delete
+* it in the license file.
+*/
+
+#pragma once
+
+#include <functional>
+#include <memory>
+
+namespace mongo {
+class ServiceContext;
+
+// This is a initialization registration system similar to MONGO_INITIALIZER. But it cannot be an
+// MONGO_INITIALIZER because we need to create the service context before the MONGO_INITIALIZERS
+// execute. This class should probably be refactored to use the shim system from this ticket:
+// https://jira.mongodb.org/browse/SERVER-32645
+class ServiceContextRegistrar {
+public:
+ explicit ServiceContextRegistrar(std::function<std::unique_ptr<ServiceContext>()> fn);
+};
+
+bool hasServiceContextFactory();
+std::unique_ptr<ServiceContext> createServiceContext();
+} // namespace mongo
diff --git a/src/mongo/db/sorter/sorter_test.cpp b/src/mongo/db/sorter/sorter_test.cpp
index 6a85cbfaef2..3ba4e8a98c3 100644
--- a/src/mongo/db/sorter/sorter_test.cpp
+++ b/src/mongo/db/sorter/sorter_test.cpp
@@ -38,7 +38,7 @@
#include "mongo/config.h"
#include "mongo/db/service_context.h"
#include "mongo/db/service_context_noop.h"
-#include "mongo/stdx/memory.h"
+#include "mongo/db/service_context_registrar.h"
#include "mongo/stdx/thread.h"
#include "mongo/unittest/temp_dir.h"
#include "mongo/unittest/unittest.h"
@@ -47,6 +47,8 @@
// Need access to internal classes
#include "mongo/db/sorter/sorter.cpp"
+#include <memory>
+
namespace mongo {
using namespace mongo::sorter;
using std::make_shared;
@@ -55,10 +57,9 @@ using std::pair;
namespace {
// Stub to avoid including the server environment library.
-MONGO_INITIALIZER(SetGlobalEnvironment)(InitializerContext* context) {
- setGlobalServiceContext(stdx::make_unique<ServiceContextNoop>());
- return Status::OK();
-}
+ServiceContextRegistrar serviceContextCreator([]() {
+ return std::make_unique<ServiceContextNoop>();
+});
} // namespace
//
diff --git a/src/mongo/db/storage/devnull/devnull_init.cpp b/src/mongo/db/storage/devnull/devnull_init.cpp
index 7403a5d2fb9..dff10077427 100644
--- a/src/mongo/db/storage/devnull/devnull_init.cpp
+++ b/src/mongo/db/storage/devnull/devnull_init.cpp
@@ -1,5 +1,3 @@
-// devnull_init.cpp
-
/**
* Copyright (C) 2014 MongoDB Inc.
*
@@ -66,7 +64,7 @@ public:
};
} // namespace
-MONGO_INITIALIZER_WITH_PREREQUISITES(DevNullEngineInit, ("SetGlobalEnvironment"))
+MONGO_INITIALIZER(DevNullEngineInit)
(InitializerContext* context) {
getGlobalServiceContext()->registerStorageEngine("devnull", new DevNullStorageEngineFactory());
return Status::OK();
diff --git a/src/mongo/db/storage/encryption_hooks.cpp b/src/mongo/db/storage/encryption_hooks.cpp
index 9ee9a317dbe..8a81d20dd2d 100644
--- a/src/mongo/db/storage/encryption_hooks.cpp
+++ b/src/mongo/db/storage/encryption_hooks.cpp
@@ -41,7 +41,7 @@
namespace mongo {
/* Make a EncryptionHooks pointer a decoration on the global ServiceContext */
-MONGO_INITIALIZER_WITH_PREREQUISITES(SetEncryptionHooks, ("SetGlobalEnvironment"))
+MONGO_INITIALIZER(SetEncryptionHooks)
(InitializerContext* context) {
auto encryptionHooks = stdx::make_unique<EncryptionHooks>();
EncryptionHooks::set(getGlobalServiceContext(), std::move(encryptionHooks));
diff --git a/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_init.cpp b/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_init.cpp
index df936cfacb8..b52507c20df 100644
--- a/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_init.cpp
+++ b/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_init.cpp
@@ -72,7 +72,7 @@ public:
} // namespace
-MONGO_INITIALIZER_WITH_PREREQUISITES(EphemeralForTestEngineInit, ("SetGlobalEnvironment"))
+MONGO_INITIALIZER(EphemeralForTestEngineInit)
(InitializerContext* context) {
getGlobalServiceContext()->registerStorageEngine("ephemeralForTest",
new EphemeralForTestFactory());
diff --git a/src/mongo/db/storage/mmap_v1/mmap_v1_init.cpp b/src/mongo/db/storage/mmap_v1/mmap_v1_init.cpp
index 10eb30243f4..08f586f2035 100644
--- a/src/mongo/db/storage/mmap_v1/mmap_v1_init.cpp
+++ b/src/mongo/db/storage/mmap_v1/mmap_v1_init.cpp
@@ -76,7 +76,7 @@ public:
} // namespace
-MONGO_INITIALIZER_WITH_PREREQUISITES(MMAPV1EngineInit, ("SetGlobalEnvironment"))
+MONGO_INITIALIZER(MMAPV1EngineInit)
(InitializerContext* context) {
getGlobalServiceContext()->registerStorageEngine("mmapv1", new MMAPV1Factory());
return Status::OK();
diff --git a/src/mongo/db/storage/mobile/mobile_init.cpp b/src/mongo/db/storage/mobile/mobile_init.cpp
index 08d078cd2fc..c9d895d0332 100644
--- a/src/mongo/db/storage/mobile/mobile_init.cpp
+++ b/src/mongo/db/storage/mobile/mobile_init.cpp
@@ -70,10 +70,12 @@ public:
};
} // namespace
-MONGO_INITIALIZER_WITH_PREREQUISITES(MobileKVEngineInit, ("SetGlobalEnvironment"))
-(InitializerContext* context) {
- getGlobalServiceContext()->registerStorageEngine("mobile", new MobileFactory());
- return Status::OK();
-}
+GlobalInitializerRegisterer mobileKVEngineInitializer(
+ "MobileKVEngineInit",
+ [](InitializerContext* context) {
+ context->serviceContext()->registerStorageEngine("mobile", new MobileFactory());
+ return Status::OK();
+ },
+ [](DeinitializerContext* const) { return Status::OK(); });
} // namespace mongo
diff --git a/src/mongo/db/storage/storage_engine.h b/src/mongo/db/storage/storage_engine.h
index 486360ba35d..fc2d9d99a08 100644
--- a/src/mongo/db/storage/storage_engine.h
+++ b/src/mongo/db/storage/storage_engine.h
@@ -139,6 +139,11 @@ public:
};
/**
+ * The destructor should only be called if we are tearing down but not exiting the process.
+ */
+ virtual ~StorageEngine() {}
+
+ /**
* Called after the globalStorageEngine pointer has been set up, before any other methods
* are called. Any initialization work that requires the ability to create OperationContexts
* should be done here rather than in the constructor.
@@ -389,12 +394,6 @@ public:
* implementation.
*/
virtual Timestamp getAllCommittedTimestamp(OperationContext* opCtx) const = 0;
-
-protected:
- /**
- * The destructor will never be called. See cleanShutdown instead.
- */
- virtual ~StorageEngine() {}
};
} // namespace mongo
diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_customization_hooks.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_customization_hooks.cpp
index e40d3a58edb..dfc59b26f3f 100644
--- a/src/mongo/db/storage/wiredtiger/wiredtiger_customization_hooks.cpp
+++ b/src/mongo/db/storage/wiredtiger/wiredtiger_customization_hooks.cpp
@@ -39,7 +39,7 @@
namespace mongo {
/* Make a WiredTigerCustomizationHooks pointer a decoration on the global ServiceContext */
-MONGO_INITIALIZER_WITH_PREREQUISITES(SetWiredTigerCustomizationHooks, ("SetGlobalEnvironment"))
+MONGO_INITIALIZER(SetWiredTigerCustomizationHooks)
(InitializerContext* context) {
auto customizationHooks = stdx::make_unique<WiredTigerCustomizationHooks>();
WiredTigerCustomizationHooks::set(getGlobalServiceContext(), std::move(customizationHooks));
diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_extensions.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_extensions.cpp
index f9bd90126e2..b0149c0b5aa 100644
--- a/src/mongo/db/storage/wiredtiger/wiredtiger_extensions.cpp
+++ b/src/mongo/db/storage/wiredtiger/wiredtiger_extensions.cpp
@@ -38,7 +38,7 @@
namespace mongo {
-MONGO_INITIALIZER_WITH_PREREQUISITES(SetWiredTigerExtensions, ("SetGlobalEnvironment"))
+MONGO_INITIALIZER(SetWiredTigerExtensions)
(InitializerContext* context) {
auto configHooks = stdx::make_unique<WiredTigerExtensions>();
WiredTigerExtensions::set(getGlobalServiceContext(), std::move(configHooks));
diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_init.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_init.cpp
index 1e839e2c1ac..5b7d2cc2239 100644
--- a/src/mongo/db/storage/wiredtiger/wiredtiger_init.cpp
+++ b/src/mongo/db/storage/wiredtiger/wiredtiger_init.cpp
@@ -166,7 +166,7 @@ public:
};
} // namespace
-MONGO_INITIALIZER_WITH_PREREQUISITES(WiredTigerEngineInit, ("SetGlobalEnvironment"))
+MONGO_INITIALIZER(WiredTigerEngineInit)
(InitializerContext* context) {
getGlobalServiceContext()->registerStorageEngine(kWiredTigerEngineName,
new WiredTigerFactory());
diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store_mock.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store_mock.cpp
index 770b1d9b3cd..118471655ad 100644
--- a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store_mock.cpp
+++ b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store_mock.cpp
@@ -35,8 +35,10 @@
#include "mongo/db/namespace_string.h"
#include "mongo/db/service_context.h"
#include "mongo/db/service_context_noop.h"
+#include "mongo/db/service_context_registrar.h"
#include "mongo/db/storage/wiredtiger/wiredtiger_kv_engine.h"
-#include "mongo/stdx/memory.h"
+
+#include <memory>
namespace mongo {
namespace {
@@ -50,9 +52,8 @@ MONGO_INITIALIZER(SetInitRsOplogBackgroundThreadCallback)(InitializerContext* co
return Status::OK();
}
-MONGO_INITIALIZER(SetGlobalEnvironment)(InitializerContext* context) {
- setGlobalServiceContext(stdx::make_unique<ServiceContextNoop>());
- return Status::OK();
-}
+ServiceContextRegistrar serviceContextCreator([]() {
+ return std::make_unique<ServiceContextNoop>();
+});
} // namespace
} // namespace mongo
diff --git a/src/mongo/dbtests/dbtests.cpp b/src/mongo/dbtests/dbtests.cpp
index 5e51f5c5c0b..07db83f45ac 100644
--- a/src/mongo/dbtests/dbtests.cpp
+++ b/src/mongo/dbtests/dbtests.cpp
@@ -50,6 +50,7 @@
#include "mongo/db/repl/storage_interface_mock.h"
#include "mongo/db/service_context.h"
#include "mongo/db/service_context_d.h"
+#include "mongo/db/service_context_registrar.h"
#include "mongo/db/wire_version.h"
#include "mongo/dbtests/framework.h"
#include "mongo/scripting/engine.h"
@@ -129,7 +130,9 @@ int dbtestsMain(int argc, char** argv, char** envp) {
::mongo::setTestCommandsEnabled(true);
::mongo::setupSynchronousSignalHandlers();
mongo::dbtests::initWireSpec();
- mongo::runGlobalInitializersOrDie(argc, argv, envp);
+
+ setGlobalServiceContext(createServiceContext());
+ mongo::runGlobalInitializersOrDie(argc, argv, envp, getGlobalServiceContext());
serverGlobalParams.featureCompatibility.setVersion(
ServerGlobalParams::FeatureCompatibility::Version::kFullyUpgradedTo40);
repl::ReplSettings replSettings;
diff --git a/src/mongo/executor/connection_pool.cpp b/src/mongo/executor/connection_pool.cpp
index 43d061db5a8..c00fe1c739b 100644
--- a/src/mongo/executor/connection_pool.cpp
+++ b/src/mongo/executor/connection_pool.cpp
@@ -280,7 +280,9 @@ ConnectionPool::ConnectionPool(std::unique_ptr<DependentTypeFactoryInterface> im
}
ConnectionPool::~ConnectionPool() {
- if (_manager) {
+ // If we're currently destroying the service context the _manager is already deleted and this
+ // pointer dangles. No need for cleanup in that case.
+ if (hasGlobalServiceContext() && _manager) {
_manager->remove(this);
}
}
diff --git a/src/mongo/s/server.cpp b/src/mongo/s/server.cpp
index 449f51389db..cedcf00ff64 100644
--- a/src/mongo/s/server.cpp
+++ b/src/mongo/s/server.cpp
@@ -61,6 +61,7 @@
#include "mongo/db/server_options.h"
#include "mongo/db/service_context.h"
#include "mongo/db/service_context_noop.h"
+#include "mongo/db/service_context_registrar.h"
#include "mongo/db/session_killer.h"
#include "mongo/db/startup_warnings_common.h"
#include "mongo/db/wire_version.h"
@@ -549,13 +550,14 @@ MONGO_INITIALIZER(CreateAuthorizationExternalStateFactory)(InitializerContext* c
return Status::OK();
}
-MONGO_INITIALIZER(SetGlobalEnvironment)(InitializerContext* context) {
- setGlobalServiceContext(stdx::make_unique<ServiceContextNoop>());
- getGlobalServiceContext()->setTickSource(stdx::make_unique<SystemTickSource>());
- getGlobalServiceContext()->setFastClockSource(stdx::make_unique<SystemClockSource>());
- getGlobalServiceContext()->setPreciseClockSource(stdx::make_unique<SystemClockSource>());
- return Status::OK();
-}
+ServiceContextRegistrar serviceContextCreator([]() {
+ auto service = std::make_unique<ServiceContextNoop>();
+ service->setTickSource(std::make_unique<SystemTickSource>());
+ service->setFastClockSource(std::make_unique<SystemClockSource>());
+ service->setPreciseClockSource(std::make_unique<SystemClockSource>());
+ return service;
+});
+
#ifdef MONGO_CONFIG_SSL
MONGO_INITIALIZER_GENERAL(setSSLManagerType, MONGO_NO_PREREQUISITES, ("SSLManager"))
@@ -577,7 +579,8 @@ ExitCode mongoSMain(int argc, char* argv[], char** envp) {
setupSignalHandlers();
- Status status = runGlobalInitializers(argc, argv, envp);
+ setGlobalServiceContext(createServiceContext());
+ Status status = runGlobalInitializers(argc, argv, envp, getGlobalServiceContext());
if (!status.isOK()) {
severe(LogComponent::kDefault) << "Failed global initialization: " << status;
return EXIT_ABRUPT;
diff --git a/src/mongo/shell/dbshell.cpp b/src/mongo/shell/dbshell.cpp
index 1d58305a883..a85e8a16f92 100644
--- a/src/mongo/shell/dbshell.cpp
+++ b/src/mongo/shell/dbshell.cpp
@@ -47,6 +47,7 @@
#include "mongo/db/client.h"
#include "mongo/db/log_process_details.h"
#include "mongo/db/server_options.h"
+#include "mongo/db/service_context_registrar.h"
#include "mongo/logger/console_appender.h"
#include "mongo/logger/logger.h"
#include "mongo/logger/message_event_utf8_encoder.h"
@@ -740,7 +741,8 @@ int _main(int argc, char* argv[], char** envp) {
mongo::shell_utils::RecordMyLocation(argv[0]);
- mongo::runGlobalInitializersOrDie(argc, argv, envp);
+ setGlobalServiceContext(createServiceContext());
+ mongo::runGlobalInitializersOrDie(argc, argv, envp, getGlobalServiceContext());
// TODO This should use a TransportLayerManager or TransportLayerFactory
auto serviceContext = getGlobalServiceContext();
diff --git a/src/mongo/tools/bridge.cpp b/src/mongo/tools/bridge.cpp
index 375c88bbc1b..5e5fcbf7417 100644
--- a/src/mongo/tools/bridge.cpp
+++ b/src/mongo/tools/bridge.cpp
@@ -39,6 +39,7 @@
#include "mongo/db/dbmessage.h"
#include "mongo/db/service_context.h"
#include "mongo/db/service_context_noop.h"
+#include "mongo/db/service_context_registrar.h"
#include "mongo/platform/atomic_word.h"
#include "mongo/platform/random.h"
#include "mongo/rpc/command_request.h"
@@ -391,10 +392,9 @@ private:
std::unique_ptr<mongo::BridgeListener> listener;
-MONGO_INITIALIZER(SetGlobalEnvironment)(InitializerContext* context) {
- setGlobalServiceContext(stdx::make_unique<ServiceContextNoop>());
- return Status::OK();
-}
+ServiceContextRegistrar serviceContextCreator([]() {
+ return std::make_unique<ServiceContextNoop>();
+});
} // namespace
@@ -409,7 +409,8 @@ int bridgeMain(int argc, char** argv, char** envp) {
});
setupSignalHandlers();
- runGlobalInitializersOrDie(argc, argv, envp);
+ setGlobalServiceContext(createServiceContext());
+ runGlobalInitializersOrDie(argc, argv, envp, getGlobalServiceContext());
startSignalProcessingThread(LogFileStatus::kNoLogFileToRotate);
auto serviceContext = getGlobalServiceContext();
diff --git a/src/mongo/transport/transport_layer_egress_init.cpp b/src/mongo/transport/transport_layer_egress_init.cpp
index 20a4fe5a47a..279bd05b6ce 100644
--- a/src/mongo/transport/transport_layer_egress_init.cpp
+++ b/src/mongo/transport/transport_layer_egress_init.cpp
@@ -38,7 +38,7 @@ namespace mongo {
namespace {
// Linking with this file will configure an egress-only TransportLayer on a ServiceContextNoop.
// Use this for unit/integration tests that require only egress networking.
-MONGO_INITIALIZER_WITH_PREREQUISITES(ConfigureEgressTransportLayer, ("SetGlobalEnvironment"))
+MONGO_INITIALIZER(ConfigureEgressTransportLayer)
(InitializerContext* context) {
auto sc = getGlobalServiceContext();
invariant(!sc->getTransportLayer());
diff --git a/src/mongo/unittest/SConscript b/src/mongo/unittest/SConscript
index 50c94ac7abf..dbc75f2f62f 100644
--- a/src/mongo/unittest/SConscript
+++ b/src/mongo/unittest/SConscript
@@ -21,6 +21,7 @@ env.Library(target="unittest",
env.Library("unittest_main", ['unittest_main.cpp'],
LIBDEPS=[
'unittest',
+ '$BUILD_DIR/mongo/db/service_context',
])
env.Library(target="integration_test_main",
@@ -47,6 +48,7 @@ bmEnv.Library(
],
LIBDEPS=[
'$BUILD_DIR/mongo/base',
+ '$BUILD_DIR/mongo/db/service_context',
'$BUILD_DIR/third_party/shim_benchmark',
],
)
diff --git a/src/mongo/unittest/benchmark_main.cpp b/src/mongo/unittest/benchmark_main.cpp
index a992ddb06bf..b714ace268a 100644
--- a/src/mongo/unittest/benchmark_main.cpp
+++ b/src/mongo/unittest/benchmark_main.cpp
@@ -33,13 +33,21 @@
#include <benchmark/benchmark.h>
#include "mongo/base/initializer.h"
+#include "mongo/db/service_context.h"
+#include "mongo/db/service_context_registrar.h"
#include "mongo/util/signal_handlers_synchronous.h"
int main(int argc, char** argv, char** envp) {
::mongo::clearSignalMask();
::mongo::setupSynchronousSignalHandlers();
- ::mongo::runGlobalInitializersOrDie(argc, argv, envp);
+
+ ::mongo::ServiceContext* serviceContext = nullptr;
+ if (::mongo::hasServiceContextFactory()) {
+ ::mongo::setGlobalServiceContext(::mongo::createServiceContext());
+ serviceContext = ::mongo::getGlobalServiceContext();
+ }
+ ::mongo::runGlobalInitializersOrDie(argc, argv, envp, serviceContext);
// Copied from the BENCHMARK_MAIN macro.
::benchmark::Initialize(&argc, argv);
diff --git a/src/mongo/unittest/integration_test_main.cpp b/src/mongo/unittest/integration_test_main.cpp
index aaaf12f8c23..382ea69b087 100644
--- a/src/mongo/unittest/integration_test_main.cpp
+++ b/src/mongo/unittest/integration_test_main.cpp
@@ -37,6 +37,7 @@
#include "mongo/base/initializer.h"
#include "mongo/client/connection_string.h"
#include "mongo/db/service_context.h"
+#include "mongo/db/service_context_registrar.h"
#include "mongo/transport/transport_layer_asio.h"
#include "mongo/unittest/unittest.h"
#include "mongo/util/log.h"
@@ -70,7 +71,13 @@ ConnectionString getFixtureConnectionString() {
int main(int argc, char** argv, char** envp) {
setupSynchronousSignalHandlers();
- runGlobalInitializersOrDie(argc, argv, envp);
+
+ ::mongo::ServiceContext* serviceContext = nullptr;
+ if (::mongo::hasServiceContextFactory()) {
+ ::mongo::setGlobalServiceContext(::mongo::createServiceContext());
+ serviceContext = ::mongo::getGlobalServiceContext();
+ }
+ runGlobalInitializersOrDie(argc, argv, envp, serviceContext);
quickExit(unittest::Suite::run(std::vector<std::string>(), "", 1));
}
diff --git a/src/mongo/unittest/unittest_main.cpp b/src/mongo/unittest/unittest_main.cpp
index cd259f4e7f5..0b4adf11d3d 100644
--- a/src/mongo/unittest/unittest_main.cpp
+++ b/src/mongo/unittest/unittest_main.cpp
@@ -33,6 +33,8 @@
#include "mongo/base/initializer.h"
#include "mongo/base/status.h"
+#include "mongo/db/service_context.h"
+#include "mongo/db/service_context_registrar.h"
#include "mongo/unittest/unittest.h"
#include "mongo/util/options_parser/environment.h"
#include "mongo/util/options_parser/option_section.h"
@@ -44,7 +46,13 @@ using mongo::Status;
int main(int argc, char** argv, char** envp) {
::mongo::clearSignalMask();
::mongo::setupSynchronousSignalHandlers();
- ::mongo::runGlobalInitializersOrDie(argc, argv, envp);
+
+ ::mongo::ServiceContext* serviceContext = nullptr;
+ if (::mongo::hasServiceContextFactory()) {
+ ::mongo::setGlobalServiceContext(::mongo::createServiceContext());
+ serviceContext = ::mongo::getGlobalServiceContext();
+ }
+ ::mongo::runGlobalInitializersOrDie(argc, argv, envp, serviceContext);
namespace moe = ::mongo::optionenvironment;
moe::OptionsParser parser;