void ShardingUptimeReporter::startPeriodicThread() { invariant(!_thread.joinable()); _thread = stdx::thread([] { Client::initThread("Uptime reporter"); const std::string hostName(getHostNameCached()); const std::string instanceId(constructInstanceIdString(hostName)); const Timer upTimeTimer; while (!globalInShutdownDeprecated()) { { auto opCtx = cc().makeOperationContext(); reportStatus(opCtx.get(), instanceId, hostName, upTimeTimer); auto status = Grid::get(opCtx.get()) ->getBalancerConfiguration() ->refreshAndCheck(opCtx.get()); if (!status.isOK()) { warning() << "failed to refresh mongos settings" << causedBy(status); } } MONGO_IDLE_THREAD_BLOCK; sleepFor(kUptimeReportInterval); } }); }
void shutdownNoTerminate(const ShutdownTaskArgs& shutdownArgs) { decltype(shutdownTasks) localTasks; { stdx::lock_guard<stdx::mutex> lock(shutdownMutex); if (globalInShutdownDeprecated()) return; setShutdownFlag(); shutdownTasksInProgress = true; shutdownTasksThreadId = stdx::this_thread::get_id(); localTasks.swap(shutdownTasks); } runTasks(std::move(localTasks), shutdownArgs); { stdx::lock_guard<stdx::mutex> lock(shutdownMutex); shutdownTasksInProgress = false; shutdownExitCode.emplace(EXIT_CLEAN); } shutdownTasksComplete.notify_all(); }
void UserCacheInvalidator::run() { Client::initThread("UserCacheInvalidator"); lastInvalidationTime = Date_t::now(); while (true) { stdx::unique_lock<stdx::mutex> lock(invalidationIntervalMutex); Date_t sleepUntil = lastInvalidationTime + Seconds(userCacheInvalidationIntervalSecs.load()); Date_t now = Date_t::now(); while (now < sleepUntil) { MONGO_IDLE_THREAD_BLOCK; invalidationIntervalChangedCondition.wait_until(lock, sleepUntil.toSystemTimePoint()); sleepUntil = lastInvalidationTime + Seconds(userCacheInvalidationIntervalSecs.load()); now = Date_t::now(); } lastInvalidationTime = now; lock.unlock(); if (globalInShutdownDeprecated()) { break; } auto opCtx = cc().makeOperationContext(); StatusWith<OID> currentGeneration = getCurrentCacheGeneration(opCtx.get()); if (!currentGeneration.isOK()) { if (currentGeneration.getStatus().code() == ErrorCodes::CommandNotFound) { warning() << "_getUserCacheGeneration command not found on config server(s), " "this most likely means you are running an outdated version of mongod " "on the config servers"; } else { warning() << "An error occurred while fetching current user cache generation " "to check if user cache needs invalidation: " << currentGeneration.getStatus(); } // When in doubt, invalidate the cache _authzManager->invalidateUserCache(); continue; } if (currentGeneration.getValue() != _previousCacheGeneration) { log() << "User cache generation changed from " << _previousCacheGeneration << " to " << currentGeneration.getValue() << "; invalidating user cache"; _authzManager->invalidateUserCache(); _previousCacheGeneration = currentGeneration.getValue(); } } }
void shutdown(ExitCode code, const ShutdownTaskArgs& shutdownArgs) { decltype(shutdownTasks) localTasks; { stdx::unique_lock<stdx::mutex> lock(shutdownMutex); if (shutdownTasksInProgress) { // Someone better have called shutdown in some form already. invariant(globalInShutdownDeprecated()); // Re-entrant calls to shutdown are not allowed. invariant(shutdownTasksThreadId != stdx::this_thread::get_id()); ExitCode originallyRequestedCode = shutdownExitCode.get(); if (code != originallyRequestedCode) { log() << "While running shutdown tasks with the intent to exit with code " << originallyRequestedCode << ", an additional shutdown request arrived with " "the intent to exit with a different exit code " << code << "; ignoring the conflicting exit code"; } // Wait for the shutdown tasks to complete while (shutdownTasksInProgress) shutdownTasksComplete.wait(lock); logAndQuickExit_inlock(); } setShutdownFlag(); shutdownExitCode.emplace(code); shutdownTasksInProgress = true; shutdownTasksThreadId = stdx::this_thread::get_id(); localTasks.swap(shutdownTasks); } runTasks(std::move(localTasks), shutdownArgs); { stdx::lock_guard<stdx::mutex> lock(shutdownMutex); shutdownTasksInProgress = false; shutdownTasksComplete.notify_all(); logAndQuickExit_inlock(); } }
void UserCacheInvalidator::run() { Client::initThread("UserCacheInvalidator"); auto interval = globalInvalidationInterval(); interval->start(); while (true) { interval->wait(); if (globalInShutdownDeprecated()) { break; } auto opCtx = cc().makeOperationContext(); StatusWith<OID> currentGeneration = getCurrentCacheGeneration(opCtx.get()); if (!currentGeneration.isOK()) { if (currentGeneration.getStatus().code() == ErrorCodes::CommandNotFound) { warning() << "_getUserCacheGeneration command not found on config server(s), " "this most likely means you are running an outdated version of mongod " "on the config servers"; } else { warning() << "An error occurred while fetching current user cache generation " "to check if user cache needs invalidation: " << currentGeneration.getStatus(); } // When in doubt, invalidate the cache try { _authzManager->invalidateUserCache(opCtx.get()); } catch (const DBException& e) { warning() << "Error invalidating user cache: " << e.toStatus(); } continue; } if (currentGeneration.getValue() != _previousCacheGeneration) { log() << "User cache generation changed from " << _previousCacheGeneration << " to " << currentGeneration.getValue() << "; invalidating user cache"; try { _authzManager->invalidateUserCache(opCtx.get()); } catch (const DBException& e) { warning() << "Error invalidating user cache: " << e.toStatus(); } _previousCacheGeneration = currentGeneration.getValue(); } } }
ExitCode runMongosServer(ServiceContext* serviceContext) { Client::initThread("mongosMain"); printShardingVersionInfo(false); initWireSpec(); serviceContext->setServiceEntryPoint( stdx::make_unique<ServiceEntryPointMongos>(serviceContext)); auto tl = transport::TransportLayerManager::createWithConfig(&serverGlobalParams, serviceContext); auto res = tl->setup(); if (!res.isOK()) { error() << "Failed to set up listener: " << res; return EXIT_NET_ERROR; } serviceContext->setTransportLayer(std::move(tl)); auto unshardedHookList = stdx::make_unique<rpc::EgressMetadataHookList>(); unshardedHookList->addHook(stdx::make_unique<rpc::LogicalTimeMetadataHook>(serviceContext)); unshardedHookList->addHook( stdx::make_unique<rpc::ShardingEgressMetadataHookForMongos>(serviceContext)); // TODO SERVER-33053: readReplyMetadata is not called on hooks added through // ShardingConnectionHook with _shardedConnections=false, so this hook will not run for // connections using globalConnPool. unshardedHookList->addHook(stdx::make_unique<rpc::CommittedOpTimeMetadataHook>(serviceContext)); // Add sharding hooks to both connection pools - ShardingConnectionHook includes auth hooks globalConnPool.addHook(new ShardingConnectionHook(false, std::move(unshardedHookList))); auto shardedHookList = stdx::make_unique<rpc::EgressMetadataHookList>(); shardedHookList->addHook(stdx::make_unique<rpc::LogicalTimeMetadataHook>(serviceContext)); shardedHookList->addHook( stdx::make_unique<rpc::ShardingEgressMetadataHookForMongos>(serviceContext)); shardedHookList->addHook(stdx::make_unique<rpc::CommittedOpTimeMetadataHook>(serviceContext)); shardConnectionPool.addHook(new ShardingConnectionHook(true, std::move(shardedHookList))); // Hook up a Listener for changes from the ReplicaSetMonitor // This will last for the scope of this function. i.e. until shutdown finishes auto shardingRSCL = ReplicaSetMonitor::getNotifier().makeListener<ShardingReplicaSetChangeListener>( serviceContext); // Mongos connection pools already takes care of authenticating new connections so the // replica set connection shouldn't need to. DBClientReplicaSet::setAuthPooledSecondaryConn(false); if (getHostName().empty()) { quickExit(EXIT_BADOPTIONS); } auto opCtx = cc().makeOperationContext(); auto logicalClock = stdx::make_unique<LogicalClock>(opCtx->getServiceContext()); LogicalClock::set(opCtx->getServiceContext(), std::move(logicalClock)); { Status status = initializeSharding(opCtx.get()); if (!status.isOK()) { if (status == ErrorCodes::CallbackCanceled) { invariant(globalInShutdownDeprecated()); log() << "Shutdown called before mongos finished starting up"; return EXIT_CLEAN; } error() << "Error initializing sharding system: " << status; return EXIT_SHARDING_ERROR; } Grid::get(opCtx.get()) ->getBalancerConfiguration() ->refreshAndCheck(opCtx.get()) .transitional_ignore(); } startMongoSFTDC(); Status status = AuthorizationManager::get(serviceContext)->initialize(opCtx.get()); if (!status.isOK()) { error() << "Initializing authorization data failed: " << status; return EXIT_SHARDING_ERROR; } // Construct the sharding uptime reporter after the startup parameters have been parsed in order // to ensure that it picks up the server port instead of reporting the default value. shardingUptimeReporter.emplace(); shardingUptimeReporter->startPeriodicThread(); clusterCursorCleanupJob.go(); UserCacheInvalidator cacheInvalidatorThread(AuthorizationManager::get(serviceContext)); { cacheInvalidatorThread.initialize(opCtx.get()); cacheInvalidatorThread.go(); } PeriodicTask::startRunningPeriodicTasks(); // Set up the periodic runner for background job execution auto runner = makePeriodicRunner(serviceContext); runner->startup(); serviceContext->setPeriodicRunner(std::move(runner)); SessionKiller::set(serviceContext, std::make_shared<SessionKiller>(serviceContext, killSessionsRemote)); LogicalSessionCache::set( serviceContext, stdx::make_unique<LogicalSessionCacheImpl>(stdx::make_unique<ServiceLiaisonMongos>(), stdx::make_unique<SessionsCollectionSharded>(), RouterSessionCatalog::reapSessionsOlderThan)); status = serviceContext->getServiceExecutor()->start(); if (!status.isOK()) { error() << "Failed to start the service executor: " << redact(status); return EXIT_NET_ERROR; } status = serviceContext->getServiceEntryPoint()->start(); if (!status.isOK()) { error() << "Failed to start the service entry point: " << redact(status); return EXIT_NET_ERROR; } status = serviceContext->getTransportLayer()->start(); if (!status.isOK()) { error() << "Failed to start the transport layer: " << redact(status); return EXIT_NET_ERROR; } serviceContext->notifyStartupComplete(); #if !defined(_WIN32) signalForkSuccess(); #else if (ntservice::shouldStartService()) { ntservice::reportStatus(SERVICE_RUNNING); log() << "Service running"; } #endif // Block until shutdown. MONGO_IDLE_THREAD_BLOCK; return waitForShutdown(); }
UserCacheInvalidator::~UserCacheInvalidator() { invariant(globalInShutdownDeprecated()); // Wait to stop running. wait(); }
void registerShutdownTask(unique_function<void(const ShutdownTaskArgs&)> task) { stdx::lock_guard<stdx::mutex> lock(shutdownMutex); invariant(!globalInShutdownDeprecated()); shutdownTasks.emplace(std::move(task)); }