#pragma once #include "types.hh" #include "store-api.hh" #include "build-result.hh" namespace nix { /* Forward definition. */ struct Goal; class Worker; /* A pointer to a goal. */ typedef std::shared_ptr GoalPtr; typedef std::weak_ptr WeakGoalPtr; struct CompareGoalPtrs { bool operator() (const GoalPtr & a, const GoalPtr & b) const; }; /* Set of goals. */ typedef std::set Goals; typedef std::set> WeakGoals; /* A map of paths to goals (and the other way around). */ typedef std::map WeakGoalMap; struct Goal : public std::enable_shared_from_this { typedef enum {ecBusy, ecSuccess, ecFailed, ecNoSubstituters, ecIncompleteClosure} ExitCode; /* Backlink to the worker. */ Worker & worker; /* Goals that this goal is waiting for. */ Goals waitees; /* Goals waiting for this one to finish. Must use weak pointers here to prevent cycles. */ WeakGoals waiters; /* Number of goals we are/were waiting for that have failed. */ unsigned int nrFailed; /* Number of substitution goals we are/were waiting for that failed because there are no substituters. */ unsigned int nrNoSubstituters; /* Number of substitution goals we are/were waiting for that failed because they had unsubstitutable references. */ unsigned int nrIncompleteClosure; /* Name of this goal for debugging purposes. */ std::string name; /* Whether the goal is finished. */ ExitCode exitCode; /* Build result. */ BuildResult buildResult; /* Exception containing an error message, if any. */ std::optional ex; Goal(Worker & worker) : worker(worker) { nrFailed = nrNoSubstituters = nrIncompleteClosure = 0; exitCode = ecBusy; } virtual ~Goal() { trace("goal destroyed"); } virtual void work() = 0; void addWaitee(GoalPtr waitee); virtual void waiteeDone(GoalPtr waitee, ExitCode result); virtual void handleChildOutput(int fd, std::string_view data) { abort(); } virtual void handleEOF(int fd) { abort(); } void trace(const FormatOrString & fs); std::string getName() { return name; } /* Callback in case of a timeout. It should wake up its waiters, get rid of any running child processes that are being monitored by the worker (important!), etc. */ virtual void timedOut(Error && ex) = 0; virtual std::string key() = 0; void amDone(ExitCode result, std::optional ex = {}); virtual void cleanup() { } }; void addToWeakGoals(WeakGoals & goals, GoalPtr p); }