diff options
author | Kevin Pulo <kevin.pulo@mongodb.com> | 2020-09-16 16:55:25 +1000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-09-16 12:54:34 +0000 |
commit | 5a1953c4ae4416a60c45c5c90a210bd84b352032 (patch) | |
tree | 8f6865fcacb0a3adddee1357e8b6b8163fe6fd1d /src/mongo/util | |
parent | cb3d67879708a44c8ec77247017e6e1b9b14dec6 (diff) | |
download | mongo-5a1953c4ae4416a60c45c5c90a210bd84b352032.tar.gz |
SERVER-46202 Implement ShardRegistry on top of ReadThroughCache
Diffstat (limited to 'src/mongo/util')
-rw-r--r-- | src/mongo/util/invalidating_lru_cache.h | 56 | ||||
-rw-r--r-- | src/mongo/util/read_through_cache.h | 44 |
2 files changed, 80 insertions, 20 deletions
diff --git a/src/mongo/util/invalidating_lru_cache.h b/src/mongo/util/invalidating_lru_cache.h index c8ead4adecc..2852313ef22 100644 --- a/src/mongo/util/invalidating_lru_cache.h +++ b/src/mongo/util/invalidating_lru_cache.h @@ -67,6 +67,18 @@ struct CacheNotCausallyConsistent { }; /** + * Helper for determining if a given type is CacheNotCausallyConsistent or not. + */ +template <typename T> +struct isCausallyConsistentImpl : std::true_type {}; + +template <> +struct isCausallyConsistentImpl<CacheNotCausallyConsistent> : std::false_type {}; + +template <class T> +inline constexpr bool isCausallyConsistent = isCausallyConsistentImpl<T>::value; + +/** * Specifies the desired causal consistency for calls to 'get' (and 'acquire', respectively in the * ReadThroughCache, which is its main consumer). */ @@ -200,12 +212,8 @@ public: // doesn't support pinning items. Their only usage must be in the authorization mananager // for the internal authentication user. explicit ValueHandle(Value&& value) - : _value(std::make_shared<StoredValue>(nullptr, - 0, - boost::none, - std::move(value), - CacheNotCausallyConsistent(), - CacheNotCausallyConsistent())) {} + : _value(std::make_shared<StoredValue>( + nullptr, 0, boost::none, std::move(value), Time(), Time())) {} explicit ValueHandle(Value&& value, const Time& t) : _value( @@ -218,9 +226,15 @@ public: } bool isValid() const { + invariant(bool(*this)); return _value->isValid.loadRelaxed(); } + const Time& getTime() const { + invariant(bool(*this)); + return _value->time; + } + Value* get() { invariant(bool(*this)); return &_value->value; @@ -260,13 +274,16 @@ public: * was called, it will become invalidated. * * The 'time' parameter is mandatory for causally-consistent caches, but not needed otherwise - * (since the time never changes). Using a default of '= CacheNotCausallyConsistent()' allows - * non-causally-consistent users to not have to pass a second parameter, but would fail - * compilation if causally-consistent users forget to pass it. + * (since the time never changes). */ - void insertOrAssign(const Key& key, - Value&& value, - const Time& time = CacheNotCausallyConsistent()) { + void insertOrAssign(const Key& key, Value&& value) { + MONGO_STATIC_ASSERT_MSG( + !isCausallyConsistent<Time>, + "Time must be passed to insertOrAssign on causally consistent caches"); + insertOrAssign(key, std::move(value), Time()); + } + + void insertOrAssign(const Key& key, Value&& value, const Time& time) { LockGuardWithPostUnlockDestructor guard(_mutex); Time currentTime, currentTimeInStore; _invalidate(&guard, key, _cache.find(key), ¤tTime, ¤tTimeInStore); @@ -307,13 +324,16 @@ public: * destroyed. * * The 'time' parameter is mandatory for causally-consistent caches, but not needed otherwise - * (since the time never changes). Using a default of '= CacheNotCausallyConsistent()' allows - * non-causally-consistent users to not have to pass a second parameter, but would fail - * compilation if causally-consistent users forget to pass it. + * (since the time never changes). */ - ValueHandle insertOrAssignAndGet(const Key& key, - Value&& value, - const Time& time = CacheNotCausallyConsistent()) { + ValueHandle insertOrAssignAndGet(const Key& key, Value&& value) { + MONGO_STATIC_ASSERT_MSG( + !isCausallyConsistent<Time>, + "Time must be passed to insertOrAssignAndGet on causally consistent caches"); + return insertOrAssignAndGet(key, std::move(value), Time()); + } + + ValueHandle insertOrAssignAndGet(const Key& key, Value&& value, const Time& time) { LockGuardWithPostUnlockDestructor guard(_mutex); Time currentTime, currentTimeInStore; _invalidate(&guard, key, _cache.find(key), ¤tTime, ¤tTimeInStore); diff --git a/src/mongo/util/read_through_cache.h b/src/mongo/util/read_through_cache.h index 72b3e7a5771..32efbc576ae 100644 --- a/src/mongo/util/read_through_cache.h +++ b/src/mongo/util/read_through_cache.h @@ -152,6 +152,10 @@ public: return _valueHandle.isValid(); } + const Time& getTime() const { + return _valueHandle.getTime(); + } + Value* get() { return &_valueHandle->value; } @@ -302,6 +306,33 @@ public: /** * Invalidates the given 'key' and immediately replaces it with a new value. + * + * The 'time' parameter is mandatory for causally-consistent caches, but not needed otherwise + * (since the time never changes). + */ + void insertOrAssign(const Key& key, Value&& newValue, Date_t updateWallClockTime) { + stdx::lock_guard lg(_mutex); + if (auto it = _inProgressLookups.find(key); it != _inProgressLookups.end()) + it->second->invalidateAndCancelCurrentLookupRound(lg); + _cache.insertOrAssign(key, {std::move(newValue), updateWallClockTime}); + } + + void insertOrAssign(const Key& key, + Value&& newValue, + Date_t updateWallClockTime, + const Time& time) { + stdx::lock_guard lg(_mutex); + if (auto it = _inProgressLookups.find(key); it != _inProgressLookups.end()) + it->second->invalidateAndCancelCurrentLookupRound(lg); + _cache.insertOrAssign(key, {std::move(newValue), updateWallClockTime}, time); + } + + /** + * Invalidates the given 'key' and immediately replaces it with a new value, returning a handle + * to the new value. + * + * The 'time' parameter is mandatory for causally-consistent caches, but not needed otherwise + * (since the time never changes). */ ValueHandle insertOrAssignAndGet(const Key& key, Value&& newValue, Date_t updateWallClockTime) { stdx::lock_guard lg(_mutex); @@ -310,6 +341,16 @@ public: return _cache.insertOrAssignAndGet(key, {std::move(newValue), updateWallClockTime}); } + ValueHandle insertOrAssignAndGet(const Key& key, + Value&& newValue, + Date_t updateWallClockTime, + const Time& time) { + stdx::lock_guard lg(_mutex); + if (auto it = _inProgressLookups.find(key); it != _inProgressLookups.end()) + it->second->invalidateAndCancelCurrentLookupRound(lg); + return _cache.insertOrAssignAndGet(key, {std::move(newValue), updateWallClockTime}, time); + } + /** * Indicates to the cache that the backing store has a newer version of 'key', corresponding to * 'newTime'. Subsequent calls to 'acquireAsync' with a causal consistency set to 'LatestKnown' @@ -377,9 +418,8 @@ public: return _cache.getCacheInfo(); } -protected: /** - * ReadThroughCache constructor, to be called by sub-classes, which implement 'lookup'. + * ReadThroughCache constructor. * * The 'mutex' is for the exclusive usage of the ReadThroughCache and must not be used in any * way by the implementing class. Having the mutex stored by the sub-class allows latch |