blob: 67378610183c01a3e020083f044c8188132747bd [file] [log] [blame]
Brad Bishop3d57f502016-10-19 12:18:41 -04001#pragma once
2
3#include <utility>
4#include <memory>
5#include <sdbusplus/message.hpp>
Brad Bishop65ffffa2016-11-29 12:31:31 -05006#include "utils.hpp"
Brad Bishop3d57f502016-10-19 12:18:41 -04007
8namespace phosphor
9{
10namespace inventory
11{
12namespace manager
13{
Brad Bishopc0eae112016-10-19 21:59:47 -040014
15class Manager;
Brad Bishop65ffffa2016-11-29 12:31:31 -050016namespace details
17{
Brad Bishop7b337772017-01-12 16:11:24 -050018using FilterBase = holder::CallableBase <
Brad Bishop23719002017-01-24 21:08:46 -050019 bool, sdbusplus::bus::bus&, sdbusplus::message::message&, Manager& >;
Brad Bishop65ffffa2016-11-29 12:31:31 -050020using FilterBasePtr = std::shared_ptr<FilterBase>;
21template <typename T>
Brad Bishop7b337772017-01-12 16:11:24 -050022using Filter = holder::CallableHolder <
Brad Bishop23719002017-01-24 21:08:46 -050023 T, bool, sdbusplus::bus::bus&, sdbusplus::message::message&, Manager& >;
Brad Bishop65ffffa2016-11-29 12:31:31 -050024
Brad Bishop4f20a3e2016-11-29 15:21:46 -050025/** @struct Event
26 * @brief Event object interface.
Brad Bishop48547a82017-01-19 15:12:50 -050027 *
28 * The event base is an assocation of an event type
29 * and an array of filter callbacks.
Brad Bishop4f20a3e2016-11-29 15:21:46 -050030 */
Brad Bishop48547a82017-01-19 15:12:50 -050031struct Event : public std::vector<FilterBasePtr>
Brad Bishop4f20a3e2016-11-29 15:21:46 -050032{
33 enum class Type
34 {
35 DBUS_SIGNAL,
Brad Bishop3e4a19a2017-01-21 22:17:09 -050036 STARTUP,
Brad Bishop4f20a3e2016-11-29 15:21:46 -050037 };
38
39 virtual ~Event() = default;
Brad Bishop48547a82017-01-19 15:12:50 -050040 Event(const Event&) = delete;
41 Event& operator=(const Event&) = delete;
Brad Bishop4f20a3e2016-11-29 15:21:46 -050042 Event(Event&&) = default;
43 Event& operator=(Event&&) = default;
Brad Bishop4f20a3e2016-11-29 15:21:46 -050044
Brad Bishop48547a82017-01-19 15:12:50 -050045 /** @brief Event constructor.
46 *
47 * @param[in] filters - An array of filter callbacks.
48 * @param[in] t - The event type.
49 */
50 explicit Event(
Brad Bishop3e4a19a2017-01-21 22:17:09 -050051 const std::vector<FilterBasePtr>& filters, Type t = Type::STARTUP) :
Brad Bishop48547a82017-01-19 15:12:50 -050052 std::vector<FilterBasePtr>(filters),
53 type(t) {}
54
55 /** @brief event class enumeration. */
Brad Bishop4f20a3e2016-11-29 15:21:46 -050056 Type type;
57};
58
Brad Bishop3e4a19a2017-01-21 22:17:09 -050059using StartupEvent = Event;
60
Brad Bishop4f20a3e2016-11-29 15:21:46 -050061using EventBasePtr = std::shared_ptr<Event>;
62
63/** @struct DbusSignal
64 * @brief DBus signal event.
65 *
66 * DBus signal events are an association of a match signature
67 * and filtering function object.
68 */
Brad Bishop48547a82017-01-19 15:12:50 -050069struct DbusSignal final : public Event
Brad Bishop4f20a3e2016-11-29 15:21:46 -050070{
Brad Bishop48547a82017-01-19 15:12:50 -050071 ~DbusSignal() = default;
72 DbusSignal(const DbusSignal&) = delete;
Brad Bishop7b337772017-01-12 16:11:24 -050073 DbusSignal& operator=(const DbusSignal&) = delete;
Brad Bishop4f20a3e2016-11-29 15:21:46 -050074 DbusSignal(DbusSignal&&) = default;
75 DbusSignal& operator=(DbusSignal&&) = default;
76
77 /** @brief Import from signature and filter constructor.
78 *
79 * @param[in] sig - The DBus match signature.
Brad Bishop48547a82017-01-19 15:12:50 -050080 * @param[in] filter - An array of DBus signal
81 * match callback filtering functions.
Brad Bishop4f20a3e2016-11-29 15:21:46 -050082 */
Brad Bishop064c94a2017-01-21 21:33:30 -050083 DbusSignal(const char* sig, const std::vector<FilterBasePtr>& filters) :
Brad Bishop48547a82017-01-19 15:12:50 -050084 Event(filters, Type::DBUS_SIGNAL),
85 signature(sig) {}
86
87 const char* signature;
Brad Bishop4f20a3e2016-11-29 15:21:46 -050088};
89
Brad Bishop65ffffa2016-11-29 12:31:31 -050090/** @brief make_filter
91 *
92 * Adapt a filter function object.
93 *
94 * @param[in] filter - The filter being adapted.
95 * @returns - The adapted filter.
96 *
97 * @tparam T - The type of the filter being adapted.
98 */
99template <typename T>
100auto make_filter(T&& filter)
101{
102 return Filter<T>::template make_shared<Filter<T>>(
103 std::forward<T>(filter));
104}
105} // namespace details
106
Brad Bishop3d57f502016-10-19 12:18:41 -0400107namespace filters
108{
109namespace details
110{
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400111namespace property_condition
112{
113
Brad Bishop143522e2017-01-19 09:12:54 -0500114/** @struct PropertyChangedCondition
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400115 * @brief Match filter functor that tests a property value.
116 *
117 * @tparam T - The type of the property being tested.
118 * @tparam U - The type of the condition checking functor.
119 */
120template <typename T, typename U>
Brad Bishop143522e2017-01-19 09:12:54 -0500121struct PropertyChangedCondition
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400122{
Brad Bishop143522e2017-01-19 09:12:54 -0500123 PropertyChangedCondition() = delete;
124 ~PropertyChangedCondition() = default;
125 PropertyChangedCondition(const PropertyChangedCondition&) = default;
126 PropertyChangedCondition& operator=(const PropertyChangedCondition&) = delete;
127 PropertyChangedCondition(PropertyChangedCondition&&) = default;
128 PropertyChangedCondition& operator=(PropertyChangedCondition&&) = default;
129 PropertyChangedCondition(const char* iface, const char* property,
130 U&& condition) :
Brad Bishop7b337772017-01-12 16:11:24 -0500131 _iface(iface),
132 _property(property),
133 _condition(std::forward<U>(condition)) { }
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400134
Brad Bishop7b337772017-01-12 16:11:24 -0500135 /** @brief Test a property value.
136 *
137 * Extract the property from the PropertiesChanged
138 * message and run the condition test.
139 */
Brad Bishop23719002017-01-24 21:08:46 -0500140 bool operator()(
141 sdbusplus::bus::bus&,
142 sdbusplus::message::message& msg,
143 Manager&) const
Brad Bishop7b337772017-01-12 16:11:24 -0500144 {
145 std::map <
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400146 std::string,
Brad Bishop7b337772017-01-12 16:11:24 -0500147 sdbusplus::message::variant<T >> properties;
148 const char* iface = nullptr;
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400149
Brad Bishop7b337772017-01-12 16:11:24 -0500150 msg.read(iface);
Brad Bishop064c94a2017-01-21 21:33:30 -0500151 if (!iface || strcmp(iface, _iface))
Brad Bishop7b337772017-01-12 16:11:24 -0500152 {
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400153 return false;
Brad Bishop7b337772017-01-12 16:11:24 -0500154 }
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400155
Brad Bishop7b337772017-01-12 16:11:24 -0500156 msg.read(properties);
157 auto it = properties.find(_property);
158 if (it == properties.cend())
159 {
160 return false;
161 }
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400162
Brad Bishopfb083c22017-01-19 09:22:04 -0500163 return _condition(
164 std::forward<T>(it->second.template get<T>()));
Brad Bishop7b337772017-01-12 16:11:24 -0500165 }
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400166
167 private:
Brad Bishop7b337772017-01-12 16:11:24 -0500168 const char* _iface;
169 const char* _property;
170 U _condition;
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400171};
172
Brad Bishopfa51da72017-01-19 11:06:51 -0500173/** @struct PropertyConditionBase
174 * @brief Match filter functor that tests a property value.
175 *
176 * Base class for PropertyCondition - factored out code that
177 * doesn't need to be templated.
178 */
179struct PropertyConditionBase
180{
181 PropertyConditionBase() = delete;
182 virtual ~PropertyConditionBase() = default;
183 PropertyConditionBase(const PropertyConditionBase&) = delete;
184 PropertyConditionBase& operator=(const PropertyConditionBase&) = delete;
185 PropertyConditionBase(PropertyConditionBase&&) = default;
186 PropertyConditionBase& operator=(PropertyConditionBase&&) = default;
187
188 /** @brief Constructor
189 *
190 * The service argument can be nullptr. If something
191 * else is provided the function will call the the
192 * service directly. If omitted, the function will
193 * look up the service in the ObjectMapper.
194 *
195 * @param path - The path of the object containing
196 * the property to be tested.
197 * @param iface - The interface hosting the property
198 * to be tested.
199 * @param property - The property to be tested.
200 * @param service - The DBus service hosting the object.
201 */
202 PropertyConditionBase(
203 const char* path,
204 const char* iface,
205 const char* property,
206 const char* service) :
207 _path(path),
208 _iface(iface),
209 _property(property),
210 _service(service) {}
211
212 /** @brief Forward comparison to type specific implementation. */
213 virtual bool eval(sdbusplus::message::message&) const = 0;
214
215 /** @brief Test a property value.
216 *
217 * Make a DBus call and test the value of any property.
218 */
219 bool operator()(
220 sdbusplus::bus::bus&,
221 sdbusplus::message::message&,
222 Manager&) const;
223
224 private:
225 std::string _path;
226 std::string _iface;
227 std::string _property;
228 const char* _service;
229};
230
231/** @struct PropertyCondition
232 * @brief Match filter functor that tests a property value.
233 *
234 * @tparam T - The type of the property being tested.
235 * @tparam U - The type of the condition checking functor.
236 */
237template <typename T, typename U>
238struct PropertyCondition final : public PropertyConditionBase
239{
240 PropertyCondition() = delete;
241 ~PropertyCondition() = default;
242 PropertyCondition(const PropertyCondition&) = delete;
243 PropertyCondition& operator=(const PropertyCondition&) = delete;
244 PropertyCondition(PropertyCondition&&) = default;
245 PropertyCondition& operator=(PropertyCondition&&) = default;
246
247 /** @brief Constructor
248 *
249 * The service argument can be nullptr. If something
250 * else is provided the function will call the the
251 * service directly. If omitted, the function will
252 * look up the service in the ObjectMapper.
253 *
254 * @param path - The path of the object containing
255 * the property to be tested.
256 * @param iface - The interface hosting the property
257 * to be tested.
258 * @param property - The property to be tested.
259 * @param condition - The test to run on the property.
260 * @param service - The DBus service hosting the object.
261 */
262 PropertyCondition(
263 const char* path,
264 const char* iface,
265 const char* property,
266 U&& condition,
267 const char* service) :
268 PropertyConditionBase(path, iface, property, service),
269 _condition(std::forward<decltype(condition)>(condition)) {}
270
271 /** @brief Test a property value.
272 *
273 * Make a DBus call and test the value of any property.
274 */
275 bool eval(sdbusplus::message::message& msg) const override
276 {
277 sdbusplus::message::variant<T> value;
278 msg.read(value);
279 return _condition(
280 std::forward<T>(value.template get<T>()));
281 }
282
283 private:
284 U _condition;
285};
286
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400287} // namespace property_condition
Brad Bishop3d57f502016-10-19 12:18:41 -0400288} // namespace details
289
Brad Bishop143522e2017-01-19 09:12:54 -0500290/** @brief Implicit type deduction for constructing PropertyChangedCondition. */
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400291template <typename T>
292auto propertyChangedTo(
Brad Bishop7b337772017-01-12 16:11:24 -0500293 const char* iface,
294 const char* property,
Brad Bishopfb083c22017-01-19 09:22:04 -0500295 T&& val)
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400296{
Brad Bishop76e2f6a2017-01-31 14:05:22 -0500297 auto condition = [val = std::forward<T>(val)](T && arg)
Brad Bishopd1bbf3a2016-12-01 00:03:26 -0500298 {
299 return arg == val;
300 };
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400301 using U = decltype(condition);
Brad Bishop143522e2017-01-19 09:12:54 -0500302 return details::property_condition::PropertyChangedCondition<T, U>(
Brad Bishop7b337772017-01-12 16:11:24 -0500303 iface, property, std::move(condition));
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400304}
305
Brad Bishopfa51da72017-01-19 11:06:51 -0500306/** @brief Implicit type deduction for constructing PropertyCondition. */
307template <typename T>
308auto propertyIs(
309 const char* path,
310 const char* iface,
311 const char* property,
312 T&& val,
313 const char* service = nullptr)
314{
315 auto condition = [val = std::forward<T>(val)](T && arg)
316 {
317 return arg == val;
318 };
319 using U = decltype(condition);
320 return details::property_condition::PropertyCondition<T, U>(
321 path, iface, property, std::move(condition), service);
322}
323
Brad Bishop3d57f502016-10-19 12:18:41 -0400324} // namespace filters
325} // namespace manager
326} // namespace inventory
327} // namespace phosphor
328
329// vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4