summaryrefslogtreecommitdiff
path: root/src/mongo/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/util')
-rw-r--r--src/mongo/util/invalidating_lru_cache.h56
-rw-r--r--src/mongo/util/read_through_cache.h44
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), &currentTime, &currentTimeInStore);
@@ -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), &currentTime, &currentTimeInStore);
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