summaryrefslogtreecommitdiff
path: root/src/mongo/db
diff options
context:
space:
mode:
authorKaitlin Mahar <kaitlin.mahar@mongodb.com>2017-12-07 14:56:25 -0500
committerKaitlin Mahar <kaitlin.mahar@mongodb.com>2017-12-13 11:41:02 -0500
commit65c64a7845ca8159028148b25d3ec1867158108d (patch)
treedc8f4abd70848187b906d9b76bcad4b15faaf05b /src/mongo/db
parent33bf1580977524b1beb84f9bcedd51547c68aeb4 (diff)
downloadmongo-65c64a7845ca8159028148b25d3ec1867158108d.tar.gz
SERVER-31316 Remove unused code and unnecessary inheritance in KeysCollectionManager* classes
Diffstat (limited to 'src/mongo/db')
-rw-r--r--src/mongo/db/SConscript47
-rw-r--r--src/mongo/db/db.cpp3
-rw-r--r--src/mongo/db/keys_collection_manager.cpp315
-rw-r--r--src/mongo/db/keys_collection_manager.h142
-rw-r--r--src/mongo/db/keys_collection_manager_direct.cpp137
-rw-r--r--src/mongo/db/keys_collection_manager_direct.h73
-rw-r--r--src/mongo/db/keys_collection_manager_sharding.cpp350
-rw-r--r--src/mongo/db/keys_collection_manager_sharding.h197
-rw-r--r--src/mongo/db/keys_collection_manager_sharding_test.cpp10
-rw-r--r--src/mongo/db/keys_collection_manager_zero.cpp57
-rw-r--r--src/mongo/db/keys_collection_manager_zero.h69
-rw-r--r--src/mongo/db/logical_time_validator.cpp7
-rw-r--r--src/mongo/db/logical_time_validator.h8
-rw-r--r--src/mongo/db/logical_time_validator_test.cpp5
-rw-r--r--src/mongo/db/service_context.h1
-rw-r--r--src/mongo/db/service_liason.cpp1
16 files changed, 468 insertions, 954 deletions
diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript
index b4b4d5e0efb..428ea17e5de 100644
--- a/src/mongo/db/SConscript
+++ b/src/mongo/db/SConscript
@@ -902,8 +902,6 @@ env.Library(
LIBDEPS=[
'$BUILD_DIR/mongo/crypto/sha1_block',
'keys_collection_document',
- 'keys_collection_manager',
- 'keys_collection_manager_zero',
'logical_clock',
],
)
@@ -1240,40 +1238,6 @@ env.Library(
)
env.Library(
- target='keys_collection_manager',
- source=[
- 'keys_collection_manager.cpp',
- ],
- LIBDEPS=[
- 'server_parameters',
- ],
-)
-
-env.Library(
- target='keys_collection_manager_direct',
- source=[
- 'keys_collection_manager_direct.cpp',
- ],
- LIBDEPS=[
- 'dbdirectclient',
- 'keys_collection_manager',
- 'logical_clock',
- 'logical_time',
- ],
-)
-
-env.Library(
- target='keys_collection_manager_zero',
- source=[
- 'keys_collection_manager_zero.cpp',
- ],
- LIBDEPS=[
- 'keys_collection_manager',
- 'logical_time',
- ],
-)
-
-env.Library(
target='keys_collection_client_direct',
source=[
'keys_collection_client_direct.cpp',
@@ -1302,16 +1266,15 @@ env.Library(
)
env.Library(
- target='keys_collection_manager_sharding',
+ target='keys_collection_manager',
source=[
- 'keys_collection_manager_sharding.cpp',
+ 'keys_collection_manager.cpp',
'keys_collection_cache_reader.cpp',
'keys_collection_cache_reader_and_updater.cpp',
],
LIBDEPS=[
'logical_clock',
'keys_collection_document',
- 'keys_collection_manager',
'logical_time',
'server_options',
'keys_collection_client_sharded',
@@ -1336,7 +1299,7 @@ env.Library(
'logical_time_validator.cpp',
],
LIBDEPS=[
- 'keys_collection_manager_sharding',
+ 'keys_collection_manager',
'service_context',
'signed_logical_time',
'time_proof_service',
@@ -1394,7 +1357,7 @@ env.CppUnitTest(
'logical_time_validator_test.cpp',
],
LIBDEPS=[
- 'keys_collection_manager_sharding',
+ 'keys_collection_manager',
'logical_time_validator',
'$BUILD_DIR/mongo/s/config_server_test_fixture',
'$BUILD_DIR/mongo/s/coreshard',
@@ -1466,7 +1429,7 @@ env.CppUnitTest(
'keys_collection_manager_sharding_test.cpp',
],
LIBDEPS=[
- 'keys_collection_manager_sharding',
+ 'keys_collection_manager',
'$BUILD_DIR/mongo/s/config_server_test_fixture',
],
)
diff --git a/src/mongo/db/db.cpp b/src/mongo/db/db.cpp
index fe0402f15e3..b6ad9f7bdd2 100644
--- a/src/mongo/db/db.cpp
+++ b/src/mongo/db/db.cpp
@@ -78,7 +78,6 @@
#include "mongo/db/keys_collection_client_direct.h"
#include "mongo/db/keys_collection_client_sharded.h"
#include "mongo/db/keys_collection_manager.h"
-#include "mongo/db/keys_collection_manager_sharding.h"
#include "mongo/db/kill_sessions.h"
#include "mongo/db/kill_sessions_local.h"
#include "mongo/db/log_process_details.h"
@@ -946,7 +945,7 @@ ExitCode _initAndListen(int listenPort) {
makeShardingTaskExecutor(executor::makeNetworkInterface("AddShard-TaskExecutor")));
} else if (replSettings.usingReplSets()) { // standalone replica set
auto keysCollectionClient = stdx::make_unique<KeysCollectionClientDirect>();
- auto keyManager = std::make_shared<KeysCollectionManagerSharding>(
+ auto keyManager = std::make_shared<KeysCollectionManager>(
KeysCollectionManager::kKeyManagerPurposeString,
std::move(keysCollectionClient),
Seconds(KeysRotationIntervalSec));
diff --git a/src/mongo/db/keys_collection_manager.cpp b/src/mongo/db/keys_collection_manager.cpp
index 1ef6a8bb673..24fb4a8b6da 100644
--- a/src/mongo/db/keys_collection_manager.cpp
+++ b/src/mongo/db/keys_collection_manager.cpp
@@ -25,12 +25,27 @@
* 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::kDefault
#include "mongo/platform/basic.h"
#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/keys_collection_client.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/server_parameters.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/log.h"
+#include "mongo/util/mongoutils/str.h"
+#include "mongo/util/time_support.h"
namespace mongo {
@@ -41,6 +56,304 @@ MONGO_EXPORT_STARTUP_SERVER_PARAMETER(KeysRotationIntervalSec,
int,
KeysCollectionManager::kKeyValidInterval.count());
-KeysCollectionManager::~KeysCollectionManager() = default;
+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,
+ std::unique_ptr<KeysCollectionClient> client,
+ Seconds keyValidForInterval)
+ : _client(std::move(client)),
+ _purpose(std::move(purpose)),
+ _keyValidForInterval(keyValidForInterval),
+ _keysCache(_purpose, _client.get()) {}
+
+
+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(
+ OperationContext* opCtx, 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) {
+ _keysCache.resetCache();
+ _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, _client.get(), _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) {
+ uasserted(ErrorCodes::ShutdownInProgress,
+ "aborting keys cache refresh because node is shutting down");
+ }
+
+ 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)) {
+ uasserted(ErrorCodes::ExceededTimeLimit, "timed out waiting for refresh");
+ }
+}
+
+void KeysCollectionManager::PeriodicRunner::_doPeriodicRefresh(ServiceContext* service,
+ std::string threadName,
+ Milliseconds refreshInterval) {
+ Client::initThreadIfNotAlready(threadName);
+
+ while (true) {
+ 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.getVersion() ==
+ ServerGlobalParams::FeatureCompatibility::Version::kFullyUpgradedTo36) {
+ auto opCtx = cc().makeOperationContext();
+
+ 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;
+ }
+
+ // Use a new opCtx so we won't be holding any RecoveryUnit while this thread goes to sleep.
+ auto opCtx = cc().makeOperationContext();
+
+ 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));
+ _refreshNeededCV.notify_all();
+}
+
+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([this, service, threadName, refreshInterval] {
+ _doPeriodicRefresh(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;
+}
} // namespace mongo
diff --git a/src/mongo/db/keys_collection_manager.h b/src/mongo/db/keys_collection_manager.h
index 4d6771be838..3cdac7b9bf2 100644
--- a/src/mongo/db/keys_collection_manager.h
+++ b/src/mongo/db/keys_collection_manager.h
@@ -31,34 +31,47 @@
#include <memory>
#include "mongo/base/status_with.h"
+#include "mongo/db/keys_collection_cache_reader.h"
+#include "mongo/db/keys_collection_cache_reader_and_updater.h"
#include "mongo/db/keys_collection_document.h"
+#include "mongo/stdx/functional.h"
+#include "mongo/stdx/mutex.h"
+#include "mongo/stdx/thread.h"
+#include "mongo/util/concurrency/notification.h"
+#include "mongo/util/duration.h"
namespace mongo {
class OperationContext;
class LogicalTime;
class ServiceContext;
+class KeysCollectionClient;
extern int KeysRotationIntervalSec;
+
/**
- * This is responsible for providing keys that can be used for HMAC computation. This also supports
- * automatic key rotation that happens on a configurable interval.
+ * The KeysCollectionManager queries the config servers for keys that can be used for
+ * HMAC computation. It maintains an internal background thread that is used to periodically
+ * refresh the local key cache against the keys collection stored on the config servers.
*/
class KeysCollectionManager {
public:
static const Seconds kKeyValidInterval;
static const std::string kKeyManagerPurposeString;
- virtual ~KeysCollectionManager();
+ KeysCollectionManager(std::string purpose,
+ std::unique_ptr<KeysCollectionClient> client,
+ Seconds keyValidForInterval);
/**
* Return a key that is valid for the given time and also matches the keyId. Note that this call
- * can block if it will need to do a refresh and we are on a sharded cluster.
+ * can block if it will need to do a refresh.
*
* Throws ErrorCode::ExceededTimeLimit if it times out.
*/
- virtual StatusWith<KeysCollectionDocument> getKeyForValidation(
- OperationContext* opCtx, long long keyId, const LogicalTime& forThisTime) = 0;
+ StatusWith<KeysCollectionDocument> getKeyForValidation(OperationContext* opCtx,
+ long long keyId,
+ const LogicalTime& forThisTime);
/**
* Returns a key that is valid for the given time. Note that unlike getKeyForValidation, this
@@ -66,8 +79,121 @@ public:
*
* Throws ErrorCode::ExceededTimeLimit if it times out.
*/
- virtual StatusWith<KeysCollectionDocument> getKeyForSigning(OperationContext* opCtx,
- const LogicalTime& forThisTime) = 0;
+ StatusWith<KeysCollectionDocument> getKeyForSigning(OperationContext* opCtx,
+ const LogicalTime& forThisTime);
+
+ /**
+ * Request this manager to perform a refresh.
+ */
+ void refreshNow(OperationContext* opCtx);
+
+ /**
+ * Starts a background thread that will constantly update the internal cache of keys.
+ *
+ * Cannot call this after stopMonitoring was called at least once.
+ */
+ void startMonitoring(ServiceContext* service);
+
+ /**
+ * Stops the background thread updating the cache.
+ */
+ void stopMonitoring();
+
+ /**
+ * Enable writing new keys to the config server primary. Should only be called if current node
+ * is the config primary.
+ */
+ void enableKeyGenerator(OperationContext* opCtx, bool doEnable);
+
+ /**
+ * Returns true if the refresher has ever successfully returned keys from the config server.
+ */
+ bool hasSeenKeys();
+
+private:
+ /**
+ * This is responsible for periodically performing refresh in the background.
+ */
+ class PeriodicRunner {
+ public:
+ using RefreshFunc = stdx::function<StatusWith<KeysCollectionDocument>(OperationContext*)>;
+
+ /**
+ * Preemptively inform the monitoring thread it needs to perform a refresh. Returns an
+ * object
+ * that gets notified after the current round of refresh is over. Note that being notified
+ * can
+ * mean either of these things:
+ *
+ * 1. An error occurred and refresh was not performed.
+ * 2. No error occurred but no new key was found.
+ * 3. No error occurred and new keys were found.
+ */
+ void refreshNow(OperationContext* opCtx);
+
+ /**
+ * Sets the refresh function to use.
+ * Should only be used to bootstrap this refresher with initial strategy.
+ */
+ void setFunc(RefreshFunc newRefreshStrategy);
+
+ /**
+ * Switches the current strategy with a new one. This also waits to make sure that the old
+ * strategy is not being used and will no longer be used after this call.
+ */
+ void switchFunc(OperationContext* opCtx, RefreshFunc newRefreshStrategy);
+
+ /**
+ * Starts the refresh thread.
+ */
+ void start(ServiceContext* service,
+ const std::string& threadName,
+ Milliseconds refreshInterval);
+
+ /**
+ * Stops the refresh thread.
+ */
+ void stop();
+
+ /**
+ * Returns true if keys have ever successfully been returned from the config server.
+ */
+ bool hasSeenKeys();
+
+ private:
+ void _doPeriodicRefresh(ServiceContext* service,
+ std::string threadName,
+ Milliseconds refreshInterval);
+
+ stdx::mutex _mutex; // protects all the member variables below.
+ std::shared_ptr<Notification<void>> _refreshRequest;
+ stdx::condition_variable _refreshNeededCV;
+
+ stdx::thread _backgroundThread;
+ std::shared_ptr<RefreshFunc> _doRefresh;
+
+ bool _hasSeenKeys = false;
+ bool _inShutdown = false;
+ };
+
+ /**
+ * Return a key that is valid for the given time and also matches the keyId.
+ */
+ StatusWith<KeysCollectionDocument> _getKeyWithKeyIdCheck(long long keyId,
+ const LogicalTime& forThisTime);
+
+ /**
+ * Return a key that is valid for the given time.
+ */
+ StatusWith<KeysCollectionDocument> _getKey(const LogicalTime& forThisTime);
+
+ std::unique_ptr<KeysCollectionClient> _client;
+ const std::string _purpose;
+ const Seconds _keyValidForInterval;
+
+ // No mutex needed since the members below have their own mutexes.
+ KeysCollectionCacheReader _keysCache;
+ PeriodicRunner _refresher;
};
} // namespace mongo
diff --git a/src/mongo/db/keys_collection_manager_direct.cpp b/src/mongo/db/keys_collection_manager_direct.cpp
deleted file mode 100644
index 60cf5672e6e..00000000000
--- a/src/mongo/db/keys_collection_manager_direct.cpp
+++ /dev/null
@@ -1,137 +0,0 @@
-/**
- * Copyright (C) 2017 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/keys_collection_manager_direct.h"
-
-#include "mongo/db/dbdirectclient.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"
-
-namespace mongo {
-
-namespace {
-const char kLogicalTimeKeysCollection[] = "admin.system.keys";
-const int kMaxCachedKeys = 20;
-} // namespace
-
-KeysCollectionManagerDirect::KeysCollectionManagerDirect(std::string purpose,
- Seconds keyValidForInterval)
- : _purpose(std::move(purpose)),
- _keyValidForInterval(keyValidForInterval),
- _cache(kMaxCachedKeys) {}
-
-StatusWith<KeysCollectionDocument> KeysCollectionManagerDirect::getKeyForValidation(
- OperationContext* opCtx, long long keyId, const LogicalTime& forThisTime) {
- // First, attempt to find the key in our cache.
- {
- stdx::lock_guard<stdx::mutex> lk(_mutex);
- auto it = _cache.find(keyId);
- if (it != _cache.end()) {
- return it->second;
- }
- }
-
- // Query admin.system.keys for an active key with this id.
- DBDirectClient client(opCtx);
-
- BSONObjBuilder queryBuilder;
- queryBuilder.append("purpose", _purpose);
- queryBuilder.append("_id", keyId);
- queryBuilder.append("expiresAt", BSON("$gt" << forThisTime.asTimestamp()));
-
- auto cursor = client.query(KeysCollectionDocument::ConfigNS, queryBuilder.obj());
-
- if (!cursor->more()) {
- return {ErrorCodes::KeyNotFound, "Could not find matching key"};
- }
-
- // Parse the key.
- auto res = KeysCollectionDocument::fromBSON(cursor->next());
- if (!res.isOK()) {
- return res.getStatus();
- }
-
- // Add to our cache.
- {
- stdx::lock_guard<stdx::mutex> lk(_mutex);
- _cache.add(keyId, res.getValue());
- }
-
- return res.getValue();
-}
-
-StatusWith<KeysCollectionDocument> KeysCollectionManagerDirect::getKeyForSigning(
- OperationContext* opCtx, const LogicalTime& forThisTime) {
- // Search through the cache for active keys.
- {
- stdx::lock_guard<stdx::mutex> lk(_mutex);
- for (auto& it : _cache) {
- auto keyDoc = it.second;
- auto expiration = keyDoc.getExpiresAt();
- if (expiration > forThisTime) {
- return keyDoc;
- }
- }
- }
-
- // Query admin.system.keys for active keys.
- DBDirectClient client(opCtx);
-
- BSONObjBuilder queryBuilder;
- queryBuilder.append("purpose", _purpose);
- queryBuilder.append("expiresAt", BSON("$gt" << forThisTime.asTimestamp()));
-
- auto cursor = client.query(KeysCollectionDocument::ConfigNS, queryBuilder.obj());
-
- if (!cursor->more()) {
- return {ErrorCodes::KeyNotFound, "Could not find an active key for signing"};
- }
-
- // Parse and return the key.
- auto res = KeysCollectionDocument::fromBSON(cursor->next());
- if (!res.isOK()) {
- return res.getStatus();
- }
-
- auto keyDoc = res.getValue();
-
- // Add to our cache.
- {
- stdx::lock_guard<stdx::mutex> lk(_mutex);
- _cache.add(keyDoc.getKeyId(), keyDoc);
- }
-
- return keyDoc;
-}
-
-} // namespace mongo
diff --git a/src/mongo/db/keys_collection_manager_direct.h b/src/mongo/db/keys_collection_manager_direct.h
deleted file mode 100644
index 2f1228ff056..00000000000
--- a/src/mongo/db/keys_collection_manager_direct.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/**
- * Copyright (C) 2017 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 <memory>
-
-#include "mongo/db/keys_collection_document.h"
-#include "mongo/db/keys_collection_manager.h"
-#include "mongo/stdx/mutex.h"
-#include "mongo/util/lru_cache.h"
-
-namespace mongo {
-
-class OperationContext;
-class LogicalTime;
-class ServiceContext;
-
-/**
- * This implementation of the KeysCollectionManager uses DBDirectclient to query the
- * keys collection local to this server.
- */
-class KeysCollectionManagerDirect : public KeysCollectionManager {
-public:
- KeysCollectionManagerDirect(std::string purpose, Seconds keyValidForInterval);
-
- /**
- * Return a key that is valid for the given time and also matches the keyId.
- */
- StatusWith<KeysCollectionDocument> getKeyForValidation(OperationContext* opCtx,
- long long keyId,
- const LogicalTime& forThisTime) override;
-
- /**
- * Returns a key that is valid for the given time.
- */
- StatusWith<KeysCollectionDocument> getKeyForSigning(OperationContext* opCtx,
- const LogicalTime& forThisTime) override;
-
-private:
- const std::string _purpose;
- const Seconds _keyValidForInterval;
-
- stdx::mutex _mutex;
- LRUCache<long long, KeysCollectionDocument> _cache;
-};
-
-} // namespace mongo
diff --git a/src/mongo/db/keys_collection_manager_sharding.cpp b/src/mongo/db/keys_collection_manager_sharding.cpp
deleted file mode 100644
index 8baf74d073c..00000000000
--- a/src/mongo/db/keys_collection_manager_sharding.cpp
+++ /dev/null
@@ -1,350 +0,0 @@
-/**
- * Copyright (C) 2017 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::kDefault
-
-#include "mongo/platform/basic.h"
-
-#include "mongo/db/keys_collection_manager_sharding.h"
-
-#include "mongo/db/keys_collection_cache_reader.h"
-#include "mongo/db/keys_collection_cache_reader_and_updater.h"
-#include "mongo/db/keys_collection_client.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/log.h"
-#include "mongo/util/mongoutils/str.h"
-#include "mongo/util/time_support.h"
-
-namespace mongo {
-
-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
-
-KeysCollectionManagerSharding::KeysCollectionManagerSharding(
- std::string purpose, std::unique_ptr<KeysCollectionClient> client, Seconds keyValidForInterval)
- : _client(std::move(client)),
- _purpose(std::move(purpose)),
- _keyValidForInterval(keyValidForInterval),
- _keysCache(_purpose, _client.get()) {}
-
-
-StatusWith<KeysCollectionDocument> KeysCollectionManagerSharding::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> KeysCollectionManagerSharding::getKeyForSigning(
- OperationContext* opCtx, const LogicalTime& forThisTime) {
- return _getKey(forThisTime);
-}
-
-StatusWith<KeysCollectionDocument> KeysCollectionManagerSharding::_getKeyWithKeyIdCheck(
- long long keyId, const LogicalTime& forThisTime) {
- auto keyStatus = _keysCache.getKeyById(keyId, forThisTime);
-
- if (!keyStatus.isOK()) {
- return keyStatus;
- }
-
- return keyStatus.getValue();
-}
-
-StatusWith<KeysCollectionDocument> KeysCollectionManagerSharding::_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 KeysCollectionManagerSharding::refreshNow(OperationContext* opCtx) {
- _refresher.refreshNow(opCtx);
-}
-
-void KeysCollectionManagerSharding::startMonitoring(ServiceContext* service) {
- _keysCache.resetCache();
- _refresher.setFunc([this](OperationContext* opCtx) { return _keysCache.refresh(opCtx); });
- _refresher.start(
- service, str::stream() << "monitoring keys for " << _purpose, _keyValidForInterval);
-}
-
-void KeysCollectionManagerSharding::stopMonitoring() {
- _refresher.stop();
-}
-
-void KeysCollectionManagerSharding::enableKeyGenerator(OperationContext* opCtx, bool doEnable) {
- if (doEnable) {
- _refresher.switchFunc(opCtx, [this](OperationContext* opCtx) {
- KeysCollectionCacheReaderAndUpdater keyGenerator(
- _purpose, _client.get(), _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 KeysCollectionManagerSharding::hasSeenKeys() {
- return _refresher.hasSeenKeys();
-}
-
-void KeysCollectionManagerSharding::PeriodicRunner::refreshNow(OperationContext* opCtx) {
- auto refreshRequest = [this]() {
- stdx::lock_guard<stdx::mutex> lk(_mutex);
-
- if (_inShutdown) {
- uasserted(ErrorCodes::ShutdownInProgress,
- "aborting keys cache refresh because node is shutting down");
- }
-
- 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)) {
- uasserted(ErrorCodes::ExceededTimeLimit, "timed out waiting for refresh");
- }
-}
-
-void KeysCollectionManagerSharding::PeriodicRunner::_doPeriodicRefresh(
- ServiceContext* service, std::string threadName, Milliseconds refreshInterval) {
- Client::initThreadIfNotAlready(threadName);
-
- while (true) {
- 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.getVersion() ==
- ServerGlobalParams::FeatureCompatibility::Version::kFullyUpgradedTo36) {
- auto opCtx = cc().makeOperationContext();
-
- 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;
- }
-
- // Use a new opCtx so we won't be holding any RecoveryUnit while this thread goes to sleep.
- auto opCtx = cc().makeOperationContext();
-
- 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 KeysCollectionManagerSharding::PeriodicRunner::setFunc(RefreshFunc newRefreshStrategy) {
- stdx::lock_guard<stdx::mutex> lock(_mutex);
- _doRefresh = std::make_shared<RefreshFunc>(std::move(newRefreshStrategy));
- _refreshNeededCV.notify_all();
-}
-
-void KeysCollectionManagerSharding::PeriodicRunner::switchFunc(OperationContext* opCtx,
- RefreshFunc newRefreshStrategy) {
- setFunc(newRefreshStrategy);
-}
-
-void KeysCollectionManagerSharding::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([this, service, threadName, refreshInterval] {
- _doPeriodicRefresh(service, threadName, refreshInterval);
- });
-}
-
-void KeysCollectionManagerSharding::PeriodicRunner::stop() {
- {
- stdx::lock_guard<stdx::mutex> lock(_mutex);
- if (!_backgroundThread.joinable()) {
- return;
- }
-
- _inShutdown = true;
- _refreshNeededCV.notify_all();
- }
-
- _backgroundThread.join();
-}
-
-bool KeysCollectionManagerSharding::PeriodicRunner::hasSeenKeys() {
- stdx::lock_guard<stdx::mutex> lock(_mutex);
- return _hasSeenKeys;
-}
-
-} // namespace mongo
diff --git a/src/mongo/db/keys_collection_manager_sharding.h b/src/mongo/db/keys_collection_manager_sharding.h
deleted file mode 100644
index d1ebd96e540..00000000000
--- a/src/mongo/db/keys_collection_manager_sharding.h
+++ /dev/null
@@ -1,197 +0,0 @@
-/**
- * Copyright (C) 2017 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 <memory>
-
-#include "mongo/base/status_with.h"
-#include "mongo/db/keys_collection_cache_reader.h"
-#include "mongo/db/keys_collection_cache_reader_and_updater.h"
-#include "mongo/db/keys_collection_document.h"
-#include "mongo/db/keys_collection_manager.h"
-#include "mongo/stdx/functional.h"
-#include "mongo/stdx/mutex.h"
-#include "mongo/stdx/thread.h"
-#include "mongo/util/concurrency/notification.h"
-#include "mongo/util/duration.h"
-
-namespace mongo {
-
-class OperationContext;
-class LogicalTime;
-class ServiceContext;
-class KeysCollectionClient;
-
-/**
- * This implementation of the KeysCollectionManager queries the config servers for keys.
- * It maintains in internal background thread that is used to periodically refresh
- * the local key cache against the keys collection stored on the config servers.
- */
-class KeysCollectionManagerSharding : public KeysCollectionManager {
-public:
- static const Seconds kKeyValidInterval;
-
- KeysCollectionManagerSharding(std::string purpose,
- std::unique_ptr<KeysCollectionClient> client,
- Seconds keyValidForInterval);
-
- /**
- * Return a key that is valid for the given time and also matches the keyId. Note that this call
- * can block if it will need to do a refresh.
- *
- * Throws ErrorCode::ExceededTimeLimit if it times out.
- */
- StatusWith<KeysCollectionDocument> getKeyForValidation(OperationContext* opCtx,
- long long keyId,
- const LogicalTime& forThisTime) override;
-
- /**
- * Returns a key that is valid for the given time. Note that unlike getKeyForValidation, this
- * will never do a refresh.
- *
- * Throws ErrorCode::ExceededTimeLimit if it times out.
- */
- StatusWith<KeysCollectionDocument> getKeyForSigning(OperationContext* opCtx,
- const LogicalTime& forThisTime) override;
-
- /**
- * Request this manager to perform a refresh.
- */
- void refreshNow(OperationContext* opCtx);
-
- /**
- * Starts a background thread that will constantly update the internal cache of keys.
- *
- * Cannot call this after stopMonitoring was called at least once.
- */
- void startMonitoring(ServiceContext* service);
-
- /**
- * Stops the background thread updating the cache.
- */
- void stopMonitoring();
-
- /**
- * Enable writing new keys to the config server primary. Should only be called if current node
- * is the config primary.
- */
- void enableKeyGenerator(OperationContext* opCtx, bool doEnable);
-
- /**
- * Returns true if the refresher has ever successfully returned keys from the config server.
- */
- bool hasSeenKeys();
-
-private:
- /**
- * This is responsible for periodically performing refresh in the background.
- */
- class PeriodicRunner {
- public:
- using RefreshFunc = stdx::function<StatusWith<KeysCollectionDocument>(OperationContext*)>;
-
- /**
- * Preemptively inform the monitoring thread it needs to perform a refresh. Returns an
- * object
- * that gets notified after the current round of refresh is over. Note that being notified
- * can
- * mean either of these things:
- *
- * 1. An error occurred and refresh was not performed.
- * 2. No error occurred but no new key was found.
- * 3. No error occurred and new keys were found.
- */
- void refreshNow(OperationContext* opCtx);
-
- /**
- * Sets the refresh function to use.
- * Should only be used to bootstrap this refresher with initial strategy.
- */
- void setFunc(RefreshFunc newRefreshStrategy);
-
- /**
- * Switches the current strategy with a new one. This also waits to make sure that the old
- * strategy is not being used and will no longer be used after this call.
- */
- void switchFunc(OperationContext* opCtx, RefreshFunc newRefreshStrategy);
-
- /**
- * Starts the refresh thread.
- */
- void start(ServiceContext* service,
- const std::string& threadName,
- Milliseconds refreshInterval);
-
- /**
- * Stops the refresh thread.
- */
- void stop();
-
- /**
- * Returns true if keys have ever successfully been returned from the config server.
- */
- bool hasSeenKeys();
-
- private:
- void _doPeriodicRefresh(ServiceContext* service,
- std::string threadName,
- Milliseconds refreshInterval);
-
- stdx::mutex _mutex; // protects all the member variables below.
- std::shared_ptr<Notification<void>> _refreshRequest;
- stdx::condition_variable _refreshNeededCV;
-
- stdx::thread _backgroundThread;
- std::shared_ptr<RefreshFunc> _doRefresh;
-
- bool _hasSeenKeys = false;
- bool _inShutdown = false;
- };
-
- /**
- * Return a key that is valid for the given time and also matches the keyId.
- */
- StatusWith<KeysCollectionDocument> _getKeyWithKeyIdCheck(long long keyId,
- const LogicalTime& forThisTime);
-
- /**
- * Return a key that is valid for the given time.
- */
- StatusWith<KeysCollectionDocument> _getKey(const LogicalTime& forThisTime);
-
- std::unique_ptr<KeysCollectionClient> _client;
- const std::string _purpose;
- const Seconds _keyValidForInterval;
-
- // No mutex needed since the members below have their own mutexes.
- KeysCollectionCacheReader _keysCache;
- PeriodicRunner _refresher;
-};
-
-} // namespace mongo
diff --git a/src/mongo/db/keys_collection_manager_sharding_test.cpp b/src/mongo/db/keys_collection_manager_sharding_test.cpp
index 0ba9588ce50..0646ea41167 100644
--- a/src/mongo/db/keys_collection_manager_sharding_test.cpp
+++ b/src/mongo/db/keys_collection_manager_sharding_test.cpp
@@ -34,7 +34,7 @@
#include "mongo/db/jsobj.h"
#include "mongo/db/keys_collection_client_sharded.h"
#include "mongo/db/keys_collection_document.h"
-#include "mongo/db/keys_collection_manager_sharding.h"
+#include "mongo/db/keys_collection_manager.h"
#include "mongo/db/logical_clock.h"
#include "mongo/db/namespace_string.h"
#include "mongo/db/operation_context.h"
@@ -51,7 +51,7 @@ namespace mongo {
class KeysManagerShardedTest : public ConfigServerTestFixture {
public:
- KeysCollectionManagerSharding* keyManager() {
+ KeysCollectionManager* keyManager() {
return _keyManager.get();
}
@@ -71,8 +71,8 @@ protected:
operationContext()->getServiceContext()->setFastClockSource(std::move(clockSource));
auto catalogClient = stdx::make_unique<KeysCollectionClientSharded>(
Grid::get(operationContext())->catalogClient());
- _keyManager = stdx::make_unique<KeysCollectionManagerSharding>(
- "dummy", std::move(catalogClient), Seconds(1));
+ _keyManager =
+ stdx::make_unique<KeysCollectionManager>("dummy", std::move(catalogClient), Seconds(1));
}
void tearDown() override {
@@ -88,7 +88,7 @@ protected:
}
private:
- std::unique_ptr<KeysCollectionManagerSharding> _keyManager;
+ std::unique_ptr<KeysCollectionManager> _keyManager;
};
TEST_F(KeysManagerShardedTest, GetKeyForValidationTimesOutIfRefresherIsNotRunning) {
diff --git a/src/mongo/db/keys_collection_manager_zero.cpp b/src/mongo/db/keys_collection_manager_zero.cpp
deleted file mode 100644
index 5f773b0152d..00000000000
--- a/src/mongo/db/keys_collection_manager_zero.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-/**
- * Copyright (C) 2017 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/keys_collection_manager_zero.h"
-
-#include "mongo/db/keys_collection_document.h"
-
-namespace mongo {
-
-namespace {
-
-const TimeProofService::Key kTimeProofServiceKey{};
-const long long kKeyId = 1;
-
-} // namespace
-
-KeysCollectionManagerZero::KeysCollectionManagerZero(std::string purpose)
- : _purpose(std::move(purpose)) {}
-
-StatusWith<KeysCollectionDocument> KeysCollectionManagerZero::getKeyForValidation(
- OperationContext* opCtx, long long keyId, const LogicalTime& forThisTime) {
- return KeysCollectionDocument(keyId, _purpose, kTimeProofServiceKey, forThisTime);
-}
-
-StatusWith<KeysCollectionDocument> KeysCollectionManagerZero::getKeyForSigning(
- OperationContext* opCtx, const LogicalTime& forThisTime) {
- return KeysCollectionDocument(kKeyId, _purpose, kTimeProofServiceKey, forThisTime);
-}
-
-} // namespace mongo
diff --git a/src/mongo/db/keys_collection_manager_zero.h b/src/mongo/db/keys_collection_manager_zero.h
deleted file mode 100644
index 71f2dcc89ee..00000000000
--- a/src/mongo/db/keys_collection_manager_zero.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/**
- * Copyright (C) 2017 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 <memory>
-#include <string>
-
-#include "mongo/db/keys_collection_document.h"
-#include "mongo/db/keys_collection_manager.h"
-
-namespace mongo {
-
-class OperationContext;
-class LogicalTime;
-class ServiceContext;
-
-/**
- * This implementation of the KeysCollectionManager always returns a zeroed key. This is a
- * transitional type to bridge the gap until we decide how to store and rotate keys in standalones
- * and non-clustered replica sets.
- */
-class KeysCollectionManagerZero : public KeysCollectionManager {
-public:
- KeysCollectionManagerZero(std::string purpose);
-
- /**
- * Return a key that is valid for the given time and also matches the keyId.
- */
- StatusWith<KeysCollectionDocument> getKeyForValidation(OperationContext* opCtx,
- long long keyId,
- const LogicalTime& forThisTime) override;
-
- /**
- * Returns a key that is valid for the given time.
- */
- StatusWith<KeysCollectionDocument> getKeyForSigning(OperationContext* opCtx,
- const LogicalTime& forThisTime) override;
-
-private:
- std::string _purpose;
-};
-
-} // namespace mongo
diff --git a/src/mongo/db/logical_time_validator.cpp b/src/mongo/db/logical_time_validator.cpp
index 5c751eddf06..27133b5fcc0 100644
--- a/src/mongo/db/logical_time_validator.cpp
+++ b/src/mongo/db/logical_time_validator.cpp
@@ -37,7 +37,7 @@
#include "mongo/db/auth/action_type.h"
#include "mongo/db/auth/authorization_session.h"
#include "mongo/db/auth/privilege.h"
-#include "mongo/db/keys_collection_manager_sharding.h"
+#include "mongo/db/keys_collection_manager.h"
#include "mongo/db/operation_context.h"
#include "mongo/db/service_context.h"
#include "mongo/util/assert_util.h"
@@ -80,8 +80,7 @@ void LogicalTimeValidator::set(ServiceContext* service,
validator = std::move(newValidator);
}
-LogicalTimeValidator::LogicalTimeValidator(
- std::shared_ptr<KeysCollectionManagerSharding> keyManager)
+LogicalTimeValidator::LogicalTimeValidator(std::shared_ptr<KeysCollectionManager> keyManager)
: _keyManager(keyManager) {}
SignedLogicalTime LogicalTimeValidator::_getProof(const KeysCollectionDocument& keyDoc,
@@ -216,7 +215,7 @@ void LogicalTimeValidator::resetKeyManager() {
}
}
-std::shared_ptr<KeysCollectionManagerSharding> LogicalTimeValidator::_getKeyManagerCopy() {
+std::shared_ptr<KeysCollectionManager> LogicalTimeValidator::_getKeyManagerCopy() {
stdx::lock_guard<stdx::mutex> lk(_mutexKeyManager);
invariant(_keyManager);
return _keyManager;
diff --git a/src/mongo/db/logical_time_validator.h b/src/mongo/db/logical_time_validator.h
index 43d1c1c2678..0598fa8ec44 100644
--- a/src/mongo/db/logical_time_validator.h
+++ b/src/mongo/db/logical_time_validator.h
@@ -39,7 +39,7 @@ namespace mongo {
class OperationContext;
class ServiceContext;
class KeysCollectionDocument;
-class KeysCollectionManagerSharding;
+class KeysCollectionManager;
/**
* This is responsible for signing cluster times that can be used to sent to other servers and
@@ -56,7 +56,7 @@ public:
* Constructs a new LogicalTimeValidator that uses the given key manager. The passed-in
* key manager must outlive this object.
*/
- explicit LogicalTimeValidator(std::shared_ptr<KeysCollectionManagerSharding> keyManager);
+ explicit LogicalTimeValidator(std::shared_ptr<KeysCollectionManager> keyManager);
/**
* Tries to sign the newTime with a valid signature. Can return an empty signature and keyId
@@ -121,7 +121,7 @@ private:
/**
* Returns the copy of the _keyManager to work when its reset by resetKeyManager call.
*/
- std::shared_ptr<KeysCollectionManagerSharding> _getKeyManagerCopy();
+ std::shared_ptr<KeysCollectionManager> _getKeyManagerCopy();
SignedLogicalTime _getProof(const KeysCollectionDocument& keyDoc, LogicalTime newTime);
@@ -130,7 +130,7 @@ private:
stdx::mutex _mutexKeyManager; // protects _keyManager
SignedLogicalTime _lastSeenValidTime;
TimeProofService _timeProofService;
- std::shared_ptr<KeysCollectionManagerSharding> _keyManager;
+ std::shared_ptr<KeysCollectionManager> _keyManager;
};
} // namespace mongo
diff --git a/src/mongo/db/logical_time_validator_test.cpp b/src/mongo/db/logical_time_validator_test.cpp
index 1bb46ba0802..bbd7826eae8 100644
--- a/src/mongo/db/logical_time_validator_test.cpp
+++ b/src/mongo/db/logical_time_validator_test.cpp
@@ -31,7 +31,6 @@
#include "mongo/bson/timestamp.h"
#include "mongo/db/keys_collection_client_sharded.h"
#include "mongo/db/keys_collection_manager.h"
-#include "mongo/db/keys_collection_manager_sharding.h"
#include "mongo/db/logical_clock.h"
#include "mongo/db/logical_time.h"
#include "mongo/db/logical_time_validator.h"
@@ -73,7 +72,7 @@ protected:
const LogicalTime currentTime(LogicalTime(Timestamp(1, 0)));
LogicalClock::get(operationContext())->setClusterTimeFromTrustedSource(currentTime);
- _keyManager = std::make_shared<KeysCollectionManagerSharding>(
+ _keyManager = std::make_shared<KeysCollectionManager>(
"dummy", std::move(catalogClient), Seconds(1000));
_validator = stdx::make_unique<LogicalTimeValidator>(_keyManager);
_validator->init(operationContext()->getServiceContext());
@@ -99,7 +98,7 @@ protected:
private:
std::unique_ptr<LogicalTimeValidator> _validator;
- std::shared_ptr<KeysCollectionManagerSharding> _keyManager;
+ std::shared_ptr<KeysCollectionManager> _keyManager;
};
TEST_F(LogicalTimeValidatorTest, GetTimeWithIncreasingTimes) {
diff --git a/src/mongo/db/service_context.h b/src/mongo/db/service_context.h
index 6fa9fa96157..681bbdc6262 100644
--- a/src/mongo/db/service_context.h
+++ b/src/mongo/db/service_context.h
@@ -31,7 +31,6 @@
#include <vector>
#include "mongo/base/disallow_copying.h"
-#include "mongo/db/keys_collection_manager.h"
#include "mongo/db/logical_session_id.h"
#include "mongo/db/storage/storage_engine.h"
#include "mongo/platform/atomic_word.h"
diff --git a/src/mongo/db/service_liason.cpp b/src/mongo/db/service_liason.cpp
index 22edb98b5c2..ade0f4b65f6 100644
--- a/src/mongo/db/service_liason.cpp
+++ b/src/mongo/db/service_liason.cpp
@@ -30,7 +30,6 @@
#include "mongo/db/service_liason.h"
-#include "mongo/db/keys_collection_manager_zero.h"
#include "mongo/db/logical_clock.h"
#include "mongo/db/service_context.h"