summaryrefslogtreecommitdiff
path: root/src/mongo/db/keys_collection_manager.cpp
diff options
context:
space:
mode:
authorsamantharitter <samantha.ritter@10gen.com>2017-06-27 12:09:40 -0400
committerJason Carey <jcarey@argv.me>2017-07-13 17:40:53 -0400
commite1cae24805e3e7282958ee67a01555dd6ce40039 (patch)
treeebce77d9a502a193784483b2201b65e1a5010d98 /src/mongo/db/keys_collection_manager.cpp
parent9a49ee3a03e02597086e577f06a71a0723bc0582 (diff)
downloadmongo-e1cae24805e3e7282958ee67a01555dd6ce40039.tar.gz
SERVER-29610 Allow LogicalSessionIds to contain signed user information
Diffstat (limited to 'src/mongo/db/keys_collection_manager.cpp')
-rw-r--r--src/mongo/db/keys_collection_manager.cpp309
1 files changed, 1 insertions, 308 deletions
diff --git a/src/mongo/db/keys_collection_manager.cpp b/src/mongo/db/keys_collection_manager.cpp
index e91d9af8dad..bed56f87847 100644
--- a/src/mongo/db/keys_collection_manager.cpp
+++ b/src/mongo/db/keys_collection_manager.cpp
@@ -30,317 +30,10 @@
#include "mongo/db/keys_collection_manager.h"
-#include "mongo/db/keys_collection_cache_reader.h"
-#include "mongo/db/keys_collection_cache_reader_and_updater.h"
-#include "mongo/db/logical_clock.h"
-#include "mongo/db/logical_time.h"
-#include "mongo/db/operation_context.h"
-#include "mongo/db/server_options.h"
-#include "mongo/db/service_context.h"
-#include "mongo/stdx/memory.h"
-#include "mongo/util/concurrency/idle_thread_block.h"
-#include "mongo/util/fail_point_service.h"
-#include "mongo/util/mongoutils/str.h"
-#include "mongo/util/time_support.h"
-
namespace mongo {
const Seconds KeysCollectionManager::kKeyValidInterval{3 * 30 * 24 * 60 * 60}; // ~3 months
-namespace {
-
-Milliseconds kDefaultRefreshWaitTime(30 * 1000);
-Milliseconds kRefreshIntervalIfErrored(200);
-Milliseconds kMaxRefreshWaitTime(10 * 60 * 1000);
-
-// Prevents the refresher thread from waiting longer than the given number of milliseconds, even on
-// a successful refresh.
-MONGO_FP_DECLARE(maxKeyRefreshWaitTimeOverrideMS);
-
-/**
- * Returns the amount of time to wait until the monitoring thread should attempt to refresh again.
- */
-Milliseconds howMuchSleepNeedFor(const LogicalTime& currentTime,
- const LogicalTime& latestExpiredAt,
- const Milliseconds& interval) {
- auto currentSecs = currentTime.asTimestamp().getSecs();
- auto expiredSecs = latestExpiredAt.asTimestamp().getSecs();
-
- if (currentSecs >= expiredSecs) {
- // This means that the last round didn't generate a usable key for the current time.
- // However, we don't want to poll too hard as well, so use a low interval.
- return kRefreshIntervalIfErrored;
- }
-
- auto millisBeforeExpire = 1000 * (expiredSecs - currentSecs);
-
- if (interval.count() <= millisBeforeExpire) {
- return interval;
- }
-
- return Milliseconds(millisBeforeExpire);
-}
-
-} // unnamed namespace
-
-KeysCollectionManager::KeysCollectionManager(std::string purpose,
- ShardingCatalogClient* client,
- Seconds keyValidForInterval)
- : _purpose(std::move(purpose)),
- _keyValidForInterval(keyValidForInterval),
- _catalogClient(client),
- _keysCache(_purpose, client) {}
-
-StatusWith<KeysCollectionDocument> KeysCollectionManager::getKeyForValidation(
- OperationContext* opCtx, long long keyId, const LogicalTime& forThisTime) {
- auto keyStatus = _getKeyWithKeyIdCheck(keyId, forThisTime);
-
- if (keyStatus != ErrorCodes::KeyNotFound) {
- return keyStatus;
- }
-
- _refresher.refreshNow(opCtx);
-
- return _getKeyWithKeyIdCheck(keyId, forThisTime);
-}
-
-StatusWith<KeysCollectionDocument> KeysCollectionManager::getKeyForSigning(
- const LogicalTime& forThisTime) {
- return _getKey(forThisTime);
-}
-
-StatusWith<KeysCollectionDocument> KeysCollectionManager::_getKeyWithKeyIdCheck(
- long long keyId, const LogicalTime& forThisTime) {
- auto keyStatus = _keysCache.getKeyById(keyId, forThisTime);
-
- if (!keyStatus.isOK()) {
- return keyStatus;
- }
-
- return keyStatus.getValue();
-}
-
-StatusWith<KeysCollectionDocument> KeysCollectionManager::_getKey(const LogicalTime& forThisTime) {
- auto keyStatus = _keysCache.getKey(forThisTime);
-
- if (!keyStatus.isOK()) {
- return keyStatus;
- }
-
- const auto& key = keyStatus.getValue();
-
- if (key.getExpiresAt() < forThisTime) {
- return {ErrorCodes::KeyNotFound,
- str::stream() << "No keys found for " << _purpose << " that is valid for "
- << forThisTime.toString()};
- }
-
- return key;
-}
-
-void KeysCollectionManager::refreshNow(OperationContext* opCtx) {
- _refresher.refreshNow(opCtx);
-}
-
-void KeysCollectionManager::startMonitoring(ServiceContext* service) {
- _refresher.setFunc([this](OperationContext* opCtx) { return _keysCache.refresh(opCtx); });
- _refresher.start(
- service, str::stream() << "monitoring keys for " << _purpose, _keyValidForInterval);
-}
-
-void KeysCollectionManager::stopMonitoring() {
- _refresher.stop();
-}
-
-void KeysCollectionManager::enableKeyGenerator(OperationContext* opCtx, bool doEnable) {
- if (doEnable) {
- _refresher.switchFunc(opCtx, [this](OperationContext* opCtx) {
- KeysCollectionCacheReaderAndUpdater keyGenerator(
- _purpose, _catalogClient, _keyValidForInterval);
- auto keyGenerationStatus = keyGenerator.refresh(opCtx);
-
- if (ErrorCodes::isShutdownError(keyGenerationStatus.getStatus().code())) {
- return keyGenerationStatus;
- }
-
- // An error encountered by the keyGenerator should not prevent refreshing the cache
- auto cacheRefreshStatus = _keysCache.refresh(opCtx);
-
- if (!keyGenerationStatus.isOK()) {
- return keyGenerationStatus;
- }
-
- return cacheRefreshStatus;
- });
- } else {
- _refresher.switchFunc(
- opCtx, [this](OperationContext* opCtx) { return _keysCache.refresh(opCtx); });
- }
-}
-
-bool KeysCollectionManager::hasSeenKeys() {
- return _refresher.hasSeenKeys();
-}
-
-void KeysCollectionManager::PeriodicRunner::refreshNow(OperationContext* opCtx) {
- auto refreshRequest = [this]() {
- stdx::lock_guard<stdx::mutex> lk(_mutex);
-
- if (_inShutdown) {
- throw DBException("aborting keys cache refresh because node is shutting down",
- ErrorCodes::ShutdownInProgress);
- }
-
- if (_refreshRequest) {
- return _refreshRequest;
- }
-
- _refreshNeededCV.notify_all();
- _refreshRequest = std::make_shared<Notification<void>>();
- return _refreshRequest;
- }();
-
- // note: waitFor waits min(maxTimeMS, kDefaultRefreshWaitTime).
- // waitFor also throws if timeout, so also throw when notification was not satisfied after
- // waiting.
- if (!refreshRequest->waitFor(opCtx, kDefaultRefreshWaitTime)) {
- throw DBException("timed out waiting for refresh", ErrorCodes::ExceededTimeLimit);
- }
-}
-
-void KeysCollectionManager::PeriodicRunner::_doPeriodicRefresh(ServiceContext* service,
- std::string threadName,
- Milliseconds refreshInterval) {
- Client::initThreadIfNotAlready(threadName);
-
- while (true) {
- auto opCtx = cc().makeOperationContext();
-
- bool hasRefreshRequestInitially = false;
- unsigned errorCount = 0;
- std::shared_ptr<RefreshFunc> doRefresh;
- {
- stdx::lock_guard<stdx::mutex> lock(_mutex);
-
- if (_inShutdown) {
- break;
- }
-
- invariant(_doRefresh.get() != nullptr);
- doRefresh = _doRefresh;
- hasRefreshRequestInitially = _refreshRequest.get() != nullptr;
- }
-
- Milliseconds nextWakeup = kRefreshIntervalIfErrored;
-
- // No need to refresh keys in FCV 3.4, since key generation will be disabled.
- if (serverGlobalParams.featureCompatibility.version.load() !=
- ServerGlobalParams::FeatureCompatibility::Version::k34) {
- auto latestKeyStatusWith = (*doRefresh)(opCtx.get());
- if (latestKeyStatusWith.getStatus().isOK()) {
- errorCount = 0;
- const auto& latestKey = latestKeyStatusWith.getValue();
- auto currentTime = LogicalClock::get(service)->getClusterTime();
-
- {
- stdx::unique_lock<stdx::mutex> lock(_mutex);
- _hasSeenKeys = true;
- }
-
- nextWakeup =
- howMuchSleepNeedFor(currentTime, latestKey.getExpiresAt(), refreshInterval);
- } else {
- errorCount += 1;
- nextWakeup = Milliseconds(kRefreshIntervalIfErrored.count() * errorCount);
- if (nextWakeup > kMaxRefreshWaitTime) {
- nextWakeup = kMaxRefreshWaitTime;
- }
- }
- } else {
- nextWakeup = kDefaultRefreshWaitTime;
- }
-
- MONGO_FAIL_POINT_BLOCK(maxKeyRefreshWaitTimeOverrideMS, data) {
- const BSONObj& dataObj = data.getData();
- auto overrideMS = Milliseconds(dataObj["overrideMS"].numberInt());
- if (nextWakeup > overrideMS) {
- nextWakeup = overrideMS;
- }
- }
-
- stdx::unique_lock<stdx::mutex> lock(_mutex);
-
- if (_refreshRequest) {
- if (!hasRefreshRequestInitially) {
- // A fresh request came in, fulfill the request before going to sleep.
- continue;
- }
-
- _refreshRequest->set();
- _refreshRequest.reset();
- }
-
- if (_inShutdown) {
- break;
- }
-
- MONGO_IDLE_THREAD_BLOCK;
- auto sleepStatus = opCtx->waitForConditionOrInterruptNoAssertUntil(
- _refreshNeededCV, lock, Date_t::now() + nextWakeup);
-
- if (ErrorCodes::isShutdownError(sleepStatus.getStatus().code())) {
- break;
- }
- }
-
- stdx::unique_lock<stdx::mutex> lock(_mutex);
- if (_refreshRequest) {
- _refreshRequest->set();
- _refreshRequest.reset();
- }
-}
-
-void KeysCollectionManager::PeriodicRunner::setFunc(RefreshFunc newRefreshStrategy) {
- stdx::lock_guard<stdx::mutex> lock(_mutex);
- _doRefresh = std::make_shared<RefreshFunc>(std::move(newRefreshStrategy));
-}
-
-void KeysCollectionManager::PeriodicRunner::switchFunc(OperationContext* opCtx,
- RefreshFunc newRefreshStrategy) {
- setFunc(newRefreshStrategy);
-}
-
-void KeysCollectionManager::PeriodicRunner::start(ServiceContext* service,
- const std::string& threadName,
- Milliseconds refreshInterval) {
- stdx::lock_guard<stdx::mutex> lock(_mutex);
- invariant(!_backgroundThread.joinable());
- invariant(!_inShutdown);
-
- _backgroundThread =
- stdx::thread(stdx::bind(&KeysCollectionManager::PeriodicRunner::_doPeriodicRefresh,
- this,
- service,
- threadName,
- refreshInterval));
-}
-
-void KeysCollectionManager::PeriodicRunner::stop() {
- {
- stdx::lock_guard<stdx::mutex> lock(_mutex);
- if (!_backgroundThread.joinable()) {
- return;
- }
-
- _inShutdown = true;
- _refreshNeededCV.notify_all();
- }
-
- _backgroundThread.join();
-}
-bool KeysCollectionManager::PeriodicRunner::hasSeenKeys() {
- stdx::lock_guard<stdx::mutex> lock(_mutex);
- return _hasSeenKeys;
-}
+KeysCollectionManager::~KeysCollectionManager() = default;
} // namespace mongo