refactor: Extract simply, awkwardly Store::queryPathInfoFromClientCache

This is useful for determining quickly which substituters to query.

An alternative would be for users to invoke the narinfo cache db directly,
so why do we need this change?

 - It is easier to use. I believe Nix itself should also use it.

 - This way, the narinfo cache db remains an implementation detail.

 - Callers get to use the in-memory cache as well.
This commit is contained in:
Robert Hensing 2024-01-17 16:54:45 +01:00
parent 01271f2996
commit d0a284284b
2 changed files with 50 additions and 26 deletions

View File

@ -685,6 +685,42 @@ static bool goodStorePath(const StorePath & expected, const StorePath & actual)
&& (expected.name() == Store::MissingName || expected.name() == actual.name());
}
bool Store::queryPathInfoFromClientCache(const StorePath & storePath,
Callback<ref<const ValidPathInfo>> & callback)
{
auto hashPart = std::string(storePath.hashPart());
{
auto res = state.lock()->pathInfoCache.get(std::string(storePath.to_string()));
if (res && res->isKnownNow()) {
stats.narInfoReadAverted++;
if (!res->didExist())
throw InvalidPath("path '%s' is not valid", printStorePath(storePath));
callback(ref<const ValidPathInfo>(res->value));
return true;
}
}
if (diskCache) {
auto res = diskCache->lookupNarInfo(getUri(), hashPart);
if (res.first != NarInfoDiskCache::oUnknown) {
stats.narInfoReadAverted++;
{
auto state_(state.lock());
state_->pathInfoCache.upsert(std::string(storePath.to_string()),
res.first == NarInfoDiskCache::oInvalid ? PathInfoCacheValue{} : PathInfoCacheValue{ .value = res.second });
if (res.first == NarInfoDiskCache::oInvalid ||
!goodStorePath(storePath, res.second->path))
throw InvalidPath("path '%s' is not valid", printStorePath(storePath));
}
callback(ref<const ValidPathInfo>(res.second));
return true;
}
}
return false;
}
void Store::queryPathInfo(const StorePath & storePath,
Callback<ref<const ValidPathInfo>> callback) noexcept
@ -692,32 +728,8 @@ void Store::queryPathInfo(const StorePath & storePath,
auto hashPart = std::string(storePath.hashPart());
try {
{
auto res = state.lock()->pathInfoCache.get(std::string(storePath.to_string()));
if (res && res->isKnownNow()) {
stats.narInfoReadAverted++;
if (!res->didExist())
throw InvalidPath("path '%s' is not valid", printStorePath(storePath));
return callback(ref<const ValidPathInfo>(res->value));
}
}
if (diskCache) {
auto res = diskCache->lookupNarInfo(getUri(), hashPart);
if (res.first != NarInfoDiskCache::oUnknown) {
stats.narInfoReadAverted++;
{
auto state_(state.lock());
state_->pathInfoCache.upsert(std::string(storePath.to_string()),
res.first == NarInfoDiskCache::oInvalid ? PathInfoCacheValue{} : PathInfoCacheValue{ .value = res.second });
if (res.first == NarInfoDiskCache::oInvalid ||
!goodStorePath(storePath, res.second->path))
throw InvalidPath("path '%s' is not valid", printStorePath(storePath));
}
return callback(ref<const ValidPathInfo>(res.second));
}
}
if (queryPathInfoFromClientCache(storePath, callback))
return;
} catch (...) { return callback.rethrow(); }
auto callbackPtr = std::make_shared<decltype(callback)>(std::move(callback));

View File

@ -282,6 +282,18 @@ public:
void queryPathInfo(const StorePath & path,
Callback<ref<const ValidPathInfo>> callback) noexcept;
/**
* NOTE: this is not the final interface - to be modified in next commit.
*
* Asynchronous version that only queries the local narinfo cache and not
* the actual store.
*
* @return true if the path was known and the callback invoked
* @return false if the path was not known and the callback not invoked
* @throw InvalidPathError if the path is known to be invalid
*/
bool queryPathInfoFromClientCache(const StorePath & path, Callback<ref<const ValidPathInfo>> & callback);
/**
* Query the information about a realisation.
*/