libstore: don't derive store classes from their configs

the very slight speedup in config setting access is not worth the
maintenance overhead of conflating concers like this. the virtual
inheritance scheme used for configs requires too much duplication
of base class constructor arguments to be worth doing. perhaps we
should get rid of all virtual inheritance of data-membered bases?

Change-Id: I4acf5ceaedb4ed7476efe1114c2e065ec72d2c6d
This commit is contained in:
eldritch horrors 2024-11-17 14:43:57 +01:00
parent b0d7a81613
commit 95a9a4cece
42 changed files with 356 additions and 324 deletions

View file

@ -51,7 +51,7 @@ static AutoCloseFD openSlotLock(const Machine & m, uint64_t slot)
static bool allSupportedLocally(Store & store, const std::set<std::string>& requiredFeatures) {
for (auto & feature : requiredFeatures)
if (!store.systemFeatures.get().count(feature)) return false;
if (!store.config().systemFeatures.get().count(feature)) return false;
return true;
}
@ -92,7 +92,7 @@ static int main_build_remote(int argc, char * * argv)
that gets cleared on reboot, but it wouldn't work on macOS. */
auto currentLoadName = "/current-load";
if (auto localStore = store.dynamic_pointer_cast<LocalFSStore>())
currentLoad = std::string { localStore->stateDir } + currentLoadName;
currentLoad = std::string { localStore->config().stateDir } + currentLoadName;
else
currentLoad = settings.nixStateDir + currentLoadName;

View file

@ -430,7 +430,7 @@ static void main_nix_build(int argc, char * * argv)
// Don't use defaultTempDir() here! We want to preserve the user's TMPDIR for the shell
env["NIX_BUILD_TOP"] = env["TMPDIR"] = env["TEMPDIR"] = env["TMP"] = env["TEMP"] = getEnvNonEmpty("TMPDIR").value_or("/tmp");
env["NIX_STORE"] = store->storeDir;
env["NIX_STORE"] = store->config().storeDir;
env["NIX_BUILD_CORES"] = std::to_string(settings.buildCores);
auto passAsFile = tokenizeString<StringSet>(getOr(drv.env, "passAsFile", ""));

View file

