1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-08 19:46:02 +01:00

Make Dummy store store derivations separately

This makes for more efficiency. Once we have JSON for the dummy store,
it will also make for better JSON, too.
This commit is contained in:
John Ericson 2025-10-13 16:00:27 -04:00
parent 2a194aa29e
commit 2d4c7d3d03
3 changed files with 93 additions and 23 deletions

View file

@ -50,8 +50,8 @@ TEST_F(WriteDerivationTest, addToStoreFromDumpCalledOnce)
EXPECT_EQ(path1, path2);
EXPECT_THAT(
[&] { writeDerivation(*store, drv, Repair); },
::testing::ThrowsMessage<Error>(testing::HasSubstrIgnoreANSIMatcher(
"operation 'addToStoreFromDump' is not supported by store 'dummy://'")));
::testing::ThrowsMessage<Error>(
testing::HasSubstrIgnoreANSIMatcher("operation 'writeDerivation' is not supported by store 'dummy://'")));
}
} // namespace nix

View file

@ -137,12 +137,35 @@ struct DummyStoreImpl : DummyStore
void queryPathInfoUncached(
const StorePath & path, Callback<std::shared_ptr<const ValidPathInfo>> callback) noexcept override
{
bool visited = contents.cvisit(path, [&](const auto & kv) {
callback(std::make_shared<ValidPathInfo>(StorePath{kv.first}, kv.second.info));
});
if (path.isDerivation()) {
if (derivations.cvisit(path, [&](const auto & kv) {
/* compute path info on demand */
auto accessor = make_ref<MemorySourceAccessor>();
accessor->root = MemorySourceAccessor::File::Regular{
.contents = kv.second.unparse(*this, false),
};
auto narHash = hashPath(
{accessor, CanonPath::root}, FileSerialisationMethod::NixArchive, HashAlgorithm::SHA256);
auto info =
std::make_shared<ValidPathInfo>(StorePath{kv.first}, UnkeyedValidPathInfo{narHash.hash});
info->narSize = narHash.numBytesDigested;
info->ca = ContentAddress{
.method = ContentAddressMethod::Raw::Text,
.hash = hashString(
HashAlgorithm::SHA256,
std::get<MemorySourceAccessor::File::Regular>(accessor->root->raw).contents),
};
callback(std::move(info));
}))
return;
} else {
if (contents.cvisit(path, [&](const auto & kv) {
callback(std::make_shared<ValidPathInfo>(StorePath{kv.first}, kv.second.info));
}))
return;
}
if (!visited)
callback(nullptr);
callback(nullptr);
}
/**
@ -169,18 +192,25 @@ struct DummyStoreImpl : DummyStore
if (checkSigs)
throw Error("checking signatures is not supported for '%s' store", config->getHumanReadableURI());
auto temp = make_ref<MemorySourceAccessor>();
MemorySink tempSink{*temp};
auto accessor = make_ref<MemorySourceAccessor>();
MemorySink tempSink{*accessor};
parseDump(tempSink, source);
auto path = info.path;
auto accessor = make_ref<MemorySourceAccessor>(std::move(*temp));
contents.insert(
{path,
PathInfoAndContents{
std::move(info),
accessor,
}});
if (info.path.isDerivation()) {
warn("back compat supporting `addToStore` for inserting derivations in dummy store");
writeDerivation(
parseDerivation(*this, accessor->readFile(CanonPath::root), Derivation::nameFromPath(info.path)));
return;
}
contents.insert({
path,
PathInfoAndContents{
std::move(info),
accessor,
},
});
wholeStoreView->addObject(path.to_string(), accessor);
}
@ -193,6 +223,9 @@ struct DummyStoreImpl : DummyStore
const StorePathSet & references = StorePathSet(),
RepairFlag repair = NoRepair) override
{
if (isDerivation(name))
throw Error("Do not insert derivation into dummy store with `addToStoreFromDump`");
if (config->readOnly)
unsupported("addToStoreFromDump");
@ -239,17 +272,47 @@ struct DummyStoreImpl : DummyStore
auto path = info.path;
auto accessor = make_ref<MemorySourceAccessor>(std::move(*temp));
contents.insert(
{path,
PathInfoAndContents{
std::move(info),
accessor,
}});
contents.insert({
path,
PathInfoAndContents{
std::move(info),
accessor,
},
});
wholeStoreView->addObject(path.to_string(), accessor);
return path;
}
StorePath writeDerivation(const Derivation & drv, RepairFlag repair = NoRepair) override
{
auto drvPath = ::nix::writeDerivation(*this, drv, repair, /*readonly=*/true);
if (!derivations.contains(drvPath) || repair) {
if (config->readOnly)
unsupported("writeDerivation");
derivations.insert({drvPath, drv});
}
return drvPath;
}
Derivation readDerivation(const StorePath & drvPath) override
{
if (std::optional res = getConcurrent(derivations, drvPath))
return *res;
else
throw Error("derivation '%s' is not valid", printStorePath(drvPath));
}
/**
* No such thing as an "invalid derivation" with the dummy store
*/
Derivation readInvalidDerivation(const StorePath & drvPath) override
{
return readDerivation(drvPath);
}
void registerDrvOutput(const Realisation & output) override
{
auto ref = make_ref<UnkeyedRealisation>(output);

View file

@ -2,6 +2,7 @@
///@file
#include "nix/store/dummy-store.hh"
#include "nix/store/derivations.hh"
#include <boost/unordered/concurrent_flat_map.hpp>
@ -25,11 +26,17 @@ struct DummyStore : virtual Store
};
/**
* This is map conceptually owns the file system objects for each
* This map conceptually owns the file system objects for each
* store object.
*/
boost::concurrent_flat_map<StorePath, PathInfoAndContents> contents;
/**
* This map conceptually owns every derivation, allowing us to
* avoid "on-disk drv format" serialization round-trips.
*/
boost::concurrent_flat_map<StorePath, Derivation> derivations;
/**
* The build trace maps the pair of a content-addressing (fixed or
* floating) derivations an one of its output to a