blob: e1977197a45d379a7a1a4d36d5f0bc1114b70c5d [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,
36 };
37
38 virtual ~Event() = default;
Brad Bishop48547a82017-01-19 15:12:50 -050039 Event(const Event&) = delete;
40 Event& operator=(const Event&) = delete;
Brad Bishop4f20a3e2016-11-29 15:21:46 -050041 Event(Event&&) = default;
42 Event& operator=(Event&&) = default;
Brad Bishop4f20a3e2016-11-29 15:21:46 -050043
Brad Bishop48547a82017-01-19 15:12:50 -050044 /** @brief Event constructor.
45 *
46 * @param[in] filters - An array of filter callbacks.
47 * @param[in] t - The event type.
48 */
49 explicit Event(
50 const std::vector<FilterBasePtr>& filters, Type t) :
51 std::vector<FilterBasePtr>(filters),
52 type(t) {}
53
54 /** @brief event class enumeration. */
Brad Bishop4f20a3e2016-11-29 15:21:46 -050055 Type type;
56};
57
58using 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 Bishop064c94a2017-01-21 21:33:30 -050080 DbusSignal(const char* sig, const std::vector<FilterBasePtr>& 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{
99 return Filter<T>::template make_shared<Filter<T>>(
100 std::forward<T>(filter));
101}
102} // namespace details
103
Brad Bishop3d57f502016-10-19 12:18:41 -0400104namespace filters
105{
106namespace details
107{
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400108namespace property_condition
109{
110
Brad Bishop143522e2017-01-19 09:12:54 -0500111/** @struct PropertyChangedCondition
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400112 * @brief Match filter functor that tests a property value.
113 *
114 * @tparam T - The type of the property being tested.
115 * @tparam U - The type of the condition checking functor.
116 */
117template <typename T, typename U>
Brad Bishop143522e2017-01-19 09:12:54 -0500118struct PropertyChangedCondition
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400119{
Brad Bishop143522e2017-01-19 09:12:54 -0500120 PropertyChangedCondition() = delete;
121 ~PropertyChangedCondition() = default;
122 PropertyChangedCondition(const PropertyChangedCondition&) = default;
123 PropertyChangedCondition& operator=(const PropertyChangedCondition&) = delete;
124 PropertyChangedCondition(PropertyChangedCondition&&) = default;
125 PropertyChangedCondition& operator=(PropertyChangedCondition&&) = default;
126 PropertyChangedCondition(const char* iface, const char* property,
127 U&& condition) :
Brad Bishop7b337772017-01-12 16:11:24 -0500128 _iface(iface),
129 _property(property),
130 _condition(std::forward<U>(condition)) { }
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400131
Brad Bishop7b337772017-01-12 16:11:24 -0500132 /** @brief Test a property value.
133 *
134 * Extract the property from the PropertiesChanged
135 * message and run the condition test.
136 */
Brad Bishop23719002017-01-24 21:08:46 -0500137 bool operator()(
138 sdbusplus::bus::bus&,
139 sdbusplus::message::message& msg,
140 Manager&) const
Brad Bishop7b337772017-01-12 16:11:24 -0500141 {
142 std::map <
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400143 std::string,
Brad Bishop7b337772017-01-12 16:11:24 -0500144 sdbusplus::message::variant<T >> properties;
145 const char* iface = nullptr;
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400146
Brad Bishop7b337772017-01-12 16:11:24 -0500147 msg.read(iface);
Brad Bishop064c94a2017-01-21 21:33:30 -0500148 if (!iface || strcmp(iface, _iface))
Brad Bishop7b337772017-01-12 16:11:24 -0500149 {
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400150 return false;
Brad Bishop7b337772017-01-12 16:11:24 -0500151 }
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400152
Brad Bishop7b337772017-01-12 16:11:24 -0500153 msg.read(properties);
154 auto it = properties.find(_property);
155 if (it == properties.cend())
156 {
157 return false;
158 }
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400159
Brad Bishopfb083c22017-01-19 09:22:04 -0500160 return _condition(
161 std::forward<T>(it->second.template get<T>()));
Brad Bishop7b337772017-01-12 16:11:24 -0500162 }
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400163
164 private:
Brad Bishop7b337772017-01-12 16:11:24 -0500165 const char* _iface;
166 const char* _property;
167 U _condition;
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400168};
169
Brad Bishopfa51da72017-01-19 11:06:51 -0500170/** @struct PropertyConditionBase
171 * @brief Match filter functor that tests a property value.
172 *
173 * Base class for PropertyCondition - factored out code that
174 * doesn't need to be templated.
175 */
176struct PropertyConditionBase
177{
178 PropertyConditionBase() = delete;
179 virtual ~PropertyConditionBase() = default;
180 PropertyConditionBase(const PropertyConditionBase&) = delete;
181 PropertyConditionBase& operator=(const PropertyConditionBase&) = delete;
182 PropertyConditionBase(PropertyConditionBase&&) = default;
183 PropertyConditionBase& operator=(PropertyConditionBase&&) = default;
184
185 /** @brief Constructor
186 *
187 * The service argument can be nullptr. If something
188 * else is provided the function will call the the
189 * service directly. If omitted, the function will
190 * look up the service in the ObjectMapper.
191 *
192 * @param path - The path of the object containing
193 * the property to be tested.
194 * @param iface - The interface hosting the property
195 * to be tested.
196 * @param property - The property to be tested.
197 * @param service - The DBus service hosting the object.
198 */
199 PropertyConditionBase(
200 const char* path,
201 const char* iface,
202 const char* property,
203 const char* service) :
204 _path(path),
205 _iface(iface),
206 _property(property),
207 _service(service) {}
208
209 /** @brief Forward comparison to type specific implementation. */
210 virtual bool eval(sdbusplus::message::message&) const = 0;
211
212 /** @brief Test a property value.
213 *
214 * Make a DBus call and test the value of any property.
215 */
216 bool operator()(
217 sdbusplus::bus::bus&,
218 sdbusplus::message::message&,
219 Manager&) const;
220
221 private:
222 std::string _path;
223 std::string _iface;
224 std::string _property;
225 const char* _service;
226};
227
228/** @struct PropertyCondition
229 * @brief Match filter functor that tests a property value.
230 *
231 * @tparam T - The type of the property being tested.
232 * @tparam U - The type of the condition checking functor.
233 */
234template <typename T, typename U>
235struct PropertyCondition final : public PropertyConditionBase
236{
237 PropertyCondition() = delete;
238 ~PropertyCondition() = default;
239 PropertyCondition(const PropertyCondition&) = delete;
240 PropertyCondition& operator=(const PropertyCondition&) = delete;
241 PropertyCondition(PropertyCondition&&) = default;
242 PropertyCondition& operator=(PropertyCondition&&) = default;
243
244 /** @brief Constructor
245 *
246 * The service argument can be nullptr. If something
247 * else is provided the function will call the the
248 * service directly. If omitted, the function will
249 * look up the service in the ObjectMapper.
250 *
251 * @param path - The path of the object containing
252 * the property to be tested.
253 * @param iface - The interface hosting the property
254 * to be tested.
255 * @param property - The property to be tested.
256 * @param condition - The test to run on the property.
257 * @param service - The DBus service hosting the object.
258 */
259 PropertyCondition(
260 const char* path,
261 const char* iface,
262 const char* property,
263 U&& condition,
264 const char* service) :
265 PropertyConditionBase(path, iface, property, service),
266 _condition(std::forward<decltype(condition)>(condition)) {}
267
268 /** @brief Test a property value.
269 *
270 * Make a DBus call and test the value of any property.
271 */
272 bool eval(sdbusplus::message::message& msg) const override
273 {
274 sdbusplus::message::variant<T> value;
275 msg.read(value);
276 return _condition(
277 std::forward<T>(value.template get<T>()));
278 }
279
280 private:
281 U _condition;
282};
283
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400284} // namespace property_condition
Brad Bishop3d57f502016-10-19 12:18:41 -0400285} // namespace details
286
Brad Bishop143522e2017-01-19 09:12:54 -0500287/** @brief Implicit type deduction for constructing PropertyChangedCondition. */
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400288template <typename T>
289auto propertyChangedTo(
Brad Bishop7b337772017-01-12 16:11:24 -0500290 const char* iface,
291 const char* property,
Brad Bishopfb083c22017-01-19 09:22:04 -0500292 T&& val)
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400293{
Brad Bishop76e2f6a2017-01-31 14:05:22 -0500294 auto condition = [val = std::forward<T>(val)](T && arg)
Brad Bishopd1bbf3a2016-12-01 00:03:26 -0500295 {
296 return arg == val;
297 };
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400298 using U = decltype(condition);
Brad Bishop143522e2017-01-19 09:12:54 -0500299 return details::property_condition::PropertyChangedCondition<T, U>(
Brad Bishop7b337772017-01-12 16:11:24 -0500300 iface, property, std::move(condition));
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400301}
302
Brad Bishopfa51da72017-01-19 11:06:51 -0500303/** @brief Implicit type deduction for constructing PropertyCondition. */
304template <typename T>
305auto propertyIs(
306 const char* path,
307 const char* iface,
308 const char* property,
309 T&& val,
310 const char* service = nullptr)
311{
312 auto condition = [val = std::forward<T>(val)](T && arg)
313 {
314 return arg == val;
315 };
316 using U = decltype(condition);
317 return details::property_condition::PropertyCondition<T, U>(
318 path, iface, property, std::move(condition), service);
319}
320
Brad Bishop3d57f502016-10-19 12:18:41 -0400321} // namespace filters
322} // namespace manager
323} // namespace inventory
324} // namespace phosphor
325
326// vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4