summaryrefslogtreecommitdiff
path: root/src/mongo/db
diff options
context:
space:
mode:
authorAndy Schwerin <schwerin@mongodb.com>2018-05-05 10:20:46 -0400
committerAndy Schwerin <schwerin@mongodb.com>2018-05-05 10:20:46 -0400
commit30994f3bacb6e814ae015d83693c549a3b924ccc (patch)
treebb959682199469dc6039406721a2f8000cefc10e /src/mongo/db
parent757c434668e4936d6b2ac62131be7f12aeac25be (diff)
downloadmongo-30994f3bacb6e814ae015d83693c549a3b924ccc.tar.gz
SERVER-34798 Move storage initialization behaviors out of ServiceContext subclasses to new library.
Diffstat (limited to 'src/mongo/db')
-rw-r--r--src/mongo/db/SConscript1
-rw-r--r--src/mongo/db/catalog/SConscript1
-rw-r--r--src/mongo/db/catalog/database_impl.cpp18
-rw-r--r--src/mongo/db/catalog/index_catalog_impl.cpp9
-rw-r--r--src/mongo/db/commands/SConscript1
-rw-r--r--src/mongo/db/commands/dbcommands.cpp35
-rw-r--r--src/mongo/db/commands/generic.cpp34
-rw-r--r--src/mongo/db/db.cpp14
-rw-r--r--src/mongo/db/service_context.cpp60
-rw-r--r--src/mongo/db/service_context.h66
-rw-r--r--src/mongo/db/service_context_d.cpp208
-rw-r--r--src/mongo/db/service_context_d.h36
-rw-r--r--src/mongo/db/service_context_d_test_fixture.cpp5
-rw-r--r--src/mongo/db/service_context_noop.cpp27
-rw-r--r--src/mongo/db/service_context_noop.h12
-rw-r--r--src/mongo/db/storage/SConscript18
-rw-r--r--src/mongo/db/storage/devnull/SConscript3
-rw-r--r--src/mongo/db/storage/devnull/devnull_init.cpp6
-rw-r--r--src/mongo/db/storage/ephemeral_for_test/SConscript3
-rw-r--r--src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_init.cpp4
-rw-r--r--src/mongo/db/storage/mmap_v1/SConscript1
-rw-r--r--src/mongo/db/storage/mmap_v1/mmap_v1_init.cpp3
-rw-r--r--src/mongo/db/storage/mmap_v1/mmap_v1_init_test.cpp20
-rw-r--r--src/mongo/db/storage/mobile/SConscript7
-rw-r--r--src/mongo/db/storage/mobile/mobile_init.cpp3
-rw-r--r--src/mongo/db/storage/storage_engine_init.cpp308
-rw-r--r--src/mongo/db/storage/storage_engine_init.h93
-rw-r--r--src/mongo/db/storage/storage_engine_lock_file.cpp46
-rw-r--r--src/mongo/db/storage/storage_engine_lock_file.h4
-rw-r--r--src/mongo/db/storage/wiredtiger/SConscript1
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_init.cpp5
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_init_test.cpp21
32 files changed, 566 insertions, 507 deletions
diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript
index fdb33e83840..a77d3d7de2e 100644
--- a/src/mongo/db/SConscript
+++ b/src/mongo/db/SConscript
@@ -699,6 +699,7 @@ env.Library(
'$BUILD_DIR/mongo/db/concurrency/lock_manager',
'$BUILD_DIR/mongo/db/ops/write_ops_parsers',
'$BUILD_DIR/mongo/db/s/sharding',
+ '$BUILD_DIR/mongo/db/storage/storage_engine_common',
'$BUILD_DIR/mongo/db/storage/storage_options',
'$BUILD_DIR/mongo/db/storage/storage_engine_lock_file',
'$BUILD_DIR/mongo/db/storage/storage_engine_metadata',
diff --git a/src/mongo/db/catalog/SConscript b/src/mongo/db/catalog/SConscript
index 5ed9e0ad896..47c0b0f662e 100644
--- a/src/mongo/db/catalog/SConscript
+++ b/src/mongo/db/catalog/SConscript
@@ -289,6 +289,7 @@ env.Library(
LIBDEPS_PRIVATE=[
'$BUILD_DIR/mongo/db/logical_clock',
'$BUILD_DIR/mongo/db/storage/mmap_v1/mmap_v1_options',
+ '$BUILD_DIR/mongo/db/storage/storage_engine_common',
],
)
diff --git a/src/mongo/db/catalog/database_impl.cpp b/src/mongo/db/catalog/database_impl.cpp
index 7ee8c22b7ba..b2df4e237b0 100644
--- a/src/mongo/db/catalog/database_impl.cpp
+++ b/src/mongo/db/catalog/database_impl.cpp
@@ -67,6 +67,7 @@
#include "mongo/db/stats/top.h"
#include "mongo/db/storage/recovery_unit.h"
#include "mongo/db/storage/storage_engine.h"
+#include "mongo/db/storage/storage_engine_init.h"
#include "mongo/db/storage/storage_options.h"
#include "mongo/db/system_index.h"
#include "mongo/db/views/view_catalog.h"
@@ -92,12 +93,12 @@ namespace {
MONGO_FP_DECLARE(hangBeforeLoggingCreateCollection);
} // namespace
-using std::unique_ptr;
using std::endl;
using std::list;
using std::set;
using std::string;
using std::stringstream;
+using std::unique_ptr;
using std::vector;
void uassertNamespaceNotIndex(StringData ns, StringData caller) {
@@ -1019,18 +1020,19 @@ MONGO_REGISTER_SHIM(Database::userCreateNS)
}
}
- status =
- validateStorageOptions(collectionOptions.storageEngine, [](const auto& x, const auto& y) {
- return x->validateCollectionStorageOptions(y);
- });
+ status = validateStorageOptions(
+ opCtx->getServiceContext(),
+ collectionOptions.storageEngine,
+ [](const auto& x, const auto& y) { return x->validateCollectionStorageOptions(y); });
if (!status.isOK())
return status;
if (auto indexOptions = collectionOptions.indexOptionDefaults["storageEngine"]) {
- status = validateStorageOptions(indexOptions.Obj(), [](const auto& x, const auto& y) {
- return x->validateIndexStorageOptions(y);
- });
+ status = validateStorageOptions(
+ opCtx->getServiceContext(), indexOptions.Obj(), [](const auto& x, const auto& y) {
+ return x->validateIndexStorageOptions(y);
+ });
if (!status.isOK()) {
return status;
diff --git a/src/mongo/db/catalog/index_catalog_impl.cpp b/src/mongo/db/catalog/index_catalog_impl.cpp
index 583721aba4b..ac93349e71e 100644
--- a/src/mongo/db/catalog/index_catalog_impl.cpp
+++ b/src/mongo/db/catalog/index_catalog_impl.cpp
@@ -64,6 +64,7 @@
#include "mongo/db/repl/replication_coordinator.h"
#include "mongo/db/server_options.h"
#include "mongo/db/service_context.h"
+#include "mongo/db/storage/storage_engine_init.h"
#include "mongo/util/assert_util.h"
#include "mongo/util/log.h"
#include "mongo/util/mongoutils/str.h"
@@ -97,9 +98,9 @@ MONGO_REGISTER_SHIM(IndexCatalog::prepareInsertDeleteOptions)
return IndexCatalogImpl::prepareInsertDeleteOptions(opCtx, desc, options);
}
-using std::unique_ptr;
using std::endl;
using std::string;
+using std::unique_ptr;
using std::vector;
using IndexVersion = IndexDescriptor::IndexVersion;
@@ -535,7 +536,7 @@ Status _checkValidFilterExpressions(MatchExpression* expression, int level = 0)
<< expression->toString());
}
}
-}
+} // namespace
Status IndexCatalogImpl::_isSpecOk(OperationContext* opCtx, const BSONObj& spec) const {
const NamespaceString& nss = _collection->ns();
@@ -764,8 +765,8 @@ Status IndexCatalogImpl::_isSpecOk(OperationContext* opCtx, const BSONObj& spec)
"Empty \"storageEngine\" options are invalid. "
"Please remove the field or include valid options.");
}
- Status storageEngineStatus =
- validateStorageOptions(storageEngineOptions, [](const auto& x, const auto& y) {
+ Status storageEngineStatus = validateStorageOptions(
+ opCtx->getServiceContext(), storageEngineOptions, [](const auto& x, const auto& y) {
return x->validateIndexStorageOptions(y);
});
if (!storageEngineStatus.isOK()) {
diff --git a/src/mongo/db/commands/SConscript b/src/mongo/db/commands/SConscript
index 03dd3919180..b95489f622c 100644
--- a/src/mongo/db/commands/SConscript
+++ b/src/mongo/db/commands/SConscript
@@ -221,6 +221,7 @@ env.Library(
'$BUILD_DIR/mongo/db/query_exec',
'$BUILD_DIR/mongo/db/repair_database',
'$BUILD_DIR/mongo/db/rw_concern_d',
+ '$BUILD_DIR/mongo/db/storage/storage_engine_common',
'$BUILD_DIR/mongo/db/views/views_mongod',
'core',
'current_op_common',
diff --git a/src/mongo/db/commands/dbcommands.cpp b/src/mongo/db/commands/dbcommands.cpp
index 0499c35f683..02a279e4653 100644
--- a/src/mongo/db/commands/dbcommands.cpp
+++ b/src/mongo/db/commands/dbcommands.cpp
@@ -87,6 +87,7 @@
#include "mongo/db/repl/replication_coordinator.h"
#include "mongo/db/server_parameters.h"
#include "mongo/db/stats/storage_stats.h"
+#include "mongo/db/storage/storage_engine_init.h"
#include "mongo/db/write_concern.h"
#include "mongo/s/stale_exception.h"
#include "mongo/scripting/engine.h"
@@ -94,6 +95,7 @@
#include "mongo/util/log.h"
#include "mongo/util/md5.hpp"
#include "mongo/util/scopeguard.h"
+#include "mongo/util/version.h"
namespace mongo {
@@ -764,5 +766,38 @@ public:
} cmdDBStats;
+class CmdBuildInfo : public BasicCommand {
+public:
+ CmdBuildInfo() : BasicCommand("buildInfo", "buildinfo") {}
+
+ AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
+ return AllowedOnSecondary::kAlways;
+ }
+
+ virtual bool adminOnly() const {
+ return false;
+ }
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
+ virtual void addRequiredPrivileges(const std::string& dbname,
+ const BSONObj& cmdObj,
+ std::vector<Privilege>* out) const {} // No auth required
+ std::string help() const override {
+ return "get version #, etc.\n"
+ "{ buildinfo:1 }";
+ }
+
+ bool run(OperationContext* opCtx,
+ const std::string& dbname,
+ const BSONObj& jsobj,
+ BSONObjBuilder& result) {
+ VersionInfoInterface::instance().appendBuildInfo(&result);
+ appendStorageEngineList(opCtx->getServiceContext(), &result);
+ return true;
+ }
+
+} cmdBuildInfo;
+
} // namespace
} // namespace mongo
diff --git a/src/mongo/db/commands/generic.cpp b/src/mongo/db/commands/generic.cpp
index e157ff5a64a..9a4bf94a78b 100644
--- a/src/mongo/db/commands/generic.cpp
+++ b/src/mongo/db/commands/generic.cpp
@@ -38,7 +38,6 @@
#include "mongo/util/log.h"
#include "mongo/util/processinfo.h"
#include "mongo/util/ramlog.h"
-#include "mongo/util/version.h"
#include <sstream>
#include <string>
@@ -51,39 +50,6 @@ using std::string;
using std::stringstream;
using std::vector;
-class CmdBuildInfo : public BasicCommand {
-public:
- CmdBuildInfo() : BasicCommand("buildInfo", "buildinfo") {}
-
- AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
- return AllowedOnSecondary::kAlways;
- }
-
- virtual bool adminOnly() const {
- return false;
- }
- virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
- return false;
- }
- virtual void addRequiredPrivileges(const std::string& dbname,
- const BSONObj& cmdObj,
- std::vector<Privilege>* out) const {} // No auth required
- std::string help() const override {
- return "get version #, etc.\n"
- "{ buildinfo:1 }";
- }
-
- bool run(OperationContext* opCtx,
- const std::string& dbname,
- const BSONObj& jsobj,
- BSONObjBuilder& result) {
- VersionInfoInterface::instance().appendBuildInfo(&result);
- appendStorageEngineList(&result);
- return true;
- }
-
-} cmdBuildInfo;
-
class PingCommand : public BasicCommand {
public:
PingCommand() : BasicCommand("ping") {}
diff --git a/src/mongo/db/db.cpp b/src/mongo/db/db.cpp
index 957b55b633b..f9496fe49cf 100644
--- a/src/mongo/db/db.cpp
+++ b/src/mongo/db/db.cpp
@@ -40,7 +40,6 @@
#include <signal.h>
#include <string>
-#include "mongo/base/checked_cast.h"
#include "mongo/base/init.h"
#include "mongo/base/initializer.h"
#include "mongo/base/status.h"
@@ -129,6 +128,7 @@
#include "mongo/db/storage/encryption_hooks.h"
#include "mongo/db/storage/mmap_v1/mmap_v1_options.h"
#include "mongo/db/storage/storage_engine.h"
+#include "mongo/db/storage/storage_engine_init.h"
#include "mongo/db/storage/storage_options.h"
#include "mongo/db/system_index.h"
#include "mongo/db/ttl.h"
@@ -209,7 +209,7 @@ void logStartup(OperationContext* opCtx) {
BSONObjBuilder buildinfo(toLog.subobjStart("buildinfo"));
VersionInfoInterface::instance().appendBuildInfo(&buildinfo);
- appendStorageEngineList(&buildinfo);
+ appendStorageEngineList(opCtx->getServiceContext(), &buildinfo);
buildinfo.doneFast();
BSONObj o = toLog.obj();
@@ -270,7 +270,7 @@ ExitCode _initAndListen(int listenPort) {
Client::initThread("initandlisten");
initWireSpec();
- auto serviceContext = checked_cast<ServiceContextMongoD*>(getGlobalServiceContext());
+ auto serviceContext = getGlobalServiceContext();
serviceContext->setFastClockSource(FastClockSourceFactory::create(Milliseconds(10)));
auto opObserverRegistry = stdx::make_unique<OpObserverRegistry>();
@@ -312,7 +312,7 @@ ExitCode _initAndListen(int listenPort) {
logProcessDetails();
- serviceContext->createLockFile();
+ createLockFile(serviceContext);
serviceContext->setServiceEntryPoint(
stdx::make_unique<ServiceEntryPointMongod>(serviceContext));
@@ -328,7 +328,7 @@ ExitCode _initAndListen(int listenPort) {
serviceContext->setTransportLayer(std::move(tl));
}
- serviceContext->initializeGlobalStorageEngine();
+ initializeStorageEngine(serviceContext);
#ifdef MONGO_CONFIG_WIREDTIGER_ENABLED
if (EncryptionHooks::get(serviceContext)->restartRequired()) {
@@ -348,7 +348,7 @@ ExitCode _initAndListen(int listenPort) {
}
// Warn if field name matches non-active registered storage engine.
- if (serviceContext->isRegisteredStorageEngine(e.fieldName())) {
+ if (isRegisteredStorageEngine(serviceContext, e.fieldName())) {
warning() << "Detected configuration for non-active storage engine "
<< e.fieldName() << " when current storage engine is "
<< storageGlobalParams.engine;
@@ -931,7 +931,7 @@ void shutdownTask() {
// Global storage engine may not be started in all cases before we exit
if (serviceContext->getStorageEngine()) {
- serviceContext->shutdownGlobalStorageEngineCleanly();
+ shutdownGlobalStorageEngineCleanly(serviceContext);
}
// We drop the scope cache because leak sanitizer can't see across the
diff --git a/src/mongo/db/service_context.cpp b/src/mongo/db/service_context.cpp
index 17193d9462a..92389a0f6a1 100644
--- a/src/mongo/db/service_context.cpp
+++ b/src/mongo/db/service_context.cpp
@@ -99,43 +99,6 @@ bool isMMAPV1() {
return globalStorageEngine->isMmapV1();
}
-Status validateStorageOptions(
- const BSONObj& storageEngineOptions,
- stdx::function<Status(const StorageEngine::Factory* const, const BSONObj&)> validateFunc) {
- BSONObjIterator storageIt(storageEngineOptions);
- while (storageIt.more()) {
- BSONElement storageElement = storageIt.next();
- StringData storageEngineName = storageElement.fieldNameStringData();
- if (storageElement.type() != mongo::Object) {
- return Status(ErrorCodes::BadValue,
- str::stream() << "'storageEngine." << storageElement.fieldNameStringData()
- << "' has to be an embedded document.");
- }
-
- std::unique_ptr<StorageFactoriesIterator> sfi(
- getGlobalServiceContext()->makeStorageFactoriesIterator());
- invariant(sfi);
- bool found = false;
- while (sfi->more()) {
- const StorageEngine::Factory* const& factory = sfi->next();
- if (storageEngineName != factory->getCanonicalName()) {
- continue;
- }
- Status status = validateFunc(factory, storageElement.Obj());
- if (!status.isOK()) {
- return status;
- }
- found = true;
- }
- if (!found) {
- return Status(ErrorCodes::InvalidOptions,
- str::stream() << storageEngineName
- << " is not a registered storage engine for this server");
- }
- }
- return Status::OK();
-}
-
ServiceContext::ServiceContext()
: _tickSource(stdx::make_unique<SystemTickSource>()),
_fastClockSource(stdx::make_unique<SystemClockSource>()),
@@ -300,29 +263,6 @@ Client* ServiceContext::LockedClientsCursor::next() {
return result;
}
-BSONArray storageEngineList() {
- if (!hasGlobalServiceContext())
- return BSONArray();
-
- std::unique_ptr<StorageFactoriesIterator> sfi(
- getGlobalServiceContext()->makeStorageFactoriesIterator());
-
- if (!sfi)
- return BSONArray();
-
- BSONArrayBuilder engineArrayBuilder;
-
- while (sfi->more()) {
- engineArrayBuilder.append(sfi->next()->getCanonicalName());
- }
-
- return engineArrayBuilder.arr();
-}
-
-void appendStorageEngineList(BSONObjBuilder* result) {
- result->append("storageEngines", storageEngineList());
-}
-
void ServiceContext::setKillAllOperations() {
stdx::lock_guard<stdx::mutex> clientLock(_mutex);
diff --git a/src/mongo/db/service_context.h b/src/mongo/db/service_context.h
index 1caa0fd0f05..73b272470e6 100644
--- a/src/mongo/db/service_context.h
+++ b/src/mongo/db/service_context.h
@@ -82,19 +82,6 @@ protected:
virtual ~KillOpListenerInterface() = default;
};
-class StorageFactoriesIterator {
- MONGO_DISALLOW_COPYING(StorageFactoriesIterator);
-
-public:
- virtual ~StorageFactoriesIterator() = default;
-
- virtual bool more() const = 0;
- virtual const StorageEngine::Factory* next() = 0;
-
-protected:
- StorageFactoriesIterator() = default;
-};
-
/**
* Class representing the context of a service, such as a MongoD database service or
* a MongoS routing service.
@@ -239,34 +226,6 @@ public:
//
/**
- * Register a storage engine. Called from a MONGO_INIT that depends on initializiation of
- * the global environment.
- * Ownership of 'factory' is transferred to global environment upon registration.
- */
- virtual void registerStorageEngine(const std::string& name,
- const StorageEngine::Factory* factory) = 0;
-
- /**
- * Returns true if "name" refers to a registered storage engine.
- */
- virtual bool isRegisteredStorageEngine(const std::string& name) = 0;
-
- /**
- * Produce an iterator over all registered storage engine factories.
- * Caller owns the returned object and is responsible for deleting when finished.
- *
- * Never returns nullptr.
- */
- virtual StorageFactoriesIterator* makeStorageFactoriesIterator() = 0;
-
- virtual void initializeGlobalStorageEngine() = 0;
-
- /**
- * Shuts down storage engine cleanly and releases any locks on mongod.lock.
- */
- virtual void shutdownGlobalStorageEngineCleanly() = 0;
-
- /**
* Sets the storage engine for this instance. May be called up to once per instance.
*/
void setStorageEngine(std::unique_ptr<StorageEngine> engine);
@@ -574,29 +533,4 @@ bool supportsDocLocking();
*/
bool isMMAPV1();
-/*
- * Extracts the storageEngine bson from the CollectionOptions provided. Loops through each
- * provided storageEngine and asks the matching registered storage engine if the
- * collection/index options are valid. Returns an error if the collection/index options are
- * invalid.
- * If no matching registered storage engine is found, return an error.
- * Validation function 'func' must be either:
- * - &StorageEngine::Factory::validateCollectionStorageOptions; or
- * - &StorageEngine::Factory::validateIndexStorageOptions
- */
-Status validateStorageOptions(
- const BSONObj& storageEngineOptions,
- stdx::function<Status(const StorageEngine::Factory* const, const BSONObj&)> validateFunc);
-
-/*
- * Returns a BSONArray containing the names of available storage engines, or an empty
- * array if there is no global ServiceContext
- */
-BSONArray storageEngineList();
-
-/*
- * Appends a the list of available storage engines to a BSONObjBuilder for reporting purposes.
- */
-void appendStorageEngineList(BSONObjBuilder* result);
-
} // namespace mongo
diff --git a/src/mongo/db/service_context_d.cpp b/src/mongo/db/service_context_d.cpp
index ca500ce6abe..b4595b97c98 100644
--- a/src/mongo/db/service_context_d.cpp
+++ b/src/mongo/db/service_context_d.cpp
@@ -43,7 +43,6 @@
#include "mongo/db/storage/storage_engine_lock_file.h"
#include "mongo/db/storage/storage_engine_metadata.h"
#include "mongo/db/storage/storage_options.h"
-#include "mongo/db/unclean_shutdown.h"
#include "mongo/stdx/memory.h"
#include "mongo/util/log.h"
#include "mongo/util/map_util.h"
@@ -70,213 +69,6 @@ ServiceContextMongoD::ServiceContextMongoD() = default;
ServiceContextMongoD::~ServiceContextMongoD() = default;
-void ServiceContextMongoD::createLockFile() {
- try {
- _lockFile.reset(new StorageEngineLockFile(storageGlobalParams.dbpath));
- } catch (const std::exception& ex) {
- uassert(28596,
- str::stream() << "Unable to determine status of lock file in the data directory "
- << storageGlobalParams.dbpath
- << ": "
- << ex.what(),
- false);
- }
- bool wasUnclean = _lockFile->createdByUncleanShutdown();
- auto openStatus = _lockFile->open();
- if (storageGlobalParams.readOnly && openStatus == ErrorCodes::IllegalOperation) {
- _lockFile.reset();
- } else {
- uassertStatusOK(openStatus);
- }
-
- if (wasUnclean) {
- if (storageGlobalParams.readOnly) {
- severe() << "Attempted to open dbpath in readOnly mode, but the server was "
- "previously not shut down cleanly.";
- fassertFailedNoTrace(34416);
- }
- warning() << "Detected unclean shutdown - " << _lockFile->getFilespec() << " is not empty.";
- startingAfterUncleanShutdown(this) = true;
- }
-}
-
-void ServiceContextMongoD::initializeGlobalStorageEngine() {
- // This should be set once.
- invariant(!getStorageEngine());
-
- // We should have a _lockFile or be in read-only mode. Confusingly, we can still have a lockFile
- // if we are in read-only mode. This can happen if the server is started in read-only mode on a
- // writable dbpath.
- invariant(_lockFile || storageGlobalParams.readOnly);
-
- const std::string dbpath = storageGlobalParams.dbpath;
- if (auto existingStorageEngine = StorageEngineMetadata::getStorageEngineForPath(dbpath)) {
- if (*existingStorageEngine == "mmapv1" ||
- (storageGlobalParams.engineSetByUser && storageGlobalParams.engine == "mmapv1")) {
- log() << startupWarningsLog;
- log() << "** WARNING: Support for MMAPV1 storage engine has been deprecated and will be"
- << startupWarningsLog;
- log() << "** removed in version 4.2. Please plan to migrate to the wiredTiger"
- << startupWarningsLog;
- log() << "** storage engine." << startupWarningsLog;
- log() << "** See http://dochub.mongodb.org/core/deprecated-mmapv1";
- log() << startupWarningsLog;
- }
-
- 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));
-
- if (factory) {
- uassert(28662,
- str::stream() << "Cannot start server. Detected data files in " << dbpath
- << " created by"
- << " the '"
- << *existingStorageEngine
- << "' storage engine, but the"
- << " specified storage engine was '"
- << factory->getCanonicalName()
- << "'.",
- factory->getCanonicalName() == *existingStorageEngine);
- }
- } else {
- // Otherwise set the active storage engine as the contents of the metadata file.
- log() << "Detected data files in " << dbpath << " created by the '"
- << *existingStorageEngine << "' storage engine, so setting the active"
- << " storage engine to '" << *existingStorageEngine << "'.";
- storageGlobalParams.engine = *existingStorageEngine;
- }
- } else if (!storageGlobalParams.engineSetByUser) {
- // Ensure the default storage engine is available with this build of mongod.
- uassert(28663,
- str::stream()
- << "Cannot start server. The default storage engine '"
- << storageGlobalParams.engine
- << "' is not available with this build of mongod. Please specify a different"
- << " storage engine explicitly, e.g. --storageEngine=mmapv1.",
- isRegisteredStorageEngine(storageGlobalParams.engine));
- } else if (storageGlobalParams.engineSetByUser && storageGlobalParams.engine == "mmapv1") {
- log() << startupWarningsLog;
- log() << "** WARNING: You have explicitly specified 'MMAPV1' storage engine in your"
- << startupWarningsLog;
- log() << "** config file or as a command line option. Support for the MMAPV1"
- << startupWarningsLog;
- log() << "** storage engine has been deprecated and will be removed in"
- << startupWarningsLog;
- log() << "** version 4.2. See http://dochub.mongodb.org/core/deprecated-mmapv1";
- log() << startupWarningsLog;
- }
-
- const std::string repairpath = storageGlobalParams.repairpath;
- uassert(40311,
- str::stream() << "Cannot start server. The command line option '--repairpath'"
- << " is only supported by the mmapv1 storage engine",
- repairpath.empty() || repairpath == dbpath || storageGlobalParams.engine == "mmapv1");
-
- const StorageEngine::Factory* factory = _storageFactories[storageGlobalParams.engine];
-
- uassert(18656,
- str::stream() << "Cannot start server with an unknown storage engine: "
- << storageGlobalParams.engine,
- factory);
-
- if (storageGlobalParams.readOnly) {
- uassert(34368,
- str::stream()
- << "Server was started in read-only mode, but the configured storage engine, "
- << storageGlobalParams.engine
- << ", does not support read-only operation",
- factory->supportsReadOnly());
- }
-
- std::unique_ptr<StorageEngineMetadata> metadata = StorageEngineMetadata::forPath(dbpath);
-
- if (storageGlobalParams.readOnly) {
- uassert(34415,
- "Server was started in read-only mode, but the storage metadata file was not"
- " found.",
- metadata.get());
- }
-
- // Validate options in metadata against current startup options.
- if (metadata.get()) {
- uassertStatusOK(factory->validateMetadata(*metadata, storageGlobalParams));
- }
-
- ScopeGuard guard = MakeGuard([&] {
- if (_lockFile) {
- _lockFile->close();
- }
- });
-
- setStorageEngine(
- std::unique_ptr<StorageEngine>(factory->create(storageGlobalParams, _lockFile.get())));
- getStorageEngine()->finishInit();
-
- if (_lockFile) {
- uassertStatusOK(_lockFile->writePid());
- }
-
- // Write a new metadata file if it is not present.
- if (!metadata.get()) {
- invariant(!storageGlobalParams.readOnly);
- metadata.reset(new StorageEngineMetadata(storageGlobalParams.dbpath));
- metadata->setStorageEngine(factory->getCanonicalName().toString());
- metadata->setStorageEngineOptions(factory->createMetadataOptions(storageGlobalParams));
- uassertStatusOK(metadata->write());
- }
-
- guard.Dismiss();
-
- _supportsDocLocking = getStorageEngine()->supportsDocLocking();
-}
-
-void ServiceContextMongoD::shutdownGlobalStorageEngineCleanly() {
- invariant(getStorageEngine());
- getStorageEngine()->cleanShutdown();
- if (_lockFile) {
- _lockFile->clearPidAndUnlock();
- }
-}
-
-void ServiceContextMongoD::registerStorageEngine(const std::string& name,
- const StorageEngine::Factory* factory) {
- // No double-registering.
- invariant(0 == _storageFactories.count(name));
-
- // Some sanity checks: the factory must exist,
- invariant(factory);
-
- // and all factories should be added before we pick a storage engine.
- invariant(!getStorageEngine());
-
- _storageFactories[name] = factory;
-}
-
-bool ServiceContextMongoD::isRegisteredStorageEngine(const std::string& name) {
- return _storageFactories.count(name);
-}
-
-StorageFactoriesIterator* ServiceContextMongoD::makeStorageFactoriesIterator() {
- return new StorageFactoriesIteratorMongoD(_storageFactories.begin(), _storageFactories.end());
-}
-
-StorageFactoriesIteratorMongoD::StorageFactoriesIteratorMongoD(const FactoryMapIterator& begin,
- const FactoryMapIterator& end)
- : _curr(begin), _end(end) {}
-
-bool StorageFactoriesIteratorMongoD::more() const {
- return _curr != _end;
-}
-
-const StorageEngine::Factory* StorageFactoriesIteratorMongoD::next() {
- return _curr++->second;
-}
-
std::unique_ptr<OperationContext> ServiceContextMongoD::_newOpCtx(Client* client, unsigned opId) {
invariant(&cc() == client);
auto opCtx = stdx::make_unique<OperationContext>(client, opId);
diff --git a/src/mongo/db/service_context_d.h b/src/mongo/db/service_context_d.h
index 9074cb07e51..dfab1926390 100644
--- a/src/mongo/db/service_context_d.h
+++ b/src/mongo/db/service_context_d.h
@@ -28,8 +28,6 @@
#pragma once
-#include <map>
-
#include "mongo/db/service_context.h"
namespace mongo {
@@ -39,46 +37,12 @@ class StorageEngineLockFile;
class ServiceContextMongoD final : public ServiceContext {
public:
- using FactoryMap = std::map<std::string, const StorageEngine::Factory*>;
-
ServiceContextMongoD();
~ServiceContextMongoD();
- void createLockFile();
-
- void initializeGlobalStorageEngine() override;
-
- void shutdownGlobalStorageEngineCleanly() override;
-
- void registerStorageEngine(const std::string& name,
- const StorageEngine::Factory* factory) override;
-
- bool isRegisteredStorageEngine(const std::string& name) override;
-
- StorageFactoriesIterator* makeStorageFactoriesIterator() override;
-
private:
std::unique_ptr<OperationContext> _newOpCtx(Client* client, unsigned opId) override;
-
- std::unique_ptr<StorageEngineLockFile> _lockFile;
-
- // All possible storage engines are registered here through MONGO_INIT.
- FactoryMap _storageFactories;
-};
-
-class StorageFactoriesIteratorMongoD final : public StorageFactoriesIterator {
-public:
- typedef ServiceContextMongoD::FactoryMap::const_iterator FactoryMapIterator;
-
- StorageFactoriesIteratorMongoD(const FactoryMapIterator& begin, const FactoryMapIterator& end);
-
- bool more() const override;
- const StorageEngine::Factory* next() override;
-
-private:
- FactoryMapIterator _curr;
- FactoryMapIterator _end;
};
} // namespace mongo
diff --git a/src/mongo/db/service_context_d_test_fixture.cpp b/src/mongo/db/service_context_d_test_fixture.cpp
index 1b51ac9e966..db0b6bbee7b 100644
--- a/src/mongo/db/service_context_d_test_fixture.cpp
+++ b/src/mongo/db/service_context_d_test_fixture.cpp
@@ -42,6 +42,7 @@
#include "mongo/db/op_observer_noop.h"
#include "mongo/db/op_observer_registry.h"
#include "mongo/db/service_context_d.h"
+#include "mongo/db/storage/storage_engine_init.h"
#include "mongo/db/storage/storage_options.h"
#include "mongo/stdx/memory.h"
#include "mongo/unittest/temp_dir.h"
@@ -67,8 +68,8 @@ void ServiceContextMongoDTest::setUp() {
storageGlobalParams.engine = "ephemeralForTest";
storageGlobalParams.engineSetByUser = true;
- checked_cast<ServiceContextMongoD*>(serviceContext)->createLockFile();
- serviceContext->initializeGlobalStorageEngine();
+ createLockFile(serviceContext);
+ initializeStorageEngine(serviceContext);
serviceContext->setOpObserver(stdx::make_unique<OpObserverNoop>());
}
diff --git a/src/mongo/db/service_context_noop.cpp b/src/mongo/db/service_context_noop.cpp
index 59d0e696fb6..e2cc4b7d41e 100644
--- a/src/mongo/db/service_context_noop.cpp
+++ b/src/mongo/db/service_context_noop.cpp
@@ -35,33 +35,6 @@
namespace mongo {
-void ServiceContextNoop::initializeGlobalStorageEngine() {}
-
-void ServiceContextNoop::shutdownGlobalStorageEngineCleanly() {}
-
-void ServiceContextNoop::registerStorageEngine(const std::string& name,
- const StorageEngine::Factory* factory) {
- // Takes ownership of 'factory' and deletes it because we don't need it.
- delete factory;
-}
-
-bool ServiceContextNoop::isRegisteredStorageEngine(const std::string& name) {
- return false;
-}
-
-StorageFactoriesIterator* ServiceContextNoop::makeStorageFactoriesIterator() {
- class EmptySFI : public StorageFactoriesIterator {
- public:
- virtual bool more() const {
- return false;
- }
- virtual const StorageEngine::Factory* next() {
- MONGO_UNREACHABLE;
- }
- };
- return new EmptySFI();
-}
-
std::unique_ptr<OperationContext> ServiceContextNoop::_newOpCtx(Client* client, unsigned opId) {
return stdx::make_unique<OperationContextNoop>(client, opId);
}
diff --git a/src/mongo/db/service_context_noop.h b/src/mongo/db/service_context_noop.h
index 3bf4829cffe..77e8119accd 100644
--- a/src/mongo/db/service_context_noop.h
+++ b/src/mongo/db/service_context_noop.h
@@ -33,18 +33,6 @@
namespace mongo {
class ServiceContextNoop : public ServiceContext {
-public:
- void initializeGlobalStorageEngine() override;
-
- void shutdownGlobalStorageEngineCleanly() override;
-
- void registerStorageEngine(const std::string& name,
- const StorageEngine::Factory* factory) override;
-
- bool isRegisteredStorageEngine(const std::string& name) override;
-
- StorageFactoriesIterator* makeStorageFactoriesIterator() override;
-
private:
std::unique_ptr<OperationContext> _newOpCtx(Client* client, unsigned opId) override;
};
diff --git a/src/mongo/db/storage/SConscript b/src/mongo/db/storage/SConscript
index 95a8a6bd74e..398007c45fa 100644
--- a/src/mongo/db/storage/SConscript
+++ b/src/mongo/db/storage/SConscript
@@ -181,14 +181,30 @@ env.Library(
env.Library(
target='storage_engine_lock_file',
source=[
+ 'storage_engine_lock_file.cpp',
'storage_engine_lock_file_${TARGET_OS_FAMILY}.cpp',
],
LIBDEPS=[
'$BUILD_DIR/mongo/base',
- ]
+ '$BUILD_DIR/mongo/db/service_context',
+ ],
)
env.Library(
+ target='storage_engine_common',
+ source=[
+ 'storage_engine_init.cpp'
+ ],
+ LIBDEPS=[
+ ],
+ LIBDEPS_PRIVATE=[
+ '$BUILD_DIR/mongo/db/service_context',
+ 'storage_engine_lock_file',
+ 'storage_engine_metadata',
+ 'storage_options',
+ ],
+)
+env.Library(
target="storage_init_d",
source=[
"storage_init.cpp",
diff --git a/src/mongo/db/storage/devnull/SConscript b/src/mongo/db/storage/devnull/SConscript
index 564ec403783..1d960936a60 100644
--- a/src/mongo/db/storage/devnull/SConscript
+++ b/src/mongo/db/storage/devnull/SConscript
@@ -24,4 +24,7 @@ env.Library(
'storage_devnull_core',
'$BUILD_DIR/mongo/db/storage/kv/kv_engine',
],
+ LIBDEPS_PRIVATE=[
+ '$BUILD_DIR/mongo/db/storage/storage_engine_common',
+ ],
)
diff --git a/src/mongo/db/storage/devnull/devnull_init.cpp b/src/mongo/db/storage/devnull/devnull_init.cpp
index c3df87cda3e..68e80902d29 100644
--- a/src/mongo/db/storage/devnull/devnull_init.cpp
+++ b/src/mongo/db/storage/devnull/devnull_init.cpp
@@ -34,6 +34,7 @@
#include "mongo/db/service_context_d.h"
#include "mongo/db/storage/devnull/devnull_kv_engine.h"
#include "mongo/db/storage/kv/kv_storage_engine.h"
+#include "mongo/db/storage/storage_engine_init.h"
#include "mongo/db/storage/storage_options.h"
namespace mongo {
@@ -66,7 +67,8 @@ public:
MONGO_INITIALIZER_WITH_PREREQUISITES(DevNullEngineInit, ("ServiceContext"))
(InitializerContext* context) {
- getGlobalServiceContext()->registerStorageEngine("devnull", new DevNullStorageEngineFactory());
+ registerStorageEngine(getGlobalServiceContext(),
+ std::make_unique<DevNullStorageEngineFactory>());
return Status::OK();
}
-}
+} // namespace mongo
diff --git a/src/mongo/db/storage/ephemeral_for_test/SConscript b/src/mongo/db/storage/ephemeral_for_test/SConscript
index fed440462a4..13e16746684 100644
--- a/src/mongo/db/storage/ephemeral_for_test/SConscript
+++ b/src/mongo/db/storage/ephemeral_for_test/SConscript
@@ -44,6 +44,9 @@ env.Library(
'storage_ephemeral_for_test_core',
'$BUILD_DIR/mongo/db/storage/kv/kv_engine'
],
+ LIBDEPS_PRIVATE=[
+ '$BUILD_DIR/mongo/db/storage/storage_engine_common',
+ ],
)
env.CppUnitTest(
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 8922776255f..a4de16caf63 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
@@ -33,6 +33,7 @@
#include "mongo/db/service_context.h"
#include "mongo/db/storage/ephemeral_for_test/ephemeral_for_test_engine.h"
#include "mongo/db/storage/kv/kv_storage_engine.h"
+#include "mongo/db/storage/storage_engine_init.h"
#include "mongo/db/storage/storage_options.h"
namespace mongo {
@@ -72,8 +73,7 @@ public:
MONGO_INITIALIZER_WITH_PREREQUISITES(EphemeralForTestEngineInit, ("ServiceContext"))
(InitializerContext* context) {
- getGlobalServiceContext()->registerStorageEngine("ephemeralForTest",
- new EphemeralForTestFactory());
+ registerStorageEngine(getGlobalServiceContext(), std::make_unique<EphemeralForTestFactory>());
return Status::OK();
}
diff --git a/src/mongo/db/storage/mmap_v1/SConscript b/src/mongo/db/storage/mmap_v1/SConscript
index 4d7bf2b5f87..c879be79a24 100644
--- a/src/mongo/db/storage/mmap_v1/SConscript
+++ b/src/mongo/db/storage/mmap_v1/SConscript
@@ -80,6 +80,7 @@ env.Library(
LIBDEPS_PRIVATE=[
'$BUILD_DIR/mongo/db/commands/server_status',
'$BUILD_DIR/mongo/db/commands/test_commands_enabled',
+ '$BUILD_DIR/mongo/db/storage/storage_engine_common',
],
)
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 3bce0e22fba..42ba6cb864c 100644
--- a/src/mongo/db/storage/mmap_v1/mmap_v1_init.cpp
+++ b/src/mongo/db/storage/mmap_v1/mmap_v1_init.cpp
@@ -33,6 +33,7 @@
#include "mongo/bson/bsonobjbuilder.h"
#include "mongo/db/service_context.h"
#include "mongo/db/storage/mmap_v1/mmap_v1_engine.h"
+#include "mongo/db/storage/storage_engine_init.h"
#include "mongo/db/storage/storage_engine_metadata.h"
#include "mongo/db/storage/storage_options.h"
@@ -78,7 +79,7 @@ public:
MONGO_INITIALIZER_WITH_PREREQUISITES(MMAPV1EngineInit, ("ServiceContext"))
(InitializerContext* context) {
- getGlobalServiceContext()->registerStorageEngine("mmapv1", new MMAPV1Factory());
+ registerStorageEngine(getGlobalServiceContext(), std::make_unique<MMAPV1Factory>());
return Status::OK();
}
diff --git a/src/mongo/db/storage/mmap_v1/mmap_v1_init_test.cpp b/src/mongo/db/storage/mmap_v1/mmap_v1_init_test.cpp
index 19ec450e1ac..dff7166e77a 100644
--- a/src/mongo/db/storage/mmap_v1/mmap_v1_init_test.cpp
+++ b/src/mongo/db/storage/mmap_v1/mmap_v1_init_test.cpp
@@ -31,6 +31,7 @@
#include "mongo/db/json.h"
#include "mongo/db/service_context.h"
+#include "mongo/db/storage/storage_engine_init.h"
#include "mongo/db/storage/storage_engine_metadata.h"
#include "mongo/db/storage/storage_options.h"
#include "mongo/unittest/unittest.h"
@@ -45,24 +46,13 @@ private:
virtual void setUp() {
ServiceContext* globalEnv = getGlobalServiceContext();
ASSERT_TRUE(globalEnv);
- ASSERT_TRUE(getGlobalServiceContext()->isRegisteredStorageEngine("mmapv1"));
- std::unique_ptr<StorageFactoriesIterator> sfi(
- getGlobalServiceContext()->makeStorageFactoriesIterator());
- ASSERT_TRUE(sfi);
- bool found = false;
- while (sfi->more()) {
- const StorageEngine::Factory* currentFactory = sfi->next();
- if (currentFactory->getCanonicalName() == "mmapv1") {
- found = true;
- factory = currentFactory;
- break;
- }
- }
- ASSERT_TRUE(found);
+ ASSERT_TRUE(isRegisteredStorageEngine(globalEnv, "mmapv1"));
+ factory = getFactoryForStorageEngine(globalEnv, "mmapv1");
+ ASSERT_TRUE(factory);
}
virtual void tearDown() {
- factory = NULL;
+ factory = nullptr;
}
protected:
diff --git a/src/mongo/db/storage/mobile/SConscript b/src/mongo/db/storage/mobile/SConscript
index 98ed0435228..1f481c23d0a 100644
--- a/src/mongo/db/storage/mobile/SConscript
+++ b/src/mongo/db/storage/mobile/SConscript
@@ -50,8 +50,11 @@ env.Library(
LIBDEPS=[
'storage_mobile_core',
'$BUILD_DIR/mongo/db/storage/kv/kv_engine'
- ]
- )
+ ],
+ LIBDEPS_PRIVATE=[
+ '$BUILD_DIR/mongo/db/storage/storage_engine_common',
+ ],
+)
'''
env.CppUnitTest(
target='storage_mobile_index_test',
diff --git a/src/mongo/db/storage/mobile/mobile_init.cpp b/src/mongo/db/storage/mobile/mobile_init.cpp
index edadad22887..41a5dc83159 100644
--- a/src/mongo/db/storage/mobile/mobile_init.cpp
+++ b/src/mongo/db/storage/mobile/mobile_init.cpp
@@ -34,6 +34,7 @@
#include "mongo/db/service_context.h"
#include "mongo/db/storage/kv/kv_storage_engine.h"
#include "mongo/db/storage/mobile/mobile_kv_engine.h"
+#include "mongo/db/storage/storage_engine_init.h"
#include "mongo/db/storage/storage_options.h"
namespace mongo {
@@ -74,7 +75,7 @@ GlobalInitializerRegisterer mobileKVEngineInitializer(
"MobileKVEngineInit",
{"ServiceContext"},
[](InitializerContext* context) {
- getGlobalServiceContext()->registerStorageEngine("mobile", new MobileFactory());
+ registerStorageEngine(getGlobalServiceContext(), std::make_unique<MobileFactory>());
return Status::OK();
},
[](DeinitializerContext* const) { return Status::OK(); });
diff --git a/src/mongo/db/storage/storage_engine_init.cpp b/src/mongo/db/storage/storage_engine_init.cpp
new file mode 100644
index 00000000000..24a0b790972
--- /dev/null
+++ b/src/mongo/db/storage/storage_engine_init.cpp
@@ -0,0 +1,308 @@
+/**
+ * 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.
+ */
+
+#define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kStorage
+
+#include "mongo/platform/basic.h"
+
+#include "mongo/db/storage/storage_engine_init.h"
+
+#include <map>
+
+#include "mongo/bson/bsonobjbuilder.h"
+#include "mongo/db/storage/storage_engine_lock_file.h"
+#include "mongo/db/storage/storage_engine_metadata.h"
+#include "mongo/db/storage/storage_options.h"
+#include "mongo/db/unclean_shutdown.h"
+#include "mongo/util/assert_util.h"
+#include "mongo/util/log.h"
+#include "mongo/util/mongoutils/str.h"
+
+namespace mongo {
+
+extern bool _supportsDocLocking;
+
+void initializeStorageEngine(ServiceContext* service) {
+ // This should be set once.
+ invariant(!service->getStorageEngine());
+
+ // We should have a lock file or be in read-only mode. Confusingly, we can still have a lockFile
+ // if we are in read-only mode. This can happen if the server is started in read-only mode on a
+ // writable dbpath.
+ invariant(StorageEngineLockFile::get(service) || storageGlobalParams.readOnly);
+
+ const std::string dbpath = storageGlobalParams.dbpath;
+ if (auto existingStorageEngine = StorageEngineMetadata::getStorageEngineForPath(dbpath)) {
+ if (*existingStorageEngine == "mmapv1" ||
+ (storageGlobalParams.engineSetByUser && storageGlobalParams.engine == "mmapv1")) {
+ log() << startupWarningsLog;
+ log() << "** WARNING: Support for MMAPV1 storage engine has been deprecated and will be"
+ << startupWarningsLog;
+ log() << "** removed in version 4.2. Please plan to migrate to the wiredTiger"
+ << startupWarningsLog;
+ log() << "** storage engine." << startupWarningsLog;
+ log() << "** See http://dochub.mongodb.org/core/deprecated-mmapv1";
+ log() << startupWarningsLog;
+ }
+
+ if (storageGlobalParams.engineSetByUser) {
+ // Verify that the name of the user-supplied storage engine matches the contents of
+ // the metadata file.
+ const StorageEngine::Factory* factory =
+ getFactoryForStorageEngine(service, storageGlobalParams.engine);
+ if (factory) {
+ uassert(28662,
+ str::stream() << "Cannot start server. Detected data files in " << dbpath
+ << " created by"
+ << " the '"
+ << *existingStorageEngine
+ << "' storage engine, but the"
+ << " specified storage engine was '"
+ << factory->getCanonicalName()
+ << "'.",
+ factory->getCanonicalName() == *existingStorageEngine);
+ }
+ } else {
+ // Otherwise set the active storage engine as the contents of the metadata file.
+ log() << "Detected data files in " << dbpath << " created by the '"
+ << *existingStorageEngine << "' storage engine, so setting the active"
+ << " storage engine to '" << *existingStorageEngine << "'.";
+ storageGlobalParams.engine = *existingStorageEngine;
+ }
+ } else if (!storageGlobalParams.engineSetByUser) {
+ // Ensure the default storage engine is available with this build of mongod.
+ uassert(28663,
+ str::stream()
+ << "Cannot start server. The default storage engine '"
+ << storageGlobalParams.engine
+ << "' is not available with this build of mongod. Please specify a different"
+ << " storage engine explicitly, e.g. --storageEngine=mmapv1.",
+ isRegisteredStorageEngine(service, storageGlobalParams.engine));
+ } else if (storageGlobalParams.engineSetByUser && storageGlobalParams.engine == "mmapv1") {
+ log() << startupWarningsLog;
+ log() << "** WARNING: You have explicitly specified 'MMAPV1' storage engine in your"
+ << startupWarningsLog;
+ log() << "** config file or as a command line option. Support for the MMAPV1"
+ << startupWarningsLog;
+ log() << "** storage engine has been deprecated and will be removed in"
+ << startupWarningsLog;
+ log() << "** version 4.2. See http://dochub.mongodb.org/core/deprecated-mmapv1";
+ log() << startupWarningsLog;
+ }
+
+ const std::string repairpath = storageGlobalParams.repairpath;
+ uassert(40311,
+ str::stream() << "Cannot start server. The command line option '--repairpath'"
+ << " is only supported by the mmapv1 storage engine",
+ repairpath.empty() || repairpath == dbpath || storageGlobalParams.engine == "mmapv1");
+
+ const StorageEngine::Factory* factory =
+ getFactoryForStorageEngine(service, storageGlobalParams.engine);
+
+ uassert(18656,
+ str::stream() << "Cannot start server with an unknown storage engine: "
+ << storageGlobalParams.engine,
+ factory);
+
+ if (storageGlobalParams.readOnly) {
+ uassert(34368,
+ str::stream()
+ << "Server was started in read-only mode, but the configured storage engine, "
+ << storageGlobalParams.engine
+ << ", does not support read-only operation",
+ factory->supportsReadOnly());
+ }
+
+ std::unique_ptr<StorageEngineMetadata> metadata = StorageEngineMetadata::forPath(dbpath);
+
+ if (storageGlobalParams.readOnly) {
+ uassert(34415,
+ "Server was started in read-only mode, but the storage metadata file was not"
+ " found.",
+ metadata.get());
+ }
+
+ // Validate options in metadata against current startup options.
+ if (metadata.get()) {
+ uassertStatusOK(factory->validateMetadata(*metadata, storageGlobalParams));
+ }
+
+ ScopeGuard guard = MakeGuard([&] {
+ auto& lockFile = StorageEngineLockFile::get(service);
+ if (lockFile) {
+ lockFile->close();
+ }
+ });
+
+ auto& lockFile = StorageEngineLockFile::get(service);
+ service->setStorageEngine(std::unique_ptr<StorageEngine>(
+ factory->create(storageGlobalParams, lockFile ? &*lockFile : nullptr)));
+ service->getStorageEngine()->finishInit();
+
+ if (lockFile) {
+ uassertStatusOK(lockFile->writePid());
+ }
+
+ // Write a new metadata file if it is not present.
+ if (!metadata.get()) {
+ invariant(!storageGlobalParams.readOnly);
+ metadata.reset(new StorageEngineMetadata(storageGlobalParams.dbpath));
+ metadata->setStorageEngine(factory->getCanonicalName().toString());
+ metadata->setStorageEngineOptions(factory->createMetadataOptions(storageGlobalParams));
+ uassertStatusOK(metadata->write());
+ }
+
+ guard.Dismiss();
+
+ _supportsDocLocking = service->getStorageEngine()->supportsDocLocking();
+}
+
+void shutdownGlobalStorageEngineCleanly(ServiceContext* service) {
+ invariant(service->getStorageEngine());
+ service->getStorageEngine()->cleanShutdown();
+ auto& lockFile = StorageEngineLockFile::get(service);
+ if (lockFile) {
+ lockFile->clearPidAndUnlock();
+ }
+}
+
+void createLockFile(ServiceContext* service) {
+ auto& lockFile = StorageEngineLockFile::get(service);
+ try {
+ lockFile.emplace(storageGlobalParams.dbpath);
+ } catch (const std::exception& ex) {
+ uassert(28596,
+ str::stream() << "Unable to determine status of lock file in the data directory "
+ << storageGlobalParams.dbpath
+ << ": "
+ << ex.what(),
+ false);
+ }
+ const bool wasUnclean = lockFile->createdByUncleanShutdown();
+ const auto openStatus = lockFile->open();
+ if (storageGlobalParams.readOnly && openStatus == ErrorCodes::IllegalOperation) {
+ lockFile = boost::none;
+ } else {
+ uassertStatusOK(openStatus);
+ }
+
+ if (wasUnclean) {
+ if (storageGlobalParams.readOnly) {
+ severe() << "Attempted to open dbpath in readOnly mode, but the server was "
+ "previously not shut down cleanly.";
+ fassertFailedNoTrace(34416);
+ }
+ warning() << "Detected unclean shutdown - " << lockFile->getFilespec() << " is not empty.";
+ startingAfterUncleanShutdown(service) = true;
+ }
+}
+
+namespace {
+
+using FactoryMap = std::map<std::string, std::unique_ptr<StorageEngine::Factory>>;
+
+auto storageFactories = ServiceContext::declareDecoration<FactoryMap>();
+
+} // namespace
+
+void registerStorageEngine(ServiceContext* service,
+ std::unique_ptr<StorageEngine::Factory> factory) {
+ // No double-registering.
+ invariant(!getFactoryForStorageEngine(service, factory->getCanonicalName()));
+
+ // Some sanity checks: the factory must exist,
+ invariant(factory);
+
+ // and all factories should be added before we pick a storage engine.
+ invariant(!service->getStorageEngine());
+
+ auto name = factory->getCanonicalName().toString();
+ storageFactories(service).emplace(name, std::move(factory));
+}
+
+bool isRegisteredStorageEngine(ServiceContext* service, StringData name) {
+ return getFactoryForStorageEngine(service, name);
+}
+
+StorageEngine::Factory* getFactoryForStorageEngine(ServiceContext* service, StringData name) {
+ const auto result = storageFactories(service).find(name.toString());
+ if (result == storageFactories(service).end()) {
+ return nullptr;
+ }
+ return result->second.get();
+}
+
+Status validateStorageOptions(
+ ServiceContext* service,
+ const BSONObj& storageEngineOptions,
+ stdx::function<Status(const StorageEngine::Factory* const, const BSONObj&)> validateFunc) {
+
+ BSONObjIterator storageIt(storageEngineOptions);
+ while (storageIt.more()) {
+ BSONElement storageElement = storageIt.next();
+ StringData storageEngineName = storageElement.fieldNameStringData();
+ if (storageElement.type() != mongo::Object) {
+ return Status(ErrorCodes::BadValue,
+ str::stream() << "'storageEngine." << storageElement.fieldNameStringData()
+ << "' has to be an embedded document.");
+ }
+
+ if (auto factory = getFactoryForStorageEngine(service, storageEngineName)) {
+ Status status = validateFunc(factory, storageElement.Obj());
+ if (!status.isOK()) {
+ return status;
+ }
+ } else {
+ return Status(ErrorCodes::InvalidOptions,
+ str::stream() << storageEngineName
+ << " is not a registered storage engine for this server");
+ }
+ }
+ return Status::OK();
+}
+
+namespace {
+BSONArray storageEngineList(ServiceContext* service) {
+ if (!service)
+ return BSONArray();
+
+ BSONArrayBuilder engineArrayBuilder;
+
+ for (const auto& nameAndFactory : storageFactories(service)) {
+ engineArrayBuilder.append(nameAndFactory.first);
+ }
+
+ return engineArrayBuilder.arr();
+}
+} // namespace
+
+void appendStorageEngineList(ServiceContext* service, BSONObjBuilder* result) {
+ result->append("storageEngines", storageEngineList(service));
+}
+
+} // namespace mongo
diff --git a/src/mongo/db/storage/storage_engine_init.h b/src/mongo/db/storage/storage_engine_init.h
new file mode 100644
index 00000000000..161cc4558b9
--- /dev/null
+++ b/src/mongo/db/storage/storage_engine_init.h
@@ -0,0 +1,93 @@
+/**
+ * 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 <memory>
+
+#include "mongo/base/string_data.h"
+#include "mongo/db/service_context.h"
+#include "mongo/db/storage/storage_engine.h"
+
+namespace mongo {
+
+/**
+ * Initializes the storage engine on "service".
+ */
+void initializeStorageEngine(ServiceContext* service);
+
+/**
+ * Shuts down storage engine cleanly and releases any locks on mongod.lock.
+ */
+void shutdownGlobalStorageEngineCleanly(ServiceContext* service);
+
+/**
+ * Creates the lock file used to prevent concurrent processes from accessing the data files,
+ * as appropriate.
+ */
+void createLockFile(ServiceContext* service);
+
+/**
+ * Registers a storage engine onto the given "service".
+ */
+void registerStorageEngine(ServiceContext* service,
+ std::unique_ptr<StorageEngine::Factory> factory);
+
+/**
+ * Returns true if "name" refers to a registered storage engine.
+ */
+bool isRegisteredStorageEngine(ServiceContext* service, StringData name);
+
+/**
+ * Returns an unowned pointer to the factory for the named storage engine, or nullptr.
+ *
+ * NOTE: Exposed only for use in legacy testing scenarios.
+ */
+StorageEngine::Factory* getFactoryForStorageEngine(ServiceContext* context, StringData name);
+
+/*
+ * Extracts the storageEngine bson from the CollectionOptions provided. Loops through each
+ * provided storageEngine and asks the matching registered storage engine if the
+ * collection/index options are valid. Returns an error if the collection/index options are
+ * invalid.
+ * If no matching registered storage engine is found, return an error.
+ * Validation function 'func' must be either:
+ * - &StorageEngine::Factory::validateCollectionStorageOptions; or
+ * - &StorageEngine::Factory::validateIndexStorageOptions
+ */
+Status validateStorageOptions(
+ ServiceContext* service,
+ const BSONObj& storageEngineOptions,
+ stdx::function<Status(const StorageEngine::Factory* const, const BSONObj&)> validateFunc);
+
+/*
+ * Appends a the list of available storage engines to a BSONObjBuilder for reporting purposes.
+ */
+void appendStorageEngineList(ServiceContext* service, BSONObjBuilder* result);
+
+} // namespace mongo
diff --git a/src/mongo/db/storage/storage_engine_lock_file.cpp b/src/mongo/db/storage/storage_engine_lock_file.cpp
new file mode 100644
index 00000000000..56b0bde2442
--- /dev/null
+++ b/src/mongo/db/storage/storage_engine_lock_file.cpp
@@ -0,0 +1,46 @@
+/**
+ * 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.
+ */
+
+#define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kStorage
+
+#include "mongo/platform/basic.h"
+
+#include "mongo/db/storage/storage_engine_lock_file.h"
+
+namespace mongo {
+namespace {
+
+auto getLockFile = ServiceContext::declareDecoration<boost::optional<StorageEngineLockFile>>();
+
+} // namespace
+
+boost::optional<StorageEngineLockFile>& StorageEngineLockFile::get(ServiceContext* service) {
+ return getLockFile(service);
+}
+
+} // namespace mongo
diff --git a/src/mongo/db/storage/storage_engine_lock_file.h b/src/mongo/db/storage/storage_engine_lock_file.h
index 24e2359396e..b65364bc65e 100644
--- a/src/mongo/db/storage/storage_engine_lock_file.h
+++ b/src/mongo/db/storage/storage_engine_lock_file.h
@@ -28,11 +28,13 @@
#pragma once
+#include <boost/optional.hpp>
#include <memory>
#include <string>
#include "mongo/base/disallow_copying.h"
#include "mongo/base/status.h"
+#include "mongo/db/service_context.h"
namespace mongo {
@@ -40,6 +42,8 @@ class StorageEngineLockFile {
MONGO_DISALLOW_COPYING(StorageEngineLockFile);
public:
+ static boost::optional<StorageEngineLockFile>& get(ServiceContext* service);
+
/**
* Checks existing lock file, if present, to see if it contains data from a previous
* unclean shutdown. A clean shutdown should have produced a zero length lock file.
diff --git a/src/mongo/db/storage/wiredtiger/SConscript b/src/mongo/db/storage/wiredtiger/SConscript
index 826ff227314..142a108aaa7 100644
--- a/src/mongo/db/storage/wiredtiger/SConscript
+++ b/src/mongo/db/storage/wiredtiger/SConscript
@@ -102,6 +102,7 @@ if wiredtiger:
LIBDEPS_PRIVATE=[
'$BUILD_DIR/mongo/db/commands/server_status',
'$BUILD_DIR/mongo/db/concurrency/lock_manager',
+ '$BUILD_DIR/mongo/db/storage/storage_engine_common',
],
)
diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_init.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_init.cpp
index 26ce1200659..9408642b210 100644
--- a/src/mongo/db/storage/wiredtiger/wiredtiger_init.cpp
+++ b/src/mongo/db/storage/wiredtiger/wiredtiger_init.cpp
@@ -41,6 +41,7 @@
#include "mongo/db/service_context.h"
#include "mongo/db/service_context_d.h"
#include "mongo/db/storage/kv/kv_storage_engine.h"
+#include "mongo/db/storage/storage_engine_init.h"
#include "mongo/db/storage/storage_engine_lock_file.h"
#include "mongo/db/storage/storage_engine_metadata.h"
#include "mongo/db/storage/storage_options.h"
@@ -182,9 +183,7 @@ public:
MONGO_INITIALIZER_WITH_PREREQUISITES(WiredTigerEngineInit, ("ServiceContext"))
(InitializerContext* context) {
- getGlobalServiceContext()->registerStorageEngine(kWiredTigerEngineName,
- new WiredTigerFactory());
-
+ registerStorageEngine(getGlobalServiceContext(), std::make_unique<WiredTigerFactory>());
return Status::OK();
}
}
diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_init_test.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_init_test.cpp
index a2830efebfd..164d52013dd 100644
--- a/src/mongo/db/storage/wiredtiger/wiredtiger_init_test.cpp
+++ b/src/mongo/db/storage/wiredtiger/wiredtiger_init_test.cpp
@@ -31,6 +31,7 @@
#include "mongo/db/json.h"
#include "mongo/db/service_context.h"
+#include "mongo/db/storage/storage_engine_init.h"
#include "mongo/db/storage/storage_engine_metadata.h"
#include "mongo/db/storage/storage_options.h"
#include "mongo/db/storage/wiredtiger/wiredtiger_global_options.h"
@@ -47,27 +48,15 @@ private:
virtual void setUp() {
ServiceContext* globalEnv = getGlobalServiceContext();
ASSERT_TRUE(globalEnv);
- ASSERT_TRUE(getGlobalServiceContext()->isRegisteredStorageEngine(kWiredTigerEngineName));
- std::unique_ptr<StorageFactoriesIterator> sfi(
- getGlobalServiceContext()->makeStorageFactoriesIterator());
- ASSERT_TRUE(sfi);
- bool found = false;
- while (sfi->more()) {
- const StorageEngine::Factory* currentFactory = sfi->next();
- if (currentFactory->getCanonicalName() == kWiredTigerEngineName) {
- found = true;
- factory = currentFactory;
- break;
- }
- found = true;
- }
- ASSERT_TRUE(found);
+ ASSERT_TRUE(isRegisteredStorageEngine(globalEnv, kWiredTigerEngineName));
+ factory = getFactoryForStorageEngine(globalEnv, kWiredTigerEngineName);
+ ASSERT_TRUE(factory);
_oldOptions = wiredTigerGlobalOptions;
}
virtual void tearDown() {
wiredTigerGlobalOptions = _oldOptions;
- factory = NULL;
+ factory = nullptr;
}
WiredTigerGlobalOptions _oldOptions;