mirror of
https://github.com/NixOS/nix.git
synced 2025-11-09 03:56:01 +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:
parent
28b73cabcc
commit
136825b4a2
3 changed files with 107 additions and 26 deletions
|
|
@ -50,8 +50,8 @@ TEST_F(WriteDerivationTest, addToStoreFromDumpCalledOnce)
|
||||||
EXPECT_EQ(path1, path2);
|
EXPECT_EQ(path1, path2);
|
||||||
EXPECT_THAT(
|
EXPECT_THAT(
|
||||||
[&] { writeDerivation(*store, drv, Repair); },
|
[&] { writeDerivation(*store, drv, Repair); },
|
||||||
::testing::ThrowsMessage<Error>(testing::HasSubstrIgnoreANSIMatcher(
|
::testing::ThrowsMessage<Error>(
|
||||||
"operation 'addToStoreFromDump' is not supported by store 'dummy://'")));
|
testing::HasSubstrIgnoreANSIMatcher("operation 'writeDerivation' is not supported by store 'dummy://'")));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace nix
|
} // namespace nix
|
||||||
|
|
|
||||||
|
|
@ -137,12 +137,31 @@ struct DummyStoreImpl : DummyStore
|
||||||
void queryPathInfoUncached(
|
void queryPathInfoUncached(
|
||||||
const StorePath & path, Callback<std::shared_ptr<const ValidPathInfo>> callback) noexcept override
|
const StorePath & path, Callback<std::shared_ptr<const ValidPathInfo>> callback) noexcept override
|
||||||
{
|
{
|
||||||
bool visited = contents.cvisit(path, [&](const auto & kv) {
|
if (path.isDerivation()) {
|
||||||
callback(std::make_shared<ValidPathInfo>(StorePath{kv.first}, kv.second.info));
|
if (auto accessor_ = getMemoryFSAccessor(path)) {
|
||||||
});
|
ref<MemorySourceAccessor> accessor = ref{std::move(accessor_)};
|
||||||
|
/* compute path info on demand */
|
||||||
|
auto narHash =
|
||||||
|
hashPath({accessor, CanonPath::root}, FileSerialisationMethod::NixArchive, HashAlgorithm::SHA256);
|
||||||
|
auto info = std::make_shared<ValidPathInfo>(path, 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 +188,25 @@ struct DummyStoreImpl : DummyStore
|
||||||
if (checkSigs)
|
if (checkSigs)
|
||||||
throw Error("checking signatures is not supported for '%s' store", config->getHumanReadableURI());
|
throw Error("checking signatures is not supported for '%s' store", config->getHumanReadableURI());
|
||||||
|
|
||||||
auto temp = make_ref<MemorySourceAccessor>();
|
auto accessor = make_ref<MemorySourceAccessor>();
|
||||||
MemorySink tempSink{*temp};
|
MemorySink tempSink{*accessor};
|
||||||
parseDump(tempSink, source);
|
parseDump(tempSink, source);
|
||||||
auto path = info.path;
|
auto path = info.path;
|
||||||
|
|
||||||
auto accessor = make_ref<MemorySourceAccessor>(std::move(*temp));
|
if (info.path.isDerivation()) {
|
||||||
contents.insert(
|
warn("back compat supporting `addToStore` for inserting derivations in dummy store");
|
||||||
{path,
|
writeDerivation(
|
||||||
PathInfoAndContents{
|
parseDerivation(*this, accessor->readFile(CanonPath::root), Derivation::nameFromPath(info.path)));
|
||||||
std::move(info),
|
return;
|
||||||
accessor,
|
}
|
||||||
}});
|
|
||||||
|
contents.insert({
|
||||||
|
path,
|
||||||
|
PathInfoAndContents{
|
||||||
|
std::move(info),
|
||||||
|
accessor,
|
||||||
|
},
|
||||||
|
});
|
||||||
wholeStoreView->addObject(path.to_string(), accessor);
|
wholeStoreView->addObject(path.to_string(), accessor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -193,6 +219,9 @@ struct DummyStoreImpl : DummyStore
|
||||||
const StorePathSet & references = StorePathSet(),
|
const StorePathSet & references = StorePathSet(),
|
||||||
RepairFlag repair = NoRepair) override
|
RepairFlag repair = NoRepair) override
|
||||||
{
|
{
|
||||||
|
if (isDerivation(name))
|
||||||
|
throw Error("Do not insert derivation into dummy store with `addToStoreFromDump`");
|
||||||
|
|
||||||
if (config->readOnly)
|
if (config->readOnly)
|
||||||
unsupported("addToStoreFromDump");
|
unsupported("addToStoreFromDump");
|
||||||
|
|
||||||
|
|
@ -239,17 +268,47 @@ struct DummyStoreImpl : DummyStore
|
||||||
|
|
||||||
auto path = info.path;
|
auto path = info.path;
|
||||||
auto accessor = make_ref<MemorySourceAccessor>(std::move(*temp));
|
auto accessor = make_ref<MemorySourceAccessor>(std::move(*temp));
|
||||||
contents.insert(
|
contents.insert({
|
||||||
{path,
|
path,
|
||||||
PathInfoAndContents{
|
PathInfoAndContents{
|
||||||
std::move(info),
|
std::move(info),
|
||||||
accessor,
|
accessor,
|
||||||
}});
|
},
|
||||||
|
});
|
||||||
wholeStoreView->addObject(path.to_string(), accessor);
|
wholeStoreView->addObject(path.to_string(), accessor);
|
||||||
|
|
||||||
return path;
|
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
|
void registerDrvOutput(const Realisation & output) override
|
||||||
{
|
{
|
||||||
auto ref = make_ref<UnkeyedRealisation>(output);
|
auto ref = make_ref<UnkeyedRealisation>(output);
|
||||||
|
|
@ -273,13 +332,28 @@ struct DummyStoreImpl : DummyStore
|
||||||
callback(nullptr);
|
callback(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<SourceAccessor> getFSAccessor(const StorePath & path, bool requireValidPath) override
|
std::shared_ptr<MemorySourceAccessor> getMemoryFSAccessor(const StorePath & path, bool requireValidPath = true)
|
||||||
{
|
{
|
||||||
std::shared_ptr<SourceAccessor> res;
|
std::shared_ptr<MemorySourceAccessor> res;
|
||||||
contents.cvisit(path, [&](const auto & kv) { res = kv.second.contents.get_ptr(); });
|
if (path.isDerivation())
|
||||||
|
derivations.cvisit(path, [&](const auto & kv) {
|
||||||
|
/* compute path info on demand */
|
||||||
|
auto res2 = make_ref<MemorySourceAccessor>();
|
||||||
|
res2->root = MemorySourceAccessor::File::Regular{
|
||||||
|
.contents = kv.second.unparse(*this, false),
|
||||||
|
};
|
||||||
|
res = std::move(res2).get_ptr();
|
||||||
|
});
|
||||||
|
else
|
||||||
|
contents.cvisit(path, [&](const auto & kv) { res = kv.second.contents.get_ptr(); });
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<SourceAccessor> getFSAccessor(const StorePath & path, bool requireValidPath = true) override
|
||||||
|
{
|
||||||
|
return getMemoryFSAccessor(path, requireValidPath);
|
||||||
|
}
|
||||||
|
|
||||||
ref<SourceAccessor> getFSAccessor(bool requireValidPath) override
|
ref<SourceAccessor> getFSAccessor(bool requireValidPath) override
|
||||||
{
|
{
|
||||||
return wholeStoreView;
|
return wholeStoreView;
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
///@file
|
///@file
|
||||||
|
|
||||||
#include "nix/store/dummy-store.hh"
|
#include "nix/store/dummy-store.hh"
|
||||||
|
#include "nix/store/derivations.hh"
|
||||||
|
|
||||||
#include <boost/unordered/concurrent_flat_map.hpp>
|
#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.
|
* store object.
|
||||||
*/
|
*/
|
||||||
boost::concurrent_flat_map<StorePath, PathInfoAndContents> contents;
|
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
|
* The build trace maps the pair of a content-addressing (fixed or
|
||||||
* floating) derivations an one of its output to a
|
* floating) derivations an one of its output to a
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue