blob: 9ecb93a269f0e5d529afc4863bff02b5cd9cb2a8 [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 Bishop65ffffa2016-11-29 12:31:31 -050017namespace details
18{
Brad Bishop07934a62017-02-08 23:34:59 -050019using Filter = std::function <
20 bool (sdbusplus::bus::bus&, sdbusplus::message::message&, Manager&) >;
Brad Bishop65ffffa2016-11-29 12:31:31 -050021
Brad Bishop4f20a3e2016-11-29 15:21:46 -050022/** @struct Event
23 * @brief Event object interface.
Brad Bishop48547a82017-01-19 15:12:50 -050024 *
25 * The event base is an assocation of an event type
26 * and an array of filter callbacks.
Brad Bishop4f20a3e2016-11-29 15:21:46 -050027 */
Brad Bishop07934a62017-02-08 23:34:59 -050028struct Event : public std::vector<Filter>
Brad Bishop4f20a3e2016-11-29 15:21:46 -050029{
30 enum class Type
31 {
32 DBUS_SIGNAL,
Brad Bishop3e4a19a2017-01-21 22:17:09 -050033 STARTUP,
Brad Bishop4f20a3e2016-11-29 15:21:46 -050034 };
35
36 virtual ~Event() = default;
Brad Bishop48547a82017-01-19 15:12:50 -050037 Event(const Event&) = delete;
38 Event& operator=(const Event&) = delete;
Brad Bishop4f20a3e2016-11-29 15:21:46 -050039 Event(Event&&) = default;
40 Event& operator=(Event&&) = default;
Brad Bishop4f20a3e2016-11-29 15:21:46 -050041
Brad Bishop48547a82017-01-19 15:12:50 -050042 /** @brief Event constructor.
43 *
44 * @param[in] filters - An array of filter callbacks.
45 * @param[in] t - The event type.
46 */
47 explicit Event(
Brad Bishop07934a62017-02-08 23:34:59 -050048 const std::vector<Filter>& filters, Type t = Type::STARTUP) :
49 std::vector<Filter>(filters),
Brad Bishop48547a82017-01-19 15:12:50 -050050 type(t) {}
51
52 /** @brief event class enumeration. */
Brad Bishop4f20a3e2016-11-29 15:21:46 -050053 Type type;
54};
55
Brad Bishop3e4a19a2017-01-21 22:17:09 -050056using StartupEvent = Event;
57
Brad Bishop4f20a3e2016-11-29 15:21:46 -050058using EventBasePtr = std::shared_ptr<Event>;
59
60/** @struct DbusSignal
61 * @brief DBus signal event.
62 *
63 * DBus signal events are an association of a match signature
64 * and filtering function object.
65 */
Brad Bishop48547a82017-01-19 15:12:50 -050066struct DbusSignal final : public Event
Brad Bishop4f20a3e2016-11-29 15:21:46 -050067{
Brad Bishop48547a82017-01-19 15:12:50 -050068 ~DbusSignal() = default;
69 DbusSignal(const DbusSignal&) = delete;
Brad Bishop7b337772017-01-12 16:11:24 -050070 DbusSignal& operator=(const DbusSignal&) = delete;
Brad Bishop4f20a3e2016-11-29 15:21:46 -050071 DbusSignal(DbusSignal&&) = default;
72 DbusSignal& operator=(DbusSignal&&) = default;
73
74 /** @brief Import from signature and filter constructor.
75 *
76 * @param[in] sig - The DBus match signature.
Brad Bishop48547a82017-01-19 15:12:50 -050077 * @param[in] filter - An array of DBus signal
78 * match callback filtering functions.
Brad Bishop4f20a3e2016-11-29 15:21:46 -050079 */
Brad Bishop07934a62017-02-08 23:34:59 -050080 DbusSignal(const char* sig, const std::vector<Filter>& filters) :
Brad Bishop48547a82017-01-19 15:12:50 -050081 Event(filters, Type::DBUS_SIGNAL),
82 signature(sig) {}
83
84 const char* signature;
Brad Bishop4f20a3e2016-11-29 15:21:46 -050085};
86
Brad Bishop65ffffa2016-11-29 12:31:31 -050087/** @brief make_filter
88 *
89 * Adapt a filter function object.
90 *
91 * @param[in] filter - The filter being adapted.
92 * @returns - The adapted filter.
93 *
94 * @tparam T - The type of the filter being adapted.
95 */
96template <typename T>
97auto make_filter(T&& filter)
98{
Brad Bishop07934a62017-02-08 23:34:59 -050099 return Filter(std::forward<T>(filter));
Brad Bishop65ffffa2016-11-29 12:31:31 -0500100}
101} // namespace details
102
Brad Bishop3d57f502016-10-19 12:18:41 -0400103namespace filters
104{
105namespace details
106{
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400107namespace property_condition
108{
109
Brad Bishop143522e2017-01-19 09:12:54 -0500110/** @struct PropertyChangedCondition
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400111 * @brief Match filter functor that tests a property value.
112 *
113 * @tparam T - The type of the property being tested.
114 * @tparam U - The type of the condition checking functor.
115 */
116template <typename T, typename U>
Brad Bishop143522e2017-01-19 09:12:54 -0500117struct PropertyChangedCondition
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400118{
Brad Bishop143522e2017-01-19 09:12:54 -0500119 PropertyChangedCondition() = delete;
120 ~PropertyChangedCondition() = default;
121 PropertyChangedCondition(const PropertyChangedCondition&) = default;
Brad Bishop07934a62017-02-08 23:34:59 -0500122 PropertyChangedCondition& operator=(const PropertyChangedCondition&) = default;
Brad Bishop143522e2017-01-19 09:12:54 -0500123 PropertyChangedCondition(PropertyChangedCondition&&) = default;
124 PropertyChangedCondition& operator=(PropertyChangedCondition&&) = default;
125 PropertyChangedCondition(const char* iface, const char* property,
126 U&& condition) :
Brad Bishop7b337772017-01-12 16:11:24 -0500127 _iface(iface),
128 _property(property),
129 _condition(std::forward<U>(condition)) { }
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400130
Brad Bishop7b337772017-01-12 16:11:24 -0500131 /** @brief Test a property value.
132 *
133 * Extract the property from the PropertiesChanged
134 * message and run the condition test.
135 */
Brad Bishop23719002017-01-24 21:08:46 -0500136 bool operator()(
137 sdbusplus::bus::bus&,
138 sdbusplus::message::message& msg,
139 Manager&) const
Brad Bishop7b337772017-01-12 16:11:24 -0500140 {
141 std::map <
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400142 std::string,
Brad Bishop7b337772017-01-12 16:11:24 -0500143 sdbusplus::message::variant<T >> properties;
144 const char* iface = nullptr;
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400145
Brad Bishop7b337772017-01-12 16:11:24 -0500146 msg.read(iface);
Brad Bishop064c94a2017-01-21 21:33:30 -0500147 if (!iface || strcmp(iface, _iface))
Brad Bishop7b337772017-01-12 16:11:24 -0500148 {
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400149 return false;
Brad Bishop7b337772017-01-12 16:11:24 -0500150 }
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400151
Brad Bishop7b337772017-01-12 16:11:24 -0500152 msg.read(properties);
153 auto it = properties.find(_property);
154 if (it == properties.cend())
155 {
156 return false;
157 }
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400158
Brad Bishopfb083c22017-01-19 09:22:04 -0500159 return _condition(
160 std::forward<T>(it->second.template get<T>()));
Brad Bishop7b337772017-01-12 16:11:24 -0500161 }
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400162
163 private:
Brad Bishop7b337772017-01-12 16:11:24 -0500164 const char* _iface;
165 const char* _property;
166 U _condition;
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400167};
168
Brad Bishopfa51da72017-01-19 11:06:51 -0500169/** @struct PropertyConditionBase
170 * @brief Match filter functor that tests a property value.
171 *
172 * Base class for PropertyCondition - factored out code that
173 * doesn't need to be templated.
174 */
175struct PropertyConditionBase
176{
177 PropertyConditionBase() = delete;
178 virtual ~PropertyConditionBase() = default;
Brad Bishop07934a62017-02-08 23:34:59 -0500179 PropertyConditionBase(const PropertyConditionBase&) = default;
180 PropertyConditionBase& operator=(const PropertyConditionBase&) = default;
Brad Bishopfa51da72017-01-19 11:06:51 -0500181 PropertyConditionBase(PropertyConditionBase&&) = default;
182 PropertyConditionBase& operator=(PropertyConditionBase&&) = default;
183
184 /** @brief Constructor
185 *
186 * The service argument can be nullptr. If something
187 * else is provided the function will call the the
188 * service directly. If omitted, the function will
189 * look up the service in the ObjectMapper.
190 *
191 * @param path - The path of the object containing
192 * the property to be tested.
193 * @param iface - The interface hosting the property
194 * to be tested.
195 * @param property - The property to be tested.
196 * @param service - The DBus service hosting the object.
197 */
198 PropertyConditionBase(
199 const char* path,
200 const char* iface,
201 const char* property,
202 const char* service) :
203 _path(path),
204 _iface(iface),
205 _property(property),
206 _service(service) {}
207
208 /** @brief Forward comparison to type specific implementation. */
209 virtual bool eval(sdbusplus::message::message&) const = 0;
210
211 /** @brief Test a property value.
212 *
213 * Make a DBus call and test the value of any property.
214 */
215 bool operator()(
216 sdbusplus::bus::bus&,
217 sdbusplus::message::message&,
218 Manager&) const;
219
220 private:
221 std::string _path;
222 std::string _iface;
223 std::string _property;
224 const char* _service;
225};
226
227/** @struct PropertyCondition
228 * @brief Match filter functor that tests a property value.
229 *
230 * @tparam T - The type of the property being tested.
231 * @tparam U - The type of the condition checking functor.
232 */
233template <typename T, typename U>
234struct PropertyCondition final : public PropertyConditionBase
235{
236 PropertyCondition() = delete;
237 ~PropertyCondition() = default;
Brad Bishop07934a62017-02-08 23:34:59 -0500238 PropertyCondition(const PropertyCondition&) = default;
239 PropertyCondition& operator=(const PropertyCondition&) = default;
Brad Bishopfa51da72017-01-19 11:06:51 -0500240 PropertyCondition(PropertyCondition&&) = default;
241 PropertyCondition& operator=(PropertyCondition&&) = default;
242
243 /** @brief Constructor
244 *
245 * The service argument can be nullptr. If something
246 * else is provided the function will call the the
247 * service directly. If omitted, the function will
248 * look up the service in the ObjectMapper.
249 *
250 * @param path - The path of the object containing
251 * the property to be tested.
252 * @param iface - The interface hosting the property
253 * to be tested.
254 * @param property - The property to be tested.
255 * @param condition - The test to run on the property.
256 * @param service - The DBus service hosting the object.
257 */
258 PropertyCondition(
259 const char* path,
260 const char* iface,
261 const char* property,
262 U&& condition,
263 const char* service) :
264 PropertyConditionBase(path, iface, property, service),
265 _condition(std::forward<decltype(condition)>(condition)) {}
266
267 /** @brief Test a property value.
268 *
269 * Make a DBus call and test the value of any property.
270 */
271 bool eval(sdbusplus::message::message& msg) const override
272 {
273 sdbusplus::message::variant<T> value;
274 msg.read(value);
275 return _condition(
276 std::forward<T>(value.template get<T>()));
277 }
278
279 private:
280 U _condition;
281};
282
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400283} // namespace property_condition
Brad Bishop3d57f502016-10-19 12:18:41 -0400284} // namespace details
285
Brad Bishop143522e2017-01-19 09:12:54 -0500286/** @brief Implicit type deduction for constructing PropertyChangedCondition. */
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400287template <typename T>
288auto propertyChangedTo(
Brad Bishop7b337772017-01-12 16:11:24 -0500289 const char* iface,
290 const char* property,
Brad Bishopfb083c22017-01-19 09:22:04 -0500291 T&& val)
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400292{
Brad Bishop76e2f6a2017-01-31 14:05:22 -0500293 auto condition = [val = std::forward<T>(val)](T && arg)
Brad Bishopd1bbf3a2016-12-01 00:03:26 -0500294 {
295 return arg == val;
296 };
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400297 using U = decltype(condition);
Brad Bishop143522e2017-01-19 09:12:54 -0500298 return details::property_condition::PropertyChangedCondition<T, U>(
Brad Bishop7b337772017-01-12 16:11:24 -0500299 iface, property, std::move(condition));
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400300}
301
Brad Bishopfa51da72017-01-19 11:06:51 -0500302/** @brief Implicit type deduction for constructing PropertyCondition. */
303template <typename T>
304auto propertyIs(
305 const char* path,
306 const char* iface,
307 const char* property,
308 T&& val,
309 const char* service = nullptr)
310{
311 auto condition = [val = std::forward<T>(val)](T && arg)
312 {
313 return arg == val;
314 };
315 using U = decltype(condition);
316 return details::property_condition::PropertyCondition<T, U>(
317 path, iface, property, std::move(condition), service);
318}
319
Brad Bishop3d57f502016-10-19 12:18:41 -0400320} // namespace filters
321} // namespace manager
322} // namespace inventory
323} // namespace phosphor
324
325// vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4