blob: ef9d085e662dfc71181533cfc1a87f43f09456ef [file] [log] [blame]
Brad Bishop3d57f502016-10-19 12:18:41 -04001#pragma once
2
3#include <utility>
4#include <memory>
Brad Bishop07934a62017-02-08 23:34:59 -05005#include <functional>
Brad Bishop3d57f502016-10-19 12:18:41 -04006#include <sdbusplus/message.hpp>
Brad Bishop65ffffa2016-11-29 12:31:31 -05007#include "utils.hpp"
Brad Bishop3d57f502016-10-19 12:18:41 -04008
9namespace phosphor
10{
11namespace inventory
12{
13namespace manager
14{
Brad Bishopc0eae112016-10-19 21:59:47 -040015
16class Manager;
Brad Bishop07934a62017-02-08 23:34:59 -050017using Filter = std::function <
18 bool (sdbusplus::bus::bus&, sdbusplus::message::message&, Manager&) >;
Brad Bishop65ffffa2016-11-29 12:31:31 -050019
Brad Bishop4f20a3e2016-11-29 15:21:46 -050020/** @struct Event
21 * @brief Event object interface.
Brad Bishop48547a82017-01-19 15:12:50 -050022 *
23 * The event base is an assocation of an event type
24 * and an array of filter callbacks.
Brad Bishop4f20a3e2016-11-29 15:21:46 -050025 */
Brad Bishop07934a62017-02-08 23:34:59 -050026struct Event : public std::vector<Filter>
Brad Bishop4f20a3e2016-11-29 15:21:46 -050027{
28 enum class Type
29 {
30 DBUS_SIGNAL,
Brad Bishop3e4a19a2017-01-21 22:17:09 -050031 STARTUP,
Brad Bishop4f20a3e2016-11-29 15:21:46 -050032 };
33
34 virtual ~Event() = default;
Brad Bishop48547a82017-01-19 15:12:50 -050035 Event(const Event&) = delete;
36 Event& operator=(const Event&) = delete;
Brad Bishop4f20a3e2016-11-29 15:21:46 -050037 Event(Event&&) = default;
38 Event& operator=(Event&&) = default;
Brad Bishop4f20a3e2016-11-29 15:21:46 -050039
Brad Bishop48547a82017-01-19 15:12:50 -050040 /** @brief Event constructor.
41 *
42 * @param[in] filters - An array of filter callbacks.
43 * @param[in] t - The event type.
44 */
45 explicit Event(
Brad Bishop07934a62017-02-08 23:34:59 -050046 const std::vector<Filter>& filters, Type t = Type::STARTUP) :
47 std::vector<Filter>(filters),
Brad Bishop48547a82017-01-19 15:12:50 -050048 type(t) {}
49
50 /** @brief event class enumeration. */
Brad Bishop4f20a3e2016-11-29 15:21:46 -050051 Type type;
52};
53
Brad Bishop3e4a19a2017-01-21 22:17:09 -050054using StartupEvent = Event;
55
Brad Bishop4f20a3e2016-11-29 15:21:46 -050056using EventBasePtr = std::shared_ptr<Event>;
57
58/** @struct DbusSignal
59 * @brief DBus signal event.
60 *
61 * DBus signal events are an association of a match signature
62 * and filtering function object.
63 */
Brad Bishop48547a82017-01-19 15:12:50 -050064struct DbusSignal final : public Event
Brad Bishop4f20a3e2016-11-29 15:21:46 -050065{
Brad Bishop48547a82017-01-19 15:12:50 -050066 ~DbusSignal() = default;
67 DbusSignal(const DbusSignal&) = delete;
Brad Bishop7b337772017-01-12 16:11:24 -050068 DbusSignal& operator=(const DbusSignal&) = delete;
Brad Bishop4f20a3e2016-11-29 15:21:46 -050069 DbusSignal(DbusSignal&&) = default;
70 DbusSignal& operator=(DbusSignal&&) = default;
71
72 /** @brief Import from signature and filter constructor.
73 *
74 * @param[in] sig - The DBus match signature.
Brad Bishop48547a82017-01-19 15:12:50 -050075 * @param[in] filter - An array of DBus signal
76 * match callback filtering functions.
Brad Bishop4f20a3e2016-11-29 15:21:46 -050077 */
Brad Bishop07934a62017-02-08 23:34:59 -050078 DbusSignal(const char* sig, const std::vector<Filter>& filters) :
Brad Bishop48547a82017-01-19 15:12:50 -050079 Event(filters, Type::DBUS_SIGNAL),
80 signature(sig) {}
81
82 const char* signature;
Brad Bishop4f20a3e2016-11-29 15:21:46 -050083};
84
Brad Bishop65ffffa2016-11-29 12:31:31 -050085/** @brief make_filter
86 *
87 * Adapt a filter function object.
88 *
89 * @param[in] filter - The filter being adapted.
90 * @returns - The adapted filter.
91 *
92 * @tparam T - The type of the filter being adapted.
93 */
94template <typename T>
95auto make_filter(T&& filter)
96{
Brad Bishop07934a62017-02-08 23:34:59 -050097 return Filter(std::forward<T>(filter));
Brad Bishop65ffffa2016-11-29 12:31:31 -050098}
Brad Bishop65ffffa2016-11-29 12:31:31 -050099
Brad Bishop3d57f502016-10-19 12:18:41 -0400100namespace filters
101{
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400102namespace property_condition
103{
104
Brad Bishop143522e2017-01-19 09:12:54 -0500105/** @struct PropertyChangedCondition
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400106 * @brief Match filter functor that tests a property value.
107 *
108 * @tparam T - The type of the property being tested.
109 * @tparam U - The type of the condition checking functor.
110 */
111template <typename T, typename U>
Brad Bishop143522e2017-01-19 09:12:54 -0500112struct PropertyChangedCondition
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400113{
Brad Bishop143522e2017-01-19 09:12:54 -0500114 PropertyChangedCondition() = delete;
115 ~PropertyChangedCondition() = default;
116 PropertyChangedCondition(const PropertyChangedCondition&) = default;
Brad Bishop07934a62017-02-08 23:34:59 -0500117 PropertyChangedCondition& operator=(const PropertyChangedCondition&) = default;
Brad Bishop143522e2017-01-19 09:12:54 -0500118 PropertyChangedCondition(PropertyChangedCondition&&) = default;
119 PropertyChangedCondition& operator=(PropertyChangedCondition&&) = default;
120 PropertyChangedCondition(const char* iface, const char* property,
121 U&& condition) :
Brad Bishop7b337772017-01-12 16:11:24 -0500122 _iface(iface),
123 _property(property),
124 _condition(std::forward<U>(condition)) { }
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400125
Brad Bishop7b337772017-01-12 16:11:24 -0500126 /** @brief Test a property value.
127 *
128 * Extract the property from the PropertiesChanged
129 * message and run the condition test.
130 */
Brad Bishop23719002017-01-24 21:08:46 -0500131 bool operator()(
132 sdbusplus::bus::bus&,
133 sdbusplus::message::message& msg,
134 Manager&) const
Brad Bishop7b337772017-01-12 16:11:24 -0500135 {
136 std::map <
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400137 std::string,
Brad Bishop7b337772017-01-12 16:11:24 -0500138 sdbusplus::message::variant<T >> properties;
139 const char* iface = nullptr;
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400140
Brad Bishop7b337772017-01-12 16:11:24 -0500141 msg.read(iface);
Brad Bishop064c94a2017-01-21 21:33:30 -0500142 if (!iface || strcmp(iface, _iface))
Brad Bishop7b337772017-01-12 16:11:24 -0500143 {
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400144 return false;
Brad Bishop7b337772017-01-12 16:11:24 -0500145 }
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400146
Brad Bishop7b337772017-01-12 16:11:24 -0500147 msg.read(properties);
148 auto it = properties.find(_property);
149 if (it == properties.cend())
150 {
151 return false;
152 }
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400153
Brad Bishopfb083c22017-01-19 09:22:04 -0500154 return _condition(
155 std::forward<T>(it->second.template get<T>()));
Brad Bishop7b337772017-01-12 16:11:24 -0500156 }
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400157
158 private:
Brad Bishop7b337772017-01-12 16:11:24 -0500159 const char* _iface;
160 const char* _property;
161 U _condition;
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400162};
163
Brad Bishopfa51da72017-01-19 11:06:51 -0500164/** @struct PropertyConditionBase
165 * @brief Match filter functor that tests a property value.
166 *
167 * Base class for PropertyCondition - factored out code that
168 * doesn't need to be templated.
169 */
170struct PropertyConditionBase
171{
172 PropertyConditionBase() = delete;
173 virtual ~PropertyConditionBase() = default;
Brad Bishop07934a62017-02-08 23:34:59 -0500174 PropertyConditionBase(const PropertyConditionBase&) = default;
175 PropertyConditionBase& operator=(const PropertyConditionBase&) = default;
Brad Bishopfa51da72017-01-19 11:06:51 -0500176 PropertyConditionBase(PropertyConditionBase&&) = default;
177 PropertyConditionBase& operator=(PropertyConditionBase&&) = default;
178
179 /** @brief Constructor
180 *
181 * The service argument can be nullptr. If something
182 * else is provided the function will call the the
183 * service directly. If omitted, the function will
184 * look up the service in the ObjectMapper.
185 *
186 * @param path - The path of the object containing
187 * the property to be tested.
188 * @param iface - The interface hosting the property
189 * to be tested.
190 * @param property - The property to be tested.
191 * @param service - The DBus service hosting the object.
192 */
193 PropertyConditionBase(
194 const char* path,
195 const char* iface,
196 const char* property,
197 const char* service) :
198 _path(path),
199 _iface(iface),
200 _property(property),
201 _service(service) {}
202
203 /** @brief Forward comparison to type specific implementation. */
204 virtual bool eval(sdbusplus::message::message&) const = 0;
205
206 /** @brief Test a property value.
207 *
208 * Make a DBus call and test the value of any property.
209 */
210 bool operator()(
211 sdbusplus::bus::bus&,
212 sdbusplus::message::message&,
213 Manager&) const;
214
215 private:
216 std::string _path;
217 std::string _iface;
218 std::string _property;
219 const char* _service;
220};
221
222/** @struct PropertyCondition
223 * @brief Match filter functor that tests a property value.
224 *
225 * @tparam T - The type of the property being tested.
226 * @tparam U - The type of the condition checking functor.
227 */
228template <typename T, typename U>
229struct PropertyCondition final : public PropertyConditionBase
230{
231 PropertyCondition() = delete;
232 ~PropertyCondition() = default;
Brad Bishop07934a62017-02-08 23:34:59 -0500233 PropertyCondition(const PropertyCondition&) = default;
234 PropertyCondition& operator=(const PropertyCondition&) = default;
Brad Bishopfa51da72017-01-19 11:06:51 -0500235 PropertyCondition(PropertyCondition&&) = default;
236 PropertyCondition& operator=(PropertyCondition&&) = default;
237
238 /** @brief Constructor
239 *
240 * The service argument can be nullptr. If something
241 * else is provided the function will call the the
242 * service directly. If omitted, the function will
243 * look up the service in the ObjectMapper.
244 *
245 * @param path - The path of the object containing
246 * the property to be tested.
247 * @param iface - The interface hosting the property
248 * to be tested.
249 * @param property - The property to be tested.
250 * @param condition - The test to run on the property.
251 * @param service - The DBus service hosting the object.
252 */
253 PropertyCondition(
254 const char* path,
255 const char* iface,
256 const char* property,
257 U&& condition,
258 const char* service) :
259 PropertyConditionBase(path, iface, property, service),
260 _condition(std::forward<decltype(condition)>(condition)) {}
261
262 /** @brief Test a property value.
263 *
264 * Make a DBus call and test the value of any property.
265 */
266 bool eval(sdbusplus::message::message& msg) const override
267 {
268 sdbusplus::message::variant<T> value;
269 msg.read(value);
270 return _condition(
271 std::forward<T>(value.template get<T>()));
272 }
273
274 private:
275 U _condition;
276};
277
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400278} // namespace property_condition
Brad Bishop3d57f502016-10-19 12:18:41 -0400279
Brad Bishop143522e2017-01-19 09:12:54 -0500280/** @brief Implicit type deduction for constructing PropertyChangedCondition. */
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400281template <typename T>
282auto propertyChangedTo(
Brad Bishop7b337772017-01-12 16:11:24 -0500283 const char* iface,
284 const char* property,
Brad Bishopfb083c22017-01-19 09:22:04 -0500285 T&& val)
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400286{
Brad Bishop76e2f6a2017-01-31 14:05:22 -0500287 auto condition = [val = std::forward<T>(val)](T && arg)
Brad Bishopd1bbf3a2016-12-01 00:03:26 -0500288 {
289 return arg == val;
290 };
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400291 using U = decltype(condition);
Brad Bishop12f8a3c2017-02-09 00:02:00 -0500292 return property_condition::PropertyChangedCondition<T, U>(
Brad Bishop7b337772017-01-12 16:11:24 -0500293 iface, property, std::move(condition));
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400294}
295
Brad Bishopfa51da72017-01-19 11:06:51 -0500296/** @brief Implicit type deduction for constructing PropertyCondition. */
297template <typename T>
298auto propertyIs(
299 const char* path,
300 const char* iface,
301 const char* property,
302 T&& val,
303 const char* service = nullptr)
304{
305 auto condition = [val = std::forward<T>(val)](T && arg)
306 {
307 return arg == val;
308 };
309 using U = decltype(condition);
Brad Bishop12f8a3c2017-02-09 00:02:00 -0500310 return property_condition::PropertyCondition<T, U>(
Brad Bishopfa51da72017-01-19 11:06:51 -0500311 path, iface, property, std::move(condition), service);
312}
313
Brad Bishop3d57f502016-10-19 12:18:41 -0400314} // namespace filters
315} // namespace manager
316} // namespace inventory
317} // namespace phosphor
318
319// vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4