mirror of
https://github.com/genodelabs/genode.git
synced 2025-03-10 22:44:30 +00:00
os: improved label matching
This patch unifies the mechanism of selecting server-side policies and taking session-routing decisions based on session labels. In both cases, XML nodes are scored against session labels. The score depends on the XML attributes 'label' (exact match), 'label_prefix', and 'label_suffix'. Issue #1766
This commit is contained in:
parent
b766387069
commit
3f6ff39d76
@ -178,17 +178,12 @@ namespace Init {
|
||||
if (!service_matches)
|
||||
return false;
|
||||
|
||||
if (!service_node.has_attribute("label"))
|
||||
return true;
|
||||
|
||||
typedef Genode::String<160> Label;
|
||||
|
||||
Label const expected = service_node.attribute_value("label", Label());
|
||||
typedef Genode::String<128> Label;
|
||||
|
||||
Label const session_label =
|
||||
Label(skip_label_prefix(child_name, Genode::Session_label(args).string()));
|
||||
|
||||
return session_label == expected;
|
||||
return !Genode::Xml_node_label_score(service_node, session_label).conflict();
|
||||
}
|
||||
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011-2013 Genode Labs GmbH
|
||||
* Copyright (C) 2011-2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
@ -19,11 +19,136 @@
|
||||
|
||||
namespace Genode {
|
||||
|
||||
struct Xml_node_label_score;
|
||||
struct Session_label;
|
||||
class Session_policy;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Score for matching an Xml_node against a label
|
||||
*
|
||||
* The score is based on the attributes 'label', 'label_prefix', and
|
||||
* 'label_suffix'.
|
||||
*/
|
||||
struct Genode::Xml_node_label_score
|
||||
{
|
||||
bool label_present = true;
|
||||
bool prefix_present = true;
|
||||
bool suffix_present = true;
|
||||
|
||||
bool label_match = false;
|
||||
|
||||
/*
|
||||
* The match values contain the number of matching characters + 1.
|
||||
* If 0, there is a conflict. If 1, an empty string matched.
|
||||
*/
|
||||
enum { CONFLICT = 0 };
|
||||
unsigned prefix_match = CONFLICT;
|
||||
unsigned suffix_match = CONFLICT;
|
||||
|
||||
Xml_node_label_score() { }
|
||||
|
||||
template <size_t N>
|
||||
Xml_node_label_score(Xml_node node, String<N> const &label)
|
||||
:
|
||||
label_present (node.has_attribute("label")),
|
||||
prefix_present(node.has_attribute("label_prefix")),
|
||||
suffix_present(node.has_attribute("label_suffix"))
|
||||
{
|
||||
if (label_present)
|
||||
label_match = node.attribute_value("label", String<N>()) == label;
|
||||
|
||||
if (prefix_present) {
|
||||
typedef String<N> Prefix;
|
||||
Prefix const prefix = node.attribute_value("label_prefix", Prefix());
|
||||
|
||||
if (!strcmp(label.string(), prefix.string(), prefix.length() - 1))
|
||||
prefix_match = prefix.length();
|
||||
}
|
||||
|
||||
if (suffix_present) {
|
||||
typedef String<N> Suffix;
|
||||
Suffix const suffix = node.attribute_value("label_suffix", Suffix());
|
||||
|
||||
if (label.length() >= suffix.length()) {
|
||||
unsigned const offset = label.length() - suffix.length();
|
||||
|
||||
if (!strcmp(label.string() + offset, suffix.string()))
|
||||
suffix_match = suffix.length();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool conflict() const
|
||||
{
|
||||
return (label_present && !label_match)
|
||||
|| (prefix_present && !prefix_match)
|
||||
|| (suffix_present && !suffix_match);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this node's score is higher than 'other'
|
||||
*/
|
||||
bool stronger(Xml_node_label_score const &other) const
|
||||
{
|
||||
/* if we are in conflict, we have a lower score than any other node */
|
||||
if (conflict())
|
||||
return false;
|
||||
|
||||
/* there are no conflicts */
|
||||
|
||||
/* we have a higher score than another conflicting node */
|
||||
if (other.conflict())
|
||||
return true;
|
||||
|
||||
if (label_present && !other.label_present)
|
||||
return true;
|
||||
|
||||
if (other.label_present)
|
||||
return false;
|
||||
|
||||
/* labels are equally good */
|
||||
|
||||
if (prefix_present && !other.prefix_present)
|
||||
return true;
|
||||
|
||||
if (!prefix_present && other.prefix_present)
|
||||
return false;
|
||||
|
||||
if (prefix_present && other.prefix_present) {
|
||||
|
||||
if (prefix_match > other.prefix_match)
|
||||
return true;
|
||||
|
||||
if (prefix_match < other.prefix_match)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* prefixes are equally good */
|
||||
|
||||
if (suffix_present && !other.suffix_present)
|
||||
return true;
|
||||
|
||||
if (!suffix_present && other.suffix_present)
|
||||
return false;
|
||||
|
||||
if (suffix_present && other.suffix_present) {
|
||||
|
||||
if (suffix_match > other.suffix_match)
|
||||
return true;
|
||||
|
||||
if (suffix_match < other.suffix_match)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* nodes are equally good */
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Genode::Session_label : String<128>
|
||||
{
|
||||
Session_label() { }
|
||||
@ -62,41 +187,27 @@ class Genode::Session_policy : public Xml_node
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Returns true if the start of the label matches the specified
|
||||
* match string
|
||||
*/
|
||||
static bool _label_matches(char const *label, char const *match) {
|
||||
return strcmp(label, match, strlen(match)) == 0; }
|
||||
|
||||
/**
|
||||
* Query session policy from session label
|
||||
*/
|
||||
static Xml_node _query_policy(char const *label, Xml_node config)
|
||||
template <size_t N>
|
||||
static Xml_node _query_policy(String<N> const &label, Xml_node config)
|
||||
{
|
||||
/*
|
||||
* Find policy node that matches best
|
||||
*/
|
||||
Xml_node best_match("<none/>");
|
||||
|
||||
unsigned label_len = 0;
|
||||
Xml_node best_match("<none/>");
|
||||
Xml_node_label_score best_score;
|
||||
|
||||
/*
|
||||
* Functor to be applied to each policy node
|
||||
*/
|
||||
auto lambda = [&] (Xml_node policy) {
|
||||
|
||||
/* label attribute from policy node */
|
||||
char policy_label[Session_label::capacity()];
|
||||
policy.attribute("label").value(policy_label,
|
||||
sizeof(policy_label));
|
||||
|
||||
if (!_label_matches(label, policy_label)
|
||||
|| strlen(policy_label) < label_len)
|
||||
return;
|
||||
|
||||
label_len = strlen(policy_label);
|
||||
best_match = policy;
|
||||
Xml_node_label_score const score(policy, label);
|
||||
if (score.stronger(best_score)) {
|
||||
best_match = policy;
|
||||
best_score = score;
|
||||
}
|
||||
};
|
||||
|
||||
config.for_each_sub_node("policy", lambda);
|
||||
@ -132,7 +243,7 @@ class Genode::Session_policy : public Xml_node
|
||||
explicit Session_policy(String<N> const &label,
|
||||
Xml_node config = Genode::config()->xml_node())
|
||||
:
|
||||
Xml_node(_query_policy(label.string(), config))
|
||||
Xml_node(_query_policy(label, config))
|
||||
{ }
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user