2023-05-08 17:20:06 +03:00
|
|
|
#include "local-overlay-store.hh"
|
2023-05-09 00:30:17 +03:00
|
|
|
#include "callback.hh"
|
2023-05-08 17:20:06 +03:00
|
|
|
|
|
|
|
namespace nix {
|
|
|
|
|
2023-05-09 01:50:16 +03:00
|
|
|
Path LocalOverlayStoreConfig::toUpperPath(const StorePath & path) {
|
2023-05-09 17:22:38 +03:00
|
|
|
return upperLayer + "/" + path.to_string();
|
2023-05-09 01:50:16 +03:00
|
|
|
}
|
|
|
|
|
2023-05-08 17:20:06 +03:00
|
|
|
LocalOverlayStore::LocalOverlayStore(const Params & params)
|
|
|
|
: StoreConfig(params)
|
|
|
|
, LocalFSStoreConfig(params)
|
|
|
|
, LocalStoreConfig(params)
|
|
|
|
, LocalOverlayStoreConfig(params)
|
|
|
|
, Store(params)
|
|
|
|
, LocalFSStore(params)
|
|
|
|
, LocalStore(params)
|
|
|
|
, lowerStore(openStore(lowerStoreUri).dynamic_pointer_cast<LocalFSStore>())
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-05-08 23:48:55 +03:00
|
|
|
void LocalOverlayStore::registerDrvOutput(const Realisation & info)
|
|
|
|
{
|
|
|
|
// First do queryRealisation on lower layer to populate DB
|
|
|
|
auto res = lowerStore->queryRealisation(info.id);
|
|
|
|
if (res)
|
|
|
|
LocalStore::registerDrvOutput(*res);
|
|
|
|
|
|
|
|
LocalStore::registerDrvOutput(info);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-05-09 00:30:17 +03:00
|
|
|
void LocalOverlayStore::queryPathInfoUncached(const StorePath & path,
|
|
|
|
Callback<std::shared_ptr<const ValidPathInfo>> callback) noexcept
|
|
|
|
{
|
|
|
|
auto callbackPtr = std::make_shared<decltype(callback)>(std::move(callback));
|
|
|
|
|
|
|
|
LocalStore::queryPathInfoUncached(path,
|
|
|
|
{[this, path, callbackPtr](std::future<std::shared_ptr<const ValidPathInfo>> fut) {
|
|
|
|
try {
|
2023-05-09 00:37:40 +03:00
|
|
|
auto info = fut.get();
|
|
|
|
if (info)
|
|
|
|
return (*callbackPtr)(std::move(info));
|
2023-05-09 00:30:17 +03:00
|
|
|
} catch (...) {
|
2023-05-09 00:37:40 +03:00
|
|
|
return callbackPtr->rethrow();
|
2023-05-09 00:30:17 +03:00
|
|
|
}
|
2023-05-09 00:37:40 +03:00
|
|
|
// If we don't have it, check lower store
|
|
|
|
lowerStore->queryPathInfo(path,
|
|
|
|
{[path, callbackPtr](std::future<ref<const ValidPathInfo>> fut) {
|
|
|
|
try {
|
|
|
|
(*callbackPtr)(fut.get().get_ptr());
|
|
|
|
} catch (...) {
|
|
|
|
return callbackPtr->rethrow();
|
|
|
|
}
|
|
|
|
}});
|
2023-05-09 00:30:17 +03:00
|
|
|
}});
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-05-09 01:50:16 +03:00
|
|
|
void LocalOverlayStore::queryRealisationUncached(const DrvOutput & drvOutput,
|
|
|
|
Callback<std::shared_ptr<const Realisation>> callback) noexcept
|
|
|
|
{
|
|
|
|
auto callbackPtr = std::make_shared<decltype(callback)>(std::move(callback));
|
|
|
|
|
|
|
|
LocalStore::queryRealisationUncached(drvOutput,
|
|
|
|
{[this, drvOutput, callbackPtr](std::future<std::shared_ptr<const Realisation>> 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<std::shared_ptr<const Realisation>> fut) {
|
|
|
|
try {
|
|
|
|
(*callbackPtr)(fut.get());
|
|
|
|
} catch (...) {
|
|
|
|
return callbackPtr->rethrow();
|
|
|
|
}
|
|
|
|
}});
|
|
|
|
}});
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool LocalOverlayStore::isValidPathUncached(const StorePath & path)
|
|
|
|
{
|
|
|
|
auto res = LocalStore::isValidPathUncached(path);
|
|
|
|
if (res) return res;
|
2023-05-09 17:22:38 +03:00
|
|
|
res = lowerStore->isValidPath(path);
|
|
|
|
if (res) {
|
|
|
|
// Get path info from lower store so upper DB genuinely has it.
|
|
|
|
LocalStore::registerValidPath(*lowerStore->queryPathInfo(path));
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void LocalOverlayStore::registerValidPaths(const ValidPathInfos & infos)
|
|
|
|
{
|
|
|
|
// First, get any from lower store so we merge
|
|
|
|
{
|
|
|
|
StorePathSet notInUpper;
|
|
|
|
for (auto & [p, _] : infos)
|
|
|
|
if (!LocalStore::isValidPathUncached(p)) // avoid divergence
|
|
|
|
notInUpper.insert(p);
|
|
|
|
auto pathsInLower = lowerStore->queryValidPaths(notInUpper);
|
|
|
|
ValidPathInfos inLower;
|
|
|
|
for (auto & p : pathsInLower)
|
|
|
|
inLower.insert_or_assign(p, *lowerStore->queryPathInfo(p));
|
|
|
|
LocalStore::registerValidPaths(inLower);
|
|
|
|
}
|
|
|
|
// Then do original request
|
|
|
|
LocalStore::registerValidPaths(infos);
|
2023-05-09 01:50:16 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-05-08 17:20:06 +03:00
|
|
|
static RegisterStoreImplementation<LocalOverlayStore, LocalOverlayStoreConfig> regLocalOverlayStore;
|
|
|
|
|
|
|
|
}
|