sculpt: show failed downloads in diagnostics

This patch complements the diagnostics view with the failure state
tracked by the download queue.

Issue #4818
This commit is contained in:
Norman Feske 2023-04-19 15:07:30 +02:00 committed by Christian Helmuth
parent 9e42c94e30
commit bb6a189589
3 changed files with 63 additions and 37 deletions

View File

@ -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);

View File

@ -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 <typename FN>
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); });
}
};

View File

@ -16,11 +16,16 @@
/* local includes */
#include <xml.h>
#include <model/download_queue.h>
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"); });
}
});
});
}