blob: 0c328d93460b82539481bf7e6527eeb2a5a24371 [file] [log] [blame]
Brad Bishopc1f47982017-02-09 01:27:38 -05001#pragma once
2
Patrick Venturea680d1e2018-10-14 13:34:26 -07003#include "types.hpp"
4#include "utils.hpp"
5
Brad Bishopc1f47982017-02-09 01:27:38 -05006#include <memory>
7#include <sdbusplus/bus.hpp>
Patrick Venturea680d1e2018-10-14 13:34:26 -07008#include <utility>
Brad Bishopc1f47982017-02-09 01:27:38 -05009
10namespace phosphor
11{
12namespace inventory
13{
14namespace manager
15{
16
17class Manager;
18
19/** @brief make_action
20 *
21 * Adapt an action function object.
22 *
23 * @param[in] action - The action being adapted.
24 * @returns - The adapted action.
25 *
26 * @tparam T - The type of the action being adapted.
27 */
Patrick Venturea680d1e2018-10-14 13:34:26 -070028template <typename T>
29auto make_action(T&& action)
Brad Bishopc1f47982017-02-09 01:27:38 -050030{
31 return Action(std::forward<T>(action));
32}
33
34/** @brief make_filter
35 *
36 * Adapt a filter function object.
37 *
38 * @param[in] filter - The filter being adapted.
39 * @returns - The adapted filter.
40 *
41 * @tparam T - The type of the filter being adapted.
42 */
Patrick Venturea680d1e2018-10-14 13:34:26 -070043template <typename T>
44auto make_filter(T&& filter)
Brad Bishopc1f47982017-02-09 01:27:38 -050045{
46 return Filter(std::forward<T>(filter));
47}
48
Brad Bishopd0f48ad2017-01-30 08:52:26 -050049/** @brief make_path_condition
50 *
51 * Adapt a path_condition function object.
52 *
53 * @param[in] filter - The functor being adapted.
54 * @returns - The adapted functor.
55 *
56 * @tparam T - The type of the functor being adapted.
57 */
Patrick Venturea680d1e2018-10-14 13:34:26 -070058template <typename T>
59auto make_path_condition(T&& condition)
Brad Bishopd0f48ad2017-01-30 08:52:26 -050060{
61 return PathCondition(std::forward<T>(condition));
62}
63
Matthew Barthf094d442018-09-26 15:06:15 -050064/** @brief make_get_property
65 *
66 * Adapt a get_property function object.
67 *
68 * @param[in] method - The functor being adapted.
69 * @returns - The adapted functor.
70 *
71 * @tparam T - The return type of the function object.
72 * @tparam U - The type of the functor being adapted.
73 */
74template <typename T, typename U>
75auto make_get_property(U&& method)
76{
77 return GetProperty<T>(std::forward<U>(method));
78}
79
Brad Bishop615b2a82018-03-29 10:32:41 -040080template <typename T, typename... Args>
81auto callArrayWithStatus(T&& container, Args&&... args)
Brad Bishopd0f48ad2017-01-30 08:52:26 -050082{
83 for (auto f : container)
84 {
85 if (!f(std::forward<Args>(args)...))
86 {
87 return false;
88 }
89 }
90 return true;
91}
92
Brad Bishopc1f47982017-02-09 01:27:38 -050093namespace functor
94{
95
96/** @brief Destroy objects action. */
Brad Bishop615b2a82018-03-29 10:32:41 -040097inline auto destroyObjects(std::vector<const char*>&& paths,
98 std::vector<PathCondition>&& conditions)
Brad Bishopc1f47982017-02-09 01:27:38 -050099{
Brad Bishop615b2a82018-03-29 10:32:41 -0400100 return [=](auto& b, auto& m) {
Brad Bishopd0f48ad2017-01-30 08:52:26 -0500101 for (const auto& p : paths)
102 {
103 if (callArrayWithStatus(conditions, p, b, m))
104 {
105 m.destroyObjects({p});
106 }
107 }
Brad Bishopc1f47982017-02-09 01:27:38 -0500108 };
109}
110
111/** @brief Create objects action. */
Brad Bishop615b2a82018-03-29 10:32:41 -0400112inline auto
113 createObjects(std::map<sdbusplus::message::object_path, Object>&& objs)
Brad Bishopc1f47982017-02-09 01:27:38 -0500114{
Brad Bishop615b2a82018-03-29 10:32:41 -0400115 return [=](auto&, auto& m) { m.createObjects(objs); };
Brad Bishopc1f47982017-02-09 01:27:38 -0500116}
117
118/** @brief Set a property action.
119 *
120 * Invoke the requested method with a reference to the requested
121 * sdbusplus server binding interface as a parameter.
122 *
123 * @tparam T - The sdbusplus server binding interface type.
124 * @tparam U - The type of the sdbusplus server binding member
125 * function that sets the property.
126 * @tparam V - The property value type.
127 *
128 * @param[in] paths - The DBus paths on which the property should
129 * be set.
130 * @param[in] iface - The DBus interface hosting the property.
131 * @param[in] member - Pointer to sdbusplus server binding member.
132 * @param[in] value - The value the property should be set to.
133 *
134 * @returns - A function object that sets the requested property
135 * to the requested value.
136 */
137template <typename T, typename U, typename V>
Brad Bishop615b2a82018-03-29 10:32:41 -0400138auto setProperty(std::vector<const char*>&& paths,
139 std::vector<PathCondition>&& conditions, const char* iface,
140 U&& member, V&& value)
Brad Bishopc1f47982017-02-09 01:27:38 -0500141{
142 // The manager is the only parameter passed to actions.
143 // Bind the path, interface, interface member function pointer,
144 // and value to a lambda. When it is called, forward the
145 // path, interface and value on to the manager member function.
Patrick Venturea680d1e2018-10-14 13:34:26 -0700146 return [paths, conditions = conditions, iface, member,
147 value = std::forward<V>(value)](auto& b, auto& m) {
Brad Bishopc1f47982017-02-09 01:27:38 -0500148 for (auto p : paths)
149 {
Brad Bishopd0f48ad2017-01-30 08:52:26 -0500150 if (callArrayWithStatus(conditions, p, b, m))
151 {
Brad Bishop615b2a82018-03-29 10:32:41 -0400152 m.template invokeMethod<T>(p, iface, member, value);
Brad Bishopd0f48ad2017-01-30 08:52:26 -0500153 }
Brad Bishopc1f47982017-02-09 01:27:38 -0500154 }
155 };
156}
157
Matthew Barthf094d442018-09-26 15:06:15 -0500158/** @brief Get a property.
159 *
160 * Invoke the requested method with a reference to the requested
161 * sdbusplus server binding interface as a parameter.
162 *
163 * @tparam T - The sdbusplus server binding interface type.
164 * @tparam U - The type of the sdbusplus server binding member
165 * function that sets the property.
166 *
167 * @param[in] path - The DBus path to get the property from.
168 * @param[in] iface - The DBus interface hosting the property.
169 * @param[in] member - Pointer to sdbusplus server binding member.
170 * @param[in] prop - The property name to get the value from.
171 *
172 * @returns - A function object that gets the requested property.
173 */
174template <typename T, typename U>
175inline auto getProperty(const char* path, const char* iface, U&& member,
176 const char* prop)
177{
178 return [path, iface, member, prop](auto& mgr) {
179 return mgr.template invokeMethod<T>(path, iface, member, prop);
180 };
181}
182
Brad Bishopc1f47982017-02-09 01:27:38 -0500183/** @struct PropertyChangedCondition
184 * @brief Match filter functor that tests a property value.
185 *
186 * @tparam T - The type of the property being tested.
187 * @tparam U - The type of the condition checking functor.
188 */
Patrick Venturea680d1e2018-10-14 13:34:26 -0700189template <typename T, typename U>
190struct PropertyChangedCondition
Brad Bishopc1f47982017-02-09 01:27:38 -0500191{
Brad Bishop615b2a82018-03-29 10:32:41 -0400192 PropertyChangedCondition() = delete;
193 ~PropertyChangedCondition() = default;
194 PropertyChangedCondition(const PropertyChangedCondition&) = default;
195 PropertyChangedCondition&
196 operator=(const PropertyChangedCondition&) = default;
197 PropertyChangedCondition(PropertyChangedCondition&&) = default;
198 PropertyChangedCondition& operator=(PropertyChangedCondition&&) = default;
199 PropertyChangedCondition(const char* iface, const char* property,
200 U&& condition) :
201 _iface(iface),
202 _property(property), _condition(std::forward<U>(condition))
203 {
204 }
Brad Bishopc1f47982017-02-09 01:27:38 -0500205
Brad Bishop615b2a82018-03-29 10:32:41 -0400206 /** @brief Test a property value.
207 *
208 * Extract the property from the PropertiesChanged
209 * message and run the condition test.
210 */
211 bool operator()(sdbusplus::bus::bus&, sdbusplus::message::message& msg,
212 Manager&) const
213 {
214 std::map<std::string, sdbusplus::message::variant<T>> properties;
215 const char* iface = nullptr;
216
217 msg.read(iface);
218 if (!iface || strcmp(iface, _iface))
Brad Bishopc1f47982017-02-09 01:27:38 -0500219 {
Brad Bishop615b2a82018-03-29 10:32:41 -0400220 return false;
Brad Bishopc1f47982017-02-09 01:27:38 -0500221 }
222
Brad Bishop615b2a82018-03-29 10:32:41 -0400223 msg.read(properties);
224 auto it = properties.find(_property);
225 if (it == properties.cend())
226 {
227 return false;
228 }
229
Patrick Williams26f86682020-05-13 11:36:19 -0500230 return _condition(std::forward<T>(std::get<T>(it->second)));
Brad Bishop615b2a82018-03-29 10:32:41 -0400231 }
232
233 private:
234 const char* _iface;
235 const char* _property;
236 U _condition;
Brad Bishopc1f47982017-02-09 01:27:38 -0500237};
238
239/** @struct PropertyConditionBase
240 * @brief Match filter functor that tests a property value.
241 *
242 * Base class for PropertyCondition - factored out code that
243 * doesn't need to be templated.
244 */
245struct PropertyConditionBase
246{
Brad Bishop615b2a82018-03-29 10:32:41 -0400247 PropertyConditionBase() = delete;
248 virtual ~PropertyConditionBase() = default;
249 PropertyConditionBase(const PropertyConditionBase&) = default;
250 PropertyConditionBase& operator=(const PropertyConditionBase&) = default;
251 PropertyConditionBase(PropertyConditionBase&&) = default;
252 PropertyConditionBase& operator=(PropertyConditionBase&&) = default;
Brad Bishopc1f47982017-02-09 01:27:38 -0500253
Brad Bishop615b2a82018-03-29 10:32:41 -0400254 /** @brief Constructor
255 *
256 * The service argument can be nullptr. If something
257 * else is provided the function will call the the
258 * service directly. If omitted, the function will
259 * look up the service in the ObjectMapper.
260 *
261 * @param path - The path of the object containing
262 * the property to be tested.
263 * @param iface - The interface hosting the property
264 * to be tested.
265 * @param property - The property to be tested.
266 * @param service - The DBus service hosting the object.
267 */
268 PropertyConditionBase(const char* path, const char* iface,
269 const char* property, const char* service) :
270 _path(path ? path : std::string()),
271 _iface(iface), _property(property), _service(service)
272 {
273 }
Brad Bishopc1f47982017-02-09 01:27:38 -0500274
Brad Bishop615b2a82018-03-29 10:32:41 -0400275 /** @brief Forward comparison to type specific implementation. */
276 virtual bool eval(sdbusplus::message::message&) const = 0;
Brad Bishopc1f47982017-02-09 01:27:38 -0500277
Matthew Barthf094d442018-09-26 15:06:15 -0500278 /** @brief Forward comparison to type specific implementation. */
279 virtual bool eval(Manager&) const = 0;
280
Brad Bishop615b2a82018-03-29 10:32:41 -0400281 /** @brief Test a property value.
282 *
283 * Make a DBus call and test the value of any property.
284 */
285 bool operator()(sdbusplus::bus::bus&, sdbusplus::message::message&,
286 Manager&) const;
Brad Bishopc1f47982017-02-09 01:27:38 -0500287
Brad Bishop615b2a82018-03-29 10:32:41 -0400288 /** @brief Test a property value.
289 *
290 * Make a DBus call and test the value of any property.
291 */
292 bool operator()(const std::string&, sdbusplus::bus::bus&, Manager&) const;
Brad Bishopd0f48ad2017-01-30 08:52:26 -0500293
Brad Bishop615b2a82018-03-29 10:32:41 -0400294 private:
295 std::string _path;
296 std::string _iface;
297 std::string _property;
298 const char* _service;
Brad Bishopc1f47982017-02-09 01:27:38 -0500299};
300
301/** @struct PropertyCondition
302 * @brief Match filter functor that tests a property value.
303 *
304 * @tparam T - The type of the property being tested.
305 * @tparam U - The type of the condition checking functor.
Matthew Barthf094d442018-09-26 15:06:15 -0500306 * @tparam V - The getProperty functor return type.
Brad Bishopc1f47982017-02-09 01:27:38 -0500307 */
Matthew Barthf094d442018-09-26 15:06:15 -0500308template <typename T, typename U, typename V>
Brad Bishopc1f47982017-02-09 01:27:38 -0500309struct PropertyCondition final : public PropertyConditionBase
310{
Brad Bishop615b2a82018-03-29 10:32:41 -0400311 PropertyCondition() = delete;
312 ~PropertyCondition() = default;
313 PropertyCondition(const PropertyCondition&) = default;
314 PropertyCondition& operator=(const PropertyCondition&) = default;
315 PropertyCondition(PropertyCondition&&) = default;
316 PropertyCondition& operator=(PropertyCondition&&) = default;
Brad Bishopc1f47982017-02-09 01:27:38 -0500317
Brad Bishop615b2a82018-03-29 10:32:41 -0400318 /** @brief Constructor
319 *
Matthew Barthf094d442018-09-26 15:06:15 -0500320 * The service & getProperty arguments can be nullptrs.
321 * If something else is provided the function will call the the
Brad Bishop615b2a82018-03-29 10:32:41 -0400322 * service directly. If omitted, the function will
323 * look up the service in the ObjectMapper.
Matthew Barthf094d442018-09-26 15:06:15 -0500324 * The getProperty function will be called to retrieve a property
325 * value when given and the property is hosted by inventory manager.
326 * When not given, the condition will default to return that the
327 * condition failed and will not be executed.
Brad Bishop615b2a82018-03-29 10:32:41 -0400328 *
329 * @param path - The path of the object containing
330 * the property to be tested.
331 * @param iface - The interface hosting the property
332 * to be tested.
333 * @param property - The property to be tested.
334 * @param condition - The test to run on the property.
335 * @param service - The DBus service hosting the object.
Matthew Barthf094d442018-09-26 15:06:15 -0500336 * @param getProperty - The function to get a property value
337 * for the condition.
Brad Bishop615b2a82018-03-29 10:32:41 -0400338 */
339 PropertyCondition(const char* path, const char* iface, const char* property,
Matthew Barthf094d442018-09-26 15:06:15 -0500340 U&& condition, const char* service,
341 GetProperty<V>&& getProperty = nullptr) :
Brad Bishop615b2a82018-03-29 10:32:41 -0400342 PropertyConditionBase(path, iface, property, service),
Matthew Barthf094d442018-09-26 15:06:15 -0500343 _condition(std::forward<decltype(condition)>(condition)),
344 _getProperty(getProperty)
Brad Bishop615b2a82018-03-29 10:32:41 -0400345 {
346 }
Brad Bishopc1f47982017-02-09 01:27:38 -0500347
Brad Bishop615b2a82018-03-29 10:32:41 -0400348 /** @brief Test a property value.
349 *
350 * Make a DBus call and test the value of any property.
351 */
352 bool eval(sdbusplus::message::message& msg) const override
353 {
354 sdbusplus::message::variant<T> value;
355 msg.read(value);
Patrick Williams26f86682020-05-13 11:36:19 -0500356 return _condition(std::forward<T>(std::get<T>(value)));
Brad Bishop615b2a82018-03-29 10:32:41 -0400357 }
Brad Bishopc1f47982017-02-09 01:27:38 -0500358
Matthew Barthf094d442018-09-26 15:06:15 -0500359 /** @brief Retrieve a property value from inventory and test it.
360 *
361 * Get a property from the inventory manager and test the value.
362 * Default to fail the test where no function is given to get the
363 * property from the inventory manager.
364 */
365 bool eval(Manager& mgr) const override
366 {
367 if (_getProperty)
368 {
369 auto variant = _getProperty(mgr);
Patrick Williams26f86682020-05-13 11:36:19 -0500370 auto value = std::get<T>(variant);
Matthew Barthf094d442018-09-26 15:06:15 -0500371 return _condition(std::forward<T>(value));
372 }
373 return false;
374 }
375
Brad Bishop615b2a82018-03-29 10:32:41 -0400376 private:
377 U _condition;
Matthew Barthf094d442018-09-26 15:06:15 -0500378 GetProperty<V> _getProperty;
Brad Bishopc1f47982017-02-09 01:27:38 -0500379};
380
Brad Bishop615b2a82018-03-29 10:32:41 -0400381/** @brief Implicit type deduction for constructing PropertyChangedCondition. */
Brad Bishopc1f47982017-02-09 01:27:38 -0500382template <typename T>
Brad Bishop615b2a82018-03-29 10:32:41 -0400383auto propertyChangedTo(const char* iface, const char* property, T&& val)
Brad Bishopc1f47982017-02-09 01:27:38 -0500384{
Patrick Venturea680d1e2018-10-14 13:34:26 -0700385 auto condition = [val = std::forward<T>(val)](T&& arg) {
Brad Bishopc1f47982017-02-09 01:27:38 -0500386 return arg == val;
387 };
388 using U = decltype(condition);
Brad Bishop615b2a82018-03-29 10:32:41 -0400389 return PropertyChangedCondition<T, U>(iface, property,
390 std::move(condition));
Brad Bishopc1f47982017-02-09 01:27:38 -0500391}
392
393/** @brief Implicit type deduction for constructing PropertyCondition. */
Matthew Barthf094d442018-09-26 15:06:15 -0500394template <typename T, typename V = InterfaceVariantType>
Brad Bishop615b2a82018-03-29 10:32:41 -0400395auto propertyIs(const char* path, const char* iface, const char* property,
Matthew Barthf094d442018-09-26 15:06:15 -0500396 T&& val, const char* service = nullptr,
397 GetProperty<V>&& getProperty = nullptr)
Brad Bishopc1f47982017-02-09 01:27:38 -0500398{
Patrick Venturea680d1e2018-10-14 13:34:26 -0700399 auto condition = [val = std::forward<T>(val)](T&& arg) {
Brad Bishopc1f47982017-02-09 01:27:38 -0500400 return arg == val;
401 };
402 using U = decltype(condition);
Matthew Barthf094d442018-09-26 15:06:15 -0500403 return PropertyCondition<T, U, V>(path, iface, property,
404 std::move(condition), service,
405 std::move(getProperty));
Brad Bishopc1f47982017-02-09 01:27:38 -0500406}
407} // namespace functor
408} // namespace manager
409} // namespace inventory
410} // namespace phosphor
411
412// vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4