From bb6a189589785a42d7b20dc87e9bb853c969bea6 Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Wed, 19 Apr 2023 15:07:30 +0200 Subject: [PATCH] sculpt: show failed downloads in diagnostics This patch complements the diagnostics view with the failure state tracked by the download queue. Issue #4818 --- repos/gems/src/app/sculpt_manager/main.cc | 16 +++++-- .../app/sculpt_manager/model/download_queue.h | 37 ++++++++------- .../app/sculpt_manager/view/download_status.h | 47 +++++++++++++------ 3 files changed, 63 insertions(+), 37 deletions(-) diff --git a/repos/gems/src/app/sculpt_manager/main.cc b/repos/gems/src/app/sculpt_manager/main.cc index 2880b68e6a..000e2dc4cf 100644 --- a/repos/gems/src/app/sculpt_manager/main.cc +++ b/repos/gems/src/app/sculpt_manager/main.cc @@ -223,6 +223,7 @@ struct Sculpt::Main : Input_event_handler, /* trigger loading of the configuration from the sculpt partition */ _prepare_version.value++; + _download_queue.remove_inactive_downloads(); _deploy.restart(); generate_runtime_config(); @@ -482,8 +483,8 @@ struct Sculpt::Main : Input_event_handler, bool const network_missing = _deploy.update_needed() && !_network._nic_state.ready(); - bool const show_diagnostics = - _deploy.any_unsatisfied_child() || network_missing; + bool const show_diagnostics = _deploy.any_unsatisfied_child() + || network_missing; auto gen_network_diagnostics = [&] (Xml_generator &xml) { @@ -519,8 +520,12 @@ struct Sculpt::Main : Input_event_handler, } Xml_node const state = _update_state_rom.xml(); - if (_update_running() && state.attribute_value("progress", false)) - gen_download_status(xml, state); + + bool const download_in_progress = + (_update_running() && state.attribute_value("progress", false)); + + if (download_in_progress || _download_queue.any_failed_download()) + gen_download_status(xml, state, _download_queue); }); } @@ -1103,6 +1108,7 @@ struct Sculpt::Main : Input_event_handler, _close_popup_dialog(); /* trigger change of the deployment */ + _download_queue.remove_inactive_downloads(); _deploy.update_managed_deploy_config(); } @@ -1131,6 +1137,7 @@ struct Sculpt::Main : Input_event_handler, void trigger_download(Path const &path, Verify verify) override { + _download_queue.remove_inactive_downloads(); _download_queue.add(path, verify); /* incorporate new download-queue content into update */ @@ -1618,7 +1625,6 @@ void Sculpt::Main::_handle_update_state() _popup_dialog.interested_in_download(); _download_queue.apply_update_state(update_state); - _download_queue.remove_inactive_downloads(); bool const installation_complete = !update_state.attribute_value("progress", false); diff --git a/repos/gems/src/app/sculpt_manager/model/download_queue.h b/repos/gems/src/app/sculpt_manager/model/download_queue.h index 44dd547153..6d524bc197 100644 --- a/repos/gems/src/app/sculpt_manager/model/download_queue.h +++ b/repos/gems/src/app/sculpt_manager/model/download_queue.h @@ -71,9 +71,18 @@ struct Sculpt::Download_queue : Noncopyable Download_queue(Allocator &alloc) : _alloc(alloc) { } + bool _state_present(Download::State const state) const + { + bool result = false; + _downloads.for_each([&] (Download const &download) { + if (!result && download.state == state) + result = true; }); + + return result; + } + void add(Path const &path, Verify const verify) { - log("add to download queue: ", path); bool already_exists = false; _downloads.for_each([&] (Download const &download) { if (download.path == path) @@ -102,7 +111,7 @@ struct Sculpt::Download_queue : Noncopyable return result; } - void apply_update_state(Xml_node state) + void apply_update_state(Xml_node const &state) { /* 'elem' may be of type 'index' or 'archive' */ state.for_each_sub_node([&] (Xml_node elem) { @@ -150,24 +159,16 @@ struct Sculpt::Download_queue : Noncopyable download.gen_installation_entry(xml); }); } - bool any_active_download() const + bool any_active_download() const { return _state_present(Download::State::DOWNLOADING); } + bool any_completed_download() const { return _state_present(Download::State::DONE); } + bool any_failed_download() const { return _state_present(Download::State::FAILED); } + + template + void for_each_failed_download(FN const &fn) const { - bool result = false; _downloads.for_each([&] (Download const &download) { - if (!result && download.state == Download::State::DOWNLOADING) - result = true; }); - - return result; - } - - bool any_completed_download() const - { - bool result = false; - _downloads.for_each([&] (Download const &download) { - if (!result && download.state == Download::State::DONE) - result = true; }); - - return result; + if (download.state == Download::State::FAILED) + fn(download.path); }); } }; diff --git a/repos/gems/src/app/sculpt_manager/view/download_status.h b/repos/gems/src/app/sculpt_manager/view/download_status.h index 57d3c8d7b3..0d377a246a 100644 --- a/repos/gems/src/app/sculpt_manager/view/download_status.h +++ b/repos/gems/src/app/sculpt_manager/view/download_status.h @@ -16,11 +16,16 @@ /* local includes */ #include +#include -namespace Sculpt { static void gen_download_status(Xml_generator &, Xml_node); } +namespace Sculpt { + + static void gen_download_status(Xml_generator &, Xml_node const &, Download_queue const &); +} -void Sculpt::gen_download_status(Xml_generator &xml, Xml_node state) +void Sculpt::gen_download_status(Xml_generator &xml, Xml_node const &state, + Download_queue const &download_queue) { gen_named_node(xml, "frame", "downloads", [&] () { xml.node("vbox", [&] () { @@ -28,20 +33,37 @@ void Sculpt::gen_download_status(Xml_generator &xml, Xml_node state) xml.node("label", [&] () { xml.attribute("text", "Download"); }); + using Path = String<40>; + using Info = String<16>; + unsigned count = 0; - state.for_each_sub_node("archive", [&] (Xml_node archive) { + + auto gen_message = [&] (auto const &path, auto const &info) + { gen_named_node(xml, "hbox", String<10>(count++), [&] () { gen_named_node(xml, "float", "left", [&] () { xml.attribute("west", "yes"); - typedef String<40> Path; xml.node("label", [&] () { - xml.attribute("text", archive.attribute_value("path", Path())); + xml.attribute("text", path); xml.attribute("font", "annotation/regular"); }); }); + gen_named_node(xml, "float", "right", [&] () { + xml.attribute("east", "yes"); + xml.node("label", [&] () { + xml.attribute("text", Info(" ", info)); + xml.attribute("font", "annotation/regular"); + }); + }); + }); + }; - typedef String<16> Info; + bool const download_in_progress = state.attribute_value("progress", false); + if (download_in_progress) { + state.for_each_sub_node("archive", [&] (Xml_node archive) { + + Path const path = archive.attribute_value("path", Path()); Info info = archive.attribute_value("state", Info()); double const total = archive.attribute_value("total", 0.0d); double const now = archive.attribute_value("now", 0.0d); @@ -53,15 +75,12 @@ void Sculpt::gen_download_status(Xml_generator &xml, Xml_node state) info = Info("fetch"); } - gen_named_node(xml, "float", "right", [&] () { - xml.attribute("east", "yes"); - xml.node("label", [&] () { - xml.attribute("text", info); - xml.attribute("font", "annotation/regular"); - }); - }); + gen_message(path, info); }); - }); + } else { + download_queue.for_each_failed_download([&] (Path const &path) { + gen_message(path, "failed"); }); + } }); }); }