Exemplo n.º 1
0
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);
        }
    });
}
Exemplo n.º 2
0
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();
}
Exemplo n.º 3
0
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();
        }
    }
}
Exemplo n.º 4
0
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();
        }
    }
}
Exemplo n.º 6
0
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();
}
Exemplo n.º 7
0
UserCacheInvalidator::~UserCacheInvalidator() {
    invariant(globalInShutdownDeprecated());
    // Wait to stop running.
    wait();
}
Exemplo n.º 8
0
void registerShutdownTask(unique_function<void(const ShutdownTaskArgs&)> task) {
    stdx::lock_guard<stdx::mutex> lock(shutdownMutex);
    invariant(!globalInShutdownDeprecated());
    shutdownTasks.emplace(std::move(task));
}