base: Add Child_policy::Route

The new return value of 'resolve_session_request' allows the child
policy to define the label used as the policy selector at the server.

Because this patch introduces the distinction of the child-provided
label from the label as presented to the server along with the session
request, the latter is now handled as a dedicated 'Session_state'
argument.

Issue #2248
This commit is contained in:
Norman Feske 2017-02-14 17:38:09 +01:00 committed by Christian Helmuth
parent 2d199982eb
commit c0af463b81
8 changed files with 110 additions and 18 deletions

View File

@ -69,11 +69,38 @@ struct Genode::Child_policy
* Determine service to provide a session request
*
* \return service to be contacted for the new session
* \deprecated
*
* \throw Parent::Service_denied
*/
virtual Service &resolve_session_request(Service::Name const &,
Session_state::Args const &) = 0;
Session_state::Args const &)
{
throw Parent::Service_denied();
}
/**
* Routing destination of a session request
*/
struct Route
{
Service &service;
Session_label const label;
};
/**
* Determine service and server-side label for a given session request
*
* \return routing and policy-selection information for the session
*
* \throw Parent::Service_denied
*/
virtual Route resolve_session_request(Service::Name const &,
Session_label const &)
{
/* \deprecated make pure virtual once the old version is gone */
throw Parent::Service_denied();
}
/**
* Apply transformations to session arguments
@ -271,6 +298,9 @@ class Genode::Child : protected Rpc_object<Parent>,
typedef Session_state::Args Args;
static Child_policy::Route _resolve_session_request(Child_policy &,
Service::Name const &,
char const *);
/*
* Members that are initialized not before the child's environment is
* complete.
@ -370,7 +400,7 @@ class Genode::Child : protected Rpc_object<Parent>,
Args const _args;
Service &_service;
Child_policy::Route _route;
/*
* The 'Env_service' monitors session responses in order to attempt
@ -439,8 +469,9 @@ class Genode::Child : protected Rpc_object<Parent>,
Label const &label = Label())
:
_args(_construct_args(child._policy, label)),
_service(child._policy.resolve_session_request(_service_name(), _args)),
_env_service(child, _service),
_route(child._resolve_session_request(child._policy, _service_name(),
_args.string())),
_env_service(child, _route.service),
_connection(_env_service, child._id_space, id, _args,
child._policy.filter_session_affinity(Affinity()))
{ }

View File

@ -60,8 +60,8 @@ struct Genode::Local_connection_base : Noncopyable
Args const &args, Affinity const &affinity,
size_t ram_quota)
:
_session_state(service, id_space, id, _init_args(args, ram_quota),
affinity)
_session_state(service, id_space, id, label_from_args(args.string()),
_init_args(args, ram_quota), affinity)
{
_session_state.service().initiate_request(_session_state);
}

View File

@ -192,7 +192,7 @@ class Genode::Local_service : public Service
case Session_state::CREATE_REQUESTED:
try {
SESSION &rpc_obj = _factory.create(session.args(),
SESSION &rpc_obj = _factory.create(Session_state::Server_args(session).string(),
session.affinity());
session.local_ptr = &rpc_obj;
session.cap = rpc_obj.cap();
@ -272,9 +272,10 @@ class Genode::Parent_service : public Service
session.id_at_parent.construct(session.parent_client,
_env.id_space());
try {
session.cap = _env.session(name().string(),
session.id_at_parent->id(),
session.args().string(),
Session_state::Server_args(session).string(),
session.affinity());
session.phase = Session_state::AVAILABLE;

View File

@ -21,6 +21,7 @@
#include <base/id_space.h>
#include <base/env.h>
#include <base/log.h>
#include <base/session_label.h>
namespace Genode {
@ -62,8 +63,9 @@ class Genode::Session_state : public Parent::Client, public Parent::Server,
Reconstructible<Id_space<Parent::Client>::Element> _id_at_client;
Args _args;
Affinity _affinity;
Session_label const _label;
Args _args;
Affinity _affinity;
public:
@ -110,15 +112,22 @@ class Genode::Session_state : public Parent::Client, public Parent::Server,
* Constructor
*
* \param service interface that was used to create the session
* \param label session label to be presented to the server
* \param client_id_space ID space for client-side session IDs
* \param client_id session ID picked by the client
* \param args session arguments
*
* \throw Id_space<Parent::Client>::Conflicting_id
*
* The client-provided (and child-name-prefixed) session label is
* contained in 'args'. In contrast, the 'label' argument is the label
* presented to the server along with the session request, which
* depends on the policy of 'Child_policy::resolve_session_request'.
*/
Session_state(Service &service,
Id_space<Parent::Client> &client_id_space,
Parent::Client::Id client_id,
Session_label const &label,
Args const &args,
Affinity const &affinity);
@ -195,6 +204,24 @@ class Genode::Session_state : public Parent::Client, public Parent::Server,
* This function has no effect for sessions not created via a 'Factory'.
*/
void destroy();
/**
* Utility to override the client-provided label by the label assigned
* by 'Child_policy::resolve_session_request'.
*/
struct Server_args
{
char _buf[Args::capacity()];
Server_args(Session_state const &session)
{
Genode::strncpy(_buf, session._args.string(), sizeof(_buf));
Arg_string::set_arg_string(_buf, sizeof(_buf),
"label", session._label.string());
}
char const *string() const { return _buf; }
};
};

