diff options
author | Andy Schwerin <schwerin@mongodb.com> | 2018-06-22 12:00:21 -0400 |
---|---|---|
committer | Andy Schwerin <schwerin@mongodb.com> | 2018-06-22 12:32:29 -0400 |
commit | d520be0814492c262515cf0a5d62a127ace70dce (patch) | |
tree | e754e3cce243a7b51922b6d2a179a3d355ccefb7 /src/mongo | |
parent | c0b942e3a80b9ccd8434ab0927d97cbd1862d19a (diff) | |
download | mongo-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')
160 files changed, 1153 insertions, 2003 deletions
diff --git a/src/mongo/SConscript b/src/mongo/SConscript index e2f48d3fdfb..2c5093dee1b 100644 --- a/src/mongo/SConscript +++ b/src/mongo/SConscript @@ -524,7 +524,6 @@ if not has_option('noshell') and usemozjs: "$BUILD_DIR/third_party/shim_pcrecpp", "shell_core", "db/server_options_core", - "db/service_context_noop_init", "client/clientdriver_network", "$BUILD_DIR/mongo/util/password", ], diff --git a/src/mongo/bson/SConscript b/src/mongo/bson/SConscript index dc87d2978d0..fbe9ef1dae0 100644 --- a/src/mongo/bson/SConscript +++ b/src/mongo/bson/SConscript @@ -95,6 +95,7 @@ asioEnv.CppIntegrationTest( ], LIBDEPS=[ '$BUILD_DIR/mongo/executor/network_interface_fixture', - '$BUILD_DIR/mongo/rpc/protocol' + '$BUILD_DIR/mongo/rpc/protocol', + '$BUILD_DIR/mongo/transport/transport_layer_egress_init', ], ) diff --git a/src/mongo/client/SConscript b/src/mongo/client/SConscript index ac4acab29fe..2a49afcd2ca 100644 --- a/src/mongo/client/SConscript +++ b/src/mongo/client/SConscript @@ -36,8 +36,8 @@ env.CppUnitTest( 'mongo_uri_test.cpp', ], LIBDEPS=[ - 'clientdriver_network', '$BUILD_DIR/mongo/transport/transport_layer_egress_init', + 'clientdriver_network', ], ) @@ -211,6 +211,7 @@ env.CppIntegrationTest( ], LIBDEPS=[ 'clientdriver_network', + '$BUILD_DIR/mongo/transport/transport_layer_egress_init', '$BUILD_DIR/mongo/util/version_impl', ], ) @@ -326,7 +327,6 @@ env.CppUnitTest( LIBDEPS=[ 'fetcher', '$BUILD_DIR/mongo/db/auth/authmocks', - '$BUILD_DIR/mongo/db/service_context_noop_init', '$BUILD_DIR/mongo/executor/thread_pool_task_executor_test_fixture', ], ) diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript index 3fc627ea446..54445e732fd 100644 --- a/src/mongo/db/SConscript +++ b/src/mongo/db/SConscript @@ -234,7 +234,6 @@ env.CppUnitTest( 'logical_session_id_helpers', 'service_context', '$BUILD_DIR/mongo/db/auth/authmocks', - '$BUILD_DIR/mongo/db/service_context_noop_init', '$BUILD_DIR/mongo/unittest/concurrency', '$BUILD_DIR/mongo/util/clock_source_mock', ], @@ -499,8 +498,6 @@ env.Library( 'operation_context.cpp', 'operation_context_group.cpp', 'service_context.cpp', - 'service_context_noop.cpp', - 'service_context_registrar.cpp', 'server_recovery.cpp', 'unclean_shutdown.cpp', ], @@ -517,16 +514,6 @@ env.Library( ) env.Library( - target='service_context_noop_init', - source=[ - 'service_context_noop_init.cpp' - ], - LIBDEPS=[ - 'service_context', - ], -) - -env.Library( target='lasterror', source=[ "lasterror.cpp", @@ -598,9 +585,9 @@ env.CppUnitTest( LIBDEPS=[ '$BUILD_DIR/mongo/idl/idl_parser', "commands", - "service_context_noop_init", "auth/authmocks", "repl/replmocks", + "service_context_test_fixture", ], ) @@ -665,7 +652,6 @@ env.CppUnitTest( 'auth/authmocks', 'catalog/database_holder_mock', 'catalog_raii', - 'service_context_noop_init', 'stats/fill_locker_info', ], ) @@ -714,7 +700,6 @@ env.Library( env.Library( target="service_context_d", source=[ - "service_context_d.cpp", "service_entry_point_mongod.cpp", ], LIBDEPS=[ @@ -931,9 +916,9 @@ env.Library( source=[ 'exec/projection_exec_agg.cpp', ], - LIBDEPS_PRIVATE=[ - 'pipeline/parsed_aggregation_projection' - ] + LIBDEPS=[ + 'pipeline/parsed_aggregation_projection', + ], ) env.Library( @@ -1196,13 +1181,12 @@ envWithAsio.CppUnitTest( '$BUILD_DIR/mongo/base', '$BUILD_DIR/mongo/db/auth/auth', '$BUILD_DIR/mongo/db/auth/authmocks', - '$BUILD_DIR/mongo/db/auth/authorization_session_for_test', - '$BUILD_DIR/mongo/db/service_context_noop_init', '$BUILD_DIR/mongo/transport/transport_layer_mock', 'logical_session_cache', 'logical_session_cache_impl', 'logical_session_id', 'logical_session_id_helpers', + 'service_context_test_fixture', 'service_liaison_mock', 'sessions_collection_mock', ], @@ -1398,7 +1382,6 @@ envWithAsio.CppUnitTest( 'logical_session_cache_test.cpp', ], LIBDEPS=[ - '$BUILD_DIR/mongo/db/service_context_noop_init', '$BUILD_DIR/mongo/executor/async_timer_mock', 'auth/authmocks', 'keys_collection_manager', @@ -1409,6 +1392,7 @@ envWithAsio.CppUnitTest( 'logical_session_cache', 'logical_session_cache_impl', 'service_liaison_mock', + 'service_context_test_fixture', 'sessions_collection_mock', ], ) @@ -1755,6 +1739,20 @@ env.CppUnitTest( ) env.Library( + target='service_context_test_fixture', + source=[ + 'service_context_test_fixture.cpp', + ], + LIBDEPS=[ + 'service_context', + '$BUILD_DIR/mongo/unittest/unittest', + ], + LIBDEPS_PRIVATE=[ + 'op_observer', + ], +) + +env.Library( target= 'service_context_d_test_fixture', source= [ 'service_context_d_test_fixture.cpp', @@ -1765,6 +1763,7 @@ env.Library( '$BUILD_DIR/mongo/db/storage/storage_options', '$BUILD_DIR/mongo/unittest/unittest', 'service_context_d', + 'service_context_test_fixture', ], ) @@ -1776,12 +1775,11 @@ env.Library( LIBDEPS=[ # this library is required only because of SERVER-29908 '$BUILD_DIR/mongo/db/s/sharding_runtime_d', + 'service_context_d_test_fixture', ], LIBDEPS_PRIVATE=[ '$BUILD_DIR/mongo/db/auth/authmocks', '$BUILD_DIR/mongo/db/storage/devnull/storage_devnull', - '$BUILD_DIR/mongo/unittest/unittest', - 'service_context_d', ], ) @@ -1851,6 +1849,7 @@ asioEnv.CppIntegrationTest( ], LIBDEPS=[ '$BUILD_DIR/mongo/executor/network_interface_fixture', + '$BUILD_DIR/mongo/transport/transport_layer_egress_init', ], ) diff --git a/src/mongo/db/auth/SConscript b/src/mongo/db/auth/SConscript index a086c1e7d6f..35c418f448d 100644 --- a/src/mongo/db/auth/SConscript +++ b/src/mongo/db/auth/SConscript @@ -282,6 +282,7 @@ env.Library( LIBDEPS=[ '$BUILD_DIR/mongo/base', '$BUILD_DIR/mongo/db/server_parameters', + '$BUILD_DIR/mongo/util/net/network', '$BUILD_DIR/mongo/util/options_parser/options_parser', ], ) @@ -309,17 +310,15 @@ env.Library( ], ) -env.CppUnitTest( - target='sasl_mechanism_registry_test', - source=[ - 'sasl_mechanism_registry_test.cpp', - ], - LIBDEPS=[ - 'authmocks', - 'saslauth', - '$BUILD_DIR/mongo/db/service_context_noop_init', - ], -) +env.CppUnitTest(target='sasl_mechanism_registry_test', + source=[ + 'sasl_mechanism_registry_test.cpp', + ], + LIBDEPS=[ + '$BUILD_DIR/mongo/db/service_context_test_fixture', + 'authmocks', + 'saslauth', + ]) env.Library( target='authmongod', @@ -343,8 +342,7 @@ env.Library( source=[ 'authz_manager_external_state_s.cpp', 'authz_session_external_state_s.cpp', - 'user_cache_invalidator_job.cpp' - ], + 'user_cache_invalidator_job.cpp'], LIBDEPS=[ 'authservercommon', '$BUILD_DIR/mongo/s/catalog/dist_lock_manager', @@ -376,7 +374,7 @@ env.CppUnitTest( LIBDEPS=[ 'auth', 'authmocks', - '$BUILD_DIR/mongo/db/service_context_noop_init', + '$BUILD_DIR/mongo/db/service_context_test_fixture', ], ) @@ -388,7 +386,7 @@ env.CppUnitTest( LIBDEPS=[ 'auth', 'authmocks', - '$BUILD_DIR/mongo/db/service_context_noop_init', + '$BUILD_DIR/mongo/db/service_context_test_fixture', ], ) @@ -400,7 +398,7 @@ env.CppUnitTest( LIBDEPS=[ 'auth', 'authmocks', - '$BUILD_DIR/mongo/db/service_context_noop_init', + '$BUILD_DIR/mongo/db/service_context_test_fixture', ], ) @@ -412,7 +410,7 @@ env.CppUnitTest( LIBDEPS=[ 'auth', 'authmocks', - '$BUILD_DIR/mongo/db/service_context_noop_init', + '$BUILD_DIR/mongo/db/service_context_test_fixture', ], ) @@ -424,7 +422,7 @@ env.CppUnitTest( LIBDEPS=[ 'auth', 'authmocks', - '$BUILD_DIR/mongo/db/service_context_noop_init', + '$BUILD_DIR/mongo/db/service_context_test_fixture', ], ) @@ -436,35 +434,25 @@ env.CppUnitTest( LIBDEPS=[ 'auth', 'authmocks', - '$BUILD_DIR/mongo/db/service_context_noop_init', + '$BUILD_DIR/mongo/db/service_context_test_fixture', '$BUILD_DIR/mongo/transport/transport_layer_common', '$BUILD_DIR/mongo/transport/transport_layer_mock', ], ) -env.Library( - target='authorization_session_for_test', - source=[ - 'authorization_session_for_test.cpp', - ], - LIBDEPS=[ - 'auth', - 'auth_impl_internal', - ], -) - env.CppUnitTest( target='authorization_session_test', source=[ 'authorization_session_test.cpp', + 'authorization_session_for_test.cpp', ], LIBDEPS=[ 'auth', 'authmocks', + 'auth_impl_internal', 'saslauth', - 'authorization_session_for_test', '$BUILD_DIR/mongo/db/pipeline/pipeline', - '$BUILD_DIR/mongo/db/service_context_noop_init', + '$BUILD_DIR/mongo/db/service_context_test_fixture', '$BUILD_DIR/mongo/transport/transport_layer_mock', ], ) @@ -491,7 +479,7 @@ env.CppUnitTest( LIBDEPS=[ 'address_restriction', '$BUILD_DIR/mongo/base', - '$BUILD_DIR/mongo/db/service_context_noop_init', + '$BUILD_DIR/mongo/db/service_context_test_fixture', '$BUILD_DIR/mongo/util/net/network', ], ) @@ -506,7 +494,7 @@ env.CppUnitTest( 'authmocks', 'saslauth', '$BUILD_DIR/mongo/client/sasl_client', - '$BUILD_DIR/mongo/db/service_context_noop_init', + '$BUILD_DIR/mongo/db/service_context_test_fixture', ], ) diff --git a/src/mongo/db/auth/auth_decorations.cpp b/src/mongo/db/auth/auth_decorations.cpp index c78117b91e6..13b4edbc6b5 100644 --- a/src/mongo/db/auth/auth_decorations.cpp +++ b/src/mongo/db/auth/auth_decorations.cpp @@ -53,9 +53,9 @@ const auto getAuthorizationSession = class AuthzClientObserver final : public ServiceContext::ClientObserver { public: void onCreateClient(Client* client) override { - auto service = client->getServiceContext(); - AuthorizationSession::set(client, - AuthorizationManager::get(service)->makeAuthorizationSession()); + if (auto authzManager = AuthorizationManager::get(client->getServiceContext())) { + AuthorizationSession::set(client, authzManager->makeAuthorizationSession()); + } } void onDestroyClient(Client* client) override {} @@ -64,6 +64,11 @@ public: void onDestroyOperationContext(OperationContext* opCtx) override {} }; +ServiceContext::ConstructorActionRegisterer authzClientObserverRegisterer{ + "AuthzClientObserver", [](ServiceContext* service) { + service->registerClientObserver(std::make_unique<AuthzClientObserver>()); + }}; + } // namespace void AuthenticationSession::set(Client* client, std::unique_ptr<AuthenticationSession> newSession) { @@ -86,7 +91,6 @@ AuthorizationManager* AuthorizationManager::get(ServiceContext& service) { void AuthorizationManager::set(ServiceContext* service, std::unique_ptr<AuthorizationManager> authzManager) { getAuthorizationManager(service) = std::move(authzManager); - service->registerClientObserver(std::make_unique<AuthzClientObserver>()); } AuthorizationSession* AuthorizationSession::get(Client* client) { diff --git a/src/mongo/db/auth/authorization_manager_global.cpp b/src/mongo/db/auth/authorization_manager_global.cpp index 3f8a8808d04..0088ac451d5 100644 --- a/src/mongo/db/auth/authorization_manager_global.cpp +++ b/src/mongo/db/auth/authorization_manager_global.cpp @@ -91,23 +91,16 @@ AuthorizationManager* getGlobalAuthorizationManager() { MONGO_EXPORT_STARTUP_SERVER_PARAMETER(startupAuthSchemaValidation, bool, true); -GlobalInitializerRegisterer authorizationManagerInitializer( +ServiceContext::ConstructorActionRegisterer createAuthorizationManager( "CreateAuthorizationManager", - {MONGO_SHIM_DEPENDENCY(AuthorizationManager::create), - "OIDGeneration", + {"OIDGeneration", "EndStartupOptionStorage", - "ServiceContext"}, - [](InitializerContext* context) { + MONGO_SHIM_DEPENDENCY(AuthorizationManager::create)}, + [](ServiceContext* service) { auto authzManager = AuthorizationManager::create(); authzManager->setAuthEnabled(serverGlobalParams.authState == ServerGlobalParams::AuthState::kEnabled); authzManager->setShouldValidateAuthSchemaOnStartup(startupAuthSchemaValidation); - AuthorizationManager::set(getGlobalServiceContext(), std::move(authzManager)); - return Status::OK(); - }, - [](DeinitializerContext* context) { - AuthorizationManager::set(getGlobalServiceContext(), nullptr); - return Status::OK(); + AuthorizationManager::set(service, std::move(authzManager)); }); - } // namespace mongo diff --git a/src/mongo/db/auth/authorization_manager_test.cpp b/src/mongo/db/auth/authorization_manager_test.cpp index cfb62e5ff50..e0ba470d4f5 100644 --- a/src/mongo/db/auth/authorization_manager_test.cpp +++ b/src/mongo/db/auth/authorization_manager_test.cpp @@ -46,8 +46,9 @@ #include "mongo/db/auth/sasl_options.h" #include "mongo/db/jsobj.h" #include "mongo/db/namespace_string.h" -#include "mongo/db/operation_context_noop.h" -#include "mongo/db/service_context_noop.h" +#include "mongo/db/operation_context.h" +#include "mongo/db/service_context_test_fixture.h" +#include "mongo/db/storage/recovery_unit_noop.h" #include "mongo/stdx/memory.h" #include "mongo/transport/session.h" #include "mongo/transport/transport_layer_mock.h" @@ -73,21 +74,29 @@ void setX509PeerInfo(const transport::SessionHandle& session, SSLPeerInfo info) using std::vector; -class AuthorizationManagerTest : public ::mongo::unittest::Test { +class AuthorizationManagerTest : public ServiceContextTest { public: virtual ~AuthorizationManagerTest() { if (authzManager) authzManager->invalidateUserCache(); } - void setUp() override { + AuthorizationManagerTest() { auto localExternalState = std::make_unique<AuthzManagerExternalStateMock>(); externalState = localExternalState.get(); - authzManager = std::make_unique<AuthorizationManagerImpl>( + auto localAuthzManager = std::make_unique<AuthorizationManagerImpl>( std::move(localExternalState), AuthorizationManagerImpl::InstallMockForTestingOrAuthImpl{}); - externalState->setAuthorizationManager(authzManager.get()); + authzManager = localAuthzManager.get(); + externalState->setAuthorizationManager(authzManager); authzManager->setAuthEnabled(true); + AuthorizationManager::set(getServiceContext(), std::move(localAuthzManager)); + + // Re-initialize the client after setting the AuthorizationManager to get an + // AuthorizationSession. + Client::releaseCurrent(); + Client::initThread(getThreadName(), session); + opCtx = makeOperationContext(); credentials = BSON("SCRAM-SHA-1" << scram::Secrets<SHA1Block>::generateCredentials( @@ -97,15 +106,18 @@ public: "password", saslGlobalParams.scramSHA256IterationCount.load())); } - std::unique_ptr<AuthorizationManager> authzManager; + transport::TransportLayerMock transportLayer; + transport::SessionHandle session = transportLayer.createSession(); + AuthorizationManager* authzManager; AuthzManagerExternalStateMock* externalState; BSONObj credentials; + ServiceContext::UniqueOperationContext opCtx; }; TEST_F(AuthorizationManagerTest, testAcquireV2User) { - OperationContextNoop opCtx; - ASSERT_OK(externalState->insertPrivilegeDocument(&opCtx, + + ASSERT_OK(externalState->insertPrivilegeDocument(opCtx.get(), BSON("_id" << "admin.v2read" << "user" @@ -120,7 +132,7 @@ TEST_F(AuthorizationManagerTest, testAcquireV2User) { << "db" << "test"))), BSONObj())); - ASSERT_OK(externalState->insertPrivilegeDocument(&opCtx, + ASSERT_OK(externalState->insertPrivilegeDocument(opCtx.get(), BSON("_id" << "admin.v2cluster" << "user" @@ -137,7 +149,7 @@ TEST_F(AuthorizationManagerTest, testAcquireV2User) { BSONObj())); User* v2read; - ASSERT_OK(authzManager->acquireUser(&opCtx, UserName("v2read", "test"), &v2read)); + ASSERT_OK(authzManager->acquireUser(opCtx.get(), UserName("v2read", "test"), &v2read)); ASSERT_EQUALS(UserName("v2read", "test"), v2read->getName()); ASSERT(v2read->isValid()); ASSERT_EQUALS(1U, v2read->getRefCount()); @@ -151,7 +163,7 @@ TEST_F(AuthorizationManagerTest, testAcquireV2User) { authzManager->releaseUser(v2read); User* v2cluster; - ASSERT_OK(authzManager->acquireUser(&opCtx, UserName("v2cluster", "admin"), &v2cluster)); + ASSERT_OK(authzManager->acquireUser(opCtx.get(), UserName("v2cluster", "admin"), &v2cluster)); ASSERT_EQUALS(UserName("v2cluster", "admin"), v2cluster->getName()); ASSERT(v2cluster->isValid()); ASSERT_EQUALS(1U, v2cluster->getRefCount()); @@ -167,14 +179,9 @@ TEST_F(AuthorizationManagerTest, testAcquireV2User) { #ifdef MONGO_CONFIG_SSL TEST_F(AuthorizationManagerTest, testLocalX509Authorization) { - ServiceContextNoop serviceContext; - transport::TransportLayerMock transportLayer{}; - transport::SessionHandle session = transportLayer.createSession(); setX509PeerInfo( session, SSLPeerInfo(buildX509Name(), {RoleName("read", "test"), RoleName("readWrite", "test")})); - ServiceContext::UniqueClient client = serviceContext.makeClient("testClient", session); - ServiceContext::UniqueOperationContext opCtx = client->makeOperationContext(); User* x509User; ASSERT_OK( @@ -202,14 +209,9 @@ TEST_F(AuthorizationManagerTest, testLocalX509Authorization) { #endif TEST_F(AuthorizationManagerTest, testLocalX509AuthorizationInvalidUser) { - ServiceContextNoop serviceContext; - transport::TransportLayerMock transportLayer{}; - transport::SessionHandle session = transportLayer.createSession(); setX509PeerInfo( session, SSLPeerInfo(buildX509Name(), {RoleName("read", "test"), RoleName("write", "test")})); - ServiceContext::UniqueClient client = serviceContext.makeClient("testClient", session); - ServiceContext::UniqueOperationContext opCtx = client->makeOperationContext(); User* x509User; ASSERT_NOT_OK( @@ -217,12 +219,7 @@ TEST_F(AuthorizationManagerTest, testLocalX509AuthorizationInvalidUser) { } TEST_F(AuthorizationManagerTest, testLocalX509AuthenticationNoAuthorization) { - ServiceContextNoop serviceContext; - transport::TransportLayerMock transportLayer{}; - transport::SessionHandle session = transportLayer.createSession(); setX509PeerInfo(session, {}); - ServiceContext::UniqueClient client = serviceContext.makeClient("testClient", session); - ServiceContext::UniqueOperationContext opCtx = client->makeOperationContext(); User* x509User; ASSERT_NOT_OK( @@ -295,10 +292,10 @@ public: // Tests SERVER-21535, unrecognized actions should be ignored rather than causing errors. TEST_F(AuthorizationManagerTest, testAcquireV2UserWithUnrecognizedActions) { - OperationContextNoop opCtx; + ASSERT_OK(externalState->insertPrivilegeDocument( - &opCtx, + opCtx.get(), BSON("_id" << "admin.myUser" << "user" @@ -324,7 +321,7 @@ TEST_F(AuthorizationManagerTest, testAcquireV2UserWithUnrecognizedActions) { BSONObj())); User* myUser; - ASSERT_OK(authzManager->acquireUser(&opCtx, UserName("myUser", "test"), &myUser)); + ASSERT_OK(authzManager->acquireUser(opCtx.get(), UserName("myUser", "test"), &myUser)); ASSERT_EQUALS(UserName("myUser", "test"), myUser->getName()); ASSERT(myUser->isValid()); ASSERT_EQUALS(1U, myUser->getRefCount()); @@ -365,17 +362,16 @@ public: }; virtual void setUp() override { - opCtx.setRecoveryUnit(recoveryUnit, WriteUnitOfWork::RecoveryUnitState::kNotInUnitOfWork); + opCtx->setRecoveryUnit(recoveryUnit, WriteUnitOfWork::RecoveryUnitState::kNotInUnitOfWork); AuthorizationManagerTest::setUp(); } - OperationContextNoop opCtx; size_t registeredChanges = 0; MockRecoveryUnit* recoveryUnit = new MockRecoveryUnit(®isteredChanges); }; TEST_F(AuthorizationManagerLogOpTest, testDropDatabaseAddsRecoveryUnits) { - authzManager->logOp(&opCtx, + authzManager->logOp(opCtx.get(), "c", {"admin", "$cmd"}, BSON("dropDatabase" @@ -385,7 +381,7 @@ TEST_F(AuthorizationManagerLogOpTest, testDropDatabaseAddsRecoveryUnits) { } TEST_F(AuthorizationManagerLogOpTest, testDropAuthCollectionAddsRecoveryUnits) { - authzManager->logOp(&opCtx, + authzManager->logOp(opCtx.get(), "c", {"admin", "$cmd"}, BSON("drop" @@ -393,7 +389,7 @@ TEST_F(AuthorizationManagerLogOpTest, testDropAuthCollectionAddsRecoveryUnits) { nullptr); ASSERT_EQ(size_t(1), registeredChanges); - authzManager->logOp(&opCtx, + authzManager->logOp(opCtx.get(), "c", {"admin", "$cmd"}, BSON("drop" @@ -401,7 +397,7 @@ TEST_F(AuthorizationManagerLogOpTest, testDropAuthCollectionAddsRecoveryUnits) { nullptr); ASSERT_EQ(size_t(2), registeredChanges); - authzManager->logOp(&opCtx, + authzManager->logOp(opCtx.get(), "c", {"admin", "$cmd"}, BSON("drop" @@ -409,7 +405,7 @@ TEST_F(AuthorizationManagerLogOpTest, testDropAuthCollectionAddsRecoveryUnits) { nullptr); ASSERT_EQ(size_t(3), registeredChanges); - authzManager->logOp(&opCtx, + authzManager->logOp(opCtx.get(), "c", {"admin", "$cmd"}, BSON("drop" @@ -419,21 +415,21 @@ TEST_F(AuthorizationManagerLogOpTest, testDropAuthCollectionAddsRecoveryUnits) { } TEST_F(AuthorizationManagerLogOpTest, testCreateAnyCollectionAddsNoRecoveryUnits) { - authzManager->logOp(&opCtx, + authzManager->logOp(opCtx.get(), "c", {"admin", "$cmd"}, BSON("create" << "system.users"), nullptr); - authzManager->logOp(&opCtx, + authzManager->logOp(opCtx.get(), "c", {"admin", "$cmd"}, BSON("create" << "system.profile"), nullptr); - authzManager->logOp(&opCtx, + authzManager->logOp(opCtx.get(), "c", {"admin", "$cmd"}, BSON("create" @@ -444,7 +440,7 @@ TEST_F(AuthorizationManagerLogOpTest, testCreateAnyCollectionAddsNoRecoveryUnits } TEST_F(AuthorizationManagerLogOpTest, testRawInsertToRolesCollectionAddsRecoveryUnits) { - authzManager->logOp(&opCtx, + authzManager->logOp(opCtx.get(), "i", {"admin", "system.profile"}, BSON("_id" @@ -452,7 +448,7 @@ TEST_F(AuthorizationManagerLogOpTest, testRawInsertToRolesCollectionAddsRecovery nullptr); ASSERT_EQ(size_t(0), registeredChanges); - authzManager->logOp(&opCtx, + authzManager->logOp(opCtx.get(), "i", {"admin", "system.users"}, BSON("_id" @@ -460,7 +456,7 @@ TEST_F(AuthorizationManagerLogOpTest, testRawInsertToRolesCollectionAddsRecovery nullptr); ASSERT_EQ(size_t(0), registeredChanges); - authzManager->logOp(&opCtx, + authzManager->logOp(opCtx.get(), "i", {"admin", "system.roles"}, BSON("_id" diff --git a/src/mongo/db/auth/authorization_session_test.cpp b/src/mongo/db/auth/authorization_session_test.cpp index 19e29fcb6f3..e629f50cac5 100644 --- a/src/mongo/db/auth/authorization_session_test.cpp +++ b/src/mongo/db/auth/authorization_session_test.cpp @@ -47,7 +47,7 @@ #include "mongo/db/json.h" #include "mongo/db/namespace_string.h" #include "mongo/db/operation_context.h" -#include "mongo/db/service_context_noop.h" +#include "mongo/db/service_context.h" #include "mongo/stdx/memory.h" #include "mongo/transport/session.h" #include "mongo/transport/transport_layer_mock.h" @@ -89,7 +89,7 @@ public: FailureCapableAuthzManagerExternalStateMock* managerState; transport::TransportLayerMock transportLayer; transport::SessionHandle session; - ServiceContextNoop serviceContext; + ServiceContext::UniqueServiceContext serviceContext = ServiceContext::make(); ServiceContext::UniqueClient client; ServiceContext::UniqueOperationContext _opCtx; AuthzSessionExternalStateMock* sessionState; @@ -99,7 +99,7 @@ public: void setUp() { session = transportLayer.createSession(); - client = serviceContext.makeClient("testClient", session); + client = serviceContext->makeClient("testClient", session); RestrictionEnvironment::set( session, stdx::make_unique<RestrictionEnvironment>(SockAddr(), SockAddr())); _opCtx = client->makeOperationContext(); @@ -110,7 +110,7 @@ public: std::move(localManagerState), AuthorizationManagerImpl::InstallMockForTestingOrAuthImpl{}); authzManager = uniqueAuthzManager.get(); - AuthorizationManager::set(&serviceContext, std::move(uniqueAuthzManager)); + AuthorizationManager::set(serviceContext.get(), std::move(uniqueAuthzManager)); auto localSessionState = std::make_unique<AuthzSessionExternalStateMock>(authzManager); sessionState = localSessionState.get(); authzSession = std::make_unique<AuthorizationSessionForTest>( diff --git a/src/mongo/db/auth/sasl_authentication_session_test.cpp b/src/mongo/db/auth/sasl_authentication_session_test.cpp index 8497edcac37..70e07043966 100644 --- a/src/mongo/db/auth/sasl_authentication_session_test.cpp +++ b/src/mongo/db/auth/sasl_authentication_session_test.cpp @@ -22,8 +22,8 @@ #include "mongo/db/auth/sasl_plain_server_conversation.h" #include "mongo/db/auth/sasl_scram_server_conversation.h" #include "mongo/db/jsobj.h" -#include "mongo/db/operation_context_noop.h" -#include "mongo/db/service_context_noop.h" +#include "mongo/db/operation_context.h" +#include "mongo/db/service_context_test_fixture.h" #include "mongo/unittest/unittest.h" #include "mongo/util/log.h" #include "mongo/util/password_digest.h" @@ -32,7 +32,7 @@ namespace mongo { namespace { -class SaslConversation : public unittest::Test { +class SaslConversation : public ServiceContextTest { public: explicit SaslConversation(std::string mech); @@ -42,8 +42,6 @@ public: void testWrongClientMechanism(); void testWrongServerMechanism(); - ServiceContextNoop serviceContext; - ServiceContext::UniqueClient opClient; ServiceContext::UniqueOperationContext opCtx; AuthzManagerExternalStateMock* authManagerExternalState; AuthorizationManager* authManager; @@ -66,8 +64,7 @@ const std::string mockServiceName = "mocksvc"; const std::string mockHostName = "host.mockery.com"; SaslConversation::SaslConversation(std::string mech) - : opClient(serviceContext.makeClient("saslTest")), - opCtx(serviceContext.makeOperationContext(opClient.get())), + : opCtx(makeOperationContext()), authManagerExternalState(new AuthzManagerExternalStateMock), authManager(new AuthorizationManagerImpl( std::unique_ptr<AuthzManagerExternalState>(authManagerExternalState), @@ -75,7 +72,8 @@ SaslConversation::SaslConversation(std::string mech) authSession(authManager->makeAuthorizationSession()), mechanism(mech) { - AuthorizationManager::set(&serviceContext, std::unique_ptr<AuthorizationManager>(authManager)); + AuthorizationManager::set(getServiceContext(), + std::unique_ptr<AuthorizationManager>(authManager)); client.reset(SaslClientSession::create(mechanism)); diff --git a/src/mongo/db/auth/sasl_mechanism_registry.cpp b/src/mongo/db/auth/sasl_mechanism_registry.cpp index 3426ca97b80..cb588b9b829 100644 --- a/src/mongo/db/auth/sasl_mechanism_registry.cpp +++ b/src/mongo/db/auth/sasl_mechanism_registry.cpp @@ -124,23 +124,13 @@ bool SASLServerMechanismRegistry::_mechanismSupportedByConfig(StringData mechNam return sequenceContains(saslGlobalParams.authenticationMechanisms, mechName); } -GlobalInitializerRegisterer SASLServerMechanismRegistryInitializer( +namespace { +ServiceContext::ConstructorActionRegisterer SASLServerMechanismRegistryInitializer{ "CreateSASLServerMechanismRegistry", - {"ServiceContext"}, - [](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(); - }, - [](DeinitializerContext* context) { - SASLServerMechanismRegistry::set(getGlobalServiceContext(), nullptr); - - return Status::OK(); - }); + {"EndStartupOptionStorage"}, + [](ServiceContext* service) { + SASLServerMechanismRegistry::set(service, std::make_unique<SASLServerMechanismRegistry>()); + }}; +} // namespace } // namespace mongo diff --git a/src/mongo/db/auth/sasl_mechanism_registry.h b/src/mongo/db/auth/sasl_mechanism_registry.h index 6d8fba8efd0..78c790b7223 100644 --- a/src/mongo/db/auth/sasl_mechanism_registry.h +++ b/src/mongo/db/auth/sasl_mechanism_registry.h @@ -28,6 +28,7 @@ #pragma once +#include <boost/optional.hpp> #include <memory> #include <unordered_map> @@ -333,4 +334,18 @@ private: stdx::unordered_map<std::string, std::unique_ptr<ServerFactoryBase>> _externalMap; }; +template <typename Factory> +class GlobalSASLMechanismRegisterer { +private: + boost::optional<ServiceContext::ConstructorActionRegisterer> registerer; + +public: + GlobalSASLMechanismRegisterer() { + registerer.emplace(std::string(typeid(Factory).name()), + std::vector<std::string>{"CreateSASLServerMechanismRegistry"}, + [](ServiceContext* service) { + SASLServerMechanismRegistry::get(service).registerFactory<Factory>(); + }); + } +}; } // namespace mongo diff --git a/src/mongo/db/auth/sasl_mechanism_registry_test.cpp b/src/mongo/db/auth/sasl_mechanism_registry_test.cpp index 6122498e20a..d7f4527f6e7 100644 --- a/src/mongo/db/auth/sasl_mechanism_registry_test.cpp +++ b/src/mongo/db/auth/sasl_mechanism_registry_test.cpp @@ -31,8 +31,8 @@ #include "mongo/db/auth/authorization_manager.h" #include "mongo/db/auth/authorization_manager_impl.h" #include "mongo/db/auth/authz_manager_external_state_mock.h" -#include "mongo/db/operation_context_noop.h" -#include "mongo/db/service_context_noop.h" +#include "mongo/db/operation_context.h" +#include "mongo/db/service_context_test_fixture.h" #include "mongo/unittest/unittest.h" namespace mongo { @@ -128,16 +128,15 @@ public: }; -class MechanismRegistryTest : public mongo::unittest::Test { +class MechanismRegistryTest : public ServiceContextTest { public: MechanismRegistryTest() - : opClient(serviceContext.makeClient("mechanismRegistryTest")), - opCtx(serviceContext.makeOperationContext(opClient.get())), + : opCtx(makeOperationContext()), authManagerExternalState(new AuthzManagerExternalStateMock()), authManager(new AuthorizationManagerImpl( std::unique_ptr<AuthzManagerExternalStateMock>(authManagerExternalState), AuthorizationManagerImpl::InstallMockForTestingOrAuthImpl{})) { - AuthorizationManager::set(&serviceContext, + AuthorizationManager::set(getServiceContext(), std::unique_ptr<AuthorizationManager>(authManager)); ASSERT_OK(authManagerExternalState->updateOne( @@ -181,8 +180,6 @@ public: BSONObj())); } - ServiceContextNoop serviceContext; - ServiceContext::UniqueClient opClient; ServiceContext::UniqueOperationContext opCtx; AuthzManagerExternalStateMock* authManagerExternalState; AuthorizationManager* authManager; diff --git a/src/mongo/db/auth/sasl_options.cpp b/src/mongo/db/auth/sasl_options.cpp index f35825c6d14..d3eb191a8b4 100644 --- a/src/mongo/db/auth/sasl_options.cpp +++ b/src/mongo/db/auth/sasl_options.cpp @@ -34,6 +34,7 @@ #include "mongo/db/server_parameters.h" #include "mongo/util/log.h" #include "mongo/util/mongoutils/str.h" +#include "mongo/util/net/socket_utils.h" #include "mongo/util/options_parser/startup_option_init.h" #include "mongo/util/options_parser/startup_options.h" @@ -172,6 +173,11 @@ Status storeSASLOptions(const moe::Environment& params) { } } + if (saslGlobalParams.hostName.empty()) + saslGlobalParams.hostName = getHostNameCached(); + if (saslGlobalParams.serviceName.empty()) + saslGlobalParams.serviceName = "mongodb"; + return Status::OK(); } diff --git a/src/mongo/db/auth/sasl_plain_server_conversation.cpp b/src/mongo/db/auth/sasl_plain_server_conversation.cpp index 3c32c9b7f58..7d89c2eaeb8 100644 --- a/src/mongo/db/auth/sasl_plain_server_conversation.cpp +++ b/src/mongo/db/auth/sasl_plain_server_conversation.cpp @@ -157,12 +157,7 @@ StatusWith<std::tuple<bool, std::string>> SASLPlainServerMechanism::stepImpl( return std::make_tuple(true, std::string()); } -MONGO_INITIALIZER_WITH_PREREQUISITES(SASLPLAINServerMechanism, - ("CreateSASLServerMechanismRegistry")) -(::mongo::InitializerContext* context) { - auto& registry = SASLServerMechanismRegistry::get(getGlobalServiceContext()); - registry.registerFactory<PLAINServerFactory>(); - return Status::OK(); -} - +namespace { +GlobalSASLMechanismRegisterer<PLAINServerFactory> plainRegisterer; +} // namespace } // namespace mongo diff --git a/src/mongo/db/auth/sasl_scram_server_conversation.cpp b/src/mongo/db/auth/sasl_scram_server_conversation.cpp index 28cbe4537fd..d3ded3c88f8 100644 --- a/src/mongo/db/auth/sasl_scram_server_conversation.cpp +++ b/src/mongo/db/auth/sasl_scram_server_conversation.cpp @@ -342,13 +342,8 @@ StatusWith<std::tuple<bool, std::string>> SaslSCRAMServerMechanism<Policy>::_sec template class SaslSCRAMServerMechanism<SCRAMSHA1Policy>; template class SaslSCRAMServerMechanism<SCRAMSHA256Policy>; -MONGO_INITIALIZER_WITH_PREREQUISITES(SASLSCRAMServerMechanism, - ("CreateSASLServerMechanismRegistry")) -(::mongo::InitializerContext* context) { - auto& registry = SASLServerMechanismRegistry::get(getGlobalServiceContext()); - registry.registerFactory<SCRAMSHA1ServerFactory>(); - registry.registerFactory<SCRAMSHA256ServerFactory>(); - return Status::OK(); -} - +namespace { +GlobalSASLMechanismRegisterer<SCRAMSHA1ServerFactory> scramsha1Registerer; +GlobalSASLMechanismRegisterer<SCRAMSHA256ServerFactory> scramsha256Registerer; +} // namespace } // namespace mongo diff --git a/src/mongo/db/auth/sasl_scram_test.cpp b/src/mongo/db/auth/sasl_scram_test.cpp index 2a347b6d464..4520586f0a4 100644 --- a/src/mongo/db/auth/sasl_scram_test.cpp +++ b/src/mongo/db/auth/sasl_scram_test.cpp @@ -43,7 +43,7 @@ #include "mongo/db/auth/authz_session_external_state_mock.h" #include "mongo/db/auth/sasl_mechanism_registry.h" #include "mongo/db/auth/sasl_scram_server_conversation.h" -#include "mongo/db/service_context_noop.h" +#include "mongo/db/service_context.h" #include "mongo/stdx/memory.h" #include "mongo/unittest/unittest.h" #include "mongo/util/base64.h" @@ -174,9 +174,9 @@ protected: const SCRAMStepsResult goalState = SCRAMStepsResult(SaslTestState(SaslTestState::kClient, 4), Status::OK()); - std::unique_ptr<ServiceContextNoop> serviceContext; - ServiceContextNoop::UniqueClient client; - ServiceContextNoop::UniqueOperationContext opCtx; + ServiceContext::UniqueServiceContext serviceContext; + ServiceContext::UniqueClient client; + ServiceContext::UniqueOperationContext opCtx; AuthzManagerExternalStateMock* authzManagerExternalState; AuthorizationManager* authzManager; @@ -186,7 +186,7 @@ protected: std::unique_ptr<NativeSaslClientSession> saslClientSession; void setUp() final { - serviceContext = stdx::make_unique<ServiceContextNoop>(); + serviceContext = ServiceContext::make(); client = serviceContext->makeClient("test"); opCtx = serviceContext->makeOperationContext(client.get()); diff --git a/src/mongo/db/catalog/database_holder_impl.cpp b/src/mongo/db/catalog/database_holder_impl.cpp index c4873930036..0497c3fa74a 100644 --- a/src/mongo/db/catalog/database_holder_impl.cpp +++ b/src/mongo/db/catalog/database_holder_impl.cpp @@ -50,23 +50,14 @@ namespace mongo { namespace { -std::unique_ptr<DatabaseHolder> dbHolderStorage; - -GlobalInitializerRegisterer dbHolderImplInitializer("InitializeDbHolderimpl", - [](InitializerContext* const) { - dbHolderStorage = - std::make_unique<DatabaseHolder>(); - return Status::OK(); - }, - [](DeinitializerContext* const) { - dbHolderStorage = nullptr; - return Status::OK(); - }); + +const auto dbHolderStorage = ServiceContext::declareDecoration<DatabaseHolder>(); + } // namespace MONGO_REGISTER_SHIM(DatabaseHolder::getDatabaseHolder) ()->DatabaseHolder& { - return *dbHolderStorage; + return dbHolderStorage(getGlobalServiceContext()); } MONGO_REGISTER_SHIM(DatabaseHolder::makeImpl) diff --git a/src/mongo/db/client.h b/src/mongo/db/client.h index 99b172505e3..74130191b99 100644 --- a/src/mongo/db/client.h +++ b/src/mongo/db/client.h @@ -47,6 +47,7 @@ #include "mongo/transport/session.h" #include "mongo/util/concurrency/spin_lock.h" #include "mongo/util/decorable.h" +#include "mongo/util/invariant.h" #include "mongo/util/net/hostandport.h" namespace mongo { @@ -242,6 +243,37 @@ private: PseudoRandom _prng; }; +/** + * Utility class to temporarily swap which client is bound to the running thread. + * + * Use this class to bind a client to the current thread for the duration of the + * AlternativeClientRegion's lifetime, restoring the prior client, if any, at the + * end of the block. + */ +class AlternativeClientRegion { +public: + explicit AlternativeClientRegion(ServiceContext::UniqueClient& clientToUse) + : _alternateClient(&clientToUse) { + invariant(clientToUse); + if (Client::getCurrent()) { + _originalClient = Client::releaseCurrent(); + } + Client::setCurrent(std::move(*_alternateClient)); + } + + ~AlternativeClientRegion() { + *_alternateClient = Client::releaseCurrent(); + if (_originalClient) { + Client::setCurrent(std::move(_originalClient)); + } + } + +private: + ServiceContext::UniqueClient _originalClient; + ServiceContext::UniqueClient* const _alternateClient; +}; + + /** get the Client object for this thread. */ Client& cc(); diff --git a/src/mongo/db/commands/index_filter_commands_test.cpp b/src/mongo/db/commands/index_filter_commands_test.cpp index 46423af1ed3..f9c6fb51f70 100644 --- a/src/mongo/db/commands/index_filter_commands_test.cpp +++ b/src/mongo/db/commands/index_filter_commands_test.cpp @@ -149,13 +149,12 @@ void addQueryShapeToPlanCache(OperationContext* opCtx, /** * Checks if plan cache contains query shape. */ -bool planCacheContains(const PlanCache& planCache, +bool planCacheContains(OperationContext* opCtx, + const PlanCache& planCache, const char* queryStr, const char* sortStr, const char* projectionStr, const char* collationStr) { - QueryTestServiceContext serviceContext; - auto opCtx = serviceContext.makeOperationContext(); // Create canonical query. auto qr = stdx::make_unique<QueryRequest>(nss); @@ -163,7 +162,7 @@ bool planCacheContains(const PlanCache& planCache, qr->setSort(fromjson(sortStr)); qr->setProj(fromjson(projectionStr)); qr->setCollation(fromjson(collationStr)); - auto statusWithInputQuery = CanonicalQuery::canonicalize(opCtx.get(), std::move(qr)); + auto statusWithInputQuery = CanonicalQuery::canonicalize(opCtx, std::move(qr)); ASSERT_OK(statusWithInputQuery.getStatus()); unique_ptr<CanonicalQuery> inputQuery = std::move(statusWithInputQuery.getValue()); @@ -183,7 +182,7 @@ bool planCacheContains(const PlanCache& planCache, qr->setSort(entry->sort); qr->setProj(entry->projection); qr->setCollation(entry->collation); - auto statusWithCurrentQuery = CanonicalQuery::canonicalize(opCtx.get(), std::move(qr)); + auto statusWithCurrentQuery = CanonicalQuery::canonicalize(opCtx, std::move(qr)); ASSERT_OK(statusWithCurrentQuery.getStatus()); unique_ptr<CanonicalQuery> currentQuery = std::move(statusWithCurrentQuery.getValue()); @@ -333,8 +332,12 @@ TEST(IndexFilterCommandsTest, SetAndClearFilters) { "{a: -1}", "{_id: 0, a: 1}", "{locale: 'mock_reverse_string'}"); - ASSERT_TRUE(planCacheContains( - planCache, "{a: 1, b: 1}", "{a: -1}", "{_id: 0, a: 1}", "{locale: 'mock_reverse_string'}")); + ASSERT_TRUE(planCacheContains(opCtx.get(), + planCache, + "{a: 1, b: 1}", + "{a: -1}", + "{_id: 0, a: 1}", + "{locale: 'mock_reverse_string'}")); ASSERT_OK(SetFilter::set(opCtx.get(), &querySettings, @@ -347,8 +350,12 @@ TEST(IndexFilterCommandsTest, SetAndClearFilters) { ASSERT_EQUALS(filters.size(), 1U); // Query shape should not exist in plan cache after hint is updated. - ASSERT_FALSE(planCacheContains( - planCache, "{a: 1, b: 1}", "{a: -1}", "{_id: 0, a: 1}", "{locale: 'mock_reverse_string'}")); + ASSERT_FALSE(planCacheContains(opCtx.get(), + planCache, + "{a: 1, b: 1}", + "{a: -1}", + "{_id: 0, a: 1}", + "{locale: 'mock_reverse_string'}")); // Fields in filter should match criteria in most recent query settings update. ASSERT_BSONOBJ_EQ(filters[0].getObjectField("query"), fromjson("{a: 1, b: 1}")); @@ -403,8 +410,8 @@ TEST(IndexFilterCommandsTest, SetAndClearFilters) { ASSERT_EQUALS(filters.size(), 2U); // Query shape should not exist in plan cache after cleaing 1 hint. - ASSERT_FALSE(planCacheContains(planCache, "{a: 1}", "{}", "{}", "{}")); - ASSERT_TRUE(planCacheContains(planCache, "{b: 1}", "{}", "{}", "{}")); + ASSERT_FALSE(planCacheContains(opCtx.get(), planCache, "{a: 1}", "{}", "{}", "{}")); + ASSERT_TRUE(planCacheContains(opCtx.get(), planCache, "{b: 1}", "{}", "{}", "{}")); // Clear all filters ASSERT_OK( @@ -413,7 +420,7 @@ TEST(IndexFilterCommandsTest, SetAndClearFilters) { ASSERT_TRUE(filters.empty()); // {b: 1} should be gone from plan cache after flushing query settings. - ASSERT_FALSE(planCacheContains(planCache, "{b: 1}", "{}", "{}", "{}")); + ASSERT_FALSE(planCacheContains(opCtx.get(), planCache, "{b: 1}", "{}", "{}", "{}")); } TEST(IndexFilterCommandsTest, SetAndClearFiltersCollation) { @@ -430,9 +437,9 @@ TEST(IndexFilterCommandsTest, SetAndClearFiltersCollation) { addQueryShapeToPlanCache( opCtx.get(), &planCache, "{a: 'foo'}", "{}", "{}", "{locale: 'mock_reverse_string'}"); addQueryShapeToPlanCache(opCtx.get(), &planCache, "{a: 'foo'}", "{}", "{}", "{}"); - ASSERT_TRUE( - planCacheContains(planCache, "{a: 'foo'}", "{}", "{}", "{locale: 'mock_reverse_string'}")); - ASSERT_TRUE(planCacheContains(planCache, "{a: 'foo'}", "{}", "{}", "{}")); + ASSERT_TRUE(planCacheContains( + opCtx.get(), planCache, "{a: 'foo'}", "{}", "{}", "{locale: 'mock_reverse_string'}")); + ASSERT_TRUE(planCacheContains(opCtx.get(), planCache, "{a: 'foo'}", "{}", "{}", "{}")); ASSERT_OK(SetFilter::set(opCtx.get(), &querySettings, @@ -450,9 +457,9 @@ TEST(IndexFilterCommandsTest, SetAndClearFiltersCollation) { "mock_reverse_string"); // Plan cache should only contain entry for query without collation. - ASSERT_FALSE( - planCacheContains(planCache, "{a: 'foo'}", "{}", "{}", "{locale: 'mock_reverse_string'}")); - ASSERT_TRUE(planCacheContains(planCache, "{a: 'foo'}", "{}", "{}", "{}")); + ASSERT_FALSE(planCacheContains( + opCtx.get(), planCache, "{a: 'foo'}", "{}", "{}", "{locale: 'mock_reverse_string'}")); + ASSERT_TRUE(planCacheContains(opCtx.get(), planCache, "{a: 'foo'}", "{}", "{}", "{}")); // Add filter for query shape without collation. ASSERT_OK(SetFilter::set(opCtx.get(), @@ -483,9 +490,9 @@ TEST(IndexFilterCommandsTest, SetAndClearFiltersCollation) { ASSERT_BSONOBJ_EQ(filters[0].getObjectField("collation"), fromjson("{}")); // Plan cache should only contain entry for query without collation. - ASSERT_FALSE( - planCacheContains(planCache, "{a: 'foo'}", "{}", "{}", "{locale: 'mock_reverse_string'}")); - ASSERT_TRUE(planCacheContains(planCache, "{a: 'foo'}", "{}", "{}", "{}")); + ASSERT_FALSE(planCacheContains( + opCtx.get(), planCache, "{a: 'foo'}", "{}", "{}", "{locale: 'mock_reverse_string'}")); + ASSERT_TRUE(planCacheContains(opCtx.get(), planCache, "{a: 'foo'}", "{}", "{}", "{}")); } @@ -504,7 +511,7 @@ TEST(IndexFilterCommandsTest, SetFilterAcceptsIndexNames) { collatedIndex}); addQueryShapeToPlanCache(opCtx.get(), &planCache, "{a: 2}", "{}", "{}", "{}"); - ASSERT_TRUE(planCacheContains(planCache, "{a: 2}", "{}", "{}", "{}")); + ASSERT_TRUE(planCacheContains(opCtx.get(), planCache, "{a: 2}", "{}", "{}", "{}")); ASSERT_OK(SetFilter::set(opCtx.get(), &querySettings, diff --git a/src/mongo/db/commands_test.cpp b/src/mongo/db/commands_test.cpp index 0bec7ad4b51..2cdc620d0d9 100644 --- a/src/mongo/db/commands_test.cpp +++ b/src/mongo/db/commands_test.cpp @@ -32,7 +32,7 @@ #include "mongo/db/commands.h" #include "mongo/db/commands_test_example_gen.h" #include "mongo/db/dbmessage.h" -#include "mongo/db/service_context_noop.h" +#include "mongo/db/service_context_test_fixture.h" #include "mongo/unittest/unittest.h" namespace mongo { @@ -96,14 +96,9 @@ TEST(Commands, appendCommandStatusErrorExtraInfo) { ASSERT_BSONOBJ_EQ(actualResult.obj(), expectedResult.obj()); } -class ParseNsOrUUID : public unittest::Test { +class ParseNsOrUUID : public ServiceContextTest { public: - ParseNsOrUUID() - : client(service.makeClient("test")), - opCtxPtr(client->makeOperationContext()), - opCtx(opCtxPtr.get()) {} - ServiceContextNoop service; - ServiceContext::UniqueClient client; + ParseNsOrUUID() : opCtxPtr(makeOperationContext()), opCtx(opCtxPtr.get()) {} ServiceContext::UniqueOperationContext opCtxPtr; OperationContext* opCtx; }; @@ -333,18 +328,18 @@ ExampleMinimalCommand exampleMinimalCommand; ExampleVoidCommand exampleVoidCommand; CmdT<decltype(throwFn)> throwStatusCommand("throwsStatus", throwFn); -struct IncrementTestCommon { +class TypedCommand : public ServiceContextTest { +protected: template <typename T> - void run(T& command, std::function<void(int, const BSONObj&)> postAssert) { + void runIncr(T& command, std::function<void(int, const BSONObj&)> postAssert) { const NamespaceString ns("testdb.coll"); - auto client = getGlobalServiceContext()->makeClient("commands_test"); for (std::int32_t i : {123, 12345, 0, -456}) { const OpMsgRequest request = [&] { typename T::Request incr(ns); incr.setI(i); return incr.serialize(BSON("$db" << ns.db())); }(); - auto opCtx = client->makeOperationContext(); + auto opCtx = makeOperationContext(); auto invocation = command.parse(opCtx.get(), request); ASSERT_EQ(invocation->ns(), ns); @@ -368,29 +363,29 @@ struct IncrementTestCommon { } }; -TEST(TypedCommand, runTyped) { - IncrementTestCommon{}.run(exampleIncrementCommand, [](int i, const BSONObj& reply) { +TEST_F(TypedCommand, runTyped) { + runIncr(exampleIncrementCommand, [](int i, const BSONObj& reply) { ASSERT_EQ(reply["ok"].Double(), 1.0); ASSERT_EQ(reply["iPlusOne"].Int(), i + 1); }); } -TEST(TypedCommand, runMinimal) { - IncrementTestCommon{}.run(exampleMinimalCommand, [](int i, const BSONObj& reply) { +TEST_F(TypedCommand, runMinimal) { + runIncr(exampleMinimalCommand, [](int i, const BSONObj& reply) { ASSERT_EQ(reply["ok"].Double(), 1.0); ASSERT_EQ(reply["iPlusOne"].Int(), i + 1); }); } -TEST(TypedCommand, runVoid) { - IncrementTestCommon{}.run(exampleVoidCommand, [](int i, const BSONObj& reply) { +TEST_F(TypedCommand, runVoid) { + runIncr(exampleVoidCommand, [](int i, const BSONObj& reply) { ASSERT_EQ(reply["ok"].Double(), 1.0); ASSERT_EQ(exampleVoidCommand.iCapture, i + 1); }); } -TEST(TypedCommand, runThrowStatus) { - IncrementTestCommon{}.run(throwStatusCommand, [](int i, const BSONObj& reply) { +TEST_F(TypedCommand, runThrowStatus) { + runIncr(throwStatusCommand, [](int i, const BSONObj& reply) { Status status = Status::OK(); try { (void)throwFn(); diff --git a/src/mongo/db/concurrency/SConscript b/src/mongo/db/concurrency/SConscript index 947096a1eab..0ca5123d60b 100644 --- a/src/mongo/db/concurrency/SConscript +++ b/src/mongo/db/concurrency/SConscript @@ -56,7 +56,6 @@ env.Benchmark( 'd_concurrency_bm.cpp', ], LIBDEPS=[ - '$BUILD_DIR/mongo/db/service_context_noop_init', 'lock_manager', ]) @@ -70,9 +69,10 @@ env.CppUnitTest( 'lock_stats_test.cpp', ], LIBDEPS=[ + '$BUILD_DIR/mongo/db/auth/authmocks', '$BUILD_DIR/mongo/db/curop', + '$BUILD_DIR/mongo/db/service_context_d_test_fixture', '$BUILD_DIR/mongo/util/progress_meter', - '$BUILD_DIR/mongo/db/service_context_noop_init', 'lock_manager', 'write_conflict_exception', ] diff --git a/src/mongo/db/concurrency/d_concurrency_test.cpp b/src/mongo/db/concurrency/d_concurrency_test.cpp index 2be5c7c33d5..145f4f31846 100644 --- a/src/mongo/db/concurrency/d_concurrency_test.cpp +++ b/src/mongo/db/concurrency/d_concurrency_test.cpp @@ -37,6 +37,7 @@ #include "mongo/db/concurrency/global_lock_acquisition_tracker.h" #include "mongo/db/concurrency/lock_manager_test_help.h" #include "mongo/db/concurrency/write_conflict_exception.h" +#include "mongo/db/service_context_d_test_fixture.h" #include "mongo/db/storage/recovery_unit_noop.h" #include "mongo/stdx/functional.h" #include "mongo/stdx/future.h" @@ -77,19 +78,8 @@ private: }; -class DConcurrencyTestFixture : public unittest::Test { +class DConcurrencyTestFixture : public ServiceContextMongoDTest { public: - DConcurrencyTestFixture() : _client(getGlobalServiceContext()->makeClient("testClient")) {} - ~DConcurrencyTestFixture() {} - - /** - * Constructs and returns a new OperationContext. - */ - ServiceContext::UniqueOperationContext makeOpCtx() const { - auto opCtx = _client->makeOperationContext(); - return opCtx; - } - /** * Returns a vector of Clients of length 'k', each of which has an OperationContext with its * lockState set to a DefaultLockerImpl. @@ -101,8 +91,8 @@ public: clients; clients.reserve(k); for (int i = 0; i < k; ++i) { - auto client = getGlobalServiceContext()->makeClient( - str::stream() << "test client for thread " << i); + auto client = + getServiceContext()->makeClient(str::stream() << "test client for thread " << i); auto opCtx = client->makeOperationContext(); opCtx->swapLockState(stdx::make_unique<LockerType>()); clients.emplace_back(std::move(client), std::move(opCtx)); @@ -129,20 +119,17 @@ public: return result; } - -private: - ServiceContext::UniqueClient _client; }; TEST_F(DConcurrencyTestFixture, WriteConflictRetryInstantiatesOK) { - auto opCtx = makeOpCtx(); + auto opCtx = makeOperationContext(); opCtx->swapLockState(stdx::make_unique<MMAPV1LockerImpl>()); writeConflictRetry(opCtx.get(), "", "", [] {}); } TEST_F(DConcurrencyTestFixture, WriteConflictRetryRetriesFunctionOnWriteConflictException) { - auto opCtx = makeOpCtx(); + auto opCtx = makeOperationContext(); opCtx->swapLockState(stdx::make_unique<MMAPV1LockerImpl>()); auto&& opDebug = CurOp::get(opCtx.get())->debug(); ASSERT_EQUALS(0LL, opDebug.writeConflicts); @@ -156,7 +143,7 @@ TEST_F(DConcurrencyTestFixture, WriteConflictRetryRetriesFunctionOnWriteConflict } TEST_F(DConcurrencyTestFixture, WriteConflictRetryPropagatesNonWriteConflictException) { - auto opCtx = makeOpCtx(); + auto opCtx = makeOperationContext(); opCtx->swapLockState(stdx::make_unique<MMAPV1LockerImpl>()); ASSERT_THROWS_CODE(writeConflictRetry(opCtx.get(), "", @@ -171,7 +158,7 @@ TEST_F(DConcurrencyTestFixture, WriteConflictRetryPropagatesNonWriteConflictExce TEST_F(DConcurrencyTestFixture, WriteConflictRetryPropagatesWriteConflictExceptionIfAlreadyInAWriteUnitOfWork) { - auto opCtx = makeOpCtx(); + auto opCtx = makeOperationContext(); opCtx->swapLockState(stdx::make_unique<MMAPV1LockerImpl>()); Lock::GlobalWrite globalWrite(opCtx.get()); WriteUnitOfWork wuow(opCtx.get()); @@ -262,21 +249,21 @@ TEST_F(DConcurrencyTestFixture, ResourceMutex) { } TEST_F(DConcurrencyTestFixture, GlobalRead) { - auto opCtx = makeOpCtx(); + auto opCtx = makeOperationContext(); opCtx->swapLockState(stdx::make_unique<MMAPV1LockerImpl>()); Lock::GlobalRead globalRead(opCtx.get()); ASSERT(opCtx->lockState()->isR()); } TEST_F(DConcurrencyTestFixture, GlobalWrite) { - auto opCtx = makeOpCtx(); + auto opCtx = makeOperationContext(); opCtx->swapLockState(stdx::make_unique<MMAPV1LockerImpl>()); Lock::GlobalWrite globalWrite(opCtx.get()); ASSERT(opCtx->lockState()->isW()); } TEST_F(DConcurrencyTestFixture, GlobalWriteAndGlobalRead) { - auto opCtx = makeOpCtx(); + auto opCtx = makeOperationContext(); opCtx->swapLockState(stdx::make_unique<MMAPV1LockerImpl>()); auto lockState = opCtx->lockState(); @@ -293,7 +280,7 @@ TEST_F(DConcurrencyTestFixture, GlobalWriteAndGlobalRead) { TEST_F(DConcurrencyTestFixture, GlobalWriteRequiresExplicitDowngradeToIntentWriteModeIfDestroyedWhileHoldingDatabaseLock) { - auto opCtx = makeOpCtx(); + auto opCtx = makeOperationContext(); opCtx->swapLockState(stdx::make_unique<MMAPV1LockerImpl>()); auto lockState = opCtx->lockState(); @@ -341,7 +328,7 @@ TEST_F(DConcurrencyTestFixture, TEST_F(DConcurrencyTestFixture, GlobalWriteRequiresSupportsDowngradeToIntentWriteModeWhileHoldingDatabaseLock) { - auto opCtx = makeOpCtx(); + auto opCtx = makeOperationContext(); opCtx->swapLockState(stdx::make_unique<MMAPV1LockerImpl>()); auto lockState = opCtx->lockState(); @@ -388,7 +375,7 @@ TEST_F(DConcurrencyTestFixture, TEST_F(DConcurrencyTestFixture, NestedGlobalWriteSupportsDowngradeToIntentWriteModeWhileHoldingDatabaseLock) { - auto opCtx = makeOpCtx(); + auto opCtx = makeOperationContext(); opCtx->swapLockState(stdx::make_unique<MMAPV1LockerImpl>()); auto lockState = opCtx->lockState(); @@ -595,7 +582,7 @@ TEST_F(DConcurrencyTestFixture, GlobalLockX_TimeoutDueToGlobalLockX) { } TEST_F(DConcurrencyTestFixture, TempReleaseGlobalWrite) { - auto opCtx = makeOpCtx(); + auto opCtx = makeOperationContext(); opCtx->swapLockState(stdx::make_unique<MMAPV1LockerImpl>()); auto lockState = opCtx->lockState(); Lock::GlobalWrite globalWrite(opCtx.get()); @@ -609,7 +596,7 @@ TEST_F(DConcurrencyTestFixture, TempReleaseGlobalWrite) { } TEST_F(DConcurrencyTestFixture, TempReleaseRecursive) { - auto opCtx = makeOpCtx(); + auto opCtx = makeOperationContext(); opCtx->swapLockState(stdx::make_unique<MMAPV1LockerImpl>()); auto lockState = opCtx->lockState(); Lock::GlobalWrite globalWrite(opCtx.get()); @@ -825,7 +812,7 @@ TEST_F(DConcurrencyTestFixture, DBLockWaitIsNotInterruptibleWithLockGuard) { TEST_F(DConcurrencyTestFixture, DBLockTakesS) { - auto opCtx = makeOpCtx(); + auto opCtx = makeOperationContext(); opCtx->swapLockState(stdx::make_unique<MMAPV1LockerImpl>()); Lock::DBLock dbRead(opCtx.get(), "db", MODE_S); @@ -834,7 +821,7 @@ TEST_F(DConcurrencyTestFixture, DBLockTakesS) { } TEST_F(DConcurrencyTestFixture, DBLockTakesX) { - auto opCtx = makeOpCtx(); + auto opCtx = makeOperationContext(); opCtx->swapLockState(stdx::make_unique<MMAPV1LockerImpl>()); Lock::DBLock dbWrite(opCtx.get(), "db", MODE_X); @@ -843,7 +830,7 @@ TEST_F(DConcurrencyTestFixture, DBLockTakesX) { } TEST_F(DConcurrencyTestFixture, DBLockTakesISForAdminIS) { - auto opCtx = makeOpCtx(); + auto opCtx = makeOperationContext(); opCtx->swapLockState(stdx::make_unique<MMAPV1LockerImpl>()); Lock::DBLock dbRead(opCtx.get(), "admin", MODE_IS); @@ -851,7 +838,7 @@ TEST_F(DConcurrencyTestFixture, DBLockTakesISForAdminIS) { } TEST_F(DConcurrencyTestFixture, DBLockTakesSForAdminS) { - auto opCtx = makeOpCtx(); + auto opCtx = makeOperationContext(); opCtx->swapLockState(stdx::make_unique<MMAPV1LockerImpl>()); Lock::DBLock dbRead(opCtx.get(), "admin", MODE_S); @@ -859,7 +846,7 @@ TEST_F(DConcurrencyTestFixture, DBLockTakesSForAdminS) { } TEST_F(DConcurrencyTestFixture, DBLockTakesXForAdminIX) { - auto opCtx = makeOpCtx(); + auto opCtx = makeOperationContext(); opCtx->swapLockState(stdx::make_unique<MMAPV1LockerImpl>()); Lock::DBLock dbWrite(opCtx.get(), "admin", MODE_IX); @@ -867,7 +854,7 @@ TEST_F(DConcurrencyTestFixture, DBLockTakesXForAdminIX) { } TEST_F(DConcurrencyTestFixture, DBLockTakesXForAdminX) { - auto opCtx = makeOpCtx(); + auto opCtx = makeOperationContext(); opCtx->swapLockState(stdx::make_unique<MMAPV1LockerImpl>()); Lock::DBLock dbWrite(opCtx.get(), "admin", MODE_X); @@ -875,7 +862,7 @@ TEST_F(DConcurrencyTestFixture, DBLockTakesXForAdminX) { } TEST_F(DConcurrencyTestFixture, MultipleWriteDBLocksOnSameThread) { - auto opCtx = makeOpCtx(); + auto opCtx = makeOperationContext(); opCtx->swapLockState(stdx::make_unique<MMAPV1LockerImpl>()); Lock::DBLock r1(opCtx.get(), "db1", MODE_X); Lock::DBLock r2(opCtx.get(), "db1", MODE_X); @@ -884,7 +871,7 @@ TEST_F(DConcurrencyTestFixture, MultipleWriteDBLocksOnSameThread) { } TEST_F(DConcurrencyTestFixture, MultipleConflictingDBLocksOnSameThread) { - auto opCtx = makeOpCtx(); + auto opCtx = makeOperationContext(); opCtx->swapLockState(stdx::make_unique<MMAPV1LockerImpl>()); auto lockState = opCtx->lockState(); Lock::DBLock r1(opCtx.get(), "db1", MODE_X); @@ -897,7 +884,7 @@ TEST_F(DConcurrencyTestFixture, MultipleConflictingDBLocksOnSameThread) { TEST_F(DConcurrencyTestFixture, IsDbLockedForSMode) { const std::string dbName("db"); - auto opCtx = makeOpCtx(); + auto opCtx = makeOperationContext(); opCtx->swapLockState(stdx::make_unique<MMAPV1LockerImpl>()); auto lockState = opCtx->lockState(); Lock::DBLock dbLock(opCtx.get(), dbName, MODE_S); @@ -911,7 +898,7 @@ TEST_F(DConcurrencyTestFixture, IsDbLockedForSMode) { TEST_F(DConcurrencyTestFixture, IsDbLockedForXMode) { const std::string dbName("db"); - auto opCtx = makeOpCtx(); + auto opCtx = makeOperationContext(); opCtx->swapLockState(stdx::make_unique<MMAPV1LockerImpl>()); auto lockState = opCtx->lockState(); Lock::DBLock dbLock(opCtx.get(), dbName, MODE_X); @@ -925,7 +912,7 @@ TEST_F(DConcurrencyTestFixture, IsDbLockedForXMode) { TEST_F(DConcurrencyTestFixture, IsCollectionLocked_DB_Locked_IS) { const std::string ns("db1.coll"); - auto opCtx = makeOpCtx(); + auto opCtx = makeOperationContext(); opCtx->swapLockState(stdx::make_unique<MMAPV1LockerImpl>()); auto lockState = opCtx->lockState(); @@ -956,7 +943,7 @@ TEST_F(DConcurrencyTestFixture, IsCollectionLocked_DB_Locked_IS) { TEST_F(DConcurrencyTestFixture, IsCollectionLocked_DB_Locked_IX) { const std::string ns("db1.coll"); - auto opCtx = makeOpCtx(); + auto opCtx = makeOperationContext(); opCtx->swapLockState(stdx::make_unique<MMAPV1LockerImpl>()); auto lockState = opCtx->lockState(); diff --git a/src/mongo/db/db.cpp b/src/mongo/db/db.cpp index ea2fd75bb51..996a0123864 100644 --- a/src/mongo/db/db.cpp +++ b/src/mongo/db/db.cpp @@ -120,8 +120,6 @@ #include "mongo/db/server_options.h" #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" @@ -323,8 +321,6 @@ ExitCode _initAndListen(int listenPort) { logProcessDetails(); - createLockFile(serviceContext); - serviceContext->setServiceEntryPoint( stdx::make_unique<ServiceEntryPointMongod>(serviceContext)); @@ -990,6 +986,8 @@ int mongoDbMain(int argc, char* argv[], char** envp) { severe(LogComponent::kControl) << "Failed global initialization: " << status; quickExit(EXIT_FAILURE); } + auto service = getGlobalServiceContext(); + service->setServiceEntryPoint(std::make_unique<ServiceEntryPointMongod>(service)); ErrorExtraInfo::invariantHaveAllParsers(); diff --git a/src/mongo/db/exec/SConscript b/src/mongo/db/exec/SConscript index 70d48105e2c..ba19b626965 100644 --- a/src/mongo/db/exec/SConscript +++ b/src/mongo/db/exec/SConscript @@ -60,7 +60,7 @@ env.CppUnitTest( "$BUILD_DIR/mongo/db/auth/authmocks", "$BUILD_DIR/mongo/db/query_exec", "$BUILD_DIR/mongo/db/serveronly", - "$BUILD_DIR/mongo/db/service_context_d", + "$BUILD_DIR/mongo/db/service_context_d_test_fixture", "$BUILD_DIR/mongo/dbtests/mocklib", "$BUILD_DIR/mongo/util/clock_source_mock", ], @@ -75,7 +75,7 @@ env.CppUnitTest( "$BUILD_DIR/mongo/db/auth/authmocks", "$BUILD_DIR/mongo/db/query_exec", "$BUILD_DIR/mongo/db/serveronly", - "$BUILD_DIR/mongo/db/service_context_d", + "$BUILD_DIR/mongo/db/service_context_d_test_fixture", "$BUILD_DIR/mongo/dbtests/mocklib", "$BUILD_DIR/mongo/db/query/collation/collator_factory_mock", "$BUILD_DIR/mongo/db/query/collation/collator_interface_mock", diff --git a/src/mongo/db/exec/queued_data_stage_test.cpp b/src/mongo/db/exec/queued_data_stage_test.cpp index 960d832777a..de09994b2a0 100644 --- a/src/mongo/db/exec/queued_data_stage_test.cpp +++ b/src/mongo/db/exec/queued_data_stage_test.cpp @@ -35,9 +35,8 @@ #include <boost/optional.hpp> #include "mongo/db/exec/working_set.h" -#include "mongo/db/operation_context_noop.h" -#include "mongo/db/service_context.h" -#include "mongo/db/service_context_noop.h" +#include "mongo/db/operation_context.h" +#include "mongo/db/service_context_d_test_fixture.h" #include "mongo/stdx/memory.h" #include "mongo/unittest/unittest.h" #include "mongo/util/clock_source_mock.h" @@ -49,30 +48,20 @@ namespace { using std::unique_ptr; using stdx::make_unique; -class QueuedDataStageTest : public unittest::Test { +class QueuedDataStageTest : public ServiceContextMongoDTest { public: QueuedDataStageTest() { - _service = stdx::make_unique<ServiceContextNoop>(); - _service->setFastClockSource(stdx::make_unique<ClockSourceMock>()); - _client = _service->makeClient("test"); - _opCtxNoop = _client->makeOperationContext(); - _opCtx = _opCtxNoop.get(); + getServiceContext()->setFastClockSource(stdx::make_unique<ClockSourceMock>()); + _opCtx = makeOperationContext(); } protected: OperationContext* getOpCtx() { - return _opCtx; + return _opCtx.get(); } private: - OperationContext* _opCtx; - - // Members of a class are destroyed in reverse order of declaration. - // The UniqueClient must be destroyed before the ServiceContextNoop is destroyed. - // The OperationContextNoop must be destroyed before the UniqueClient is destroyed. - std::unique_ptr<ServiceContextNoop> _service; - ServiceContext::UniqueClient _client; - ServiceContext::UniqueOperationContext _opCtxNoop; + ServiceContext::UniqueOperationContext _opCtx; }; // diff --git a/src/mongo/db/exec/sort_test.cpp b/src/mongo/db/exec/sort_test.cpp index 08f3f15580e..b45626b0999 100644 --- a/src/mongo/db/exec/sort_test.cpp +++ b/src/mongo/db/exec/sort_test.cpp @@ -36,11 +36,10 @@ #include "mongo/db/exec/queued_data_stage.h" #include "mongo/db/json.h" -#include "mongo/db/operation_context_noop.h" +#include "mongo/db/operation_context.h" #include "mongo/db/query/collation/collator_factory_mock.h" #include "mongo/db/query/collation/collator_interface_mock.h" -#include "mongo/db/service_context.h" -#include "mongo/db/service_context_noop.h" +#include "mongo/db/service_context_d_test_fixture.h" #include "mongo/stdx/memory.h" #include "mongo/unittest/unittest.h" #include "mongo/util/clock_source_mock.h" @@ -49,19 +48,17 @@ using namespace mongo; namespace { -class SortStageTest : public unittest::Test { +class SortStageTest : public ServiceContextMongoDTest { public: SortStageTest() { - _service = stdx::make_unique<ServiceContextNoop>(); - _service->setFastClockSource(stdx::make_unique<ClockSourceMock>()); - _client = _service->makeClient("test"); - _opCtxNoop = _client->makeOperationContext(); - _opCtx = _opCtxNoop.get(); - CollatorFactoryInterface::set(_service.get(), stdx::make_unique<CollatorFactoryMock>()); + getServiceContext()->setFastClockSource(stdx::make_unique<ClockSourceMock>()); + _opCtx = makeOperationContext(); + CollatorFactoryInterface::set(getServiceContext(), + stdx::make_unique<CollatorFactoryMock>()); } OperationContext* getOpCtx() { - return _opCtx; + return _opCtx.get(); } /** @@ -155,15 +152,7 @@ public: } private: - OperationContext* _opCtx; - - std::unique_ptr<ServiceContextNoop> _service; - - // Members of a class are destroyed in reverse order of declaration. - // The UniqueClient must be destroyed before the ServiceContextNoop is destroyed. - // The OperationContextNoop must be destroyed before the UniqueClient is destroyed. - ServiceContext::UniqueClient _client; - ServiceContext::UniqueOperationContext _opCtxNoop; + ServiceContext::UniqueOperationContext _opCtx; }; TEST_F(SortStageTest, SortEmptyWorkingSet) { diff --git a/src/mongo/db/free_mon/free_mon_controller_test.cpp b/src/mongo/db/free_mon/free_mon_controller_test.cpp index 29bf8ec9acd..76ba859fdee 100644 --- a/src/mongo/db/free_mon/free_mon_controller_test.cpp +++ b/src/mongo/db/free_mon/free_mon_controller_test.cpp @@ -59,7 +59,6 @@ #include "mongo/db/repl/storage_interface_impl.h" #include "mongo/db/service_context.h" #include "mongo/db/service_context_d_test_fixture.h" -#include "mongo/db/service_context_noop.h" #include "mongo/executor/network_interface_mock.h" #include "mongo/executor/thread_pool_task_executor_test_fixture.h" #include "mongo/rpc/object_check.h" diff --git a/src/mongo/db/ftdc/SConscript b/src/mongo/db/ftdc/SConscript index 4822907a540..6415ae347dd 100644 --- a/src/mongo/db/ftdc/SConscript +++ b/src/mongo/db/ftdc/SConscript @@ -96,6 +96,7 @@ env.CppUnitTest( 'varint_test.cpp', ], LIBDEPS=[ + '$BUILD_DIR/mongo/db/service_context_test_fixture', '$BUILD_DIR/mongo/util/clock_source_mock', 'ftdc', ], diff --git a/src/mongo/db/ftdc/compressor_test.cpp b/src/mongo/db/ftdc/compressor_test.cpp index 0c01bd58040..38ae3958a7b 100644 --- a/src/mongo/db/ftdc/compressor_test.cpp +++ b/src/mongo/db/ftdc/compressor_test.cpp @@ -60,8 +60,10 @@ namespace mongo { FTDCCompressor::CompressorState::kCompressorFull); \ ASSERT_TRUE(st.getValue().is_initialized()); +class FTDCCompressorTest : public FTDCTest {}; + // Sanity check -TEST(FTDCCompressor, TestBasic) { +TEST_F(FTDCCompressorTest, TestBasic) { FTDCConfig config; FTDCCompressor c(&config); @@ -91,7 +93,7 @@ TEST(FTDCCompressor, TestBasic) { } // Test strings only -TEST(FTDCCompressor, TestStrings) { +TEST_F(FTDCCompressorTest, TestStrings) { FTDCConfig config; FTDCCompressor c(&config); @@ -180,7 +182,7 @@ private: }; // Test various schema changes -TEST(FTDCCompressor, TestSchemaChanges) { +TEST_F(FTDCCompressorTest, TestSchemaChanges) { TestTie c; auto st = c.addSample(BSON("name" @@ -341,7 +343,7 @@ TEST(FTDCCompressor, TestSchemaChanges) { } // Ensure changing between the various number formats is considered compatible -TEST(FTDCCompressor, TestNumbersCompat) { +TEST_F(FTDCCompressorTest, TestNumbersCompat) { TestTie c; auto st = c.addSample(BSON("name" @@ -368,7 +370,7 @@ TEST(FTDCCompressor, TestNumbersCompat) { } // Test various date time types -TEST(FTDCCompressor, TestDateTimeTypes) { +TEST_F(FTDCCompressorTest, TestDateTimeTypes) { TestTie c; for (int i = 0; i < 10; i++) { BSONObjBuilder builder1; @@ -382,7 +384,7 @@ TEST(FTDCCompressor, TestDateTimeTypes) { } // Test all types -TEST(FTDCCompressor, Types) { +TEST_F(FTDCCompressorTest, Types) { TestTie c; auto st = c.addSample(BSON("name" @@ -455,7 +457,7 @@ TEST(FTDCCompressor, Types) { } // Test a full buffer -TEST(FTDCCompressor, TestFull) { +TEST_F(FTDCCompressorTest, TestFull) { // Test a large numbers of zeros, and incremental numbers in a full buffer for (int j = 0; j < 2; j++) { TestTie c; @@ -509,7 +511,7 @@ BSONObj generateSample(std::random_device& rd, T generator, size_t count) { } // Test many metrics -TEST(ZFTDCCompressor, TestManyMetrics) { +TEST_F(FTDCCompressorTest, TestManyMetrics) { std::random_device rd; std::mt19937 gen(rd()); diff --git a/src/mongo/db/ftdc/controller_test.cpp b/src/mongo/db/ftdc/controller_test.cpp index c307d02cca8..de88054aec9 100644 --- a/src/mongo/db/ftdc/controller_test.cpp +++ b/src/mongo/db/ftdc/controller_test.cpp @@ -50,6 +50,8 @@ namespace mongo { +class FTDCControllerTest : public FTDCTest {}; + class FTDCMetricsCollectorMockTee : public FTDCCollectorInterface { public: ~FTDCMetricsCollectorMockTee() { @@ -154,7 +156,7 @@ public: }; // Test a run of the controller and the data it logs to log file -TEST(FTDCControllerTest, TestFull) { +TEST_F(FTDCControllerTest, TestFull) { unittest::TempDir tempdir("metrics_testpath"); boost::filesystem::path dir(tempdir.path()); @@ -207,7 +209,7 @@ TEST(FTDCControllerTest, TestFull) { // Test we can start and stop the controller in quick succession, make sure it succeeds without // assert or fault -TEST(FTDCControllerTest, TestStartStop) { +TEST_F(FTDCControllerTest, TestStartStop) { unittest::TempDir tempdir("metrics_testpath"); boost::filesystem::path dir(tempdir.path()); @@ -228,7 +230,7 @@ TEST(FTDCControllerTest, TestStartStop) { // Test we can start the controller as disabled, the directory is empty, and then we can succesfully // enable it -TEST(FTDCControllerTest, TestStartAsDisabled) { +TEST_F(FTDCControllerTest, TestStartAsDisabled) { unittest::TempDir tempdir("metrics_testpath"); boost::filesystem::path dir(tempdir.path()); diff --git a/src/mongo/db/ftdc/file_manager_test.cpp b/src/mongo/db/ftdc/file_manager_test.cpp index 027ae88af62..0a0b0367221 100644 --- a/src/mongo/db/ftdc/file_manager_test.cpp +++ b/src/mongo/db/ftdc/file_manager_test.cpp @@ -50,8 +50,10 @@ namespace mongo { +class FTDCFileManagerTest : public ServiceContextTest {}; + // Test a full buffer -TEST(FTDCFileManagerTest, TestFull) { +TEST_F(FTDCFileManagerTest, TestFull) { Client* client = &cc(); FTDCConfig c; c.maxFileSizeBytes = 300; @@ -149,7 +151,7 @@ void ValidateInterimFileHasData(const boost::filesystem::path& dir, bool hasData } // Test a normal restart -TEST(FTDCFileManagerTest, TestNormalRestart) { +TEST_F(FTDCFileManagerTest, TestNormalRestart) { Client* client = &cc(); FTDCConfig c; c.maxFileSizeBytes = 1000; @@ -219,7 +221,7 @@ TEST(FTDCFileManagerTest, TestNormalRestart) { } // Test a restart after a crash with a corrupt archive file -TEST(FTDCFileManagerTest, TestCorruptCrashRestart) { +TEST_F(FTDCFileManagerTest, TestCorruptCrashRestart) { Client* client = &cc(); FTDCConfig c; c.maxFileSizeBytes = 1000; @@ -296,7 +298,7 @@ TEST(FTDCFileManagerTest, TestCorruptCrashRestart) { } // Test a restart with a good interim file, and validate we have all the data -TEST(FTDCFileManagerTest, TestNormalCrashInterim) { +TEST_F(FTDCFileManagerTest, TestNormalCrashInterim) { Client* client = &cc(); FTDCConfig c; c.maxSamplesPerInterimMetricChunk = 3; diff --git a/src/mongo/db/ftdc/file_writer_test.cpp b/src/mongo/db/ftdc/file_writer_test.cpp index f7977e2b8b3..81e3a741d24 100644 --- a/src/mongo/db/ftdc/file_writer_test.cpp +++ b/src/mongo/db/ftdc/file_writer_test.cpp @@ -47,8 +47,10 @@ namespace mongo { const char* kTestFile = "metrics.test"; const char* kTestFileCopy = "metrics.test.copy"; +class FTDCFileTest : public ServiceContextTest {}; + // File Sanity check -TEST(FTDCFileTest, TestFileBasicMetadata) { +TEST_F(FTDCFileTest, TestFileBasicMetadata) { unittest::TempDir tempdir("metrics_testpath"); boost::filesystem::path p(tempdir.path()); p /= kTestFile; @@ -99,7 +101,7 @@ TEST(FTDCFileTest, TestFileBasicMetadata) { } // File Sanity check -TEST(FTDCFileTest, TestFileBasicCompress) { +TEST_F(FTDCFileTest, TestFileBasicCompress) { unittest::TempDir tempdir("metrics_testpath"); boost::filesystem::path p(tempdir.path()); p /= kTestFile; @@ -208,7 +210,7 @@ private: }; // Test various schema changes -TEST(FTDCFileTest, TestSchemaChanges) { +TEST_F(FTDCFileTest, TestSchemaChanges) { FileTestTie c; c.addSample(BSON("name" @@ -279,7 +281,7 @@ TEST(FTDCFileTest, TestSchemaChanges) { } // Test a full buffer -TEST(FTDCFileTest, TestFull) { +TEST_F(FTDCFileTest, TestFull) { // Test a large numbers of zeros, and incremental numbers in a full buffer for (int j = 0; j < 2; j++) { FileTestTie c; @@ -318,7 +320,7 @@ TEST(FTDCFileTest, TestFull) { } // Test a large documents so that we cause multiple 4kb buffers to flush on Windows. -TEST(FTDCFileTest, TestLargeDocuments) { +TEST_F(FTDCFileTest, TestLargeDocuments) { FileTestTie c; for (int j = 0; j < 5; j++) { @@ -337,7 +339,7 @@ TEST(FTDCFileTest, TestLargeDocuments) { } // Test a bad file -TEST(FTDCFileTest, TestBadFile) { +TEST_F(FTDCFileTest, TestBadFile) { unittest::TempDir tempdir("metrics_testpath"); boost::filesystem::path p(tempdir.path()); p /= kTestFile; diff --git a/src/mongo/db/ftdc/ftdc_test.cpp b/src/mongo/db/ftdc/ftdc_test.cpp index 7e4020b3979..11674ea2cad 100644 --- a/src/mongo/db/ftdc/ftdc_test.cpp +++ b/src/mongo/db/ftdc/ftdc_test.cpp @@ -39,7 +39,6 @@ #include "mongo/db/ftdc/file_reader.h" #include "mongo/db/jsobj.h" #include "mongo/db/service_context.h" -#include "mongo/db/service_context_noop.h" #include "mongo/stdx/memory.h" #include "mongo/unittest/unittest.h" #include "mongo/util/clock_source.h" @@ -111,17 +110,11 @@ void createDirectoryClean(const boost::filesystem::path& dir) { boost::filesystem::create_directory(dir); } -MONGO_INITIALIZER_WITH_PREREQUISITES(FTDCTestInit, ("ThreadNameInitializer")) -(InitializerContext* context) { - setGlobalServiceContext(stdx::make_unique<ServiceContextNoop>()); - - getGlobalServiceContext()->setFastClockSource(stdx::make_unique<ClockSourceMock>()); - getGlobalServiceContext()->setPreciseClockSource(stdx::make_unique<ClockSourceMock>()); - getGlobalServiceContext()->setTickSource(stdx::make_unique<TickSourceMock>()); - - Client::initThreadIfNotAlready("UnitTest"); - - return Status::OK(); +FTDCTest::FTDCTest() { + auto service = getServiceContext(); + service->setFastClockSource(stdx::make_unique<ClockSourceMock>()); + service->setPreciseClockSource(stdx::make_unique<ClockSourceMock>()); + service->setTickSource(stdx::make_unique<TickSourceMock>()); } } // namespace mongo diff --git a/src/mongo/db/ftdc/ftdc_test.h b/src/mongo/db/ftdc/ftdc_test.h index afbca103b4f..fb9ada44f2f 100644 --- a/src/mongo/db/ftdc/ftdc_test.h +++ b/src/mongo/db/ftdc/ftdc_test.h @@ -30,9 +30,15 @@ #include <vector> #include "mongo/db/jsobj.h" +#include "mongo/db/service_context_test_fixture.h" namespace mongo { +class FTDCTest : public ServiceContextTest { +public: + FTDCTest(); +}; + /** * Validate the documents in a file match the specified vector. * diff --git a/src/mongo/db/logical_session_cache_test.cpp b/src/mongo/db/logical_session_cache_test.cpp index 98d3df0d000..37256c26670 100644 --- a/src/mongo/db/logical_session_cache_test.cpp +++ b/src/mongo/db/logical_session_cache_test.cpp @@ -39,8 +39,9 @@ #include "mongo/db/logical_session_cache.h" #include "mongo/db/logical_session_id.h" #include "mongo/db/logical_session_id_helpers.h" -#include "mongo/db/operation_context_noop.h" -#include "mongo/db/service_context_noop.h" +#include "mongo/db/operation_context.h" +#include "mongo/db/service_context.h" +#include "mongo/db/service_context_test_fixture.h" #include "mongo/db/service_liaison_mock.h" #include "mongo/db/sessions_collection_mock.h" #include "mongo/stdx/future.h" @@ -62,35 +63,25 @@ using unittest::EnsureFCV; * Test fixture that sets up a session cache attached to a mock service liaison * and mock sessions collection implementation. */ -class LogicalSessionCacheTest : public unittest::Test { +class LogicalSessionCacheTest : public ServiceContextTest { public: LogicalSessionCacheTest() : _service(std::make_shared<MockServiceLiaisonImpl>()), - _sessions(std::make_shared<MockSessionsCollectionImpl>()) {} + _sessions(std::make_shared<MockSessionsCollectionImpl>()) { - void setUp() override { - AuthorizationManager::set(&serviceContext, AuthorizationManager::create()); - - auto client = serviceContext.makeClient("testClient"); - _opCtx = client->makeOperationContext(); - _client = client.get(); - Client::setCurrent(std::move(client)); + AuthorizationManager::set(getServiceContext(), AuthorizationManager::create()); + // Re-initialize the client after setting the AuthorizationManager to get an + // AuthorizationSession. + Client::releaseCurrent(); + Client::initThread(getThreadName()); + _opCtx = makeOperationContext(); auto mockService = stdx::make_unique<MockServiceLiaison>(_service); auto mockSessions = stdx::make_unique<MockSessionsCollection>(_sessions); _cache = stdx::make_unique<LogicalSessionCacheImpl>( std::move(mockService), std::move(mockSessions), nullptr); } - void tearDown() override { - if (_opCtx) { - _opCtx.reset(); - } - - _service->join(); - auto client = Client::releaseCurrent(); - } - void waitUntilRefreshScheduled() { while (service()->jobs() < 2) { sleepmillis(10); @@ -110,7 +101,7 @@ public: } void setOpCtx() { - _opCtx = client()->makeOperationContext(); + _opCtx = getClient()->makeOperationContext(); } void clearOpCtx() { @@ -121,20 +112,13 @@ public: return _opCtx.get(); } - Client* client() { - return _client; - } - private: - ServiceContextNoop serviceContext; ServiceContext::UniqueOperationContext _opCtx; std::shared_ptr<MockServiceLiaisonImpl> _service; std::shared_ptr<MockSessionsCollectionImpl> _sessions; std::unique_ptr<LogicalSessionCache> _cache; - - Client* _client; }; // Test that the getFromCache method does not make calls to the sessions collection @@ -205,7 +189,7 @@ TEST_F(LogicalSessionCacheTest, StartSession) { // Do refresh, cached records should get flushed to collection. clearOpCtx(); - ASSERT(cache()->refreshNow(client()).isOK()); + ASSERT(cache()->refreshNow(getClient()).isOK()); ASSERT(sessions()->has(lsid)); // Try to start the same session again, should succeed. @@ -237,7 +221,7 @@ TEST_F(LogicalSessionCacheTest, BasicSessionExpiration) { service()->fastForward(Milliseconds(kSessionTimeout.count() + 5)); // Check that it is no longer in the cache - ASSERT(cache()->refreshNow(client()).isOK()); + ASSERT(cache()->refreshNow(getClient()).isOK()); res = cache()->promote(record.getId()); // TODO SERVER-29709 // ASSERT(!res.isOK()); @@ -260,7 +244,7 @@ TEST_F(LogicalSessionCacheTest, ManySignedLsidsInCacheRefresh) { // Force a refresh clearOpCtx(); service()->fastForward(kForceRefresh); - ASSERT(cache()->refreshNow(client()).isOK()); + ASSERT(cache()->refreshNow(getClient()).isOK()); } // @@ -378,7 +362,7 @@ TEST_F(LogicalSessionCacheTest, RefreshMatrixSessionState) { // Force a refresh clearOpCtx(); service()->fastForward(kForceRefresh); - ASSERT(cache()->refreshNow(client()).isOK()); + ASSERT(cache()->refreshNow(getClient()).isOK()); for (int i = 0; i < 32; i++) { std::stringstream failText; diff --git a/src/mongo/db/logical_session_id_test.cpp b/src/mongo/db/logical_session_id_test.cpp index 96f2dd2ac51..7a314bd61b0 100644 --- a/src/mongo/db/logical_session_id_test.cpp +++ b/src/mongo/db/logical_session_id_test.cpp @@ -40,7 +40,6 @@ #include "mongo/db/auth/authorization_manager.h" #include "mongo/db/auth/authorization_manager_impl.h" #include "mongo/db/auth/authorization_session.h" -#include "mongo/db/auth/authorization_session_for_test.h" #include "mongo/db/auth/authz_manager_external_state_mock.h" #include "mongo/db/auth/authz_session_external_state_mock.h" #include "mongo/db/auth/sasl_options.h" @@ -50,8 +49,9 @@ #include "mongo/db/logical_session_cache.h" #include "mongo/db/logical_session_cache_impl.h" #include "mongo/db/logical_session_id_helpers.h" -#include "mongo/db/operation_context_noop.h" -#include "mongo/db/service_context_noop.h" +#include "mongo/db/operation_context.h" +#include "mongo/db/service_context.h" +#include "mongo/db/service_context_test_fixture.h" #include "mongo/db/service_liaison_mock.h" #include "mongo/db/sessions_collection_mock.h" #include "mongo/transport/session.h" @@ -61,42 +61,29 @@ namespace mongo { namespace { -class LogicalSessionIdTest : public ::mongo::unittest::Test { +class LogicalSessionIdTest : public ServiceContextTest { public: AuthzManagerExternalStateMock* managerState; transport::TransportLayerMock transportLayer; - transport::SessionHandle session; - ServiceContextNoop serviceContext; - ServiceContext::UniqueClient client; + transport::SessionHandle session = transportLayer.createSession(); ServiceContext::UniqueOperationContext _opCtx; - AuthzSessionExternalStateMock* sessionState; - AuthorizationManager* authzManager; - AuthorizationSessionForTest* authzSession; + AuthorizationSession* authzSession; - void setUp() { - session = transportLayer.createSession(); - client = serviceContext.makeClient("testClient", session); + LogicalSessionIdTest() { RestrictionEnvironment::set( session, std::make_unique<RestrictionEnvironment>(SockAddr(), SockAddr())); - _opCtx = client->makeOperationContext(); auto localManagerState = std::make_unique<AuthzManagerExternalStateMock>(); managerState = localManagerState.get(); managerState->setAuthzVersion(AuthorizationManager::schemaVersion26Final); - auto uniqueAuthzManager = std::make_unique<AuthorizationManagerImpl>( + auto authzManager = std::make_unique<AuthorizationManagerImpl>( std::move(localManagerState), AuthorizationManagerImpl::InstallMockForTestingOrAuthImpl{}); - authzManager = uniqueAuthzManager.get(); - AuthorizationManager::set(&serviceContext, std::move(uniqueAuthzManager)); - auto localSessionState = std::make_unique<AuthzSessionExternalStateMock>(authzManager); - sessionState = localSessionState.get(); - - auto localauthzSession = std::make_unique<AuthorizationSessionForTest>( - std::move(localSessionState), - AuthorizationSessionImpl::InstallMockForTestingOrAuthImpl{}); - authzSession = localauthzSession.get(); - - AuthorizationSession::set(client.get(), std::move(localauthzSession)); authzManager->setAuthEnabled(true); + AuthorizationManager::set(getServiceContext(), std::move(authzManager)); + Client::releaseCurrent(); + Client::initThread(getThreadName(), session); + authzSession = AuthorizationSession::get(getClient()); + _opCtx = makeOperationContext(); auto localServiceLiaison = std::make_unique<MockServiceLiaison>(std::make_shared<MockServiceLiaisonImpl>()); @@ -106,7 +93,7 @@ public: auto localLogicalSessionCache = std::make_unique<LogicalSessionCacheImpl>( std::move(localServiceLiaison), std::move(localSessionsCollection), nullptr); - LogicalSessionCache::set(&serviceContext, std::move(localLogicalSessionCache)); + LogicalSessionCache::set(getServiceContext(), std::move(localLogicalSessionCache)); } User* addSimpleUser(UserName un) { diff --git a/src/mongo/db/operation_context_test.cpp b/src/mongo/db/operation_context_test.cpp index 751aee986cc..4660afedd21 100644 --- a/src/mongo/db/operation_context_test.cpp +++ b/src/mongo/db/operation_context_test.cpp @@ -36,7 +36,6 @@ #include "mongo/db/operation_context.h" #include "mongo/db/operation_context_group.h" #include "mongo/db/service_context.h" -#include "mongo/db/service_context_noop.h" #include "mongo/stdx/future.h" #include "mongo/stdx/memory.h" #include "mongo/stdx/thread.h" @@ -77,7 +76,7 @@ std::ostream& operator<<(std::ostream& os, stdx::future_status futureStatus) { } TEST(OperationContextTest, NoSessionIdNoTransactionNumber) { - auto serviceCtx = stdx::make_unique<ServiceContextNoop>(); + auto serviceCtx = ServiceContext::make(); auto client = serviceCtx->makeClient("OperationContextTest"); auto opCtx = client->makeOperationContext(); @@ -86,7 +85,7 @@ TEST(OperationContextTest, NoSessionIdNoTransactionNumber) { } TEST(OperationContextTest, SessionIdNoTransactionNumber) { - auto serviceCtx = stdx::make_unique<ServiceContextNoop>(); + auto serviceCtx = ServiceContext::make(); auto client = serviceCtx->makeClient("OperationContextTest"); auto opCtx = client->makeOperationContext(); @@ -100,7 +99,7 @@ TEST(OperationContextTest, SessionIdNoTransactionNumber) { } TEST(OperationContextTest, SessionIdAndTransactionNumber) { - auto serviceCtx = stdx::make_unique<ServiceContextNoop>(); + auto serviceCtx = ServiceContext::make(); auto client = serviceCtx->makeClient("OperationContextTest"); auto opCtx = client->makeOperationContext(); @@ -113,7 +112,7 @@ TEST(OperationContextTest, SessionIdAndTransactionNumber) { } DEATH_TEST(OperationContextTest, SettingSessionIdMoreThanOnceShouldCrash, "invariant") { - auto serviceCtx = stdx::make_unique<ServiceContextNoop>(); + auto serviceCtx = ServiceContext::make(); auto client = serviceCtx->makeClient("OperationContextTest"); auto opCtx = client->makeOperationContext(); @@ -122,7 +121,7 @@ DEATH_TEST(OperationContextTest, SettingSessionIdMoreThanOnceShouldCrash, "invar } DEATH_TEST(OperationContextTest, SettingTransactionNumberMoreThanOnceShouldCrash, "invariant") { - auto serviceCtx = stdx::make_unique<ServiceContextNoop>(); + auto serviceCtx = ServiceContext::make(); auto client = serviceCtx->makeClient("OperationContextTest"); auto opCtx = client->makeOperationContext(); @@ -133,7 +132,7 @@ DEATH_TEST(OperationContextTest, SettingTransactionNumberMoreThanOnceShouldCrash } DEATH_TEST(OperationContextTest, SettingTransactionNumberWithoutSessionIdShouldCrash, "invariant") { - auto serviceCtx = stdx::make_unique<ServiceContextNoop>(); + auto serviceCtx = ServiceContext::make(); auto client = serviceCtx->makeClient("OperationContextTest"); auto opCtx = client->makeOperationContext(); @@ -144,12 +143,12 @@ TEST(OperationContextTest, OpCtxGroup) { OperationContextGroup group1; ASSERT_TRUE(group1.isEmpty()); { - auto serviceCtx1 = stdx::make_unique<ServiceContextNoop>(); + auto serviceCtx1 = ServiceContext::make(); auto client1 = serviceCtx1->makeClient("OperationContextTest1"); auto opCtx1 = group1.makeOperationContext(*client1); ASSERT_FALSE(group1.isEmpty()); - auto serviceCtx2 = stdx::make_unique<ServiceContextNoop>(); + auto serviceCtx2 = ServiceContext::make(); auto client2 = serviceCtx2->makeClient("OperationContextTest2"); { auto opCtx2 = group1.makeOperationContext(*client2); @@ -170,7 +169,7 @@ TEST(OperationContextTest, OpCtxGroup) { OperationContextGroup group2; { - auto serviceCtx = stdx::make_unique<ServiceContextNoop>(); + auto serviceCtx = ServiceContext::make(); auto client = serviceCtx->makeClient("OperationContextTest1"); auto opCtx2 = group2.adopt(client->makeOperationContext()); ASSERT_FALSE(group2.isEmpty()); @@ -185,7 +184,7 @@ TEST(OperationContextTest, OpCtxGroup) { OperationContextGroup group3; OperationContextGroup group4; { - auto serviceCtx = stdx::make_unique<ServiceContextNoop>(); + auto serviceCtx = ServiceContext::make(); auto client3 = serviceCtx->makeClient("OperationContextTest3"); auto opCtx3 = group3.makeOperationContext(*client3); auto p3 = opCtx3.opCtx(); @@ -204,7 +203,7 @@ TEST(OperationContextTest, OpCtxGroup) { class OperationDeadlineTests : public unittest::Test { public: void setUp() { - service = stdx::make_unique<ServiceContextNoop>(); + service = ServiceContext::make(); service->setFastClockSource(stdx::make_unique<SharedClockSourceAdapter>(mockClock)); service->setPreciseClockSource(stdx::make_unique<SharedClockSourceAdapter>(mockClock)); service->setTickSource(stdx::make_unique<TickSourceMock>()); @@ -212,7 +211,7 @@ public: } const std::shared_ptr<ClockSourceMock> mockClock = std::make_shared<ClockSourceMock>(); - std::unique_ptr<ServiceContext> service; + ServiceContext::UniqueServiceContext service; ServiceContext::UniqueClient client; }; diff --git a/src/mongo/db/ops/SConscript b/src/mongo/db/ops/SConscript index 50a443d74f5..c272c6d3a2a 100644 --- a/src/mongo/db/ops/SConscript +++ b/src/mongo/db/ops/SConscript @@ -60,6 +60,7 @@ env.CppIntegrationTest( source='write_ops_document_stream_integration_test.cpp', LIBDEPS=[ '$BUILD_DIR/mongo/client/clientdriver_network', + '$BUILD_DIR/mongo/transport/transport_layer_egress_init', '$BUILD_DIR/mongo/util/version_impl', ], ) diff --git a/src/mongo/db/pipeline/SConscript b/src/mongo/db/pipeline/SConscript index 3d73e724af4..120996f96ff 100644 --- a/src/mongo/db/pipeline/SConscript +++ b/src/mongo/db/pipeline/SConscript @@ -73,7 +73,6 @@ env.CppUnitTest( ], LIBDEPS=[ '$BUILD_DIR/mongo/db/query/collation/collator_interface_mock', - '$BUILD_DIR/mongo/db/service_context_noop_init', 'document_value', 'document_value_test_util', ], @@ -242,7 +241,7 @@ env.CppUnitTest( source='document_source_facet_test.cpp', LIBDEPS=[ '$BUILD_DIR/mongo/db/auth/authmocks', - '$BUILD_DIR/mongo/db/service_context_noop_init', + '$BUILD_DIR/mongo/db/service_context_test_fixture', '$BUILD_DIR/mongo/s/is_mongos', 'pipeline', 'document_source_mock', @@ -353,7 +352,6 @@ env.CppUnitTest( source='tee_buffer_test.cpp', LIBDEPS=[ '$BUILD_DIR/mongo/db/auth/authmocks', - '$BUILD_DIR/mongo/db/service_context_noop_init', '$BUILD_DIR/mongo/s/is_mongos', 'document_source_mock', 'document_value_test_util', @@ -369,6 +367,7 @@ env.CppUnitTest( ], LIBDEPS=[ '$BUILD_DIR/mongo/db/query/query_test_service_context', + '$BUILD_DIR/mongo/db/service_context_test_fixture', 'accumulator', 'document_value_test_util', 'expression', @@ -396,8 +395,7 @@ env.CppUnitTest( '$BUILD_DIR/mongo/db/auth/authmocks', '$BUILD_DIR/mongo/db/query/collation/collator_interface_mock', '$BUILD_DIR/mongo/db/repl/replmocks', - '$BUILD_DIR/mongo/db/service_context', - '$BUILD_DIR/mongo/db/service_context_noop_init', + '$BUILD_DIR/mongo/db/service_context_test_fixture', '$BUILD_DIR/mongo/s/is_mongos', 'document_value_test_util', 'document_source_mock', @@ -413,7 +411,6 @@ env.CppUnitTest( LIBDEPS=[ '$BUILD_DIR/mongo/base', '$BUILD_DIR/mongo/db/query/collation/collator_interface_mock', - '$BUILD_DIR/mongo/db/service_context_noop_init', 'document_value', ] ) @@ -503,7 +500,6 @@ env.CppUnitTest( target='resume_token_test', source='resume_token_test.cpp', LIBDEPS=[ - '$BUILD_DIR/mongo/db/service_context_noop_init', '$BUILD_DIR/mongo/db/auth/authmocks', 'document_sources_idl', ], diff --git a/src/mongo/db/pipeline/aggregation_context_fixture.h b/src/mongo/db/pipeline/aggregation_context_fixture.h index b2833c5a70b..2fe53f43822 100644 --- a/src/mongo/db/pipeline/aggregation_context_fixture.h +++ b/src/mongo/db/pipeline/aggregation_context_fixture.h @@ -32,6 +32,7 @@ #include <memory> #include "mongo/db/pipeline/expression_context_for_test.h" +#include "mongo/db/service_context_test_fixture.h" #include "mongo/stdx/memory.h" #include "mongo/unittest/unittest.h" @@ -40,18 +41,25 @@ namespace mongo { /** * Test fixture which provides an ExpressionContext for use in testing. */ -class AggregationContextFixture : public unittest::Test { +class AggregationContextFixture : public ServiceContextTest { public: AggregationContextFixture() : AggregationContextFixture(NamespaceString("unittests.pipeline_test")) {} - AggregationContextFixture(NamespaceString nss) : _expCtx(new ExpressionContextForTest(nss)) {} + AggregationContextFixture(NamespaceString nss) { + TimeZoneDatabase::set(getServiceContext(), std::make_unique<TimeZoneDatabase>()); + // Must instantiate ExpressionContext _after_ setting the TZ database on the service + // context. + _expCtx = new ExpressionContext(_opCtx.get(), nullptr); + _expCtx->ns = std::move(nss); + } - boost::intrusive_ptr<ExpressionContextForTest> getExpCtx() { + boost::intrusive_ptr<ExpressionContext> getExpCtx() { return _expCtx.get(); } private: - boost::intrusive_ptr<ExpressionContextForTest> _expCtx; + ServiceContext::UniqueOperationContext _opCtx = makeOperationContext(); + boost::intrusive_ptr<ExpressionContext> _expCtx; }; } // namespace mongo diff --git a/src/mongo/db/pipeline/document_source_graph_lookup_test.cpp b/src/mongo/db/pipeline/document_source_graph_lookup_test.cpp index 05a62606bb6..b3079f0573f 100644 --- a/src/mongo/db/pipeline/document_source_graph_lookup_test.cpp +++ b/src/mongo/db/pipeline/document_source_graph_lookup_test.cpp @@ -100,7 +100,7 @@ TEST_F(DocumentSourceGraphLookUpTest, std::deque<DocumentSource::GetNextResult> fromContents{Document{{"to", 0}}}; NamespaceString fromNs("test", "graph_lookup"); - expCtx->setResolvedNamespace(fromNs, {fromNs, std::vector<BSONObj>{}}); + expCtx->setResolvedNamespace_forTest(fromNs, {fromNs, std::vector<BSONObj>{}}); expCtx->mongoProcessInterface = std::make_shared<MockMongoInterface>(std::move(fromContents)); auto graphLookupStage = DocumentSourceGraphLookUp::create(expCtx, @@ -128,7 +128,7 @@ TEST_F(DocumentSourceGraphLookUpTest, Document{{"_id", "a"_sd}, {"to", 0}, {"from", 1}}, Document{{"to", 1}}}; NamespaceString fromNs("test", "graph_lookup"); - expCtx->setResolvedNamespace(fromNs, {fromNs, std::vector<BSONObj>{}}); + expCtx->setResolvedNamespace_forTest(fromNs, {fromNs, std::vector<BSONObj>{}}); expCtx->mongoProcessInterface = std::make_shared<MockMongoInterface>(std::move(fromContents)); auto graphLookupStage = DocumentSourceGraphLookUp::create(expCtx, @@ -156,7 +156,7 @@ TEST_F(DocumentSourceGraphLookUpTest, std::deque<DocumentSource::GetNextResult> fromContents{Document{{"to", 0}}}; NamespaceString fromNs("test", "graph_lookup"); - expCtx->setResolvedNamespace(fromNs, {fromNs, std::vector<BSONObj>{}}); + expCtx->setResolvedNamespace_forTest(fromNs, {fromNs, std::vector<BSONObj>{}}); expCtx->mongoProcessInterface = std::make_shared<MockMongoInterface>(std::move(fromContents)); auto unwindStage = DocumentSourceUnwind::create(expCtx, "results", false, boost::none); auto graphLookupStage = @@ -199,7 +199,7 @@ TEST_F(DocumentSourceGraphLookUpTest, Document(to1), Document(to2), Document(to0from1), Document(to0from2)}; NamespaceString fromNs("test", "graph_lookup"); - expCtx->setResolvedNamespace(fromNs, {fromNs, std::vector<BSONObj>{}}); + expCtx->setResolvedNamespace_forTest(fromNs, {fromNs, std::vector<BSONObj>{}}); expCtx->mongoProcessInterface = std::make_shared<MockMongoInterface>(std::move(fromContents)); auto graphLookupStage = DocumentSourceGraphLookUp::create(expCtx, @@ -263,7 +263,7 @@ TEST_F(DocumentSourceGraphLookUpTest, ShouldPropagatePauses) { Document{{"_id", "a"_sd}, {"to", 0}, {"from", 1}}, Document{{"_id", "b"_sd}, {"to", 1}}}; NamespaceString fromNs("test", "foreign"); - expCtx->setResolvedNamespace(fromNs, {fromNs, std::vector<BSONObj>{}}); + expCtx->setResolvedNamespace_forTest(fromNs, {fromNs, std::vector<BSONObj>{}}); expCtx->mongoProcessInterface = std::make_shared<MockMongoInterface>(std::move(fromContents)); auto graphLookupStage = DocumentSourceGraphLookUp::create(expCtx, @@ -329,7 +329,7 @@ TEST_F(DocumentSourceGraphLookUpTest, ShouldPropagatePausesWhileUnwinding) { Document{{"_id", "a"_sd}, {"to", 0}, {"from", 1}}, Document{{"_id", "b"_sd}, {"to", 1}}}; NamespaceString fromNs("test", "foreign"); - expCtx->setResolvedNamespace(fromNs, {fromNs, std::vector<BSONObj>{}}); + expCtx->setResolvedNamespace_forTest(fromNs, {fromNs, std::vector<BSONObj>{}}); expCtx->mongoProcessInterface = std::make_shared<MockMongoInterface>(std::move(fromContents)); const bool preserveNullAndEmptyArrays = false; @@ -392,7 +392,7 @@ TEST_F(DocumentSourceGraphLookUpTest, ShouldPropagatePausesWhileUnwinding) { TEST_F(DocumentSourceGraphLookUpTest, GraphLookupShouldReportAsFieldIsModified) { auto expCtx = getExpCtx(); NamespaceString fromNs("test", "foreign"); - expCtx->setResolvedNamespace(fromNs, {fromNs, std::vector<BSONObj>{}}); + expCtx->setResolvedNamespace_forTest(fromNs, {fromNs, std::vector<BSONObj>{}}); expCtx->mongoProcessInterface = std::make_shared<MockMongoInterface>(std::deque<DocumentSource::GetNextResult>{}); auto graphLookupStage = @@ -416,7 +416,7 @@ TEST_F(DocumentSourceGraphLookUpTest, GraphLookupShouldReportAsFieldIsModified) TEST_F(DocumentSourceGraphLookUpTest, GraphLookupShouldReportFieldsModifiedByAbsorbedUnwind) { auto expCtx = getExpCtx(); NamespaceString fromNs("test", "foreign"); - expCtx->setResolvedNamespace(fromNs, {fromNs, std::vector<BSONObj>{}}); + expCtx->setResolvedNamespace_forTest(fromNs, {fromNs, std::vector<BSONObj>{}}); expCtx->mongoProcessInterface = std::make_shared<MockMongoInterface>(std::deque<DocumentSource::GetNextResult>{}); auto unwindStage = @@ -446,7 +446,7 @@ TEST_F(DocumentSourceGraphLookUpTest, GraphLookupWithComparisonExpressionForStar auto inputMock = DocumentSourceMock::create(Document({{"_id", 0}, {"a", 1}, {"b", 2}})); NamespaceString fromNs("test", "foreign"); - expCtx->setResolvedNamespace(fromNs, {fromNs, std::vector<BSONObj>{}}); + expCtx->setResolvedNamespace_forTest(fromNs, {fromNs, std::vector<BSONObj>{}}); std::deque<DocumentSource::GetNextResult> fromContents{Document{{"_id", 0}, {"to", true}}, Document{{"_id", 1}, {"to", false}}}; expCtx->mongoProcessInterface = std::make_shared<MockMongoInterface>(std::move(fromContents)); @@ -511,7 +511,7 @@ TEST_F(DocumentSourceGraphLookUpTest, ShouldExpandArraysAtEndOfConnectFromField) Document(sinkDoc)}; NamespaceString fromNs("test", "graph_lookup"); - expCtx->setResolvedNamespace(fromNs, {fromNs, std::vector<BSONObj>{}}); + expCtx->setResolvedNamespace_forTest(fromNs, {fromNs, std::vector<BSONObj>{}}); expCtx->mongoProcessInterface = std::make_shared<MockMongoInterface>(std::move(fromContents)); auto graphLookupStage = DocumentSourceGraphLookUp::create(expCtx, @@ -583,7 +583,7 @@ TEST_F(DocumentSourceGraphLookUpTest, ShouldNotExpandArraysWithinArraysAtEndOfCo Document(startDoc), Document(target1), Document(target2), Document(soloDoc)}; NamespaceString fromNs("test", "graph_lookup"); - expCtx->setResolvedNamespace(fromNs, {fromNs, std::vector<BSONObj>{}}); + expCtx->setResolvedNamespace_forTest(fromNs, {fromNs, std::vector<BSONObj>{}}); expCtx->mongoProcessInterface = std::make_shared<MockMongoInterface>(std::move(fromContents)); auto graphLookupStage = DocumentSourceGraphLookUp::create(expCtx, diff --git a/src/mongo/db/pipeline/document_source_group_test.cpp b/src/mongo/db/pipeline/document_source_group_test.cpp index 6a6d3232248..4062c497a53 100644 --- a/src/mongo/db/pipeline/document_source_group_test.cpp +++ b/src/mongo/db/pipeline/document_source_group_test.cpp @@ -196,11 +196,10 @@ BSONObj toBson(const intrusive_ptr<DocumentSource>& source) { return arr[0].getDocument().toBson(); } -class Base { +class Base : public ServiceContextTest { public: Base() - : _queryServiceContext(stdx::make_unique<QueryTestServiceContext>()), - _opCtx(_queryServiceContext->makeOperationContext()), + : _opCtx(makeOperationContext()), _ctx(new ExpressionContextForTest(_opCtx.get(), AggregationRequest(NamespaceString(ns), {}))), _tempDir("DocumentSourceGroupTest") {} @@ -257,7 +256,7 @@ private: class ParseErrorBase : public Base { public: virtual ~ParseErrorBase() {} - void run() { + void _doTest() final { ASSERT_THROWS(createGroup(spec()), AssertionException); } @@ -268,7 +267,7 @@ protected: class ExpressionBase : public Base { public: virtual ~ExpressionBase() {} - void run() { + void _doTest() final { createGroup(spec()); auto source = DocumentSourceMock::create(Document(doc())); group()->setSource(source.get()); @@ -298,7 +297,7 @@ class IdConstantBase : public ExpressionBase { /** $group spec is not an object. */ class NonObject : public Base { public: - void run() { + void _doTest() final { BSONObj spec = BSON("$group" << "foo"); BSONElement specElement = spec.firstElement(); @@ -500,7 +499,7 @@ typedef map<Value, Document, ValueCmp> IdMap; class CheckResultsBase : public Base { public: virtual ~CheckResultsBase() {} - void run() { + void _doTest() { runSharded(false); runSharded(true); } @@ -726,7 +725,7 @@ class UndefinedAccumulatorValue : public CheckResultsBase { /** Simulate merging sharded results in the router. */ class RouterMerger : public CheckResultsBase { public: - void run() { + void _doTest() final { auto source = DocumentSourceMock::create({"{_id:0,list:[1,2]}", "{_id:1,list:[3,4]}", "{_id:0,list:[10,20]}", @@ -755,7 +754,7 @@ private: /** Dependant field paths. */ class Dependencies : public Base { public: - void run() { + void _doTest() final { createGroup(fromjson("{_id:'$x',a:{$sum:'$y.z'},b:{$avg:{$add:['$u','$v']}}}")); DepsTracker dependencies; ASSERT_EQUALS(DepsTracker::State::EXHAUSTIVE_ALL, group()->getDependencies(&dependencies)); @@ -773,7 +772,7 @@ public: class StreamingOptimization : public Base { public: - void run() { + void _doTest() final { auto source = DocumentSourceMock::create({"{a: 0}", "{a: 0}", "{a: 1}", "{a: 1}"}); source->sorts = {BSON("a" << 1)}; @@ -808,7 +807,7 @@ public: class StreamingWithMultipleIdFields : public Base { public: - void run() { + void _doTest() final { auto source = DocumentSourceMock::create( {"{a: 1, b: 2}", "{a: 1, b: 2}", "{a: 1, b: 1}", "{a: 2, b: 1}", "{a: 2, b: 1}"}); source->sorts = {BSON("a" << 1 << "b" << -1)}; @@ -848,7 +847,7 @@ public: class StreamingWithMultipleLevels : public Base { public: - void run() { + void _doTest() final { auto source = DocumentSourceMock::create( {"{a: {b: {c: 3}}, d: 1}", "{a: {b: {c: 1}}, d: 2}", "{a: {b: {c: 1}}, d: 0}"}); source->sorts = {BSON("a.b.c" << -1 << "a.b.d" << 1 << "d" << 1)}; @@ -884,7 +883,7 @@ public: class StreamingWithFieldRepeated : public Base { public: - void run() { + void _doTest() final { auto source = DocumentSourceMock::create( {"{a: 1, b: 1}", "{a: 1, b: 1}", "{a: 2, b: 1}", "{a: 2, b: 3}"}); source->sorts = {BSON("a" << 1 << "b" << 1)}; @@ -919,7 +918,7 @@ public: class StreamingWithConstantAndFieldPath : public Base { public: - void run() { + void _doTest() final { auto source = DocumentSourceMock::create( {"{a: 5, b: 1}", "{a: 5, b: 2}", "{a: 3, b: 1}", "{a: 1, b: 1}", "{a: 1, b: 1}"}); source->sorts = {BSON("a" << -1 << "b" << 1)}; @@ -953,7 +952,7 @@ public: class StreamingWithRootSubfield : public Base { public: - void run() { + void _doTest() final { auto source = DocumentSourceMock::create({"{a: 1}", "{a: 2}", "{a: 3}"}); source->sorts = {BSON("a" << 1)}; @@ -973,7 +972,7 @@ public: class StreamingWithConstant : public Base { public: - void run() { + void _doTest() final { auto source = DocumentSourceMock::create({"{a: 1}", "{a: 2}", "{a: 3}"}); source->sorts = {BSON("$a" << 1)}; @@ -990,7 +989,7 @@ public: class StreamingWithEmptyId : public Base { public: - void run() { + void _doTest() final { auto source = DocumentSourceMock::create({"{a: 1}", "{a: 2}", "{a: 3}"}); source->sorts = {BSON("$a" << 1)}; @@ -1007,7 +1006,7 @@ public: class NoOptimizationIfMissingDoubleSort : public Base { public: - void run() { + void _doTest() final { auto source = DocumentSourceMock::create({"{a: 1}", "{a: 2}", "{a: 3}"}); source->sorts = {BSON("a" << 1)}; @@ -1034,7 +1033,7 @@ public: class NoOptimizationWithRawRoot : public Base { public: - void run() { + void _doTest() final { auto source = DocumentSourceMock::create({"{a: 1}", "{a: 2}", "{a: 3}"}); source->sorts = {BSON("a" << 1)}; @@ -1061,7 +1060,7 @@ public: class NoOptimizationIfUsingExpressions : public Base { public: - void run() { + void _doTest() final { auto source = DocumentSourceMock::create({"{a: 1, b: 1}", "{a: 2, b: 2}", "{a: 3, b: 1}"}); source->sorts = {BSON("a" << 1 << "b" << 1)}; @@ -1100,11 +1099,11 @@ class StringConstantIdAndAccumulatorExpressions : public CheckResultsBase { /** An array constant passed to an accumulator. */ class ArrayConstantAccumulatorExpression : public CheckResultsBase { public: - void run() { + void _doTest() final { // A parse exception is thrown when a raw array is provided to an accumulator. ASSERT_THROWS(createGroup(fromjson("{_id:1,a:{$push:[4,5,6]}}")), AssertionException); // Run standard base tests. - CheckResultsBase::run(); + CheckResultsBase::_doTest(); } deque<DocumentSource::GetNextResult> inputData() { return {Document()}; diff --git a/src/mongo/db/pipeline/document_source_lookup_test.cpp b/src/mongo/db/pipeline/document_source_lookup_test.cpp index 3c27f9a90ab..00c0baeecdb 100644 --- a/src/mongo/db/pipeline/document_source_lookup_test.cpp +++ b/src/mongo/db/pipeline/document_source_lookup_test.cpp @@ -85,7 +85,7 @@ public: TEST_F(DocumentSourceLookUpTest, PreservesParentPipelineLetVariables) { auto expCtx = getExpCtx(); NamespaceString fromNs("test", "coll"); - expCtx->setResolvedNamespace(fromNs, {fromNs, std::vector<BSONObj>{}}); + expCtx->setResolvedNamespace_forTest(fromNs, {fromNs, std::vector<BSONObj>{}}); auto varId = expCtx->variablesParseState.defineVariable("foo"); expCtx->variables.setValue(varId, Value(123)); @@ -109,7 +109,7 @@ TEST_F(DocumentSourceLookUpTest, PreservesParentPipelineLetVariables) { TEST_F(DocumentSourceLookUpTest, ShouldTruncateOutputSortOnAsField) { auto expCtx = getExpCtx(); NamespaceString fromNs("test", "a"); - expCtx->setResolvedNamespace(fromNs, {fromNs, std::vector<BSONObj>{}}); + expCtx->setResolvedNamespace_forTest(fromNs, {fromNs, std::vector<BSONObj>{}}); intrusive_ptr<DocumentSourceMock> source = DocumentSourceMock::create(); source->sorts = {BSON("a" << 1 << "d.e" << 1 << "c" << 1)}; @@ -132,7 +132,7 @@ TEST_F(DocumentSourceLookUpTest, ShouldTruncateOutputSortOnAsField) { TEST_F(DocumentSourceLookUpTest, ShouldTruncateOutputSortOnSuffixOfAsField) { auto expCtx = getExpCtx(); NamespaceString fromNs("test", "a"); - expCtx->setResolvedNamespace(fromNs, {fromNs, std::vector<BSONObj>{}}); + expCtx->setResolvedNamespace_forTest(fromNs, {fromNs, std::vector<BSONObj>{}}); intrusive_ptr<DocumentSourceMock> source = DocumentSourceMock::create(); source->sorts = {BSON("a" << 1 << "d.e" << 1 << "c" << 1)}; @@ -155,7 +155,7 @@ TEST_F(DocumentSourceLookUpTest, ShouldTruncateOutputSortOnSuffixOfAsField) { TEST_F(DocumentSourceLookUpTest, AcceptsPipelineSyntax) { auto expCtx = getExpCtx(); NamespaceString fromNs("test", "coll"); - expCtx->setResolvedNamespace(fromNs, {fromNs, std::vector<BSONObj>{}}); + expCtx->setResolvedNamespace_forTest(fromNs, {fromNs, std::vector<BSONObj>{}}); auto docSource = DocumentSourceLookUp::createFromBson( BSON("$lookup" << BSON("from" @@ -173,7 +173,7 @@ TEST_F(DocumentSourceLookUpTest, AcceptsPipelineSyntax) { TEST_F(DocumentSourceLookUpTest, AcceptsPipelineWithLetSyntax) { auto expCtx = getExpCtx(); NamespaceString fromNs("test", "coll"); - expCtx->setResolvedNamespace(fromNs, {fromNs, std::vector<BSONObj>{}}); + expCtx->setResolvedNamespace_forTest(fromNs, {fromNs, std::vector<BSONObj>{}}); auto docSource = DocumentSourceLookUp::createFromBson( BSON("$lookup" << BSON("from" @@ -225,7 +225,7 @@ TEST_F(DocumentSourceLookUpTest, LiteParsedDocumentSourceLookupContainsExpectedN TEST_F(DocumentSourceLookUpTest, RejectLookupWhenDepthLimitIsExceeded) { auto expCtx = getExpCtx(); NamespaceString fromNs("test", "coll"); - expCtx->setResolvedNamespace(fromNs, {fromNs, std::vector<BSONObj>{}}); + expCtx->setResolvedNamespace_forTest(fromNs, {fromNs, std::vector<BSONObj>{}}); expCtx->subPipelineDepth = DocumentSourceLookUp::kMaxSubPipelineDepth; @@ -245,7 +245,7 @@ TEST_F(DocumentSourceLookUpTest, RejectLookupWhenDepthLimitIsExceeded) { TEST_F(ReplDocumentSourceLookUpTest, RejectsPipelineWithChangeStreamStage) { auto expCtx = getExpCtx(); NamespaceString fromNs("test", "coll"); - expCtx->setResolvedNamespace(fromNs, {fromNs, std::vector<BSONObj>{}}); + expCtx->setResolvedNamespace_forTest(fromNs, {fromNs, std::vector<BSONObj>{}}); // Verify that attempting to create a $lookup pipeline containing a $changeStream stage fails. ASSERT_THROWS_CODE( @@ -260,7 +260,7 @@ TEST_F(ReplDocumentSourceLookUpTest, RejectsPipelineWithChangeStreamStage) { TEST_F(ReplDocumentSourceLookUpTest, RejectsSubPipelineWithChangeStreamStage) { auto expCtx = getExpCtx(); NamespaceString fromNs("test", "coll"); - expCtx->setResolvedNamespace(fromNs, {fromNs, std::vector<BSONObj>{}}); + expCtx->setResolvedNamespace_forTest(fromNs, {fromNs, std::vector<BSONObj>{}}); // Verify that attempting to create a sub-$lookup pipeline containing a $changeStream stage // fails at parse time, even if the outer pipeline does not have a $changeStream stage. @@ -277,7 +277,7 @@ TEST_F(ReplDocumentSourceLookUpTest, RejectsSubPipelineWithChangeStreamStage) { TEST_F(DocumentSourceLookUpTest, RejectsLocalFieldForeignFieldWhenPipelineIsSpecified) { auto expCtx = getExpCtx(); NamespaceString fromNs("test", "coll"); - expCtx->setResolvedNamespace(fromNs, {fromNs, std::vector<BSONObj>{}}); + expCtx->setResolvedNamespace_forTest(fromNs, {fromNs, std::vector<BSONObj>{}}); try { auto lookupStage = DocumentSourceLookUp::createFromBson( @@ -306,7 +306,7 @@ TEST_F(DocumentSourceLookUpTest, RejectsLocalFieldForeignFieldWhenPipelineIsSpec TEST_F(DocumentSourceLookUpTest, RejectsLocalFieldForeignFieldWhenLetIsSpecified) { auto expCtx = getExpCtx(); NamespaceString fromNs("test", "coll"); - expCtx->setResolvedNamespace(fromNs, {fromNs, std::vector<BSONObj>{}}); + expCtx->setResolvedNamespace_forTest(fromNs, {fromNs, std::vector<BSONObj>{}}); ASSERT_THROWS_CODE(DocumentSourceLookUp::createFromBson(BSON("$lookup" << BSON("from" << "coll" @@ -328,7 +328,7 @@ TEST_F(DocumentSourceLookUpTest, RejectsLocalFieldForeignFieldWhenLetIsSpecified TEST_F(DocumentSourceLookUpTest, RejectsInvalidLetVariableName) { auto expCtx = getExpCtx(); NamespaceString fromNs("test", "coll"); - expCtx->setResolvedNamespace(fromNs, {fromNs, std::vector<BSONObj>{}}); + expCtx->setResolvedNamespace_forTest(fromNs, {fromNs, std::vector<BSONObj>{}}); ASSERT_THROWS_CODE(DocumentSourceLookUp::createFromBson( BSON("$lookup" << BSON("from" @@ -379,7 +379,7 @@ TEST_F(DocumentSourceLookUpTest, RejectsInvalidLetVariableName) { TEST_F(DocumentSourceLookUpTest, ShouldBeAbleToReParseSerializedStage) { auto expCtx = getExpCtx(); NamespaceString fromNs("test", "coll"); - expCtx->setResolvedNamespace(fromNs, {fromNs, std::vector<BSONObj>{}}); + expCtx->setResolvedNamespace_forTest(fromNs, {fromNs, std::vector<BSONObj>{}}); auto lookupStage = DocumentSourceLookUp::createFromBson( BSON("$lookup" << BSON("from" @@ -540,7 +540,7 @@ private: TEST_F(DocumentSourceLookUpTest, ShouldPropagatePauses) { auto expCtx = getExpCtx(); NamespaceString fromNs("test", "foreign"); - expCtx->setResolvedNamespace(fromNs, {fromNs, std::vector<BSONObj>{}}); + expCtx->setResolvedNamespace_forTest(fromNs, {fromNs, std::vector<BSONObj>{}}); // Set up the $lookup stage. auto lookupSpec = Document{{"$lookup", @@ -591,7 +591,7 @@ TEST_F(DocumentSourceLookUpTest, ShouldPropagatePauses) { TEST_F(DocumentSourceLookUpTest, ShouldPropagatePausesWhileUnwinding) { auto expCtx = getExpCtx(); NamespaceString fromNs("test", "foreign"); - expCtx->setResolvedNamespace(fromNs, {fromNs, std::vector<BSONObj>{}}); + expCtx->setResolvedNamespace_forTest(fromNs, {fromNs, std::vector<BSONObj>{}}); // Set up the $lookup stage. auto lookupSpec = Document{{"$lookup", @@ -644,7 +644,7 @@ TEST_F(DocumentSourceLookUpTest, ShouldPropagatePausesWhileUnwinding) { TEST_F(DocumentSourceLookUpTest, LookupReportsAsFieldIsModified) { auto expCtx = getExpCtx(); NamespaceString fromNs("test", "foreign"); - expCtx->setResolvedNamespace(fromNs, {fromNs, std::vector<BSONObj>{}}); + expCtx->setResolvedNamespace_forTest(fromNs, {fromNs, std::vector<BSONObj>{}}); // Set up the $lookup stage. auto lookupSpec = Document{{"$lookup", @@ -666,7 +666,7 @@ TEST_F(DocumentSourceLookUpTest, LookupReportsAsFieldIsModified) { TEST_F(DocumentSourceLookUpTest, LookupReportsFieldsModifiedByAbsorbedUnwind) { auto expCtx = getExpCtx(); NamespaceString fromNs("test", "foreign"); - expCtx->setResolvedNamespace(fromNs, {fromNs, std::vector<BSONObj>{}}); + expCtx->setResolvedNamespace_forTest(fromNs, {fromNs, std::vector<BSONObj>{}}); // Set up the $lookup stage. auto lookupSpec = Document{{"$lookup", @@ -699,7 +699,7 @@ BSONObj sequentialCacheStageObj(const StringData status = "kBuilding"_sd, TEST_F(DocumentSourceLookUpTest, ShouldCacheNonCorrelatedSubPipelinePrefix) { auto expCtx = getExpCtx(); NamespaceString fromNs("test", "coll"); - expCtx->setResolvedNamespace(fromNs, {fromNs, std::vector<BSONObj>{}}); + expCtx->setResolvedNamespace_forTest(fromNs, {fromNs, std::vector<BSONObj>{}}); auto docSource = DocumentSourceLookUp::createFromBson( fromjson("{$lookup: {let: {var1: '$_id'}, pipeline: [{$match: {x:1}}, {$sort: {x: 1}}, " @@ -728,7 +728,7 @@ TEST_F(DocumentSourceLookUpTest, ShouldDiscoverVariablesReferencedInFacetPipelineAfterAnExhaustiveAllStage) { auto expCtx = getExpCtx(); NamespaceString fromNs("test", "coll"); - expCtx->setResolvedNamespace(fromNs, {fromNs, std::vector<BSONObj>{}}); + expCtx->setResolvedNamespace_forTest(fromNs, {fromNs, std::vector<BSONObj>{}}); // In the $facet stage here, the correlated $match stage comes after a $group stage which // returns EXHAUSTIVE_ALL for its dependencies. Verify that we continue enumerating the $facet @@ -763,7 +763,7 @@ TEST_F(DocumentSourceLookUpTest, TEST_F(DocumentSourceLookUpTest, ExprEmbeddedInMatchExpressionShouldBeOptimized) { auto expCtx = getExpCtx(); NamespaceString fromNs("test", "coll"); - expCtx->setResolvedNamespace(fromNs, {fromNs, std::vector<BSONObj>{}}); + expCtx->setResolvedNamespace_forTest(fromNs, {fromNs, std::vector<BSONObj>{}}); // This pipeline includes a $match stage that itself includes a $expr expression. auto docSource = DocumentSourceLookUp::createFromBson( @@ -802,7 +802,7 @@ TEST_F(DocumentSourceLookUpTest, ShouldIgnoreLocalVariablesShadowingLetVariablesWhenFindingNonCorrelatedPrefix) { auto expCtx = getExpCtx(); NamespaceString fromNs("test", "coll"); - expCtx->setResolvedNamespace(fromNs, {fromNs, std::vector<BSONObj>{}}); + expCtx->setResolvedNamespace_forTest(fromNs, {fromNs, std::vector<BSONObj>{}}); // The $project stage defines a local variable with the same name as the $lookup 'let' variable. // Verify that the $project is identified as non-correlated and the cache is placed after it. @@ -836,7 +836,7 @@ TEST_F(DocumentSourceLookUpTest, TEST_F(DocumentSourceLookUpTest, ShouldInsertCacheBeforeCorrelatedNestedLookup) { auto expCtx = getExpCtx(); NamespaceString fromNs("test", "coll"); - expCtx->setResolvedNamespace(fromNs, {fromNs, std::vector<BSONObj>{}}); + expCtx->setResolvedNamespace_forTest(fromNs, {fromNs, std::vector<BSONObj>{}}); // Create a $lookup stage whose pipeline contains nested $lookups. The third-level $lookup // refers to a 'let' variable defined in the top-level $lookup. Verify that the second-level @@ -873,7 +873,7 @@ TEST_F(DocumentSourceLookUpTest, ShouldIgnoreNestedLookupLetVariablesShadowingOuterLookupLetVariablesWhenFindingPrefix) { auto expCtx = getExpCtx(); NamespaceString fromNs("test", "coll"); - expCtx->setResolvedNamespace(fromNs, {fromNs, std::vector<BSONObj>{}}); + expCtx->setResolvedNamespace_forTest(fromNs, {fromNs, std::vector<BSONObj>{}}); // The nested $lookup stage defines a 'let' variable with the same name as the top-level 'let'. // Verify the nested $lookup is identified as non-correlated and the cache is placed after it. @@ -907,7 +907,7 @@ TEST_F(DocumentSourceLookUpTest, TEST_F(DocumentSourceLookUpTest, ShouldCacheEntirePipelineIfNonCorrelated) { auto expCtx = getExpCtx(); NamespaceString fromNs("test", "coll"); - expCtx->setResolvedNamespace(fromNs, {fromNs, std::vector<BSONObj>{}}); + expCtx->setResolvedNamespace_forTest(fromNs, {fromNs, std::vector<BSONObj>{}}); auto docSource = DocumentSourceLookUp::createFromBson( fromjson("{$lookup: {let: {}, pipeline: [{$match: {x:1}}, {$sort: {x: 1}}, {$lookup: " @@ -940,7 +940,7 @@ TEST_F(DocumentSourceLookUpTest, ShouldReplaceNonCorrelatedPrefixWithCacheAfterFirstSubPipelineIteration) { auto expCtx = getExpCtx(); NamespaceString fromNs("test", "coll"); - expCtx->setResolvedNamespace(fromNs, {fromNs, std::vector<BSONObj>{}}); + expCtx->setResolvedNamespace_forTest(fromNs, {fromNs, std::vector<BSONObj>{}}); auto docSource = DocumentSourceLookUp::createFromBson( fromjson( @@ -1014,7 +1014,7 @@ TEST_F(DocumentSourceLookUpTest, ShouldAbandonCacheIfMaxSizeIsExceededAfterFirstSubPipelineIteration) { auto expCtx = getExpCtx(); NamespaceString fromNs("test", "coll"); - expCtx->setResolvedNamespace(fromNs, {fromNs, std::vector<BSONObj>{}}); + expCtx->setResolvedNamespace_forTest(fromNs, {fromNs, std::vector<BSONObj>{}}); // Ensure the cache is abandoned after the first iteration by setting its max size to 0. size_t maxCacheSizeBytes = 0; @@ -1079,7 +1079,7 @@ TEST_F(DocumentSourceLookUpTest, TEST_F(DocumentSourceLookUpTest, ShouldNotCacheIfCorrelatedStageIsAbsorbedIntoPlanExecutor) { auto expCtx = getExpCtx(); NamespaceString fromNs("test", "coll"); - expCtx->setResolvedNamespace(fromNs, {fromNs, std::vector<BSONObj>{}}); + expCtx->setResolvedNamespace_forTest(fromNs, {fromNs, std::vector<BSONObj>{}}); auto docSource = DocumentSourceLookUp::createFromBson( fromjson("{$lookup: {let: {var1: '$_id'}, pipeline: [{$match: {$expr: { $gte: ['$x', " diff --git a/src/mongo/db/pipeline/document_source_merge_cursors_test.cpp b/src/mongo/db/pipeline/document_source_merge_cursors_test.cpp index 3614324d27d..902063bd233 100644 --- a/src/mongo/db/pipeline/document_source_merge_cursors_test.cpp +++ b/src/mongo/db/pipeline/document_source_merge_cursors_test.cpp @@ -37,7 +37,7 @@ #include "mongo/db/pipeline/document_source_limit.h" #include "mongo/db/pipeline/document_source_sort.h" #include "mongo/db/pipeline/document_value_test_util.h" -#include "mongo/db/pipeline/expression_context_for_test.h" +#include "mongo/db/pipeline/expression_context.h" #include "mongo/db/query/cursor_response.h" #include "mongo/db/query/getmore_request.h" #include "mongo/db/query/query_request.h" @@ -74,7 +74,11 @@ const CursorId kExhaustedCursorID = 0; class DocumentSourceMergeCursorsTest : public ShardingTestFixture { public: - DocumentSourceMergeCursorsTest() : _expCtx(new ExpressionContextForTest(kTestNss)) {} + DocumentSourceMergeCursorsTest() { + TimeZoneDatabase::set(getServiceContext(), std::make_unique<TimeZoneDatabase>()); + _expCtx = new ExpressionContext(operationContext(), nullptr); + _expCtx->ns = kTestNss; + } void setUp() override { ShardingTestFixture::setUp(); @@ -102,12 +106,12 @@ public: setupShards(shards); } - boost::intrusive_ptr<ExpressionContextForTest> getExpCtx() { + boost::intrusive_ptr<ExpressionContext> getExpCtx() { return _expCtx.get(); } private: - boost::intrusive_ptr<ExpressionContextForTest> _expCtx; + boost::intrusive_ptr<ExpressionContext> _expCtx; }; TEST_F(DocumentSourceMergeCursorsTest, ShouldRejectNonArray) { diff --git a/src/mongo/db/pipeline/document_source_test.cpp b/src/mongo/db/pipeline/document_source_test.cpp index 934f9bf024a..2979179c255 100644 --- a/src/mongo/db/pipeline/document_source_test.cpp +++ b/src/mongo/db/pipeline/document_source_test.cpp @@ -32,13 +32,16 @@ #include "mongo/bson/bsonobj.h" #include "mongo/bson/bsonobjbuilder.h" #include "mongo/db/pipeline/document_source.h" +#include "mongo/db/service_context_test_fixture.h" #include "mongo/unittest/unittest.h" namespace mongo { namespace { -TEST(TruncateSort, SortTruncatesNormalField) { +class DocumentSourceTruncateSort : public ServiceContextTest {}; + +TEST_F(DocumentSourceTruncateSort, SortTruncatesNormalField) { SimpleBSONObjComparator bsonComparator{}; BSONObj sortKey = BSON("a" << 1 << "b" << 1 << "c" << 1); auto truncated = @@ -47,7 +50,7 @@ TEST(TruncateSort, SortTruncatesNormalField) { ASSERT_EQUALS(truncated.count(BSON("a" << 1)), 1U); } -TEST(DocumentSourceTruncateSort, SortTruncatesOnSubfield) { +TEST_F(DocumentSourceTruncateSort, SortTruncatesOnSubfield) { SimpleBSONObjComparator bsonComparator{}; BSONObj sortKey = BSON("a" << 1 << "b.c" << 1 << "d" << 1); auto truncated = @@ -56,7 +59,7 @@ TEST(DocumentSourceTruncateSort, SortTruncatesOnSubfield) { ASSERT_EQUALS(truncated.count(BSON("a" << 1)), 1U); } -TEST(DocumentSourceTruncateSort, SortDoesNotTruncateOnParent) { +TEST_F(DocumentSourceTruncateSort, SortDoesNotTruncateOnParent) { SimpleBSONObjComparator bsonComparator{}; BSONObj sortKey = BSON("a" << 1 << "b" << 1 << "d" << 1); auto truncated = @@ -65,7 +68,7 @@ TEST(DocumentSourceTruncateSort, SortDoesNotTruncateOnParent) { ASSERT_EQUALS(truncated.count(BSON("a" << 1 << "b" << 1 << "d" << 1)), 1U); } -TEST(DocumentSourceTruncateSort, TruncateSortDedupsSortCorrectly) { +TEST_F(DocumentSourceTruncateSort, TruncateSortDedupsSortCorrectly) { SimpleBSONObjComparator bsonComparator{}; BSONObj sortKeyOne = BSON("a" << 1 << "b" << 1); BSONObj sortKeyTwo = BSON("a" << 1); diff --git a/src/mongo/db/pipeline/expression_context.h b/src/mongo/db/pipeline/expression_context.h index ed5dd84b251..495797b7575 100644 --- a/src/mongo/db/pipeline/expression_context.h +++ b/src/mongo/db/pipeline/expression_context.h @@ -186,6 +186,14 @@ public: return tailableMode == TailableModeEnum::kTailableAndAwaitData; } + /** + * Sets the resolved definition for an involved namespace. + */ + void setResolvedNamespace_forTest(const NamespaceString& nss, + ResolvedNamespace resolvedNamespace) { + _resolvedNamespaces[nss.coll()] = std::move(resolvedNamespace); + } + // The explain verbosity requested by the user, or boost::none if no explain was requested. boost::optional<ExplainOptions::Verbosity> explain; diff --git a/src/mongo/db/query/SConscript b/src/mongo/db/query/SConscript index a52027feee7..7247f723a02 100644 --- a/src/mongo/db/query/SConscript +++ b/src/mongo/db/query/SConscript @@ -108,7 +108,6 @@ env.CppUnitTest( ], LIBDEPS=[ "$BUILD_DIR/mongo/db/pipeline/aggregation_request", - '$BUILD_DIR/mongo/db/service_context_noop_init', "query_test_service_context", "query_common", ], @@ -203,6 +202,8 @@ env.Library( "$BUILD_DIR/mongo/db/logical_session_id", "$BUILD_DIR/mongo/db/service_context", ], + LIBDEPS_PRIVATE=[ + ], ) env.Library( @@ -263,6 +264,7 @@ env.CppUnitTest( LIBDEPS=[ "$BUILD_DIR/mongo/db/pipeline/aggregation_request", "$BUILD_DIR/mongo/db/concurrency/lock_manager", + "$BUILD_DIR/mongo/db/service_context_test_fixture", "query_request", ], ) 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 c2a4922071f..abe71a471d6 100644 --- a/src/mongo/db/query/collation/collator_factory_icu_decoration.cpp +++ b/src/mongo/db/query/collation/collator_factory_icu_decoration.cpp @@ -37,13 +37,12 @@ namespace mongo { namespace { -MONGO_INITIALIZER_WITH_PREREQUISITES(CreateCollatorFactory, ("ServiceContext", "LoadICUData")) -(InitializerContext* context) { - CollatorFactoryInterface::set(getGlobalServiceContext(), - stdx::make_unique<CollatorFactoryICU>()); - return Status::OK(); -} - +ServiceContext::ConstructorActionRegisterer registerIcuCollator{ + "CreateCollatorFactory", + {"LoadICUData"}, + [](ServiceContext* service) { + CollatorFactoryInterface::set(service, stdx::make_unique<CollatorFactoryICU>()); + }}; } // namespace } // namespace mongo diff --git a/src/mongo/db/query/query_request_test.cpp b/src/mongo/db/query/query_request_test.cpp index cb0a537c85c..d52631051e5 100644 --- a/src/mongo/db/query/query_request_test.cpp +++ b/src/mongo/db/query/query_request_test.cpp @@ -39,7 +39,7 @@ #include "mongo/db/namespace_string.h" #include "mongo/db/pipeline/aggregation_request.h" #include "mongo/db/query/query_request.h" -#include "mongo/db/service_context_noop.h" +#include "mongo/db/service_context_test_fixture.h" #include "mongo/unittest/unittest.h" namespace mongo { @@ -1322,20 +1322,19 @@ TEST(QueryRequestTest, ParseFromLegacyQueryTooNegativeNToReturn) { .getStatus()); } -TEST(QueryRequestTest, ParseFromUUID) { - ServiceContextNoop service; - auto client = service.makeClient("test"); - auto opCtxNoop = client->makeOperationContext(); - auto opCtx = opCtxNoop.get(); +class QueryRequestTest : public ServiceContextTest {}; + +TEST_F(QueryRequestTest, ParseFromUUID) { + auto opCtx = makeOperationContext(); // Register a UUID/Collection pair in the UUIDCatalog. const CollectionUUID uuid = UUID::gen(); const NamespaceString nss("test.testns"); Collection coll(stdx::make_unique<CollectionMock>(nss)); - UUIDCatalog& catalog = UUIDCatalog::get(opCtx); - catalog.onCreateCollection(opCtx, &coll, uuid); + UUIDCatalog& catalog = UUIDCatalog::get(opCtx.get()); + catalog.onCreateCollection(opCtx.get(), &coll, uuid); QueryRequest qr(uuid); // Ensure a call to refreshNSS succeeds. - qr.refreshNSS(opCtx); + qr.refreshNSS(opCtx.get()); ASSERT_EQ(nss, qr.nss()); } diff --git a/src/mongo/db/query/query_test_service_context.cpp b/src/mongo/db/query/query_test_service_context.cpp index d752db15664..490e3aff679 100644 --- a/src/mongo/db/query/query_test_service_context.cpp +++ b/src/mongo/db/query/query_test_service_context.cpp @@ -36,13 +36,15 @@ namespace mongo { -QueryTestServiceContext::QueryTestServiceContext() { - CollatorFactoryInterface::set(&_serviceContext, stdx::make_unique<CollatorFactoryMock>()); - _uniqueClient = _serviceContext.makeClient("QueryTest"); +QueryTestServiceContext::QueryTestServiceContext() + : _service(ServiceContext::make()), _client(_service->makeClient("query_test")) { + CollatorFactoryInterface::set(getServiceContext(), stdx::make_unique<CollatorFactoryMock>()); } +QueryTestServiceContext::~QueryTestServiceContext() = default; + ServiceContext::UniqueOperationContext QueryTestServiceContext::makeOperationContext() { - return _uniqueClient->makeOperationContext(); + return getClient()->makeOperationContext(); } ServiceContext::UniqueOperationContext QueryTestServiceContext::makeOperationContext( @@ -53,7 +55,11 @@ ServiceContext::UniqueOperationContext QueryTestServiceContext::makeOperationCon } Client* QueryTestServiceContext::getClient() const { - return _uniqueClient.get(); + return _client.get(); +} + +ServiceContext* QueryTestServiceContext::getServiceContext() { + return _service.get(); } } // namespace mongo diff --git a/src/mongo/db/query/query_test_service_context.h b/src/mongo/db/query/query_test_service_context.h index c52944cf2f5..05a21afef3f 100644 --- a/src/mongo/db/query/query_test_service_context.h +++ b/src/mongo/db/query/query_test_service_context.h @@ -30,7 +30,7 @@ #include "mongo/db/client.h" #include "mongo/db/logical_session_id.h" -#include "mongo/db/service_context_noop.h" +#include "mongo/db/service_context.h" namespace mongo { @@ -42,20 +42,18 @@ namespace mongo { class QueryTestServiceContext { public: QueryTestServiceContext(); + ~QueryTestServiceContext(); ServiceContext::UniqueOperationContext makeOperationContext(); ServiceContext::UniqueOperationContext makeOperationContext(LogicalSessionId lsid); Client* getClient() const; - - ServiceContext* getServiceContext() { - return &_serviceContext; - } + ServiceContext* getServiceContext(); private: - ServiceContextNoop _serviceContext; - ServiceContext::UniqueClient _uniqueClient; + ServiceContext::UniqueServiceContext _service; + ServiceContext::UniqueClient _client; }; } // namespace mongo diff --git a/src/mongo/db/repl/SConscript b/src/mongo/db/repl/SConscript index 187aa7f366c..ac1d6cb6f04 100644 --- a/src/mongo/db/repl/SConscript +++ b/src/mongo/db/repl/SConscript @@ -796,7 +796,6 @@ env.CppUnitTest( 'topology_coordinator', 'replica_set_messages', '$BUILD_DIR/mongo/db/auth/authmocks', - '$BUILD_DIR/mongo/db/service_context_noop_init', '$BUILD_DIR/mongo/executor/network_interface_factory', '$BUILD_DIR/mongo/executor/network_interface_mock', '$BUILD_DIR/mongo/executor/network_interface_thread_pool', @@ -852,10 +851,10 @@ env.Library( LIBDEPS=[ 'repl_coordinator_impl', 'replmocks', - 'service_context_repl_mock_init', 'topology_coordinator', '$BUILD_DIR/mongo/db/auth/authorization_manager_global', '$BUILD_DIR/mongo/db/auth/authmocks', + '$BUILD_DIR/mongo/db/service_context_d_test_fixture', '$BUILD_DIR/mongo/executor/network_interface_mock', '$BUILD_DIR/mongo/executor/network_interface_factory', '$BUILD_DIR/mongo/executor/network_interface_thread_pool', @@ -863,6 +862,10 @@ env.Library( '$BUILD_DIR/mongo/unittest/unittest', ], + LIBDEPS_PRIVATE=[ + '$BUILD_DIR/mongo/db/storage/ephemeral_for_test/storage_ephemeral_for_test', + '$BUILD_DIR/mongo/db/storage/storage_engine_common', + ], ) env.CppUnitTest( @@ -885,7 +888,6 @@ env.CppUnitTest( 'repl_coordinator_impl', 'replmocks', '$BUILD_DIR/mongo/db/auth/authmocks', - '$BUILD_DIR/mongo/db/service_context_noop_init', ], ) @@ -908,7 +910,6 @@ env.CppUnitTest( LIBDEPS=[ 'repl_coordinator_impl', 'replmocks', - '$BUILD_DIR/mongo/db/service_context_noop_init', '$BUILD_DIR/mongo/db/auth/authmocks', '$BUILD_DIR/mongo/executor/thread_pool_task_executor_test_fixture', ], @@ -923,7 +924,6 @@ env.CppUnitTest( 'repl_coordinator_impl', 'replica_set_messages', 'replmocks', - '$BUILD_DIR/mongo/db/service_context_noop_init', '$BUILD_DIR/mongo/db/auth/authmocks', '$BUILD_DIR/mongo/executor/thread_pool_task_executor_test_fixture', ], @@ -939,7 +939,6 @@ env.CppUnitTest( 'replica_set_messages', 'replmocks', '$BUILD_DIR/mongo/db/auth/authmocks', - '$BUILD_DIR/mongo/db/service_context_noop_init', ], ) @@ -953,7 +952,6 @@ env.CppUnitTest( 'repl_coordinator_impl', 'replica_set_messages', 'replmocks', - '$BUILD_DIR/mongo/db/service_context_noop_init', '$BUILD_DIR/mongo/db/auth/authmocks', '$BUILD_DIR/mongo/executor/thread_pool_task_executor_test_fixture', ], @@ -992,7 +990,6 @@ env.Library( 'replication_consistency_markers_mock.cpp', 'replication_coordinator_external_state_mock.cpp', 'replication_coordinator_mock.cpp', - 'service_context_repl_mock.cpp', 'storage_interface_mock.cpp', ], LIBDEPS=[ @@ -1007,17 +1004,6 @@ env.Library( ], ) -env.Library( - target='service_context_repl_mock_init', - source=[ - 'service_context_repl_mock_init.cpp', - ], - LIBDEPS=[ - 'replmocks', - '$BUILD_DIR/mongo/util/clock_source_mock', - ], -) - env.Library('read_concern_args', [ 'read_concern_args.cpp' @@ -1186,7 +1172,6 @@ env.CppUnitTest( source='oplog_fetcher_test.cpp', LIBDEPS=[ '$BUILD_DIR/mongo/db/auth/authmocks', - '$BUILD_DIR/mongo/db/service_context_noop_init', 'oplog_fetcher', 'data_replicator_external_state_mock', 'abstract_oplog_fetcher_test_fixture', @@ -1215,7 +1200,6 @@ env.CppUnitTest( 'reporter', '$BUILD_DIR/mongo/db/auth/authmocks', '$BUILD_DIR/mongo/executor/thread_pool_task_executor_test_fixture', - '$BUILD_DIR/mongo/db/service_context_noop_init', '$BUILD_DIR/mongo/unittest/task_executor_proxy', ], ) @@ -1300,7 +1284,6 @@ env.CppUnitTest( 'base_cloner_test_fixture', '$BUILD_DIR/mongo/db/auth/authmocks', '$BUILD_DIR/mongo/db/auth/authorization_manager_global', - '$BUILD_DIR/mongo/db/service_context_noop_init', '$BUILD_DIR/mongo/unittest/task_executor_proxy', ], ) @@ -1327,7 +1310,6 @@ env.CppUnitTest( 'base_cloner_test_fixture', '$BUILD_DIR/mongo/db/auth/authmocks', '$BUILD_DIR/mongo/db/commands/list_collections_filter', - '$BUILD_DIR/mongo/db/service_context_noop_init', '$BUILD_DIR/mongo/unittest/task_executor_proxy', ], ) @@ -1351,7 +1333,6 @@ env.CppUnitTest( 'oplog_entry', 'replmocks', '$BUILD_DIR/mongo/db/auth/authmocks', - '$BUILD_DIR/mongo/db/service_context_noop_init', '$BUILD_DIR/mongo/executor/thread_pool_task_executor_test_fixture', '$BUILD_DIR/mongo/unittest/task_executor_proxy', ], @@ -1368,32 +1349,24 @@ env.Library( ], ) -env.Library( - target='task_runner_test_fixture', +env.CppUnitTest( + target='task_runner_test', source=[ + 'task_runner_test.cpp', 'task_runner_test_fixture.cpp', ], LIBDEPS=[ 'replmocks', - 'service_context_repl_mock_init', 'task_runner', '$BUILD_DIR/mongo/db/auth/authmocks', '$BUILD_DIR/mongo/db/auth/authorization_manager_global', - '$BUILD_DIR/mongo/db/service_context', + '$BUILD_DIR/mongo/db/service_context_test_fixture', '$BUILD_DIR/mongo/unittest/concurrency', '$BUILD_DIR/mongo/unittest/unittest', ], ) env.CppUnitTest( - target='task_runner_test', - source='task_runner_test.cpp', - LIBDEPS=[ - 'task_runner_test_fixture', - ], -) - -env.CppUnitTest( target='read_concern_args_test', source=[ 'read_concern_args_test.cpp', @@ -1442,7 +1415,6 @@ env.CppUnitTest( source='multiapplier_test.cpp', LIBDEPS=[ 'multiapplier', - 'service_context_repl_mock_init', '$BUILD_DIR/mongo/db/auth/authmocks', '$BUILD_DIR/mongo/executor/thread_pool_task_executor_test_fixture', '$BUILD_DIR/mongo/unittest/task_executor_proxy', @@ -1533,7 +1505,6 @@ env.CppUnitTest( 'initial_syncer', 'replication_process', 'replmocks', - 'service_context_repl_mock_init', 'sync_source_selector_mock', 'task_executor_mock', ], diff --git a/src/mongo/db/repl/collection_bulk_loader_impl.cpp b/src/mongo/db/repl/collection_bulk_loader_impl.cpp index a8b432e7a7f..b0ccc6dfcc9 100644 --- a/src/mongo/db/repl/collection_bulk_loader_impl.cpp +++ b/src/mongo/db/repl/collection_bulk_loader_impl.cpp @@ -51,40 +51,6 @@ namespace mongo { namespace repl { -namespace { - -/** - * Utility class to temporarily swap which client is bound to the running thread. - * - * Use this class to bind a client to the current thread for the duration of the - * AlternativeClientRegion's lifetime, restoring the prior client, if any, at the - * end of the block. - */ -class AlternativeClientRegion { -public: - explicit AlternativeClientRegion(ServiceContext::UniqueClient& clientToUse) - : _alternateClient(&clientToUse) { - invariant(clientToUse); - if (Client::getCurrent()) { - _originalClient = Client::releaseCurrent(); - } - Client::setCurrent(std::move(*_alternateClient)); - } - - ~AlternativeClientRegion() { - *_alternateClient = Client::releaseCurrent(); - if (_originalClient) { - Client::setCurrent(std::move(_originalClient)); - } - } - -private: - ServiceContext::UniqueClient _originalClient; - ServiceContext::UniqueClient* const _alternateClient; -}; - -} // namespace - CollectionBulkLoaderImpl::CollectionBulkLoaderImpl(ServiceContext::UniqueClient&& client, ServiceContext::UniqueOperationContext&& opCtx, std::unique_ptr<AutoGetCollection>&& autoColl, diff --git a/src/mongo/db/repl/replication_coordinator_impl_test.cpp b/src/mongo/db/repl/replication_coordinator_impl_test.cpp index a3f3c3e2669..d009a9914fc 100644 --- a/src/mongo/db/repl/replication_coordinator_impl_test.cpp +++ b/src/mongo/db/repl/replication_coordinator_impl_test.cpp @@ -56,7 +56,7 @@ #include "mongo/db/repl/topology_coordinator.h" #include "mongo/db/repl/update_position_args.h" #include "mongo/db/server_options.h" -#include "mongo/db/service_context_noop.h" +#include "mongo/db/service_context.h" #include "mongo/db/write_concern_options.h" #include "mongo/executor/network_interface_mock.h" #include "mongo/rpc/metadata/oplog_query_metadata.h" @@ -828,10 +828,6 @@ TEST_F(ReplCoordTest, NodeReturnsWriteConcernFailedUntilASufficientNumberOfNodes TEST_F(ReplCoordTest, NodeReturnsUnknownReplWriteConcernWhenAwaitReplicationReceivesAnInvalidWriteConcernMode) { - auto service = stdx::make_unique<ServiceContextNoop>(); - auto client = service->makeClient("test"); - auto opCtx = client->makeOperationContext(); - assertStartSuccess(BSON("_id" << "mySet" << "version" @@ -861,6 +857,7 @@ TEST_F(ReplCoordTest, invalidWriteConcern.wTimeout = WriteConcernOptions::kNoWaiting; invalidWriteConcern.wMode = "fakemode"; + auto opCtx = makeOperationContext(); ReplicationCoordinator::StatusAndDuration statusAndDur = getReplCoord()->awaitReplication(opCtx.get(), time1, invalidWriteConcern); ASSERT_EQUALS(ErrorCodes::UnknownReplWriteConcern, statusAndDur.status); @@ -869,10 +866,6 @@ TEST_F(ReplCoordTest, TEST_F( ReplCoordTest, NodeReturnsWriteConcernFailedUntilASufficientSetOfNodesHaveTheWriteAndTheWriteIsInACommittedSnapshot) { - auto service = stdx::make_unique<ServiceContextNoop>(); - auto client = service->makeClient("test"); - auto opCtx = client->makeOperationContext(); - assertStartSuccess( BSON("_id" << "mySet" @@ -940,7 +933,7 @@ TEST_F( multiRackWriteConcern.wTimeout = WriteConcernOptions::kNoWaiting; multiRackWriteConcern.wMode = "multiDCAndRack"; - + auto opCtx = makeOperationContext(); // Nothing satisfied getReplCoord()->setMyLastAppliedOpTime(time1); getReplCoord()->setMyLastDurableOpTime(time1); diff --git a/src/mongo/db/repl/replication_coordinator_test_fixture.cpp b/src/mongo/db/repl/replication_coordinator_test_fixture.cpp index db81b8e46d8..7b2defbe0ad 100644 --- a/src/mongo/db/repl/replication_coordinator_test_fixture.cpp +++ b/src/mongo/db/repl/replication_coordinator_test_fixture.cpp @@ -45,6 +45,8 @@ #include "mongo/db/repl/replication_recovery_mock.h" #include "mongo/db/repl/storage_interface_mock.h" #include "mongo/db/repl/topology_coordinator.h" +#include "mongo/db/storage/storage_engine_init.h" +#include "mongo/db/storage/storage_options.h" #include "mongo/executor/network_interface_mock.h" #include "mongo/executor/thread_pool_mock.h" #include "mongo/executor/thread_pool_task_executor.h" @@ -79,12 +81,11 @@ BSONObj ReplCoordTest::addProtocolVersion(const BSONObj& configDoc, int protocol return builder.obj(); } - -void ReplCoordTest::setUp() { +ReplCoordTest::ReplCoordTest() { _settings.setReplSetString("mySet/node1:12345,node2:54321"); } -void ReplCoordTest::tearDown() { +ReplCoordTest::~ReplCoordTest() { getGlobalFailPointRegistry() ->getFailPoint("blockHeartbeatReconfigFinish") ->setMode(FailPoint::off); diff --git a/src/mongo/db/repl/replication_coordinator_test_fixture.h b/src/mongo/db/repl/replication_coordinator_test_fixture.h index 67f30ceeff9..3f0cb66f838 100644 --- a/src/mongo/db/repl/replication_coordinator_test_fixture.h +++ b/src/mongo/db/repl/replication_coordinator_test_fixture.h @@ -33,6 +33,7 @@ #include "mongo/db/client.h" #include "mongo/db/repl/repl_settings.h" #include "mongo/db/repl/replication_coordinator.h" +#include "mongo/db/service_context_d_test_fixture.h" #include "mongo/executor/network_interface_mock.h" #include "mongo/executor/task_executor.h" #include "mongo/unittest/unittest.h" @@ -55,7 +56,7 @@ using executor::NetworkInterfaceMock; /** * Fixture for testing ReplicationCoordinatorImpl behaviors. */ -class ReplCoordTest : public mongo::unittest::Test { +class ReplCoordTest : public ServiceContextMongoDTest { public: /** * Makes a command response with the given "doc" response and optional elapsed time "millis". @@ -81,8 +82,8 @@ public: static BSONObj addProtocolVersion(const BSONObj& configDoc, int protocolVersion); protected: - virtual void setUp(); - virtual void tearDown(); + ReplCoordTest(); + virtual ~ReplCoordTest(); /** * Asserts that calling start(configDoc, selfHost) successfully initiates the @@ -131,27 +132,6 @@ protected: } /** - * Makes a new OperationContext on the default Client for this test. - */ - ServiceContext::UniqueOperationContext makeOperationContext() { - return _client->makeOperationContext(); - } - - /** - * Returns the ServiceContext for this test. - */ - ServiceContext* getServiceContext() { - return getGlobalServiceContext(); - } - - /** - * Returns the default Client for this test. - */ - Client* getClient() { - return _client.get(); - } - - /** * Adds "selfHost" to the list of hosts that identify as "this" host. */ void addSelf(const HostAndPort& selfHost); @@ -298,7 +278,6 @@ private: ReplSettings _settings; bool _callShutdown = false; - ServiceContext::UniqueClient _client = getGlobalServiceContext()->makeClient("testClient"); }; } // namespace repl diff --git a/src/mongo/db/repl/rollback_impl_test.cpp b/src/mongo/db/repl/rollback_impl_test.cpp index 427ff7688a4..8561743e303 100644 --- a/src/mongo/db/repl/rollback_impl_test.cpp +++ b/src/mongo/db/repl/rollback_impl_test.cpp @@ -419,7 +419,7 @@ void _assertDocsInOplog(OperationContext* opCtx, std::vector<int> timestamps) { } TEST_F(RollbackImplTest, TestFixtureSetUpInitializesStorageEngine) { - auto serviceContext = _serviceContextMongoDTest.getServiceContext(); + auto serviceContext = getServiceContext(); ASSERT_TRUE(serviceContext); ASSERT_TRUE(serviceContext->getStorageEngine()); } diff --git a/src/mongo/db/repl/rollback_test_fixture.cpp b/src/mongo/db/repl/rollback_test_fixture.cpp index b0d49b1473a..db6b01e3d02 100644 --- a/src/mongo/db/repl/rollback_test_fixture.cpp +++ b/src/mongo/db/repl/rollback_test_fixture.cpp @@ -68,9 +68,8 @@ ReplSettings createReplSettings() { } // namespace void RollbackTest::setUp() { - _serviceContextMongoDTest.setUp(); _storageInterface = new StorageInterfaceRollback(); - auto serviceContext = _serviceContextMongoDTest.getServiceContext(); + auto serviceContext = getServiceContext(); auto consistencyMarkers = stdx::make_unique<ReplicationConsistencyMarkersMock>(); auto recovery = stdx::make_unique<ReplicationRecoveryImpl>(_storageInterface, consistencyMarkers.get()); @@ -85,7 +84,7 @@ void RollbackTest::setUp() { std::unique_ptr<ReplicationCoordinator>(_coordinator)); setOplogCollectionName(serviceContext); - _opCtx = cc().makeOperationContext(); + _opCtx = makeOperationContext(); _replicationProcess->getConsistencyMarkers()->clearAppliedThrough(_opCtx.get(), {}); _replicationProcess->getConsistencyMarkers()->setMinValid(_opCtx.get(), OpTime{}); _replicationProcess->initializeRollbackID(_opCtx.get()).transitional_ignore(); @@ -95,24 +94,6 @@ void RollbackTest::setUp() { logger::LogComponent::kReplicationRollback, logger::LogSeverity::Debug(2)); } -void RollbackTest::tearDown() { - _coordinator = nullptr; - _opCtx.reset(); - - SessionCatalog::get(_serviceContextMongoDTest.getServiceContext())->reset_forTest(); - - // We cannot unset the global replication coordinator because ServiceContextMongoD::tearDown() - // calls Databse::dropAllDatabasesExceptLocal() which requires the replication coordinator to - // clear all snapshots. - _serviceContextMongoDTest.tearDown(); - - // ServiceContextMongoD::tearDown() does not destroy service context so it is okay - // to access the service context after tearDown(). - auto serviceContext = _serviceContextMongoDTest.getServiceContext(); - _replicationProcess.reset(); - ReplicationCoordinator::set(serviceContext, {}); -} - RollbackTest::ReplicationCoordinatorRollbackMock::ReplicationCoordinatorRollbackMock( ServiceContext* service) : ReplicationCoordinatorMock(service, createReplSettings()) {} diff --git a/src/mongo/db/repl/rollback_test_fixture.h b/src/mongo/db/repl/rollback_test_fixture.h index 4f43fb47945..8d31c63564f 100644 --- a/src/mongo/db/repl/rollback_test_fixture.h +++ b/src/mongo/db/repl/rollback_test_fixture.h @@ -49,7 +49,7 @@ namespace repl { * storage layer. The storage engine is initialized as part of the ServiceContextForMongoD test * fixture. */ -class RollbackTest : public unittest::Test { +class RollbackTest : public ServiceContextMongoDTest { public: RollbackTest() = default; @@ -59,15 +59,6 @@ public: void setUp() override; /** - * Destroys the service context and task executor. - * - * Note on overriding tearDown() in tests: - * This cancels outstanding tasks and remote command requests scheduled using the task - * executor. - */ - void tearDown() override; - - /** * Creates a collection with the given namespace and options. */ static Collection* _createCollection(OperationContext* opCtx, @@ -101,9 +92,6 @@ public: Timestamp ts, OptionalCollectionUUID uuid, StringData nss, BSONObj cmdObj, int recordId); protected: - // Test fixture used to manage the service context and global storage engine. - ServiceContextMongoDTest _serviceContextMongoDTest; - // OperationContext provided to test cases for storage layer operations. ServiceContext::UniqueOperationContext _opCtx; diff --git a/src/mongo/db/repl/rs_rollback_test.cpp b/src/mongo/db/repl/rs_rollback_test.cpp index 4573e277d83..8b254a65988 100644 --- a/src/mongo/db/repl/rs_rollback_test.cpp +++ b/src/mongo/db/repl/rs_rollback_test.cpp @@ -69,23 +69,8 @@ using namespace mongo::repl::rollback_internal; const auto kIndexVersion = IndexDescriptor::IndexVersion::kV2; -class RSRollbackTest : public RollbackTest { -private: - void setUp() override; - void tearDown() override; -}; - -void RSRollbackTest::setUp() { - RollbackTest::setUp(); - auto observerRegistry = stdx::make_unique<OpObserverRegistry>(); - observerRegistry->addObserver(stdx::make_unique<UUIDCatalogObserver>()); - _serviceContextMongoDTest.getServiceContext()->setOpObserver( - std::unique_ptr<OpObserver>(observerRegistry.release())); -} +class RSRollbackTest : public RollbackTest {}; -void RSRollbackTest::tearDown() { - RollbackTest::tearDown(); -} OplogInterfaceMock::Operation makeNoopOplogEntryAndRecordId(Seconds seconds) { OpTime ts(Timestamp(seconds, 0), 0); diff --git a/src/mongo/db/repl/service_context_repl_mock.cpp b/src/mongo/db/repl/service_context_repl_mock.cpp deleted file mode 100644 index c8d87716e8d..00000000000 --- a/src/mongo/db/repl/service_context_repl_mock.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/** - * Copyright (C) 2016 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/platform/basic.h" - -#include "mongo/db/repl/service_context_repl_mock.h" - -#include "mongo/db/concurrency/lock_state.h" -#include "mongo/db/operation_context_noop.h" -#include "mongo/stdx/memory.h" - -namespace mongo { -namespace repl { - -std::unique_ptr<OperationContext> ServiceContextReplMock::_newOpCtx(Client* client, unsigned opId) { - auto opCtx = stdx::make_unique<OperationContextNoop>(client, opId); - opCtx->swapLockState(stdx::make_unique<MMAPV1LockerImpl>()); - return {std::move(opCtx)}; -} - -} // namespace repl -} // namespace mongo diff --git a/src/mongo/db/repl/service_context_repl_mock.h b/src/mongo/db/repl/service_context_repl_mock.h deleted file mode 100644 index 8ffb92a9da1..00000000000 --- a/src/mongo/db/repl/service_context_repl_mock.h +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Copyright (C) 2016 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 "mongo/db/service_context_noop.h" - -namespace mongo { -namespace repl { - -/** - * Testing-only service context that extends ServiceContextNoop so that makeOperationContext() - * returns an instance of OperationContextReplMock. - */ -class ServiceContextReplMock : public ServiceContextNoop { -private: - std::unique_ptr<OperationContext> _newOpCtx(Client* client, unsigned opId) override; -}; - -} // namespace repl -} // namespace mongo diff --git a/src/mongo/db/repl/task_runner_test_fixture.cpp b/src/mongo/db/repl/task_runner_test_fixture.cpp index f16bfa67be0..3e510603d8a 100644 --- a/src/mongo/db/repl/task_runner_test_fixture.cpp +++ b/src/mongo/db/repl/task_runner_test_fixture.cpp @@ -30,7 +30,7 @@ #include "mongo/db/repl/task_runner_test_fixture.h" -#include "mongo/db/operation_context_noop.h" +#include "mongo/db/auth/authorization_manager.h" #include "mongo/db/repl/task_runner.h" #include "mongo/stdx/functional.h" #include "mongo/stdx/memory.h" diff --git a/src/mongo/db/repl/task_runner_test_fixture.h b/src/mongo/db/repl/task_runner_test_fixture.h index 2787419a1e5..9076bea4135 100644 --- a/src/mongo/db/repl/task_runner_test_fixture.h +++ b/src/mongo/db/repl/task_runner_test_fixture.h @@ -31,7 +31,7 @@ #include <memory> #include "mongo/base/status.h" -#include "mongo/db/service_context.h" +#include "mongo/db/service_context_test_fixture.h" #include "mongo/unittest/unittest.h" #include "mongo/util/concurrency/thread_pool.h" @@ -48,7 +48,7 @@ class TaskRunner; * Test fixture for tests that require a TaskRunner and/or * ThreadPool. */ -class TaskRunnerTest : public unittest::Test { +class TaskRunnerTest : public ServiceContextTest { public: static Status getDetectableErrorStatus(); diff --git a/src/mongo/db/s/SConscript b/src/mongo/db/s/SConscript index cb57c8b8456..0af63a22dc6 100644 --- a/src/mongo/db/s/SConscript +++ b/src/mongo/db/s/SConscript @@ -306,6 +306,7 @@ env.CppUnitTest( 'sharding_runtime_d', '$BUILD_DIR/mongo/db/auth/authmocks', '$BUILD_DIR/mongo/db/query/query_request', + '$BUILD_DIR/mongo/db/service_context_d_test_fixture', '$BUILD_DIR/mongo/s/catalog/dist_lock_manager_mock', '$BUILD_DIR/mongo/s/catalog/sharding_catalog_client_impl', '$BUILD_DIR/mongo/s/catalog/sharding_catalog_client_mock', diff --git a/src/mongo/db/s/active_migrations_registry_test.cpp b/src/mongo/db/s/active_migrations_registry_test.cpp index 5450296d505..ba0d148b863 100644 --- a/src/mongo/db/s/active_migrations_registry_test.cpp +++ b/src/mongo/db/s/active_migrations_registry_test.cpp @@ -32,7 +32,7 @@ #include "mongo/bson/bsonobjbuilder.h" #include "mongo/db/client.h" #include "mongo/db/s/active_migrations_registry.h" -#include "mongo/db/service_context_noop.h" +#include "mongo/db/service_context_d_test_fixture.h" #include "mongo/s/request_types/move_chunk_request.h" #include "mongo/unittest/unittest.h" @@ -41,26 +41,8 @@ namespace { using unittest::assertGet; -class MoveChunkRegistration : public unittest::Test { +class MoveChunkRegistration : public ServiceContextMongoDTest { protected: - void setUp() override { - _client = _serviceContext.makeClient("MoveChunkRegistrationTest"); - _opCtx = _serviceContext.makeOperationContext(_client.get()); - } - - void tearDown() override { - _opCtx.reset(); - _client.reset(); - } - - OperationContext* getTxn() const { - return _opCtx.get(); - } - - ServiceContextNoop _serviceContext; - ServiceContext::UniqueClient _client; - ServiceContext::UniqueOperationContext _opCtx; - ActiveMigrationsRegistry _registry; }; @@ -133,8 +115,9 @@ TEST_F(MoveChunkRegistration, SecondMigrationWithSameArgumentsJoinsFirst) { ASSERT(!secondScopedDonateChunk.mustExecute()); originalScopedDonateChunk.signalComplete({ErrorCodes::InternalError, "Test error"}); + auto opCtx = makeOperationContext(); ASSERT_EQ(Status(ErrorCodes::InternalError, "Test error"), - secondScopedDonateChunk.waitForCompletion(getTxn())); + secondScopedDonateChunk.waitForCompletion(opCtx.get())); } } // namespace diff --git a/src/mongo/db/s/active_move_primaries_registry_test.cpp b/src/mongo/db/s/active_move_primaries_registry_test.cpp index b196fdc2621..25c028e3b48 100644 --- a/src/mongo/db/s/active_move_primaries_registry_test.cpp +++ b/src/mongo/db/s/active_move_primaries_registry_test.cpp @@ -29,7 +29,7 @@ #include "mongo/db/s/active_move_primaries_registry.h" #include "mongo/bson/bsonmisc.h" #include "mongo/db/client.h" -#include "mongo/db/service_context_noop.h" +#include "mongo/db/service_context_d_test_fixture.h" #include "mongo/s/request_types/move_primary_gen.h" #include "mongo/unittest/unittest.h" @@ -38,26 +38,8 @@ namespace { using unittest::assertGet; -class MovePrimaryRegistration : public unittest::Test { +class MovePrimaryRegistration : public ServiceContextMongoDTest { protected: - void setUp() override { - _client = _serviceContext.makeClient("MovePrimaryRegistrationTest"); - _opCtx = _serviceContext.makeOperationContext(_client.get()); - } - - void tearDown() override { - _opCtx.reset(); - _client.reset(); - } - - OperationContext* getTxn() const { - return _opCtx.get(); - } - - ServiceContextNoop _serviceContext; - ServiceContext::UniqueClient _client; - ServiceContext::UniqueOperationContext _opCtx; - ActiveMovePrimariesRegistry _registry; }; @@ -120,8 +102,9 @@ TEST_F(MovePrimaryRegistration, SecondMovePrimaryWithSameArgumentsJoinsFirst) { ASSERT(!secondScopedMovePrimary.mustExecute()); originalScopedMovePrimary.signalComplete({ErrorCodes::InternalError, "Test error"}); + auto opCtx = makeOperationContext(); ASSERT_EQ(Status(ErrorCodes::InternalError, "Test error"), - secondScopedMovePrimary.waitForCompletion(getTxn())); + secondScopedMovePrimary.waitForCompletion(opCtx.get())); } } // namespace diff --git a/src/mongo/db/s/migration_chunk_cloner_source_legacy.cpp b/src/mongo/db/s/migration_chunk_cloner_source_legacy.cpp index be6aafbe27f..43144f59b99 100644 --- a/src/mongo/db/s/migration_chunk_cloner_source_legacy.cpp +++ b/src/mongo/db/s/migration_chunk_cloner_source_legacy.cpp @@ -557,7 +557,7 @@ StatusWith<BSONObj> MigrationChunkClonerSourceLegacy::_callRecipient(const BSONO executor::RemoteCommandResponse responseStatus( Status{ErrorCodes::InternalError, "Uninitialized value"}); - auto executor = grid.getExecutorPool()->getFixedExecutor(); + auto executor = Grid::get(getGlobalServiceContext())->getExecutorPool()->getFixedExecutor(); auto scheduleStatus = executor->scheduleRemoteCommand( executor::RemoteCommandRequest(_recipientHost, "admin", cmdObj, nullptr), [&responseStatus](const executor::TaskExecutor::RemoteCommandCallbackArgs& args) { diff --git a/src/mongo/db/s/namespace_metadata_change_notifications_test.cpp b/src/mongo/db/s/namespace_metadata_change_notifications_test.cpp index 155eed7cae3..5e4cde64b6e 100644 --- a/src/mongo/db/s/namespace_metadata_change_notifications_test.cpp +++ b/src/mongo/db/s/namespace_metadata_change_notifications_test.cpp @@ -30,7 +30,8 @@ #include "mongo/db/operation_context_noop.h" #include "mongo/db/s/namespace_metadata_change_notifications.h" -#include "mongo/db/service_context_noop.h" +#include "mongo/db/service_context.h" +#include "mongo/db/service_context_d_test_fixture.h" #include "mongo/stdx/memory.h" #include "mongo/stdx/thread.h" #include "mongo/unittest/unittest.h" @@ -41,23 +42,11 @@ namespace { const NamespaceString kNss("foo.bar"); -class NamespaceMetadataChangeNotificationsTest : public unittest::Test { +class NamespaceMetadataChangeNotificationsTest : public ServiceContextMongoDTest { protected: NamespaceMetadataChangeNotificationsTest() { - _serviceCtx.setTickSource(stdx::make_unique<TickSourceMock>()); + getServiceContext()->setTickSource(stdx::make_unique<TickSourceMock>()); } - - void setUp() override { - _client = _serviceCtx.makeClient("Test"); - } - - Client* client() const { - return _client.get(); - } - -private: - ServiceContextNoop _serviceCtx; - ServiceContext::UniqueClient _client; }; TEST_F(NamespaceMetadataChangeNotificationsTest, WaitForNotify) { @@ -66,7 +55,7 @@ TEST_F(NamespaceMetadataChangeNotificationsTest, WaitForNotify) { auto scopedNotif = notifications.createNotification(kNss); { - auto opCtx = client()->makeOperationContext(); + auto opCtx = getClient()->makeOperationContext(); opCtx->setDeadlineAfterNowBy(Milliseconds{0}); ASSERT_THROWS_CODE( scopedNotif.get(opCtx.get()), AssertionException, ErrorCodes::ExceededTimeLimit); @@ -75,7 +64,7 @@ TEST_F(NamespaceMetadataChangeNotificationsTest, WaitForNotify) { notifications.notifyChange(kNss); { - auto opCtx = client()->makeOperationContext(); + auto opCtx = getClient()->makeOperationContext(); scopedNotif.get(opCtx.get()); } } @@ -86,7 +75,7 @@ TEST_F(NamespaceMetadataChangeNotificationsTest, GiveUpWaitingForNotify) { { auto scopedNotif = notifications.createNotification(kNss); - auto opCtx = client()->makeOperationContext(); + auto opCtx = getClient()->makeOperationContext(); opCtx->setDeadlineAfterNowBy(Milliseconds{0}); ASSERT_THROWS_CODE( scopedNotif.get(opCtx.get()), AssertionException, ErrorCodes::ExceededTimeLimit); @@ -102,7 +91,7 @@ TEST_F(NamespaceMetadataChangeNotificationsTest, MoveConstructionWaitForNotify) auto movedScopedNotif = std::move(scopedNotif); { - auto opCtx = client()->makeOperationContext(); + auto opCtx = getClient()->makeOperationContext(); opCtx->setDeadlineAfterNowBy(Milliseconds{0}); ASSERT_THROWS_CODE( movedScopedNotif.get(opCtx.get()), AssertionException, ErrorCodes::ExceededTimeLimit); @@ -111,7 +100,7 @@ TEST_F(NamespaceMetadataChangeNotificationsTest, MoveConstructionWaitForNotify) notifications.notifyChange(kNss); { - auto opCtx = client()->makeOperationContext(); + auto opCtx = getClient()->makeOperationContext(); movedScopedNotif.get(opCtx.get()); } } diff --git a/src/mongo/db/s/sharding_state.cpp b/src/mongo/db/s/sharding_state.cpp index c45ddb1e71d..d7843fcac26 100644 --- a/src/mongo/db/s/sharding_state.cpp +++ b/src/mongo/db/s/sharding_state.cpp @@ -79,7 +79,8 @@ const auto getShardingState = ServiceContext::declareDecoration<ShardingState>() */ void updateShardIdentityConfigStringCB(const std::string& setName, const std::string& newConnectionString) { - auto configsvrConnStr = grid.shardRegistry()->getConfigServerConnectionString(); + auto configsvrConnStr = + Grid::get(getGlobalServiceContext())->shardRegistry()->getConfigServerConnectionString(); if (configsvrConnStr.getSetName() != setName) { // Ignore all change notification for other sets that are not the config server. return; diff --git a/src/mongo/db/service_context.cpp b/src/mongo/db/service_context.cpp index 92389a0f6a1..a3749d29ce0 100644 --- a/src/mongo/db/service_context.cpp +++ b/src/mongo/db/service_context.cpp @@ -26,19 +26,26 @@ * it in the license file. */ +#define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kDefault + #include "mongo/platform/basic.h" #include "mongo/db/service_context.h" +#include "mongo/base/init.h" #include "mongo/bson/bsonobj.h" #include "mongo/db/client.h" +#include "mongo/db/concurrency/locker_noop.h" #include "mongo/db/op_observer.h" #include "mongo/db/operation_context.h" +#include "mongo/db/storage/recovery_unit_noop.h" +#include "mongo/stdx/list.h" #include "mongo/stdx/memory.h" #include "mongo/transport/service_entry_point.h" #include "mongo/transport/session.h" #include "mongo/transport/transport_layer.h" #include "mongo/util/assert_util.h" +#include "mongo/util/log.h" #include "mongo/util/mongoutils/str.h" #include "mongo/util/system_clock_source.h" #include "mongo/util/system_tick_source.h" @@ -46,9 +53,9 @@ namespace mongo { namespace { +using ConstructorActionList = stdx::list<ServiceContext::ConstructorDestructorActions>; + ServiceContext* globalServiceContext = nullptr; -stdx::mutex globalServiceContextMutex; -stdx::condition_variable globalServiceContextCV; } // namespace @@ -61,26 +68,12 @@ ServiceContext* getGlobalServiceContext() { return globalServiceContext; } -ServiceContext* waitAndGetGlobalServiceContext() { - stdx::unique_lock<stdx::mutex> lk(globalServiceContextMutex); - globalServiceContextCV.wait(lk, [] { return globalServiceContext; }); - fassert(40549, globalServiceContext); - return globalServiceContext; -} - -void setGlobalServiceContext(std::unique_ptr<ServiceContext>&& serviceContext) { +void setGlobalServiceContext(ServiceContext::UniqueServiceContext&& serviceContext) { if (globalServiceContext) { // Make sure that calling getGlobalServiceContext() during the destructor results in // nullptr. Decorations might try and do this. - auto oldServiceContext = globalServiceContext; + ServiceContext::UniqueServiceContext oldServiceContext{globalServiceContext}; globalServiceContext = nullptr; - delete oldServiceContext; - } - - stdx::lock_guard<stdx::mutex> lk(globalServiceContextMutex); - - if (!globalServiceContext) { - globalServiceContextCV.notify_all(); } globalServiceContext = serviceContext.release(); @@ -106,28 +99,70 @@ ServiceContext::ServiceContext() ServiceContext::~ServiceContext() { stdx::lock_guard<stdx::mutex> lk(_mutex); + for (const auto& client : _clients) { + severe() << "Client " << client->desc() << " still exists while destroying ServiceContext@" + << static_cast<void*>(this); + } invariant(_clients.empty()); } -ServiceContext::UniqueClient ServiceContext::makeClient(std::string desc, - transport::SessionHandle session) { - std::unique_ptr<Client> client(new Client(std::move(desc), this, std::move(session))); - auto observer = _clientObservers.cbegin(); +namespace { + +// +// These onDestroy and onCreate functions are utilities for correctly executing supplemental +// constructor and destructor methods for the ServiceContext, Client and OperationContext types. +// +// Note that destructors run in reverse order of constructors, and that failed construction +// leads to corresponding destructors to run, similarly to how member variable construction and +// destruction behave. +// + +template <typename T, typename ObserversIterator> +void onDestroy(T* object, + const ObserversIterator& observerBegin, + const ObserversIterator& observerEnd) { try { - for (; observer != _clientObservers.cend(); ++observer) { - observer->get()->onCreateClient(client.get()); + auto observer = observerEnd; + while (observer != observerBegin) { + --observer; + observer->onDestroy(object); } } catch (...) { - try { - while (observer != _clientObservers.cbegin()) { - --observer; - observer->get()->onDestroyClient(client.get()); - } - } catch (...) { - std::terminate(); + std::terminate(); + } +} +template <typename T, typename ObserversContainer> +void onDestroy(T* object, const ObserversContainer& observers) { + onDestroy(object, observers.cbegin(), observers.cend()); +} + +template <typename T, typename ObserversIterator> +void onCreate(T* object, + const ObserversIterator& observerBegin, + const ObserversIterator& observerEnd) { + auto observer = observerBegin; + try { + for (; observer != observerEnd; ++observer) { + observer->onCreate(object); } + } catch (...) { + onDestroy(object, observerBegin, observer); throw; } +} + +template <typename T, typename ObserversContainer> +void onCreate(T* object, const ObserversContainer& observers) { + onCreate(object, observers.cbegin(), observers.cend()); +} + + +} // namespace + +ServiceContext::UniqueClient ServiceContext::makeClient(std::string desc, + transport::SessionHandle session) { + std::unique_ptr<Client> client(new Client(std::move(desc), this, std::move(session))); + onCreate(client.get(), _clientObservers); { stdx::lock_guard<stdx::mutex> lk(_mutex); invariant(_clients.insert(client.get()).second); @@ -196,33 +231,19 @@ void ServiceContext::ClientDeleter::operator()(Client* client) const { stdx::lock_guard<stdx::mutex> lk(service->_mutex); invariant(service->_clients.erase(client)); } - try { - for (const auto& observer : service->_clientObservers) { - observer->onDestroyClient(client); - } - } catch (...) { - std::terminate(); - } + onDestroy(client, service->_clientObservers); delete client; } ServiceContext::UniqueOperationContext ServiceContext::makeOperationContext(Client* client) { - auto opCtx = _newOpCtx(client, _nextOpId.fetchAndAdd(1)); - auto observer = _clientObservers.begin(); - try { - for (; observer != _clientObservers.cend(); ++observer) { - observer->get()->onCreateOperationContext(opCtx.get()); - } - } catch (...) { - try { - while (observer != _clientObservers.cbegin()) { - --observer; - observer->get()->onDestroyOperationContext(opCtx.get()); - } - } catch (...) { - std::terminate(); - } - throw; + auto opCtx = std::make_unique<OperationContext>(client, _nextOpId.fetchAndAdd(1)); + onCreate(opCtx.get(), _clientObservers); + if (!opCtx->lockState()) { + opCtx->setLockState(std::make_unique<LockerNoop>()); + } + if (!opCtx->recoveryUnit()) { + opCtx->setRecoveryUnit(new RecoveryUnitNoop(), + WriteUnitOfWork::RecoveryUnitState::kNotInUnitOfWork); } { stdx::lock_guard<Client> lk(*client); @@ -238,18 +259,12 @@ void ServiceContext::OperationContextDeleter::operator()(OperationContext* opCtx stdx::lock_guard<Client> lk(*client); client->resetOperationContext(); } - try { - for (const auto& observer : service->_clientObservers) { - observer->onDestroyOperationContext(opCtx); - } - } catch (...) { - std::terminate(); - } + onDestroy(opCtx, service->_clientObservers); delete opCtx; } void ServiceContext::registerClientObserver(std::unique_ptr<ClientObserver> observer) { - _clientObservers.push_back(std::move(observer)); + _clientObservers.emplace_back(std::move(observer)); } ServiceContext::LockedClientsCursor::LockedClientsCursor(ServiceContext* service) @@ -339,4 +354,72 @@ void ServiceContext::notifyStartupComplete() { _startupCompleteCondVar.notify_all(); } +namespace { + +// clang-format off +GlobalInitializerRegisterer registerCreateServiceContext{ + "ServiceContext", + {"default"}, + [](InitializerContext* context) { + setGlobalServiceContext(ServiceContext::make()); + return Status::OK(); + }, + [](DeinitializerContext* context) { + // For now, deregistration is done manually after all deinitializers run, in case any + // erroneously access the globalServiceContext without expressing a dependency. + return Status::OK(); + } +}; +// clang-format on + +/** + * Accessor function to get the global list of ServiceContext constructor and destructor + * functions. + */ +ConstructorActionList& registeredConstructorActions() { + static ConstructorActionList cal; + return cal; +} + +} // namespace + +ServiceContext::ConstructorActionRegisterer::ConstructorActionRegisterer( + std::string name, ConstructorAction constructor, DestructorAction destructor) + : ConstructorActionRegisterer( + std::move(name), {}, std::move(constructor), std::move(destructor)) {} + +ServiceContext::ConstructorActionRegisterer::ConstructorActionRegisterer( + std::string name, + std::vector<std::string> prereqs, + ConstructorAction constructor, + DestructorAction destructor) { + if (!destructor) + destructor = [](ServiceContext*) {}; + _registerer.emplace(std::move(name), + std::move(prereqs), + std::vector<std::string>{"ServiceContext"}, + [this, constructor, destructor](InitializerContext* context) { + _iter = registeredConstructorActions().emplace( + registeredConstructorActions().end(), + std::move(constructor), + std::move(destructor)); + return Status::OK(); + }, + [this](DeinitializerContext* context) { + registeredConstructorActions().erase(_iter); + return Status::OK(); + }); +} + +ServiceContext::UniqueServiceContext ServiceContext::make() { + auto service = std::make_unique<ServiceContext>(); + onCreate(service.get(), registeredConstructorActions()); + return UniqueServiceContext{service.release()}; +} + +void ServiceContext::ServiceContextDeleter::operator()(ServiceContext* service) const { + onDestroy(service, registeredConstructorActions()); + delete service; +} + } // namespace mongo diff --git a/src/mongo/db/service_context.h b/src/mongo/db/service_context.h index 73b272470e6..24905f2fc4d 100644 --- a/src/mongo/db/service_context.h +++ b/src/mongo/db/service_context.h @@ -28,14 +28,17 @@ #pragma once +#include <boost/optional.hpp> #include <vector> #include "mongo/base/disallow_copying.h" +#include "mongo/base/global_initializer_registerer.h" #include "mongo/db/logical_session_id.h" #include "mongo/db/storage/storage_engine.h" #include "mongo/platform/atomic_word.h" #include "mongo/stdx/condition_variable.h" #include "mongo/stdx/functional.h" +#include "mongo/stdx/list.h" #include "mongo/stdx/memory.h" #include "mongo/stdx/mutex.h" #include "mongo/stdx/unordered_set.h" @@ -89,20 +92,11 @@ protected: * A ServiceContext is the root of a hierarchy of contexts. A ServiceContext owns * zero or more Clients, which in turn each own OperationContexts. */ -class ServiceContext : public Decorable<ServiceContext> { +class ServiceContext final : public Decorable<ServiceContext> { MONGO_DISALLOW_COPYING(ServiceContext); public: /** - * Special deleter used for cleaning up Client objects owned by a ServiceContext. - * See UniqueClient, below. - */ - class ClientDeleter { - public: - void operator()(Client* client) const; - }; - - /** * Observer interface implemented to hook client and operation context creation and * destruction. */ @@ -172,12 +166,23 @@ public: }; /** - * Special deleter used for cleaning up OperationContext objects owned by a ServiceContext. - * See UniqueOperationContext, below. + * Special deleter used for cleaning up ServiceContext objects. + * See UniqueServiceContext, below. */ - class OperationContextDeleter { + class ServiceContextDeleter { public: - void operator()(OperationContext* opCtx) const; + void operator()(ServiceContext* service) const; + }; + + using UniqueServiceContext = std::unique_ptr<ServiceContext, ServiceContextDeleter>; + + /** + * Special deleter used for cleaning up Client objects owned by a ServiceContext. + * See UniqueClient, below. + */ + class ClientDeleter { + public: + void operator()(Client* client) const; }; /** @@ -186,11 +191,96 @@ public: using UniqueClient = std::unique_ptr<Client, ClientDeleter>; /** + * Special deleter used for cleaning up OperationContext objects owned by a ServiceContext. + * See UniqueOperationContext, below. + */ + class OperationContextDeleter { + public: + void operator()(OperationContext* opCtx) const; + }; + + /** * This is the unique handle type for OperationContexts created by a ServiceContext. */ using UniqueOperationContext = std::unique_ptr<OperationContext, OperationContextDeleter>; - virtual ~ServiceContext(); + /** + * Register a function of this type using an instance of ConstructorActionRegisterer, + * below, to cause the function to be executed on new ServiceContext instances. + */ + using ConstructorAction = stdx::function<void(ServiceContext*)>; + + /** + * Register a function of this type using an instance of ConstructorActionRegisterer, + * below, to cause the function to be executed on ServiceContext instances before they + * are destroyed. + */ + using DestructorAction = stdx::function<void(ServiceContext*) noexcept>; + + /** + * Representation of a paired ConstructorAction and DestructorAction. + */ + class ConstructorDestructorActions { + public: + ConstructorDestructorActions(ConstructorAction constructor, DestructorAction destructor) + : _constructor(std::move(constructor)), _destructor(std::move(destructor)) {} + + void onCreate(ServiceContext* service) const { + _constructor(service); + } + void onDestroy(ServiceContext* service) const { + _destructor(service); + } + + private: + ConstructorAction _constructor; + DestructorAction _destructor; + }; + + /** + * Registers a function to execute on new service contexts when they are created, and optionally + * also register a function to execute before those contexts are destroyed. + * + * Construct instances of this type during static initialization only, as they register + * MONGO_INITIALIZERS. + */ + class ConstructorActionRegisterer { + public: + /** + * This constructor registers a constructor and optional destructor with the given + * "name" and no prerequisite constructors or mongo initializers. + */ + ConstructorActionRegisterer(std::string name, + ConstructorAction constructor, + DestructorAction destructor = {}); + + /** + * This constructor registers a constructor and optional destructor with the given + * "name", and a list of names of prerequisites, "prereqs". + * + * The named constructor will run after all of its prereqs successfully complete, + * and the corresponding destructor, if provided, will run before any of its + * prerequisites execute. + */ + ConstructorActionRegisterer(std::string name, + std::vector<std::string> prereqs, + ConstructorAction constructor, + DestructorAction destructor = {}); + + private: + using ConstructorActionListIterator = stdx::list<ConstructorDestructorActions>::iterator; + ConstructorActionListIterator _iter; + boost::optional<GlobalInitializerRegisterer> _registerer; + }; + + /** + * Factory function for making instances of ServiceContext. It is the only means by which they + * should be created. + */ + static UniqueServiceContext make(); + + ServiceContext(); + ~ServiceContext(); /** * Registers an observer of lifecycle events on Clients created by this ServiceContext. @@ -411,20 +501,29 @@ public: */ void setServiceExecutor(std::unique_ptr<transport::ServiceExecutor> exec); -protected: - ServiceContext(); +private: + class ClientObserverHolder { + public: + explicit ClientObserverHolder(std::unique_ptr<ClientObserver> observer) + : _observer(std::move(observer)) {} + void onCreate(Client* client) const { + _observer->onCreateClient(client); + } + void onDestroy(Client* client) const { + _observer->onDestroyClient(client); + } + void onCreate(OperationContext* opCtx) const { + _observer->onCreateOperationContext(opCtx); + } + void onDestroy(OperationContext* opCtx) const { + _observer->onDestroyOperationContext(opCtx); + } - /** - * Mutex used to synchronize access to mutable state of this ServiceContext instance, - * including possibly by its subclasses. - */ - stdx::mutex _mutex; + private: + std::unique_ptr<ClientObserver> _observer; + }; -private: - /** - * Returns a new OperationContext. Private, for use by makeOperationContext. - */ - virtual std::unique_ptr<OperationContext> _newOpCtx(Client* client, unsigned opId) = 0; + stdx::mutex _mutex; /** * The storage engine, if any. @@ -454,7 +553,7 @@ private: /** * Vector of registered observers. */ - std::vector<std::unique_ptr<ClientObserver>> _clientObservers; + std::vector<ClientObserverHolder> _clientObservers; ClientSet _clients; /** @@ -503,23 +602,12 @@ bool hasGlobalServiceContext(); ServiceContext* getGlobalServiceContext(); /** - * Warning - This function is temporary. Do not introduce new uses of this API. - * - * Returns the singleton ServiceContext for this server process. - * - * Waits until there is a valid global ServiceContext. - * - * Caller does not own pointer. - */ -ServiceContext* waitAndGetGlobalServiceContext(); - -/** * Sets the global ServiceContext. If 'serviceContext' is NULL, un-sets and deletes * the current global ServiceContext. * * Takes ownership of 'serviceContext'. */ -void setGlobalServiceContext(std::unique_ptr<ServiceContext>&& serviceContext); +void setGlobalServiceContext(ServiceContext::UniqueServiceContext&& serviceContext); /** * Shortcut for querying the storage engine about whether it supports document-level locking. diff --git a/src/mongo/db/service_context_d.cpp b/src/mongo/db/service_context_d.cpp deleted file mode 100644 index b4595b97c98..00000000000 --- a/src/mongo/db/service_context_d.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/** - * Copyright (C) 2014 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/service_context_d.h" - -#include "mongo/base/init.h" -#include "mongo/base/initializer.h" -#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" -#include "mongo/db/storage/storage_engine_metadata.h" -#include "mongo/db/storage/storage_options.h" -#include "mongo/stdx/memory.h" -#include "mongo/util/log.h" -#include "mongo/util/map_util.h" -#include "mongo/util/mongoutils/str.h" -#include "mongo/util/scopeguard.h" -#include "mongo/util/system_clock_source.h" -#include "mongo/util/system_tick_source.h" - -namespace mongo { -namespace { -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; -}); -} // namespace - -extern bool _supportsDocLocking; - -ServiceContextMongoD::ServiceContextMongoD() = default; - -ServiceContextMongoD::~ServiceContextMongoD() = default; - -std::unique_ptr<OperationContext> ServiceContextMongoD::_newOpCtx(Client* client, unsigned opId) { - invariant(&cc() == client); - auto opCtx = stdx::make_unique<OperationContext>(client, opId); - - if (isMMAPV1()) { - opCtx->setLockState(stdx::make_unique<MMAPV1LockerImpl>()); - } else { - opCtx->setLockState(stdx::make_unique<DefaultLockerImpl>()); - } - - opCtx->setRecoveryUnit(getStorageEngine()->newRecoveryUnit(), - WriteUnitOfWork::RecoveryUnitState::kNotInUnitOfWork); - return opCtx; -} - -} // namespace mongo diff --git a/src/mongo/db/service_context_d.h b/src/mongo/db/service_context_d.h deleted file mode 100644 index dfab1926390..00000000000 --- a/src/mongo/db/service_context_d.h +++ /dev/null @@ -1,48 +0,0 @@ -/** - * Copyright (C) 2014 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 "mongo/db/service_context.h" - -namespace mongo { - -class Client; -class StorageEngineLockFile; - -class ServiceContextMongoD final : public ServiceContext { -public: - ServiceContextMongoD(); - - ~ServiceContextMongoD(); - -private: - std::unique_ptr<OperationContext> _newOpCtx(Client* client, unsigned opId) override; -}; - -} // 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 ae0e39a2ab4..3ae23161235 100644 --- a/src/mongo/db/service_context_d_test_fixture.cpp +++ b/src/mongo/db/service_context_d_test_fixture.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) 2016 MongoDB Inc. + * Copyright (C) 2016-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, @@ -30,48 +30,40 @@ #include "mongo/db/service_context_d_test_fixture.h" +#include <memory> + #include "mongo/base/checked_cast.h" -#include "mongo/db/catalog/database.h" -#include "mongo/db/catalog/database_holder.h" +#include "mongo/db/catalog/catalog_control.h" #include "mongo/db/catalog/uuid_catalog.h" -#include "mongo/db/client.h" -#include "mongo/db/concurrency/write_conflict_exception.h" -#include "mongo/db/curop.h" -#include "mongo/db/db_raii.h" +#include "mongo/db/concurrency/d_concurrency.h" #include "mongo/db/logical_clock.h" -#include "mongo/db/op_observer_noop.h" #include "mongo/db/op_observer_registry.h" -#include "mongo/db/service_context_d.h" +#include "mongo/db/service_entry_point_mongod.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" #include "mongo/util/assert_util.h" -#include "mongo/util/scopeguard.h" namespace mongo { -void ServiceContextMongoDTest::setUp() { - Test::setUp(); - Client::initThread(getThreadName()); +ServiceContextMongoDTest::ServiceContextMongoDTest() + : ServiceContextMongoDTest("ephemeralForTest") {} - auto const serviceContext = getServiceContext(); +ServiceContextMongoDTest::ServiceContextMongoDTest(std::string engine) { - auto logicalClock = stdx::make_unique<LogicalClock>(serviceContext); + _stashedStorageParams.engine = std::exchange(storageGlobalParams.engine, std::move(engine)); + _stashedStorageParams.engineSetByUser = + std::exchange(storageGlobalParams.engineSetByUser, true); + + auto const serviceContext = getServiceContext(); + serviceContext->setServiceEntryPoint(std::make_unique<ServiceEntryPointMongod>(serviceContext)); + auto logicalClock = std::make_unique<LogicalClock>(serviceContext); LogicalClock::set(serviceContext, std::move(logicalClock)); - if (!serviceContext->getStorageEngine()) { - // When using the "ephemeralForTest" storage engine, it is fine for the temporary directory - // to go away after the global storage engine is initialized. - unittest::TempDir tempDir("service_context_d_test_fixture"); - storageGlobalParams.dbpath = tempDir.path(); - storageGlobalParams.engine = "ephemeralForTest"; - storageGlobalParams.engineSetByUser = true; + unittest::TempDir tempDir("service_context_d_test_fixture"); + storageGlobalParams.dbpath = tempDir.path(); - createLockFile(serviceContext); - initializeStorageEngine(serviceContext, StorageEngineInitFlags::kNone); - serviceContext->setOpObserver(stdx::make_unique<OpObserverNoop>()); - } + initializeStorageEngine(serviceContext, StorageEngineInitFlags::kNone); // Set up UUID Catalog observer. This is necessary because the Collection destructor contains an // invariant to ensure the UUID corresponding to that Collection object is no longer associated @@ -79,44 +71,19 @@ void ServiceContextMongoDTest::setUp() { // directly in certain code paths, but they can only be removed from the UUIDCatalog via a // UUIDCatalogObserver. It is therefore necessary to install the observer to ensure the // invariant in the Collection destructor is not triggered. - auto observerRegistry = stdx::make_unique<OpObserverRegistry>(); - observerRegistry->addObserver(stdx::make_unique<UUIDCatalogObserver>()); - serviceContext->setOpObserver(std::unique_ptr<OpObserver>(observerRegistry.release())); -} - -void ServiceContextMongoDTest::tearDown() { - ON_BLOCK_EXIT([&] { Client::destroy(); }); - auto opCtx = cc().makeOperationContext(); - _dropAllDBs(opCtx.get()); - Test::tearDown(); + auto observerRegistry = checked_cast<OpObserverRegistry*>(serviceContext->getOpObserver()); + observerRegistry->addObserver(std::make_unique<UUIDCatalogObserver>()); } -ServiceContext* ServiceContextMongoDTest::getServiceContext() { - return getGlobalServiceContext(); -} - -void ServiceContextMongoDTest::_doTest() { - MONGO_UNREACHABLE; -} - -void ServiceContextMongoDTest::_dropAllDBs(OperationContext* opCtx) { - Database::dropAllDatabasesExceptLocal(opCtx); - - Lock::GlobalWrite lk(opCtx); - AutoGetDb autoDBLocal(opCtx, "local", MODE_X); - const auto localDB = autoDBLocal.getDb(); - if (localDB) { - writeConflictRetry(opCtx, "_dropAllDBs", "local", [&] { - // Do not wrap in a WriteUnitOfWork until SERVER-17103 is addressed. - autoDBLocal.getDb()->dropDatabase(opCtx, localDB); - }); +ServiceContextMongoDTest::~ServiceContextMongoDTest() { + { + auto opCtx = getClient()->makeOperationContext(); + Lock::GlobalLock glk(opCtx.get(), MODE_X); + catalog::closeCatalog(opCtx.get()); } - - // Database::dropAllDatabasesExceptLocal() does not close empty databases. However the holder - // still allocates resources to track these empty databases. These resources not released by - // Database::dropAllDatabasesExceptLocal() will be leaked at exit unless we call - // DatabaseHolder::closeAll. - DatabaseHolder::getDatabaseHolder().closeAll(opCtx, "all databases dropped"); + shutdownGlobalStorageEngineCleanly(getGlobalServiceContext()); + std::swap(storageGlobalParams.engine, _stashedStorageParams.engine); + std::swap(storageGlobalParams.engineSetByUser, _stashedStorageParams.engineSetByUser); } } // namespace mongo diff --git a/src/mongo/db/service_context_d_test_fixture.h b/src/mongo/db/service_context_d_test_fixture.h index bd56f4f2ae6..19619f0d0fe 100644 --- a/src/mongo/db/service_context_d_test_fixture.h +++ b/src/mongo/db/service_context_d_test_fixture.h @@ -1,5 +1,5 @@ /** - * Copyright (C) 2016 MongoDB Inc. + * Copyright (C) 2016-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, @@ -29,7 +29,7 @@ #pragma once #include "mongo/db/operation_context.h" -#include "mongo/db/service_context.h" +#include "mongo/db/service_context_test_fixture.h" #include "mongo/unittest/unittest.h" namespace mongo { @@ -37,40 +37,21 @@ namespace mongo { /** * Test fixture class for tests that use the "ephemeralForTest" storage engine. */ -class ServiceContextMongoDTest : public unittest::Test { -public: - /** - * Initializes global storage engine. - */ - void setUp() override; - - /** - * Clear all databases. - */ - void tearDown() override; +class ServiceContextMongoDTest : public ServiceContextTest { +protected: + ServiceContextMongoDTest(); /** - * Returns a service context, which is only valid for this instance of the test. - * Must not be called before setUp or after tearDown. + * Build a ServiceContextMongoDTest, using the named storage engine. */ - ServiceContext* getServiceContext(); + explicit ServiceContextMongoDTest(std::string engine); + virtual ~ServiceContextMongoDTest(); private: - /** - * Unused implementation of test function. This allows us to instantiate - * ServiceContextMongoDTest on its own without the need to inherit from it in a test. - * This supports using ServiceContextMongoDTest inside another test fixture and works around the - * limitation that tests cannot inherit from multiple test fixtures. - * - * It is an error to call this implementation of _doTest() directly. - */ - void _doTest() override; - - /** - * Drops all databases. Call this before global ReplicationCoordinator is destroyed -- it is - * used to drop the databases. - */ - void _dropAllDBs(OperationContext* opCtx); + struct { + std::string engine; + bool engineSetByUser; + } _stashedStorageParams; }; } // namespace mongo diff --git a/src/mongo/db/service_context_devnull_test_fixture.cpp b/src/mongo/db/service_context_devnull_test_fixture.cpp index e3d47823733..6bd2ea21b5b 100644 --- a/src/mongo/db/service_context_devnull_test_fixture.cpp +++ b/src/mongo/db/service_context_devnull_test_fixture.cpp @@ -30,41 +30,9 @@ #include "mongo/db/service_context_devnull_test_fixture.h" -#include "mongo/db/client.h" -#include "mongo/db/operation_context.h" -#include "mongo/db/service_context.h" -#include "mongo/db/service_context_d.h" -#include "mongo/db/storage/storage_engine_init.h" -#include "mongo/stdx/memory.h" -#include "mongo/unittest/temp_dir.h" -#include "mongo/util/assert_util.h" - namespace mongo { -void ServiceContextDevnullTestFixture::setUp() { - Test::setUp(); - Client::initThread(getThreadName()); - - auto const serviceContext = getServiceContext(); - if (!serviceContext->getStorageEngine()) { - // When using the 'devnull' storage engine, it is fine for the temporary directory to - // go away after the global storage engine is initialized. - unittest::TempDir tempDir("service_context_devnull_test"); - mongo::storageGlobalParams.dbpath = tempDir.path(); - mongo::storageGlobalParams.engine = "devnull"; - mongo::storageGlobalParams.engineSetByUser = true; - createLockFile(serviceContext); - initializeStorageEngine(serviceContext, StorageEngineInitFlags::kNone); - } -} - -void ServiceContextDevnullTestFixture::tearDown() { - Client::destroy(); - Test::tearDown(); -} - -ServiceContext* ServiceContextDevnullTestFixture::getServiceContext() { - return getGlobalServiceContext(); -} +ServiceContextDevnullTestFixture::ServiceContextDevnullTestFixture() + : ServiceContextMongoDTest("devnull") {} } // namespace mongo diff --git a/src/mongo/db/service_context_devnull_test_fixture.h b/src/mongo/db/service_context_devnull_test_fixture.h index 77a0d551965..1304546f903 100644 --- a/src/mongo/db/service_context_devnull_test_fixture.h +++ b/src/mongo/db/service_context_devnull_test_fixture.h @@ -28,30 +28,16 @@ #pragma once -#include "mongo/unittest/unittest.h" +#include "mongo/db/service_context_d_test_fixture.h" namespace mongo { -class ServiceContext; - /** * Test fixture class for mongod tests that use the "devnull" storage engine. */ -class ServiceContextDevnullTestFixture : public unittest::Test { -public: - /** - * Initializes the devnull engine as the global storage engine. - * Also sets up a Client on the thread, which can be accessed via 'cc()'. - */ - void setUp() override; - - void tearDown() override; - - /** - * Returns a service context, which is only valid for this instance of the test. - * Must not be called before setUp() or after tearDown(). - */ - ServiceContext* getServiceContext(); +class ServiceContextDevnullTestFixture : public ServiceContextMongoDTest { +protected: + ServiceContextDevnullTestFixture(); }; } // namespace mongo diff --git a/src/mongo/db/service_context_noop.cpp b/src/mongo/db/service_context_noop.cpp deleted file mode 100644 index e2cc4b7d41e..00000000000 --- a/src/mongo/db/service_context_noop.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/** - * Copyright (C) 2014 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/platform/basic.h" - -#include "mongo/db/service_context_noop.h" - -#include "mongo/db/operation_context_noop.h" -#include "mongo/stdx/memory.h" - -namespace mongo { - -std::unique_ptr<OperationContext> ServiceContextNoop::_newOpCtx(Client* client, unsigned opId) { - return stdx::make_unique<OperationContextNoop>(client, opId); -} - -} // namespace mongo diff --git a/src/mongo/db/service_context_noop.h b/src/mongo/db/service_context_noop.h deleted file mode 100644 index 77e8119accd..00000000000 --- a/src/mongo/db/service_context_noop.h +++ /dev/null @@ -1,40 +0,0 @@ -/** - * Copyright (C) 2014 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 "mongo/db/service_context.h" - -namespace mongo { - -class ServiceContextNoop : public ServiceContext { -private: - std::unique_ptr<OperationContext> _newOpCtx(Client* client, unsigned opId) override; -}; - -} // namespace mongo diff --git a/src/mongo/db/service_context_noop_init.cpp b/src/mongo/db/service_context_noop_init.cpp deleted file mode 100644 index 27e4306ad49..00000000000 --- a/src/mongo/db/service_context_noop_init.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2015 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/platform/basic.h" - -#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 { - -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 deleted file mode 100644 index 061936c98ec..00000000000 --- a/src/mongo/db/service_context_registrar.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/** - * 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/platform/basic.h" - -#include "mongo/db/service_context_registrar.h" - -#include "mongo/base/init.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; -} - -// clang-format off -GlobalInitializerRegisterer registerCreateServiceContext{ - "ServiceContext", - {"default"}, - [](InitializerContext* context) { - // Set the global service context if a service context factory was previously registered. - if (getServiceContextFactory()) { - setGlobalServiceContext(getServiceContextFactory()()); - } - return Status::OK(); - }, - [](DeinitializerContext* context) { - // For now, deregistration is done manually after all deinitializers run, in case any - // erroneously access the globalServiceContext without expressing a dependency. - return Status::OK(); - } -}; -// clang-format on - -} // namespace - -ServiceContextRegistrar::ServiceContextRegistrar( - std::function<std::unique_ptr<ServiceContext>()> fn) { - invariant(!getServiceContextFactory()); - getServiceContextFactory() = std::move(fn); -} - -} // namespace mongo diff --git a/src/mongo/db/service_context_registrar.h b/src/mongo/db/service_context_registrar.h deleted file mode 100644 index 72f6e6ea2dd..00000000000 --- a/src/mongo/db/service_context_registrar.h +++ /dev/null @@ -1,46 +0,0 @@ -/** -* 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); -}; - -} // namespace mongo diff --git a/src/mongo/db/repl/service_context_repl_mock_init.cpp b/src/mongo/db/service_context_test_fixture.cpp index c35b47f61d7..486478f56e6 100644 --- a/src/mongo/db/repl/service_context_repl_mock_init.cpp +++ b/src/mongo/db/service_context_test_fixture.cpp @@ -1,5 +1,5 @@ -/* - * Copyright (C) 2016 MongoDB Inc. +/** + * Copyright (C) 2016-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, @@ -28,22 +28,35 @@ #include "mongo/platform/basic.h" -#include "mongo/base/init.h" -#include "mongo/db/repl/service_context_repl_mock.h" -#include "mongo/db/service_context.h" -#include "mongo/db/service_context_registrar.h" -#include "mongo/util/clock_source_mock.h" +#include "mongo/db/service_context_test_fixture.h" #include <memory> +#include "mongo/db/client.h" +#include "mongo/db/op_observer_registry.h" +#include "mongo/util/assert_util.h" + namespace mongo { -namespace repl { -namespace { -ServiceContextRegistrar serviceContextCreator([]() { - return std::make_unique<ServiceContextReplMock>(); -}); +ServiceContextTest::ServiceContextTest() { + setGlobalServiceContext(ServiceContext::make()); + auto const serviceContext = getGlobalServiceContext(); + Client::initThread(getThreadName()); + auto observerRegistry = std::make_unique<OpObserverRegistry>(); + serviceContext->setOpObserver(std::move(observerRegistry)); +} + +ServiceContextTest::~ServiceContextTest() { + Client::destroy(); + setGlobalServiceContext({}); +} + +ServiceContext* ServiceContextTest::getServiceContext() { + return getGlobalServiceContext(); +} + +Client* ServiceContextTest::getClient() { + return Client::getCurrent(); +} -} // namespace -} // namespace repl } // namespace mongo diff --git a/src/mongo/embedded/service_context_embedded.h b/src/mongo/db/service_context_test_fixture.h index 3f697ec9a91..1e23c6666d2 100644 --- a/src/mongo/embedded/service_context_embedded.h +++ b/src/mongo/db/service_context_test_fixture.h @@ -1,5 +1,5 @@ /** - * Copyright (C) 2018 MongoDB Inc. + * Copyright (C) 2016-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, @@ -28,21 +28,35 @@ #pragma once +#include "mongo/db/operation_context.h" #include "mongo/db/service_context.h" +#include "mongo/unittest/unittest.h" namespace mongo { -class Client; -class StorageEngineLockFile; - -class ServiceContextMongoEmbedded final : public ServiceContext { +/** + * Test fixture for tests that require a properly initialized global service context. + */ +class ServiceContextTest : public unittest::Test { public: - ServiceContextMongoEmbedded(); - - ~ServiceContextMongoEmbedded(); - -private: - std::unique_ptr<OperationContext> _newOpCtx(Client* client, unsigned opId) override; + /** + * Returns a service context, which is only valid for this instance of the test. + * Must not be called before setUp or after tearDown. + */ + ServiceContext* getServiceContext(); + + /** + * Returns the default Client for this test. + */ + Client* getClient(); + + ServiceContext::UniqueOperationContext makeOperationContext() { + return getClient()->makeOperationContext(); + } + +protected: + ServiceContextTest(); + virtual ~ServiceContextTest(); }; } // namespace mongo diff --git a/src/mongo/db/service_liaison_mock.h b/src/mongo/db/service_liaison_mock.h index 26aaf611589..177f0f8ba7c 100644 --- a/src/mongo/db/service_liaison_mock.h +++ b/src/mongo/db/service_liaison_mock.h @@ -29,7 +29,6 @@ #pragma once #include "mongo/db/service_context.h" -#include "mongo/db/service_context_noop.h" #include "mongo/db/service_liaison.h" #include "mongo/executor/async_timer_mock.h" #include "mongo/platform/atomic_word.h" @@ -132,7 +131,7 @@ protected: private: std::shared_ptr<MockServiceLiaisonImpl> _impl; - std::unique_ptr<ServiceContextNoop> _serviceContext; + ServiceContext::UniqueServiceContext _serviceContext; }; } // namespace mongo diff --git a/src/mongo/db/sorter/sorter_test.cpp b/src/mongo/db/sorter/sorter_test.cpp index 6fb550b24cd..3d9fc03b58f 100644 --- a/src/mongo/db/sorter/sorter_test.cpp +++ b/src/mongo/db/sorter/sorter_test.cpp @@ -36,9 +36,6 @@ #include "mongo/base/init.h" #include "mongo/base/static_assert.h" #include "mongo/config.h" -#include "mongo/db/service_context.h" -#include "mongo/db/service_context_noop.h" -#include "mongo/db/service_context_registrar.h" #include "mongo/platform/random.h" #include "mongo/stdx/thread.h" #include "mongo/unittest/temp_dir.h" @@ -55,14 +52,6 @@ using namespace mongo::sorter; using std::make_shared; using std::pair; -namespace { - -// Stub to avoid including the server environment library. -ServiceContextRegistrar serviceContextCreator([]() { - return std::make_unique<ServiceContextNoop>(); -}); -} // namespace - // // Sorter framework testing utilities // diff --git a/src/mongo/db/storage/SConscript b/src/mongo/db/storage/SConscript index 398007c45fa..0a2e629e9b6 100644 --- a/src/mongo/db/storage/SConscript +++ b/src/mongo/db/storage/SConscript @@ -199,6 +199,7 @@ env.Library( ], LIBDEPS_PRIVATE=[ '$BUILD_DIR/mongo/db/service_context', + '$BUILD_DIR/mongo/db/concurrency/lock_manager', 'storage_engine_lock_file', 'storage_engine_metadata', 'storage_options', diff --git a/src/mongo/db/storage/devnull/devnull_init.cpp b/src/mongo/db/storage/devnull/devnull_init.cpp index 68e80902d29..e6272dbb163 100644 --- a/src/mongo/db/storage/devnull/devnull_init.cpp +++ b/src/mongo/db/storage/devnull/devnull_init.cpp @@ -31,7 +31,6 @@ #include "mongo/base/init.h" #include "mongo/db/service_context.h" -#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" @@ -65,10 +64,8 @@ public: }; } // namespace -MONGO_INITIALIZER_WITH_PREREQUISITES(DevNullEngineInit, ("ServiceContext")) -(InitializerContext* context) { - registerStorageEngine(getGlobalServiceContext(), - std::make_unique<DevNullStorageEngineFactory>()); - return Status::OK(); -} +ServiceContext::ConstructorActionRegisterer registerDevNull( + "RegisterDevNullEngine", [](ServiceContext* service) { + registerStorageEngine(service, std::make_unique<DevNullStorageEngineFactory>()); + }); } // namespace mongo diff --git a/src/mongo/db/storage/encryption_hooks.cpp b/src/mongo/db/storage/encryption_hooks.cpp index ffa7f319a06..c703c80fda4 100644 --- a/src/mongo/db/storage/encryption_hooks.cpp +++ b/src/mongo/db/storage/encryption_hooks.cpp @@ -40,30 +40,21 @@ namespace mongo { -/* Make a EncryptionHooks pointer a decoration on the global ServiceContext */ -GlobalInitializerRegisterer encryptionHooksInitializer( - "SetEncryptionHooks", - {"ServiceContext"}, - [](InitializerContext* context) { - EncryptionHooks::set(getGlobalServiceContext(), stdx::make_unique<EncryptionHooks>()); - return Status::OK(); - }, - [](DeinitializerContext* context) { - EncryptionHooks::set(getGlobalServiceContext(), nullptr); - return Status::OK(); - }); - namespace { -const auto getEncryptionHooks = - ServiceContext::declareDecoration<std::unique_ptr<EncryptionHooks>>(); + +struct EncryptionHooksHolder { + std::unique_ptr<EncryptionHooks> ptr = std::make_unique<EncryptionHooks>(); +}; + +const auto getEncryptionHooks = ServiceContext::declareDecoration<EncryptionHooksHolder>(); } // namespace void EncryptionHooks::set(ServiceContext* service, std::unique_ptr<EncryptionHooks> custHooks) { - getEncryptionHooks(service) = std::move(custHooks); + getEncryptionHooks(service).ptr = std::move(custHooks); } EncryptionHooks* EncryptionHooks::get(ServiceContext* service) { - return getEncryptionHooks(service).get(); + return getEncryptionHooks(service).ptr.get(); } EncryptionHooks::~EncryptionHooks() {} diff --git a/src/mongo/db/storage/ephemeral_for_test/SConscript b/src/mongo/db/storage/ephemeral_for_test/SConscript index 0b1c846d3a6..add504fffc0 100644 --- a/src/mongo/db/storage/ephemeral_for_test/SConscript +++ b/src/mongo/db/storage/ephemeral_for_test/SConscript @@ -80,6 +80,5 @@ env.CppUnitTest( ], LIBDEPS_PRIVATE=[ '$BUILD_DIR/mongo/db/auth/authmocks', - '$BUILD_DIR/mongo/db/repl/service_context_repl_mock_init', ], ) 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 a4de16caf63..fa23b283c3a 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 @@ -29,7 +29,6 @@ #include "mongo/platform/basic.h" -#include "mongo/base/init.h" #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" @@ -69,12 +68,10 @@ public: } }; -} // namespace - -MONGO_INITIALIZER_WITH_PREREQUISITES(EphemeralForTestEngineInit, ("ServiceContext")) -(InitializerContext* context) { - registerStorageEngine(getGlobalServiceContext(), std::make_unique<EphemeralForTestFactory>()); - return Status::OK(); -} +ServiceContext::ConstructorActionRegisterer registerEphemeralForTest( + "RegisterEphemeralForTestEngine", [](ServiceContext* service) { + registerStorageEngine(service, std::make_unique<EphemeralForTestFactory>()); + }); +} // namespace } // namespace mongo diff --git a/src/mongo/db/storage/kv/SConscript b/src/mongo/db/storage/kv/SConscript index d8e8f7665f7..7edb39d2366 100644 --- a/src/mongo/db/storage/kv/SConscript +++ b/src/mongo/db/storage/kv/SConscript @@ -96,6 +96,7 @@ env.Library( ], LIBDEPS=[ '$BUILD_DIR/mongo/db/service_context', + '$BUILD_DIR/mongo/db/service_context_test_fixture', '$BUILD_DIR/mongo/db/storage/storage_options', '$BUILD_DIR/mongo/unittest/unittest', '$BUILD_DIR/mongo/util/clock_source_mock', @@ -113,7 +114,6 @@ env.CppUnitTest( 'kv_engine_mock', '$BUILD_DIR/mongo/db/catalog/collection_options', '$BUILD_DIR/mongo/db/namespace_string', - '$BUILD_DIR/mongo/db/service_context_noop_init', '$BUILD_DIR/mongo/db/storage/devnull/storage_devnull_core', '$BUILD_DIR/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_record_store', ], @@ -131,7 +131,6 @@ env.CppUnitTest( 'kv_engine_mock', '$BUILD_DIR/mongo/db/catalog/collection_options', '$BUILD_DIR/mongo/db/namespace_string', - '$BUILD_DIR/mongo/db/service_context_noop_init', '$BUILD_DIR/mongo/db/storage/devnull/storage_devnull_core', '$BUILD_DIR/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_record_store', ], diff --git a/src/mongo/db/storage/kv/kv_engine_test_timestamps.cpp b/src/mongo/db/storage/kv/kv_engine_test_timestamps.cpp index 0e8384a4afe..d2c24f3b44e 100644 --- a/src/mongo/db/storage/kv/kv_engine_test_timestamps.cpp +++ b/src/mongo/db/storage/kv/kv_engine_test_timestamps.cpp @@ -35,7 +35,7 @@ #include "mongo/db/operation_context_noop.h" #include "mongo/db/repl/read_concern_level.h" #include "mongo/db/repl/replication_coordinator.h" -#include "mongo/db/service_context_noop.h" +#include "mongo/db/service_context_test_fixture.h" #include "mongo/db/storage/kv/kv_engine.h" #include "mongo/db/storage/record_store.h" #include "mongo/db/storage/snapshot_manager.h" @@ -46,7 +46,7 @@ namespace mongo { namespace { -class SnapshotManagerTests : public unittest::Test { +class SnapshotManagerTests : public ServiceContextTest { public: /** * Usable as an OperationContext* but owns both the Client and the OperationContext. @@ -89,7 +89,8 @@ public: }; Operation makeOperation() { - return Operation(service.makeClient(""), helper->getEngine()->newRecoveryUnit()); + return Operation(getServiceContext()->makeClient(""), + helper->getEngine()->newRecoveryUnit()); } // Returns the timestamp before incrementing. @@ -200,7 +201,6 @@ public: ASSERT(rs); } - ServiceContextNoop service; std::unique_ptr<KVHarnessHelper> helper; KVEngine* engine; SnapshotManager* snapshotManager; diff --git a/src/mongo/db/storage/kv/kv_storage_engine_test.cpp b/src/mongo/db/storage/kv/kv_storage_engine_test.cpp index 4330a4906fa..e9d6c0accab 100644 --- a/src/mongo/db/storage/kv/kv_storage_engine_test.cpp +++ b/src/mongo/db/storage/kv/kv_storage_engine_test.cpp @@ -28,6 +28,7 @@ #include "mongo/platform/basic.h" +#include "mongo/base/checked_cast.h" #include "mongo/base/status_with.h" #include "mongo/bson/bsonobjbuilder.h" #include "mongo/db/db_raii.h" @@ -48,21 +49,13 @@ #include "mongo/unittest/unittest.h" namespace mongo { +namespace { -class KVStorageEngineTest : public unittest::Test { +class KVStorageEngineTest : public ServiceContextMongoDTest { public: KVStorageEngineTest() - : _storageEngine(stdx::make_unique<KVStorageEngine>(new EphemeralForTestEngine(), - KVStorageEngineOptions())) {} - - void setUp() final { - _serviceContext.setUp(); - } - - void tearDown() final { - _storageEngine->cleanShutdown(); - _serviceContext.tearDown(); - } + : ServiceContextMongoDTest("ephemeralForTest"), + _storageEngine(checked_cast<KVStorageEngine*>(getServiceContext()->getStorageEngine())) {} /** * Create a collection in the catalog and in the KVEngine. Return the storage engine's `ident`. @@ -134,8 +127,7 @@ public: return Status::OK(); } - ServiceContextMongoDTest _serviceContext; - std::unique_ptr<KVStorageEngine> _storageEngine; + KVStorageEngine* _storageEngine; }; TEST_F(KVStorageEngineTest, ReconcileIdentsTest) { @@ -229,4 +221,6 @@ TEST_F(KVStorageEngineTest, RecreateIndexes) { return str.find("index-") == 0; })); } + +} // namespace } // namespace mongo diff --git a/src/mongo/db/storage/mobile/SConscript b/src/mongo/db/storage/mobile/SConscript index 5ff2276f1c0..5d627509ffd 100644 --- a/src/mongo/db/storage/mobile/SConscript +++ b/src/mongo/db/storage/mobile/SConscript @@ -92,6 +92,5 @@ env.CppUnitTest( ], LIBDEPS_PRIVATE=[ '$BUILD_DIR/mongo/db/auth/authmocks', - '$BUILD_DIR/mongo/db/repl/service_context_repl_mock_init', ], ) diff --git a/src/mongo/db/storage/mobile/mobile_init.cpp b/src/mongo/db/storage/mobile/mobile_init.cpp index 41a5dc83159..76e863993de 100644 --- a/src/mongo/db/storage/mobile/mobile_init.cpp +++ b/src/mongo/db/storage/mobile/mobile_init.cpp @@ -69,15 +69,10 @@ public: return BSONObj(); } }; -} // namespace - -GlobalInitializerRegisterer mobileKVEngineInitializer( - "MobileKVEngineInit", - {"ServiceContext"}, - [](InitializerContext* context) { - registerStorageEngine(getGlobalServiceContext(), std::make_unique<MobileFactory>()); - return Status::OK(); - }, - [](DeinitializerContext* const) { return Status::OK(); }); +ServiceContext::ConstructorActionRegisterer mobileKVEngineInitializer{ + "MobileKVEngineInit", [](ServiceContext* service) { + registerStorageEngine(service, std::make_unique<MobileFactory>()); + }}; +} // namespace } // namespace mongo diff --git a/src/mongo/db/storage/record_store_test_harness.h b/src/mongo/db/storage/record_store_test_harness.h index 8b6e35faf19..3f94ad76ad2 100644 --- a/src/mongo/db/storage/record_store_test_harness.h +++ b/src/mongo/db/storage/record_store_test_harness.h @@ -33,7 +33,7 @@ #include <cstdint> #include "mongo/db/operation_context_noop.h" -#include "mongo/db/service_context_noop.h" +#include "mongo/db/service_context.h" #include "mongo/db/storage/test_harness_helper.h" #include "mongo/stdx/memory.h" diff --git a/src/mongo/db/storage/sorted_data_interface_test_harness.h b/src/mongo/db/storage/sorted_data_interface_test_harness.h index 5966755397e..40b18e1ab56 100644 --- a/src/mongo/db/storage/sorted_data_interface_test_harness.h +++ b/src/mongo/db/storage/sorted_data_interface_test_harness.h @@ -35,7 +35,6 @@ #include "mongo/db/operation_context_noop.h" #include "mongo/db/record_id.h" #include "mongo/db/service_context.h" -#include "mongo/db/service_context_noop.h" #include "mongo/db/storage/sorted_data_interface.h" #include "mongo/db/storage/test_harness_helper.h" #include "mongo/stdx/memory.h" 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 diff --git a/src/mongo/db/storage/storage_engine_init.h b/src/mongo/db/storage/storage_engine_init.h index 1cf30ff43ad..47e57d5b5cd 100644 --- a/src/mongo/db/storage/storage_engine_init.h +++ b/src/mongo/db/storage/storage_engine_init.h @@ -56,12 +56,6 @@ void initializeStorageEngine(ServiceContext* service, StorageEngineInitFlags ini 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, diff --git a/src/mongo/db/storage/test_harness_helper.cpp b/src/mongo/db/storage/test_harness_helper.cpp index 62d99709c29..99f3b023847 100644 --- a/src/mongo/db/storage/test_harness_helper.cpp +++ b/src/mongo/db/storage/test_harness_helper.cpp @@ -37,15 +37,24 @@ namespace mongo { namespace { stdx::function<std::unique_ptr<HarnessHelper>()> basicHarnessFactory; } // namespace -} // namespace mongo -mongo::HarnessHelper::~HarnessHelper() = default; +HarnessHelper::HarnessHelper() { + setGlobalServiceContext(ServiceContext::make()); + Client::initThread(getThreadName()); +} + +HarnessHelper::~HarnessHelper() { + Client::destroy(); + setGlobalServiceContext({}); +} -void mongo::registerHarnessHelperFactory(stdx::function<std::unique_ptr<HarnessHelper>()> factory) { +void registerHarnessHelperFactory(stdx::function<std::unique_ptr<HarnessHelper>()> factory) { basicHarnessFactory = std::move(factory); } -auto mongo::newHarnessHelper() -> std::unique_ptr<HarnessHelper> { +auto newHarnessHelper() -> std::unique_ptr<HarnessHelper> { return basicHarnessFactory(); } + +} // namespace mongo diff --git a/src/mongo/db/storage/test_harness_helper.h b/src/mongo/db/storage/test_harness_helper.h index c0891f0235d..e21947e917c 100644 --- a/src/mongo/db/storage/test_harness_helper.h +++ b/src/mongo/db/storage/test_harness_helper.h @@ -36,7 +36,6 @@ #include "mongo/db/operation_context_noop.h" #include "mongo/db/record_id.h" #include "mongo/db/service_context.h" -#include "mongo/db/service_context_noop.h" #include "mongo/db/storage/sorted_data_interface.h" #include "mongo/stdx/functional.h" #include "mongo/stdx/memory.h" @@ -54,9 +53,9 @@ namespace mongo { */ class HarnessHelper { public: - virtual ~HarnessHelper() = 0; + virtual ~HarnessHelper(); - explicit HarnessHelper() = default; + explicit HarnessHelper(); virtual ServiceContext::UniqueOperationContext newOperationContext(Client* const client) { auto opCtx = client->makeOperationContext(); @@ -66,26 +65,22 @@ public: } virtual ServiceContext::UniqueOperationContext newOperationContext() { - return newOperationContext(_client.get()); + return newOperationContext(client()); } Client* client() const { - return _client.get(); + return Client::getCurrent(); } ServiceContext* serviceContext() { - return &_serviceContext; + return getGlobalServiceContext(); } const ServiceContext* serviceContext() const { - return &_serviceContext; + return getGlobalServiceContext(); } virtual std::unique_ptr<RecoveryUnit> newRecoveryUnit() = 0; - -private: - ServiceContextNoop _serviceContext; - ServiceContext::UniqueClient _client = _serviceContext.makeClient("hh"); }; namespace harness_helper_detail { diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_customization_hooks.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_customization_hooks.cpp index 3d4d7ccb3cf..edc40080909 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_customization_hooks.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_customization_hooks.cpp @@ -37,17 +37,14 @@ #include "mongo/stdx/memory.h" namespace mongo { +namespace { -/* Make a WiredTigerCustomizationHooks pointer a decoration on the global ServiceContext */ -MONGO_INITIALIZER_WITH_PREREQUISITES(SetWiredTigerCustomizationHooks, ("ServiceContext")) -(InitializerContext* context) { - auto customizationHooks = stdx::make_unique<WiredTigerCustomizationHooks>(); - WiredTigerCustomizationHooks::set(getGlobalServiceContext(), std::move(customizationHooks)); - - return Status::OK(); -} +ServiceContext::ConstructorActionRegisterer setWiredTigerCustomizationHooks{ + "SetWiredTigerCustomizationHooks", [](ServiceContext* service) { + auto customizationHooks = stdx::make_unique<WiredTigerCustomizationHooks>(); + WiredTigerCustomizationHooks::set(service, std::move(customizationHooks)); + }}; -namespace { const auto getCustomizationHooks = ServiceContext::declareDecoration<std::unique_ptr<WiredTigerCustomizationHooks>>(); } // namespace diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_extensions.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_extensions.cpp index b2df3f8c99c..c6e04dc0483 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_extensions.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_extensions.cpp @@ -31,35 +31,18 @@ #include "mongo/db/storage/wiredtiger/wiredtiger_extensions.h" -#include "mongo/base/init.h" #include "mongo/base/string_data.h" #include "mongo/db/service_context.h" #include "mongo/stdx/memory.h" namespace mongo { -MONGO_INITIALIZER_WITH_PREREQUISITES(SetWiredTigerExtensions, ("ServiceContext")) -(InitializerContext* context) { - auto configHooks = stdx::make_unique<WiredTigerExtensions>(); - WiredTigerExtensions::set(getGlobalServiceContext(), std::move(configHooks)); - - return Status::OK(); -} - namespace { -const auto getConfigHooks = - ServiceContext::declareDecoration<std::unique_ptr<WiredTigerExtensions>>(); +const auto getConfigHooks = ServiceContext::declareDecoration<WiredTigerExtensions>(); } // namespace -void WiredTigerExtensions::set(ServiceContext* service, - std::unique_ptr<WiredTigerExtensions> configHooks) { - auto& hooks = getConfigHooks(service); - invariant(configHooks); - hooks = std::move(configHooks); -} - WiredTigerExtensions* WiredTigerExtensions::get(ServiceContext* service) { - return getConfigHooks(service).get(); + return &getConfigHooks(service); } std::string WiredTigerExtensions::getOpenExtensionsConfig() const { diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_extensions.h b/src/mongo/db/storage/wiredtiger/wiredtiger_extensions.h index ba73a7ff060..94767a08c9b 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_extensions.h +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_extensions.h @@ -39,8 +39,6 @@ class ServiceContext; class WiredTigerExtensions { public: - static void set(ServiceContext* service, std::unique_ptr<WiredTigerExtensions> custHooks); - static WiredTigerExtensions* get(ServiceContext* service); /** diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_init.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_init.cpp index 9408642b210..9290b113405 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_init.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_init.cpp @@ -39,7 +39,6 @@ #include "mongo/db/catalog/collection_options.h" #include "mongo/db/jsobj.h" #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" @@ -179,11 +178,10 @@ public: return true; } }; -} // namespace -MONGO_INITIALIZER_WITH_PREREQUISITES(WiredTigerEngineInit, ("ServiceContext")) -(InitializerContext* context) { - registerStorageEngine(getGlobalServiceContext(), std::make_unique<WiredTigerFactory>()); - return Status::OK(); -} -} +ServiceContext::ConstructorActionRegisterer registerWiredTiger( + "WiredTigerEngineInit", [](ServiceContext* service) { + registerStorageEngine(service, std::make_unique<WiredTigerFactory>()); + }); +} // namespace +} // namespace 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 118471655ad..2eb689e642d 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store_mock.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store_mock.cpp @@ -34,8 +34,6 @@ #include "mongo/base/init.h" #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 <memory> @@ -52,8 +50,5 @@ MONGO_INITIALIZER(SetInitRsOplogBackgroundThreadCallback)(InitializerContext* co return Status::OK(); } -ServiceContextRegistrar serviceContextCreator([]() { - return std::make_unique<ServiceContextNoop>(); -}); } // namespace } // namespace mongo diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_standard_record_store_test.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_standard_record_store_test.cpp index 5433a581a02..479bd470bf5 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_standard_record_store_test.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_standard_record_store_test.cpp @@ -69,14 +69,7 @@ using std::stringstream; class WiredTigerHarnessHelper final : public RecordStoreHarnessHelper { public: - WiredTigerHarnessHelper() - : _dbpath("wt_test"), - _engine(kWiredTigerEngineName, _dbpath.path(), &_cs, "", 1, false, false, false, false) { - repl::ReplicationCoordinator::set( - getGlobalServiceContext(), - std::unique_ptr<repl::ReplicationCoordinator>(new repl::ReplicationCoordinatorMock( - getGlobalServiceContext(), repl::ReplSettings()))); - } + WiredTigerHarnessHelper() : WiredTigerHarnessHelper(""_sd) {} WiredTigerHarnessHelper(StringData extraStrings) : _dbpath("wt_test"), @@ -88,8 +81,11 @@ public: false, false, false, - false) {} - + false) { + repl::ReplicationCoordinator::set(serviceContext(), + std::make_unique<repl::ReplicationCoordinatorMock>( + serviceContext(), repl::ReplSettings())); + } ~WiredTigerHarnessHelper() {} diff --git a/src/mongo/db/update/SConscript b/src/mongo/db/update/SConscript index 37895498200..405f3a5bb9c 100644 --- a/src/mongo/db/update/SConscript +++ b/src/mongo/db/update/SConscript @@ -120,7 +120,6 @@ env.CppUnitTest( '$BUILD_DIR/mongo/db/logical_clock', '$BUILD_DIR/mongo/db/query/collation/collator_interface_mock', '$BUILD_DIR/mongo/db/query/query_test_service_context', - '$BUILD_DIR/mongo/db/service_context_noop_init', 'update', ], ) diff --git a/src/mongo/db/update/object_replace_node_test.cpp b/src/mongo/db/update/object_replace_node_test.cpp index 27bb8aea7b3..e3cff950dcd 100644 --- a/src/mongo/db/update/object_replace_node_test.cpp +++ b/src/mongo/db/update/object_replace_node_test.cpp @@ -34,7 +34,6 @@ #include "mongo/bson/mutable/mutable_bson_test_utils.h" #include "mongo/db/json.h" #include "mongo/db/logical_clock.h" -#include "mongo/db/service_context_noop.h" #include "mongo/db/update/update_node_test_fixture.h" #include "mongo/unittest/unittest.h" diff --git a/src/mongo/db/update/update_node_test_fixture.h b/src/mongo/db/update/update_node_test_fixture.h index 7a3e47636c1..050c9444e75 100644 --- a/src/mongo/db/update/update_node_test_fixture.h +++ b/src/mongo/db/update/update_node_test_fixture.h @@ -29,7 +29,7 @@ #pragma once #include "mongo/db/logical_clock.h" -#include "mongo/db/service_context_noop.h" +#include "mongo/db/service_context.h" #include "mongo/db/update/update_node.h" #include "mongo/unittest/unittest.h" diff --git a/src/mongo/db/views/SConscript b/src/mongo/db/views/SConscript index 95300503828..b03379bd81a 100644 --- a/src/mongo/db/views/SConscript +++ b/src/mongo/db/views/SConscript @@ -46,7 +46,6 @@ env.CppUnitTest( '$BUILD_DIR/mongo/db/auth/authmocks', '$BUILD_DIR/mongo/db/query/collation/collator_interface_mock', '$BUILD_DIR/mongo/db/query/query_test_service_context', - '$BUILD_DIR/mongo/db/service_context_noop_init', '$BUILD_DIR/mongo/db/repl/replmocks', '$BUILD_DIR/mongo/s/is_mongos', '$BUILD_DIR/mongo/unittest/unittest', diff --git a/src/mongo/db/views/view_catalog_test.cpp b/src/mongo/db/views/view_catalog_test.cpp index e4e5061a21c..ac22a1b6247 100644 --- a/src/mongo/db/views/view_catalog_test.cpp +++ b/src/mongo/db/views/view_catalog_test.cpp @@ -44,7 +44,7 @@ #include "mongo/db/repl/replication_coordinator_mock.h" #include "mongo/db/repl/storage_interface_mock.h" #include "mongo/db/server_options.h" -#include "mongo/db/service_context_noop.h" +#include "mongo/db/service_context.h" #include "mongo/db/views/durable_view_catalog.h" #include "mongo/db/views/view.h" #include "mongo/db/views/view_catalog.h" diff --git a/src/mongo/dbtests/dbtests.cpp b/src/mongo/dbtests/dbtests.cpp index 2aff3249936..a0823458812 100644 --- a/src/mongo/dbtests/dbtests.cpp +++ b/src/mongo/dbtests/dbtests.cpp @@ -49,8 +49,7 @@ #include "mongo/db/repl/replication_coordinator_mock.h" #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/service_entry_point_mongod.h" #include "mongo/db/wire_version.h" #include "mongo/dbtests/framework.h" #include "mongo/scripting/engine.h" @@ -171,6 +170,7 @@ int dbtestsMain(int argc, char** argv, char** envp) { repl::ReplSettings replSettings; replSettings.setOplogSizeBytes(10 * 1024 * 1024); ServiceContext* service = getGlobalServiceContext(); + service->setServiceEntryPoint(std::make_unique<ServiceEntryPointMongod>(service)); auto logicalClock = stdx::make_unique<LogicalClock>(service); LogicalClock::set(service, std::move(logicalClock)); diff --git a/src/mongo/dbtests/framework.cpp b/src/mongo/dbtests/framework.cpp index 0a9d923eb4e..66713babef9 100644 --- a/src/mongo/dbtests/framework.cpp +++ b/src/mongo/dbtests/framework.cpp @@ -43,7 +43,6 @@ #include "mongo/db/op_observer_registry.h" #include "mongo/db/s/sharding_state.h" #include "mongo/db/service_context.h" -#include "mongo/db/service_context_d.h" #include "mongo/db/storage/storage_engine_init.h" #include "mongo/dbtests/dbtests.h" #include "mongo/dbtests/framework_options.h" @@ -90,7 +89,6 @@ int runDbTests(int argc, char** argv) { srand((unsigned)frameworkGlobalParams.seed); - createLockFile(globalServiceContext); initializeStorageEngine(globalServiceContext, StorageEngineInitFlags::kNone); auto registry = stdx::make_unique<OpObserverRegistry>(); registry->addObserver(stdx::make_unique<UUIDCatalogObserver>()); diff --git a/src/mongo/dbtests/indexupdatetests.cpp b/src/mongo/dbtests/indexupdatetests.cpp index e7926489671..697a8ce1abd 100644 --- a/src/mongo/dbtests/indexupdatetests.cpp +++ b/src/mongo/dbtests/indexupdatetests.cpp @@ -40,7 +40,6 @@ #include "mongo/db/dbdirectclient.h" #include "mongo/db/index/index_descriptor.h" #include "mongo/db/service_context.h" -#include "mongo/db/service_context_d.h" #include "mongo/db/storage/storage_engine_init.h" #include "mongo/dbtests/dbtests.h" diff --git a/src/mongo/dbtests/querytests.cpp b/src/mongo/dbtests/querytests.cpp index 6cda42ae07f..d954cf9d727 100644 --- a/src/mongo/dbtests/querytests.cpp +++ b/src/mongo/dbtests/querytests.cpp @@ -46,7 +46,6 @@ #include "mongo/db/namespace_string.h" #include "mongo/db/query/find.h" #include "mongo/db/service_context.h" -#include "mongo/db/service_context_d.h" #include "mongo/dbtests/dbtests.h" #include "mongo/util/timer.h" @@ -702,7 +701,7 @@ public: // Check number of results and filterSet flag in explain. // filterSet is not available in oplog replay mode. BSONObj explainObj = c->next(); - ASSERT(explainObj.hasField("executionStats")); + ASSERT(explainObj.hasField("executionStats")) << explainObj; BSONObj execStats = explainObj["executionStats"].Obj(); ASSERT_EQUALS(1, execStats.getIntField("nReturned")); diff --git a/src/mongo/dbtests/validate_tests.cpp b/src/mongo/dbtests/validate_tests.cpp index 818ae60ee0b..28d4f5e8498 100644 --- a/src/mongo/dbtests/validate_tests.cpp +++ b/src/mongo/dbtests/validate_tests.cpp @@ -38,7 +38,6 @@ #include "mongo/db/dbdirectclient.h" #include "mongo/db/index/index_descriptor.h" #include "mongo/db/service_context.h" -#include "mongo/db/service_context_d.h" #include "mongo/dbtests/dbtests.h" namespace ValidateTests { diff --git a/src/mongo/embedded/SConscript b/src/mongo/embedded/SConscript index 0cfb20659f8..73dc960d1c3 100644 --- a/src/mongo/embedded/SConscript +++ b/src/mongo/embedded/SConscript @@ -21,7 +21,6 @@ env.Library( 'embedded_options_parser_init.cpp', 'index_create_impl_embedded.cpp', 'replication_coordinator_embedded.cpp', - 'service_context_embedded.cpp', 'service_entry_point_embedded.cpp', ], LIBDEPS=[ diff --git a/src/mongo/embedded/embedded.cpp b/src/mongo/embedded/embedded.cpp index a548a6922e2..a7c5c6c719d 100644 --- a/src/mongo/embedded/embedded.cpp +++ b/src/mongo/embedded/embedded.cpp @@ -50,14 +50,12 @@ #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/storage/encryption_hooks.h" #include "mongo/db/storage/storage_engine_init.h" #include "mongo/db/ttl.h" #include "mongo/embedded/replication_coordinator_embedded.h" -#include "mongo/embedded/service_context_embedded.h" #include "mongo/embedded/service_entry_point_embedded.h" #include "mongo/logger/log_component.h" #include "mongo/scripting/dbdirectclient_factory.h" @@ -98,11 +96,10 @@ 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. -GlobalInitializerRegisterer replicationManagerInitializer( +ServiceContext::ConstructorActionRegisterer replicationManagerInitializer( "CreateReplicationManager", - {"SSLManager", "ServiceContext", "default"}, - [](InitializerContext* context) { - auto serviceContext = getGlobalServiceContext(); + {"SSLManager", "default"}, + [](ServiceContext* serviceContext) { repl::StorageInterface::set(serviceContext, std::make_unique<repl::StorageInterfaceImpl>()); auto logicalClock = stdx::make_unique<LogicalClock>(serviceContext); @@ -111,16 +108,6 @@ GlobalInitializerRegisterer replicationManagerInitializer( auto replCoord = std::make_unique<ReplicationCoordinatorEmbedded>(serviceContext); repl::ReplicationCoordinator::set(serviceContext, std::move(replCoord)); repl::setOplogCollectionName(serviceContext); - return Status::OK(); - }, - [](DeinitializerContext* context) { - auto serviceContext = getGlobalServiceContext(); - - repl::ReplicationCoordinator::set(serviceContext, nullptr); - LogicalClock::set(serviceContext, nullptr); - repl::StorageInterface::set(serviceContext, nullptr); - - return Status::OK(); }); MONGO_INITIALIZER(fsyncLockedForWriting)(InitializerContext* context) { @@ -188,6 +175,7 @@ ServiceContext* initialize(const char* yaml_config) { initWireSpec(); auto serviceContext = getGlobalServiceContext(); + serviceContext->setServiceEntryPoint(std::make_unique<ServiceEntryPointEmbedded>()); auto opObserverRegistry = std::make_unique<OpObserverRegistry>(); opObserverRegistry->addObserver(std::make_unique<OpObserverImpl>()); diff --git a/src/mongo/embedded/service_context_embedded.cpp b/src/mongo/embedded/service_context_embedded.cpp deleted file mode 100644 index cc90580fb04..00000000000 --- a/src/mongo/embedded/service_context_embedded.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/** - * 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/base/init.h" -#include "mongo/base/initializer.h" -#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" -#include "mongo/db/storage/storage_options.h" -#include "mongo/embedded/service_context_embedded.h" -#include "mongo/embedded/service_entry_point_embedded.h" -#include "mongo/stdx/memory.h" -#include "mongo/util/log.h" -#include "mongo/util/map_util.h" -#include "mongo/util/mongoutils/str.h" -#include "mongo/util/scopeguard.h" -#include "mongo/util/system_clock_source.h" -#include "mongo/util/system_tick_source.h" - -namespace mongo { -namespace { -ServiceContextRegistrar serviceContextCreator([]() { - auto service = std::make_unique<ServiceContextMongoEmbedded>(); - service->setServiceEntryPoint(std::make_unique<ServiceEntryPointEmbedded>()); - service->setTickSource(std::make_unique<SystemTickSource>()); - service->setFastClockSource(std::make_unique<SystemClockSource>()); - service->setPreciseClockSource(std::make_unique<SystemClockSource>()); - return service; -}); -} // namespace - -extern bool _supportsDocLocking; - -ServiceContextMongoEmbedded::ServiceContextMongoEmbedded() = default; - -ServiceContextMongoEmbedded::~ServiceContextMongoEmbedded() = default; - -std::unique_ptr<OperationContext> ServiceContextMongoEmbedded::_newOpCtx(Client* client, - unsigned opId) { - invariant(&cc() == client); - auto opCtx = stdx::make_unique<OperationContext>(client, opId); - - if (isMMAPV1()) { - opCtx->setLockState(stdx::make_unique<MMAPV1LockerImpl>()); - } else { - opCtx->setLockState(stdx::make_unique<DefaultLockerImpl>()); - } - - opCtx->setRecoveryUnit(getStorageEngine()->newRecoveryUnit(), - WriteUnitOfWork::RecoveryUnitState::kNotInUnitOfWork); - return opCtx; -} - -} // namespace mongo diff --git a/src/mongo/executor/SConscript b/src/mongo/executor/SConscript index 0222cb4b278..2b3286f9d0d 100644 --- a/src/mongo/executor/SConscript +++ b/src/mongo/executor/SConscript @@ -171,6 +171,7 @@ env.CppIntegrationTest( 'network_interface_fixture', '$BUILD_DIR/mongo/db/commands/test_commands_enabled', '$BUILD_DIR/mongo/db/wire_version', + '$BUILD_DIR/mongo/transport/transport_layer_egress_init', ], ) @@ -241,7 +242,6 @@ env.CppUnitTest( 'thread_pool_task_executor_test.cpp', ], LIBDEPS=[ - '$BUILD_DIR/mongo/db/service_context_noop_init', '$BUILD_DIR/mongo/unittest/concurrency', 'thread_pool_task_executor_test_fixture', ] diff --git a/src/mongo/rpc/SConscript b/src/mongo/rpc/SConscript index 1acf5acae73..35651a9edd6 100644 --- a/src/mongo/rpc/SConscript +++ b/src/mongo/rpc/SConscript @@ -270,6 +270,7 @@ env.CppIntegrationTest( LIBDEPS=[ 'protocol', '$BUILD_DIR/mongo/client/clientdriver_network', + '$BUILD_DIR/mongo/transport/transport_layer_egress_init', '$BUILD_DIR/mongo/util/version_impl', ], ) diff --git a/src/mongo/s/SConscript b/src/mongo/s/SConscript index bda3163ced7..553f2211387 100644 --- a/src/mongo/s/SConscript +++ b/src/mongo/s/SConscript @@ -180,7 +180,7 @@ env.Library( ], LIBDEPS=[ '$BUILD_DIR/mongo/db/query/collation/collator_factory_mock', - '$BUILD_DIR/mongo/db/service_context_noop_init', + '$BUILD_DIR/mongo/db/service_context_test_fixture', '$BUILD_DIR/mongo/executor/task_executor_pool', '$BUILD_DIR/mongo/s/catalog/dist_lock_manager_mock', '$BUILD_DIR/mongo/s/catalog/sharding_catalog_client_impl', @@ -485,9 +485,7 @@ env.CppUnitTest( 'client/shard_connection_test.cpp', ], LIBDEPS=[ - '$BUILD_DIR/mongo/db/service_context_noop_init', '$BUILD_DIR/mongo/dbtests/mocklib', - '$BUILD_DIR/mongo/transport/transport_layer_egress_init', '$BUILD_DIR/mongo/util/net/network', 'client/sharding_connection_hook', 'sharding_legacy_api', diff --git a/src/mongo/s/async_requests_sender.cpp b/src/mongo/s/async_requests_sender.cpp index b944ac0bb8d..61efb9ae468 100644 --- a/src/mongo/s/async_requests_sender.cpp +++ b/src/mongo/s/async_requests_sender.cpp @@ -392,7 +392,7 @@ Status AsyncRequestsSender::RemoteData::resolveShardIdToHostAndPort( std::shared_ptr<Shard> AsyncRequestsSender::RemoteData::getShard() { // TODO: Pass down an OperationContext* to use here. - return grid.shardRegistry()->getShardNoReload(shardId); + return Grid::get(getGlobalServiceContext())->shardRegistry()->getShardNoReload(shardId); } AsyncRequestsSender::BatonDetacher::BatonDetacher(OperationContext* opCtx) diff --git a/src/mongo/s/catalog_cache_test_fixture.cpp b/src/mongo/s/catalog_cache_test_fixture.cpp index a1ab2acbba7..835aedebf2f 100644 --- a/src/mongo/s/catalog_cache_test_fixture.cpp +++ b/src/mongo/s/catalog_cache_test_fixture.cpp @@ -57,15 +57,15 @@ void CatalogCacheTestFixture::setUp() { setRemote(HostAndPort("FakeRemoteClient:34567")); configTargeter()->setFindHostReturnValue(kConfigHostAndPort); - CollatorFactoryInterface::set(serviceContext(), stdx::make_unique<CollatorFactoryMock>()); + CollatorFactoryInterface::set(getServiceContext(), stdx::make_unique<CollatorFactoryMock>()); } executor::NetworkTestEnv::FutureHandle<boost::optional<CachedCollectionRoutingInfo>> CatalogCacheTestFixture::scheduleRoutingInfoRefresh(const NamespaceString& nss) { return launchAsync([this, nss] { - auto client = serviceContext()->makeClient("Test"); + auto client = getServiceContext()->makeClient("Test"); auto opCtx = client->makeOperationContext(); - auto const catalogCache = Grid::get(serviceContext())->catalogCache(); + auto const catalogCache = Grid::get(getServiceContext())->catalogCache(); catalogCache->invalidateShardedCollection(nss); return boost::make_optional( diff --git a/src/mongo/s/client/shard_registry.cpp b/src/mongo/s/client/shard_registry.cpp index ddc749edcd9..e450fa9e54e 100644 --- a/src/mongo/s/client/shard_registry.cpp +++ b/src/mongo/s/client/shard_registry.cpp @@ -345,7 +345,7 @@ void ShardRegistry::replicaSetChangeShardRegistryUpdateHook( // Inform the ShardRegsitry of the new connection string for the shard. auto connString = fassert(28805, ConnectionString::parse(newConnectionString)); invariant(setName == connString.getSetName()); - grid.shardRegistry()->updateReplSetHosts(connString); + Grid::get(getGlobalServiceContext())->shardRegistry()->updateReplSetHosts(connString); } void ShardRegistry::replicaSetChangeConfigServerUpdateHook(const std::string& setName, diff --git a/src/mongo/s/client/sharding_network_connection_hook.cpp b/src/mongo/s/client/sharding_network_connection_hook.cpp index 88ed8882b60..7bc307e4ab7 100644 --- a/src/mongo/s/client/sharding_network_connection_hook.cpp +++ b/src/mongo/s/client/sharding_network_connection_hook.cpp @@ -53,7 +53,8 @@ Status ShardingNetworkConnectionHook::validateHost( Status ShardingNetworkConnectionHook::validateHostImpl( const HostAndPort& remoteHost, const executor::RemoteCommandResponse& isMasterReply) { - auto shard = grid.shardRegistry()->getShardForHostNoReload(remoteHost); + auto shard = + Grid::get(getGlobalServiceContext())->shardRegistry()->getShardForHostNoReload(remoteHost); if (!shard) { return {ErrorCodes::ShardNotFound, str::stream() << "No shard found for host: " << remoteHost.toString()}; diff --git a/src/mongo/s/cluster_cursor_stats.cpp b/src/mongo/s/cluster_cursor_stats.cpp index 4aa5ca97891..2906fbfc8df 100644 --- a/src/mongo/s/cluster_cursor_stats.cpp +++ b/src/mongo/s/cluster_cursor_stats.cpp @@ -44,12 +44,13 @@ public: ClusterCursorStats() : ServerStatusMetric("cursor") {} void appendAtLeaf(BSONObjBuilder& b) const final { + auto grid = Grid::get(getGlobalServiceContext()); BSONObjBuilder cursorBob(b.subobjStart(_leafName)); cursorBob.append("timedOut", - static_cast<long long>(grid.getCursorManager()->cursorsTimedOut())); + static_cast<long long>(grid->getCursorManager()->cursorsTimedOut())); { BSONObjBuilder openBob(cursorBob.subobjStart("open")); - auto stats = grid.getCursorManager()->stats(); + auto stats = grid->getCursorManager()->stats(); openBob.append("multiTarget", static_cast<long long>(stats.cursorsMultiTarget)); openBob.append("singleTarget", static_cast<long long>(stats.cursorsSingleTarget)); openBob.append("pinned", static_cast<long long>(stats.cursorsPinned)); diff --git a/src/mongo/s/cluster_identity_loader_test.cpp b/src/mongo/s/cluster_identity_loader_test.cpp index 98817150d6b..18685da1086 100644 --- a/src/mongo/s/cluster_identity_loader_test.cpp +++ b/src/mongo/s/cluster_identity_loader_test.cpp @@ -35,7 +35,7 @@ #include "mongo/client/remote_command_targeter_mock.h" #include "mongo/db/commands.h" #include "mongo/db/query/query_request.h" -#include "mongo/db/service_context_noop.h" +#include "mongo/db/service_context.h" #include "mongo/executor/network_interface_mock.h" #include "mongo/executor/task_executor.h" #include "mongo/rpc/metadata/repl_set_metadata.h" @@ -67,19 +67,10 @@ BSONObj getReplSecondaryOkMetadata() { class ClusterIdentityTest : public ShardingTestFixture { public: - void setUp() override { - ShardingTestFixture::setUp(); - + ClusterIdentityTest() { configTargeter()->setFindHostReturnValue(configHost); } - void tearDown() override { - ShardingTestFixture::tearDown(); - - // Reset the global service context so that the cluster identity gets cleared - setGlobalServiceContext(std::make_unique<ServiceContextNoop>()); - } - void expectConfigVersionLoad(StatusWith<OID> result) { onFindCommand([&](const RemoteCommandRequest& request) { ASSERT_EQUALS(configHost, request.target); diff --git a/src/mongo/s/commands/SConscript b/src/mongo/s/commands/SConscript index cfb4aca929c..c1e7a9d1092 100644 --- a/src/mongo/s/commands/SConscript +++ b/src/mongo/s/commands/SConscript @@ -129,7 +129,6 @@ env.CppUnitTest( LIBDEPS=[ 'shared_cluster_commands', '$BUILD_DIR/mongo/db/auth/authmocks', - '$BUILD_DIR/mongo/db/service_context_noop_init', '$BUILD_DIR/mongo/db/logical_time', '$BUILD_DIR/mongo/unittest/unittest', ] @@ -144,7 +143,6 @@ env.CppUnitTest( 'shared_cluster_commands', '$BUILD_DIR/mongo/s/catalog_cache_test_fixture', '$BUILD_DIR/mongo/db/auth/authmocks', - '$BUILD_DIR/mongo/db/service_context_noop_init', '$BUILD_DIR/mongo/db/logical_clock', '$BUILD_DIR/mongo/unittest/unittest', ] @@ -159,7 +157,6 @@ env.CppUnitTest( 'cluster_commands', '$BUILD_DIR/mongo/db/auth/authmocks', '$BUILD_DIR/mongo/db/auth/saslauth', - '$BUILD_DIR/mongo/db/service_context_noop_init', '$BUILD_DIR/mongo/s/catalog_cache_test_fixture', ], ) diff --git a/src/mongo/s/commands/cluster_aggregate_test.cpp b/src/mongo/s/commands/cluster_aggregate_test.cpp index 37a94a57c5a..4f11447faac 100644 --- a/src/mongo/s/commands/cluster_aggregate_test.cpp +++ b/src/mongo/s/commands/cluster_aggregate_test.cpp @@ -69,10 +69,10 @@ protected: CatalogCacheTestFixture::setupNShards(numShards); // Set up a logical clock with an initial time. - auto logicalClock = stdx::make_unique<LogicalClock>(serviceContext()); + auto logicalClock = stdx::make_unique<LogicalClock>(getServiceContext()); LogicalTime initialTime(Timestamp(10, 1)); logicalClock->setClusterTimeFromTrustedSource(initialTime); - LogicalClock::set(serviceContext(), std::move(logicalClock)); + LogicalClock::set(getServiceContext(), std::move(logicalClock)); auto keysCollectionClient = stdx::make_unique<KeysCollectionClientSharded>( Grid::get(operationContext())->catalogClient()); @@ -81,7 +81,7 @@ protected: "dummy", std::move(keysCollectionClient), Seconds(KeysRotationIntervalSec)); auto validator = stdx::make_unique<LogicalTimeValidator>(keyManager); - LogicalTimeValidator::set(serviceContext(), std::move(validator)); + LogicalTimeValidator::set(getServiceContext(), std::move(validator)); // ReadConcern 'snapshot' is only supported with test commands enabled. setTestCommandsEnabled(true); @@ -123,7 +123,7 @@ protected: DbResponse runAggregateCommand(BSONObj aggCmd) { // Create a new client/operation context per command, and setup a test session ID and // transaction number. - auto client = serviceContext()->makeClient("ClusterAggClient"); + auto client = getServiceContext()->makeClient("ClusterAggClient"); auto opCtx = client->makeOperationContext(); opCtx->setLogicalSessionId(makeLogicalSessionIdForTest()); opCtx->setTxnNumber(1); diff --git a/src/mongo/s/commands/compute_at_cluster_time_test.cpp b/src/mongo/s/commands/compute_at_cluster_time_test.cpp index a4701547bbb..4d34d390326 100644 --- a/src/mongo/s/commands/compute_at_cluster_time_test.cpp +++ b/src/mongo/s/commands/compute_at_cluster_time_test.cpp @@ -71,9 +71,9 @@ protected: repl::ReadConcernArgs(repl::ReadConcernLevel::kSnapshotReadConcern); // Set up a logical clock with an initial time. - auto logicalClock = stdx::make_unique<LogicalClock>(serviceContext()); + auto logicalClock = stdx::make_unique<LogicalClock>(getServiceContext()); logicalClock->setClusterTimeFromTrustedSource(kInMemoryLogicalTime); - LogicalClock::set(serviceContext(), std::move(logicalClock)); + LogicalClock::set(getServiceContext(), std::move(logicalClock)); } }; @@ -131,9 +131,9 @@ protected: CatalogCacheTestFixture::setupNShards(2); // Set up a logical clock with an initial time. - auto logicalClock = stdx::make_unique<LogicalClock>(serviceContext()); + auto logicalClock = stdx::make_unique<LogicalClock>(getServiceContext()); logicalClock->setClusterTimeFromTrustedSource(kInMemoryLogicalTime); - LogicalClock::set(serviceContext(), std::move(logicalClock)); + LogicalClock::set(getServiceContext(), std::move(logicalClock)); } }; diff --git a/src/mongo/s/grid.cpp b/src/mongo/s/grid.cpp index 6570ca0c751..65d8b1c1f8c 100644 --- a/src/mongo/s/grid.cpp +++ b/src/mongo/s/grid.cpp @@ -44,15 +44,17 @@ namespace mongo { +namespace { // Global grid instance -Grid grid; +const auto grid = ServiceContext::declareDecoration<Grid>(); +} Grid::Grid() = default; Grid::~Grid() = default; Grid* Grid::get(ServiceContext* serviceContext) { - return &grid; + return &grid(serviceContext); } Grid* Grid::get(OperationContext* operationContext) { diff --git a/src/mongo/s/grid.h b/src/mongo/s/grid.h index 443c9b81304..02da388532b 100644 --- a/src/mongo/s/grid.h +++ b/src/mongo/s/grid.h @@ -200,8 +200,4 @@ private: bool _allowLocalShard{true}; }; -// Reference to the global Grid instance. Do not use in new code. Use one of the Grid::get methods -// instead. -extern Grid grid; - } // namespace mongo diff --git a/src/mongo/s/metadata_filtering_test.cpp b/src/mongo/s/metadata_filtering_test.cpp index 826ac629429..42926b7e5e6 100644 --- a/src/mongo/s/metadata_filtering_test.cpp +++ b/src/mongo/s/metadata_filtering_test.cpp @@ -53,7 +53,7 @@ protected: setupNShards(2); - _manager = std::make_shared<MetadataManager>(serviceContext(), kNss, executor()); + _manager = std::make_shared<MetadataManager>(getServiceContext(), kNss, executor()); } void expectGetDatabase() { diff --git a/src/mongo/s/query/SConscript b/src/mongo/s/query/SConscript index cd9a6c903c4..07ace658aab 100644 --- a/src/mongo/s/query/SConscript +++ b/src/mongo/s/query/SConscript @@ -30,7 +30,6 @@ env.CppUnitTest( LIBDEPS=[ 'cluster_query', '$BUILD_DIR/mongo/db/auth/authmocks', - '$BUILD_DIR/mongo/db/service_context_noop_init', '$BUILD_DIR/mongo/s/catalog_cache_test_fixture', ], ) @@ -77,7 +76,6 @@ env.CppUnitTest( LIBDEPS=[ 'router_exec_stage', '$BUILD_DIR/mongo/db/auth/authmocks', - '$BUILD_DIR/mongo/db/service_context_noop_init', ], ) @@ -117,7 +115,6 @@ env.CppUnitTest( 'cluster_client_cursor', '$BUILD_DIR/mongo/db/auth/authmocks', '$BUILD_DIR/mongo/db/query/query_request', - '$BUILD_DIR/mongo/db/service_context_noop_init', '$BUILD_DIR/mongo/executor/thread_pool_task_executor_test_fixture', '$BUILD_DIR/mongo/s/sharding_router_test_fixture', ], @@ -132,7 +129,6 @@ env.CppUnitTest( 'async_results_merger', '$BUILD_DIR/mongo/db/auth/authmocks', '$BUILD_DIR/mongo/db/query/query_request', - '$BUILD_DIR/mongo/db/service_context_noop_init', '$BUILD_DIR/mongo/s/sharding_router_test_fixture', ], ) @@ -159,7 +155,6 @@ env.CppUnitTest( 'store_possible_cursor', '$BUILD_DIR/mongo/db/auth/authmocks', '$BUILD_DIR/mongo/db/query/query_test_service_context', - '$BUILD_DIR/mongo/db/service_context_noop_init', '$BUILD_DIR/mongo/util/clock_source_mock', ], ) @@ -187,6 +182,7 @@ env.CppUnitTest( ], LIBDEPS=[ "$BUILD_DIR/mongo/db/logical_session_id", + "$BUILD_DIR/mongo/db/service_context_test_fixture", "$BUILD_DIR/mongo/util/clock_source_mock", "cluster_client_cursor_mock", "cluster_cursor_manager", @@ -213,6 +209,6 @@ env.CppUnitTest( LIBDEPS=[ 'cluster_client_cursor', '$BUILD_DIR/mongo/db/auth/authmocks', - '$BUILD_DIR/mongo/db/service_context_noop_init', + '$BUILD_DIR/mongo/db/service_context_test_fixture', ], ) diff --git a/src/mongo/s/query/async_results_merger_test.cpp b/src/mongo/s/query/async_results_merger_test.cpp index 662d78e6dd0..64428771bb0 100644 --- a/src/mongo/s/query/async_results_merger_test.cpp +++ b/src/mongo/s/query/async_results_merger_test.cpp @@ -74,7 +74,6 @@ public: AsyncResultsMergerTest() {} void setUp() override { - ShardingTestFixture::setUp(); setRemote(HostAndPort("ClientHost", 12345)); configTargeter()->setFindHostReturnValue(kTestConfigShardHost); @@ -100,10 +99,6 @@ public: setupShards(shards); } - void tearDown() override { - ShardingTestFixture::tearDown(); - } - protected: /** * Constructs an ARM with the given vector of existing cursors. @@ -2072,7 +2067,8 @@ DEATH_TEST_F(AsyncResultsMergerTest, params.setOperationSessionInfo(sessionInfo); // This should trigger an invariant. - stdx::make_unique<AsyncResultsMerger>(operationContext(), executor(), std::move(params)); + ASSERT_FALSE( + stdx::make_unique<AsyncResultsMerger>(operationContext(), executor(), std::move(params))); } DEATH_TEST_F(AsyncResultsMergerTest, diff --git a/src/mongo/s/query/cluster_client_cursor_impl_test.cpp b/src/mongo/s/query/cluster_client_cursor_impl_test.cpp index c73b33a68e4..faf4d29dda1 100644 --- a/src/mongo/s/query/cluster_client_cursor_impl_test.cpp +++ b/src/mongo/s/query/cluster_client_cursor_impl_test.cpp @@ -32,7 +32,7 @@ #include "mongo/bson/bsonobj.h" #include "mongo/bson/bsonobjbuilder.h" -#include "mongo/db/service_context_noop.h" +#include "mongo/db/service_context_test_fixture.h" #include "mongo/s/query/router_stage_mock.h" #include "mongo/stdx/memory.h" #include "mongo/unittest/unittest.h" @@ -41,27 +41,11 @@ namespace mongo { namespace { -class ClusterClientCursorImplTest : public unittest::Test { +class ClusterClientCursorImplTest : public ServiceContextTest { protected: - ServiceContextNoop _serviceContext; - ServiceContext::UniqueOperationContext _opCtx; - Client* _client; - -private: - void setUp() final { - auto client = _serviceContext.makeClient("testClient"); - _opCtx = client->makeOperationContext(); - _client = client.get(); - Client::setCurrent(std::move(client)); - } - - void tearDown() final { - if (_opCtx) { - _opCtx.reset(); - } + ClusterClientCursorImplTest() : _opCtx(makeOperationContext()) {} - Client::releaseCurrent(); - } + ServiceContext::UniqueOperationContext _opCtx; }; TEST_F(ClusterClientCursorImplTest, NumReturnedSoFar) { @@ -196,7 +180,7 @@ TEST_F(ClusterClientCursorImplTest, ChecksForInterrupt) { // Now interrupt the opCtx which the cursor is running under. { - stdx::lock_guard<Client> lk(*_client); + stdx::lock_guard<Client> lk(*_opCtx->getClient()); _opCtx->markKilled(ErrorCodes::CursorKilled); } diff --git a/src/mongo/s/query/cluster_cursor_manager_test.cpp b/src/mongo/s/query/cluster_cursor_manager_test.cpp index b5a2832cb1e..04a9d074ad7 100644 --- a/src/mongo/s/query/cluster_cursor_manager_test.cpp +++ b/src/mongo/s/query/cluster_cursor_manager_test.cpp @@ -34,8 +34,8 @@ #include "mongo/db/logical_session_cache.h" #include "mongo/db/logical_session_cache_noop.h" -#include "mongo/db/operation_context_noop.h" -#include "mongo/db/service_context_noop.h" +#include "mongo/db/operation_context.h" +#include "mongo/db/service_context_test_fixture.h" #include "mongo/s/query/cluster_client_cursor_mock.h" #include "mongo/stdx/memory.h" #include "mongo/unittest/unittest.h" @@ -48,13 +48,17 @@ namespace { using unittest::assertGet; const NamespaceString nss("test.collection"); -class ClusterCursorManagerTest : public unittest::Test { +class ClusterCursorManagerTest : public ServiceContextTest { protected: - ClusterCursorManagerTest() : _manager(&_clockSourceMock) {} + ClusterCursorManagerTest() : _opCtx(makeOperationContext()), _manager(&_clockSourceMock) { + LogicalSessionCache::set(getServiceContext(), stdx::make_unique<LogicalSessionCacheNoop>()); + } + + ~ClusterCursorManagerTest() { + _manager.shutdown(_opCtx.get()); + } - ServiceContextNoop serviceContext; ServiceContext::UniqueOperationContext _opCtx; - Client* _client; static Status successAuthChecker(UserNameIterator userNames) { return Status::OK(); @@ -106,49 +110,16 @@ protected: } void killCursorFromDifferentOpCtx(const NamespaceString& nss, CursorId cursorId) { - // Set up another client to kill the cursor. - auto killCursorClientOwned = serviceContext.makeClient("killCursorClient"); - // Keep around a raw pointer for when we transfer ownership of killingClientOwned to the - // global current client. - Client* killCursorClient = killCursorClientOwned.get(); - - // Need to swap the current client in order to make an operation context. - auto pinningClient = Client::releaseCurrent(); - Client::setCurrent(std::move(killCursorClientOwned)); + // Set up another client to kill the cursor. + auto killCursorClient = getServiceContext()->makeClient("killCursorClient"); auto killCursorOpCtx = killCursorClient->makeOperationContext(); - invariant(killCursorOpCtx); + AlternativeClientRegion acr(killCursorClient); ASSERT_OK(getManager()->killCursor(killCursorOpCtx.get(), nss, cursorId)); - - // Restore the old client. We don't need 'killCursorClient' anymore. - killCursorOpCtx.reset(); - Client::releaseCurrent(); - - Client::setCurrent(std::move(pinningClient)); } private: - void setUp() final { - auto client = serviceContext.makeClient("testClient"); - _opCtx = client->makeOperationContext(); - _client = client.get(); - Client::setCurrent(std::move(client)); - - LogicalSessionCache::set(&serviceContext, stdx::make_unique<LogicalSessionCacheNoop>()); - } - - void tearDown() final { - _manager.shutdown(_opCtx.get()); - - if (_opCtx) { - _opCtx.reset(); - } - - Client::releaseCurrent(); - LogicalSessionCache::set(&serviceContext, nullptr); - } - // List of flags representing whether our allocated cursors have been killed yet. The value of // the flag is true iff the cursor has been killed. // diff --git a/src/mongo/s/query/cluster_find_test.cpp b/src/mongo/s/query/cluster_find_test.cpp index e588521c80b..ccba55977a6 100644 --- a/src/mongo/s/query/cluster_find_test.cpp +++ b/src/mongo/s/query/cluster_find_test.cpp @@ -65,9 +65,9 @@ protected: CatalogCacheTestFixture::setupNShards(numShards); // Set up a logical clock with an initial time. - auto logicalClock = stdx::make_unique<LogicalClock>(serviceContext()); + auto logicalClock = stdx::make_unique<LogicalClock>(getServiceContext()); logicalClock->setClusterTimeFromTrustedSource(kInMemoryLogicalTime); - LogicalClock::set(serviceContext(), std::move(logicalClock)); + LogicalClock::set(getServiceContext(), std::move(logicalClock)); } // The index of the shard expected to receive the response is used to prevent different shards diff --git a/src/mongo/s/server.cpp b/src/mongo/s/server.cpp index 5978f4d4f4c..9e7358b2ca6 100644 --- a/src/mongo/s/server.cpp +++ b/src/mongo/s/server.cpp @@ -60,8 +60,6 @@ #include "mongo/db/operation_context.h" #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" @@ -112,8 +110,6 @@ #include "mongo/util/signal_handlers.h" #include "mongo/util/stacktrace.h" #include "mongo/util/stringutils.h" -#include "mongo/util/system_clock_source.h" -#include "mongo/util/system_tick_source.h" #include "mongo/util/text.h" #include "mongo/util/version.h" @@ -547,14 +543,6 @@ MONGO_INITIALIZER_WITH_PREREQUISITES(SetFeatureCompatibilityVersion40, ("EndStar 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")) (InitializerContext* context) { diff --git a/src/mongo/s/sharding_mongod_test_fixture.cpp b/src/mongo/s/sharding_mongod_test_fixture.cpp index f9a54847fd2..6fa3565cab9 100644 --- a/src/mongo/s/sharding_mongod_test_fixture.cpp +++ b/src/mongo/s/sharding_mongod_test_fixture.cpp @@ -33,6 +33,7 @@ #include <algorithm> #include <vector> +#include "mongo/base/checked_cast.h" #include "mongo/base/status_with.h" #include "mongo/client/remote_command_targeter_factory_mock.h" #include "mongo/client/remote_command_targeter_mock.h" @@ -55,7 +56,6 @@ #include "mongo/db/repl/storage_interface_mock.h" #include "mongo/db/s/config_server_op_observer.h" #include "mongo/db/s/shard_server_op_observer.h" -#include "mongo/db/service_context_noop.h" #include "mongo/executor/network_interface_mock.h" #include "mongo/executor/task_executor_pool.h" #include "mongo/executor/thread_pool_task_executor_test_fixture.h" @@ -135,14 +135,10 @@ void ShardingMongodTestFixture::setUp() { repl::StorageInterface::set(service, std::move(storagePtr)); - auto makeOpObserver = [&] { - auto opObserver = stdx::make_unique<OpObserverRegistry>(); - opObserver->addObserver(stdx::make_unique<OpObserverImpl>()); - opObserver->addObserver(stdx::make_unique<ConfigServerOpObserver>()); - opObserver->addObserver(stdx::make_unique<ShardServerOpObserver>()); - return opObserver; - }; - service->setOpObserver(makeOpObserver()); + auto opObserver = checked_cast<OpObserverRegistry*>(service->getOpObserver()); + opObserver->addObserver(stdx::make_unique<OpObserverImpl>()); + opObserver->addObserver(stdx::make_unique<ConfigServerOpObserver>()); + opObserver->addObserver(stdx::make_unique<ShardServerOpObserver>()); repl::setOplogCollectionName(service); repl::createOplog(_opCtx.get()); @@ -308,8 +304,6 @@ void ShardingMongodTestFixture::tearDown() { Grid::get(operationContext())->clearForUnitTests(); _opCtx.reset(); - _client.reset(); - ServiceContextMongoDTest::tearDown(); } diff --git a/src/mongo/s/sharding_mongod_test_fixture.h b/src/mongo/s/sharding_mongod_test_fixture.h index 222fbfd5184..02b41cfab5e 100644 --- a/src/mongo/s/sharding_mongod_test_fixture.h +++ b/src/mongo/s/sharding_mongod_test_fixture.h @@ -189,7 +189,6 @@ private: const std::vector<HostAndPort> _servers{ _host, HostAndPort("node2:12345"), HostAndPort("node3:12345")}; - ServiceContext::UniqueClient _client; ServiceContext::UniqueOperationContext _opCtx; // Since the RemoteCommandTargeterFactory is currently a private member of ShardFactory, we diff --git a/src/mongo/s/sharding_router_test_fixture.cpp b/src/mongo/s/sharding_router_test_fixture.cpp index 132e375b160..e42c1e41316 100644 --- a/src/mongo/s/sharding_router_test_fixture.cpp +++ b/src/mongo/s/sharding_router_test_fixture.cpp @@ -44,7 +44,6 @@ #include "mongo/db/query/collation/collator_factory_mock.h" #include "mongo/db/query/query_request.h" #include "mongo/db/repl/read_concern_args.h" -#include "mongo/db/service_context_noop.h" #include "mongo/executor/network_interface_mock.h" #include "mongo/executor/task_executor_pool.h" #include "mongo/executor/thread_pool_task_executor_test_fixture.h" @@ -94,12 +93,8 @@ std::unique_ptr<ShardingTaskExecutor> makeShardingTestExecutor( } // namespace -ShardingTestFixture::ShardingTestFixture() = default; - -ShardingTestFixture::~ShardingTestFixture() = default; - -void ShardingTestFixture::setUp() { - auto const service = serviceContext(); +ShardingTestFixture::ShardingTestFixture() { + auto const service = getServiceContext(); // Configure the service context service->setFastClockSource(stdx::make_unique<ClockSourceMock>()); @@ -108,8 +103,7 @@ void ShardingTestFixture::setUp() { CollatorFactoryInterface::set(service, stdx::make_unique<CollatorFactoryMock>()); _transportSession = transport::MockSession::create(nullptr); - _client = service->makeClient("ShardingTestFixture", _transportSession); - _opCtx = _client->makeOperationContext(); + _opCtx = makeOperationContext(); // Set up executor pool used for most operations. auto makeMetadataHookList = [&] { @@ -194,16 +188,9 @@ void ShardingTestFixture::setUp() { _mockNetwork); } -void ShardingTestFixture::tearDown() { - CatalogCacheLoader::clearForTests(serviceContext()); - - Grid::get(operationContext())->getExecutorPool()->shutdownAndJoin(); - Grid::get(operationContext())->catalogClient()->shutDown(_opCtx.get()); - Grid::get(operationContext())->clearForUnitTests(); - _transportSession.reset(); - _opCtx.reset(); - _client.reset(); +ShardingTestFixture::~ShardingTestFixture() { + CatalogCacheLoader::clearForTests(getServiceContext()); } void ShardingTestFixture::shutdownExecutor() { @@ -243,10 +230,6 @@ DistLockManagerMock* ShardingTestFixture::distLock() const { return _distLockManager; } -ServiceContext* ShardingTestFixture::serviceContext() const { - return getGlobalServiceContext(); -} - OperationContext* ShardingTestFixture::operationContext() const { invariant(_opCtx); diff --git a/src/mongo/s/sharding_router_test_fixture.h b/src/mongo/s/sharding_router_test_fixture.h index 05c1fa37a88..3eadf92a225 100644 --- a/src/mongo/s/sharding_router_test_fixture.h +++ b/src/mongo/s/sharding_router_test_fixture.h @@ -28,6 +28,7 @@ #pragma once +#include "mongo/db/service_context_test_fixture.h" #include "mongo/s/sharding_test_fixture_common.h" namespace mongo { @@ -50,7 +51,7 @@ class TransportLayerMock; * Sets up the mocked out objects for testing the replica-set backed catalog manager and catalog * client. */ -class ShardingTestFixture : public unittest::Test, public ShardingTestFixtureCommon { +class ShardingTestFixture : public ServiceContextTest, public ShardingTestFixtureCommon { public: ShardingTestFixture(); ~ShardingTestFixture(); @@ -64,7 +65,6 @@ public: DistLockManagerMock* distLock() const; RemoteCommandTargeterMock* configTargeter() const; - ServiceContext* serviceContext() const; OperationContext* operationContext() const; /** @@ -170,10 +170,6 @@ public: const NamespaceString& expectedNs, const ChunkVersion& expectedChunkVersion); - void setUp() override; - - void tearDown() override; - void shutdownExecutor(); void setRemote(const HostAndPort& remote); diff --git a/src/mongo/shell/dbshell.cpp b/src/mongo/shell/dbshell.cpp index c06d9a568b7..964e70e18b6 100644 --- a/src/mongo/shell/dbshell.cpp +++ b/src/mongo/shell/dbshell.cpp @@ -47,7 +47,6 @@ #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" diff --git a/src/mongo/tools/bridge.cpp b/src/mongo/tools/bridge.cpp index 6332f1cc5fe..26086ee29d1 100644 --- a/src/mongo/tools/bridge.cpp +++ b/src/mongo/tools/bridge.cpp @@ -38,8 +38,6 @@ #include "mongo/db/dbmessage.h" #include "mongo/db/operation_context.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" @@ -85,10 +83,6 @@ boost::optional<HostAndPort> extractHostInfo(const OpMsgRequest& request) { return boost::none; } -ServiceContextRegistrar serviceContextCreator([]() { - return std::make_unique<ServiceContextNoop>(); -}); - } // namespace class BridgeContext { @@ -142,7 +136,7 @@ private: HostSettingsMap _settings; }; -const ServiceContextNoop::Decoration<BridgeContext> BridgeContext::_get = +const ServiceContext::Decoration<BridgeContext> BridgeContext::_get = ServiceContext::declareDecoration<BridgeContext>(); BridgeContext* BridgeContext::get() { diff --git a/src/mongo/transport/SConscript b/src/mongo/transport/SConscript index d12800b3273..0f61fbcf12c 100644 --- a/src/mongo/transport/SConscript +++ b/src/mongo/transport/SConscript @@ -74,7 +74,6 @@ env.Library( ], LIBDEPS_PRIVATE=[ 'transport_layer', - '$BUILD_DIR/mongo/db/service_context_noop_init', ] ) @@ -86,7 +85,6 @@ tlEnv.CppUnitTest( LIBDEPS=[ 'transport_layer', '$BUILD_DIR/mongo/base', - '$BUILD_DIR/mongo/db/service_context_noop_init', '$BUILD_DIR/mongo/rpc/protocol', '$BUILD_DIR/mongo/util/net/socket', ], diff --git a/src/mongo/transport/service_executor_adaptive_test.cpp b/src/mongo/transport/service_executor_adaptive_test.cpp index c851c738ac2..30227edf3b9 100644 --- a/src/mongo/transport/service_executor_adaptive_test.cpp +++ b/src/mongo/transport/service_executor_adaptive_test.cpp @@ -32,7 +32,7 @@ #include "boost/optional.hpp" -#include "mongo/db/service_context_noop.h" +#include "mongo/db/service_context.h" #include "mongo/transport/service_executor_adaptive.h" #include "mongo/unittest/unittest.h" #include "mongo/util/log.h" @@ -107,8 +107,7 @@ struct RecursionOptions : public ServiceExecutorAdaptive::Options { class ServiceExecutorAdaptiveFixture : public unittest::Test { protected: void setUp() override { - auto scOwned = stdx::make_unique<ServiceContextNoop>(); - setGlobalServiceContext(std::move(scOwned)); + setGlobalServiceContext(ServiceContext::make()); asioIoCtx = std::make_shared<asio::io_context>(); } diff --git a/src/mongo/transport/service_executor_test.cpp b/src/mongo/transport/service_executor_test.cpp index 8e749228631..86e7187a37f 100644 --- a/src/mongo/transport/service_executor_test.cpp +++ b/src/mongo/transport/service_executor_test.cpp @@ -32,7 +32,7 @@ #include "boost/optional.hpp" -#include "mongo/db/service_context_noop.h" +#include "mongo/db/service_context.h" #include "mongo/transport/service_executor_adaptive.h" #include "mongo/transport/service_executor_synchronous.h" #include "mongo/transport/service_executor_task_names.h" @@ -135,7 +135,7 @@ private: class ServiceExecutorAdaptiveFixture : public unittest::Test { protected: void setUp() override { - auto scOwned = stdx::make_unique<ServiceContextNoop>(); + auto scOwned = ServiceContext::make(); setGlobalServiceContext(std::move(scOwned)); auto configOwned = stdx::make_unique<TestOptions>(); @@ -152,7 +152,7 @@ protected: class ServiceExecutorSynchronousFixture : public unittest::Test { protected: void setUp() override { - auto scOwned = stdx::make_unique<ServiceContextNoop>(); + auto scOwned = ServiceContext::make(); setGlobalServiceContext(std::move(scOwned)); executor = stdx::make_unique<ServiceExecutorSynchronous>(getGlobalServiceContext()); diff --git a/src/mongo/transport/service_state_machine_test.cpp b/src/mongo/transport/service_state_machine_test.cpp index 7ea13eaf12f..e29c33627a6 100644 --- a/src/mongo/transport/service_state_machine_test.cpp +++ b/src/mongo/transport/service_state_machine_test.cpp @@ -35,7 +35,7 @@ #include "mongo/bson/bsonobjbuilder.h" #include "mongo/db/client.h" #include "mongo/db/dbmessage.h" -#include "mongo/db/service_context_noop.h" +#include "mongo/db/service_context.h" #include "mongo/rpc/op_msg.h" #include "mongo/stdx/memory.h" #include "mongo/transport/mock_session.h" @@ -272,7 +272,7 @@ class ServiceStateMachineFixture : public unittest::Test { protected: void setUp() override { - auto scOwned = stdx::make_unique<ServiceContextNoop>(); + auto scOwned = ServiceContext::make(); auto sc = scOwned.get(); setGlobalServiceContext(std::move(scOwned)); diff --git a/src/mongo/transport/transport_layer_egress_init.cpp b/src/mongo/transport/transport_layer_egress_init.cpp index 628cf6c2dfc..ec8dd262515 100644 --- a/src/mongo/transport/transport_layer_egress_init.cpp +++ b/src/mongo/transport/transport_layer_egress_init.cpp @@ -34,25 +34,23 @@ #include "mongo/db/service_context.h" #include "mongo/transport/transport_layer_asio.h" +#include <iostream> + namespace mongo { namespace { -// Linking with this file will configure an egress-only TransportLayer on a ServiceContextNoop. +// Linking with this file will configure an egress-only TransportLayer on all new ServiceContexts. // Use this for unit/integration tests that require only egress networking. -MONGO_INITIALIZER_WITH_PREREQUISITES(ConfigureEgressTransportLayer, ("ServiceContext")) -(InitializerContext* context) { - auto sc = getGlobalServiceContext(); - invariant(!sc->getTransportLayer()); - - transport::TransportLayerASIO::Options opts; - opts.mode = transport::TransportLayerASIO::Options::kEgress; - sc->setTransportLayer(std::make_unique<transport::TransportLayerASIO>(opts, nullptr)); - auto status = sc->getTransportLayer()->setup(); - if (!status.isOK()) { - return status; - } - - return sc->getTransportLayer()->start(); -} + +ServiceContext::ConstructorActionRegisterer registerEgressTransportLayer{ + "ConfigureEgressTransportLayer", [](ServiceContext* sc) { + + invariant(!sc->getTransportLayer()); + transport::TransportLayerASIO::Options opts; + opts.mode = transport::TransportLayerASIO::Options::kEgress; + sc->setTransportLayer(std::make_unique<transport::TransportLayerASIO>(opts, nullptr)); + uassertStatusOK(sc->getTransportLayer()->setup()); + uassertStatusOK(sc->getTransportLayer()->start()); + }}; } // namespace -} // namespace +} // namespace mongo diff --git a/src/mongo/unittest/SConscript b/src/mongo/unittest/SConscript index 4645c23c19a..e3593d9ff8b 100644 --- a/src/mongo/unittest/SConscript +++ b/src/mongo/unittest/SConscript @@ -46,8 +46,6 @@ env.Library( ], LIBDEPS_PRIVATE=[ '$BUILD_DIR/mongo/client/connection_string', - '$BUILD_DIR/mongo/db/service_context', - '$BUILD_DIR/mongo/transport/transport_layer_egress_init', '$BUILD_DIR/mongo/util/options_parser/options_parser_init', ], ) diff --git a/src/mongo/unittest/integration_test_main.cpp b/src/mongo/unittest/integration_test_main.cpp index b4087176542..b2e3168bccc 100644 --- a/src/mongo/unittest/integration_test_main.cpp +++ b/src/mongo/unittest/integration_test_main.cpp @@ -37,7 +37,6 @@ #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" diff --git a/src/mongo/util/SConscript b/src/mongo/util/SConscript index d83b7c86759..54caf685b28 100644 --- a/src/mongo/util/SConscript +++ b/src/mongo/util/SConscript @@ -274,7 +274,7 @@ env.CppUnitTest( "periodic_runner_impl_test.cpp", ], LIBDEPS=[ - '$BUILD_DIR/mongo/db/service_context_noop_init', + "$BUILD_DIR/mongo/db/service_context_test_fixture", "clock_source_mock", "periodic_runner_impl", ], diff --git a/src/mongo/util/periodic_runner_impl_test.cpp b/src/mongo/util/periodic_runner_impl_test.cpp index cd2937c50e1..1ffda65bfaa 100644 --- a/src/mongo/util/periodic_runner_impl_test.cpp +++ b/src/mongo/util/periodic_runner_impl_test.cpp @@ -32,7 +32,7 @@ #include "mongo/util/periodic_runner_impl.h" -#include "mongo/db/service_context_noop.h" +#include "mongo/db/service_context_test_fixture.h" #include "mongo/stdx/condition_variable.h" #include "mongo/stdx/mutex.h" #include "mongo/util/clock_source_mock.h" @@ -43,12 +43,11 @@ class Client; namespace { -class PeriodicRunnerImplTestNoSetup : public unittest::Test { +class PeriodicRunnerImplTestNoSetup : public ServiceContextTest { public: void setUp() override { _clockSource = std::make_unique<ClockSourceMock>(); - _svc = stdx::make_unique<ServiceContextNoop>(); - _runner = stdx::make_unique<PeriodicRunnerImpl>(_svc.get(), _clockSource.get()); + _runner = stdx::make_unique<PeriodicRunnerImpl>(getServiceContext(), _clockSource.get()); } void tearDown() override { @@ -64,7 +63,6 @@ public: } private: - std::unique_ptr<ServiceContext> _svc; std::unique_ptr<ClockSourceMock> _clockSource; std::unique_ptr<PeriodicRunner> _runner; }; diff --git a/src/mongo/util/producer_consumer_queue_test.cpp b/src/mongo/util/producer_consumer_queue_test.cpp index 22577e791df..fa7af5e04a9 100644 --- a/src/mongo/util/producer_consumer_queue_test.cpp +++ b/src/mongo/util/producer_consumer_queue_test.cpp @@ -32,7 +32,7 @@ #include "mongo/util/producer_consumer_queue.h" -#include "mongo/db/service_context_noop.h" +#include "mongo/db/service_context.h" #include "mongo/stdx/condition_variable.h" #include "mongo/stdx/mutex.h" #include "mongo/stdx/thread.h" @@ -112,8 +112,6 @@ private: class ProducerConsumerQueueTest : public unittest::Test { public: - ProducerConsumerQueueTest() : _serviceCtx(stdx::make_unique<ServiceContextNoop>()) {} - template <typename Callback> stdx::thread runThread(StringData name, Callback&& cb) { return stdx::thread([this, name, cb] { @@ -153,7 +151,7 @@ public: } private: - std::unique_ptr<ServiceContext> _serviceCtx; + ServiceContext::UniqueServiceContext _serviceCtx = ServiceContext::make(); }; class MoveOnly { |