Merge pull request #3403 from hercules-ci/issue-3398-path-info-cache-ttls

pathInfoCache: Respect disk cache TTLs #3398
This commit is contained in:
Eelco Dolstra 2020-03-12 11:43:31 +01:00 committed by GitHub
commit d048577909
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 43 additions and 15 deletions

View file

@ -9,11 +9,11 @@ appear with Nix.
To find out more about the tool, usage and installation instructions, please To find out more about the tool, usage and installation instructions, please
read the manual, which is available on the Nix website at read the manual, which is available on the Nix website at
<http://nixos.org/nix/manual>. <https://nixos.org/nix/manual>.
## Contributing ## Contributing
Take a look at the [Hacking Section](http://nixos.org/nix/manual/#chap-hacking) Take a look at the [Hacking Section](https://nixos.org/nix/manual/#chap-hacking)
of the manual. It helps you to get started with building Nix from source. of the manual. It helps you to get started with building Nix from source.
## License ## License
@ -21,4 +21,4 @@ of the manual. It helps you to get started with building Nix from source.
Nix is released under the LGPL v2.1 Nix is released under the LGPL v2.1
This product includes software developed by the OpenSSL Project for This product includes software developed by the OpenSSL Project for
use in the [OpenSSL Toolkit](http://www.OpenSSL.org/). use in the [OpenSSL Toolkit](https://www.OpenSSL.org/).

View file

@ -87,7 +87,7 @@ if ! [ -e $dest ]; then
fi fi
if ! [ -w $dest ]; then if ! [ -w $dest ]; then
echo "$0: directory $dest exists, but is not writable by you. This could indicate that another user has already performed a single-user installation of Nix on this system. If you wish to enable multi-user support see http://nixos.org/nix/manual/#ssec-multi-user. If you wish to continue with a single-user install for $USER please run 'chown -R $USER $dest' as root." >&2 echo "$0: directory $dest exists, but is not writable by you. This could indicate that another user has already performed a single-user installation of Nix on this system. If you wish to enable multi-user support see https://nixos.org/nix/manual/#ssec-multi-user. If you wish to continue with a single-user install for $USER please run 'chown -R $USER $dest' as root." >&2
exit 1 exit 1
fi fi

View file

@ -106,7 +106,7 @@ void BinaryCacheStore::writeNarInfo(ref<NarInfo> narInfo)
{ {
auto state_(state.lock()); auto state_(state.lock());
state_->pathInfoCache.upsert(hashPart, std::shared_ptr<NarInfo>(narInfo)); state_->pathInfoCache.upsert(hashPart, PathInfoCacheValue { .value = std::shared_ptr<NarInfo>(narInfo) });
} }
if (diskCache) if (diskCache)

View file

@ -622,7 +622,8 @@ uint64_t LocalStore::addValidPath(State & state,
{ {
auto state_(Store::state.lock()); auto state_(Store::state.lock());
state_->pathInfoCache.upsert(storePathToHash(printStorePath(info.path)), std::make_shared<ValidPathInfo>(info)); state_->pathInfoCache.upsert(storePathToHash(printStorePath(info.path)),
PathInfoCacheValue{ .value = std::make_shared<const ValidPathInfo>(info) });
} }
return id; return id;

View file

@ -226,6 +226,14 @@ std::string Store::getUri()
return ""; return "";
} }
bool Store::PathInfoCacheValue::isKnownNow()
{
std::chrono::duration ttl = didExist()
? std::chrono::seconds(settings.ttlPositiveNarInfoCache)
: std::chrono::seconds(settings.ttlNegativeNarInfoCache);
return std::chrono::steady_clock::now() < time_point + ttl;
}
bool Store::isValidPath(const StorePath & storePath) bool Store::isValidPath(const StorePath & storePath)
{ {
@ -234,9 +242,9 @@ bool Store::isValidPath(const StorePath & storePath)
{ {
auto state_(state.lock()); auto state_(state.lock());
auto res = state_->pathInfoCache.get(hashPart); auto res = state_->pathInfoCache.get(hashPart);
if (res) { if (res && res->isKnownNow()) {
stats.narInfoReadAverted++; stats.narInfoReadAverted++;
return *res != 0; return res->didExist();
} }
} }
@ -246,7 +254,7 @@ bool Store::isValidPath(const StorePath & storePath)
stats.narInfoReadAverted++; stats.narInfoReadAverted++;
auto state_(state.lock()); auto state_(state.lock());
state_->pathInfoCache.upsert(hashPart, state_->pathInfoCache.upsert(hashPart,
res.first == NarInfoDiskCache::oInvalid ? 0 : res.second); res.first == NarInfoDiskCache::oInvalid ? PathInfoCacheValue{} : PathInfoCacheValue { .value = res.second });
return res.first == NarInfoDiskCache::oValid; return res.first == NarInfoDiskCache::oValid;
} }
} }
@ -301,11 +309,11 @@ void Store::queryPathInfo(const StorePath & storePath,
{ {
auto res = state.lock()->pathInfoCache.get(hashPart); auto res = state.lock()->pathInfoCache.get(hashPart);
if (res) { if (res && res->isKnownNow()) {
stats.narInfoReadAverted++; stats.narInfoReadAverted++;
if (!*res) if (!res->didExist())
throw InvalidPath("path '%s' is not valid", printStorePath(storePath)); throw InvalidPath("path '%s' is not valid", printStorePath(storePath));
return callback(ref<const ValidPathInfo>(*res)); return callback(ref<const ValidPathInfo>(res->value));
} }
} }
@ -316,7 +324,7 @@ void Store::queryPathInfo(const StorePath & storePath,
{ {
auto state_(state.lock()); auto state_(state.lock());
state_->pathInfoCache.upsert(hashPart, state_->pathInfoCache.upsert(hashPart,
res.first == NarInfoDiskCache::oInvalid ? 0 : res.second); res.first == NarInfoDiskCache::oInvalid ? PathInfoCacheValue{} : PathInfoCacheValue{ .value = res.second });
if (res.first == NarInfoDiskCache::oInvalid || if (res.first == NarInfoDiskCache::oInvalid ||
res.second->path != storePath) res.second->path != storePath)
throw InvalidPath("path '%s' is not valid", printStorePath(storePath)); throw InvalidPath("path '%s' is not valid", printStorePath(storePath));
@ -340,7 +348,7 @@ void Store::queryPathInfo(const StorePath & storePath,
{ {
auto state_(state.lock()); auto state_(state.lock());
state_->pathInfoCache.upsert(hashPart, info); state_->pathInfoCache.upsert(hashPart, PathInfoCacheValue { .value = info });
} }
if (!info || info->path != parseStorePath(storePath)) { if (!info || info->path != parseStorePath(storePath)) {

View file

@ -16,6 +16,7 @@
#include <unordered_set> #include <unordered_set>
#include <memory> #include <memory>
#include <string> #include <string>
#include <chrono>
namespace nix { namespace nix {
@ -261,10 +262,28 @@ public:
protected: protected:
struct PathInfoCacheValue {
// Time of cache entry creation or update
std::chrono::time_point<std::chrono::steady_clock> time_point = std::chrono::steady_clock::now();
// Null if missing
std::shared_ptr<const ValidPathInfo> value;
// Whether the value is valid as a cache entry. The path may not exist.
bool isKnownNow();
// Past tense, because a path can only be assumed to exists when
// isKnownNow() && didExist()
inline bool didExist() {
return value != nullptr;
}
};
struct State struct State
{ {
// FIXME: fix key // FIXME: fix key
LRUCache<std::string, std::shared_ptr<const ValidPathInfo>> pathInfoCache; LRUCache<std::string, PathInfoCacheValue> pathInfoCache;
}; };
Sync<State> state; Sync<State> state;