diff options
author | Cheahuychou Mao <mao.cheahuychou@gmail.com> | 2021-01-11 05:14:06 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2021-01-15 22:47:49 +0000 |
commit | ae738118f9f8f6ef93bc4482489cab9955a2bcb1 (patch) | |
tree | 3b6b21db4f7766de948666b6b5b188890f58dd35 /src/mongo/db/keys_collection_cache.cpp | |
parent | f99876a23cd41e89331a2fb2a3c3d799e2b514a7 (diff) | |
download | mongo-ae738118f9f8f6ef93bc4482489cab9955a2bcb1.tar.gz |
SERVER-53403 Support validating cluster times with keys from external_validation_keys
Diffstat (limited to 'src/mongo/db/keys_collection_cache.cpp')
-rw-r--r-- | src/mongo/db/keys_collection_cache.cpp | 127 |
1 files changed, 98 insertions, 29 deletions
diff --git a/src/mongo/db/keys_collection_cache.cpp b/src/mongo/db/keys_collection_cache.cpp index 5cf62f8da12..87f9e798a33 100644 --- a/src/mongo/db/keys_collection_cache.cpp +++ b/src/mongo/db/keys_collection_cache.cpp @@ -42,20 +42,6 @@ KeysCollectionCache::KeysCollectionCache(std::string purpose, KeysCollectionClie : _purpose(std::move(purpose)), _client(client) {} StatusWith<KeysCollectionDocument> KeysCollectionCache::refresh(OperationContext* opCtx) { - LogicalTime newerThanThis; - - decltype(_cache)::size_type originalSize = 0; - - { - stdx::lock_guard<Latch> lk(_cacheMutex); - auto iter = _cache.crbegin(); - if (iter != _cache.crend()) { - newerThanThis = iter->second.getExpiresAt(); - } - - originalSize = _cache.size(); - } - // Don't allow this to read during initial sync because it will read at the initialDataTimestamp // and that could conflict with reconstructing prepared transactions using the // initialDataTimestamp as the prepareTimestamp. @@ -65,7 +51,32 @@ StatusWith<KeysCollectionDocument> KeysCollectionCache::refresh(OperationContext "Cannot refresh keys collection cache during initial sync"}; } - auto refreshStatus = _client->getNewKeys(opCtx, _purpose, newerThanThis, true); + auto refreshStatus = _refreshExternalKeys(opCtx); + + if (!refreshStatus.isOK()) { + return refreshStatus; + } + + return _refreshInternalKeys(opCtx); +} + + +StatusWith<KeysCollectionDocument> KeysCollectionCache::_refreshInternalKeys( + OperationContext* opCtx) { + LogicalTime newerThanThis; + decltype(_internalKeysCache)::size_type originalSize = 0; + + { + stdx::lock_guard<Latch> lk(_cacheMutex); + auto iter = _internalKeysCache.crbegin(); + if (iter != _internalKeysCache.crend()) { + newerThanThis = iter->second.getExpiresAt(); + } + + originalSize = _internalKeysCache.size(); + } + + auto refreshStatus = _client->getNewInternalKeys(opCtx, _purpose, newerThanThis, true); if (!refreshStatus.isOK()) { return refreshStatus.getStatus(); @@ -74,9 +85,9 @@ StatusWith<KeysCollectionDocument> KeysCollectionCache::refresh(OperationContext auto& newKeys = refreshStatus.getValue(); stdx::lock_guard<Latch> lk(_cacheMutex); - if (originalSize > _cache.size()) { - // _cache cleared while we getting the new keys, just return the newest key without - // touching the _cache so the next refresh will populate it properly. + if (originalSize > _internalKeysCache.size()) { + // _internalKeysCache cleared while we were getting the new keys, just return the newest key + // without touching the _internalKeysCache so the next refresh will populate it properly. // Note: newKeys are sorted. if (!newKeys.empty()) { return std::move(newKeys.back()); @@ -84,38 +95,95 @@ StatusWith<KeysCollectionDocument> KeysCollectionCache::refresh(OperationContext } for (auto&& key : newKeys) { - _cache.emplace(std::make_pair(key.getExpiresAt(), std::move(key))); + _internalKeysCache.emplace(std::make_pair(key.getExpiresAt(), std::move(key))); } - if (_cache.empty()) { + if (_internalKeysCache.empty()) { return {ErrorCodes::KeyNotFound, "No keys found after refresh"}; } - return _cache.crbegin()->second; + return _internalKeysCache.crbegin()->second; +} + +Status KeysCollectionCache::_refreshExternalKeys(OperationContext* opCtx) { + decltype(_externalKeysCache)::size_type originalSize = 0; + + { + stdx::lock_guard<Latch> lk(_cacheMutex); + originalSize = _externalKeysCache.size(); + } + + auto refreshStatus = _client->getNewExternalKeys(opCtx, _purpose, LogicalTime(), true); + + if (!refreshStatus.isOK()) { + return refreshStatus.getStatus(); + } + + auto& newKeys = refreshStatus.getValue(); + + stdx::lock_guard<Latch> lk(_cacheMutex); + if (originalSize > _externalKeysCache.size()) { + // _externalKeysCache cleared while we were getting the new keys, just return so the next + // refresh will populate it properly. + return Status::OK(); + } + + for (auto&& key : newKeys) { + _externalKeysCache[key.getKeyId()].emplace(key.getReplicaSetName(), std::move(key)); + } + + return Status::OK(); } -StatusWith<KeysCollectionDocument> KeysCollectionCache::getKeyById(long long keyId, - const LogicalTime& forThisTime) { +StatusWith<KeysCollectionDocument> KeysCollectionCache::getInternalKeyById( + long long keyId, const LogicalTime& forThisTime) { stdx::lock_guard<Latch> lk(_cacheMutex); - for (auto iter = _cache.lower_bound(forThisTime); iter != _cache.cend(); ++iter) { + for (auto iter = _internalKeysCache.lower_bound(forThisTime); iter != _internalKeysCache.cend(); + ++iter) { if (iter->second.getKeyId() == keyId) { return iter->second; } } return {ErrorCodes::KeyNotFound, - str::stream() << "Cache Reader No keys found for " << _purpose + str::stream() << "Cache Reader No internal keys found for " << _purpose << " that is valid for time: " << forThisTime.toString() << " with id: " << keyId}; } -StatusWith<KeysCollectionDocument> KeysCollectionCache::getKey(const LogicalTime& forThisTime) { +StatusWith<std::vector<ExternalKeysCollectionDocument>> KeysCollectionCache::getExternalKeysById( + long long keyId, const LogicalTime& forThisTime) { + stdx::lock_guard<Latch> lk(_cacheMutex); + std::vector<ExternalKeysCollectionDocument> keys; + + auto keysIter = _externalKeysCache.find(keyId); + + if (keysIter == _externalKeysCache.end()) { + return {ErrorCodes::KeyNotFound, + str::stream() << "Cache Reader No external keys found for " << _purpose + << " with id: " << keyId}; + } + + invariant(!keysIter->second.empty()); + + for (auto keyIter = keysIter->second.begin(); keyIter != keysIter->second.end(); keyIter++) { + auto key = keyIter->second; + if (key.getExpiresAt() > forThisTime) { + keys.push_back(key); + } + } + + return std::move(keys); +} + +StatusWith<KeysCollectionDocument> KeysCollectionCache::getInternalKey( + const LogicalTime& forThisTime) { stdx::lock_guard<Latch> lk(_cacheMutex); - auto iter = _cache.upper_bound(forThisTime); + auto iter = _internalKeysCache.upper_bound(forThisTime); - if (iter == _cache.cend()) { + if (iter == _internalKeysCache.cend()) { return {ErrorCodes::KeyNotFound, str::stream() << "No key found that is valid for " << forThisTime.toString()}; } @@ -127,7 +195,8 @@ void KeysCollectionCache::resetCache() { // keys that read with non majority readConcern level can be rolled back. if (!_client->supportsMajorityReads()) { stdx::lock_guard<Latch> lk(_cacheMutex); - _cache.clear(); + _internalKeysCache.clear(); + _externalKeysCache.clear(); } } |