View File

@ -85,8 +85,8 @@ _ZN6Genode13Registry_base7_insertERNS0_7ElementE T
_ZN6Genode13Registry_base7_removeERNS0_7ElementE T
_ZN6Genode13Registry_base9_for_eachERNS0_15Untyped_functorE T
_ZN6Genode13Session_state7destroyEv T
_ZN6Genode13Session_stateC1ERNS_7ServiceERNS_8Id_spaceINS_6Parent6ClientEEENS6_2IdERKNS_6StringILm256EEERKNS_8AffinityE T
_ZN6Genode13Session_stateC2ERNS_7ServiceERNS_8Id_spaceINS_6Parent6ClientEEENS6_2IdERKNS_6StringILm256EEERKNS_8AffinityE T
_ZN6Genode13Session_stateC1ERNS_7ServiceERNS_8Id_spaceINS_6Parent6ClientEEENS6_2IdERKNS_13Session_labelERKNS_6StringILm256EEERKNS_8AffinityE T
_ZN6Genode13Session_stateC2ERNS_7ServiceERNS_8Id_spaceINS_6Parent6ClientEEENS6_2IdERKNS_13Session_labelERKNS_6StringILm256EEERKNS_8AffinityE T
_ZN6Genode13Shared_objectC1ERNS_3EnvERNS_9AllocatorEPKcNS0_4BindENS0_4KeepE T
_ZN6Genode13Shared_objectC2ERNS_3EnvERNS_9AllocatorEPKcNS0_4BindENS0_4KeepE T
_ZN6Genode13Shared_objectD1Ev T

View File

@ -94,7 +94,8 @@ Session_capability Core_parent::session(Parent::Client::Id id,
return;
Session_state &session = *new (_alloc)
Session_state(service, _id_space, id, args.string(), affinity);
Session_state(service, _id_space, id, label_from_args(args.string()),
args.string(), affinity);
service.initiate_request(session);

View File

@ -156,12 +156,13 @@ void Child::session_sigh(Signal_context_capability sigh)
*/
Session_state &
create_session(Child_policy::Name const &child_name, Service &service,
Session_label const &label,
Session_state::Factory &factory, Id_space<Parent::Client> &id_space,
Parent::Client::Id id, Session_state::Args const &args,
Affinity const &affinity)
{
try {
return service.create_session(factory, id_space, id, args, affinity);
return service.create_session(factory, id_space, id, label, args, affinity);
}
catch (Allocator::Out_of_memory) {
error("could not allocate session meta data for child ", child_name);
@ -179,6 +180,34 @@ create_session(Child_policy::Name const &child_name, Service &service,
}
/*
* \deprecated Temporary wrapper around 'Child_policy::resolve_session_request'
* that tries both overloads.
*
* \throw Parent::Service_denied
*/
Child_policy::Route Child::_resolve_session_request(Child_policy &policy,
Service::Name const &name,
char const *argbuf)
{
Session_label const label = label_from_args(argbuf);
/*
* \deprecated Try old interface, remove once all 'Child_policy'
* implementations are updated.
*/
try {
Session_state::Args args(argbuf);
return Child_policy::Route {
policy.resolve_session_request(name, args), label };
}
catch (Parent::Service_denied) { }
return policy.resolve_session_request(name, label);
}
Session_capability Child::session(Parent::Client::Id id,
Parent::Service_name const &name,
Parent::Session_args const &args,
@ -202,10 +231,11 @@ Session_capability Child::session(Parent::Client::Id id,
Affinity const filtered_affinity = _policy.filter_session_affinity(affinity);
/* may throw a 'Parent::Service_denied' exception */
Service &service = _policy.resolve_session_request(name.string(), argbuf);
Child_policy::Route route = _resolve_session_request(_policy, name.string(), argbuf);
Service &service = route.service;
Session_state &session =
create_session(_policy.name(), service, *_session_factory,
create_session(_policy.name(), service, route.label, *_session_factory,
_id_space, id, argbuf, filtered_affinity);
session.ready_callback = this;

View File

@ -40,8 +40,9 @@ void Session_state::generate_session_request(Xml_generator &xml) const
xml.node("create", [&] () {
xml.attribute("id", id_at_server->id().value);
xml.attribute("service", _service.name());
xml.attribute("label", _label);
xml.node("args", [&] () {
xml.append_sanitized(_args.string());
xml.append_sanitized(Server_args(*this).string());
});
});
break;
@ -110,11 +111,12 @@ void Session_state::destroy()
Session_state::Session_state(Service &service,
Id_space<Parent::Client> &client_id_space,
Parent::Client::Id client_id,
Session_label const &label,
Args const &args,
Affinity const &affinity)
:
_service(service),
_donated_ram_quota(Arg_string::find_arg(args.string(), "ram_quota").ulong_value(0)),
_id_at_client(*this, client_id_space, client_id),
_args(args), _affinity(affinity)
_label(label), _args(args), _affinity(affinity)
{ }