summaryrefslogtreecommitdiff
path: root/src/mongo/db/storage/storage_engine_init.cpp
diff options
context:
space:
mode:
authorAndy Schwerin <schwerin@mongodb.com>2018-06-22 12:00:21 -0400
committerAndy Schwerin <schwerin@mongodb.com>2018-06-22 12:32:29 -0400
commitd520be0814492c262515cf0a5d62a127ace70dce (patch)
treee754e3cce243a7b51922b6d2a179a3d355ccefb7 /src/mongo/db/storage/storage_engine_init.cpp
parentc0b942e3a80b9ccd8434ab0927d97cbd1862d19a (diff)
downloadmongo-d520be0814492c262515cf0a5d62a127ace70dce.tar.gz
SERVER-34798 Remove ServiceContext subclasses and use new ServiceContext in every unit test.
This patch does several loosely related and surprisingly hard to separate things. 1.) Make the ServiceContext class final 2.) Create a mechanism, called ConstructorActions, for running methods on ServiceContexts immediately after they're built and immediately before they're destroyed. 3.) Introduce / improve test fixture base classes for tests, giving them fresh ServiceContext instances for each test case. There is one fixture for tests that need a storage engine and another for those that do not. 4.) Make several remaining global variables SC decorations in support of (3) 5.) Replace many MONGO_INITIALIZERS that access getGlobalServiceContext with the new constructor-actions system, which is needed for (3.) 6.) Fix up tests to use the fixtures from (3) and fix tests that silently used different service contexts in together in a technically illegal fashion that now breaks. 7.) Utilize (2) as necessary to simplify initialization of new ServiceContexts, simplifying the fixtures in (3).
Diffstat (limited to 'src/mongo/db/storage/storage_engine_init.cpp')
-rw-r--r--src/mongo/db/storage/storage_engine_init.cpp62
1 files changed, 54 insertions, 8 deletions
diff --git a/src/mongo/db/storage/storage_engine_init.cpp b/src/mongo/db/storage/storage_engine_init.cpp
index d69673679fb..2c4a526e64b 100644
--- a/src/mongo/db/storage/storage_engine_init.cpp
+++ b/src/mongo/db/storage/storage_engine_init.cpp
@@ -34,28 +34,38 @@
#include <map>
+#include "mongo/base/init.h"
#include "mongo/bson/bsonobjbuilder.h"
+#include "mongo/db/concurrency/lock_state.h"
+#include "mongo/db/operation_context.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/stdx/memory.h"
#include "mongo/util/assert_util.h"
#include "mongo/util/log.h"
#include "mongo/util/mongoutils/str.h"
namespace mongo {
+namespace {
+/**
+ * Creates the lock file used to prevent concurrent processes from accessing the data files,
+ * as appropriate.
+ */
+void createLockFile(ServiceContext* service);
+} // namespace
+
extern bool _supportsDocLocking;
-void initializeStorageEngine(ServiceContext* service, StorageEngineInitFlags initFlags) {
+void initializeStorageEngine(ServiceContext* service, const StorageEngineInitFlags initFlags) {
// 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((initFlags & StorageEngineInitFlags::kAllowNoLockFile) ||
- StorageEngineLockFile::get(service) || storageGlobalParams.readOnly);
+ if (0 == (initFlags & StorageEngineInitFlags::kAllowNoLockFile)) {
+ createLockFile(service);
+ }
const std::string dbpath = storageGlobalParams.dbpath;
if (auto existingStorageEngine = StorageEngineMetadata::getStorageEngineForPath(dbpath)) {
@@ -192,6 +202,8 @@ void shutdownGlobalStorageEngineCleanly(ServiceContext* service) {
}
}
+namespace {
+
void createLockFile(ServiceContext* service) {
auto& lockFile = StorageEngineLockFile::get(service);
try {
@@ -223,8 +235,6 @@ void createLockFile(ServiceContext* service) {
}
}
-namespace {
-
using FactoryMap = std::map<std::string, std::unique_ptr<StorageEngine::Factory>>;
auto storageFactories = ServiceContext::declareDecoration<FactoryMap>();
@@ -306,4 +316,40 @@ void appendStorageEngineList(ServiceContext* service, BSONObjBuilder* result) {
result->append("storageEngines", storageEngineList(service));
}
+namespace {
+
+class StorageClientObserver final : public ServiceContext::ClientObserver {
+public:
+ void onCreateClient(Client* client) override{};
+ void onDestroyClient(Client* client) override{};
+ void onCreateOperationContext(OperationContext* opCtx) {
+ auto service = opCtx->getServiceContext();
+ auto storageEngine = service->getStorageEngine();
+ // NOTE(schwerin): The following uassert would be more desirable than the early return when
+ // no storage engine is set, but to achieve that we would have to ensure that this file was
+ // never linked into a test binary that didn't actually need/use the storage engine.
+ //
+ // uassert(<some code>,
+ // "Must instantiate storage engine before creating OperationContext",
+ // storageEngine);
+ if (!storageEngine) {
+ return;
+ }
+ if (storageEngine->isMmapV1()) {
+ opCtx->setLockState(stdx::make_unique<MMAPV1LockerImpl>());
+ } else {
+ opCtx->setLockState(stdx::make_unique<DefaultLockerImpl>());
+ }
+ opCtx->setRecoveryUnit(storageEngine->newRecoveryUnit(),
+ WriteUnitOfWork::RecoveryUnitState::kNotInUnitOfWork);
+ }
+ void onDestroyOperationContext(OperationContext* opCtx) {}
+};
+
+ServiceContext::ConstructorActionRegisterer registerStorageClientObserverConstructor{
+ "RegisterStorageClientObserverConstructor", [](ServiceContext* service) {
+ service->registerClientObserver(std::make_unique<StorageClientObserver>());
+ }};
+
+} // namespace
} // namespace mongo