aboutsummaryrefslogtreecommitdiff
path: root/src/libstore/build.cc
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2014-11-24 16:48:04 +0100
committerEelco Dolstra <eelco.dolstra@logicblox.com>2014-11-24 16:50:46 +0100
commitb7b6e3ddecae5a0463861ec6b1f400f2e37fd2a7 (patch)
tree4e87ad5068ef4568cc6dfdcfac7d613f9476948c /src/libstore/build.cc
parent9e3389c3378df026dcbf66adef8e52002c7b9d2a (diff)
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.
Diffstat (limited to 'src/libstore/build.cc')
-rw-r--r--src/libstore/build.cc48
1 files changed, 41 insertions, 7 deletions
diff --git a/src/libstore/build.cc b/src/libstore/build.cc
index 72694cfbb..539d0b21b 100644
--- a/src/libstore/build.cc
+++ b/src/libstore/build.cc
@@ -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
}
}