Refactoring

This commit is contained in:
Eelco Dolstra 2014-02-17 23:04:52 +01:00
parent 71adb090f0
commit dfbcb7c403
1 changed files with 36 additions and 29 deletions

View File

@ -196,6 +196,9 @@ struct Child
typedef map<pid_t, Child> Children; typedef map<pid_t, Child> Children;
enum BuildMode { bmNormal, bmRepair };
/* The worker class. */ /* The worker class. */
class Worker class Worker
{ {
@ -248,7 +251,7 @@ public:
~Worker(); ~Worker();
/* Make a goal (with caching). */ /* Make a goal (with caching). */
GoalPtr makeDerivationGoal(const Path & drvPath, const StringSet & wantedOutputs, bool repair = false); GoalPtr makeDerivationGoal(const Path & drvPath, const StringSet & wantedOutputs, BuildMode buildMode = bmNormal);
GoalPtr makeSubstitutionGoal(const Path & storePath, bool repair = false); GoalPtr makeSubstitutionGoal(const Path & storePath, bool repair = false);
/* Remove a dead goal. */ /* Remove a dead goal. */
@ -706,7 +709,8 @@ private:
/* Referenceable paths (i.e., input and output paths). */ /* Referenceable paths (i.e., input and output paths). */
PathSet allPaths; PathSet allPaths;
/* Outputs that are already valid. */ /* Outputs that are already valid. If we're repairing, these are
the outputs that are valid *and* not corrupt. */
PathSet validPaths; PathSet validPaths;
/* Outputs that are corrupt or not valid. */ /* Outputs that are corrupt or not valid. */
@ -762,9 +766,12 @@ private:
HashRewrites rewritesToTmp, rewritesFromTmp; HashRewrites rewritesToTmp, rewritesFromTmp;
PathSet redirectedOutputs; PathSet redirectedOutputs;
/* Whether we're repairing. If set, a derivation will be rebuilt BuildMode buildMode;
if its outputs are valid but corrupt or missing. */
bool repair; /* If we're repairing without a chroot, there may be outputs that
are valid but corrupt. So we redirect these outputs to
temporary paths. This contains the mapping from outputs to
temporary paths. */
map<Path, Path> redirectedBadOutputs; map<Path, Path> redirectedBadOutputs;
/* Set of inodes seen during calls to canonicalisePathMetaData() /* Set of inodes seen during calls to canonicalisePathMetaData()
@ -778,7 +785,7 @@ private:
const static int childSetupFailed = 189; const static int childSetupFailed = 189;
public: public:
DerivationGoal(const Path & drvPath, const StringSet & wantedOutputs, Worker & worker, bool repair = false); DerivationGoal(const Path & drvPath, const StringSet & wantedOutputs, Worker & worker, BuildMode buildMode = bmNormal);
~DerivationGoal(); ~DerivationGoal();
void cancel(bool timeout); void cancel(bool timeout);
@ -846,7 +853,7 @@ private:
}; };
DerivationGoal::DerivationGoal(const Path & drvPath, const StringSet & wantedOutputs, Worker & worker, bool repair) DerivationGoal::DerivationGoal(const Path & drvPath, const StringSet & wantedOutputs, Worker & worker, BuildMode buildMode)
: Goal(worker) : Goal(worker)
, wantedOutputs(wantedOutputs) , wantedOutputs(wantedOutputs)
, needRestart(false) , needRestart(false)
@ -854,7 +861,7 @@ DerivationGoal::DerivationGoal(const Path & drvPath, const StringSet & wantedOut
, fLogFile(0) , fLogFile(0)
, bzLogFile(0) , bzLogFile(0)
, useChroot(false) , useChroot(false)
, repair(repair) , buildMode(buildMode)
{ {
this->drvPath = drvPath; this->drvPath = drvPath;
state = &DerivationGoal::init; state = &DerivationGoal::init;
@ -974,10 +981,10 @@ void DerivationGoal::haveDerivation()
worker.store.addTempRoot(i->second.path); worker.store.addTempRoot(i->second.path);
/* Check what outputs paths are not already valid. */ /* Check what outputs paths are not already valid. */
PathSet invalidOutputs = checkPathValidity(false, repair); PathSet invalidOutputs = checkPathValidity(false, buildMode == bmRepair);
/* If they are all valid, then we're done. */ /* If they are all valid, then we're done. */
if (invalidOutputs.size() == 0 && !repair) { if (invalidOutputs.size() == 0 && buildMode == bmNormal) {
amDone(ecSuccess); amDone(ecSuccess);
return; return;
} }
@ -992,7 +999,7 @@ void DerivationGoal::haveDerivation()
them. */ them. */
if (settings.useSubstitutes && !willBuildLocally(drv)) if (settings.useSubstitutes && !willBuildLocally(drv))
foreach (PathSet::iterator, i, invalidOutputs) foreach (PathSet::iterator, i, invalidOutputs)
addWaitee(worker.makeSubstitutionGoal(*i, repair)); addWaitee(worker.makeSubstitutionGoal(*i, buildMode == bmRepair));
if (waitees.empty()) /* to prevent hang (no wake-up event) */ if (waitees.empty()) /* to prevent hang (no wake-up event) */
outputsSubstituted(); outputsSubstituted();
@ -1021,8 +1028,8 @@ void DerivationGoal::outputsSubstituted()
return; return;
} }
if (checkPathValidity(false, repair).size() == 0) { if (checkPathValidity(false, buildMode == bmRepair).size() == 0) {
if (repair) repairClosure(); else amDone(ecSuccess); if (buildMode == bmRepair) repairClosure(); else amDone(ecSuccess);
return; return;
} }
@ -1035,7 +1042,7 @@ void DerivationGoal::outputsSubstituted()
/* The inputs must be built before we can build this goal. */ /* The inputs must be built before we can build this goal. */
foreach (DerivationInputs::iterator, i, drv.inputDrvs) foreach (DerivationInputs::iterator, i, drv.inputDrvs)
addWaitee(worker.makeDerivationGoal(i->first, i->second, repair)); addWaitee(worker.makeDerivationGoal(i->first, i->second, buildMode == bmRepair ? bmRepair : bmNormal));
foreach (PathSet::iterator, i, drv.inputSrcs) foreach (PathSet::iterator, i, drv.inputSrcs)
addWaitee(worker.makeSubstitutionGoal(*i)); addWaitee(worker.makeSubstitutionGoal(*i));
@ -1085,7 +1092,7 @@ void DerivationGoal::repairClosure()
if (drvPath2 == "") if (drvPath2 == "")
addWaitee(worker.makeSubstitutionGoal(*i, true)); addWaitee(worker.makeSubstitutionGoal(*i, true));
else else
addWaitee(worker.makeDerivationGoal(drvPath2, PathSet(), true)); addWaitee(worker.makeDerivationGoal(drvPath2, PathSet(), bmRepair));
} }
if (waitees.empty()) { if (waitees.empty()) {
@ -1238,7 +1245,7 @@ void DerivationGoal::tryToBuild()
omitted, but that would be less efficient.) Note that since we omitted, but that would be less efficient.) Note that since we
now hold the locks on the output paths, no other process can now hold the locks on the output paths, no other process can
build this derivation, so no further checks are necessary. */ build this derivation, so no further checks are necessary. */
validPaths = checkPathValidity(true, repair); validPaths = checkPathValidity(true, buildMode == bmRepair);
if (validPaths.size() == drv.outputs.size()) { if (validPaths.size() == drv.outputs.size()) {
debug(format("skipping build of derivation `%1%', someone beat us to it") % drvPath); debug(format("skipping build of derivation `%1%', someone beat us to it") % drvPath);
outputLocks.setDeletion(true); outputLocks.setDeletion(true);
@ -1582,7 +1589,7 @@ int childEntry(void * arg)
void DerivationGoal::startBuilder() void DerivationGoal::startBuilder()
{ {
startNest(nest, lvlInfo, format(repair ? "repairing path(s) %1%" : "building path(s) %1%") % showPaths(missingPaths)); startNest(nest, lvlInfo, format(buildMode == bmRepair ? "repairing path(s) %1%" : "building path(s) %1%") % showPaths(missingPaths));
/* Right platform? */ /* Right platform? */
if (!canBuildLocally(drv.platform)) { if (!canBuildLocally(drv.platform)) {
@ -1838,10 +1845,11 @@ void DerivationGoal::startBuilder()
} }
} }
/* If we're repairing, it's possible that we're rebuilding a /* If we're repairing or checking, it's possible that we're
path that is in settings.dirsInChroot (typically the rebuilding a path that is in settings.dirsInChroot
dependencies of /bin/sh). Throw them out. */ (typically the dependencies of /bin/sh). Throw them
if (repair) out. */
if (buildMode != bmNormal)
foreach (DerivationOutputs::iterator, i, drv.outputs) foreach (DerivationOutputs::iterator, i, drv.outputs)
dirsInChroot.erase(i->second.path); dirsInChroot.erase(i->second.path);
@ -1871,7 +1879,7 @@ void DerivationGoal::startBuilder()
/* If we're repairing, then we don't want to delete the /* If we're repairing, then we don't want to delete the
corrupt outputs in advance. So rewrite them as well. */ corrupt outputs in advance. So rewrite them as well. */
if (repair) if (buildMode == bmRepair)
foreach (PathSet::iterator, i, missingPaths) foreach (PathSet::iterator, i, missingPaths)
if (worker.store.isValidPath(*i) && pathExists(*i)) if (worker.store.isValidPath(*i) && pathExists(*i))
redirectedBadOutputs[*i] = addHashRewrite(*i); redirectedBadOutputs[*i] = addHashRewrite(*i);
@ -1879,8 +1887,7 @@ void DerivationGoal::startBuilder()
/* Run the builder. */ /* Run the builder. */
printMsg(lvlChatty, format("executing builder `%1%'") % printMsg(lvlChatty, format("executing builder `%1%'") % drv.builder);
drv.builder);
/* Create the log file. */ /* Create the log file. */
Path logFile = openLogFile(); Path logFile = openLogFile();
@ -2162,7 +2169,7 @@ void DerivationGoal::registerOutputs()
if (useChroot) { if (useChroot) {
if (pathExists(chrootRootDir + path)) { if (pathExists(chrootRootDir + path)) {
/* Move output paths from the chroot to the Nix store. */ /* Move output paths from the chroot to the Nix store. */
if (repair) if (buildMode == bmRepair)
replaceValidPath(path, chrootRootDir + path); replaceValidPath(path, chrootRootDir + path);
else else
if (rename((chrootRootDir + path).c_str(), path.c_str()) == -1) if (rename((chrootRootDir + path).c_str(), path.c_str()) == -1)
@ -2170,7 +2177,7 @@ void DerivationGoal::registerOutputs()
} }
} else { } else {
Path redirected; Path redirected;
if (repair && (redirected = redirectedBadOutputs[path]) != "" && pathExists(redirected)) if (buildMode == bmRepair && (redirected = redirectedBadOutputs[path]) != "" && pathExists(redirected))
replaceValidPath(path, redirected); replaceValidPath(path, redirected);
} }
@ -2877,11 +2884,11 @@ Worker::~Worker()
} }
GoalPtr Worker::makeDerivationGoal(const Path & path, const StringSet & wantedOutputs, bool repair) GoalPtr Worker::makeDerivationGoal(const Path & path, const StringSet & wantedOutputs, BuildMode buildMode)
{ {
GoalPtr goal = derivationGoals[path].lock(); GoalPtr goal = derivationGoals[path].lock();
if (!goal) { if (!goal) {
goal = GoalPtr(new DerivationGoal(path, wantedOutputs, *this, repair)); goal = GoalPtr(new DerivationGoal(path, wantedOutputs, *this, buildMode));
derivationGoals[path] = goal; derivationGoals[path] = goal;
wakeUp(goal); wakeUp(goal);
} else } else
@ -3216,7 +3223,7 @@ void LocalStore::buildPaths(const PathSet & drvPaths, bool repair)
foreach (PathSet::const_iterator, i, drvPaths) { foreach (PathSet::const_iterator, i, drvPaths) {
DrvPathWithOutputs i2 = parseDrvPathWithOutputs(*i); DrvPathWithOutputs i2 = parseDrvPathWithOutputs(*i);
if (isDerivation(i2.first)) if (isDerivation(i2.first))
goals.insert(worker.makeDerivationGoal(i2.first, i2.second, repair)); goals.insert(worker.makeDerivationGoal(i2.first, i2.second, repair ? bmRepair : bmNormal));
else else
goals.insert(worker.makeSubstitutionGoal(*i, repair)); goals.insert(worker.makeSubstitutionGoal(*i, repair));
} }