From 49e661750ceed68ada3f3ae00d6d1620800c1f5f Mon Sep 17 00:00:00 2001 From: Brad Bishop Date: Tue, 23 May 2017 19:16:21 -0400 Subject: Add callback groups Allow named collections of callbacks to be defined and used anywhere callbacks are used. Change-Id: I3224aa06b2250e9a055bc70d20c186caecd033af Signed-off-by: Brad Bishop --- src/Makefile.am | 1 + src/callback.hpp | 38 ++++++++++++++++++++++ src/example/example.yaml | 19 +++++++++++ src/pdmgen.py | 62 ++++++++++++++++++++++++++++++++++++ src/templates/callbackgroup.mako.cpp | 2 ++ src/templates/generated.mako.hpp | 17 ++++++++++ 6 files changed, 139 insertions(+) create mode 100644 src/templates/callbackgroup.mako.cpp (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index f223713..c77c0a8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -22,6 +22,7 @@ BUILT_SOURCES = generated.hpp CLEANFILES = generated.hpp TEMPLATES = \ + templates/callbackgroup.mako.cpp \ templates/generated.mako.hpp \ templates/journal.mako.cpp diff --git a/src/callback.hpp b/src/callback.hpp index d7a678c..7c6f69b 100644 --- a/src/callback.hpp +++ b/src/callback.hpp @@ -52,6 +52,44 @@ class IndexedCallback : public Callback const PropertyIndex& index; }; +/** @class GroupOfCallbacks + * @brief Invoke multiple callbacks. + * + * A group of callbacks is implemented as a vector of array indicies + * into an external array of callbacks. The group function call + * operator traverses the vector of indicies, invoking each + * callback. + * + * @tparam CallbackAccess - Access to the array of callbacks. + */ +template +class GroupOfCallbacks : public Callback +{ + public: + GroupOfCallbacks() = delete; + GroupOfCallbacks(const GroupOfCallbacks&) = delete; + GroupOfCallbacks(GroupOfCallbacks&&) = default; + GroupOfCallbacks& operator=(const GroupOfCallbacks&) = delete; + GroupOfCallbacks& operator=(GroupOfCallbacks&&) = default; + ~GroupOfCallbacks() = default; + explicit GroupOfCallbacks( + const std::vector& graphEntry) + : graph(graphEntry) {} + + /** @brief Run the callbacks. */ + void operator()() override + { + for (auto e : graph) + { + (*CallbackAccess::get()[e])(); + } + } + + private: + /** @brief The offsets of the callbacks in the group. */ + const std::vector& graph; +}; + } // namespace monitoring } // namespace dbus } // namespace phosphor diff --git a/src/example/example.yaml b/src/example/example.yaml index 171aeaa..0f286dc 100644 --- a/src/example/example.yaml +++ b/src/example/example.yaml @@ -74,3 +74,22 @@ properties: example property group severity: INFO message: Hello world from PDM! + +- name: example callback group + description: > + 'Callbacks groups are simply named collections of other callbacks. + Configuration file directives can only refer to a single callback. + Through use of a group, these configuration file directives can + refer to more than one callback. + + For example for a given event, one may wish to trace multiple + messages to the systemd journal. The journal callback does not + support tracing multiple messages. To do that, define a callback + group composed of multiple journal callbacks. + + This example callback group only has one member. To add more, add + additional callbacks to the members element.' + class: callback + callback: group + members: + - example journal callback diff --git a/src/pdmgen.py b/src/pdmgen.py index e4a97e7..b20436e 100755 --- a/src/pdmgen.py +++ b/src/pdmgen.py @@ -436,6 +436,65 @@ class Journal(Callback, Renderer): indent=indent) +class CallbackGraphEntry(Group): + '''An entry in a traversal list for groups of callbacks.''' + + def __init__(self, *a, **kw): + super(CallbackGraphEntry, self).__init__(**kw) + + def setup(self, objs): + '''Resolve group members.''' + + def map_member(x): + return get_index( + objs, 'callback', x, config=self.configfile) + + self.members = map( + map_member, + self.members) + + super(CallbackGraphEntry, self).setup(objs) + + +class GroupOfCallbacks(ConfigEntry, Renderer): + '''Handle the callback group config file directive.''' + + def __init__(self, *a, **kw): + self.members = kw.pop('members') + super(GroupOfCallbacks, self).__init__(**kw) + + def factory(self, objs): + '''Create a graph instance for this group of callbacks.''' + + args = { + 'configfile': self.configfile, + 'members': self.members, + 'class': 'callbackgroup', + 'callbackgroup': 'callback', + 'name': self.members + } + + entry = CallbackGraphEntry(**args) + add_unique(entry, objs, config=self.configfile) + + super(GroupOfCallbacks, self).factory(objs) + + def setup(self, objs): + '''Resolve graph entry.''' + + self.graph = get_index( + objs, 'callbackgroup', self.members, config=self.configfile) + + super(GroupOfCallbacks, self).setup(objs) + + def construct(self, loader, indent): + return self.render( + loader, + 'callbackgroup.mako.cpp', + c=self, + indent=indent) + + class Everything(Renderer): '''Parse/render entry point.''' @@ -465,6 +524,7 @@ class Everything(Renderer): }, 'callback': { 'journal': Journal, + 'group': GroupOfCallbacks, }, } @@ -556,6 +616,7 @@ class Everything(Renderer): self.instancegroups = kw.pop('instancegroup', []) self.watches = kw.pop('watch', []) self.callbacks = kw.pop('callback', []) + self.callbackgroups = kw.pop('callbackgroup', []) super(Everything, self).__init__(**kw) @@ -578,6 +639,7 @@ class Everything(Renderer): watches=self.watches, instancegroups=self.instancegroups, callbacks=self.callbacks, + callbackgroups=self.callbackgroups, indent=Indent())) if __name__ == '__main__': diff --git a/src/templates/callbackgroup.mako.cpp b/src/templates/callbackgroup.mako.cpp new file mode 100644 index 0000000..6cc6813 --- /dev/null +++ b/src/templates/callbackgroup.mako.cpp @@ -0,0 +1,2 @@ +std::make_unique>( +${indent(1)}ConfigPropertyCallbackGroups::get()[${c.graph}])\ diff --git a/src/templates/generated.mako.hpp b/src/templates/generated.mako.hpp index 61c2b6f..67b9149 100644 --- a/src/templates/generated.mako.hpp +++ b/src/templates/generated.mako.hpp @@ -128,6 +128,23 @@ struct ConfigPropertyIndicies } }; +struct ConfigPropertyCallbackGroups +{ + using CallbackGroups = std::array, ${len(callbackgroups)}>; + static auto& get() + { + static const CallbackGroups propertyCallbackGraph = + { + { +% for g in callbackgroups: + {${', '.join([str(x) for x in g.members])}}, +% endfor + } + }; + return propertyCallbackGraph; + } +}; + struct ConfigPropertyCallbacks { using Callbacks = std::array, ${len(callbacks)}>; -- cgit v1.2.1