sysupdate: Report download progress via sd_notify
We set up a NOTIFY_SOCKET to get download progress notifications from each individual import helper. Along with the number of import jobs we have to run, this gives an overall progress value which we report using sd_notify
This commit is contained in:
@@ -25,6 +25,7 @@
|
||||
#include "path-util.h"
|
||||
#include "pretty-print.h"
|
||||
#include "set.h"
|
||||
#include "signal-util.h"
|
||||
#include "sort-util.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
@@ -135,7 +136,7 @@ static int context_read_definitions(
|
||||
if (!GREEDY_REALLOC(c->transfers, c->n_transfers + 1))
|
||||
return log_oom();
|
||||
|
||||
t = transfer_new();
|
||||
t = transfer_new(c);
|
||||
if (!t)
|
||||
return log_oom();
|
||||
|
||||
@@ -744,6 +745,30 @@ static int context_make_online(Context **ret, const char *node) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int context_on_acquire_progress(const Transfer *t, const Instance *inst, unsigned percentage) {
|
||||
const Context *c = ASSERT_PTR(t->context);
|
||||
size_t i, n = c->n_transfers;
|
||||
uint64_t base, scaled;
|
||||
unsigned overall;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
if (c->transfers[i] == t)
|
||||
break;
|
||||
assert(i < n); /* We should have found the index */
|
||||
|
||||
base = (100 * 100 * i) / n;
|
||||
scaled = (100 * percentage) / n;
|
||||
overall = (unsigned) ((base + scaled) / 100);
|
||||
assert(overall <= 100);
|
||||
|
||||
log_debug("Transfer %" PRIu64 "/%zu is %u%% complete (%u%% overall).", i+1, n, percentage, overall);
|
||||
return sd_notifyf(/* unset= */ false, "X_SYSUPDATE_PROGRESS=%u\n"
|
||||
"X_SYSUPDATE_TRANSFERS_LEFT=%zu\n"
|
||||
"X_SYSUPDATE_TRANSFERS_DONE=%zu\n"
|
||||
"STATUS=Updating to '%s' (%u%% complete).",
|
||||
overall, n - i, i, inst->metadata.version, overall);
|
||||
}
|
||||
|
||||
static int context_apply(
|
||||
Context *c,
|
||||
const char *version,
|
||||
@@ -793,8 +818,10 @@ static int context_apply(
|
||||
|
||||
log_info("Selected update '%s' for install.", us->version);
|
||||
|
||||
(void) sd_notifyf(false,
|
||||
"STATUS=Making room for '%s'.", us->version);
|
||||
(void) sd_notifyf(/* unset= */ false,
|
||||
"READY=1\n"
|
||||
"X_SYSUPDATE_VERSION=%s\n"
|
||||
"STATUS=Making room for '%s'.", us->version, us->version);
|
||||
|
||||
/* Let's make some room. We make sure for each transfer we have one free space to fill. While
|
||||
* removing stuff we'll protect the version we are trying to acquire. Why that? Maybe an earlier
|
||||
@@ -809,14 +836,15 @@ static int context_apply(
|
||||
if (arg_sync)
|
||||
sync();
|
||||
|
||||
(void) sd_notifyf(false,
|
||||
"STATUS=Updating to '%s'.\n", us->version);
|
||||
(void) sd_notifyf(/* unset= */ false,
|
||||
"STATUS=Updating to '%s'.", us->version);
|
||||
|
||||
/* There should now be one instance picked for each transfer, and the order is the same */
|
||||
assert(us->n_instances == c->n_transfers);
|
||||
|
||||
for (size_t i = 0; i < c->n_transfers; i++) {
|
||||
r = transfer_acquire_instance(c->transfers[i], us->instances[i]);
|
||||
r = transfer_acquire_instance(c->transfers[i], us->instances[i],
|
||||
context_on_acquire_progress, c);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
@@ -824,6 +852,9 @@ static int context_apply(
|
||||
if (arg_sync)
|
||||
sync();
|
||||
|
||||
(void) sd_notifyf(/* unset= */ false,
|
||||
"STATUS=Installing '%s'.", us->version);
|
||||
|
||||
for (size_t i = 0; i < c->n_transfers; i++) {
|
||||
r = transfer_install_instance(c->transfers[i], us->instances[i], arg_root);
|
||||
if (r < 0)
|
||||
@@ -1412,6 +1443,9 @@ static int run(int argc, char *argv[]) {
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
/* SIGCHLD signal must be blocked for sd_event_add_child to work */
|
||||
BLOCK_SIGNALS(SIGCHLD);
|
||||
|
||||
return sysupdate_main(argc, argv);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user