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
parent 9e3389c337
commit b7b6e3ddec

View file

@ -84,8 +84,12 @@ class Goal;
typedef std::shared_ptr<Goal> GoalPtr;
typedef std::weak_ptr<Goal> WeakGoalPtr;
struct CompareGoalPtrs {
bool operator() (const GoalPtr & a, const GoalPtr & b);
};
/* Set of goals. */
typedef set<GoalPtr> Goals;
typedef set<GoalPtr, CompareGoalPtrs> Goals;
typedef list<WeakGoalPtr> WeakGoals;
/* A map of paths to goals (and the other way around). */
@ -172,11 +176,20 @@ public:
(important!), etc. */
virtual void cancel(bool timeout) = 0;
virtual string key() = 0;
protected:
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
belongs, and file descriptors for receiving log data and output
path creation commands. */
@ -303,6 +316,7 @@ public:
void addToWeakGoals(WeakGoals & goals, GoalPtr p)
{
// FIXME: necessary?
// FIXME: O(n)
foreach (WeakGoals::iterator, i, goals)
if (i->lock() == p) return;
goals.push_back(p);
@ -767,6 +781,15 @@ public:
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();
Path getDrvPath()
@ -2575,6 +2598,13 @@ public:
void cancel(bool timeout);
string key()
{
/* "a$" ensures substitution goals happen before derivation
goals. */
return "a$" + storePathToName(storePath) + "$" + storePath;
}
void work();
/* The states. */
@ -3085,15 +3115,19 @@ void Worker::run(const Goals & _topGoals)
checkInterrupt();
/* Call every wake goal. */
/* Call every wake goal (in the ordering established by
CompareGoalPtrs). */
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();
foreach (WeakGoals::iterator, i, awake2) {
for (auto & goal : awake2) {
checkInterrupt();
GoalPtr goal = i->lock();
if (goal) goal->work();
if (topGoals.empty()) break;
goal->work();
if (topGoals.empty()) break; // stuff may have been cancelled
}
}