@ -1,7 +1,7 @@
---
name: storeDir
type: string
constructorArgs: [store->storeDir]
constructorArgs: [store->config().storeDir]
---
Logical file system location of the [Nix store](@docroot@/glossary.md#gloss-store) currently in use.

View file

@ -22,12 +22,10 @@
namespace nix {
BinaryCacheStore::BinaryCacheStore(const Params & params)
: BinaryCacheStoreConfig(params)
, Store(params)
BinaryCacheStore::BinaryCacheStore(const BinaryCacheStoreConfig & config)
{
if (secretKeyFile != "")
secretKey = std::unique_ptr<SecretKey>(new SecretKey(readFile(secretKeyFile)));
if (config.secretKeyFile != "")
secretKey = std::unique_ptr<SecretKey>(new SecretKey(readFile(config.secretKeyFile)));
StringSink sink;
sink << narVersionMagic1;
@ -40,7 +38,7 @@ void BinaryCacheStore::init()
auto cacheInfo = getFileContents(cacheInfoFile);
if (!cacheInfo) {
upsertFile(cacheInfoFile, "StoreDir: " + storeDir + "\n", "text/x-nix-cache-info");
upsertFile(cacheInfoFile, "StoreDir: " + config().storeDir + "\n", "text/x-nix-cache-info");
} else {
for (auto & line : tokenizeString<Strings>(*cacheInfo, "\n")) {
size_t colon= line.find(':');
@ -48,13 +46,13 @@ void BinaryCacheStore::init()
auto name = line.substr(0, colon);
auto value = trim(line.substr(colon + 1, std::string::npos));
if (name == "StoreDir") {
if (value != storeDir)
if (value != config().storeDir)
throw Error("binary cache '%s' is for Nix stores with prefix '%s', not '%s'",
getUri(), value, storeDir);
getUri(), value, config().storeDir);
} else if (name == "WantMassQuery") {
wantMassQuery.setDefault(value == "1");
config().wantMassQuery.setDefault(value == "1");
} else if (name == "Priority") {
priority.setDefault(std::stoi(value));
config().priority.setDefault(std::stoi(value));
}
}
}
@ -134,7 +132,12 @@ ref<const ValidPathInfo> BinaryCacheStore::addToStoreCommon(
{
FdSink fileSink(fdTemp.get());
TeeSink teeSinkCompressed { fileSink, fileHashSink };
auto compressionSink = makeCompressionSink(compression, teeSinkCompressed, parallelCompression, compressionLevel);
auto compressionSink = makeCompressionSink(
config().compression,
teeSinkCompressed,
config().parallelCompression,
config().compressionLevel
);
TeeSink teeSinkUncompressed { *compressionSink, narHashSink };
TeeSource teeSource { narSource, teeSinkUncompressed };
narAccessor = makeNarAccessor(teeSource);
@ -146,17 +149,17 @@ ref<const ValidPathInfo> BinaryCacheStore::addToStoreCommon(
auto info = mkInfo(narHashSink.finish());
auto narInfo = make_ref<NarInfo>(info);
narInfo->compression = compression;
narInfo->compression = config().compression;
auto [fileHash, fileSize] = fileHashSink.finish();
narInfo->fileHash = fileHash;
narInfo->fileSize = fileSize;
narInfo->url = "nar/" + narInfo->fileHash->to_string(Base::Base32, false) + ".nar"
+ (compression == "xz" ? ".xz" :
compression == "bzip2" ? ".bz2" :
compression == "zstd" ? ".zst" :
compression == "lzip" ? ".lzip" :
compression == "lz4" ? ".lz4" :
compression == "br" ? ".br" :
+ (config().compression == "xz" ? ".xz" :
config().compression == "bzip2" ? ".bz2" :
config().compression == "zstd" ? ".zst" :
config().compression == "lzip" ? ".lzip" :
config().compression == "lz4" ? ".lz4" :
config().compression == "br" ? ".br" :
"");
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(now2 - now1).count();
@ -178,7 +181,7 @@ ref<const ValidPathInfo> BinaryCacheStore::addToStoreCommon(
/* Optionally write a JSON file containing a listing of the
contents of the NAR. */
if (writeNARListing) {
if (config().writeNARListing) {
nlohmann::json j = {
{"version", 1},
{"root", listNar(ref<FSAccessor>(narAccessor), "", true)},
@ -190,7 +193,7 @@ ref<const ValidPathInfo> BinaryCacheStore::addToStoreCommon(
/* Optionally maintain an index of DWARF debug info files
consisting of JSON files named 'debuginfo/<build-id>' that
specify the NAR file and member containing the debug info. */
if (writeDebugInfo) {
if (config().writeDebugInfo) {
std::string buildIdDir = "/lib/debug/.build-id";
@ -470,7 +473,7 @@ void BinaryCacheStore::registerDrvOutput(const Realisation& info) {
ref<FSAccessor> BinaryCacheStore::getFSAccessor()
{
return make_ref<RemoteFSAccessor>(ref<Store>(shared_from_this()), localNarCache);
return make_ref<RemoteFSAccessor>(ref<Store>(shared_from_this()), config().localNarCache);
}
void BinaryCacheStore::addSignatures(const StorePath & storePath, const StringSet & sigs)

View file

@ -51,8 +51,7 @@ struct BinaryCacheStoreConfig : virtual StoreConfig
* @note subclasses must implement at least one of the two
* virtual getFile() methods.
*/
class BinaryCacheStore : public virtual BinaryCacheStoreConfig,
public virtual Store,
class BinaryCacheStore : public virtual Store,
public virtual LogStore
{
@ -65,10 +64,13 @@ protected:
// The prefix under which realisation infos will be stored
const std::string realisationsPrefix = "realisations";
BinaryCacheStore(const Params & params);
BinaryCacheStore(const BinaryCacheStoreConfig & config);
public:
BinaryCacheStoreConfig & config() override = 0;
const BinaryCacheStoreConfig & config() const override = 0;
virtual bool fileExists(const std::string & path) = 0;
virtual void upsertFile(const std::string & path,

View file

@ -1316,7 +1316,7 @@ Path DerivationGoal::openLogFile()
/* Create a log file. */
Path logDir;
if (auto localStore = dynamic_cast<LocalStore *>(&worker.store))
logDir = localStore->logDir;
logDir = localStore->config().logDir;
else
logDir = settings.nixLogDir;
Path dir = fmt("%s/%s/%s/", logDir, LocalFSStore::drvsLogDir, baseName.substr(0, 2));

View file

@ -200,7 +200,7 @@ retry:
}
auto & localStore = getLocalStore();
if (localStore.storeDir != localStore.realStoreDir.get()) {
if (localStore.config().storeDir != localStore.config().realStoreDir.get()) {
#if __linux__
useChroot = true;
#else
@ -355,7 +355,7 @@ bool LocalDerivationGoal::cleanupDecideWhetherDiskFull()
auto & localStore = getLocalStore();
uint64_t required = 8ULL * 1024 * 1024; // FIXME: make configurable
struct statvfs st;
if (statvfs(localStore.realStoreDir.get().c_str(), &st) == 0 &&
if (statvfs(localStore.config().realStoreDir.get().c_str(), &st) == 0 &&
(uint64_t) st.f_bavail * st.f_bsize < required)
diskFull = true;
if (statvfs(tmpDir.c_str(), &st) == 0 &&
@ -475,7 +475,7 @@ kj::Promise<Outcome<void, Goal::WorkResult>> LocalDerivationGoal::startBuilder()
concatStringsSep(", ", parsedDrv->getRequiredSystemFeatures()),
worker.store.printStorePath(drvPath),
settings.thisSystem,
concatStringsSep<StringSet>(", ", worker.store.systemFeatures),
concatStringsSep<StringSet>(", ", worker.store.config().systemFeatures),
Uncolored(addendum))
});
}
@ -596,7 +596,7 @@ kj::Promise<Outcome<void, Goal::WorkResult>> LocalDerivationGoal::startBuilder()
else
pathsInChroot[i.substr(0, p)] = {i.substr(p + 1), optional};
}
if (worker.store.storeDir.starts_with(tmpDirInSandbox))
if (worker.store.config().storeDir.starts_with(tmpDirInSandbox))
{
throw Error("`sandbox-build-dir` must not contain the storeDir");
}
@ -872,7 +872,7 @@ void LocalDerivationGoal::initEnv()
shouldn't care, but this is useful for purity checking (e.g.,
the compiler or linker might only want to accept paths to files
in the store or in the build directory). */
env["NIX_STORE"] = worker.store.storeDir;
env["NIX_STORE"] = worker.store.config().storeDir;
/* The maximum number of cores to utilize for parallel building. */
env["NIX_BUILD_CORES"] = fmt("%d", settings.buildCores);
@ -975,23 +975,25 @@ struct RestrictedStoreConfig : virtual LocalFSStoreConfig
/* A wrapper around LocalStore that only allows building/querying of
paths that are in the input closures of the build or were added via
recursive Nix calls. */
struct RestrictedStore : public virtual RestrictedStoreConfig, public virtual IndirectRootStore, public virtual GcStore
struct RestrictedStore : public virtual IndirectRootStore, public virtual GcStore
{
RestrictedStoreConfig config_;
RestrictedStoreConfig & config() override { return config_; }
const RestrictedStoreConfig & config() const override { return config_; }
ref<LocalStore> next;
LocalDerivationGoal & goal;
RestrictedStore(const Params & params, ref<LocalStore> next, LocalDerivationGoal & goal)
: StoreConfig(params)
, LocalFSStoreConfig(params)
, RestrictedStoreConfig(params)
, Store(params)
, LocalFSStore(params)
RestrictedStore(RestrictedStoreConfig config, ref<LocalStore> next, LocalDerivationGoal & goal)
: Store(config)
, config_(std::move(config))
, next(next), goal(goal)
{ }
Path getRealStoreDir() override
{ return next->realStoreDir; }
{ return next->config().realStoreDir; }
std::string getUri() override
{ return next->getUri(); }
@ -1203,10 +1205,10 @@ void LocalDerivationGoal::startDaemon()
{
experimentalFeatureSettings.require(Xp::RecursiveNix);
Store::Params params;
StoreConfig::Params params;
params["path-info-cache-size"] = "0";
params["store"] = worker.store.storeDir;
if (auto & optRoot = getLocalStore().rootDir.get())
params["store"] = worker.store.config().storeDir;
if (auto & optRoot = getLocalStore().config().rootDir.get())
params["root"] = *optRoot;
params["state"] = "/no-such-path";
params["log"] = "/no-such-path";
@ -1444,7 +1446,7 @@ void LocalDerivationGoal::runChild()
Marking chrootRootDir as MS_SHARED causes pivot_root()
to fail with EINVAL. Don't know why. */
Path chrootStoreDir = chrootRootDir + worker.store.storeDir;
Path chrootStoreDir = chrootRootDir + worker.store.config().storeDir;
if (mount(chrootStoreDir.c_str(), chrootStoreDir.c_str(), 0, MS_BIND, 0) == -1)
throw SysError("unable to bind mount the Nix store", chrootStoreDir);
@ -1459,8 +1461,11 @@ void LocalDerivationGoal::runChild()
createDirs(chrootRootDir + "/dev/shm");
createDirs(chrootRootDir + "/dev/pts");
ss.push_back("/dev/full");
if (worker.store.systemFeatures.get().count("kvm") && pathExists("/dev/kvm"))
if (worker.store.config().systemFeatures.get().count("kvm")
&& pathExists("/dev/kvm"))
{
ss.push_back("/dev/kvm");
}
ss.push_back("/dev/null");
ss.push_back("/dev/random");
ss.push_back("/dev/tty");
@ -1702,7 +1707,7 @@ void LocalDerivationGoal::runChild()
/* And we want the store in there regardless of how empty pathsInChroot. We include the innermost
path component this time, since it's typically /nix/store and we care about that. */
Path cur = worker.store.storeDir;
Path cur = worker.store.config().storeDir;
while (cur.compare("/") != 0) {
ancestry.insert(cur);
cur = dirOf(cur);

View file

@ -100,9 +100,9 @@ try {
subPath = sub->makeFixedOutputPathFromCA(
std::string { storePath.name() },
ContentAddressWithReferences::withoutRefs(*ca));
if (sub->storeDir == worker.store.storeDir)
if (sub->config().storeDir == worker.store.config().storeDir)
assert(subPath == storePath);
} else if (sub->storeDir != worker.store.storeDir) {
} else if (sub->config().storeDir != worker.store.config().storeDir) {
co_return co_await tryNext();
}
@ -151,7 +151,7 @@ try {
/* Bail out early if this substituter lacks a valid
signature. LocalStore::addToStore() also checks for this, but
only after we've downloaded the path. */
if (!sub->isTrusted && worker.store.pathInfoIsUntrusted(*info))
if (!sub->config().isTrusted && worker.store.pathInfoIsUntrusted(*info))
{
warn("ignoring substitute for '%s' from '%s', as it's not signed by any of the keys in 'trusted-public-keys'",
worker.store.printStorePath(storePath), sub->getUri());
@ -220,7 +220,11 @@ try {
PushActivity pact(act.id);
copyStorePath(
*sub, worker.store, fetchPath, repair, sub->isTrusted ? NoCheckSigs : CheckSigs
*sub,
worker.store,
fetchPath,
repair,
sub->config().isTrusted ? NoCheckSigs : CheckSigs
);
} catch (const EndOfFile &) {
throw EndOfFile(

View file

@ -16,17 +16,18 @@ struct DummyStoreConfig : virtual StoreConfig {
}
};
struct DummyStore : public virtual DummyStoreConfig, public virtual Store
struct DummyStore : public virtual Store
{
DummyStore(const std::string scheme, const std::string uri, const Params & params)
: DummyStore(params)
DummyStoreConfig config_;
DummyStoreConfig & config() override { return config_; }
const DummyStoreConfig & config() const override { return config_; }
DummyStore(const std::string scheme, const std::string uri, DummyStoreConfig config)
: DummyStore(std::move(config))
{ }
DummyStore(const Params & params)
: StoreConfig(params)
, DummyStoreConfig(params)
, Store(params)
{ }
DummyStore(DummyStoreConfig config) : Store(config), config_(std::move(config)) {}
std::string getUri() override
{

View file

@ -619,7 +619,7 @@ struct curlFileTransfer : public FileTransfer
}
#if ENABLE_S3
static std::tuple<std::string, std::string, Store::Params> parseS3Uri(std::string uri)
static std::tuple<std::string, std::string, StoreConfig::Params> parseS3Uri(std::string uri)
{
auto [path, params] = splitUriAndParams(uri);

View file

@ -46,7 +46,7 @@ static void makeSymlink(const Path & link, const Path & target)
void LocalStore::addIndirectRoot(const Path & path)
{
std::string hash = hashString(HashType::SHA1, path).to_string(Base::Base32, false);
Path realRoot = canonPath(fmt("%1%/%2%/auto/%3%", stateDir, gcRootsDir, hash));
Path realRoot = canonPath(fmt("%1%/%2%/auto/%3%", config().stateDir, gcRootsDir, hash));
makeSymlink(realRoot, path);
}
@ -111,7 +111,7 @@ void LocalStore::createTempRootsFile()
void LocalStore::addTempRoot(const StorePath & path)
{
if (readOnly) {
if (config().readOnly) {
debug("Read-only store doesn't support creating lock files for temp roots, but nothing can be deleted anyways.");
return;
}
@ -138,7 +138,7 @@ void LocalStore::addTempRoot(const StorePath & path)
auto fdRootsSocket(_fdRootsSocket.lock());
if (!*fdRootsSocket) {
auto socketPath = stateDir.get() + gcSocketPath;
auto socketPath = config().stateDir.get() + gcSocketPath;
debug("connecting to '%s'", socketPath);
*fdRootsSocket = createUnixDomainSocket();
try {
@ -268,7 +268,7 @@ void LocalStore::findRoots(const Path & path, unsigned char type, Roots & roots)
else {
target = absPath(target, dirOf(path));
if (!pathExists(target)) {
if (isInDir(path, stateDir + "/" + gcRootsDir + "/auto")) {
if (isInDir(path, config().stateDir + "/" + gcRootsDir + "/auto")) {
printInfo("removing stale link from '%1%' to '%2%'", path, target);
unlink(path.c_str());
}
@ -282,7 +282,8 @@ void LocalStore::findRoots(const Path & path, unsigned char type, Roots & roots)
}
else if (type == DT_REG) {
auto storePath = maybeParseStorePath(storeDir + "/" + std::string(baseNameOf(path)));
auto storePath =
maybeParseStorePath(config().storeDir + "/" + std::string(baseNameOf(path)));
if (storePath && isValidPath(*storePath))
roots[std::move(*storePath)].emplace(path);
}
@ -302,8 +303,8 @@ void LocalStore::findRoots(const Path & path, unsigned char type, Roots & roots)
void LocalStore::findRootsNoTemp(Roots & roots, bool censor)
{
/* Process direct roots in {gcroots,profiles}. */
findRoots(stateDir + "/" + gcRootsDir, DT_UNKNOWN, roots);
findRoots(stateDir + "/profiles", DT_UNKNOWN, roots);
findRoots(config().stateDir + "/" + gcRootsDir, DT_UNKNOWN, roots);
findRoots(config().stateDir + "/profiles", DT_UNKNOWN, roots);
/* Add additional roots returned by different platforms-specific
heuristics. This is typically used to add running programs to
@ -589,7 +590,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
if (auto p = getEnv("_NIX_TEST_GC_SYNC_1"))
readFile(*p);
GCOperation gcServer {*this, stateDir.get()};
GCOperation gcServer {*this, config().stateDir.get()};
/* Find the roots. Since we've grabbed the GC lock, the set of
permanent roots cannot increase now. */
@ -617,8 +618,8 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
GCLimitReached if we've deleted enough garbage. */
auto deleteFromStore = [&](std::string_view baseName)
{
Path path = storeDir + "/" + std::string(baseName);
Path realPath = realStoreDir + "/" + std::string(baseName);
Path path = config().storeDir + "/" + std::string(baseName);
Path realPath = config().realStoreDir + "/" + std::string(baseName);
/* There may be temp directories in the store that are still in use
by another process. We need to be sure that we can acquire an
@ -774,8 +775,8 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
printInfo("determining live/dead paths...");
try {
AutoCloseDir dir(opendir(realStoreDir.get().c_str()));
if (!dir) throw SysError("opening directory '%1%'", realStoreDir);
AutoCloseDir dir(opendir(config().realStoreDir.get().c_str()));
if (!dir) throw SysError("opening directory '%1%'", config().realStoreDir);
/* Read the store and delete all paths that are invalid or
unreachable. We don't use readDirectory() here so that
@ -788,7 +789,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
std::string name = dirent->d_name;
if (name == "." || name == ".." || name == linksName) continue;
if (auto storePath = maybeParseStorePath(storeDir + "/" + name))
if (auto storePath = maybeParseStorePath(config().storeDir + "/" + name))
deleteReferrersClosure(*storePath);
else
deleteFromStore(name);
@ -870,8 +871,8 @@ void LocalStore::autoGC(bool sync)
return std::stoll(readFile(*fakeFreeSpaceFile));
struct statvfs st;
if (statvfs(realStoreDir.get().c_str(), &st))
throw SysError("getting filesystem info about '%s'", realStoreDir);
if (statvfs(config().realStoreDir.get().c_str(), &st))
throw SysError("getting filesystem info about '%s'", config().realStoreDir);
return (uint64_t) st.f_bavail * st.f_frsize;
};

View file

@ -22,10 +22,11 @@ struct HttpBinaryCacheStoreConfig : virtual BinaryCacheStoreConfig
}
};
class HttpBinaryCacheStore : public virtual HttpBinaryCacheStoreConfig, public virtual BinaryCacheStore
class HttpBinaryCacheStore : public virtual BinaryCacheStore
{
private:
HttpBinaryCacheStoreConfig config_;
Path cacheUri;
struct State
@ -41,12 +42,10 @@ public:
HttpBinaryCacheStore(
const std::string & scheme,
const Path & _cacheUri,
const Params & params)
: StoreConfig(params)
, BinaryCacheStoreConfig(params)
, HttpBinaryCacheStoreConfig(params)
, Store(params)
, BinaryCacheStore(params)
HttpBinaryCacheStoreConfig config)
: Store(config)
, BinaryCacheStore(config)
, config_(std::move(config))
, cacheUri(scheme + "://" + _cacheUri)
{
if (cacheUri.back() == '/')
@ -55,6 +54,9 @@ public:
diskCache = getNarInfoDiskCache();
}
HttpBinaryCacheStoreConfig & config() override { return config_; }
const HttpBinaryCacheStoreConfig & config() const override { return config_; }
std::string getUri() override
{
return cacheUri;
@ -64,15 +66,17 @@ public:
{
// FIXME: do this lazily?
if (auto cacheInfo = diskCache->upToDateCacheExists(cacheUri)) {
wantMassQuery.setDefault(cacheInfo->wantMassQuery);
priority.setDefault(cacheInfo->priority);
config_.wantMassQuery.setDefault(cacheInfo->wantMassQuery);
config_.priority.setDefault(cacheInfo->priority);
} else {
try {
BinaryCacheStore::init();
} catch (UploadToHTTP &) {
throw Error("'%s' does not appear to be a binary cache", cacheUri);
}
diskCache->createCache(cacheUri, storeDir, wantMassQuery, priority);
diskCache->createCache(
cacheUri, config_.storeDir, config_.wantMassQuery, config_.priority
);
}
}

View file

@ -14,7 +14,7 @@
namespace nix {
struct LegacySSHStoreConfig : virtual CommonSSHStoreConfig
struct LegacySSHStoreConfig : CommonSSHStoreConfig
{
using CommonSSHStoreConfig::CommonSSHStoreConfig;
@ -34,12 +34,22 @@ struct LegacySSHStoreConfig : virtual CommonSSHStoreConfig
}
};
struct LegacySSHStore : public virtual LegacySSHStoreConfig, public virtual Store
struct LegacySSHStoreConfigWithLog : LegacySSHStoreConfig
{
using LegacySSHStoreConfig::LegacySSHStoreConfig;
// Hack for getting remote build log output.
// Intentionally not in `LegacySSHStoreConfig` so that it doesn't appear in
// the documentation
const Setting<int> logFD{this, -1, "log-fd", "file descriptor to which SSH's stderr is connected"};
};
struct LegacySSHStore : public virtual Store
{
LegacySSHStoreConfigWithLog config_;
LegacySSHStoreConfigWithLog & config() override { return config_; }
const LegacySSHStoreConfigWithLog & config() const override { return config_; }
struct Connection
{
@ -89,25 +99,25 @@ struct LegacySSHStore : public virtual LegacySSHStoreConfig, public virtual Stor
static std::set<std::string> uriSchemes() { return {"ssh"}; }
LegacySSHStore(const std::string & scheme, const std::string & host, const Params & params)
: StoreConfig(params)
, CommonSSHStoreConfig(params)
, LegacySSHStoreConfig(params)
, Store(params)
LegacySSHStore(
const std::string & scheme, const std::string & host, LegacySSHStoreConfigWithLog config
)
: Store(config)
, config_(std::move(config))
, host(host)
, connections(make_ref<Pool<Connection>>(
std::max(1, (int) maxConnections),
std::max(1, (int) config_.maxConnections),
[this]() { return openConnection(); },
[](const ref<Connection> & r) { return r->good; }
))
, master(
host,
sshKey,
sshPublicHostKey,
config_.sshKey,
config_.sshPublicHostKey,
// Use SSH master only if using more than 1 connection.
connections->capacity() > 1,
compress,
logFD)
config_.compress,
config_.logFD)
{
}
@ -115,8 +125,11 @@ struct LegacySSHStore : public virtual LegacySSHStoreConfig, public virtual Stor
{
auto conn = make_ref<Connection>();
conn->sshConn = master.startCommand(
fmt("%s --serve --write", remoteProgram)
+ (remoteStore.get() == "" ? "" : " --store " + shellEscape(remoteStore.get())));
fmt("%s --serve --write", config_.remoteProgram)
+ (config_.remoteStore.get() == ""
? ""
: " --store " + shellEscape(config_.remoteStore.get()))
);
conn->to = FdSink(conn->sshConn->in.get());
conn->from = FdSource(conn->sshConn->out.get());

View file

@ -21,23 +21,25 @@ struct LocalBinaryCacheStoreConfig : virtual BinaryCacheStoreConfig
}
};
class LocalBinaryCacheStore : public virtual LocalBinaryCacheStoreConfig, public virtual BinaryCacheStore
class LocalBinaryCacheStore : public virtual BinaryCacheStore
{
private:
LocalBinaryCacheStoreConfig config_;
Path binaryCacheDir;
public:
LocalBinaryCacheStoreConfig & config() override { return config_; }
const LocalBinaryCacheStoreConfig & config() const override { return config_; }
LocalBinaryCacheStore(
const std::string scheme,
const Path & binaryCacheDir,
const Params & params)
: StoreConfig(params)
, BinaryCacheStoreConfig(params)
, LocalBinaryCacheStoreConfig(params)
, Store(params)
, BinaryCacheStore(params)
LocalBinaryCacheStoreConfig config)
: Store(config)
, BinaryCacheStore(config)
, config_(std::move(config))
, binaryCacheDir(binaryCacheDir)
{
}
@ -89,7 +91,7 @@ protected:
!entry.name.ends_with(".narinfo"))
continue;
paths.insert(parseStorePath(
storeDir + "/" + entry.name.substr(0, entry.name.size() - 8)
config_.storeDir + "/" + entry.name.substr(0, entry.name.size() - 8)
+ "-" + MissingName));
}
@ -106,7 +108,7 @@ void LocalBinaryCacheStore::init()
{
createDirs(binaryCacheDir + "/nar");
createDirs(binaryCacheDir + "/" + realisationsPrefix);
if (writeDebugInfo)
if (config_.writeDebugInfo)
createDirs(binaryCacheDir + "/debuginfo");
createDirs(binaryCacheDir + "/log");
BinaryCacheStore::init();

View file

@ -8,11 +8,6 @@
namespace nix {
LocalFSStore::LocalFSStore(const Params & params)
: Store(params)
{
}
struct LocalStoreAccessor : public FSAccessor
{
ref<LocalFSStore> store;
@ -24,7 +19,7 @@ struct LocalStoreAccessor : public FSAccessor
auto storePath = store->toStorePath(path).first;
if (requireValidPath && !store->isValidPath(storePath))
throw InvalidPath("path '%1%' does not exist in the store", store->printStorePath(storePath));
return store->getRealStoreDir() + std::string(path, store->storeDir.size());
return store->getRealStoreDir() + std::string(path, store->config().storeDir.size());
}
FSAccessor::Stat stat(const Path & path) override
@ -82,7 +77,7 @@ WireFormatGenerator LocalFSStore::narFromPath(const StorePath & path)
{
if (!isValidPath(path))
throw Error("path '%s' does not exist in store", printStorePath(path));
return dumpPath(getRealStoreDir() + std::string(printStorePath(path), storeDir.size()));
return dumpPath(getRealStoreDir() + std::string(printStorePath(path), config().storeDir.size()));
}
const std::string LocalFSStore::drvsLogDir = "drvs";
@ -95,8 +90,8 @@ std::optional<std::string> LocalFSStore::getBuildLogExact(const StorePath & path
Path logPath =
j == 0
? fmt("%s/%s/%s/%s", logDir, drvsLogDir, baseName.substr(0, 2), baseName.substr(2))
: fmt("%s/%s/%s", logDir, drvsLogDir, baseName);
? fmt("%s/%s/%s/%s", config().logDir, drvsLogDir, baseName.substr(0, 2), baseName.substr(2))
: fmt("%s/%s/%s", config().logDir, drvsLogDir, baseName);
Path logBz2Path = logPath + ".bz2";
if (pathExists(logPath))

View file

@ -30,8 +30,7 @@ struct LocalFSStoreConfig : virtual StoreConfig
"Physical path of the Nix store."};
};
class LocalFSStore : public virtual LocalFSStoreConfig,
public virtual Store,
class LocalFSStore : public virtual Store,
public virtual GcStore,
public virtual LogStore
{
@ -40,7 +39,8 @@ public:
const static std::string drvsLogDir;
LocalFSStore(const Params & params);
LocalFSStoreConfig & config() override = 0;
const LocalFSStoreConfig & config() const override = 0;
WireFormatGenerator narFromPath(const StorePath & path) override;
ref<FSAccessor> getFSAccessor() override;
@ -61,12 +61,12 @@ public:
*/
virtual Path addPermRoot(const StorePath & storePath, const Path & gcRoot) = 0;
virtual Path getRealStoreDir() { return realStoreDir; }
virtual Path getRealStoreDir() { return config().realStoreDir; }
Path toRealPath(const Path & storePath) override
{
assert(isInStore(storePath));
return getRealStoreDir() + "/" + std::string(storePath, storeDir.size() + 1);
return getRealStoreDir() + "/" + std::string(storePath, config().storeDir.size() + 1);
}
std::optional<std::string> getBuildLogExact(const StorePath & path) override;

View file

@ -174,17 +174,14 @@ void migrateCASchema(SQLite& db, Path schemaPath, AutoCloseFD& lockFd)
}
}
LocalStore::LocalStore(const Params & params)
: StoreConfig(params)
, LocalFSStoreConfig(params)
, LocalStoreConfig(params)
, Store(params)
, LocalFSStore(params)
, dbDir(stateDir + "/db")
, linksDir(realStoreDir + "/.links")
LocalStore::LocalStore(LocalStoreConfig config)
: Store(config)
, config_(std::move(config))
, dbDir(config_.stateDir + "/db")
, linksDir(config_.realStoreDir + "/.links")
, reservedSpacePath(dbDir + "/reserved")
, schemaPath(dbDir + "/schema")
, tempRootsDir(stateDir + "/temproots")
, tempRootsDir(config_.stateDir + "/temproots")
, fnTempRoots(fmt("%s/%d", tempRootsDir, getpid()))
, locksHeld(tokenizeString<PathSet>(getEnv("NIX_HELD_LOCKS").value_or("")))
{
@ -192,18 +189,18 @@ LocalStore::LocalStore(const Params & params)
state->stmts = std::make_unique<State::Stmts>();
/* Create missing state directories if they don't already exist. */
createDirs(realStoreDir);
if (readOnly) {
createDirs(config_.realStoreDir);
if (config_.readOnly) {
experimentalFeatureSettings.require(Xp::ReadOnlyLocalStore);
} else {
makeStoreWritable();
}
createDirs(linksDir);
Path profilesDir = stateDir + "/profiles";
Path profilesDir = config_.stateDir + "/profiles";
createDirs(profilesDir);
createDirs(tempRootsDir);
createDirs(dbDir);
Path gcRootsDir = stateDir + "/gcroots";
Path gcRootsDir = config_.stateDir + "/gcroots";
if (!pathExists(gcRootsDir)) {
createDirs(gcRootsDir);
createSymlink(profilesDir, gcRootsDir + "/profiles");
@ -211,7 +208,7 @@ LocalStore::LocalStore(const Params & params)
for (auto & perUserDir : {profilesDir + "/per-user", gcRootsDir + "/per-user"}) {
createDirs(perUserDir);
if (!readOnly) {
if (!config_.readOnly) {
if (chmod(perUserDir.c_str(), 0755) == -1)
throw SysError("could not set permissions on '%s' to 755", perUserDir);
}
@ -227,21 +224,21 @@ LocalStore::LocalStore(const Params & params)
printError("warning: the group '%1%' specified in 'build-users-group' does not exist", settings.buildUsersGroup);
else {
struct stat st;
if (stat(realStoreDir.get().c_str(), &st))
throw SysError("getting attributes of path '%1%'", realStoreDir);
if (stat(config_.realStoreDir.get().c_str(), &st))
throw SysError("getting attributes of path '%1%'", config_.realStoreDir);
if (st.st_uid != 0 || st.st_gid != gr->gr_gid || (st.st_mode & ~S_IFMT) != perm) {
if (chown(realStoreDir.get().c_str(), 0, gr->gr_gid) == -1)
throw SysError("changing ownership of path '%1%'", realStoreDir);
if (chmod(realStoreDir.get().c_str(), perm) == -1)
throw SysError("changing permissions on path '%1%'", realStoreDir);
if (chown(config_.realStoreDir.get().c_str(), 0, gr->gr_gid) == -1)
throw SysError("changing ownership of path '%1%'", config_.realStoreDir);
if (chmod(config_.realStoreDir.get().c_str(), perm) == -1)
throw SysError("changing permissions on path '%1%'", config_.realStoreDir);
}
}
}
/* Ensure that the store and its parents are not symlinks. */
if (!settings.allowSymlinkedStore) {
Path path = realStoreDir;
Path path = config_.realStoreDir;
struct stat st;
while (path != "/") {
st = lstat(path);
@ -278,12 +275,12 @@ LocalStore::LocalStore(const Params & params)
/* Acquire the big fat lock in shared mode to make sure that no
schema upgrade is in progress. */
if (!readOnly) {
if (!config_.readOnly) {
Path globalLockPath = dbDir + "/big-lock";
globalLock = openLockFile(globalLockPath.c_str(), true);
}
if (!readOnly && !lockFile(globalLock.get(), ltRead, false)) {
if (!config_.readOnly && !lockFile(globalLock.get(), ltRead, false)) {
printInfo("waiting for the big Nix store lock...");
lockFile(globalLock.get(), ltRead, true);
}
@ -291,7 +288,7 @@ LocalStore::LocalStore(const Params & params)
/* Check the current database schema and if necessary do an
upgrade. */
int curSchema = getSchema();
if (readOnly && curSchema < nixSchemaVersion) {
if (config_.readOnly && curSchema < nixSchemaVersion) {
debug("current schema version: %d", curSchema);
debug("supported schema version: %d", nixSchemaVersion);
throw Error(curSchema == 0 ?
@ -363,7 +360,7 @@ LocalStore::LocalStore(const Params & params)
else openDB(*state, false);
if (experimentalFeatureSettings.isEnabled(Xp::CaDerivations)) {
if (!readOnly) {
if (!config_.readOnly) {
migrateCASchema(state->db, dbDir + "/ca-schema", globalLock);
} else {
throw Error("need to migrate to content-addressed schema, but this cannot be done in read-only mode");
@ -443,8 +440,8 @@ LocalStore::LocalStore(const Params & params)
}
LocalStore::LocalStore(std::string scheme, std::string path, const Params & params)
: LocalStore(params)
LocalStore::LocalStore(std::string scheme, std::string path, LocalStoreConfig config)
: LocalStore(std::move(config))
{
throw UnimplementedError("LocalStore");
}
@ -452,7 +449,7 @@ LocalStore::LocalStore(std::string scheme, std::string path, const Params & para
AutoCloseFD LocalStore::openGCLock()
{
Path fnGCLock = stateDir + "/gc.lock";
Path fnGCLock = config_.stateDir + "/gc.lock";
AutoCloseFD fdGCLock{open(fnGCLock.c_str(), O_RDWR | O_CREAT | O_CLOEXEC, 0600)};
if (!fdGCLock)
throw SysError("opening global GC lock '%1%'", fnGCLock);
@ -498,17 +495,17 @@ int LocalStore::getSchema()
void LocalStore::openDB(State & state, bool create)
{
if (create && readOnly) {
if (create && config_.readOnly) {
throw Error("cannot create database while in read-only mode");
}
if (access(dbDir.c_str(), R_OK | (readOnly ? 0 : W_OK)))
if (access(dbDir.c_str(), R_OK | (config_.readOnly ? 0 : W_OK)))
throw SysError("Nix database directory '%1%' is not writable", dbDir);
/* Open the Nix database. */
std::string dbPath = dbDir + "/db.sqlite";
auto & db(state.db);
auto openMode = readOnly ? SQLiteOpenMode::Immutable
auto openMode = config_.readOnly ? SQLiteOpenMode::Immutable
: create ? SQLiteOpenMode::Normal
: SQLiteOpenMode::NoCreate;
state.db = SQLite(dbPath, openMode);
@ -587,12 +584,12 @@ void LocalStore::makeStoreWritable()
if (getuid() != 0) return;
/* Check if /nix/store is on a read-only mount. */
struct statvfs stat;
if (statvfs(realStoreDir.get().c_str(), &stat) != 0)
if (statvfs(config_.realStoreDir.get().c_str(), &stat) != 0)
throw SysError("getting info about the Nix store mount point");
if (stat.f_flag & ST_RDONLY) {
if (mount(0, realStoreDir.get().c_str(), "none", MS_REMOUNT | MS_BIND, 0) == -1)
throw SysError("remounting %1% writable", realStoreDir);
if (mount(0, config_.realStoreDir.get().c_str(), "none", MS_REMOUNT | MS_BIND, 0) == -1)
throw SysError("remounting %1% writable", config_.realStoreDir);
}
#endif
}
@ -1068,7 +1065,7 @@ std::optional<StorePath> LocalStore::queryPathFromHashPart(const std::string & h
{
if (hashPart.size() != StorePath::HashLen) throw Error("invalid hash part");
Path prefix = storeDir + "/" + hashPart;
Path prefix = config_.storeDir + "/" + hashPart;
return retrySQLite<std::optional<StorePath>>([&]() -> std::optional<StorePath> {
auto state(_state.lock());
@ -1097,8 +1094,8 @@ StorePathSet LocalStore::querySubstitutablePaths(const StorePathSet & paths)
for (auto & sub : getDefaultSubstituters()) {
if (remaining.empty()) break;
if (sub->storeDir != storeDir) continue;
if (!sub->wantMassQuery) continue;
if (sub->config().storeDir != config_.storeDir) continue;
if (!sub->config().wantMassQuery) continue;
auto valid = sub->queryValidPaths(remaining);
@ -1208,12 +1205,12 @@ const PublicKeys & LocalStore::getPublicKeys()
bool LocalStore::pathInfoIsUntrusted(const ValidPathInfo & info)
{
return requireSigs && !info.checkSignatures(*this, getPublicKeys());
return config_.requireSigs && !info.checkSignatures(*this, getPublicKeys());
}
bool LocalStore::realisationIsUntrusted(const Realisation & realisation)
{
return requireSigs && !realisation.checkSignatures(getPublicKeys());
return config_.requireSigs && !realisation.checkSignatures(getPublicKeys());
}
void LocalStore::addToStore(const ValidPathInfo & info, Source & source,
@ -1508,7 +1505,7 @@ std::pair<Path, AutoCloseFD> LocalStore::createTempDirInStore()
/* There is a slight possibility that `tmpDir' gets deleted by
the GC between createTempDir() and when we acquire a lock on it.
We'll repeat until 'tmpDir' exists and we've locked it. */
tmpDirFn = createTempDir(realStoreDir, "tmp");
tmpDirFn = createTempDir(config_.realStoreDir, "tmp");
tmpDirFd = AutoCloseFD{open(tmpDirFn.c_str(), O_RDONLY | O_DIRECTORY)};
if (tmpDirFd.get() < 0) {
continue;
@ -1564,7 +1561,7 @@ bool LocalStore::verifyStore(bool checkContents, RepairFlag repair)
database and the filesystem) in the loop below, in order to catch
invalid states.
*/
for (auto & i : readDirectory(realStoreDir)) {
for (auto & i : readDirectory(config_.realStoreDir)) {
try {
storePathsInStoreDir.insert({i.name});
} catch (BadStorePath &) { }
@ -1758,7 +1755,7 @@ void LocalStore::upgradeStore7()
{
if (getuid() != 0) return;
printInfo("removing immutable bits from the Nix store (this may take a while)...");
makeMutable(realStoreDir);
makeMutable(config_.realStoreDir);
}
#else
@ -1927,7 +1924,9 @@ void LocalStore::addBuildLog(const StorePath & drvPath, std::string_view log)
auto baseName = drvPath.to_string();
auto logPath = fmt("%s/%s/%s/%s.bz2", logDir, drvsLogDir, baseName.substr(0, 2), baseName.substr(2));
auto logPath =
fmt("%s/%s/%s/%s.bz2", config_.logDir, drvsLogDir, baseName.substr(0, 2), baseName.substr(2)
);
if (pathExists(logPath)) return;

View file

@ -68,12 +68,13 @@ struct LocalStoreConfig : virtual LocalFSStoreConfig
std::string doc() override;
};
class LocalStore : public virtual LocalStoreConfig
, public virtual IndirectRootStore
class LocalStore : public virtual IndirectRootStore
, public virtual GcStore
{
private:
LocalStoreConfig config_;
/**
* Lock file used for upgrading.
*/
@ -125,6 +126,9 @@ public:
const Path tempRootsDir;
const Path fnTempRoots;
LocalStoreConfig & config() override { return config_; }
const LocalStoreConfig & config() const override { return config_; }
private:
const PublicKeys & getPublicKeys();
@ -137,8 +141,8 @@ protected:
* Protected so that users don't accidentally create a LocalStore
* instead of a platform's subclass.
*/
LocalStore(const Params & params);
LocalStore(std::string scheme, std::string path, const Params & params);
LocalStore(LocalStoreConfig config);
LocalStore(std::string scheme, std::string path, LocalStoreConfig config);
public:
@ -155,7 +159,7 @@ public:
/**
* Create a LocalStore, possibly a platform-specific subclass
*/
static std::shared_ptr<LocalStore> makeLocalStore(const Params & params);
static std::shared_ptr<LocalStore> makeLocalStore(const StoreConfig::Params & params);
/**
* Implementations of abstract store API methods.

View file

@ -66,7 +66,7 @@ bool Machine::mandatoryMet(const std::set<std::string> & features) const
ref<Store> Machine::openStore() const
{
Store::Params storeParams;
StoreConfig::Params storeParams;
if (storeUri.starts_with("ssh://")) {
storeParams["log-fd"] = "4";
storeParams["max-connections"] = "1";

View file

@ -208,14 +208,14 @@ void LocalStore::optimisePath_(Activity * act, OptimiseStats & stats,
the store itself (we don't want or need to mess with its
permissions). */
const Path dirOfPath(dirOf(path));
bool mustToggle = dirOfPath != realStoreDir.get();
bool mustToggle = dirOfPath != config().realStoreDir.get();
if (mustToggle) makeWritable(dirOfPath);
/* When we're done, make the directory read-only again and reset
its timestamp back to 0. */
MakeReadOnly makeReadOnly(mustToggle ? dirOfPath : "");
Path tempLink = makeTempPath(realStoreDir, "/.tmp-link");
Path tempLink = makeTempPath(config().realStoreDir, "/.tmp-link");
unlink(tempLink.c_str()); // just in case; ignore errors
if (link(linkPath.c_str(), tempLink.c_str()) == -1) {
@ -272,7 +272,13 @@ void LocalStore::optimiseStore(OptimiseStats & stats)
if (!isValidPath(i)) continue; /* path was GC'ed, probably */
{
Activity act(*logger, lvlTalkative, actUnknown, fmt("optimising path '%s'", printStorePath(i)));
optimisePath_(&act, stats, realStoreDir + "/" + std::string(i.to_string()), inodeHash, NoRepair);
optimisePath_(
&act,
stats,
config().realStoreDir + "/" + std::string(i.to_string()),
inodeHash,
NoRepair
);
}
done++;
act.progress(done, paths.size());

View file

@ -111,7 +111,7 @@ bool ParsedDerivation::canBuildLocally(Store & localStore) const
return false;
for (auto & feature : getRequiredSystemFeatures())
if (!localStore.systemFeatures.get().count(feature)) return false;
if (!localStore.config().systemFeatures.get().count(feature)) return false;
return true;
}

View file

@ -68,7 +68,7 @@ StorePath StorePath::random(std::string_view name)
StorePath Store::parseStorePath(std::string_view path) const
{
auto p = canonPath(std::string(path));
if (dirOf(p) != storeDir)
if (dirOf(p) != config().storeDir)
throw BadStorePath("path '%s' is not in the Nix store", p);
return StorePath(baseNameOf(p));
}
@ -77,7 +77,7 @@ std::optional<StorePath> Store::maybeParseStorePath(std::string_view path) const
{
// If it's not an absolute path, or if the dirname of the path isn't /nix/store
// (or whatever our storeDir is), then it can't be a store path.
if ((path.size() > 0 && path[0] != '/') || dirOf(canonPath(path)) != this->storeDir) {
if ((path.size() > 0 && path[0] != '/') || dirOf(canonPath(path)) != config().storeDir) {
return std::nullopt;
}
try {
@ -101,7 +101,7 @@ StorePathSet Store::parseStorePathSet(const PathSet & paths) const
std::string Store::printStorePath(const StorePath & path) const
{
return (storeDir + "/").append(path.to_string());
return (config().storeDir + "/").append(path.to_string());
}
PathSet Store::printStorePathSet(const StorePathSet & paths) const

View file

@ -12,7 +12,7 @@
#endif
namespace nix {
std::shared_ptr<LocalStore> LocalStore::makeLocalStore(const Params & params)
std::shared_ptr<LocalStore> LocalStore::makeLocalStore(const StoreConfig::Params & params)
{
#if __linux__
return std::shared_ptr<LocalStore>(new LinuxLocalStore(params));

View file

@ -16,7 +16,7 @@ namespace nix {
void DarwinLocalStore::findPlatformRoots(UncheckedRoots & unchecked)
{
auto storePathRegex = regex::storePathRegex(storeDir);
auto storePathRegex = regex::storePathRegex(config().storeDir);
std::vector<int> pids;
std::size_t pidBufSize = 1;

View file

@ -13,17 +13,12 @@ namespace nix {
class DarwinLocalStore : public LocalStore
{
public:
DarwinLocalStore(const Params & params)
: StoreConfig(params)
, LocalFSStoreConfig(params)
, LocalStoreConfig(params)
, Store(params)
, LocalFSStore(params)
, LocalStore(params)
DarwinLocalStore(LocalStoreConfig config)
: Store(config), LocalStore(config)
{
}
DarwinLocalStore(const std::string scheme, std::string path, const Params & params)
: DarwinLocalStore(params)
DarwinLocalStore(const std::string scheme, std::string path, LocalStoreConfig config)
: DarwinLocalStore(config)
{
throw UnimplementedError("DarwinLocalStore");
}

View file

@ -13,17 +13,9 @@ namespace nix {
class FallbackLocalStore : public LocalStore
{
public:
FallbackLocalStore(const Params & params)
: StoreConfig(params)
, LocalFSStoreConfig(params)
, LocalStoreConfig(params)
, Store(params)
, LocalFSStore(params)
, LocalStore(params)
{
}
FallbackLocalStore(const std::string scheme, std::string path, const Params & params)
: FallbackLocalStore(params)
FallbackLocalStore(LocalStoreConfig config) : Store(config), LocalStore(config) {}
FallbackLocalStore(const std::string scheme, std::string path, LocalStoreConfig config)
: FallbackLocalStore(config)
{
throw UnimplementedError("FallbackLocalStore");
}

View file

@ -62,7 +62,7 @@ void FreeBSDLocalStore::findPlatformRoots(UncheckedRoots & unchecked)
{
readSysctlRoots("kern.module_path", unchecked);
auto storePathRegex = regex::storePathRegex(storeDir);
auto storePathRegex = regex::storePathRegex(config().storeDir);
auto ps = std::unique_ptr<struct procstat, ProcstatDeleter>(procstat_open_sysctl());
if (!ps) {

View file

@ -13,17 +13,9 @@ namespace nix {
class FreeBSDLocalStore : public LocalStore
{
public:
FreeBSDLocalStore(const Params & params)
: StoreConfig(params)
, LocalFSStoreConfig(params)
, LocalStoreConfig(params)
, Store(params)
, LocalFSStore(params)
, LocalStore(params)
{
}
FreeBSDLocalStore(const std::string scheme, std::string path, const Params & params)
: FreeBSDLocalStore(params)
FreeBSDLocalStore(LocalStoreConfig config) : Store(config), LocalStore(config) {}
FreeBSDLocalStore(const std::string scheme, std::string path, LocalStoreConfig config)
: FreeBSDLocalStore(config)
{
throw UnimplementedError("FreeBSDLocalStore");
}

View file

@ -67,7 +67,7 @@ void LinuxLocalStore::findPlatformRoots(UncheckedRoots & unchecked)
struct dirent * ent;
auto digitsRegex = std::regex(R"(^\d+$)");
auto mapRegex = std::regex(R"(^\s*\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+(/\S+)\s*$)");
auto storePathRegex = regex::storePathRegex(storeDir);
auto storePathRegex = regex::storePathRegex(config().storeDir);
while (errno = 0, ent = readdir(procDir.get())) {
checkInterrupt();
if (std::regex_match(ent->d_name, digitsRegex)) {
@ -797,7 +797,7 @@ void LinuxLocalDerivationGoal::prepareSandbox()
can be bind-mounted). !!! As an extra security
precaution, make the fake Nix store only writable by the
build user. */
Path chrootStoreDir = chrootRootDir + worker.store.storeDir;
Path chrootStoreDir = chrootRootDir + worker.store.config().storeDir;
createDirs(chrootStoreDir);
chmodPath(chrootStoreDir, 01775);

View file

@ -13,17 +13,9 @@ namespace nix {
class LinuxLocalStore : public LocalStore
{
public:
LinuxLocalStore(const Params & params)
: StoreConfig(params)
, LocalFSStoreConfig(params)
, LocalStoreConfig(params)
, Store(params)
, LocalFSStore(params)
, LocalStore(params)
{
}
LinuxLocalStore(const std::string scheme, std::string path, const Params & params)
: LinuxLocalStore(params)
LinuxLocalStore(LocalStoreConfig config) : Store(config), LocalStore(config) {}
LinuxLocalStore(const std::string scheme, std::string path, LocalStoreConfig config)
: LinuxLocalStore(config)
{
throw UnimplementedError("LinuxLocalStore");
}

View file

@ -24,11 +24,10 @@
namespace nix {
/* TODO: Separate these store impls into different files, give them better names */
RemoteStore::RemoteStore(const Params & params)
: RemoteStoreConfig(params)
, Store(params)
RemoteStore::RemoteStore(const RemoteStoreConfig & config)
: Store(config)
, connections(make_ref<Pool<Connection>>(
std::max(1, (int) maxConnections),
std::max(1, (int) config.maxConnections),
[this]() {
auto conn = openConnectionWrapper();
try {
@ -44,7 +43,7 @@ RemoteStore::RemoteStore(const Params & params)
r->to.good()
&& r->from.good()
&& std::chrono::duration_cast<std::chrono::seconds>(
std::chrono::steady_clock::now() - r->startTime).count() < maxConnectionAge;
std::chrono::steady_clock::now() - r->startTime).count() < this->config().maxConnectionAge;
}
))
{

View file

@ -35,14 +35,16 @@ struct RemoteStoreConfig : virtual StoreConfig
* \todo RemoteStore is a misnomer - should be something like
* DaemonStore.
*/
class RemoteStore : public virtual RemoteStoreConfig,
public virtual Store,
class RemoteStore : public virtual Store,
public virtual GcStore,
public virtual LogStore
{
public:
RemoteStore(const Params & params);
RemoteStore(const RemoteStoreConfig & config);
RemoteStoreConfig & config() override = 0;
const RemoteStoreConfig & config() const override = 0;
/* Implementations of abstract store API methods. */

View file

@ -184,11 +184,6 @@ S3Helper::FileTransferResult S3Helper::getObject(
return res;
}
S3BinaryCacheStore::S3BinaryCacheStore(const Params & params)
: BinaryCacheStoreConfig(params)
, BinaryCacheStore(params)
{ }
struct S3BinaryCacheStoreConfig : virtual BinaryCacheStoreConfig
{
using BinaryCacheStoreConfig::BinaryCacheStoreConfig;
@ -260,8 +255,13 @@ struct S3BinaryCacheStoreConfig : virtual BinaryCacheStoreConfig
}
};
struct S3BinaryCacheStoreImpl : virtual S3BinaryCacheStoreConfig, public virtual S3BinaryCacheStore
struct S3BinaryCacheStoreImpl : public S3BinaryCacheStore
{
S3BinaryCacheStoreConfig config_;
S3BinaryCacheStoreConfig & config() override { return config_; }
const S3BinaryCacheStoreConfig & config() const override { return config_; }
std::string bucketName;
Stats stats;
@ -271,15 +271,13 @@ struct S3BinaryCacheStoreImpl : virtual S3BinaryCacheStoreConfig, public virtual
S3BinaryCacheStoreImpl(
const std::string & uriScheme,
const std::string & bucketName,
const Params & params)
: StoreConfig(params)
, BinaryCacheStoreConfig(params)
, S3BinaryCacheStoreConfig(params)
, Store(params)
, BinaryCacheStore(params)
, S3BinaryCacheStore(params)
S3BinaryCacheStoreConfig config)
: Store(config)
, BinaryCacheStore(config)
, S3BinaryCacheStore(config)
, config_(std::move(config))
, bucketName(bucketName)
, s3Helper(profile, region, scheme, endpoint)
, s3Helper(config_.profile, config_.region, config_.scheme, config_.endpoint)
{
diskCache = getNarInfoDiskCache();
}
@ -292,11 +290,13 @@ struct S3BinaryCacheStoreImpl : virtual S3BinaryCacheStoreConfig, public virtual
void init() override
{
if (auto cacheInfo = diskCache->upToDateCacheExists(getUri())) {
wantMassQuery.setDefault(cacheInfo->wantMassQuery);
priority.setDefault(cacheInfo->priority);
config().wantMassQuery.setDefault(cacheInfo->wantMassQuery);
config().priority.setDefault(cacheInfo->priority);
} else {
BinaryCacheStore::init();
diskCache->createCache(getUri(), storeDir, wantMassQuery, priority);
diskCache->createCache(
getUri(), config().storeDir, config().wantMassQuery, config().priority
);
}
}
@ -360,11 +360,11 @@ struct S3BinaryCacheStoreImpl : virtual S3BinaryCacheStoreConfig, public virtual
std::call_once(transferManagerCreated, [&]()
{
if (multipartUpload) {
if (config().multipartUpload) {
TransferManagerConfiguration transferConfig(executor.get());
transferConfig.s3Client = s3Helper.client;
transferConfig.bufferSize = bufferSize;
transferConfig.bufferSize = config().bufferSize;
transferConfig.uploadProgressCallback =
[](const TransferManager *transferManager,
@ -448,12 +448,14 @@ struct S3BinaryCacheStoreImpl : virtual S3BinaryCacheStoreConfig, public virtual
return std::make_shared<std::stringstream>(std::move(compressed));
};
if (narinfoCompression != "" && path.ends_with(".narinfo"))
uploadFile(path, compress(narinfoCompression), mimeType, narinfoCompression);
else if (lsCompression != "" && path.ends_with(".ls"))
uploadFile(path, compress(lsCompression), mimeType, lsCompression);
else if (logCompression != "" && path.starts_with("log/"))
uploadFile(path, compress(logCompression), mimeType, logCompression);
if (config().narinfoCompression != "" && path.ends_with(".narinfo")) {
uploadFile(
path, compress(config().narinfoCompression), mimeType, config().narinfoCompression
);
} else if (config().lsCompression != "" && path.ends_with(".ls")) {
uploadFile(path, compress(config().lsCompression), mimeType, config().lsCompression);
} else if (config().logCompression != "" && path.starts_with("log/"))
uploadFile(path, compress(config().logCompression), mimeType, config().logCompression);
else
uploadFile(path, istream, mimeType, "");
}
@ -504,7 +506,9 @@ struct S3BinaryCacheStoreImpl : virtual S3BinaryCacheStoreConfig, public virtual
for (auto object : contents) {
auto & key = object.GetKey();
if (key.size() != 40 || !key.ends_with(".narinfo")) continue;
paths.insert(parseStorePath(storeDir + "/" + key.substr(0, key.size() - 8) + "-" + MissingName));
paths.insert(parseStorePath(
config().storeDir + "/" + key.substr(0, key.size() - 8) + "-" + MissingName
));
}
marker = res.GetNextMarker();

View file

@ -11,7 +11,7 @@ class S3BinaryCacheStore : public virtual BinaryCacheStore
{
protected:
S3BinaryCacheStore(const Params & params);
using BinaryCacheStore::BinaryCacheStore;
public:

View file

@ -27,27 +27,29 @@ struct SSHStoreConfig : virtual RemoteStoreConfig, virtual CommonSSHStoreConfig
}
};
class SSHStore : public virtual SSHStoreConfig, public virtual RemoteStore
class SSHStore : public virtual RemoteStore
{
SSHStoreConfig config_;
public:
SSHStore(const std::string & scheme, const std::string & host, const Params & params)
: StoreConfig(params)
, RemoteStoreConfig(params)
, CommonSSHStoreConfig(params)
, SSHStoreConfig(params)
, Store(params)
, RemoteStore(params)
SSHStore(const std::string & scheme, const std::string & host, SSHStoreConfig config)
: Store(config)
, RemoteStore(config)
, config_(std::move(config))
, host(host)
, master(
host,
sshKey,
sshPublicHostKey,
config_.sshKey,
config_.sshPublicHostKey,
// Use SSH master only if using more than 1 connection.
connections->capacity() > 1,
compress)
config_.compress)
{
}
SSHStoreConfig & config() override { return config_; }
const SSHStoreConfig & config() const override { return config_; }
static std::set<std::string> uriSchemes() { return {"ssh-ng"}; }
std::string getUri() override
@ -92,9 +94,9 @@ ref<RemoteStore::Connection> SSHStore::openConnection()
{
auto conn = make_ref<Connection>();
std::string command = remoteProgram + " --stdio";
if (remoteStore.get() != "")
command += " --store " + shellEscape(remoteStore.get());
std::string command = config_.remoteProgram + " --stdio";
if (config_.remoteStore.get() != "")
command += " --store " + shellEscape(config_.remoteStore.get());
conn->sshConn = master.startCommand(command);
conn->to = FdSink(conn->sshConn->in.get());

View file

@ -32,7 +32,7 @@ BuildMode buildModeFromInteger(int raw) {
bool Store::isInStore(PathView path) const
{
return isInDir(path, storeDir);
return isInDir(path, config().storeDir);
}
@ -40,7 +40,7 @@ std::pair<StorePath, Path> Store::toStorePath(PathView path) const
{
if (!isInStore(path))
throw Error("path '%1%' is not in the Nix store", path);
auto slash = path.find('/', storeDir.size() + 1);
auto slash = path.find('/', config().storeDir.size() + 1);
if (slash == Path::npos)
return {parseStorePath(path), ""};
else
@ -155,7 +155,7 @@ StorePath Store::makeStorePath(std::string_view type,
{
/* e.g., "source:sha256:1abc...:/nix/store:foo.tar.gz" */
auto s = std::string(type) + ":" + std::string(hash)
+ ":" + storeDir + ":" + std::string(name);
+ ":" + config().storeDir + ":" + std::string(name);
auto h = compressHash(hashString(HashType::SHA256, s), 20);
return StorePath(h, name);
}
@ -524,9 +524,7 @@ StringSet StoreConfig::getDefaultSystemFeatures()
return res;
}
Store::Store(const Params & params)
: StoreConfig(params)
, state({(size_t) pathInfoCacheSize})
Store::Store(const StoreConfig & config) : state({(size_t) config.pathInfoCacheSize})
{
assertLibStoreInitialized();
}
@ -622,18 +620,21 @@ void Store::querySubstitutablePathInfos(const StorePathCAMap & paths, Substituta
subPath = makeFixedOutputPathFromCA(
path.first.name(),
ContentAddressWithReferences::withoutRefs(*path.second));
if (sub->storeDir == storeDir)
if (sub->config().storeDir == config().storeDir)
assert(subPath == path.first);
if (subPath != path.first)
debug("replaced path '%s' with '%s' for substituter '%s'", printStorePath(path.first), sub->printStorePath(subPath), sub->getUri());
} else if (sub->storeDir != storeDir) continue;
} else if (sub->config().storeDir != config().storeDir) continue;
debug("checking substituter '%s' for path '%s'", sub->getUri(), sub->printStorePath(subPath));
try {
auto info = sub->queryPathInfo(subPath);
if (sub->storeDir != storeDir && !(info->isContentAddressed(*sub) && info->references.empty()))
if (sub->config().storeDir != config().storeDir
&& !(info->isContentAddressed(*sub) && info->references.empty()))
{
continue;
}
auto narInfo = std::dynamic_pointer_cast<const NarInfo>(
std::shared_ptr<const ValidPathInfo>(info));
@ -1090,7 +1091,7 @@ void copyStorePath(
info2->path = dstStore.makeFixedOutputPathFromCA(
info->path.name(),
info->contentAddressWithReferences().value());
if (dstStore.storeDir == srcStore.storeDir)
if (dstStore.config().storeDir == srcStore.config().storeDir)
assert(info->path == info2->path);
info = info2;
}
@ -1205,7 +1206,7 @@ std::map<StorePath, StorePath> copyPaths(
storePathForDst = dstStore.makeFixedOutputPathFromCA(
currentPathInfo.path.name(),
currentPathInfo.contentAddressWithReferences().value());
if (dstStore.storeDir == srcStore.storeDir)
if (dstStore.config().storeDir == srcStore.config().storeDir)
assert(storePathForDst == storePathForSrc);
if (storePathForDst != storePathForSrc)
debug("replaced path '%s' to '%s' for substituter '%s'",
@ -1402,10 +1403,10 @@ Derivation Store::readInvalidDerivation(const StorePath & drvPath)
namespace nix {
/* Split URI into protocol+hierarchy part and its parameter set. */
std::pair<std::string, Store::Params> splitUriAndParams(const std::string & uri_)
std::pair<std::string, StoreConfig::Params> splitUriAndParams(const std::string & uri_)
{
auto uri(uri_);
Store::Params params;
StoreConfig::Params params;
auto q = uri.find('?');
if (q != std::string::npos) {
params = decodeQuery(uri.substr(q + 1));
@ -1424,7 +1425,7 @@ static bool isNonUriPath(const std::string & spec)
&& spec.find("/") != std::string::npos;
}
std::shared_ptr<Store> openFromNonUri(const std::string & uri, const Store::Params & params)
std::shared_ptr<Store> openFromNonUri(const std::string & uri, const StoreConfig::Params & params)
{
if (uri == "" || uri == "auto") {
auto stateDir = getOr(params, "state", settings.nixStateDir);
@ -1452,7 +1453,7 @@ std::shared_ptr<Store> openFromNonUri(const std::string & uri, const Store::Para
warn("'%s' does not exist, so Lix will use '%s' as a chroot store", stateDir, chrootStore);
} else
debug("'%s' does not exist, so Lix will use '%s' as a chroot store", stateDir, chrootStore);
Store::Params chrootStoreParams;
StoreConfig::Params chrootStoreParams;
chrootStoreParams["root"] = chrootStore;
// FIXME? this ignores *all* store parameters passed to this function?
return LocalStore::makeLocalStore(chrootStoreParams);
@ -1465,7 +1466,7 @@ std::shared_ptr<Store> openFromNonUri(const std::string & uri, const Store::Para
} else if (uri == "local") {
return LocalStore::makeLocalStore(params);
} else if (isNonUriPath(uri)) {
Store::Params params2 = params;
StoreConfig::Params params2 = params;
params2["root"] = absPath(uri);
return LocalStore::makeLocalStore(params2);
} else {
@ -1502,7 +1503,7 @@ static std::string extractConnStr(const std::string &proto, const std::string &c
}
ref<Store> openStore(const std::string & uri_,
const Store::Params & extraParams)
const StoreConfig::Params & extraParams)
{
auto params = extraParams;
try {
@ -1518,9 +1519,9 @@ ref<Store> openStore(const std::string & uri_,
if (implem.uriSchemes.count(parsedUri.scheme)) {
auto store = implem.create(parsedUri.scheme, baseURI, params);
if (store) {
experimentalFeatureSettings.require(store->experimentalFeature());
experimentalFeatureSettings.require(store->config().experimentalFeature());
store->init();
store->warnUnknownSettings();
store->config().warnUnknownSettings();
return ref<Store>(store);
}
}
@ -1531,7 +1532,7 @@ ref<Store> openStore(const std::string & uri_,
params.insert(uriParams.begin(), uriParams.end());
if (auto store = openFromNonUri(uri, params)) {
store->warnUnknownSettings();
store->config().warnUnknownSettings();
return ref<Store>(store);
}
}
@ -1559,7 +1560,7 @@ std::list<ref<Store>> getDefaultSubstituters()
addStore(uri);
stores.sort([](ref<Store> & a, ref<Store> & b) {
return a->priority < b->priority;
return a->config().priority < b->config().priority;
});
return stores;

View file

@ -43,11 +43,11 @@ namespace nix {
* of it) and inherit the constructors of `StoreConfig`
* (`using StoreConfig::StoreConfig`).
*
* 2. A class `Foo : virtual Store, virtual FooConfig` that contains the
* 2. A class `Foo : virtual Store` that contains the
* implementation of the store.
*
* This class is expected to have a constructor `Foo(const Params & params)`
* that calls `StoreConfig(params)` (otherwise you're gonna encounter an
* This class is expected to have a constructor `Foo(FooConfig config)`
* that calls `StoreConfig(config)` (otherwise you're gonna encounter an
* `assertion failure` when trying to instantiate it).
*
* You can then register the new store by defining a registration function
@ -181,7 +181,7 @@ struct StoreConfig : public Config
false};
};
class Store : public std::enable_shared_from_this<Store>, public virtual StoreConfig
class Store : public std::enable_shared_from_this<Store>
{
protected:
@ -221,7 +221,7 @@ protected:
std::shared_ptr<NarInfoDiskCache> diskCache;
Store(const Params & params);
Store(const StoreConfig & config);
public:
/**
@ -230,6 +230,9 @@ public:
*/
virtual void init() {};
virtual StoreConfig & config() = 0;
virtual const StoreConfig & config() const = 0;
virtual ~Store() noexcept(false) { }
virtual std::string getUri() = 0;
@ -986,7 +989,7 @@ OutputPathMap resolveDerivedPath(Store &, const DerivedPath::Built &, Store * ev
* ?key=value&key=value&... to the URI.
*/
ref<Store> openStore(const std::string & uri = settings.storeUri.get(),
const Store::Params & extraParams = Store::Params());
const StoreConfig::Params & extraParams = {});
/**
@ -998,7 +1001,13 @@ std::list<ref<Store>> getDefaultSubstituters();
struct StoreFactory
{
std::set<std::string> uriSchemes;
std::function<std::shared_ptr<Store> (const std::string & scheme, const std::string & uri, const Store::Params & params)> create;
std::function<
std::shared_ptr<Store> (
const std::string & scheme,
const std::string & uri,
const StoreConfig::Params & params
)
> create;
std::function<std::shared_ptr<StoreConfig> ()> getConfig;
};
@ -1013,7 +1022,7 @@ struct StoreImplementations
StoreFactory factory{
.uriSchemes = T::uriSchemes(),
.create =
([](const std::string & scheme, const std::string & uri, const Store::Params & params)
([](const std::string & scheme, const std::string & uri, const StoreConfig::Params & params)
-> std::shared_ptr<Store>
{ return std::make_shared<T>(scheme, uri, params); }),
.getConfig =
@ -1041,7 +1050,7 @@ std::optional<ValidPathInfo> decodeValidPathInfo(
/**
* Split URI into protocol+hierarchy part and its parameter set.
*/
std::pair<std::string, Store::Params> splitUriAndParams(const std::string & uri);
std::pair<std::string, StoreConfig::Params> splitUriAndParams(const std::string & uri);
const ContentAddress * getDerivationCA(const BasicDerivation & drv);

View file

@ -22,15 +22,10 @@ std::string UDSRemoteStoreConfig::doc()
;
}
UDSRemoteStore::UDSRemoteStore(const Params & params)
: StoreConfig(params)
, LocalFSStoreConfig(params)
, RemoteStoreConfig(params)
, UDSRemoteStoreConfig(params)
, Store(params)
, LocalFSStore(params)
, RemoteStore(params)
UDSRemoteStore::UDSRemoteStore(UDSRemoteStoreConfig config)
: Store(config)
, RemoteStore(config)
, config_(std::move(config))
{
}
@ -38,8 +33,8 @@ UDSRemoteStore::UDSRemoteStore(const Params & params)
UDSRemoteStore::UDSRemoteStore(
const std::string scheme,
std::string socket_path,
const Params & params)
: UDSRemoteStore(params)
UDSRemoteStoreConfig config)
: UDSRemoteStore(std::move(config))
{
path.emplace(socket_path);
}

View file

@ -21,14 +21,18 @@ struct UDSRemoteStoreConfig : virtual LocalFSStoreConfig, virtual RemoteStoreCon
std::string doc() override;
};
class UDSRemoteStore : public virtual UDSRemoteStoreConfig
, public virtual IndirectRootStore
class UDSRemoteStore : public virtual IndirectRootStore
, public virtual RemoteStore
{
UDSRemoteStoreConfig config_;
public:
UDSRemoteStore(const Params & params);
UDSRemoteStore(const std::string scheme, std::string path, const Params & params);
UDSRemoteStore(UDSRemoteStoreConfig config);
UDSRemoteStore(const std::string scheme, std::string path, UDSRemoteStoreConfig config);
UDSRemoteStoreConfig & config() override { return config_; }
const UDSRemoteStoreConfig & config() const override { return config_; }
std::string getUri() override;

View file

@ -204,7 +204,7 @@ static PeerInfo getPeerInfo(int remote)
*/
static ref<Store> openUncachedStore()
{
Store::Params params; // FIXME: get params from somewhere
StoreConfig::Params params; // FIXME: get params from somewhere
// Disable caching since the client already does that.
params["path-info-cache-size"] = "0";
return openStore(settings.storeUri, params);

View file

@ -48,8 +48,14 @@ void runProgramInStore(ref<Store> store,
if (!store2)
throw Error("store '%s' is not a local store so it does not support command execution", store->getUri());
if (store->storeDir != store2->getRealStoreDir()) {
Strings helperArgs = { chrootHelperName, store->storeDir, store2->getRealStoreDir(), std::string(system.value_or("")), program };
if (store->config().storeDir != store2->getRealStoreDir()) {
Strings helperArgs = {
chrootHelperName,
store->config().storeDir,
store2->getRealStoreDir(),
std::string(system.value_or("")),
program
};
for (auto & arg : args) helperArgs.push_back(arg);
execv(getSelfExe().value_or("nix").c_str(), stringsToCharPtrs(helperArgs).data());

View file

@ -142,7 +142,7 @@ RC_GTEST_FIXTURE_PROP(
auto name = *nameFuzzer;
std::string path = store->storeDir + "/575s52sh487i0ylmbs9pvi606ljdszr0-" + name;
std::string path = store->config().storeDir + "/575s52sh487i0ylmbs9pvi606ljdszr0-" + name;
bool parsed = false;
try {
store->parseStorePath(path);