Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 92 additions & 0 deletions src/libstore/local-cache-store.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
#include "archive.hh"
#include "local-cache-store.hh"
#include "callback.hh"
#include "url.hh"
#include <regex>

namespace nix {

LocalCacheStore::LocalCacheStore(const Params & params)
: StoreConfig(params)
, LocalFSStoreConfig(params)
, LocalCacheStoreConfig(params)
, Store(params)
, LocalFSStore(params)
{
}

LocalCacheStore::LocalCacheStore(std::string scheme, std::string path, const Params & params)
: LocalCacheStore(params)
{
debug("LocalCacheStore");
for (const auto& [key, value] : params)
debug("params[%s] = %s", key, value);
debug("rootDir: %s", this->rootDir.get());
debug("realStoreDir: %s", this->realStoreDir.get());
}

void LocalCacheStore::narFromPath(const StorePath & path, Sink & sink)
{
debug("narFromPath");
if (!isValidPath(path))
throw Error("path '%s' is not valid", printStorePath(path));
auto pathToDump = std::string(printStorePath(path), storeDir.size());
dumpPath(pathToDump, sink);
}

void LocalCacheStore::queryPathInfoUncached(
const StorePath & path, Callback<std::shared_ptr<const ValidPathInfo>> callback) noexcept
{
debug("queryPathInfoUncached");
auto callbackPtr = std::make_shared<decltype(callback)>(std::move(callback));
try
{
debug("LocalCacheStore.queryPathInfoUncached storePath: %s", printStorePath(path));
auto narinfo_path = std::string{path.hashPart()} + ".narinfo";
auto real_narinfo_path = this->realStoreDir.get() + narinfo_path;
debug("LocalCacheStore.queryPathInfoUncached: %s", narinfo_path);
try {
auto narinfo_str = nix::readFile(real_narinfo_path);
debug("LocalCacheStore.queryPathInfoUncached read success");
debug(narinfo_str);
debug(narinfo_path);
auto validPathInfo = (std::shared_ptr<ValidPathInfo>)std::make_shared<NarInfo>(*this, narinfo_str, narinfo_path);
return (*callbackPtr)(std::move(validPathInfo));
} catch (SysError &) {
debug("LocalCacheStore.queryPathInfoUncached error storePath: %s", printStorePath(path));
return (*callbackPtr)({});
}
} catch (...) {
debug("LocalCacheStore.queryPathInfoUncached error storePath: %s", printStorePath(path));
return callbackPtr->rethrow();
}
}

// Unimplemented methods
std::optional<StorePath> LocalCacheStore::queryPathFromHashPart(const std::string & hashPart)
{ unsupported("queryPathFromHashPart"); }
void LocalCacheStore::addToStore(const ValidPathInfo & info, Source & source,
RepairFlag repair, CheckSigsFlag checkSigs)
{ unsupported("addToStore"); }
StorePath LocalCacheStore::addTextToStore(
std::string_view name,
std::string_view s,
const StorePathSet & references,
RepairFlag repair)
{ unsupported("addTextToStore"); }
void LocalCacheStore::queryRealisationUncached(const DrvOutput & drvOutput,
Callback<std::shared_ptr<const Realisation>> callback) noexcept
{ unsupported("queryRealisationUncached"); }
std::optional<TrustedFlag> LocalCacheStore::isTrustedClient()
{ unsupported("isTrustedClient"); }
void LocalCacheStore::addIndirectRoot(const Path & path)
{ unsupported("addIndirectRoot"); }
Roots LocalCacheStore::findRoots(bool censor)
{ unsupported("findRoots"); }
void LocalCacheStore::collectGarbage(const GCOptions & options, GCResults & results)
{ unsupported("colelctGarbage"); }
void LocalCacheStore::addBuildLog(const StorePath & path, std::string_view log)
{ unsupported("addBuildLog"); }

static RegisterStoreImplementation<LocalCacheStore, LocalCacheStoreConfig> regLocalCacheStore;
}
77 changes: 77 additions & 0 deletions src/libstore/local-cache-store.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#include "local-store.hh"

