diff --git a/src/libstore/local-overlay-store.cc b/src/libstore/local-overlay-store.cc index bd48c12e4..a98d2e8fd 100644 --- a/src/libstore/local-overlay-store.cc +++ b/src/libstore/local-overlay-store.cc @@ -3,6 +3,12 @@ namespace nix { +Path LocalOverlayStoreConfig::toUpperPath(const StorePath & path) { + auto res = upperLayer + "/" + path.to_string(); + warn("upper path: %s", res); + return res; +} + LocalOverlayStore::LocalOverlayStore(const Params & params) : StoreConfig(params) , LocalFSStoreConfig(params) @@ -30,7 +36,6 @@ void LocalOverlayStore::registerDrvOutput(const Realisation & info) void LocalOverlayStore::queryPathInfoUncached(const StorePath & path, Callback> callback) noexcept { - auto callbackPtr = std::make_shared(std::move(callback)); LocalStore::queryPathInfoUncached(path, @@ -55,6 +60,79 @@ void LocalOverlayStore::queryPathInfoUncached(const StorePath & path, } +void LocalOverlayStore::queryRealisationUncached(const DrvOutput & drvOutput, + Callback> callback) noexcept +{ + auto callbackPtr = std::make_shared(std::move(callback)); + + LocalStore::queryRealisationUncached(drvOutput, + {[this, drvOutput, callbackPtr](std::future> fut) { + try { + auto info = fut.get(); + if (info) + return (*callbackPtr)(std::move(info)); + } catch (...) { + return callbackPtr->rethrow(); + } + // If we don't have it, check lower store + lowerStore->queryRealisation(drvOutput, + {[callbackPtr](std::future> fut) { + try { + (*callbackPtr)(fut.get()); + } catch (...) { + return callbackPtr->rethrow(); + } + }}); + }}); +} + + +bool LocalOverlayStore::isValidPathUncached(const StorePath & path) +{ + auto res = LocalStore::isValidPathUncached(path); + if (res) return res; + return lowerStore->isValidPath(path); +} + + +void LocalOverlayStore::addToStore(const ValidPathInfo & info, Source & source, + RepairFlag repair, CheckSigsFlag checkSigs) +{ + LocalStore::addToStore(info, source, repair, checkSigs); + if (lowerStore->isValidPath(info.path)) { + // dedup stores + deletePath(toUpperPath(info.path)); + } +} + + +StorePath LocalOverlayStore::addToStoreFromDump(Source & dump, std::string_view name, + FileIngestionMethod method, HashType hashAlgo, RepairFlag repair, const StorePathSet & references) +{ + auto path = LocalStore::addToStoreFromDump(dump, name, method, hashAlgo, repair, references); + if (lowerStore->isValidPath(path)) { + // dedup stores + deletePath(toUpperPath(path)); + } + return path; +} + + +StorePath LocalOverlayStore::addTextToStore( + std::string_view name, + std::string_view s, + const StorePathSet & references, + RepairFlag repair) +{ + auto path = LocalStore::addTextToStore(name, s, references, repair); + if (lowerStore->isValidPath(path)) { + // dedup stores + deletePath(toUpperPath(path)); + } + return path; +} + + static RegisterStoreImplementation regLocalOverlayStore; } diff --git a/src/libstore/local-overlay-store.hh b/src/libstore/local-overlay-store.hh index 12b705efb..c087b3893 100644 --- a/src/libstore/local-overlay-store.hh +++ b/src/libstore/local-overlay-store.hh @@ -22,6 +22,12 @@ struct LocalOverlayStoreConfig : virtual LocalStoreConfig for the lower store. The default is `auto` (i.e. use the Nix daemon or `/nix/store` directly). Must be a store with a store dir on the file system. + Must be used as OverlayFS lower layer for this store's store dir. + )"}; + + const Setting upperLayer{(StoreConfig*) this, "", "upper-layer", + R"( + Must be used as OverlayFS upper layer for this store's store dir. )"}; const std::string name() override { return "Experimental Local Overlay Store"; } @@ -34,6 +40,12 @@ struct LocalOverlayStoreConfig : virtual LocalStoreConfig //#include "local-overlay-store.md" ; } + + /** + * Given a store path, get its location (if it is exists) in the + * upper layer of the overlayfs. + */ + Path toUpperPath(const StorePath & path); }; /** @@ -74,6 +86,23 @@ private: void queryPathInfoUncached(const StorePath & path, Callback> callback) noexcept override; + + bool isValidPathUncached(const StorePath & path) override; + + void addToStore(const ValidPathInfo & info, Source & source, + RepairFlag repair, CheckSigsFlag checkSigs) override; + + StorePath addToStoreFromDump(Source & dump, std::string_view name, + FileIngestionMethod method, HashType hashAlgo, RepairFlag repair, const StorePathSet & references) override; + + StorePath addTextToStore( + std::string_view name, + std::string_view s, + const StorePathSet & references, + RepairFlag repair) override; + + void queryRealisationUncached(const DrvOutput&, + Callback> callback) noexcept override; }; } diff --git a/tests/overlay-local-store/inner.sh b/tests/overlay-local-store/inner.sh index 69c6f6d0c..d9d3b76cf 100755 --- a/tests/overlay-local-store/inner.sh +++ b/tests/overlay-local-store/inner.sh @@ -12,7 +12,7 @@ export NIX_CONFIG='build-users-group = ' storeA="$TEST_ROOT/store-a" storeBTop="$TEST_ROOT/store-b" -storeB="local-overlay?root=$TEST_ROOT/merged-store&lower-store=$TEST_ROOT/store-a" +storeB="local-overlay?root=$TEST_ROOT/merged-store&lower-store=$storeA&upper-layer=$storeBTop" mkdir -p "$TEST_ROOT"/{store-a,store-b,merged-store/nix/store,workdir} @@ -71,18 +71,19 @@ path=$(nix-store --store "$storeB" --add dummy) stat $(toRealPath "$storeA/nix/store" "$path") # upper layer should still not have it (no redundant copy) -# FIXME should fail -stat $(toRealPath "$storeA/nix/store" "$path") +expect 1 stat $(toRealPath "$storeB/nix/store" "$path") -### Do a build in overlay store +## Ooops something went wrong -path=$(nix-build ./hermetic.nix --arg busybox $busybox --arg seed 2 --store "$storeB") - -# Checking for path in lower layer (should fail) -expect 1 stat $(toRealPath "$storeA/nix/store" "$path") - -# Checking for path in upper layer -stat $(toRealPath "$storeBTop" "$path") - -# Verifying path in overlay store -nix-store --verify-path --store "$storeB" "$path" +## ### Do a build in overlay store +## +## path=$(nix-build ./hermetic.nix --arg busybox $busybox --arg seed 2 --store "$storeB") +## +## # Checking for path in lower layer (should fail) +## expect 1 stat $(toRealPath "$storeA/nix/store" "$path") +## +## # Checking for path in upper layer +## stat $(toRealPath "$storeBTop" "$path") +## +## # Verifying path in overlay store +## nix-store --verify-path --store "$storeB" "$path"