diff options
author | Kevin Pulo <kevin.pulo@mongodb.com> | 2020-07-07 22:02:16 +1000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-07-23 05:57:22 +0000 |
commit | 6b5b168edf19e336dacff0a8c54a9dd1f32ed1e2 (patch) | |
tree | bf2c72c3d19aecda97bad2f9e314a64f1bde10cf | |
parent | 00d90d78e84cdc16a03a2a5173ce797e3c3745b9 (diff) | |
download | mongo-6b5b168edf19e336dacff0a8c54a9dd1f32ed1e2.tar.gz |
SERVER-49189 pass current cachedValue (and time, if causally consistent) to ReadThroughCache::LookupFn
-rw-r--r-- | src/mongo/db/auth/authorization_manager_impl.cpp | 24 | ||||
-rw-r--r-- | src/mongo/db/auth/authorization_manager_impl.h | 8 | ||||
-rw-r--r-- | src/mongo/db/read_write_concern_defaults.cpp | 13 | ||||
-rw-r--r-- | src/mongo/util/invalidating_lru_cache.h | 15 | ||||
-rw-r--r-- | src/mongo/util/invalidating_lru_cache_test.cpp | 16 | ||||
-rw-r--r-- | src/mongo/util/net/ssl_manager_openssl.cpp | 4 | ||||
-rw-r--r-- | src/mongo/util/read_through_cache.h | 34 | ||||
-rw-r--r-- | src/mongo/util/read_through_cache_test.cpp | 181 |
8 files changed, 197 insertions, 98 deletions
diff --git a/src/mongo/db/auth/authorization_manager_impl.cpp b/src/mongo/db/auth/authorization_manager_impl.cpp index e793b33f51d..c7c27d3c461 100644 --- a/src/mongo/db/auth/authorization_manager_impl.cpp +++ b/src/mongo/db/auth/authorization_manager_impl.cpp @@ -656,16 +656,19 @@ AuthorizationManagerImpl::AuthSchemaVersionCache::AuthSchemaVersionCache( ServiceContext* service, ThreadPoolInterface& threadPool, AuthzManagerExternalState* externalState) - : ReadThroughCache( - _mutex, - service, - threadPool, - [this](OperationContext* opCtx, int unusedKey) { return _lookup(opCtx, unusedKey); }, - 1 /* cacheSize */), + : ReadThroughCache(_mutex, + service, + threadPool, + [this](OperationContext* opCtx, int key, const ValueHandle& cachedValue) { + return _lookup(opCtx, key, cachedValue); + }, + 1 /* cacheSize */), _externalState(externalState) {} AuthorizationManagerImpl::AuthSchemaVersionCache::LookupResult -AuthorizationManagerImpl::AuthSchemaVersionCache::_lookup(OperationContext* opCtx, int unusedKey) { +AuthorizationManagerImpl::AuthSchemaVersionCache::_lookup(OperationContext* opCtx, + int unusedKey, + const ValueHandle& unusedCachedValue) { invariant(unusedKey == 0); int authzVersion; @@ -683,8 +686,8 @@ AuthorizationManagerImpl::UserCacheImpl::UserCacheImpl( : UserCache(_mutex, service, threadPool, - [this](OperationContext* opCtx, const UserRequest& userReq) { - return _lookup(opCtx, userReq); + [this](OperationContext* opCtx, const UserRequest& userReq, UserHandle cachedUser) { + return _lookup(opCtx, userReq, cachedUser); }, cacheSize), _authSchemaVersionCache(authSchemaVersionCache), @@ -692,7 +695,8 @@ AuthorizationManagerImpl::UserCacheImpl::UserCacheImpl( AuthorizationManagerImpl::UserCacheImpl::LookupResult AuthorizationManagerImpl::UserCacheImpl::_lookup(OperationContext* opCtx, - const UserRequest& userReq) { + const UserRequest& userReq, + const UserHandle& unusedCachedUser) { LOGV2_DEBUG(20238, 1, "Getting user record", "user"_attr = userReq.name); // Number of times to retry a user document that fetches due to transient AuthSchemaIncompatible diff --git a/src/mongo/db/auth/authorization_manager_impl.h b/src/mongo/db/auth/authorization_manager_impl.h index 611aa427662..ba2d214d12a 100644 --- a/src/mongo/db/auth/authorization_manager_impl.h +++ b/src/mongo/db/auth/authorization_manager_impl.h @@ -158,7 +158,9 @@ private: // Even though the dist cache permits for lookup to return boost::none for non-existent // values, the contract of the authorization manager is that it should throw an exception if // the value can not be loaded, so if it returns, the value will always be set. - LookupResult _lookup(OperationContext* opCtx, int unusedKey); + LookupResult _lookup(OperationContext* opCtx, + int unusedKey, + const ValueHandle& unusedCachedValue); Mutex _mutex = MONGO_MAKE_LATCH("AuthorizationManagerImpl::AuthSchemaVersionDistCache::_mutex"); @@ -181,7 +183,9 @@ private: // Even though the dist cache permits for lookup to return boost::none for non-existent // values, the contract of the authorization manager is that it should throw an exception if // the value can not be loaded, so if it returns, the value will always be set. - LookupResult _lookup(OperationContext* opCtx, const UserRequest& user); + LookupResult _lookup(OperationContext* opCtx, + const UserRequest& user, + const UserHandle& unusedCachedUser); Mutex _mutex = MONGO_MAKE_LATCH("AuthorizationManagerImpl::UserDistCacheImpl::_mutex"); diff --git a/src/mongo/db/read_write_concern_defaults.cpp b/src/mongo/db/read_write_concern_defaults.cpp index 3c69751348a..5e675f6d627 100644 --- a/src/mongo/db/read_write_concern_defaults.cpp +++ b/src/mongo/db/read_write_concern_defaults.cpp @@ -237,12 +237,13 @@ ReadWriteConcernDefaults::~ReadWriteConcernDefaults() = default; ReadWriteConcernDefaults::Cache::Cache(ServiceContext* service, ThreadPoolInterface& threadPool, FetchDefaultsFn fetchDefaultsFn) - : ReadThroughCache( - _mutex, - service, - threadPool, - [this](OperationContext* opCtx, Type) { return LookupResult(lookup(opCtx)); }, - 1 /* cacheSize */), + : ReadThroughCache(_mutex, + service, + threadPool, + [this](OperationContext* opCtx, Type, const ValueHandle& unusedCachedValue) { + return LookupResult(lookup(opCtx)); + }, + 1 /* cacheSize */), _fetchDefaultsFn(std::move(fetchDefaultsFn)) {} boost::optional<RWConcernDefault> ReadWriteConcernDefaults::Cache::lookup(OperationContext* opCtx) { diff --git a/src/mongo/util/invalidating_lru_cache.h b/src/mongo/util/invalidating_lru_cache.h index 60c2341a295..a647a14de89 100644 --- a/src/mongo/util/invalidating_lru_cache.h +++ b/src/mongo/util/invalidating_lru_cache.h @@ -404,10 +404,11 @@ public: } /** - * If 'key' is in the store, returns its latest 'timeInStore', which can either be from the time - * of insertion or from the latest call to 'advanceTimeInStore'. Otherwise, returns Time(). + * If 'key' is in the store, returns its currently cached value and its latest 'timeInStore', + * which can either be from the time of insertion or from the latest call to + * 'advanceTimeInStore'. Otherwise, returns a nullptr ValueHandle and Time(). */ - Time getTimeInStore(const Key& key) { + std::pair<ValueHandle, Time> getCachedValueAndTime(const Key& key) { stdx::lock_guard<Latch> lg(_mutex); std::shared_ptr<StoredValue> storedValue; if (auto it = _cache.find(key); it != _cache.end()) { @@ -417,10 +418,12 @@ public: storedValue = it->second.lock(); } - if (storedValue) - return storedValue->timeInStore; + if (storedValue) { + auto timeInStore = storedValue->timeInStore; + return {ValueHandle(std::move(storedValue)), timeInStore}; + } - return Time(); + return {ValueHandle(nullptr), Time()}; } /** diff --git a/src/mongo/util/invalidating_lru_cache_test.cpp b/src/mongo/util/invalidating_lru_cache_test.cpp index 5d6f53470db..08fcc930486 100644 --- a/src/mongo/util/invalidating_lru_cache_test.cpp +++ b/src/mongo/util/invalidating_lru_cache_test.cpp @@ -269,14 +269,18 @@ TEST(InvalidatingLRUCacheTest, CausalConsistencyPreservedForEvictedCheckedOutKey // list cache.insertOrAssign(2, TestValue("Key 2 - Value @ TS 20"), Timestamp(20)); - ASSERT_EQ(Timestamp(10), cache.getTimeInStore(1)); + auto [cachedValueAtTS10, timeInStoreAtTS10] = cache.getCachedValueAndTime(1); + ASSERT_EQ(Timestamp(10), timeInStoreAtTS10); + ASSERT_EQ("Key 1 - Value @ TS 10", cachedValueAtTS10->value); ASSERT_EQ("Key 1 - Value @ TS 10", key1ValueAtTS10->value); ASSERT_EQ("Key 1 - Value @ TS 10", cache.get(1, CacheCausalConsistency::kLatestCached)->value); ASSERT_EQ("Key 1 - Value @ TS 10", cache.get(1, CacheCausalConsistency::kLatestKnown)->value); cache.advanceTimeInStore(1, Timestamp(11)); - ASSERT_EQ(Timestamp(11), cache.getTimeInStore(1)); + auto [cachedValueAtTS11, timeInStoreAtTS11] = cache.getCachedValueAndTime(1); + ASSERT_EQ(Timestamp(11), timeInStoreAtTS11); ASSERT(!key1ValueAtTS10.isValid()); + ASSERT_EQ("Key 1 - Value @ TS 10", cachedValueAtTS11->value); ASSERT_EQ("Key 1 - Value @ TS 10", key1ValueAtTS10->value); ASSERT_EQ("Key 1 - Value @ TS 10", cache.get(1, CacheCausalConsistency::kLatestCached)->value); ASSERT(!cache.get(1, CacheCausalConsistency::kLatestKnown)); @@ -427,14 +431,18 @@ TEST(InvalidatingLRUCacheTest, CacheSizeZeroCausalConsistency) { cache.advanceTimeInStore(100, Timestamp(30)); cache.insertOrAssign(100, TestValue("Value @ TS 30"), Timestamp(30)); - ASSERT_EQ(Timestamp(), cache.getTimeInStore(100)); + auto [cachedValueAtTS30, timeInStoreAtTS30] = cache.getCachedValueAndTime(100); + ASSERT_EQ(Timestamp(), timeInStoreAtTS30); + ASSERT(!cachedValueAtTS30); auto valueAtTS30 = cache.insertOrAssignAndGet(100, TestValue("Value @ TS 30"), Timestamp(30)); ASSERT_EQ("Value @ TS 30", cache.get(100, CacheCausalConsistency::kLatestCached)->value); ASSERT_EQ("Value @ TS 30", cache.get(100, CacheCausalConsistency::kLatestKnown)->value); cache.advanceTimeInStore(100, Timestamp(35)); - ASSERT_EQ(Timestamp(35), cache.getTimeInStore(100)); + auto [cachedValueAtTS35, timeInStoreAtTS35] = cache.getCachedValueAndTime(100); + ASSERT_EQ(Timestamp(35), timeInStoreAtTS35); + ASSERT_EQ("Value @ TS 30", cachedValueAtTS35->value); ASSERT_EQ("Value @ TS 30", cache.get(100, CacheCausalConsistency::kLatestCached)->value); ASSERT(!cache.get(100, CacheCausalConsistency::kLatestKnown)); diff --git a/src/mongo/util/net/ssl_manager_openssl.cpp b/src/mongo/util/net/ssl_manager_openssl.cpp index 8233d0fb472..2d0b1dce93e 100644 --- a/src/mongo/util/net/ssl_manager_openssl.cpp +++ b/src/mongo/util/net/ssl_manager_openssl.cpp @@ -964,7 +964,9 @@ public: } private: - static LookupResult _lookup(OperationContext* opCtx, const OCSPCacheKey& key) { + static LookupResult _lookup(OperationContext* opCtx, + const OCSPCacheKey& key, + const ValueHandle& unusedCachedValue) { // If there is a CRL file, we expect the CRL file to cover the certificate status // information, and therefore we don't need to make a roundtrip. if (!getSSLGlobalParams().sslCRLFile.empty()) { diff --git a/src/mongo/util/read_through_cache.h b/src/mongo/util/read_through_cache.h index 6a59f803c4b..159b106fcdd 100644 --- a/src/mongo/util/read_through_cache.h +++ b/src/mongo/util/read_through_cache.h @@ -97,6 +97,17 @@ protected: Mutex _cancelTokenMutex = MONGO_MAKE_LATCH("ReadThroughCacheBase::_cancelTokenMutex"); }; +template <typename Result, typename Key, typename Value, typename Time> +struct ReadThroughCacheLookupFnImpl { + using fn = unique_function<Result( + OperationContext*, const Key&, const Value& cachedValue, const Time& timeInStore)>; +}; + +template <typename Result, typename Key, typename Value> +struct ReadThroughCacheLookupFnImpl<Result, Key, Value, CacheNotCausallyConsistent> { + using fn = unique_function<Result(OperationContext*, const Key&, const Value& cachedValue)>; +}; + /** * Implements an (optionally) causally consistent read-through cache from Key to Value, built on top * of InvalidatingLRUCache. @@ -206,7 +217,9 @@ public: // contains the time that the store returned for the 'value'. Time t; }; - using LookupFn = unique_function<LookupResult(OperationContext*, const Key&)>; + + using LookupFn = + typename ReadThroughCacheLookupFnImpl<LookupResult, Key, ValueHandle, Time>::fn; // Exposed publicly so it can be unit-tested indepedently of the usages in this class. Must not // be used independently. @@ -247,8 +260,11 @@ public: return it->second->addWaiter(ul); // Schedule an asynchronous lookup for the key + auto [cachedValue, timeInStore] = _cache.getCachedValueAndTime(key); auto [it, emplaced] = _inProgressLookups.emplace( - key, std::make_unique<InProgressLookup>(*this, key, _cache.getTimeInStore(key))); + key, + std::make_unique<InProgressLookup>( + *this, key, ValueHandle(std::move(cachedValue)), timeInStore)); invariant(emplaced); auto& inProgressLookup = *it->second; auto sharedFutureToReturn = inProgressLookup.addWaiter(ul); @@ -498,8 +514,11 @@ private: template <typename Key, typename Value, typename Time> class ReadThroughCache<Key, Value, Time>::InProgressLookup { public: - InProgressLookup(ReadThroughCache& cache, Key key, Time minTimeInStore) - : _cache(cache), _key(std::move(key)), _minTimeInStore(std::move(minTimeInStore)) {} + InProgressLookup(ReadThroughCache& cache, Key key, ValueHandle cachedValue, Time minTimeInStore) + : _cache(cache), + _key(std::move(key)), + _cachedValue(std::move(cachedValue)), + _minTimeInStore(std::move(minTimeInStore)) {} Future<LookupResult> asyncLookupRound() { auto [promise, future] = makePromiseFuture<LookupResult>(); @@ -510,7 +529,11 @@ public: OperationContext * opCtx, const Status& status) mutable noexcept { promise.setWith([&] { uassertStatusOK(status); - return _cache._lookupFn(opCtx, _key); + if constexpr (std::is_same_v<Time, CacheNotCausallyConsistent>) { + return _cache._lookupFn(opCtx, _key, _cachedValue); + } else { + return _cache._lookupFn(opCtx, _key, _cachedValue, _minTimeInStore); + } }); })); @@ -580,6 +603,7 @@ private: bool _valid{false}; boost::optional<CancelToken> _cancelToken; + ValueHandle _cachedValue; Time _minTimeInStore; using TimeAndPromiseMap = std::map<Time, std::unique_ptr<SharedPromise<ValueHandle>>>; diff --git a/src/mongo/util/read_through_cache_test.cpp b/src/mongo/util/read_through_cache_test.cpp index b11f988ca94..b2b4148c744 100644 --- a/src/mongo/util/read_through_cache_test.cpp +++ b/src/mongo/util/read_through_cache_test.cpp @@ -60,9 +60,10 @@ public: service, threadPool, [this, lookupFn = std::move(lookupFn)](OperationContext* opCtx, - const std::string& key) { + const std::string& key, + const ValueHandle& cachedValue) { ++countLookups; - return lookupFn(opCtx, key); + return lookupFn(opCtx, key, cachedValue); }, size) {} @@ -82,9 +83,11 @@ public: service, threadPool, [this, lookupFn = std::move(lookupFn)](OperationContext* opCtx, - const std::string& key) { + const std::string& key, + const ValueHandle& cachedValue, + Timestamp timeInStore) { ++countLookups; - return lookupFn(opCtx, key); + return lookupFn(opCtx, key, cachedValue, timeInStore); }, size) {} @@ -149,7 +152,8 @@ TEST_F(ReadThroughCacheTest, FetchInvalidateAndRefetch) { fnTest(CacheWithThreadPool<Cache>( getServiceContext(), 1, - [&, nextValue = 0](OperationContext*, const std::string& key) mutable { + [&, nextValue = 0]( + OperationContext*, const std::string& key, const Cache::ValueHandle&) mutable { ASSERT_EQ("TestKey", key); return Cache::LookupResult(CachedValue(100 * ++nextValue)); })); @@ -157,7 +161,10 @@ TEST_F(ReadThroughCacheTest, FetchInvalidateAndRefetch) { fnTest(CacheWithThreadPool<CausallyConsistentCache>( getServiceContext(), 1, - [&, nextValue = 0](OperationContext*, const std::string& key) mutable { + [&, nextValue = 0](OperationContext*, + const std::string& key, + const CausallyConsistentCache::ValueHandle&, + const Timestamp& timeInStore) mutable { ASSERT_EQ("TestKey", key); ++nextValue; return CausallyConsistentCache::LookupResult(CachedValue(100 * nextValue), @@ -174,14 +181,16 @@ TEST_F(ReadThroughCacheTest, FailedLookup) { fnTest(CacheWithThreadPool<Cache>( getServiceContext(), 1, - [&](OperationContext*, const std::string& key) -> Cache::LookupResult { - uasserted(ErrorCodes::InternalError, "Test error"); - })); + [&](OperationContext*, const std::string& key, const Cache::ValueHandle&) + -> Cache::LookupResult { uasserted(ErrorCodes::InternalError, "Test error"); })); fnTest(CacheWithThreadPool<CausallyConsistentCache>( getServiceContext(), 1, - [&](OperationContext*, const std::string& key) -> CausallyConsistentCache::LookupResult { + [&](OperationContext*, + const std::string& key, + const CausallyConsistentCache::ValueHandle&, + const Timestamp& timeInStore) -> CausallyConsistentCache::LookupResult { uasserted(ErrorCodes::InternalError, "Test error"); })); } @@ -209,7 +218,8 @@ TEST_F(ReadThroughCacheTest, InvalidateCacheSizeZeroReissuesLookup) { fnTest(CacheWithThreadPool<Cache>( getServiceContext(), 0, - [&, nextValue = 0](OperationContext*, const std::string& key) mutable { + [&, nextValue = 0]( + OperationContext*, const std::string& key, const Cache::ValueHandle&) mutable { ASSERT_EQ("TestKey", key); return Cache::LookupResult(CachedValue(1000 * ++nextValue)); })); @@ -217,7 +227,10 @@ TEST_F(ReadThroughCacheTest, InvalidateCacheSizeZeroReissuesLookup) { fnTest(CacheWithThreadPool<CausallyConsistentCache>( getServiceContext(), 0, - [&, nextValue = 0](OperationContext*, const std::string& key) mutable { + [&, nextValue = 0](OperationContext*, + const std::string& key, + const CausallyConsistentCache::ValueHandle&, + const Timestamp& timeInStore) mutable { ASSERT_EQ("TestKey", key); ++nextValue; return CausallyConsistentCache::LookupResult(CachedValue(1000 * nextValue), @@ -229,13 +242,20 @@ TEST_F(ReadThroughCacheTest, KeyDoesNotExist) { auto fnTest = [&](auto cache) { ASSERT(!cache.acquire(_opCtx, "TestKey")); }; fnTest(CacheWithThreadPool<Cache>( - getServiceContext(), 1, [&](OperationContext*, const std::string& key) { + getServiceContext(), + 1, + [&](OperationContext*, const std::string& key, const Cache::ValueHandle&) { ASSERT_EQ("TestKey", key); return Cache::LookupResult(boost::none); })); fnTest(CacheWithThreadPool<CausallyConsistentCache>( - getServiceContext(), 1, [&](OperationContext*, const std::string& key) { + getServiceContext(), + 1, + [&](OperationContext*, + const std::string& key, + const CausallyConsistentCache::ValueHandle&, + const Timestamp& timeInStore) { ASSERT_EQ("TestKey", key); return CausallyConsistentCache::LookupResult(boost::none, Timestamp(10)); })); @@ -244,7 +264,12 @@ TEST_F(ReadThroughCacheTest, KeyDoesNotExist) { TEST_F(ReadThroughCacheTest, CausalConsistency) { boost::optional<CausallyConsistentCache::LookupResult> nextToReturn; CacheWithThreadPool<CausallyConsistentCache> cache( - getServiceContext(), 1, [&](OperationContext*, const std::string& key) { + getServiceContext(), + 1, + [&](OperationContext*, + const std::string& key, + const CausallyConsistentCache::ValueHandle&, + const Timestamp& timeInStore) { ASSERT_EQ("TestKey", key); return CausallyConsistentCache::LookupResult(std::move(*nextToReturn)); }); @@ -273,9 +298,12 @@ TEST_F(ReadThroughCacheAsyncTest, SuccessfulInProgressLookupForNotCausallyConsis ThreadPool threadPool{ThreadPool::Options()}; threadPool.startup(); - Cache cache(getServiceContext(), threadPool, 1, [&](OperationContext*, const std::string& key) { - return Cache::LookupResult(CachedValue(500)); - }); + Cache cache(getServiceContext(), + threadPool, + 1, + [&](OperationContext*, const std::string& key, const Cache::ValueHandle&) { + return Cache::LookupResult(CachedValue(500)); + }); // Join threads before destroying cache. This ensure the internal asynchronous processing tasks // are completed before the cache resources are released. @@ -284,7 +312,8 @@ TEST_F(ReadThroughCacheAsyncTest, SuccessfulInProgressLookupForNotCausallyConsis threadPool.join(); }); - Cache::InProgressLookup inProgress(cache, "TestKey", CacheNotCausallyConsistent()); + Cache::InProgressLookup inProgress( + cache, "TestKey", Cache::ValueHandle(), CacheNotCausallyConsistent()); auto future = inProgress.addWaiter(WithLock::withoutLock()); ASSERT(!future.isReady()); @@ -308,9 +337,8 @@ TEST_F(ReadThroughCacheAsyncTest, FailedInProgressLookupForNotCausallyConsistent Cache cache(getServiceContext(), threadPool, 1, - [&](OperationContext*, const std::string& key) -> Cache::LookupResult { - uasserted(ErrorCodes::InternalError, "Test error"); - }); + [&](OperationContext*, const std::string& key, const Cache::ValueHandle&) + -> Cache::LookupResult { uasserted(ErrorCodes::InternalError, "Test error"); }); // Join threads before destroying cache. This ensure the internal asynchronous processing tasks // are completed before the cache resources are released. @@ -319,7 +347,8 @@ TEST_F(ReadThroughCacheAsyncTest, FailedInProgressLookupForNotCausallyConsistent threadPool.join(); }); - Cache::InProgressLookup inProgress(cache, "TestKey", CacheNotCausallyConsistent()); + Cache::InProgressLookup inProgress( + cache, "TestKey", Cache::ValueHandle(), CacheNotCausallyConsistent()); auto future = inProgress.addWaiter(WithLock::withoutLock()); ASSERT(!future.isReady()); @@ -340,11 +369,14 @@ TEST_F(ReadThroughCacheAsyncTest, AcquireObservesOperationContextDeadline) { Barrier lookupStartedBarrier(2); Barrier completeLookupBarrier(2); - Cache cache(getServiceContext(), threadPool, 1, [&](OperationContext*, const std::string& key) { - lookupStartedBarrier.countDownAndWait(); - completeLookupBarrier.countDownAndWait(); - return Cache::LookupResult(CachedValue(5)); - }); + Cache cache(getServiceContext(), + threadPool, + 1, + [&](OperationContext*, const std::string& key, const Cache::ValueHandle&) { + lookupStartedBarrier.countDownAndWait(); + completeLookupBarrier.countDownAndWait(); + return Cache::LookupResult(CachedValue(5)); + }); // Join threads before destroying cache. This ensure the internal asynchronous processing tasks // are completed before the cache resources are released. @@ -397,12 +429,15 @@ TEST_F(ReadThroughCacheAsyncTest, InvalidateReissuesLookup) { Barrier lookupStartedBarriers[] = {Barrier{2}, Barrier{2}, Barrier{2}}; Barrier completeLookupBarriers[] = {Barrier{2}, Barrier{2}, Barrier{2}}; - Cache cache(getServiceContext(), threadPool, 1, [&](OperationContext*, const std::string& key) { - int idx = countLookups.fetchAndAdd(1); - lookupStartedBarriers[idx].countDownAndWait(); - completeLookupBarriers[idx].countDownAndWait(); - return Cache::LookupResult(CachedValue(idx)); - }); + Cache cache(getServiceContext(), + threadPool, + 1, + [&](OperationContext*, const std::string& key, const Cache::ValueHandle&) { + int idx = countLookups.fetchAndAdd(1); + lookupStartedBarriers[idx].countDownAndWait(); + completeLookupBarriers[idx].countDownAndWait(); + return Cache::LookupResult(CachedValue(idx)); + }); // Join threads before destroying cache. This ensure the internal asynchronous processing tasks // are completed before the cache resources are released. @@ -447,10 +482,13 @@ TEST_F(ReadThroughCacheAsyncTest, AcquireWithAShutdownThreadPool) { threadPool.shutdown(); threadPool.join(); - Cache cache(getServiceContext(), threadPool, 1, [&](OperationContext*, const std::string&) { - FAIL("Should not be called"); - return Cache::LookupResult(boost::none); // Will never be reached - }); + Cache cache(getServiceContext(), + threadPool, + 1, + [&](OperationContext*, const std::string&, const Cache::ValueHandle&) { + FAIL("Should not be called"); + return Cache::LookupResult(boost::none); // Will never be reached + }); auto future = cache.acquireAsync("TestKey"); ASSERT_THROWS_CODE(future.get(), DBException, ErrorCodes::ShutdownInProgress); @@ -481,10 +519,13 @@ private: TEST_F(ReadThroughCacheAsyncTest, AdvanceTimeDuringLookupOfUnCachedKey) { MockThreadPool threadPool; boost::optional<CausallyConsistentCache::LookupResult> nextToReturn; - CausallyConsistentCache cache( - getServiceContext(), threadPool, 1, [&](OperationContext*, const std::string&) { - return std::move(*nextToReturn); - }); + CausallyConsistentCache cache(getServiceContext(), + threadPool, + 1, + [&](OperationContext*, + const std::string&, + const CausallyConsistentCache::ValueHandle&, + const Timestamp&) { return std::move(*nextToReturn); }); auto futureAtTS100 = cache.acquireAsync("TestKey", CacheCausalConsistency::kLatestKnown); ASSERT(!futureAtTS100.isReady()); @@ -508,10 +549,13 @@ TEST_F(ReadThroughCacheAsyncTest, AdvanceTimeDuringLookupOfUnCachedKey) { TEST_F(ReadThroughCacheAsyncTest, KeyDeletedAfterAdvanceTimeInStore) { MockThreadPool threadPool; boost::optional<CausallyConsistentCache::LookupResult> nextToReturn; - CausallyConsistentCache cache( - getServiceContext(), threadPool, 1, [&](OperationContext*, const std::string&) { - return std::move(*nextToReturn); - }); + CausallyConsistentCache cache(getServiceContext(), + threadPool, + 1, + [&](OperationContext*, + const std::string&, + const CausallyConsistentCache::ValueHandle&, + const Timestamp&) { return std::move(*nextToReturn); }); auto futureAtTS100 = cache.acquireAsync("TestKey", CacheCausalConsistency::kLatestKnown); nextToReturn.emplace(CachedValue(100), Timestamp(100)); @@ -537,10 +581,13 @@ TEST_F(ReadThroughCacheAsyncTest, KeyDeletedAfterAdvanceTimeInStore) { TEST_F(ReadThroughCacheAsyncTest, AcquireAsyncAndAdvanceTimeInterleave) { MockThreadPool threadPool; boost::optional<CausallyConsistentCache::LookupResult> nextToReturn; - CausallyConsistentCache cache( - getServiceContext(), threadPool, 1, [&](OperationContext*, const std::string&) { - return std::move(*nextToReturn); - }); + CausallyConsistentCache cache(getServiceContext(), + threadPool, + 1, + [&](OperationContext*, + const std::string&, + const CausallyConsistentCache::ValueHandle&, + const Timestamp&) { return std::move(*nextToReturn); }); auto futureAtTS100 = cache.acquireAsync("TestKey"); nextToReturn.emplace(CachedValue(100), Timestamp(100)); @@ -573,9 +620,12 @@ TEST_F(ReadThroughCacheAsyncTest, AcquireAsyncAndAdvanceTimeInterleave) { TEST_F(ReadThroughCacheAsyncTest, InvalidateCalledBeforeLookupTaskExecutes) { MockThreadPool threadPool; - Cache cache(getServiceContext(), threadPool, 1, [&](OperationContext*, const std::string&) { - return Cache::LookupResult(CachedValue(123)); - }); + Cache cache(getServiceContext(), + threadPool, + 1, + [&](OperationContext*, const std::string&, const Cache::ValueHandle&) { + return Cache::LookupResult(CachedValue(123)); + }); auto future = cache.acquireAsync("TestKey"); cache.invalidateAll(); @@ -605,21 +655,24 @@ TEST_F(ReadThroughCacheAsyncTest, CacheSizeZero) { fnTest(Cache(getServiceContext(), threadPool, 0, - [&, nextValue = 0](OperationContext*, const std::string& key) mutable { + [&, nextValue = 0]( + OperationContext*, const std::string& key, const Cache::ValueHandle&) mutable { ASSERT_EQ("TestKey", key); return Cache::LookupResult(CachedValue(100 * ++nextValue)); })); - fnTest(CausallyConsistentCache( - getServiceContext(), - threadPool, - 0, - [&, nextValue = 0](OperationContext*, const std::string& key) mutable { - ASSERT_EQ("TestKey", key); - ++nextValue; - return CausallyConsistentCache::LookupResult(CachedValue(100 * nextValue), - Timestamp(nextValue)); - })); + fnTest(CausallyConsistentCache(getServiceContext(), + threadPool, + 0, + [&, nextValue = 0](OperationContext*, + const std::string& key, + const CausallyConsistentCache::ValueHandle&, + const Timestamp&) mutable { + ASSERT_EQ("TestKey", key); + ++nextValue; + return CausallyConsistentCache::LookupResult( + CachedValue(100 * nextValue), Timestamp(nextValue)); + })); } } // namespace |