blob: 78b63aba0b98610c395f6f554730e9c00ac66d72 [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.
27 */
28struct Event
29{
30 enum class Type
31 {
32 DBUS_SIGNAL,
33 };
34
35 virtual ~Event() = default;
36 Event(const Event&) = default;
37 Event& operator=(const Event&) = default;
38 Event(Event&&) = default;
39 Event& operator=(Event&&) = default;
40 explicit Event(Type t) : type(t) {}
41
42 Type type;
43};
44
45using EventBasePtr = std::shared_ptr<Event>;
46
47/** @struct DbusSignal
48 * @brief DBus signal event.
49 *
50 * DBus signal events are an association of a match signature
51 * and filtering function object.
52 */
53struct DbusSignal final :
54 public Event,
Brad Bishop064c94a2017-01-21 21:33:30 -050055 public std::tuple<const char*, std::vector<FilterBasePtr>>
Brad Bishop4f20a3e2016-11-29 15:21:46 -050056{
57 virtual ~DbusSignal() = default;
58 DbusSignal(const DbusSignal&) = default;
Brad Bishop7b337772017-01-12 16:11:24 -050059 DbusSignal& operator=(const DbusSignal&) = delete;
Brad Bishop4f20a3e2016-11-29 15:21:46 -050060 DbusSignal(DbusSignal&&) = default;
61 DbusSignal& operator=(DbusSignal&&) = default;
62
63 /** @brief Import from signature and filter constructor.
64 *
65 * @param[in] sig - The DBus match signature.
66 * @param[in] filter - A DBus signal match callback filtering function.
67 */
Brad Bishop064c94a2017-01-21 21:33:30 -050068 DbusSignal(const char* sig, const std::vector<FilterBasePtr>& filters) :
Brad Bishop4f20a3e2016-11-29 15:21:46 -050069 Event(Type::DBUS_SIGNAL),
Brad Bishop064c94a2017-01-21 21:33:30 -050070 std::tuple<const char*, std::vector<FilterBasePtr>>(
71 sig, std::move(filters)) {}
Brad Bishop4f20a3e2016-11-29 15:21:46 -050072};
73
Brad Bishop65ffffa2016-11-29 12:31:31 -050074/** @brief make_filter
75 *
76 * Adapt a filter function object.
77 *
78 * @param[in] filter - The filter being adapted.
79 * @returns - The adapted filter.
80 *
81 * @tparam T - The type of the filter being adapted.
82 */
83template <typename T>
84auto make_filter(T&& filter)
85{
86 return Filter<T>::template make_shared<Filter<T>>(
87 std::forward<T>(filter));
88}
89} // namespace details
90
Brad Bishop3d57f502016-10-19 12:18:41 -040091namespace filters
92{
93namespace details
94{
Brad Bishopbf5aa9c2016-10-19 21:19:04 -040095namespace property_condition
96{
97
Brad Bishop143522e2017-01-19 09:12:54 -050098/** @struct PropertyChangedCondition
Brad Bishopbf5aa9c2016-10-19 21:19:04 -040099 * @brief Match filter functor that tests a property value.
100 *
101 * @tparam T - The type of the property being tested.
102 * @tparam U - The type of the condition checking functor.
103 */
104template <typename T, typename U>
Brad Bishop143522e2017-01-19 09:12:54 -0500105struct PropertyChangedCondition
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400106{
Brad Bishop143522e2017-01-19 09:12:54 -0500107 PropertyChangedCondition() = delete;
108 ~PropertyChangedCondition() = default;
109 PropertyChangedCondition(const PropertyChangedCondition&) = default;
110 PropertyChangedCondition& operator=(const PropertyChangedCondition&) = delete;
111 PropertyChangedCondition(PropertyChangedCondition&&) = default;
112 PropertyChangedCondition& operator=(PropertyChangedCondition&&) = default;
113 PropertyChangedCondition(const char* iface, const char* property,
114 U&& condition) :
Brad Bishop7b337772017-01-12 16:11:24 -0500115 _iface(iface),
116 _property(property),
117 _condition(std::forward<U>(condition)) { }
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400118
Brad Bishop7b337772017-01-12 16:11:24 -0500119 /** @brief Test a property value.
120 *
121 * Extract the property from the PropertiesChanged
122 * message and run the condition test.
123 */
Brad Bishop23719002017-01-24 21:08:46 -0500124 bool operator()(
125 sdbusplus::bus::bus&,
126 sdbusplus::message::message& msg,
127 Manager&) const
Brad Bishop7b337772017-01-12 16:11:24 -0500128 {
129 std::map <
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400130 std::string,
Brad Bishop7b337772017-01-12 16:11:24 -0500131 sdbusplus::message::variant<T >> properties;
132 const char* iface = nullptr;
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400133
Brad Bishop7b337772017-01-12 16:11:24 -0500134 msg.read(iface);
Brad Bishop064c94a2017-01-21 21:33:30 -0500135 if (!iface || strcmp(iface, _iface))
Brad Bishop7b337772017-01-12 16:11:24 -0500136 {
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400137 return false;
Brad Bishop7b337772017-01-12 16:11:24 -0500138 }
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400139
Brad Bishop7b337772017-01-12 16:11:24 -0500140 msg.read(properties);
141 auto it = properties.find(_property);
142 if (it == properties.cend())
143 {
144 return false;
145 }
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400146
Brad Bishopfb083c22017-01-19 09:22:04 -0500147 return _condition(
148 std::forward<T>(it->second.template get<T>()));
Brad Bishop7b337772017-01-12 16:11:24 -0500149 }
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400150
151 private:
Brad Bishop7b337772017-01-12 16:11:24 -0500152 const char* _iface;
153 const char* _property;
154 U _condition;
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400155};
156
Brad Bishopfa51da72017-01-19 11:06:51 -0500157/** @struct PropertyConditionBase
158 * @brief Match filter functor that tests a property value.
159 *
160 * Base class for PropertyCondition - factored out code that
161 * doesn't need to be templated.
162 */
163struct PropertyConditionBase
164{
165 PropertyConditionBase() = delete;
166 virtual ~PropertyConditionBase() = default;
167 PropertyConditionBase(const PropertyConditionBase&) = delete;
168 PropertyConditionBase& operator=(const PropertyConditionBase&) = delete;
169 PropertyConditionBase(PropertyConditionBase&&) = default;
170 PropertyConditionBase& operator=(PropertyConditionBase&&) = default;
171
172 /** @brief Constructor
173 *
174 * The service argument can be nullptr. If something
175 * else is provided the function will call the the
176 * service directly. If omitted, the function will
177 * look up the service in the ObjectMapper.
178 *
179 * @param path - The path of the object containing
180 * the property to be tested.
181 * @param iface - The interface hosting the property
182 * to be tested.
183 * @param property - The property to be tested.
184 * @param service - The DBus service hosting the object.
185 */
186 PropertyConditionBase(
187 const char* path,
188 const char* iface,
189 const char* property,
190 const char* service) :
191 _path(path),
192 _iface(iface),
193 _property(property),
194 _service(service) {}
195
196 /** @brief Forward comparison to type specific implementation. */
197 virtual bool eval(sdbusplus::message::message&) const = 0;
198
199 /** @brief Test a property value.
200 *
201 * Make a DBus call and test the value of any property.
202 */
203 bool operator()(
204 sdbusplus::bus::bus&,
205 sdbusplus::message::message&,
206 Manager&) const;
207
208 private:
209 std::string _path;
210 std::string _iface;
211 std::string _property;
212 const char* _service;
213};
214
215/** @struct PropertyCondition
216 * @brief Match filter functor that tests a property value.
217 *
218 * @tparam T - The type of the property being tested.
219 * @tparam U - The type of the condition checking functor.
220 */
221template <typename T, typename U>
222struct PropertyCondition final : public PropertyConditionBase
223{
224 PropertyCondition() = delete;
225 ~PropertyCondition() = default;
226 PropertyCondition(const PropertyCondition&) = delete;
227 PropertyCondition& operator=(const PropertyCondition&) = delete;
228 PropertyCondition(PropertyCondition&&) = default;
229 PropertyCondition& operator=(PropertyCondition&&) = default;
230
231 /** @brief Constructor
232 *
233 * The service argument can be nullptr. If something
234 * else is provided the function will call the the
235 * service directly. If omitted, the function will
236 * look up the service in the ObjectMapper.
237 *
238 * @param path - The path of the object containing
239 * the property to be tested.
240 * @param iface - The interface hosting the property
241 * to be tested.
242 * @param property - The property to be tested.
243 * @param condition - The test to run on the property.
244 * @param service - The DBus service hosting the object.
245 */
246 PropertyCondition(
247 const char* path,
248 const char* iface,
249 const char* property,
250 U&& condition,
251 const char* service) :
252 PropertyConditionBase(path, iface, property, service),
253 _condition(std::forward<decltype(condition)>(condition)) {}
254
255 /** @brief Test a property value.
256 *
257 * Make a DBus call and test the value of any property.
258 */
259 bool eval(sdbusplus::message::message& msg) const override
260 {
261 sdbusplus::message::variant<T> value;
262 msg.read(value);
263 return _condition(
264 std::forward<T>(value.template get<T>()));
265 }
266
267 private:
268 U _condition;
269};
270
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400271} // namespace property_condition
Brad Bishop3d57f502016-10-19 12:18:41 -0400272} // namespace details
273
Brad Bishop143522e2017-01-19 09:12:54 -0500274/** @brief Implicit type deduction for constructing PropertyChangedCondition. */
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400275template <typename T>
276auto propertyChangedTo(
Brad Bishop7b337772017-01-12 16:11:24 -0500277 const char* iface,
278 const char* property,
Brad Bishopfb083c22017-01-19 09:22:04 -0500279 T&& val)
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400280{
Brad Bishop76e2f6a2017-01-31 14:05:22 -0500281 auto condition = [val = std::forward<T>(val)](T && arg)
Brad Bishopd1bbf3a2016-12-01 00:03:26 -0500282 {
283 return arg == val;
284 };
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400285 using U = decltype(condition);
Brad Bishop143522e2017-01-19 09:12:54 -0500286 return details::property_condition::PropertyChangedCondition<T, U>(
Brad Bishop7b337772017-01-12 16:11:24 -0500287 iface, property, std::move(condition));
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400288}
289
Brad Bishopfa51da72017-01-19 11:06:51 -0500290/** @brief Implicit type deduction for constructing PropertyCondition. */
291template <typename T>
292auto propertyIs(
293 const char* path,
294 const char* iface,
295 const char* property,
296 T&& val,
297 const char* service = nullptr)
298{
299 auto condition = [val = std::forward<T>(val)](T && arg)
300 {
301 return arg == val;
302 };
303 using U = decltype(condition);
304 return details::property_condition::PropertyCondition<T, U>(
305 path, iface, property, std::move(condition), service);
306}
307
Brad Bishop3d57f502016-10-19 12:18:41 -0400308} // namespace filters
309} // namespace manager
310} // namespace inventory
311} // namespace phosphor
312
313// vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4