KeysCollectionManager is installed on the service context so the LogicalClock can get the key that matches the signature generation.
Its also owns and manages KeysCollection
Pseudo code:
KeysCollectionManager { public: // for reading StatusWith<KeysCollectionDocument> getKeyForValidation(OperationContext* opCtx, long long keyId, const LogicalTime& forThisTime) { auto keyStatus = _getKeyWithKeyIdCheck(keyId, forThisTime); if (keyStatus != ErrorCodes::KeyNotFound) { return keyStatus; } auto refreshRequest = _requestRefresh(); // note: waitFor waits min(maxTimeMS, deadline) if (!refreshRequest.waitFor(opCtx, kDeadline)) { // return refresh interrupted/timed out } return _getKeyWithKeyIdCheck(keyId, forThisTime); } // for signing StatusWith<KeysCollectionDocument> getKeyForSigning(OperationContext* opCtx, const LogicalTime& forThisTime) { auto keyStatus = _getKey(forThisTime); if (keyStatus != ErrorCodes::KeyNotFound) { return keyStatus; } { // refresh retry logic until key.expiresAt > forThisTime or timeout } return _getKey(forThisTime); } void start(ServiceContext*); // start bg refresher void shutDown(); // shutdown bg refresher void switchMode(Mode); // switch between reader or updater private: void backgroundThread() { // consider moving thread logic to separate nested class // all necessary setup while (true) { auto opCtx = makeOperationContext(); std::shared_ptr<KeysCollectionCache> currentCacheImpl; { std::lock_guard<std::mutex> lock(_mutex); currentCacheImpl = _keysCache; } auto latestKey = currentCacheImpl->refresh(opCtx); if (!latestKey.isOK()) { // return if nextWakeUp returns inShutdown // add back-off? continue; } { std::lock_guard<std::mutex> lock(_mutex); if (_refreshRequest) { _refreshRequest->notification.set(); _refreshRequest.reset(); } } auto nextWakeup = howMuchSleepNeedFor(latestKey.expiresAt); // Add backoff to nextWakeup if it has a very small value in a row to avoid spinning. MONGO_IDLE_THREAD_BLOCK; auto status = opCtx.waitFor(nextWakeup); // check status for shutdown } } std::shared_ptr<Notification> _requestRefresh() { std::lock_guard<std::mutex> lock(_mutex); if (_refreshRequest) { return _refreshRequest; } _refreshRequest = stdx::make_shared<Notification>(); return _refreshRequest; } StatusWith<KeysCollectionDocument> _getKeyWithKeyIdCheck(long long keyId, const LogicalTime& forThisTime) { auto keyStatus = _getKey(forThisTime); if (!keyStatus.isOK()) { return keyStatus; } auto key = keyStatus.getValue(); if (keyId == key.keyId) { return _key; } if (key.keyId > keyId) return ErrorCodes::OldKey; // caller should decide what to do // Key not expired but keyId does not match! return ErrorCodes::KeyNotFound; } StatusWith<KeysCollectionDocument> _getKey(const LogicalTime& forThisTime) { std::lock_guard<std::mutex> lock(_mutex); auto key = _keysCache.getKey(forThisTime); if (key.expiresAt < forThisTime) { return ErrorCodes::KeyNotFound; } return key; } stdx::mutex _mutex; std::shared_ptr<Notification> _refreshRequest; std::shared_ptr<KeysCollectionCache> _keysCache; }
- is related to
-
SERVER-28435 Implement KeysCollectionCacheReader
- Closed