#pragma once #include "lock.hh" #include "store-api.hh" #include "goal.hh" namespace nix { class Worker; struct SubstitutionGoal : public Goal { /* The store path that should be realised through a substitute. */ StorePath storePath; /* The path the substituter refers to the path as. This will be * different when the stores have different names. */ std::optional subPath; /* The remaining substituters. */ std::list> subs; /* The current substituter. */ std::shared_ptr sub; /* Whether a substituter failed. */ bool substituterFailed = false; /* Path info returned by the substituter's query info operation. */ std::shared_ptr info; /* Pipe for the substituter's standard output. */ Pipe outPipe; /* The substituter thread. */ std::thread thr; std::promise promise; /* Whether to try to repair a valid path. */ RepairFlag repair; /* Location where we're downloading the substitute. Differs from storePath when doing a repair. */ Path destPath; std::unique_ptr> maintainExpectedSubstitutions, maintainRunningSubstitutions, maintainExpectedNar, maintainExpectedDownload; typedef void (SubstitutionGoal::*GoalState)(); GoalState state; /* Content address for recomputing store path */ std::optional ca; SubstitutionGoal(const StorePath & storePath, Worker & worker, RepairFlag repair = NoRepair, std::optional ca = std::nullopt); ~SubstitutionGoal(); void timedOut(Error && ex) override { abort(); }; string key() override { /* "a$" ensures substitution goals happen before derivation goals. */ return "a$" + std::string(storePath.name()) + "$" + worker.store.printStorePath(storePath); } void work() override; /* The states. */ void init(); void tryNext(); void gotInfo(); void referencesValid(); void tryToRun(); void finished(); /* Callback used by the worker to write to the log. */ void handleChildOutput(int fd, const string & data) override; void handleEOF(int fd) override; }; }