forked from lix-project/lix
Allow activities to be nested
In particular, this allows more relevant activities ("substituting X") to supersede inferior ones ("downloading X").
This commit is contained in:
parent
f194629f96
commit
c137c0a5eb
|
@ -2407,14 +2407,14 @@ struct BuilderLogger : Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
void startActivity(ActivityId act, ActivityType type,
|
void startActivity(ActivityId act, ActivityType type,
|
||||||
const std::string & s, const Fields & fields) override
|
const std::string & s, const Fields & fields, ActivityId parent) override
|
||||||
{
|
{
|
||||||
nlohmann::json json;
|
nlohmann::json json;
|
||||||
json["action"] = "start";
|
json["action"] = "start";
|
||||||
json["id"] = act;
|
json["id"] = act;
|
||||||
json["type"] = type;
|
json["type"] = type;
|
||||||
json["text"] = s;
|
json["text"] = s;
|
||||||
// FIXME: handle fields
|
// FIXME: handle fields, parent
|
||||||
log(lvlError, "@nix " + json.dump());
|
log(lvlError, "@nix " + json.dump());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3313,7 +3313,7 @@ void DerivationGoal::flushLine()
|
||||||
if (type == actDownload)
|
if (type == actDownload)
|
||||||
builderActivities.emplace(std::piecewise_construct,
|
builderActivities.emplace(std::piecewise_construct,
|
||||||
std::forward_as_tuple(json["id"]),
|
std::forward_as_tuple(json["id"]),
|
||||||
std::forward_as_tuple(*logger, type, json["text"]));
|
std::forward_as_tuple(*logger, type, json["text"], Logger::Fields{}, act->id));
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (action == "stop")
|
else if (action == "stop")
|
||||||
|
@ -3655,6 +3655,9 @@ void SubstitutionGoal::tryToRun()
|
||||||
/* Wake up the worker loop when we're done. */
|
/* Wake up the worker loop when we're done. */
|
||||||
Finally updateStats([this]() { outPipe.writeSide = -1; });
|
Finally updateStats([this]() { outPipe.writeSide = -1; });
|
||||||
|
|
||||||
|
Activity act(*logger, actSubstitute, "", Logger::Fields{storePath, sub->getUri()});
|
||||||
|
PushActivity pact(act.id);
|
||||||
|
|
||||||
copyStorePath(ref<Store>(sub), ref<Store>(worker.store.shared_from_this()),
|
copyStorePath(ref<Store>(sub), ref<Store>(worker.store.shared_from_this()),
|
||||||
storePath, repair);
|
storePath, repair);
|
||||||
|
|
||||||
|
|
|
@ -85,7 +85,7 @@ struct CurlDownloader : public Downloader
|
||||||
DownloadItem(CurlDownloader & downloader, const DownloadRequest & request)
|
DownloadItem(CurlDownloader & downloader, const DownloadRequest & request)
|
||||||
: downloader(downloader)
|
: downloader(downloader)
|
||||||
, request(request)
|
, request(request)
|
||||||
, act(*logger, actDownload, fmt("downloading '%s'", request.uri))
|
, act(*logger, actDownload, fmt("downloading '%s'", request.uri), {}, request.parentAct)
|
||||||
{
|
{
|
||||||
if (!request.expectedETag.empty())
|
if (!request.expectedETag.empty())
|
||||||
requestHeaders = curl_slist_append(requestHeaders, ("If-None-Match: " + request.expectedETag).c_str());
|
requestHeaders = curl_slist_append(requestHeaders, ("If-None-Match: " + request.expectedETag).c_str());
|
||||||
|
|
|
@ -16,8 +16,10 @@ struct DownloadRequest
|
||||||
bool head = false;
|
bool head = false;
|
||||||
size_t tries = 5;
|
size_t tries = 5;
|
||||||
unsigned int baseRetryTimeMs = 250;
|
unsigned int baseRetryTimeMs = 250;
|
||||||
|
ActivityId parentAct;
|
||||||
|
|
||||||
DownloadRequest(const std::string & uri) : uri(uri) { }
|
DownloadRequest(const std::string & uri)
|
||||||
|
: uri(uri), parentAct(curActivity) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DownloadResult
|
struct DownloadResult
|
||||||
|
|
|
@ -565,7 +565,9 @@ void Store::buildPaths(const PathSet & paths, BuildMode buildMode)
|
||||||
void copyStorePath(ref<Store> srcStore, ref<Store> dstStore,
|
void copyStorePath(ref<Store> srcStore, ref<Store> dstStore,
|
||||||
const Path & storePath, RepairFlag repair, CheckSigsFlag checkSigs)
|
const Path & storePath, RepairFlag repair, CheckSigsFlag checkSigs)
|
||||||
{
|
{
|
||||||
Activity act(*logger, actCopyPath, fmt("copying path '%s'", storePath));
|
Activity act(*logger, actCopyPath, fmt("copying path '%s'", storePath),
|
||||||
|
{storePath, srcStore->getUri(), dstStore->getUri()});
|
||||||
|
PushActivity pact(act.id);
|
||||||
|
|
||||||
auto info = srcStore->queryPathInfo(storePath);
|
auto info = srcStore->queryPathInfo(storePath);
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
|
thread_local ActivityId curActivity = 0;
|
||||||
|
|
||||||
Logger * logger = makeDefaultLogger();
|
Logger * logger = makeDefaultLogger();
|
||||||
|
|
||||||
void Logger::warn(const std::string & msg)
|
void Logger::warn(const std::string & msg)
|
||||||
|
@ -75,10 +77,10 @@ Logger * makeDefaultLogger()
|
||||||
std::atomic<uint64_t> nextId{(uint64_t) getpid() << 32};
|
std::atomic<uint64_t> nextId{(uint64_t) getpid() << 32};
|
||||||
|
|
||||||
Activity::Activity(Logger & logger, ActivityType type,
|
Activity::Activity(Logger & logger, ActivityType type,
|
||||||
const std::string & s, const Logger::Fields & fields)
|
const std::string & s, const Logger::Fields & fields, ActivityId parent)
|
||||||
: logger(logger), id(nextId++)
|
: logger(logger), id(nextId++)
|
||||||
{
|
{
|
||||||
logger.startActivity(id, type, s, fields);
|
logger.startActivity(id, type, s, fields, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ typedef enum {
|
||||||
actBuild = 105,
|
actBuild = 105,
|
||||||
actOptimiseStore = 106,
|
actOptimiseStore = 106,
|
||||||
actVerifyPaths = 107,
|
actVerifyPaths = 107,
|
||||||
|
actSubstitute = 108,
|
||||||
} ActivityType;
|
} ActivityType;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
@ -65,7 +66,7 @@ public:
|
||||||
virtual void warn(const std::string & msg);
|
virtual void warn(const std::string & msg);
|
||||||
|
|
||||||
virtual void startActivity(ActivityId act, ActivityType type,
|
virtual void startActivity(ActivityId act, ActivityType type,
|
||||||
const std::string & s, const Fields & fields) { };
|
const std::string & s, const Fields & fields, ActivityId parent) { };
|
||||||
|
|
||||||
virtual void stopActivity(ActivityId act) { };
|
virtual void stopActivity(ActivityId act) { };
|
||||||
|
|
||||||
|
@ -76,6 +77,8 @@ public:
|
||||||
virtual void result(ActivityId act, ResultType type, const Fields & fields) { };
|
virtual void result(ActivityId act, ResultType type, const Fields & fields) { };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern thread_local ActivityId curActivity;
|
||||||
|
|
||||||
struct Activity
|
struct Activity
|
||||||
{
|
{
|
||||||
Logger & logger;
|
Logger & logger;
|
||||||
|
@ -83,7 +86,7 @@ struct Activity
|
||||||
const ActivityId id;
|
const ActivityId id;
|
||||||
|
|
||||||
Activity(Logger & logger, ActivityType type, const std::string & s = "",
|
Activity(Logger & logger, ActivityType type, const std::string & s = "",
|
||||||
const Logger::Fields & fields = {});
|
const Logger::Fields & fields = {}, ActivityId parent = curActivity);
|
||||||
|
|
||||||
Activity(const Activity & act) = delete;
|
Activity(const Activity & act) = delete;
|
||||||
|
|
||||||
|
@ -107,6 +110,13 @@ struct Activity
|
||||||
friend class Logger;
|
friend class Logger;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct PushActivity
|
||||||
|
{
|
||||||
|
const ActivityId prevAct;
|
||||||
|
PushActivity(ActivityId act) : prevAct(curActivity) { curActivity = act; }
|
||||||
|
~PushActivity() { curActivity = prevAct; }
|
||||||
|
};
|
||||||
|
|
||||||
extern Logger * logger;
|
extern Logger * logger;
|
||||||
|
|
||||||
Logger * makeDefaultLogger();
|
Logger * makeDefaultLogger();
|
||||||
|
|
|
@ -73,6 +73,8 @@ private:
|
||||||
uint64_t running = 0;
|
uint64_t running = 0;
|
||||||
uint64_t failed = 0;
|
uint64_t failed = 0;
|
||||||
std::map<ActivityType, uint64_t> expectedByType;
|
std::map<ActivityType, uint64_t> expectedByType;
|
||||||
|
bool visible = true;
|
||||||
|
ActivityId parent;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ActivitiesByType
|
struct ActivitiesByType
|
||||||
|
@ -125,7 +127,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void startActivity(ActivityId act, ActivityType type, const std::string & s,
|
void startActivity(ActivityId act, ActivityType type, const std::string & s,
|
||||||
const Fields & fields) override
|
const Fields & fields, ActivityId parent) override
|
||||||
{
|
{
|
||||||
auto state(state_.lock());
|
auto state(state_.lock());
|
||||||
|
|
||||||
|
@ -133,6 +135,7 @@ public:
|
||||||
auto i = std::prev(state->activities.end());
|
auto i = std::prev(state->activities.end());
|
||||||
i->s = s;
|
i->s = s;
|
||||||
i->type = type;
|
i->type = type;
|
||||||
|
i->parent = parent;
|
||||||
state->its.emplace(act, i);
|
state->its.emplace(act, i);
|
||||||
state->activitiesByType[type].its.emplace(act, i);
|
state->activitiesByType[type].its.emplace(act, i);
|
||||||
|
|
||||||
|
@ -143,9 +146,30 @@ public:
|
||||||
i->s = fmt("building " ANSI_BOLD "%s" ANSI_NORMAL, name);
|
i->s = fmt("building " ANSI_BOLD "%s" ANSI_NORMAL, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (type == actSubstitute) {
|
||||||
|
auto name = storePathToName(getS(fields, 0));
|
||||||
|
i->s = fmt("fetching " ANSI_BOLD "%s" ANSI_NORMAL " from %s", name, getS(fields, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((type == actDownload && hasAncestor(*state, actCopyPath, parent))
|
||||||
|
|| (type == actCopyPath && hasAncestor(*state, actSubstitute, parent)))
|
||||||
|
i->visible = false;
|
||||||
|
|
||||||
update(*state);
|
update(*state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check whether an activity has an ancestore with the specified
|
||||||
|
type. */
|
||||||
|
bool hasAncestor(State & state, ActivityType type, ActivityId act)
|
||||||
|
{
|
||||||
|
while (act != 0) {
|
||||||
|
auto i = state.its.find(act);
|
||||||
|
if (i == state.its.end()) break;
|
||||||
|
if (i->second->type == type) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void stopActivity(ActivityId act) override
|
void stopActivity(ActivityId act) override
|
||||||
{
|
{
|
||||||
auto state(state_.lock());
|
auto state(state_.lock());
|
||||||
|
@ -253,7 +277,7 @@ public:
|
||||||
if (!status.empty()) line += " ";
|
if (!status.empty()) line += " ";
|
||||||
auto i = state.activities.rbegin();
|
auto i = state.activities.rbegin();
|
||||||
|
|
||||||
while (i != state.activities.rend() && i->s.empty() && i->s2.empty())
|
while (i != state.activities.rend() && (!i->visible || (i->s.empty() && i->s2.empty())))
|
||||||
++i;
|
++i;
|
||||||
|
|
||||||
if (i != state.activities.rend()) {
|
if (i != state.activities.rend()) {
|
||||||
|
|
Loading…
Reference in a new issue