sculpt: show TCB dependencies of selection

This patch enhances the runtime view such that not only immediate
dependencies but also all transitive dependencies of the selected
component are displayed. This way, the graph nicely reveals the
trusted computing base of the selection.
This commit is contained in:
Norman Feske 2019-02-23 19:09:15 +01:00 committed by Christian Helmuth
parent 21968d35bb
commit 2163ce25f6
3 changed files with 68 additions and 10 deletions

View File

@ -172,7 +172,7 @@ struct Sculpt::Graph
Runtime_state::Info const info = _runtime_state.info(name);
bool const show_details = info.selected;
bool const show_details = info.tcb;
if (show_details) {
component.for_each_secondary_dep([&] (Start_name const &dep) {
@ -266,7 +266,8 @@ struct Sculpt::Graph
}
if (_node_button_item._hovered.valid()) {
_runtime_state.toggle_selection(_node_button_item._hovered);
_runtime_state.toggle_selection(_node_button_item._hovered,
_runtime_config);
_remove_item.reset();
_gen_graph_dialog();
}

View File

@ -149,7 +149,6 @@ class Sculpt::Runtime_config
Dep &create_element(Xml_node node)
{
log("to_name -> ", _to_name(node), " for ", node);
return *new (_alloc) Dep(_to_name(node));
}
@ -186,10 +185,13 @@ class Sculpt::Runtime_config
Allocator &_alloc;
Dep::Update_policy _dep_update_policy { _alloc };
Update_policy(Allocator &alloc) : _alloc(alloc) { }
void destroy_element(Component &elem)
{
elem.deps.update_from_xml(_dep_update_policy, Xml_node("<route/>"));
destroy(_alloc, &elem);
}
@ -201,12 +203,10 @@ class Sculpt::Runtime_config
void update_element(Component &elem, Xml_node node)
{
log("update component ", elem.name);
elem.primary_dependency = _primary_dependency(node);
Dep::Update_policy policy(_alloc);
node.with_sub_node("route", [&] (Xml_node route) {
elem.deps.update_from_xml(policy, route); });
elem.deps.update_from_xml(_dep_update_policy, route); });
}
static bool element_matches_xml_node(Component const &elem, Xml_node node)
@ -234,6 +234,18 @@ class Sculpt::Runtime_config
template <typename FN>
void for_each_component(FN const &fn) const { _components.for_each(fn); }
/**
* Call 'fn' with the name of each dependency of component 'name'
*/
template <typename FN>
void for_each_dependency(Start_name const &name, FN const &fn) const
{
_components.for_each([&] (Component const &component) {
if (component.name == name) {
component.deps.for_each([&] (Component::Dep const &dep) {
fn(dep.to_name); }); } });
}
};
#endif /* _MODEL__RUNTIME_CONFIG_H_ */

View File

@ -21,6 +21,7 @@
/* local includes */
#include <types.h>
#include <runtime.h>
#include <model/runtime_config.h>
namespace Sculpt { class Runtime_state; }
@ -32,6 +33,12 @@ class Sculpt::Runtime_state : public Runtime_info
{
bool selected;
/* true if component is in the TCB of the selected one */
bool tcb;
/* true if 'tcb' is updated for the immediate dependencies */
bool tcb_updated;
unsigned long assigned_ram;
unsigned long avail_ram;
@ -47,7 +54,11 @@ class Sculpt::Runtime_state : public Runtime_info
{
Start_name const name;
Info info { false, 0, 0, 0, 0 };
Info info { .selected = false,
.tcb = false,
.tcb_updated = false,
.assigned_ram = 0, .avail_ram = 0,
.assigned_caps = 0, .avail_caps = 0 };
bool abandoned_by_user = false;
@ -118,6 +129,8 @@ class Sculpt::Runtime_state : public Runtime_info
{
return node.attribute_value("name", Start_name()) == elem.name;
}
static bool node_is_element(Xml_node node) { return node.has_type("child"); }
};
public:
@ -169,7 +182,7 @@ class Sculpt::Runtime_state : public Runtime_info
Info info(Start_name const &name) const
{
Info result { .selected = false, 0, 0, 0, 0 };
Info result { };
_children.for_each([&] (Child const &child) {
if (child.name == name)
result = child.info; });
@ -185,10 +198,42 @@ class Sculpt::Runtime_state : public Runtime_info
return result;
}
void toggle_selection(Start_name const &name)
void toggle_selection(Start_name const &name, Runtime_config const &config)
{
_children.for_each([&] (Child &child) {
child.info.selected = (child.name == name) && !child.info.selected; });
child.info.selected = (child.name == name) && !child.info.selected;
child.info.tcb = child.info.selected;
child.info.tcb_updated = false;
});
/*
* Update the TCB flag of the selected child's transitive
* dependencies.
*/
for (;;) {
Start_name name_of_updated { };
/*
* Search child that belongs to TCB but its dependencies
* have not been added to the TCB yet.
*/
_children.for_each([&] (Child &child) {
if (!name_of_updated.valid() && child.info.tcb && !child.info.tcb_updated) {
name_of_updated = child.name;
child.info.tcb_updated = true; /* skip in next iteration */
}
});
if (!name_of_updated.valid())
break;
/* tag all dependencies as part of the TCB */
config.for_each_dependency(name_of_updated, [&] (Start_name const &dep) {
_children.for_each([&] (Child &child) {
if (child.name == dep)
child.info.tcb = true; }); });
}
}
void abandon(Start_name const &name)