From e350f4804da2bca3dac8d6ff68712fe0f674f5c8 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Fri, 8 Mar 2024 20:17:47 +0100 Subject: [PATCH] autoupdater: update download progress display less frequently Updating the "XXXXX / XXXXX KiB" display for every run of recv_image_cb() is a significant bottleneck on slow consoles. This was reported for a device using a 9600 Baud serial console, but the slowdown is noticeable even on a 115200 Baud console, especially when the network is fast. Replace the output with a "XX.X / XX.X MiB" display and only update it every 0.1 MiB to fix the issue. Closes #273 --- admin/autoupdater/src/autoupdater.c | 36 +++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/admin/autoupdater/src/autoupdater.c b/admin/autoupdater/src/autoupdater.c index 6fb5d2a..99ae352 100644 --- a/admin/autoupdater/src/autoupdater.c +++ b/admin/autoupdater/src/autoupdater.c @@ -72,6 +72,7 @@ struct recv_manifest_ctx { struct recv_image_ctx { int fd; ecdsa_sha256_context_t hash_ctx; + ssize_t downloaded; }; @@ -248,6 +249,32 @@ static void recv_manifest_cb(struct uclient *cl) { } } +/** Updates the "XX.X / XX.X MiB" progress display */ +static void update_progress(struct recv_image_ctx *ctx, ssize_t downloaded, ssize_t length) +{ + /* Numbers in 0.1 MiB units */ + ssize_t downloaded_01_mib = ((downloaded / 1024) * 10) / 1024; + ssize_t length_01_mib = ((length / 1024) * 10) / 1024; + + if (downloaded_01_mib == ctx->downloaded) + return; + + ctx->downloaded = downloaded_01_mib; + + /* Integer and 1 digit fractional part in 1 MiB units */ + ssize_t downloaded_mib = downloaded_01_mib / 10; + int downloaded_mib_frac = downloaded_01_mib % 10; + ssize_t length_mib = length_01_mib / 10; + int length_mib_frac = length_01_mib % 10; + + printf( + "\rDownloading image: % 3zi.%i / %zi.%i MiB", + downloaded_mib, downloaded_mib_frac, + length_mib, length_mib_frac + ); + fflush(stdout); +} + /** Receives data from uclient and writes it to file */ static void recv_image_cb(struct uclient *cl) { @@ -260,12 +287,7 @@ static void recv_image_cb(struct uclient *cl) { if (len <= 0) return; - printf( - "\rDownloading image: % 5zi / %zi KiB", - uclient_data(cl)->downloaded / 1024, - uclient_data(cl)->length / 1024 - ); - fflush(stdout); + update_progress(ctx, uclient_data(cl)->downloaded, uclient_data(cl)->length); if (write(ctx->fd, buf, len) < len) { fputs("autoupdater: error: downloading firmware image failed: ", stderr); @@ -349,7 +371,7 @@ static bool autoupdate(const char *mirror, struct settings *s, int lock_fd) { /* Begin download of the image */ run_dir(download_d_dir); - struct recv_image_ctx image_ctx = { }; + struct recv_image_ctx image_ctx = { .downloaded = -1 }; image_ctx.fd = open(firmware_path, O_WRONLY|O_CREAT, 0600); if (image_ctx.fd < 0) { fprintf(stderr, "autoupdater: error: failed opening firmware file %s\n", firmware_path);