mirror of
https://github.com/NixOS/nix.git
synced 2025-11-14 14:32:42 +01:00
Merge pull request #93 from DeterminateSystems/fix-fetcher-cache
Fix fetchToStore() caching
This commit is contained in:
commit
550c894712
8 changed files with 73 additions and 10 deletions
|
|
@ -80,6 +80,7 @@ StorePath EvalState::mountInput(
|
||||||
storeFS->mount(CanonPath(store->printStorePath(storePath)), accessor);
|
storeFS->mount(CanonPath(store->printStorePath(storePath)), accessor);
|
||||||
|
|
||||||
if (requireLockable && (!settings.lazyTrees || !input.isLocked()) && !input.getNarHash()) {
|
if (requireLockable && (!settings.lazyTrees || !input.isLocked()) && !input.getNarHash()) {
|
||||||
|
// FIXME: use fetchToStore to make it cache this
|
||||||
auto narHash = accessor->hashPath(CanonPath::root);
|
auto narHash = accessor->hashPath(CanonPath::root);
|
||||||
input.attrs.insert_or_assign("narHash", narHash.to_string(HashFormat::SRI, true));
|
input.attrs.insert_or_assign("narHash", narHash.to_string(HashFormat::SRI, true));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,15 +31,16 @@ StorePath fetchToStore(
|
||||||
// a `PosixSourceAccessor` pointing to a store path.
|
// a `PosixSourceAccessor` pointing to a store path.
|
||||||
|
|
||||||
std::optional<fetchers::Cache::Key> cacheKey;
|
std::optional<fetchers::Cache::Key> cacheKey;
|
||||||
|
std::optional<std::string> fingerprint;
|
||||||
|
|
||||||
if (!filter && path.accessor->fingerprint) {
|
if (!filter && (fingerprint = path.accessor->getFingerprint(path.path))) {
|
||||||
cacheKey = makeFetchToStoreCacheKey(std::string{name}, *path.accessor->fingerprint, method, path.path.abs());
|
cacheKey = makeFetchToStoreCacheKey(std::string{name}, *fingerprint, method, path.path.abs());
|
||||||
if (auto res = fetchers::getCache()->lookupStorePath(*cacheKey, store)) {
|
if (auto res = fetchers::getCache()->lookupStorePath(*cacheKey, store)) {
|
||||||
debug("store path cache hit for '%s'", path);
|
debug("store path cache hit for '%s'", path);
|
||||||
return res->storePath;
|
return res->storePath;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
debug("source path '%s' is uncacheable", path);
|
debug("source path '%s' is uncacheable (%d, %d)", path, filter, (bool) fingerprint);
|
||||||
|
|
||||||
Activity act(*logger, lvlChatty, actUnknown,
|
Activity act(*logger, lvlChatty, actUnknown,
|
||||||
fmt(mode == FetchMode::DryRun ? "hashing '%s'" : "copying '%s' to the store", path));
|
fmt(mode == FetchMode::DryRun ? "hashing '%s'" : "copying '%s' to the store", path));
|
||||||
|
|
@ -55,7 +56,7 @@ StorePath fetchToStore(
|
||||||
|
|
||||||
debug(mode == FetchMode::DryRun ? "hashed '%s'" : "copied '%s' to '%s'", path, store.printStorePath(storePath));
|
debug(mode == FetchMode::DryRun ? "hashed '%s'" : "copied '%s' to '%s'", path, store.printStorePath(storePath));
|
||||||
|
|
||||||
if (cacheKey && mode == FetchMode::Copy)
|
if (cacheKey)
|
||||||
fetchers::getCache()->upsert(*cacheKey, store, {}, storePath);
|
fetchers::getCache()->upsert(*cacheKey, store, {}, storePath);
|
||||||
|
|
||||||
return storePath;
|
return storePath;
|
||||||
|
|
|
||||||
|
|
@ -338,7 +338,8 @@ std::pair<ref<SourceAccessor>, Input> Input::getAccessorUnchecked(ref<Store> sto
|
||||||
|
|
||||||
auto accessor = make_ref<SubstitutedSourceAccessor>(makeStorePathAccessor(store, storePath));
|
auto accessor = make_ref<SubstitutedSourceAccessor>(makeStorePathAccessor(store, storePath));
|
||||||
|
|
||||||
accessor->fingerprint = getFingerprint(store);
|
if (auto fingerprint = getFingerprint(store))
|
||||||
|
accessor->setFingerprint(*fingerprint);
|
||||||
|
|
||||||
// FIXME: ideally we would use the `showPath()` of the
|
// FIXME: ideally we would use the `showPath()` of the
|
||||||
// "real" accessor for this fetcher type.
|
// "real" accessor for this fetcher type.
|
||||||
|
|
@ -352,8 +353,10 @@ std::pair<ref<SourceAccessor>, Input> Input::getAccessorUnchecked(ref<Store> sto
|
||||||
|
|
||||||
auto [accessor, result] = scheme->getAccessor(store, *this);
|
auto [accessor, result] = scheme->getAccessor(store, *this);
|
||||||
|
|
||||||
assert(!accessor->fingerprint);
|
assert(!accessor->getFingerprint(CanonPath::root));
|
||||||
accessor->fingerprint = result.getFingerprint(store);
|
|
||||||
|
if (auto fingerprint = getFingerprint(store))
|
||||||
|
accessor->setFingerprint(*fingerprint);
|
||||||
|
|
||||||
return {accessor, std::move(result)};
|
return {accessor, std::move(result)};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,12 @@ std::string FilteringSourceAccessor::readFile(const CanonPath & path)
|
||||||
return next->readFile(prefix / path);
|
return next->readFile(prefix / path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FilteringSourceAccessor::readFile(const CanonPath & path, Sink & sink, std::function<void(uint64_t)> sizeCallback)
|
||||||
|
{
|
||||||
|
checkAccess(path);
|
||||||
|
return next->readFile(prefix / path, sink, sizeCallback);
|
||||||
|
}
|
||||||
|
|
||||||
bool FilteringSourceAccessor::pathExists(const CanonPath & path)
|
bool FilteringSourceAccessor::pathExists(const CanonPath & path)
|
||||||
{
|
{
|
||||||
return isAllowed(path) && next->pathExists(prefix / path);
|
return isAllowed(path) && next->pathExists(prefix / path);
|
||||||
|
|
@ -52,6 +58,16 @@ std::string FilteringSourceAccessor::showPath(const CanonPath & path)
|
||||||
return displayPrefix + next->showPath(prefix / path) + displaySuffix;
|
return displayPrefix + next->showPath(prefix / path) + displaySuffix;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<std::string> FilteringSourceAccessor::getFingerprint(const CanonPath & path)
|
||||||
|
{
|
||||||
|
return next->getFingerprint(prefix / path);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FilteringSourceAccessor::setFingerprint(std::string fingerprint)
|
||||||
|
{
|
||||||
|
next->setFingerprint(std::move(fingerprint));
|
||||||
|
}
|
||||||
|
|
||||||
void FilteringSourceAccessor::checkAccess(const CanonPath & path)
|
void FilteringSourceAccessor::checkAccess(const CanonPath & path)
|
||||||
{
|
{
|
||||||
if (!isAllowed(path))
|
if (!isAllowed(path))
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,8 @@ struct FilteringSourceAccessor : SourceAccessor
|
||||||
|
|
||||||
std::string readFile(const CanonPath & path) override;
|
std::string readFile(const CanonPath & path) override;
|
||||||
|
|
||||||
|
void readFile(const CanonPath & path, Sink & sink, std::function<void(uint64_t)> sizeCallback) override;
|
||||||
|
|
||||||
bool pathExists(const CanonPath & path) override;
|
bool pathExists(const CanonPath & path) override;
|
||||||
|
|
||||||
Stat lstat(const CanonPath & path) override;
|
Stat lstat(const CanonPath & path) override;
|
||||||
|
|
@ -48,6 +50,10 @@ struct FilteringSourceAccessor : SourceAccessor
|
||||||
|
|
||||||
std::string showPath(const CanonPath & path) override;
|
std::string showPath(const CanonPath & path) override;
|
||||||
|
|
||||||
|
std::optional<std::string> getFingerprint(const CanonPath & path) override;
|
||||||
|
|
||||||
|
void setFingerprint(std::string fingerprint) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call `makeNotAllowedError` to throw a `RestrictedPathError`
|
* Call `makeNotAllowedError` to throw a `RestrictedPathError`
|
||||||
* exception if `isAllowed()` returns `false` for `path`.
|
* exception if `isAllowed()` returns `false` for `path`.
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,16 @@ struct ForwardingSourceAccessor : SourceAccessor
|
||||||
{
|
{
|
||||||
return next->getPhysicalPath(path);
|
return next->getPhysicalPath(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<std::string> getFingerprint(const CanonPath & path) override
|
||||||
|
{
|
||||||
|
return next->getFingerprint(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setFingerprint(std::string fingerprint) override
|
||||||
|
{
|
||||||
|
next->setFingerprint(std::move(fingerprint));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -177,10 +177,27 @@ struct SourceAccessor : std::enable_shared_from_this<SourceAccessor>
|
||||||
SymlinkResolution mode = SymlinkResolution::Full);
|
SymlinkResolution mode = SymlinkResolution::Full);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A string that uniquely represents the contents of this
|
* Return a string that uniquely represents the contents of this
|
||||||
* accessor. This is used for caching lookups (see `fetchToStore()`).
|
* accessor. This is used for caching lookups (see
|
||||||
|
* `fetchToStore()`).
|
||||||
|
*
|
||||||
|
* Fingerprints are generally for the entire accessor, but this
|
||||||
|
* method takes a `path` argument to support accessors like
|
||||||
|
* `MountedSourceAccessor` that combine multiple underlying
|
||||||
|
* accessors. A fingerprint should only be returned if it uniquely
|
||||||
|
* represents everything under `path`.
|
||||||
*/
|
*/
|
||||||
std::optional<std::string> fingerprint;
|
virtual std::optional<std::string> getFingerprint(const CanonPath & path)
|
||||||
|
{
|
||||||
|
return _fingerprint;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void setFingerprint(std::string fingerprint)
|
||||||
|
{
|
||||||
|
_fingerprint = std::move(fingerprint);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<std::string> _fingerprint;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the maximum last-modified time of the files in this
|
* Return the maximum last-modified time of the files in this
|
||||||
|
|
|
||||||
|
|
@ -90,6 +90,15 @@ struct MountedSourceAccessorImpl : MountedSourceAccessor
|
||||||
else
|
else
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<std::string> getFingerprint(const CanonPath & path) override
|
||||||
|
{
|
||||||
|
auto [accessor, subpath] = resolve(path);
|
||||||
|
// FIXME: check that there are no mounts underneath the mount
|
||||||
|
// point of `accessor`, since that would invalidate the
|
||||||
|
// fingerprint. (However we don't have such at the moment.)
|
||||||
|
return accessor->getFingerprint(subpath);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ref<MountedSourceAccessor> makeMountedSourceAccessor(std::map<CanonPath, ref<SourceAccessor>> mounts)
|
ref<MountedSourceAccessor> makeMountedSourceAccessor(std::map<CanonPath, ref<SourceAccessor>> mounts)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue