mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-20 09:46:20 +00:00
parent
c9f2847420
commit
5dc8e330b6
@ -108,8 +108,43 @@ struct Sculpt::Deploy
|
||||
*/
|
||||
deploy.for_each_sub_node("start", [&] (Xml_node node) {
|
||||
Start_name const name = node.attribute_value("name", Start_name());
|
||||
if (!_runtime_info.abandoned_by_user(name))
|
||||
append_xml_node(node);
|
||||
if (_runtime_info.abandoned_by_user(name))
|
||||
return;
|
||||
|
||||
xml.node("start", [&] () {
|
||||
|
||||
/*
|
||||
* Copy attributes
|
||||
*/
|
||||
|
||||
xml.attribute("name", name);
|
||||
|
||||
/* override version with restarted version, after restart */
|
||||
using Version = Child_state::Version;
|
||||
Version version = _runtime_info.restarted_version(name);
|
||||
if (version.value == 0)
|
||||
version = Version { node.attribute_value("version", 0U) };
|
||||
|
||||
if (version.value > 0)
|
||||
xml.attribute("version", version.value);
|
||||
|
||||
auto copy_attribute = [&] (auto attr)
|
||||
{
|
||||
if (node.has_attribute(attr)) {
|
||||
using Value = String<128>;
|
||||
xml.attribute(attr, node.attribute_value(attr, Value()));
|
||||
}
|
||||
};
|
||||
|
||||
copy_attribute("caps");
|
||||
copy_attribute("ram");
|
||||
copy_attribute("cpu");
|
||||
copy_attribute("pkg");
|
||||
|
||||
/* copy start-node content */
|
||||
node.with_raw_content([&] (char const *start, size_t length) {
|
||||
xml.append(start, length); });
|
||||
});
|
||||
});
|
||||
|
||||
/*
|
||||
|
@ -24,13 +24,16 @@ void Graph::_gen_selected_node_content(Xml_generator &xml, Start_name const &nam
|
||||
|
||||
if (removable) {
|
||||
gen_named_node(xml, "frame", "operations", [&] () {
|
||||
xml.node("vbox", [&] () {
|
||||
xml.node("hbox", [&] () {
|
||||
gen_named_node(xml, "button", "remove", [&] () {
|
||||
_remove_item.gen_button_attr(xml, "remove");
|
||||
_action_item.gen_button_attr(xml, "remove");
|
||||
xml.node("label", [&] () {
|
||||
xml.attribute("text", "Remove");
|
||||
});
|
||||
});
|
||||
xml.attribute("text", "Remove"); }); });
|
||||
|
||||
gen_named_node(xml, "button", "restart", [&] () {
|
||||
_action_item.gen_button_attr(xml, "restart");
|
||||
xml.node("label", [&] () {
|
||||
xml.attribute("text", "Restart"); }); });
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -276,8 +279,8 @@ Dialog::Hover_result Graph::hover(Xml_node hover)
|
||||
_ram_fs_dialog.match_sub_dialog(hover, "depgraph", "frame", "vbox", "frame", "vbox"),
|
||||
_node_button_item.match(hover, "depgraph", "frame", "vbox", "button", "name"),
|
||||
_add_button_item .match(hover, "depgraph", "button", "name"),
|
||||
_remove_item .match(hover, "depgraph", "frame", "vbox",
|
||||
"frame", "vbox", "button", "name"));
|
||||
_action_item .match(hover, "depgraph", "frame", "vbox",
|
||||
"frame", "hbox", "button", "name"));
|
||||
|
||||
if (_add_button_item.hovered("global+")) {
|
||||
|
||||
@ -335,11 +338,11 @@ void Graph::click(Action &action)
|
||||
|
||||
_runtime_state.toggle_selection(_node_button_item._hovered,
|
||||
_runtime_config);
|
||||
_remove_item.reset();
|
||||
_action_item.reset();
|
||||
}
|
||||
|
||||
if (_remove_item.hovered("remove"))
|
||||
_remove_item.propose_activation_on_click();
|
||||
if (_action_item.hovered("remove") || _action_item.hovered("restart"))
|
||||
_action_item.propose_activation_on_click();
|
||||
}
|
||||
|
||||
|
||||
@ -352,11 +355,11 @@ void Graph::clack(Action &action, Ram_fs_dialog::Action &ram_fs_action)
|
||||
if (_storage_dialog->clack(action) == Clack_result::CONSUMED)
|
||||
return;
|
||||
|
||||
if (_remove_item.hovered("remove")) {
|
||||
if (_action_item.hovered("remove")) {
|
||||
|
||||
_remove_item.confirm_activation_on_clack();
|
||||
_action_item.confirm_activation_on_clack();
|
||||
|
||||
if (_remove_item.activated("remove")) {
|
||||
if (_action_item.activated("remove")) {
|
||||
action.remove_deployed_component(_runtime_state.selected());
|
||||
|
||||
/*
|
||||
@ -366,8 +369,16 @@ void Graph::clack(Action &action, Ram_fs_dialog::Action &ram_fs_action)
|
||||
_runtime_state.toggle_selection(_runtime_state.selected(),
|
||||
_runtime_config);
|
||||
}
|
||||
} else {
|
||||
_remove_item.reset();
|
||||
}
|
||||
|
||||
if (_action_item.hovered("restart")) {
|
||||
|
||||
_action_item.confirm_activation_on_clack();
|
||||
|
||||
if (_action_item.activated("restart"))
|
||||
action.restart_deployed_component(_runtime_state.selected());
|
||||
}
|
||||
|
||||
_action_item.reset();
|
||||
}
|
||||
|
||||
|
@ -51,8 +51,8 @@ struct Sculpt::Graph : Dialog
|
||||
Depot_deploy::Children const &_deploy_children;
|
||||
|
||||
Hoverable_item _node_button_item { };
|
||||
Hoverable_item _add_button_item { };
|
||||
Activatable_item _remove_item { };
|
||||
Hoverable_item _add_button_item { };
|
||||
Activatable_item _action_item { };
|
||||
|
||||
/*
|
||||
* Defined when '+' button is hovered
|
||||
@ -106,6 +106,7 @@ struct Sculpt::Graph : Dialog
|
||||
struct Action : Storage_dialog::Action
|
||||
{
|
||||
virtual void remove_deployed_component(Start_name const &) = 0;
|
||||
virtual void restart_deployed_component(Start_name const &) = 0;
|
||||
virtual void toggle_launcher_selector(Rect) = 0;
|
||||
};
|
||||
|
||||
|
@ -642,6 +642,17 @@ struct Sculpt::Main : Input_event_handler,
|
||||
_deploy.update_managed_deploy_config(_manual_deploy_rom.xml());
|
||||
}
|
||||
|
||||
/*
|
||||
* Graph::Action interface
|
||||
*/
|
||||
void restart_deployed_component(Start_name const &name) override
|
||||
{
|
||||
_runtime_state.restart(name);
|
||||
|
||||
/* update config/managed/deploy with the component 'name' removed */
|
||||
_deploy.update_managed_deploy_config(_manual_deploy_rom.xml());
|
||||
}
|
||||
|
||||
/*
|
||||
* Graph::Action interface
|
||||
*/
|
||||
|
@ -25,6 +25,10 @@ namespace Sculpt { struct Child_state; }
|
||||
|
||||
struct Sculpt::Child_state : Noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
struct Version { unsigned value; };
|
||||
|
||||
private:
|
||||
|
||||
Registry<Child_state>::Element _element;
|
||||
@ -37,7 +41,7 @@ struct Sculpt::Child_state : Noncopyable
|
||||
Ram_quota _ram_quota = _initial_ram_quota;
|
||||
Cap_quota _cap_quota = _initial_cap_quota;
|
||||
|
||||
struct Version { unsigned value; } _version { 0 };
|
||||
Version _version { 0 };
|
||||
|
||||
public:
|
||||
|
||||
|
@ -30,6 +30,8 @@ class Sculpt::Runtime_state : public Runtime_info
|
||||
{
|
||||
public:
|
||||
|
||||
using Version = Child_state::Version;
|
||||
|
||||
struct Info
|
||||
{
|
||||
bool selected;
|
||||
@ -45,6 +47,8 @@ class Sculpt::Runtime_state : public Runtime_info
|
||||
|
||||
unsigned long assigned_caps;
|
||||
unsigned long avail_caps;
|
||||
|
||||
Version version;
|
||||
};
|
||||
|
||||
private:
|
||||
@ -57,11 +61,14 @@ class Sculpt::Runtime_state : public Runtime_info
|
||||
{
|
||||
Start_name const name;
|
||||
|
||||
Info info { .selected = false,
|
||||
.tcb = false,
|
||||
.tcb_updated = false,
|
||||
.assigned_ram = 0, .avail_ram = 0,
|
||||
.assigned_caps = 0, .avail_caps = 0 };
|
||||
Info info { .selected = false,
|
||||
.tcb = false,
|
||||
.tcb_updated = false,
|
||||
.assigned_ram = 0,
|
||||
.avail_ram = 0,
|
||||
.assigned_caps = 0,
|
||||
.avail_caps = 0,
|
||||
.version = { 0 }};
|
||||
|
||||
bool abandoned_by_user = false;
|
||||
|
||||
@ -79,11 +86,27 @@ class Sculpt::Runtime_state : public Runtime_info
|
||||
struct Abandoned_child : Interface
|
||||
{
|
||||
Start_name const name;
|
||||
|
||||
Abandoned_child(Start_name const &name) : name(name) { };
|
||||
};
|
||||
|
||||
Registry<Registered<Abandoned_child> > _abandoned_children { };
|
||||
|
||||
/**
|
||||
* Child that was interactively restarted
|
||||
*/
|
||||
struct Restarted_child : Interface
|
||||
{
|
||||
Start_name const name;
|
||||
|
||||
Version version;
|
||||
|
||||
Restarted_child(Start_name const &name, Version const &version)
|
||||
: name(name), version(version) { };
|
||||
};
|
||||
|
||||
Registry<Registered<Restarted_child> > _restarted_children { };
|
||||
|
||||
/**
|
||||
* Child that was interactively launched
|
||||
*/
|
||||
@ -115,20 +138,25 @@ class Sculpt::Runtime_state : public Runtime_info
|
||||
construction.construct(alloc, pkg_path, info, space);
|
||||
}
|
||||
|
||||
void gen_deploy_start_node(Xml_generator &xml) const
|
||||
void gen_deploy_start_node(Xml_generator &xml, Runtime_state const &state) const
|
||||
{
|
||||
if (!launched)
|
||||
return;
|
||||
|
||||
gen_named_node(xml, "start", name, [&] () {
|
||||
|
||||
Version const version = state.restarted_version(name);
|
||||
|
||||
if (version.value > 0)
|
||||
xml.attribute("version", version.value);
|
||||
|
||||
/* interactively constructed */
|
||||
if (construction.constructed()) {
|
||||
xml.attribute("pkg", construction->path);
|
||||
|
||||
xml.attribute("xpos", construction->affinity_location.xpos());
|
||||
xml.attribute("ypos", construction->affinity_location.ypos());
|
||||
xml.attribute("width", construction->affinity_location.width());
|
||||
xml.attribute("xpos", construction->affinity_location.xpos());
|
||||
xml.attribute("ypos", construction->affinity_location.ypos());
|
||||
xml.attribute("width", construction->affinity_location.width());
|
||||
xml.attribute("height", construction->affinity_location.height());
|
||||
|
||||
xml.node("route", [&] () {
|
||||
@ -178,15 +206,17 @@ class Sculpt::Runtime_state : public Runtime_info
|
||||
Xml_node const ram = node.sub_node("ram");
|
||||
child.info.assigned_ram = max(ram.attribute_value("assigned", Number_of_bytes()),
|
||||
ram.attribute_value("quota", Number_of_bytes()));
|
||||
child.info.avail_ram = ram.attribute_value("avail", Number_of_bytes());
|
||||
child.info.avail_ram = ram.attribute_value("avail", Number_of_bytes());
|
||||
}
|
||||
|
||||
if (node.has_sub_node("caps")) {
|
||||
Xml_node const caps = node.sub_node("caps");
|
||||
child.info.assigned_caps = max(caps.attribute_value("assigned", 0UL),
|
||||
caps.attribute_value("quota", 0UL));
|
||||
child.info.avail_caps = caps.attribute_value("avail", 0UL);
|
||||
child.info.avail_caps = caps.attribute_value("avail", 0UL);
|
||||
}
|
||||
|
||||
child.info.version.value = node.attribute_value("version", 0U);
|
||||
}
|
||||
|
||||
static bool element_matches_xml_node(Child const &elem, Xml_node node)
|
||||
@ -240,9 +270,28 @@ class Sculpt::Runtime_state : public Runtime_info
|
||||
bool abandoned_by_user(Start_name const &name) const override
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
_abandoned_children.for_each([&] (Abandoned_child const &child) {
|
||||
if (!result && child.name == name)
|
||||
result = true; });
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return version of restarted child
|
||||
*
|
||||
* If the returned value is version 0, the child has not been
|
||||
* restarted.
|
||||
*/
|
||||
Version restarted_version(Start_name const &name) const override
|
||||
{
|
||||
Version result { 0 };
|
||||
|
||||
_restarted_children.for_each([&] (Restarted_child const &child) {
|
||||
if (!result.value && child.name == name)
|
||||
result = child.version; });
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -252,7 +301,7 @@ class Sculpt::Runtime_state : public Runtime_info
|
||||
void gen_launched_deploy_start_nodes(Xml_generator &xml) const override
|
||||
{
|
||||
_launched_children.for_each([&] (Launched_child const &child) {
|
||||
child.gen_deploy_start_node(xml); });
|
||||
child.gen_deploy_start_node(xml, *this); });
|
||||
}
|
||||
|
||||
Info info(Start_name const &name) const
|
||||
@ -363,6 +412,30 @@ class Sculpt::Runtime_state : public Runtime_info
|
||||
new (_alloc) Registered<Abandoned_child>(_abandoned_children, name);
|
||||
}
|
||||
|
||||
void restart(Start_name const &name)
|
||||
{
|
||||
/* determin current version from most recent state report */
|
||||
Version current_version { 0 };
|
||||
_children.for_each([&] (Child const &child) {
|
||||
if (child.name == name)
|
||||
current_version = child.info.version; });
|
||||
|
||||
Version const next_version { current_version.value + 1 };
|
||||
|
||||
bool already_restarted = false;
|
||||
|
||||
_restarted_children.for_each([&] (Restarted_child &child) {
|
||||
if (child.name == name) {
|
||||
already_restarted = true;
|
||||
child.version = next_version;
|
||||
}
|
||||
});
|
||||
|
||||
if (!already_restarted)
|
||||
new (_alloc)
|
||||
Registered<Restarted_child>(_restarted_children, name, next_version);
|
||||
}
|
||||
|
||||
void launch(Start_name const &name, Path const &launcher)
|
||||
{
|
||||
new (_alloc) Registered<Launched_child>(_launched_children, name, launcher);
|
||||
@ -431,6 +504,9 @@ class Sculpt::Runtime_state : public Runtime_info
|
||||
|
||||
_launched_children.for_each([&] (Launched_child &child) {
|
||||
destroy(_alloc, &child); });
|
||||
|
||||
_restarted_children.for_each([&] (Restarted_child &child) {
|
||||
destroy(_alloc, &child); });
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <model/storage_devices.h>
|
||||
#include <model/storage_target.h>
|
||||
#include <model/nic_target.h>
|
||||
#include <model/child_state.h>
|
||||
|
||||
namespace Sculpt {
|
||||
|
||||
@ -29,6 +30,8 @@ namespace Sculpt {
|
||||
|
||||
struct Runtime_info : Interface
|
||||
{
|
||||
using Version = Child_state::Version;
|
||||
|
||||
/**
|
||||
* Return true if specified child is present in the runtime subsystem
|
||||
*/
|
||||
@ -36,6 +39,8 @@ namespace Sculpt {
|
||||
|
||||
virtual bool abandoned_by_user(Start_name const &) const = 0;
|
||||
|
||||
virtual Version restarted_version(Start_name const &) const = 0;
|
||||
|
||||
virtual void gen_launched_deploy_start_nodes(Xml_generator &) const = 0;
|
||||
};
|
||||
|
||||
|
@ -57,7 +57,7 @@ struct Sculpt::Activatable_item : Hoverable_item
|
||||
if (!_selected.valid() || !_activated.valid())
|
||||
Hoverable_item::gen_button_attr(xml, id);
|
||||
|
||||
if (_selected.valid() && _selected == _hovered)
|
||||
if (_selected.valid() && _selected == _hovered && _selected == id)
|
||||
xml.attribute("selected", "yes");
|
||||
}
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user