namespace nix {

/**
* Configuration for `LocalCacheStore`.
*/
struct LocalCacheStoreConfig : virtual LocalFSStoreConfig
{
LocalCacheStoreConfig(const StringMap & params)
: StoreConfig(params)
, LocalFSStoreConfig(params)
{ }

const std::string name() override { return "Experimental Local Cache Store"; }

std::string doc() override
{
return
""
// FIXME write docs
//#include "local-cache-store.md"
;
}

};

/**
* Variation of local store that uses a using overlayfs for the store dir.
*/
class LocalCacheStore : public virtual LocalCacheStoreConfig, public virtual LocalFSStore
{

public:
LocalCacheStore(const Params & params);

LocalCacheStore(std::string scheme, std::string path, const Params & params);

static std::set<std::string> uriSchemes()
{ return { "local-cache" }; }

std::string getUri() override
{
return "local-cache";
}

private:
// Overridden methods…

void narFromPath(const StorePath & path, Sink & sink) override;

void queryPathInfoUncached(const StorePath & path,
Callback<std::shared_ptr<const ValidPathInfo>> callback) noexcept override;

std::optional<StorePath> queryPathFromHashPart(const std::string & hashPart);

void addToStore(const ValidPathInfo & info, Source & source,
RepairFlag repair, CheckSigsFlag checkSigs);

StorePath addTextToStore(
std::string_view name,
std::string_view s,
const StorePathSet & references,
RepairFlag repair);

void queryRealisationUncached(const DrvOutput & drvOutput,
Callback<std::shared_ptr<const Realisation>> callback) noexcept;

std::optional<TrustedFlag> isTrustedClient();
void addIndirectRoot(const Path & path);
Roots findRoots(bool censor);
void collectGarbage(const GCOptions & options, GCResults & results);
void addBuildLog(const StorePath & path, std::string_view log);

};

}
3 changes: 3 additions & 0 deletions src/libstore/store-api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "callback.hh"
#include "remote-store.hh"
#include "local-overlay-store.hh"
#include "local-cache-store.hh"

#include <nlohmann/json.hpp>
#include <regex>
Expand Down Expand Up @@ -1447,6 +1448,8 @@ std::shared_ptr<Store> openFromNonUri(const std::string & uri, const Store::Para
auto store = std::make_shared<LocalOverlayStore>(params);
experimentalFeatureSettings.require(store->experimentalFeature());
return store;
} else if (uri == "local-cache") {
return std::make_shared<LocalCacheStore>(params);
} else if (isNonUriPath(uri)) {
Store::Params params2 = params;
params2["root"] = absPath(uri);
Expand Down
55 changes: 55 additions & 0 deletions test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#!/usr/bin/env bash
set -xeuo pipefail

flakes="--extra-experimental-features nix-command --extra-experimental-features flakes"

make -j $NIX_BUILD_CORES

sudo umount /tmp/nix/store || true
#trap 'sudo umount /tmp/nix/store' EXIT

sudo rm -rf /tmp/nix
sudo rm -rf /tmp/nix-upper
sudo rm -rf /tmp/nix-work
sudo rm -rf /tmp/nix-lower
mkdir -p /tmp/nix/store
mkdir -p /tmp/nix-upper
mkdir -p /tmp/nix-work
mkdir -p /tmp/nix-lower/nix/store

export NIX_CONFIG="extra-experimental-features = nix-command flakes"

# static lower dir
#
# nix build 'github:nixos/nixpkgs/af21c31b2a1ec5d361ed8050edd0303c31306397#hello'
#
# helloOutPath=$(nix eval --raw 'github:nixos/nixpkgs/af21c31b2a1ec5d361ed8050edd0303c31306397#hello.outPath')
#
# cp -r --parents "${helloOutPath}" /tmp/nix-lower/
# curl https://cache.nixos.org/2g3jazymqbjw9c390c3b7vw8xq3r8iny.narinfo -o /tmp/nix-lower/nix/store/2g3jazymqbjw9c390c3b7vw8xq3r8iny.narinfo
#
# ls -la /tmp/nix-lower/nix/store/
#
# sudo mount -t overlay overlay \
# -o lowerdir="/tmp/nix-lower/nix/store" \
# -o upperdir="/tmp/nix-upper" \
# -o workdir="/tmp/nix-work" \
# "/tmp/nix/store"

# ./outputs/out/bin/nix build -vvvv -L --builders '' --max-jobs 0 --show-trace --store 'local-overlay?root=/tmp&lower-store=local-cache:%3Froot=%2Ftmp%2Fnix-lower&upper-layer=/tmp/nix-upper' 'github:nixos/nixpkgs/af21c31b2a1ec5d361ed8050edd0303c31306397#hello'

# ersa version

sudo mount -t overlay overlay \
-o lowerdir="/var/lib/ersa/nix/store" \
-o upperdir="/tmp/nix-upper" \
-o workdir="/tmp/nix-work" \
"/tmp/nix/store"

outPath=$(sudo -E ./outputs/out/bin/nix eval --raw -vvvv -L --show-trace --store 'local-overlay?root=/tmp&lower-store=local-cache:%3Froot=%2Fvar%2Flib%2Fersa&upper-layer=/tmp/nix-upper' 'github:nixos/nixpkgs/af21c31b2a1ec5d361ed8050edd0303c31306397#hello.outPath')

if [ "$outPath" = "/nix/store/2g3jazymqbjw9c390c3b7vw8xq3r8iny-hello-2.12.1" ]; then
echo "succeess"
else
echo "failure"
fi