mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-09 04:15:52 +00:00
depot_deploy: support multiple runtimes
This patch changes the 'depot_deploy' tool to spawn any number of runtimes. In contrast to the original version, which merely consumed a blueprint generated by a pre-configured 'depot_query' instance, the new version actively generates queries as needed. So there is a feedback loop between 'depot_deploy' and 'depot_query'. The instantiation of subsystems is controlled by the '<start>' nodes of the 'depot_deploy' configuration. For each start node, the tool tries to determine the ingredients (provided by the depot) by asking the 'depot_query' tool. Once the information is complete, a corresponding start node of the dynamic init instance is generated.
This commit is contained in:
parent
3149506963
commit
d7522defde
@ -43,7 +43,8 @@ install_config {
|
||||
<provides> <service name="Report"/> <service name="ROM"/> </provides>
|
||||
<config verbose="yes">
|
||||
<policy label="depot_deploy -> blueprint" report="depot_query -> blueprint"/>
|
||||
<policy label="subinit -> config" report="depot_deploy -> init.config"/>
|
||||
<policy label="depot_query -> query" report="depot_deploy -> query"/>
|
||||
<policy label="dynamic -> config" report="depot_deploy -> init.config"/>
|
||||
</config>
|
||||
</start>
|
||||
|
||||
@ -64,20 +65,18 @@ install_config {
|
||||
|
||||
<start name="depot_query">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<config arch="} [depot_spec] {">
|
||||
<config query="rom">
|
||||
<vfs> <dir name="depot"> <fs label="depot"/> </dir> </vfs>
|
||||
<env>
|
||||
<rom label="ld.lib.so"/>
|
||||
<rom label="init"/>
|
||||
</env>
|
||||
<scan user="genodelabs"/>
|
||||
<blueprint pkg="genodelabs/pkg/} [query_pkg] {"/>
|
||||
</config>
|
||||
<route>
|
||||
<service name="ROM" label="query"> <child name="report_rom"/> </service>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</route>
|
||||
</start>
|
||||
|
||||
<start name="depot_deploy">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<config>
|
||||
<config arch="} [depot_spec] {">
|
||||
<static>
|
||||
<parent-provides>
|
||||
<service name="ROM"/>
|
||||
@ -95,6 +94,7 @@ install_config {
|
||||
<service name="LOG"> <parent/> </service>
|
||||
<service name="Timer"> <parent/> </service>
|
||||
</common_routes>
|
||||
<start name="test" pkg="genodelabs/pkg/} [query_pkg] {"/>
|
||||
</config>
|
||||
<route>
|
||||
<service name="ROM" label="blueprint"> <child name="report_rom"/> </service>
|
||||
@ -102,7 +102,7 @@ install_config {
|
||||
</route>
|
||||
</start>
|
||||
|
||||
<start name="subinit" caps="8000">
|
||||
<start name="dynamic" caps="8000">
|
||||
<resource name="RAM" quantum="64M"/>
|
||||
<binary name="init"/>
|
||||
<route>
|
||||
|
294
repos/gems/src/app/depot_deploy/child.h
Normal file
294
repos/gems/src/app/depot_deploy/child.h
Normal file
@ -0,0 +1,294 @@
|
||||
/*
|
||||
* \brief Child representation
|
||||
* \author Norman Feske
|
||||
* \date 2018-01-23
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2018 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#ifndef _CHILD_H_
|
||||
#define _CHILD_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/list_model.h>
|
||||
#include <base/service.h>
|
||||
#include <os/reporter.h>
|
||||
#include <os/buffered_xml.h>
|
||||
#include <depot/archive.h>
|
||||
|
||||
namespace Depot_deploy {
|
||||
using namespace Depot;
|
||||
struct Child;
|
||||
}
|
||||
|
||||
|
||||
class Depot_deploy::Child : public List_model<Child>::Element
|
||||
{
|
||||
public:
|
||||
|
||||
typedef String<100> Name;
|
||||
typedef String<80> Binary_name;
|
||||
typedef String<80> Config_name;
|
||||
|
||||
private:
|
||||
|
||||
Allocator &_alloc;
|
||||
|
||||
Reconstructible<Buffered_xml> _start_xml; /* from config */
|
||||
Constructible<Buffered_xml> _pkg_xml { }; /* from blueprint */
|
||||
|
||||
Name const _name;
|
||||
|
||||
Archive::Path _config_pkg_path() const
|
||||
{
|
||||
return _start_xml->xml().attribute_value("pkg", Archive::Path());
|
||||
}
|
||||
|
||||
/*
|
||||
* The pkg-archive path of the current blueprint query, which may
|
||||
* deviate from pkg path given in the config, once the config is
|
||||
* updated.
|
||||
*/
|
||||
Archive::Path _blueprint_pkg_path = _config_pkg_path();
|
||||
|
||||
Ram_quota _ram_quota { 0 };
|
||||
Cap_quota _cap_quota { 0 };
|
||||
Binary_name _binary_name { };
|
||||
Config_name _config_name { };
|
||||
|
||||
bool _configured() const
|
||||
{
|
||||
return _pkg_xml.constructed()
|
||||
&& (_config_pkg_path() == _blueprint_pkg_path);
|
||||
}
|
||||
|
||||
inline void _gen_routes(Xml_generator &, Xml_node common) const;
|
||||
|
||||
static void _gen_provides_sub_node(Xml_generator &xml, Xml_node service,
|
||||
Xml_node::Type const &node_type,
|
||||
Service::Name const &service_name)
|
||||
{
|
||||
if (service.type() == node_type)
|
||||
xml.node("service", [&] () {
|
||||
xml.attribute("name", service_name); });
|
||||
}
|
||||
|
||||
static void _gen_copy_of_sub_node(Xml_generator &xml, Xml_node from_node,
|
||||
Xml_node::Type const &sub_node_type)
|
||||
{
|
||||
if (!from_node.has_sub_node(sub_node_type.string()))
|
||||
return;
|
||||
|
||||
Xml_node const sub_node = from_node.sub_node(sub_node_type.string());
|
||||
xml.append(sub_node.addr(), sub_node.size());
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Child(Allocator &alloc, Xml_node start_node)
|
||||
:
|
||||
_alloc(alloc),
|
||||
_start_xml(_alloc, start_node),
|
||||
_name(_start_xml->xml().attribute_value("name", Name()))
|
||||
{ }
|
||||
|
||||
Name name() const { return _name; }
|
||||
|
||||
void apply_config(Xml_node start_node)
|
||||
{
|
||||
/*
|
||||
* String-compare new with current start node to quicky skip
|
||||
* the start nodes that have not changed.
|
||||
*/
|
||||
bool const start_node_changed =
|
||||
(start_node.size() != _start_xml->xml().size()) ||
|
||||
(strcmp(start_node.addr(), _start_xml->xml().addr(),
|
||||
start_node.size()) != 0);
|
||||
|
||||
if (!start_node_changed)
|
||||
return;
|
||||
|
||||
Archive::Path const pkg =
|
||||
start_node.attribute_value("pkg", Archive::Path());
|
||||
|
||||
/* invalidate blueprint if 'pkg' attribute of start node changed */
|
||||
if (pkg != _config_pkg_path())
|
||||
_pkg_xml.destruct();
|
||||
|
||||
/* import new start node */
|
||||
_start_xml.construct(_alloc, start_node);
|
||||
}
|
||||
|
||||
void apply_blueprint(Xml_node pkg)
|
||||
{
|
||||
if (pkg.attribute_value("path", Archive::Path()) != _blueprint_pkg_path)
|
||||
return;
|
||||
|
||||
Xml_node const runtime = pkg.sub_node("runtime");
|
||||
|
||||
_ram_quota = Ram_quota { runtime.attribute_value("ram", Number_of_bytes()) };
|
||||
_cap_quota = Cap_quota { runtime.attribute_value("caps", 0UL) };
|
||||
|
||||
_binary_name = runtime.attribute_value("binary", Binary_name());
|
||||
_config_name = runtime.attribute_value("config", Config_name());
|
||||
|
||||
/* keep copy of the blueprint info */
|
||||
_pkg_xml.construct(_alloc, pkg);
|
||||
}
|
||||
|
||||
void gen_query(Xml_generator &xml) const
|
||||
{
|
||||
if (_configured())
|
||||
return;
|
||||
|
||||
xml.node("blueprint", [&] () {
|
||||
xml.attribute("pkg", _blueprint_pkg_path); });
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate start node of init configuration
|
||||
*
|
||||
* \param common session routes to be added in addition to the ones
|
||||
* found in the pkg blueprint
|
||||
*/
|
||||
inline void gen_start_node(Xml_generator &, Xml_node common) const;
|
||||
};
|
||||
|
||||
|
||||
void Depot_deploy::Child::gen_start_node(Xml_generator &xml, Xml_node common) const
|
||||
{
|
||||
if (!_configured())
|
||||
return;
|
||||
|
||||
if (!_pkg_xml->xml().has_sub_node("runtime")) {
|
||||
warning("blueprint for '", _name, "' lacks runtime information");
|
||||
return;
|
||||
}
|
||||
|
||||
xml.node("start", [&] () {
|
||||
|
||||
xml.attribute("name", _name);
|
||||
xml.attribute("caps", _cap_quota.value);
|
||||
|
||||
xml.node("binary", [&] () { xml.attribute("name", _binary_name); });
|
||||
|
||||
xml.node("resource", [&] () {
|
||||
xml.attribute("name", "RAM");
|
||||
xml.attribute("quantum", String<32>(Number_of_bytes(_ram_quota.value)));
|
||||
});
|
||||
|
||||
Xml_node const runtime = _pkg_xml->xml().sub_node("runtime");
|
||||
|
||||
/*
|
||||
* Insert inline '<config>' node if provided by the start node or the
|
||||
* blueprint. The former is preferred over the latter.
|
||||
*/
|
||||
if (_start_xml->xml().has_sub_node("config")) {
|
||||
_gen_copy_of_sub_node(xml, _start_xml->xml(), "config");
|
||||
} else {
|
||||
if (runtime.has_sub_node("config"))
|
||||
_gen_copy_of_sub_node(xml, runtime, "config");
|
||||
}
|
||||
|
||||
/*
|
||||
* Declare services provided by the subsystem.
|
||||
*/
|
||||
if (runtime.has_sub_node("provides")) {
|
||||
xml.node("provides", [&] () {
|
||||
runtime.sub_node("provides").for_each_sub_node([&] (Xml_node service) {
|
||||
_gen_provides_sub_node(xml, service, "rom", "ROM");
|
||||
_gen_provides_sub_node(xml, service, "log", "LOG");
|
||||
_gen_provides_sub_node(xml, service, "timer", "Timer");
|
||||
_gen_provides_sub_node(xml, service, "block", "Block");
|
||||
_gen_provides_sub_node(xml, service, "report", "Report");
|
||||
_gen_provides_sub_node(xml, service, "nic", "Nic");
|
||||
_gen_provides_sub_node(xml, service, "nitpicker", "Nitpicker");
|
||||
_gen_provides_sub_node(xml, service, "framebuffer", "Framebuffer");
|
||||
_gen_provides_sub_node(xml, service, "input", "Input");
|
||||
_gen_provides_sub_node(xml, service, "audio_out", "Audio_out");
|
||||
_gen_provides_sub_node(xml, service, "audio_in", "Audio_in");
|
||||
_gen_provides_sub_node(xml, service, "file_system", "File_system");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
xml.node("route", [&] () { _gen_routes(xml, common); });
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void Depot_deploy::Child::_gen_routes(Xml_generator &xml, Xml_node common) const
|
||||
{
|
||||
if (!_pkg_xml.constructed())
|
||||
return;
|
||||
|
||||
typedef String<160> Path;
|
||||
|
||||
/*
|
||||
* Add routes given in the start node.
|
||||
*/
|
||||
if (_start_xml->xml().has_sub_node("route")) {
|
||||
Xml_node const route = _start_xml->xml().sub_node("route");
|
||||
xml.append(route.content_base(), route.content_size());
|
||||
}
|
||||
|
||||
/*
|
||||
* Redirect config ROM request to label as given in the 'config' attribute,
|
||||
* if present. We need to search the blueprint's <rom> nodes for the
|
||||
* matching ROM module to rewrite the label with the configuration's path
|
||||
* within the depot.
|
||||
*/
|
||||
if (_config_name.valid()) {
|
||||
_pkg_xml->xml().for_each_sub_node("rom", [&] (Xml_node rom) {
|
||||
|
||||
if (!rom.has_attribute("path"))
|
||||
return;
|
||||
|
||||
if (rom.attribute_value("label", Name()) != _config_name)
|
||||
return;
|
||||
|
||||
/* we found the <rom> node for the config ROM */
|
||||
xml.node("service", [&] () {
|
||||
xml.attribute("name", "ROM");
|
||||
xml.attribute("label", "config");
|
||||
xml.node("parent", [&] () {
|
||||
typedef String<160> Path;
|
||||
xml.attribute("label", rom.attribute_value("path", Path()));
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* Add common routes as defined in our config.
|
||||
*/
|
||||
xml.append(common.content_base(), common.content_size());
|
||||
|
||||
/*
|
||||
* Add ROM routing rule with the label rewritten to the path within the
|
||||
* depot.
|
||||
*/
|
||||
_pkg_xml->xml().for_each_sub_node("rom", [&] (Xml_node rom) {
|
||||
|
||||
if (!rom.has_attribute("path"))
|
||||
return;
|
||||
|
||||
typedef Name Label;
|
||||
Path const path = rom.attribute_value("path", Path());
|
||||
Label const label = rom.attribute_value("label", Label());
|
||||
|
||||
xml.node("service", [&] () {
|
||||
xml.attribute("name", "ROM");
|
||||
xml.attribute("label_last", label);
|
||||
xml.node("parent", [&] () {
|
||||
xml.attribute("label", path); });
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
#endif /* _CHILD_H_ */
|
@ -12,16 +12,83 @@
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/retry.h>
|
||||
#include <base/component.h>
|
||||
#include <base/attached_rom_dataspace.h>
|
||||
#include <base/heap.h>
|
||||
#include <os/reporter.h>
|
||||
|
||||
/* local includes */
|
||||
#include "child.h"
|
||||
|
||||
namespace Depot_deploy {
|
||||
using namespace Genode;
|
||||
struct Children;
|
||||
struct Main;
|
||||
}
|
||||
|
||||
|
||||
class Depot_deploy::Children
|
||||
{
|
||||
private:
|
||||
|
||||
Allocator &_alloc;
|
||||
|
||||
List_model<Child> _children { };
|
||||
|
||||
struct Model_update_policy : List_model<Child>::Update_policy
|
||||
{
|
||||
Allocator &_alloc;
|
||||
|
||||
Model_update_policy(Allocator &alloc) : _alloc(alloc) { }
|
||||
|
||||
void destroy_element(Child &c) { destroy(_alloc, &c); }
|
||||
|
||||
Child &create_element(Xml_node node)
|
||||
{
|
||||
return *new (_alloc) Child(_alloc, node);
|
||||
}
|
||||
|
||||
void update_element(Child &c, Xml_node node) { c.apply_config(node); }
|
||||
|
||||
static bool element_matches_xml_node(Child const &child, Xml_node node)
|
||||
{
|
||||
return node.attribute_value("name", Child::Name()) == child.name();
|
||||
}
|
||||
|
||||
static bool node_is_element(Xml_node node) { return node.has_type("start"); }
|
||||
|
||||
} _model_update_policy { _alloc };
|
||||
|
||||
public:
|
||||
|
||||
Children(Allocator &alloc) : _alloc(alloc) { }
|
||||
|
||||
void apply_config(Xml_node config)
|
||||
{
|
||||
_children.update_from_xml(_model_update_policy, config);
|
||||
}
|
||||
|
||||
void apply_blueprint(Xml_node blueprint)
|
||||
{
|
||||
blueprint.for_each_sub_node("pkg", [&] (Xml_node pkg) {
|
||||
_children.for_each([&] (Child &child) {
|
||||
child.apply_blueprint(pkg); }); });
|
||||
}
|
||||
|
||||
void gen_start_nodes(Xml_generator &xml, Xml_node common)
|
||||
{
|
||||
_children.for_each([&] (Child const &child) {
|
||||
child.gen_start_node(xml, common); });
|
||||
}
|
||||
|
||||
void gen_queries(Xml_generator &xml)
|
||||
{
|
||||
_children.for_each([&] (Child const &child) {
|
||||
child.gen_query(xml); });
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Depot_deploy::Main
|
||||
{
|
||||
Env &_env;
|
||||
@ -29,67 +96,55 @@ struct Depot_deploy::Main
|
||||
Attached_rom_dataspace _config { _env, "config" };
|
||||
Attached_rom_dataspace _blueprint { _env, "blueprint" };
|
||||
|
||||
Reporter _init_config_reporter { _env, "config", "init.config", 16*1024 };
|
||||
Expanding_reporter _query_reporter { _env, "query" , "query"};
|
||||
Expanding_reporter _init_config_reporter { _env, "config", "init.config"};
|
||||
|
||||
size_t _query_buffer_size = 4096;
|
||||
size_t _init_config_buffer_size = 4096;
|
||||
|
||||
Heap _heap { _env.ram(), _env.rm() };
|
||||
|
||||
Children _children { _heap };
|
||||
|
||||
Signal_handler<Main> _config_handler {
|
||||
_env.ep(), *this, &Main::_handle_config };
|
||||
|
||||
typedef String<128> Name;
|
||||
typedef String<80> Binary;
|
||||
typedef String<80> Config;
|
||||
|
||||
/**
|
||||
* Generate start node of init configuration
|
||||
*
|
||||
* \param pkg pkg node of the subsystem blueprint
|
||||
* \param common session routes to be added in addition to the ones
|
||||
* found in the pkg blueprint
|
||||
*/
|
||||
static void _gen_start_node(Xml_generator &, Xml_node pkg, Xml_node common);
|
||||
|
||||
void _handle_config()
|
||||
{
|
||||
_config.update();
|
||||
_blueprint.update();
|
||||
|
||||
Xml_node const config = _config.xml();
|
||||
Xml_node const blueprint = _blueprint.xml();
|
||||
Xml_node const config = _config.xml();
|
||||
|
||||
Reporter::Xml_generator xml(_init_config_reporter, [&] () {
|
||||
_children.apply_config(config);
|
||||
_children.apply_blueprint(_blueprint.xml());
|
||||
|
||||
/* determine CPU architecture of deployment */
|
||||
typedef String<16> Arch;
|
||||
Arch const arch = config.attribute_value("arch", Arch());
|
||||
if (!arch.valid())
|
||||
warning("config lacks 'arch' attribute");
|
||||
|
||||
/* generate init config containing all configured start nodes */
|
||||
_init_config_reporter.generate([&] (Xml_generator &xml) {
|
||||
Xml_node static_config = config.sub_node("static");
|
||||
xml.append(static_config.content_base(), static_config.content_size());
|
||||
|
||||
blueprint.for_each_sub_node("pkg", [&] (Xml_node pkg) {
|
||||
|
||||
/*
|
||||
* Check preconditions for generating a '<start>' node.
|
||||
*/
|
||||
Name const name = pkg.attribute_value("name", Name());
|
||||
|
||||
if (!pkg.has_sub_node("runtime")) {
|
||||
warning("<pkg> node for '", name, "' lacks <runtime> node");
|
||||
return;
|
||||
}
|
||||
|
||||
Xml_node const runtime = pkg.sub_node("runtime");
|
||||
|
||||
if (!runtime.has_attribute("binary")) {
|
||||
warning("<runtime> node for '", name, "' lacks 'binary' attribute");
|
||||
return;
|
||||
}
|
||||
|
||||
xml.node("start", [&] () {
|
||||
_gen_start_node(xml, pkg, config.sub_node("common_routes"));
|
||||
});
|
||||
});
|
||||
_children.gen_start_nodes(xml, config.sub_node("common_routes"));
|
||||
});
|
||||
|
||||
/* update query for blueprints of all unconfigured start nodes */
|
||||
if (arch.valid()) {
|
||||
_query_reporter.generate([&] (Xml_generator &xml) {
|
||||
xml.attribute("arch", arch);
|
||||
_children.gen_queries(xml);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Main(Env &env) : _env(env)
|
||||
{
|
||||
_init_config_reporter.enabled(true);
|
||||
|
||||
_config .sigh(_config_handler);
|
||||
_blueprint.sigh(_config_handler);
|
||||
|
||||
@ -98,80 +153,5 @@ struct Depot_deploy::Main
|
||||
};
|
||||
|
||||
|
||||
void Depot_deploy::Main::_gen_start_node(Xml_generator &xml, Xml_node pkg, Xml_node common)
|
||||
{
|
||||
typedef String<80> Name;
|
||||
|
||||
Name const name = pkg.attribute_value("name", Name());
|
||||
Xml_node const runtime = pkg.sub_node("runtime");
|
||||
size_t const caps = runtime.attribute_value("caps", 0UL);
|
||||
Number_of_bytes const ram = runtime.attribute_value("ram", Number_of_bytes());
|
||||
Binary const binary = runtime.attribute_value("binary", Binary());
|
||||
Config const config = runtime.attribute_value("config", Config());
|
||||
|
||||
xml.attribute("name", name);
|
||||
xml.attribute("caps", caps);
|
||||
|
||||
xml.node("binary", [&] () { xml.attribute("name", binary); });
|
||||
|
||||
xml.node("resource", [&] () {
|
||||
xml.attribute("name", "RAM");
|
||||
xml.attribute("quantum", String<32>(ram));
|
||||
});
|
||||
|
||||
/*
|
||||
* Insert inline '<config>' node if provided by the blueprint.
|
||||
*/
|
||||
if (runtime.has_sub_node("config")) {
|
||||
Xml_node config = runtime.sub_node("config");
|
||||
xml.node("config", [&] () {
|
||||
xml.append(config.content_base(), config.content_size()); });
|
||||
};
|
||||
|
||||
xml.node("route", [&] () {
|
||||
|
||||
/*
|
||||
* Redirect config ROM request to label given in the 'config'
|
||||
* attribute.
|
||||
*/
|
||||
if (config.valid()) {
|
||||
xml.node("service", [&] () {
|
||||
xml.attribute("name", "ROM");
|
||||
xml.attribute("label", "config");
|
||||
xml.node("parent", [&] () {
|
||||
xml.attribute("label", config); });
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* Add common routes as defined in our config.
|
||||
*/
|
||||
xml.append(common.content_base(), common.content_size());
|
||||
|
||||
/*
|
||||
* Add ROM routing rule with the label rewritten to
|
||||
* the path within the depot.
|
||||
*/
|
||||
pkg.for_each_sub_node("rom", [&] (Xml_node rom) {
|
||||
|
||||
if (!rom.has_attribute("path"))
|
||||
return;
|
||||
|
||||
typedef String<160> Path;
|
||||
typedef Name Label;
|
||||
Path const path = rom.attribute_value("path", Path());
|
||||
Label const label = rom.attribute_value("label", Label());
|
||||
|
||||
xml.node("service", [&] () {
|
||||
xml.attribute("name", "ROM");
|
||||
xml.attribute("label_last", label);
|
||||
xml.node("parent", [&] () {
|
||||
xml.attribute("label", path); });
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void Component::construct(Genode::Env &env) { static Depot_deploy::Main main(env); }
|
||||
|
||||
|
@ -1,5 +1,3 @@
|
||||
TARGET = depot_deploy
|
||||
SRC_CC = main.cc
|
||||
LIBS += base vfs
|
||||
|
||||
CC_CXX_WARN_STRICT =
|
||||
LIBS += base
|
||||
|
@ -161,10 +161,25 @@ struct Depot_query::Main
|
||||
Signal_handler<Main> _config_handler {
|
||||
_env.ep(), *this, &Main::_handle_config };
|
||||
|
||||
Reporter _directory_reporter { _env, "directory" };
|
||||
Reporter _blueprint_reporter { _env, "blueprint" };
|
||||
Reporter _dependencies_reporter { _env, "dependencies" };
|
||||
Reporter _user_reporter { _env, "user" };
|
||||
Signal_handler<Main> _query_handler {
|
||||
_env.ep(), *this, &Main::_handle_config };
|
||||
|
||||
typedef Constructible<Expanding_reporter> Constructible_reporter;
|
||||
|
||||
Constructible_reporter _directory_reporter { _env, "directory" };
|
||||
Constructible_reporter _blueprint_reporter { _env, "blueprint" };
|
||||
Constructible_reporter _dependencies_reporter { _env, "dependencies" };
|
||||
Constructible_reporter _user_reporter { _env, "user" };
|
||||
|
||||
template <typename T, typename... ARGS>
|
||||
static void _construct_if(bool condition, Constructible<T> &obj, ARGS &&... args)
|
||||
{
|
||||
if (condition && !obj.constructed())
|
||||
obj.construct(args...);
|
||||
|
||||
if (!condition && obj.constructed())
|
||||
obj.destruct();
|
||||
}
|
||||
|
||||
typedef String<64> Rom_label;
|
||||
typedef String<16> Architecture;
|
||||
@ -205,7 +220,7 @@ struct Depot_query::Main
|
||||
|
||||
if (query_from_rom && !_query_rom.constructed()) {
|
||||
_query_rom.construct(_env, "query");
|
||||
_query_rom->sigh(_config_handler);
|
||||
_query_rom->sigh(_query_handler);
|
||||
}
|
||||
|
||||
if (!query_from_rom && _query_rom.constructed())
|
||||
@ -216,20 +231,31 @@ struct Depot_query::Main
|
||||
|
||||
Xml_node const query = (query_from_rom ? _query_rom->xml() : config);
|
||||
|
||||
_directory_reporter .enabled(query.has_sub_node("scan"));
|
||||
_blueprint_reporter .enabled(query.has_sub_node("blueprint"));
|
||||
_dependencies_reporter.enabled(query.has_sub_node("dependencies"));
|
||||
_user_reporter .enabled(query.has_sub_node("user"));
|
||||
_construct_if(query.has_sub_node("scan"),
|
||||
_directory_reporter, _env, "directory", "directory");
|
||||
|
||||
_construct_if(query.has_sub_node("blueprint"),
|
||||
_blueprint_reporter, _env, "blueprint", "blueprint");
|
||||
|
||||
_construct_if(query.has_sub_node("dependencies"),
|
||||
_dependencies_reporter, _env, "dependencies", "dependencies");
|
||||
|
||||
_construct_if(query.has_sub_node("user"),
|
||||
_user_reporter, _env, "user", "user");
|
||||
|
||||
_root.apply_config(config.sub_node("vfs"));
|
||||
|
||||
/* ignore incomplete queries that may occur at the startup */
|
||||
if (query.has_type("empty"))
|
||||
return;
|
||||
|
||||
if (!query.has_attribute("arch"))
|
||||
warning("query lacks 'arch' attribute");
|
||||
|
||||
_architecture = query.attribute_value("arch", Architecture());
|
||||
|
||||
if (_directory_reporter.enabled()) {
|
||||
Reporter::Xml_generator xml(_directory_reporter, [&] () {
|
||||
if (_directory_reporter.constructed()) {
|
||||
_directory_reporter->generate([&] (Xml_generator &xml) {
|
||||
query.for_each_sub_node("scan", [&] (Xml_node node) {
|
||||
Archive::User const user = node.attribute_value("user", Archive::User());
|
||||
Directory::Path path("depot/", user, "/pkg");
|
||||
@ -239,11 +265,13 @@ struct Depot_query::Main
|
||||
});
|
||||
}
|
||||
|
||||
if (_blueprint_reporter.enabled()) {
|
||||
Reporter::Xml_generator xml(_blueprint_reporter, [&] () {
|
||||
if (_blueprint_reporter.constructed()) {
|
||||
_blueprint_reporter->generate([&] (Xml_generator &xml) {
|
||||
query.for_each_sub_node("blueprint", [&] (Xml_node node) {
|
||||
Archive::Path pkg = node.attribute_value("pkg", Archive::Path());
|
||||
try { _query_blueprint(pkg, xml); }
|
||||
catch (Xml_generator::Buffer_exceeded) {
|
||||
throw; /* handled by 'generate' */ }
|
||||
catch (...) {
|
||||
warning("could not obtain blueprint for '", pkg, "'");
|
||||
}
|
||||
@ -251,8 +279,8 @@ struct Depot_query::Main
|
||||
});
|
||||
}
|
||||
|
||||
if (_dependencies_reporter.enabled()) {
|
||||
Reporter::Xml_generator xml(_dependencies_reporter, [&] () {
|
||||
if (_dependencies_reporter.constructed()) {
|
||||
_dependencies_reporter->generate([&] (Xml_generator &xml) {
|
||||
Dependencies dependencies(_heap, _depot_dir);
|
||||
query.for_each_sub_node("dependencies", [&] (Xml_node node) {
|
||||
|
||||
@ -268,8 +296,8 @@ struct Depot_query::Main
|
||||
});
|
||||
}
|
||||
|
||||
if (_user_reporter.enabled()) {
|
||||
Reporter::Xml_generator xml(_user_reporter, [&] () {
|
||||
if (_user_reporter.constructed()) {
|
||||
_user_reporter->generate([&] (Xml_generator &xml) {
|
||||
query.for_each_sub_node("user", [&] (Xml_node node) {
|
||||
_query_user(node.attribute_value("name", Archive::User()), xml); });
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user