Build derivations in a more predictable order

Derivations are now built in order of derivation name, so a package
named "aardvark" is built before "baboon".

Fixes #399.
This commit is contained in:
Eelco Dolstra 2014-11-24 16:48:04 +01:00 committed by Ludovic Courtès
parent 9f355738e1
commit 5241aec531
1 changed files with 41 additions and 7 deletions

View File

@ -84,8 +84,12 @@ class Goal;
typedef std::shared_ptr<Goal> GoalPtr; typedef std::shared_ptr<Goal> GoalPtr;
typedef std::weak_ptr<Goal> WeakGoalPtr; typedef std::weak_ptr<Goal> WeakGoalPtr;
struct CompareGoalPtrs {
bool operator() (const GoalPtr & a, const GoalPtr & b);
};
/* Set of goals. */ /* Set of goals. */
typedef set<GoalPtr> Goals; typedef set<GoalPtr, CompareGoalPtrs> Goals;
typedef list<WeakGoalPtr> WeakGoals; typedef list<WeakGoalPtr> WeakGoals;
/* A map of paths to goals (and the other way around). */ /* A map of paths to goals (and the other way around). */
@ -172,11 +176,20 @@ public:
(important!), etc. */ (important!), etc. */
virtual void cancel(bool timeout) = 0; virtual void cancel(bool timeout) = 0;
virtual string key() = 0;
protected: protected:
void amDone(ExitCode result); void amDone(ExitCode result);
}; };
bool CompareGoalPtrs::operator() (const GoalPtr & a, const GoalPtr & b) {
string s1 = a->key();
string s2 = b->key();
return s1 < s2;
}
/* A mapping used to remember for each child process to what goal it /* A mapping used to remember for each child process to what goal it
belongs, and file descriptors for receiving log data and output belongs, and file descriptors for receiving log data and output
path creation commands. */ path creation commands. */
@ -303,6 +316,7 @@ public:
void addToWeakGoals(WeakGoals & goals, GoalPtr p) void addToWeakGoals(WeakGoals & goals, GoalPtr p)
{ {
// FIXME: necessary? // FIXME: necessary?
// FIXME: O(n)
foreach (WeakGoals::iterator, i, goals) foreach (WeakGoals::iterator, i, goals)
if (i->lock() == p) return; if (i->lock() == p) return;
goals.push_back(p); goals.push_back(p);
@ -779,6 +793,15 @@ public:
void cancel(bool timeout); void cancel(bool timeout);
string key()
{
/* Ensure that derivations get built in order of their name,
i.e. a derivation named "aardvark" always comes before
"baboon". And substitution goals always happen before
derivation goals (due to "b$"). */
return "b$" + storePathToName(drvPath) + "$" + drvPath;
}
void work(); void work();
Path getDrvPath() Path getDrvPath()
@ -2614,6 +2637,13 @@ public:
void cancel(bool timeout); void cancel(bool timeout);
string key()
{
/* "a$" ensures substitution goals happen before derivation
goals. */
return "a$" + storePathToName(storePath) + "$" + storePath;
}
void work(); void work();
/* The states. */ /* The states. */
@ -3124,15 +3154,19 @@ void Worker::run(const Goals & _topGoals)
checkInterrupt(); checkInterrupt();
/* Call every wake goal. */ /* Call every wake goal (in the ordering established by
CompareGoalPtrs). */
while (!awake.empty() && !topGoals.empty()) { while (!awake.empty() && !topGoals.empty()) {
WeakGoals awake2(awake); Goals awake2;
for (auto & i : awake) {
GoalPtr goal = i.lock();
if (goal) awake2.insert(goal);
}
awake.clear(); awake.clear();
foreach (WeakGoals::iterator, i, awake2) { for (auto & goal : awake2) {
checkInterrupt(); checkInterrupt();
GoalPtr goal = i->lock(); goal->work();
if (goal) goal->work(); if (topGoals.empty()) break; // stuff may have been cancelled
if (topGoals.empty()) break;
} }
} }