Deduplicate the Store downcasting with a template

This commit is contained in:
John Ericson 2022-03-09 15:27:48 +00:00
parent 678d1c2aa0
commit a03b1fd7f6
11 changed files with 39 additions and 41 deletions

View file

@ -3,6 +3,7 @@
#include "worker-protocol.hh"
#include "build-result.hh"
#include "store-api.hh"
#include "store-cast.hh"
#include "gc-store.hh"
#include "log-store.hh"
#include "path-with-outputs.hh"
@ -646,7 +647,7 @@ static void performOp(TunnelLogger * logger, ref<Store> store,
Path path = absPath(readString(from));
logger->startWork();
auto & gcStore = GcStore::require(*store);
auto & gcStore = require<GcStore>(*store);
gcStore.addIndirectRoot(path);
logger->stopWork();
@ -664,7 +665,7 @@ static void performOp(TunnelLogger * logger, ref<Store> store,
case wopFindRoots: {
logger->startWork();
auto & gcStore = GcStore::require(*store);
auto & gcStore = require<GcStore>(*store);
Roots roots = gcStore.findRoots(!trusted);
logger->stopWork();
@ -696,7 +697,7 @@ static void performOp(TunnelLogger * logger, ref<Store> store,
logger->startWork();
if (options.ignoreLiveness)
throw Error("you are not allowed to ignore liveness");
auto & gcStore = GcStore::require(*store);
auto & gcStore = require<GcStore>(*store);
gcStore.collectGarbage(options, results);
logger->stopWork();
@ -954,7 +955,7 @@ static void performOp(TunnelLogger * logger, ref<Store> store,
logger->startWork();
if (!trusted)
throw Error("you are not privileged to add logs");
auto & logStore = LogStore::require(*store);
auto & logStore = require<LogStore>(*store);
{
FramedSource source(from);
StringSink sink;

View file

@ -1,13 +0,0 @@
#include "gc-store.hh"
namespace nix {
GcStore & GcStore::require(Store & store)
{
auto * gcStore = dynamic_cast<GcStore *>(&store);
if (!gcStore)
throw UsageError("Garbage collection not supported by store '%s'", store.getUri());
return *gcStore;
}
}

View file

@ -61,6 +61,8 @@ struct GCResults
struct GcStore : public virtual Store
{
inline static std::string operationName = "Garbage collection";
/* Add an indirect root, which is merely a symlink to `path' from
/nix/var/nix/gcroots/auto/<hash of `path'>. `path' is supposed
to be a symlink to a store path. The garbage collector will
@ -77,8 +79,6 @@ struct GcStore : public virtual Store
/* Perform a garbage collection. */
virtual void collectGarbage(const GCOptions & options, GCResults & results) = 0;
static GcStore & require(Store & store);
};
}

View file

@ -1,13 +0,0 @@
#include "log-store.hh"
namespace nix {
LogStore & LogStore::require(Store & store)
{
auto * gcStore = dynamic_cast<LogStore *>(&store);
if (!gcStore)
throw UsageError("Build log storage and retrieval not supported by store '%s'", store.getUri());
return *gcStore;
}
}

View file

@ -7,6 +7,8 @@ namespace nix {
struct LogStore : public virtual Store
{
inline static std::string operationName = "Build log storage and retrieval";
/* Return the build log of the specified store path, if available,
or null otherwise. */
virtual std::optional<std::string> getBuildLog(const StorePath & path) = 0;

View file

@ -0,0 +1,16 @@
#pragma once
#include "store-api.hh"
namespace nix {
template<typename T>
T & require(Store & store)
{
auto * castedStore = dynamic_cast<T *>(&store);
if (!castedStore)
throw UsageError("%s not supported by store '%s'", T::operationName, store.getUri());
return *castedStore;
}
}

View file

@ -1,4 +1,5 @@
#include "store-api.hh"
#include "store-cast.hh"
#include "gc-store.hh"
#include "profiles.hh"
#include "shared.hh"
@ -81,7 +82,7 @@ static int main_nix_collect_garbage(int argc, char * * argv)
// Run the actual garbage collector.
if (!dryRun) {
auto store = openStore();
auto & gcStore = GcStore::require(*store);
auto & gcStore = require<GcStore>(*store);
options.action = GCOptions::gcDeleteDead;
GCResults results;
PrintFreed freed(true, results);

View file

@ -3,6 +3,7 @@
#include "dotgraph.hh"
#include "globals.hh"
#include "build-result.hh"
#include "store-cast.hh"
#include "gc-store.hh"
#include "log-store.hh"
#include "local-store.hh"
@ -430,7 +431,7 @@ static void opQuery(Strings opFlags, Strings opArgs)
store->computeFSClosure(
args, referrers, true, settings.gcKeepOutputs, settings.gcKeepDerivations);
auto & gcStore = GcStore::require(*store);
auto & gcStore = require<GcStore>(*store);
Roots roots = gcStore.findRoots(false);
for (auto & [target, links] : roots)
if (referrers.find(target) != referrers.end())
@ -475,7 +476,7 @@ static void opReadLog(Strings opFlags, Strings opArgs)
{
if (!opFlags.empty()) throw UsageError("unknown flag");
auto & logStore = LogStore::require(*store);
auto & logStore = require<LogStore>(*store);
RunPager pager;
@ -593,7 +594,7 @@ static void opGC(Strings opFlags, Strings opArgs)
if (!opArgs.empty()) throw UsageError("no arguments expected");
auto & gcStore = GcStore::require(*store);
auto & gcStore = require<GcStore>(*store);
if (printRoots) {
Roots roots = gcStore.findRoots(false);
@ -632,7 +633,7 @@ static void opDelete(Strings opFlags, Strings opArgs)
for (auto & i : opArgs)
options.pathsToDelete.insert(store->followLinksToStorePath(i));
auto & gcStore = GcStore::require(*store);
auto & gcStore = require<GcStore>(*store);
GCResults results;
PrintFreed freed(true, results);

View file

@ -1,6 +1,7 @@
#include "command.hh"
#include "shared.hh"
#include "store-api.hh"
#include "store-cast.hh"
#include "log-store.hh"
#include "sync.hh"
#include "thread-pool.hh"
@ -27,10 +28,10 @@ struct CmdCopyLog : virtual CopyCommand, virtual InstallablesCommand
void run(ref<Store> srcStore) override
{
auto & srcLogStore = LogStore::require(*srcStore);
auto & srcLogStore = require<LogStore>(*srcStore);
auto dstStore = getDstStore();
auto & dstLogStore = LogStore::require(*dstStore);
auto & dstLogStore = require<LogStore>(*dstStore);
StorePathSet drvPaths;

View file

@ -2,6 +2,7 @@
#include "common-args.hh"
#include "shared.hh"
#include "store-api.hh"
#include "store-cast.hh"
#include "gc-store.hh"
using namespace nix;
@ -33,7 +34,7 @@ struct CmdStoreDelete : StorePathsCommand
void run(ref<Store> store, std::vector<StorePath> && storePaths) override
{
auto & gcStore = GcStore::require(*store);
auto & gcStore = require<GcStore>(*store);
for (auto & path : storePaths)
options.pathsToDelete.insert(path);

View file

@ -2,6 +2,7 @@
#include "common-args.hh"
#include "shared.hh"
#include "store-api.hh"
#include "store-cast.hh"
#include "gc-store.hh"
using namespace nix;
@ -34,7 +35,7 @@ struct CmdStoreGC : StoreCommand, MixDryRun
void run(ref<Store> store) override
{
auto & gcStore = GcStore::require(*store);
auto & gcStore = require<GcStore>(*store);
options.action = dryRun ? GCOptions::gcReturnDead : GCOptions::gcDeleteDead;
GCResults results;