aboutsummaryrefslogtreecommitdiff
path: root/src/libstore
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstore')
-rw-r--r--src/libstore/build.cc46
-rw-r--r--src/libstore/derivations.cc7
-rw-r--r--src/libstore/derivations.hh2
-rw-r--r--src/libstore/download.cc11
-rw-r--r--src/libstore/download.hh3
-rw-r--r--src/libstore/http-binary-cache-store.cc3
-rw-r--r--src/libstore/local-store.cc2
7 files changed, 45 insertions, 29 deletions
diff --git a/src/libstore/build.cc b/src/libstore/build.cc
index cfab0b0dc..e0eb702a4 100644
--- a/src/libstore/build.cc
+++ b/src/libstore/build.cc
@@ -193,6 +193,7 @@ bool CompareGoalPtrs::operator() (const GoalPtr & a, const GoalPtr & b) {
struct Child
{
WeakGoalPtr goal;
+ Goal * goal2; // ugly hackery
set<int> fds;
bool respectTimeouts;
bool inBuildSlot;
@@ -284,7 +285,7 @@ public:
false if there is no sense in waking up goals that are sleeping
because they can't run yet (e.g., there is no free build slot,
or the hook would still say `postpone'). */
- void childTerminated(GoalPtr goal, bool wakeSleepers = true);
+ void childTerminated(Goal * goal, bool wakeSleepers = true);
/* Put `goal' to sleep until a build slot becomes available (which
might be right away). */
@@ -652,18 +653,15 @@ HookInstance::~HookInstance()
//////////////////////////////////////////////////////////////////////
-typedef map<string, string> HashRewrites;
+typedef map<std::string, std::string> StringRewrites;
-string rewriteHashes(string s, const HashRewrites & rewrites)
+std::string rewriteStrings(std::string s, const StringRewrites & rewrites)
{
for (auto & i : rewrites) {
- assert(i.first.size() == i.second.size());
size_t j = 0;
- while ((j = s.find(i.first, j)) != string::npos) {
- debug(format("rewriting @ %1%") % j);
- s.replace(j, i.second.size(), i.second);
- }
+ while ((j = s.find(i.first, j)) != string::npos)
+ s.replace(j, i.first.size(), i.second);
}
return s;
}
@@ -782,7 +780,7 @@ private:
#endif
/* Hash rewriting. */
- HashRewrites rewritesToTmp, rewritesFromTmp;
+ StringRewrites inputRewrites, outputRewrites;
typedef map<Path, Path> RedirectedOutputs;
RedirectedOutputs redirectedOutputs;
@@ -938,7 +936,7 @@ DerivationGoal::~DerivationGoal()
void DerivationGoal::killChild()
{
if (pid != -1) {
- worker.childTerminated(shared_from_this());
+ worker.childTerminated(this);
if (buildUser.enabled()) {
/* If we're using a build user, then there is a tricky
@@ -1412,7 +1410,7 @@ void DerivationGoal::buildDone()
debug(format("builder process for ‘%1%’ finished") % drvPath);
/* So the child is gone now. */
- worker.childTerminated(shared_from_this());
+ worker.childTerminated(this);
/* Close the read side of the logger pipe. */
if (hook) {
@@ -1774,6 +1772,10 @@ void DerivationGoal::startBuilder()
for (auto & i : varNames) env[i] = getEnv(i);
}
+ /* Substitute output placeholders with the actual output paths. */
+ for (auto & output : drv->outputs)
+ inputRewrites[hashPlaceholder(output.first)] = output.second.path;
+
/* The `exportReferencesGraph' feature allows the references graph
to be passed to a builder. This attribute should be a list of
pairs [name1 path1 name2 path2 ...]. The references graph of
@@ -2418,7 +2420,7 @@ void DerivationGoal::runChild()
/* Fill in the environment. */
Strings envStrs;
for (auto & i : env)
- envStrs.push_back(rewriteHashes(i.first + "=" + i.second, rewritesToTmp));
+ envStrs.push_back(rewriteStrings(i.first + "=" + i.second, inputRewrites));
/* If we are running in `build-users' mode, then switch to the
user we allocated above. Make sure that we drop all root
@@ -2560,7 +2562,7 @@ void DerivationGoal::runChild()
}
for (auto & i : drv->args)
- args.push_back(rewriteHashes(i, rewritesToTmp));
+ args.push_back(rewriteStrings(i, inputRewrites));
restoreSIGPIPE();
@@ -2682,7 +2684,7 @@ void DerivationGoal::registerOutputs()
/* Apply hash rewriting if necessary. */
bool rewritten = false;
- if (!rewritesFromTmp.empty()) {
+ if (!outputRewrites.empty()) {
printMsg(lvlError, format("warning: rewriting hashes in ‘%1%’; cross fingers") % path);
/* Canonicalise first. This ensures that the path we're
@@ -2694,7 +2696,7 @@ void DerivationGoal::registerOutputs()
StringSink sink;
dumpPath(actualPath, sink);
deletePath(actualPath);
- sink.s = make_ref<std::string>(rewriteHashes(*sink.s, rewritesFromTmp));
+ sink.s = make_ref<std::string>(rewriteStrings(*sink.s, outputRewrites));
StringSource source(*sink.s);
restorePath(actualPath, source);
@@ -3033,8 +3035,8 @@ Path DerivationGoal::addHashRewrite(const Path & path)
Path p = worker.store.storeDir + "/" + h2 + string(path, worker.store.storeDir.size() + 33);
deletePath(p);
assert(path.size() == p.size());
- rewritesToTmp[h1] = h2;
- rewritesFromTmp[h2] = h1;
+ inputRewrites[h1] = h2;
+ outputRewrites[h2] = h1;
redirectedOutputs[path] = p;
return p;
}
@@ -3140,8 +3142,9 @@ SubstitutionGoal::~SubstitutionGoal()
{
try {
if (thr.joinable()) {
+ // FIXME: signal worker thread to quit.
thr.join();
- //worker.childTerminated(shared_from_this()); // FIXME
+ worker.childTerminated(this);
}
} catch (...) {
ignoreException();
@@ -3296,7 +3299,7 @@ void SubstitutionGoal::finished()
trace("substitute finished");
thr.join();
- worker.childTerminated(shared_from_this());
+ worker.childTerminated(this);
try {
promise.get_future().get();
@@ -3449,6 +3452,7 @@ void Worker::childStarted(GoalPtr goal, const set<int> & fds,
{
Child child;
child.goal = goal;
+ child.goal2 = goal.get();
child.fds = fds;
child.timeStarted = child.lastOutput = time(0);
child.inBuildSlot = inBuildSlot;
@@ -3458,10 +3462,10 @@ void Worker::childStarted(GoalPtr goal, const set<int> & fds,
}
-void Worker::childTerminated(GoalPtr goal, bool wakeSleepers)
+void Worker::childTerminated(Goal * goal, bool wakeSleepers)
{
auto i = std::find_if(children.begin(), children.end(),
- [&](const Child & child) { return child.goal.lock() == goal; });
+ [&](const Child & child) { return child.goal2 == goal; });
assert(i != children.end());
if (i->inBuildSlot) {
diff --git a/src/libstore/derivations.cc b/src/libstore/derivations.cc
index 7dcf71d46..f051f10bd 100644
--- a/src/libstore/derivations.cc
+++ b/src/libstore/derivations.cc
@@ -390,4 +390,11 @@ Sink & operator << (Sink & out, const BasicDerivation & drv)
}
+std::string hashPlaceholder(const std::string & outputName)
+{
+ // FIXME: memoize?
+ return "/" + printHash32(hashString(htSHA256, "nix-output:" + outputName));
+}
+
+
}
diff --git a/src/libstore/derivations.hh b/src/libstore/derivations.hh
index 974de78c5..9717a81e4 100644
--- a/src/libstore/derivations.hh
+++ b/src/libstore/derivations.hh
@@ -117,4 +117,6 @@ struct Sink;
Source & readDerivation(Source & in, Store & store, BasicDerivation & drv);
Sink & operator << (Sink & out, const BasicDerivation & drv);
+std::string hashPlaceholder(const std::string & outputName);
+
}
diff --git a/src/libstore/download.cc b/src/libstore/download.cc
index 95c7d2255..5305a4895 100644
--- a/src/libstore/download.cc
+++ b/src/libstore/download.cc
@@ -230,7 +230,7 @@ struct CurlDownloader : public Downloader
} catch (DownloadError & e) {
attempt++;
if (e.error != Transient || attempt >= options.tries) throw;
- auto ms = 25 * (1 << (attempt - 1));
+ auto ms = options.baseRetryTimeMs * (1 << (attempt - 1));
printMsg(lvlError, format("warning: %s; retrying in %d ms") % e.what() % ms);
std::this_thread::sleep_for(std::chrono::milliseconds(ms));
}
@@ -243,13 +243,14 @@ ref<Downloader> makeDownloader()
return make_ref<CurlDownloader>();
}
-Path Downloader::downloadCached(ref<Store> store, const string & url_, bool unpack, const Hash & expectedHash)
+Path Downloader::downloadCached(ref<Store> store, const string & url_, bool unpack, string name, const Hash & expectedHash)
{
auto url = resolveUri(url_);
- string name;
- auto p = url.rfind('/');
- if (p != string::npos) name = string(url, p + 1);
+ if (name == "") {
+ auto p = url.rfind('/');
+ if (p != string::npos) name = string(url, p + 1);
+ }
Path expectedStorePath;
if (expectedHash) {
diff --git a/src/libstore/download.hh b/src/libstore/download.hh
index 1f6098759..f22e68864 100644
--- a/src/libstore/download.hh
+++ b/src/libstore/download.hh
@@ -14,6 +14,7 @@ struct DownloadOptions
enum { yes, no, automatic } showProgress = yes;
bool head = false;
size_t tries = 1;
+ unsigned int baseRetryTimeMs = 100;
};
struct DownloadResult
@@ -29,7 +30,7 @@ struct Downloader
{
virtual DownloadResult download(string url, const DownloadOptions & options) = 0;
- Path downloadCached(ref<Store> store, const string & url, bool unpack,
+ Path downloadCached(ref<Store> store, const string & url, bool unpack, string name = "",
const Hash & expectedHash = Hash());
enum Error { NotFound, Forbidden, Misc, Transient };
diff --git a/src/libstore/http-binary-cache-store.cc b/src/libstore/http-binary-cache-store.cc
index 42e9099b8..bdcd2fd39 100644
--- a/src/libstore/http-binary-cache-store.cc
+++ b/src/libstore/http-binary-cache-store.cc
@@ -80,7 +80,8 @@ protected:
auto downloader(downloaders.get());
DownloadOptions options;
options.showProgress = DownloadOptions::no;
- options.tries = 3;
+ options.tries = 5;
+ options.baseRetryTimeMs = 1000;
try {
return downloader->download(cacheUri + "/" + path, options).data;
} catch (DownloadError & e) {
diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc
index d3f0c4787..10056f2f1 100644
--- a/src/libstore/local-store.cc
+++ b/src/libstore/local-store.cc
@@ -760,7 +760,7 @@ Path LocalStore::queryPathFromHashPart(const string & hashPart)
Path prefix = storeDir + "/" + hashPart;
- return retrySQLite<Path>([&]() {
+ return retrySQLite<Path>([&]() -> std::string {
auto state(_state.lock());
auto useQueryPathFromHashPart(state->stmtQueryPathFromHashPart.use()(prefix));