From 9dca1503a85e5b0a96ff83cf5ce97693cf4e643c Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Fri, 3 Mar 2017 12:50:29 +0100 Subject: [PATCH] init: apply changes of nodes This patch enables init to apply changes of any server's declarations in a differential way. Servers can in principle be extended by new services without re-starting them. Of course, changes of the declarations may affect clients or would-be clients as this information is taken into account for the session routing. --- repos/os/include/init/child.h | 118 +++++++++++++++++++++++++++------ repos/os/run/init.run | 105 +++++++++++++++++++++++++++++ repos/os/src/test/init/main.cc | 11 ++- 3 files changed, 213 insertions(+), 21 deletions(-) diff --git a/repos/os/include/init/child.h b/repos/os/include/init/child.h index ad21b4a396..530f78b28b 100644 --- a/repos/os/include/init/child.h +++ b/repos/os/include/init/child.h @@ -658,6 +658,49 @@ class Init::Child : Child_policy, Child_service::Wakeup catch (Parent::Service_denied) { return false; } } + static Xml_node _provides_sub_node(Xml_node start_node) + { + return start_node.has_sub_node("provides") + ? start_node.sub_node("provides") : Xml_node(""); + } + + /** + * Return true if service is provided by this child + */ + bool _provided_by_this(Routed_service const &service) + { + return service.has_id_space(_session_requester.id_space()); + } + + /** + * Return true if service of specified sub node is known + */ + bool _service_exists(Xml_node node) const + { + bool exists = false; + _child_services.for_each([&] (Routed_service const &service) { + if (_provided_by_this(service) && + service.name() == node.attribute_value("name", Service::Name())) + exists = true; }); + + return exists; + } + + void _add_service(Xml_node service) + { + Service::Name const name = + service.attribute_value("name", Service::Name()); + + if (_verbose.enabled()) + log(" provides service ", name); + + new (_alloc) + Routed_service(_child_services, this->name(), _ram_accessor, + _session_requester.id_space(), + _child.session_factory(), + name, *this); + } + public: /** @@ -719,25 +762,9 @@ class Init::Child : Child_policy, Child_service::Wakeup /* * Determine services provided by the child */ - try { - Xml_node service_node = start_node.sub_node("provides").sub_node("service"); - - for (; ; service_node = service_node.next("service")) { - - char name[Service::Name::capacity()]; - service_node.attribute("name").value(name, sizeof(name)); - - if (_verbose.enabled()) - log(" provides service ", Cstring(name)); - - new (_alloc) - Routed_service(child_services, this->name(), _ram_accessor, - _session_requester.id_space(), - _child.session_factory(), - name, *this); - } - } - catch (Xml_node::Nonexistent_sub_node) { } + _provides_sub_node(start_node) + .for_each_sub_node("service", + [&] (Xml_node node) { _add_service(node); }); /* * Construct inline config ROM service if "config" node is present. @@ -812,6 +839,17 @@ class Init::Child : Child_policy, Child_service::Wakeup if (_state == STATE_ABANDONED) return NO_SIDE_EFFECTS; + /* + * If the child's environment is incomplete, restart it to attempt + * the re-routing of its environment sessions. + */ + if (!_child.active()) { + abandon(); + return MAY_HAVE_SIDE_EFFECTS; + } + + bool provided_services_changed = false; + enum Config_update { CONFIG_APPEARED, CONFIG_VANISHED, CONFIG_CHANGED, CONFIG_UNCHANGED }; @@ -856,6 +894,41 @@ class Init::Child : Child_policy, Child_service::Wakeup config_update = CONFIG_CHANGED; } + /* + * Import updated node + * + * First abandon services that are no longer present in the + * node. Then add services that have newly appeared. + */ + _child_services.for_each([&] (Routed_service &service) { + + if (!_provided_by_this(service)) + return; + + typedef Service::Name Name; + Name const name = service.name(); + + bool still_provided = false; + _provides_sub_node(start_node) + .for_each_sub_node("service", [&] (Xml_node node) { + if (name == node.attribute_value("name", Name())) + still_provided = true; }); + + if (!still_provided) { + service.abandon(); + provided_services_changed = true; + } + }); + + _provides_sub_node(start_node).for_each_sub_node("service", + [&] (Xml_node node) { + if (_service_exists(node)) + return; + + _add_service(node); + provided_services_changed = true; + }); + /* * Import new binary name. A change may affect the route for * the binary's ROM session, triggering the restart of the @@ -892,6 +965,10 @@ class Init::Child : Child_policy, Child_service::Wakeup return MAY_HAVE_SIDE_EFFECTS; } } + + if (provided_services_changed) + return MAY_HAVE_SIDE_EFFECTS; + return NO_SIDE_EFFECTS; } @@ -908,6 +985,9 @@ class Init::Child : Child_policy, Child_service::Wakeup if (detail.ids()) xml.attribute("id", _id.value); + if (!_child.active()) + xml.attribute("state", "incomplete"); + if (detail.child_ram() && _child.ram_session_cap().valid()) { xml.node("ram", [&] () { /* diff --git a/repos/os/run/init.run b/repos/os/run/init.run index 0768b06cc3..b022f21297 100644 --- a/repos/os/run/init.run +++ b/repos/os/run/init.run @@ -200,6 +200,111 @@ append config { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/repos/os/src/test/init/main.cc b/repos/os/src/test/init/main.cc index 4bccff519d..55d2ff29a7 100644 --- a/repos/os/src/test/init/main.cc +++ b/repos/os/src/test/init/main.cc @@ -178,6 +178,8 @@ struct Test::Main : Log_message_handler Timer::Connection _timer { _env }; + bool _timer_scheduled = false; + Reporter _init_config_reporter { _env, "config", "init.config" }; Attached_rom_dataspace _config { _env, "config" }; @@ -269,8 +271,11 @@ struct Test::Main : Log_message_handler } if (step.type() == "sleep") { - unsigned long const timeout_ms = step.attribute_value("ms", 250UL); - _timer.trigger_once(timeout_ms*1000); + if (!_timer_scheduled) { + unsigned long const timeout_ms = step.attribute_value("ms", 250UL); + _timer.trigger_once(timeout_ms*1000); + _timer_scheduled = true; + } return; } @@ -311,6 +316,8 @@ struct Test::Main : Log_message_handler throw Exception(); } + _timer_scheduled = false; + _advance_step(); _execute_curr_step(); }