lix/src/libstore/build/derivation-goal.hh

229 lines
6.3 KiB
C++
Raw Normal View History

2020-10-11 16:17:24 +00:00
#pragma once
#include "parsed-derivations.hh"
#include "lock.hh"
#include "store-api.hh"
#include "pathlocks.hh"
2020-10-12 17:15:32 +00:00
#include "goal.hh"
namespace nix {
using std::map;
2012-07-27 13:59:18 +00:00
2014-01-21 17:29:55 +00:00
struct HookInstance;
typedef enum {rpAccept, rpDecline, rpPostpone} HookReply;
/* Unless we are repairing, we don't both to test validity and just assume it,
so the choices are `Absent` or `Valid`. */
enum struct PathStatus {
Corrupt,
Absent,
Valid,
};
struct InitialOutputStatus {
2020-08-07 19:09:26 +00:00
StorePath path;
PathStatus status;
2020-08-07 19:09:26 +00:00
/* Valid in the store, and additionally non-corrupt if we are repairing */
bool isValid() const {
return status == PathStatus::Valid;
}
/* Merely present, allowed to be corrupt */
bool isPresent() const {
return status == PathStatus::Corrupt
|| status == PathStatus::Valid;
2020-08-07 19:09:26 +00:00
}
};
struct InitialOutput {
2020-08-07 19:09:26 +00:00
bool wanted;
Hash outputHash;
std::optional<InitialOutputStatus> known;
2020-08-07 19:09:26 +00:00
};
struct DerivationGoal : public Goal
{
/* Whether to use an on-disk .drv file. */
bool useDerivation;
2005-01-20 16:01:07 +00:00
/* The path of the derivation. */
StorePath drvPath;
/* The goal for the corresponding resolved derivation */
std::shared_ptr<DerivationGoal> resolvedDrvGoal;
/* The specific outputs that we need to build. Empty means all of
them. */
StringSet wantedOutputs;
/* Whether additional wanted outputs have been added. */
bool needRestart = false;
/* Whether to retry substituting the outputs after building the
inputs. */
bool retrySubstitution;
2005-01-20 16:01:07 +00:00
/* The derivation stored at drvPath. */
std::unique_ptr<Derivation> drv;
2012-07-27 13:59:18 +00:00
std::unique_ptr<ParsedDerivation> parsedDrv;
/* The remainder is state held during the build. */
2020-08-07 19:09:26 +00:00
/* Locks on (fixed) output paths. */
PathLocks outputLocks;
/* All input paths (that is, the union of FS closures of the
immediate input paths). */
StorePathSet inputPaths;
std::map<std::string, InitialOutput> initialOutputs;
/* File descriptor for the log file. */
2012-07-17 13:40:12 +00:00
AutoCloseFD fdLogFile;
2016-05-04 13:46:25 +00:00
std::shared_ptr<BufferedSink> logFileSink, logSink;
/* Number of bytes received from the builder's stdout/stderr. */
unsigned long logSize;
/* The most recent log lines. */
std::list<std::string> logTail;
std::string currentLogLine;
2016-04-28 12:27:00 +00:00
size_t currentLogLinePos = 0; // to handle carriage return
std::string currentHookLine;
/* The build hook. */
2017-01-19 14:15:09 +00:00
std::unique_ptr<HookInstance> hook;
2012-07-27 13:59:18 +00:00
/* The sort of derivation we are building. */
DerivationType derivationType;
2012-07-27 13:59:18 +00:00
typedef void (DerivationGoal::*GoalState)();
GoalState state;
2012-07-27 13:59:18 +00:00
2014-02-17 22:04:52 +00:00
BuildMode buildMode;
/* The current round, if we're building multiple times. */
2018-05-02 11:56:34 +00:00
size_t curRound = 1;
2018-05-02 11:56:34 +00:00
size_t nrRounds;
2017-08-15 13:31:59 +00:00
std::unique_ptr<MaintainCount<uint64_t>> mcExpectedBuilds, mcRunningBuilds;
std::unique_ptr<Activity> act;
/* Activity that denotes waiting for a lock. */
std::unique_ptr<Activity> actLock;
std::map<ActivityId, Activity> builderActivities;
/* The remote machine on which we're building. */
std::string machineName;
DerivationGoal(const StorePath & drvPath,
const StringSet & wantedOutputs, Worker & worker,
BuildMode buildMode = bmNormal);
DerivationGoal(const StorePath & drvPath, const BasicDerivation & drv,
const StringSet & wantedOutputs, Worker & worker,
BuildMode buildMode = bmNormal);
virtual ~DerivationGoal();
2019-05-12 20:47:41 +00:00
void timedOut(Error && ex) override;
2012-07-27 13:59:18 +00:00
std::string key() override;
2015-09-17 23:22:06 +00:00
void work() override;
2004-06-19 21:45:04 +00:00
/* Add wanted outputs to an already existing derivation goal. */
void addWantedOutputs(const StringSet & outputs);
/* The states. */
void getDerivation();
void loadDerivation();
2006-12-07 23:58:36 +00:00
void haveDerivation();
2020-08-07 19:09:26 +00:00
void outputsSubstitutionTried();
void gaveUpOnSubstitution();
void closureRepaired();
void inputsRealised();
void tryToBuild();
virtual void tryLocalBuild();
void buildDone();
void resolvedFinished();
2004-06-19 21:45:04 +00:00
/* Is the build hook willing to perform the build? */
HookReply tryBuildHook();
virtual int getChildStatus();
/* Check that the derivation outputs all exist and register them
as valid. */
virtual DrvOutputs registerOutputs();
/* Open a log file and a pipe to it. */
Path openLogFile();
/* Sign the newly built realisation if the store allows it */
virtual void signRealisation(Realisation&) {}
/* Close the log file. */
void closeLogFile();
/* Close the read side of the logger pipe. */
virtual void closeReadPipes();
/* Cleanup hooks for buildDone() */
virtual void cleanupHookFinally();
virtual void cleanupPreChildKill();
virtual void cleanupPostChildKill();
virtual bool cleanupDecideWhetherDiskFull();
virtual void cleanupPostOutputsRegisteredModeCheck();
virtual void cleanupPostOutputsRegisteredModeNonCheck();
virtual bool isReadDesc(int fd);
2004-06-29 09:41:50 +00:00
/* Callback used by the worker to write to the log. */
void handleChildOutput(int fd, std::string_view data) override;
2015-09-17 23:22:06 +00:00
void handleEOF(int fd) override;
void flushLine();
2004-06-29 09:41:50 +00:00
2020-08-07 19:09:26 +00:00
/* Wrappers around the corresponding Store methods that first consult the
derivation. This is currently needed because when there is no drv file
there also is no DB entry. */
std::map<std::string, std::optional<StorePath>> queryPartialDerivationOutputMap();
OutputPathMap queryDerivationOutputMap();
2020-08-07 19:09:26 +00:00
/* Update 'initialOutputs' to determine the current status of the
outputs of the derivation. Also returns a Boolean denoting
whether all outputs are valid and non-corrupt, and a
'DrvOutputs' structure containing the valid and wanted
outputs. */
std::pair<bool, DrvOutputs> checkPathValidity();
/* Aborts if any output is not valid or corrupt, and otherwise
returns a 'DrvOutputs' structure containing the wanted
outputs. */
DrvOutputs assertPathValidity();
/* Forcibly kill the child process, if any. */
virtual void killChild();
void repairClosure();
void started();
void done(
BuildResult::Status status,
DrvOutputs builtOutputs = {},
std::optional<Error> ex = {});
StorePathSet exportReferences(const StorePathSet & storePaths);
};
MakeError(NotDeterministic, BuildError);
}