aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libstore/legacy-ssh-store.cc1
-rw-r--r--src/libstore/store-api.cc26
-rw-r--r--src/libutil/archive.cc2
-rw-r--r--src/libutil/logging.cc11
-rw-r--r--src/libutil/logging.hh15
-rw-r--r--src/nix/progress-bar.cc46
6 files changed, 99 insertions, 2 deletions
diff --git a/src/libstore/legacy-ssh-store.cc b/src/libstore/legacy-ssh-store.cc
index 65fe575d2..855a7c99a 100644
--- a/src/libstore/legacy-ssh-store.cc
+++ b/src/libstore/legacy-ssh-store.cc
@@ -135,7 +135,6 @@ struct LegacySSHStore : public Store
if (readInt(conn->from) != 1)
throw Error("failed to add path '%s' to remote host '%s', info.path, host");
-
}
void narFromPath(const Path & path, Sink & sink) override
diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc
index dd87a046e..88f27e806 100644
--- a/src/libstore/store-api.cc
+++ b/src/libstore/store-api.cc
@@ -565,8 +565,12 @@ void Store::buildPaths(const PathSet & paths, BuildMode buildMode)
void copyStorePath(ref<Store> srcStore, ref<Store> dstStore,
const Path & storePath, RepairFlag repair, CheckSigsFlag checkSigs)
{
+ Activity act(actCopyPath, fmt("copying path '%s'", storePath));
+
auto info = srcStore->queryPathInfo(storePath);
+ //act->progress(0, info->size());
+
StringSink sink;
srcStore->narFromPath({storePath}, sink);
@@ -600,13 +604,28 @@ void copyPaths(ref<Store> srcStore, ref<Store> dstStore, const PathSet & storePa
for (auto & path : storePaths)
if (!valid.count(path)) missing.insert(path);
+ Activity act;
+
+ logger->event(evCopyStarted, act);
+
+ std::atomic<size_t> nrCopied{0};
+ std::atomic<size_t> nrDone{storePaths.size() - missing.size()};
+
+ auto showProgress = [&]() {
+ logger->event(evCopyProgress, act, storePaths.size(), nrCopied, nrDone);
+ };
+
ThreadPool pool;
processGraph<Path>(pool,
PathSet(missing.begin(), missing.end()),
[&](const Path & storePath) {
- if (dstStore->isValidPath(storePath)) return PathSet();
+ if (dstStore->isValidPath(storePath)) {
+ nrDone++;
+ showProgress();
+ return PathSet();
+ }
return srcStore->queryPathInfo(storePath)->references;
},
@@ -616,7 +635,12 @@ void copyPaths(ref<Store> srcStore, ref<Store> dstStore, const PathSet & storePa
if (!dstStore->isValidPath(storePath)) {
printInfo("copying '%s'...", storePath);
copyStorePath(srcStore, dstStore, storePath, repair, checkSigs);
+ nrCopied++;
}
+
+ nrDone++;
+
+ showProgress();
});
}
diff --git a/src/libutil/archive.cc b/src/libutil/archive.cc
index 51b57a8f4..ea1deb924 100644
--- a/src/libutil/archive.cc
+++ b/src/libutil/archive.cc
@@ -56,6 +56,8 @@ static void dumpContents(const Path & path, size_t size,
static void dump(const Path & path, Sink & sink, PathFilter & filter)
{
+ checkInterrupt();
+
struct stat st;
if (lstat(path.c_str(), &st))
throw SysError(format("getting attributes of path '%1%'") % path);
diff --git a/src/libutil/logging.cc b/src/libutil/logging.cc
index 43245f61c..c11271e63 100644
--- a/src/libutil/logging.cc
+++ b/src/libutil/logging.cc
@@ -80,4 +80,15 @@ std::atomic<uint64_t> nextId{(uint64_t) getpid() << 32};
Activity::Activity() : id(nextId++) { };
+Activity::Activity(ActivityType type, std::string msg)
+ : Activity()
+{
+ logger->event(evStartActivity, id, msg);
+}
+
+Activity::~Activity()
+{
+ logger->event(evStopActivity, id);
+}
+
}
diff --git a/src/libutil/logging.hh b/src/libutil/logging.hh
index 9ef6e3ee3..aa407f60b 100644
--- a/src/libutil/logging.hh
+++ b/src/libutil/logging.hh
@@ -13,6 +13,10 @@ typedef enum {
lvlVomit
} Verbosity;
+typedef enum {
+ actCopyPath = 100,
+} ActivityType;
+
class Activity
{
public:
@@ -21,6 +25,10 @@ public:
Activity();
Activity(const Activity & act) : id(act.id) { };
Activity(uint64_t id) : id(id) { };
+ Activity(ActivityType type, std::string msg = "");
+ ~Activity();
+
+ //void progress(...);
};
typedef enum {
@@ -35,6 +43,13 @@ typedef enum {
evSubstitutionCreated = 8,
evSubstitutionStarted = 9,
evSubstitutionFinished = 10,
+
+ evCopyStarted = 100,
+ evCopyProgress = 101,
+
+ evStartActivity = 1000,
+ evStopActivity = 1001,
+
} EventType;
struct Event
diff --git a/src/nix/progress-bar.cc b/src/nix/progress-bar.cc
index 2ecbea8ee..7561a0084 100644
--- a/src/nix/progress-bar.cc
+++ b/src/nix/progress-bar.cc
@@ -27,17 +27,29 @@ private:
DownloadInfo(const std::string & uri) : uri(uri) { }
};
+ struct CopyInfo
+ {
+ uint64_t expected = 0;
+ uint64_t copied = 0;
+ uint64_t done = 0;
+ };
+
struct State
{
std::map<Activity::t, Path> builds;
std::set<Activity::t> runningBuilds;
uint64_t succeededBuilds = 0;
uint64_t failedBuilds = 0;
+
std::map<Activity::t, Path> substitutions;
std::set<Activity::t> runningSubstitutions;
uint64_t succeededSubstitutions = 0;
+
uint64_t downloadedBytes = 0; // finished downloads
std::map<Activity::t, DownloadInfo> downloads;
+
+ std::map<Activity::t, CopyInfo> runningCopies;
+
std::list<ActInfo> activities;
std::map<Activity::t, std::list<ActInfo>::iterator> its;
};
@@ -167,11 +179,35 @@ public:
res += fmt("%1$.0f/%2$.0f KiB", current / 1024.0, expected / 1024.0);
}
+ if (!state.runningCopies.empty()) {
+ if (!res.empty()) res += ", ";
+ uint64_t copied = 0, expected = 0;
+ for (auto & i : state.runningCopies) {
+ copied += i.second.copied;
+ expected += i.second.expected - (i.second.done - i.second.copied);
+ }
+ res += fmt("%d/%d copied", copied, expected);
+ }
+
return res;
}
void event(const Event & ev) override
{
+ if (ev.type == evStartActivity) {
+ auto state(state_.lock());
+ Activity::t act = ev.getI(0);
+ createActivity(*state, act, ev.getS(1));
+ update(*state);
+ }
+
+ if (ev.type == evStopActivity) {
+ auto state(state_.lock());
+ Activity::t act = ev.getI(0);
+ deleteActivity(*state, act);
+ update(*state);
+ }
+
if (ev.type == evBuildCreated) {
auto state(state_.lock());
state->builds[ev.getI(0)] = ev.getS(1);
@@ -280,6 +316,16 @@ public:
update(*state);
}
}
+
+ if (ev.type == evCopyProgress) {
+ auto state(state_.lock());
+ Activity::t act = ev.getI(0);
+ auto & i = state->runningCopies[act];
+ i.expected = ev.getI(1);
+ i.copied = ev.getI(2);
+ i.done = ev.getI(3);
+ update(*state);
+ }
}
};