blob: e220550b6f39ada044486f4f0b5d4a0b9b05a39c [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 <sdbusplus/bus.hpp>
Brad Bishopa83db302020-12-06 14:51:23 -05007
8#include <memory>
Patrick Venturea680d1e2018-10-14 13:34:26 -07009#include <utility>
Brad Bishopc1f47982017-02-09 01:27:38 -050010
11namespace phosphor
12{
13namespace inventory
14{
15namespace manager
16{
17
18class Manager;
19
20/** @brief make_action
21 *
22 * Adapt an action function object.
23 *
24 * @param[in] action - The action being adapted.
25 * @returns - The adapted action.
26 *
27 * @tparam T - The type of the action being adapted.
28 */
Patrick Venturea680d1e2018-10-14 13:34:26 -070029template <typename T>
30auto make_action(T&& action)
Brad Bishopc1f47982017-02-09 01:27:38 -050031{
32 return Action(std::forward<T>(action));
33}
34
35/** @brief make_filter
36 *
37 * Adapt a filter function object.
38 *
39 * @param[in] filter - The filter being adapted.
40 * @returns - The adapted filter.
41 *
42 * @tparam T - The type of the filter being adapted.
43 */
Patrick Venturea680d1e2018-10-14 13:34:26 -070044template <typename T>
45auto make_filter(T&& filter)
Brad Bishopc1f47982017-02-09 01:27:38 -050046{
47 return Filter(std::forward<T>(filter));
48}
49
Brad Bishopd0f48ad2017-01-30 08:52:26 -050050/** @brief make_path_condition
51 *
52 * Adapt a path_condition function object.
53 *
54 * @param[in] filter - The functor being adapted.
55 * @returns - The adapted functor.
56 *
57 * @tparam T - The type of the functor being adapted.
58 */
Patrick Venturea680d1e2018-10-14 13:34:26 -070059template <typename T>
60auto make_path_condition(T&& condition)
Brad Bishopd0f48ad2017-01-30 08:52:26 -050061{
62 return PathCondition(std::forward<T>(condition));
63}
64
Matthew Barthf094d442018-09-26 15:06:15 -050065/** @brief make_get_property
66 *
67 * Adapt a get_property function object.
68 *
69 * @param[in] method - The functor being adapted.
70 * @returns - The adapted functor.
71 *
72 * @tparam T - The return type of the function object.
73 * @tparam U - The type of the functor being adapted.
74 */
75template <typename T, typename U>
76auto make_get_property(U&& method)
77{
78 return GetProperty<T>(std::forward<U>(method));
79}
80
Brad Bishop615b2a82018-03-29 10:32:41 -040081template <typename T, typename... Args>
82auto callArrayWithStatus(T&& container, Args&&... args)
Brad Bishopd0f48ad2017-01-30 08:52:26 -050083{
84 for (auto f : container)
85 {
86 if (!f(std::forward<Args>(args)...))
87 {
88 return false;
89 }
90 }
91 return true;
92}
93
Brad Bishopc1f47982017-02-09 01:27:38 -050094namespace functor
95{
96
97/** @brief Destroy objects action. */
Brad Bishop615b2a82018-03-29 10:32:41 -040098inline auto destroyObjects(std::vector<const char*>&& paths,
99 std::vector<PathCondition>&& conditions)
Brad Bishopc1f47982017-02-09 01:27:38 -0500100{
Brad Bishop615b2a82018-03-29 10:32:41 -0400101 return [=](auto& b, auto& m) {
Brad Bishopd0f48ad2017-01-30 08:52:26 -0500102 for (const auto& p : paths)
103 {
104 if (callArrayWithStatus(conditions, p, b, m))
105 {
106 m.destroyObjects({p});
107 }
108 }
Brad Bishopc1f47982017-02-09 01:27:38 -0500109 };
110}
111
112/** @brief Create objects action. */
Brad Bishop615b2a82018-03-29 10:32:41 -0400113inline auto
114 createObjects(std::map<sdbusplus::message::object_path, Object>&& objs)
Brad Bishopc1f47982017-02-09 01:27:38 -0500115{
Brad Bishop615b2a82018-03-29 10:32:41 -0400116 return [=](auto&, auto& m) { m.createObjects(objs); };
Brad Bishopc1f47982017-02-09 01:27:38 -0500117}
118
119/** @brief Set a property action.
120 *
121 * Invoke the requested method with a reference to the requested
122 * sdbusplus server binding interface as a parameter.
123 *
124 * @tparam T - The sdbusplus server binding interface type.
125 * @tparam U - The type of the sdbusplus server binding member
126 * function that sets the property.
127 * @tparam V - The property value type.
128 *
129 * @param[in] paths - The DBus paths on which the property should
130 * be set.
131 * @param[in] iface - The DBus interface hosting the property.
132 * @param[in] member - Pointer to sdbusplus server binding member.
133 * @param[in] value - The value the property should be set to.
134 *
135 * @returns - A function object that sets the requested property
136 * to the requested value.
137 */
138template <typename T, typename U, typename V>
Brad Bishop615b2a82018-03-29 10:32:41 -0400139auto setProperty(std::vector<const char*>&& paths,
140 std::vector<PathCondition>&& conditions, const char* iface,
141 U&& member, V&& value)
Brad Bishopc1f47982017-02-09 01:27:38 -0500142{
143 // The manager is the only parameter passed to actions.
144 // Bind the path, interface, interface member function pointer,
145 // and value to a lambda. When it is called, forward the
146 // path, interface and value on to the manager member function.
Patrick Venturea680d1e2018-10-14 13:34:26 -0700147 return [paths, conditions = conditions, iface, member,
148 value = std::forward<V>(value)](auto& b, auto& m) {
Brad Bishopc1f47982017-02-09 01:27:38 -0500149 for (auto p : paths)
150 {
Brad Bishopd0f48ad2017-01-30 08:52:26 -0500151 if (callArrayWithStatus(conditions, p, b, m))
152 {
Brad Bishop615b2a82018-03-29 10:32:41 -0400153 m.template invokeMethod<T>(p, iface, member, value);
Brad Bishopd0f48ad2017-01-30 08:52:26 -0500154 }
Brad Bishopc1f47982017-02-09 01:27:38 -0500155 }
156 };
157}
158
Matthew Barthf094d442018-09-26 15:06:15 -0500159/** @brief Get a property.
160 *
161 * Invoke the requested method with a reference to the requested
162 * sdbusplus server binding interface as a parameter.
163 *
164 * @tparam T - The sdbusplus server binding interface type.
165 * @tparam U - The type of the sdbusplus server binding member
166 * function that sets the property.
167 *
168 * @param[in] path - The DBus path to get the property from.
169 * @param[in] iface - The DBus interface hosting the property.
170 * @param[in] member - Pointer to sdbusplus server binding member.
171 * @param[in] prop - The property name to get the value from.
172 *
173 * @returns - A function object that gets the requested property.
174 */
175template <typename T, typename U>
176inline auto getProperty(const char* path, const char* iface, U&& member,
177 const char* prop)
178{
179 return [path, iface, member, prop](auto& mgr) {
180 return mgr.template invokeMethod<T>(path, iface, member, prop);
181 };
182}
183
Brad Bishopc1f47982017-02-09 01:27:38 -0500184/** @struct PropertyChangedCondition
185 * @brief Match filter functor that tests a property value.
186 *
187 * @tparam T - The type of the property being tested.
188 * @tparam U - The type of the condition checking functor.
189 */
Patrick Venturea680d1e2018-10-14 13:34:26 -0700190template <typename T, typename U>
191struct PropertyChangedCondition
Brad Bishopc1f47982017-02-09 01:27:38 -0500192{
Brad Bishop615b2a82018-03-29 10:32:41 -0400193 PropertyChangedCondition() = delete;
194 ~PropertyChangedCondition() = default;
195 PropertyChangedCondition(const PropertyChangedCondition&) = default;
196 PropertyChangedCondition&
197 operator=(const PropertyChangedCondition&) = default;
198 PropertyChangedCondition(PropertyChangedCondition&&) = default;
199 PropertyChangedCondition& operator=(PropertyChangedCondition&&) = default;
200 PropertyChangedCondition(const char* iface, const char* property,
201 U&& condition) :
202 _iface(iface),
203 _property(property), _condition(std::forward<U>(condition))
Brad Bishopa83db302020-12-06 14:51:23 -0500204 {}
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 {
Patrick Williams55f9eae2020-05-13 17:57:04 -0500214 std::map<std::string, std::variant<T>> properties;
Brad Bishop615b2a82018-03-29 10:32:41 -0400215 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)
Brad Bishopa83db302020-12-06 14:51:23 -0500272 {}
Brad Bishopc1f47982017-02-09 01:27:38 -0500273
Brad Bishop615b2a82018-03-29 10:32:41 -0400274 /** @brief Forward comparison to type specific implementation. */
275 virtual bool eval(sdbusplus::message::message&) const = 0;
Brad Bishopc1f47982017-02-09 01:27:38 -0500276
Matthew Barthf094d442018-09-26 15:06:15 -0500277 /** @brief Forward comparison to type specific implementation. */
278 virtual bool eval(Manager&) const = 0;
279
Brad Bishop615b2a82018-03-29 10:32:41 -0400280 /** @brief Test a property value.
281 *
282 * Make a DBus call and test the value of any property.
283 */
284 bool operator()(sdbusplus::bus::bus&, sdbusplus::message::message&,
285 Manager&) const;
Brad Bishopc1f47982017-02-09 01:27:38 -0500286
Brad Bishop615b2a82018-03-29 10:32:41 -0400287 /** @brief Test a property value.
288 *
289 * Make a DBus call and test the value of any property.
290 */
291 bool operator()(const std::string&, sdbusplus::bus::bus&, Manager&) const;
Brad Bishopd0f48ad2017-01-30 08:52:26 -0500292
Brad Bishop615b2a82018-03-29 10:32:41 -0400293 private:
294 std::string _path;
295 std::string _iface;
296 std::string _property;
297 const char* _service;
Brad Bishopc1f47982017-02-09 01:27:38 -0500298};
299
300/** @struct PropertyCondition
301 * @brief Match filter functor that tests a property value.
302 *
303 * @tparam T - The type of the property being tested.
304 * @tparam U - The type of the condition checking functor.
Matthew Barthf094d442018-09-26 15:06:15 -0500305 * @tparam V - The getProperty functor return type.
Brad Bishopc1f47982017-02-09 01:27:38 -0500306 */
Matthew Barthf094d442018-09-26 15:06:15 -0500307template <typename T, typename U, typename V>
Brad Bishopc1f47982017-02-09 01:27:38 -0500308struct PropertyCondition final : public PropertyConditionBase
309{
Brad Bishop615b2a82018-03-29 10:32:41 -0400310 PropertyCondition() = delete;
311 ~PropertyCondition() = default;
312 PropertyCondition(const PropertyCondition&) = default;
313 PropertyCondition& operator=(const PropertyCondition&) = default;
314 PropertyCondition(PropertyCondition&&) = default;
315 PropertyCondition& operator=(PropertyCondition&&) = default;
Brad Bishopc1f47982017-02-09 01:27:38 -0500316
Brad Bishop615b2a82018-03-29 10:32:41 -0400317 /** @brief Constructor
318 *
Matthew Barthf094d442018-09-26 15:06:15 -0500319 * The service & getProperty arguments can be nullptrs.
320 * If something else is provided the function will call the the
Brad Bishop615b2a82018-03-29 10:32:41 -0400321 * service directly. If omitted, the function will
322 * look up the service in the ObjectMapper.
Matthew Barthf094d442018-09-26 15:06:15 -0500323 * The getProperty function will be called to retrieve a property
324 * value when given and the property is hosted by inventory manager.
325 * When not given, the condition will default to return that the
326 * condition failed and will not be executed.
Brad Bishop615b2a82018-03-29 10:32:41 -0400327 *
328 * @param path - The path of the object containing
329 * the property to be tested.
330 * @param iface - The interface hosting the property
331 * to be tested.
332 * @param property - The property to be tested.
333 * @param condition - The test to run on the property.
334 * @param service - The DBus service hosting the object.
Matthew Barthf094d442018-09-26 15:06:15 -0500335 * @param getProperty - The function to get a property value
336 * for the condition.
Brad Bishop615b2a82018-03-29 10:32:41 -0400337 */
338 PropertyCondition(const char* path, const char* iface, const char* property,
Matthew Barthf094d442018-09-26 15:06:15 -0500339 U&& condition, const char* service,
340 GetProperty<V>&& getProperty = nullptr) :
Brad Bishop615b2a82018-03-29 10:32:41 -0400341 PropertyConditionBase(path, iface, property, service),
Matthew Barthf094d442018-09-26 15:06:15 -0500342 _condition(std::forward<decltype(condition)>(condition)),
343 _getProperty(getProperty)
Brad Bishopa83db302020-12-06 14:51:23 -0500344 {}
Brad Bishopc1f47982017-02-09 01:27:38 -0500345
Brad Bishop615b2a82018-03-29 10:32:41 -0400346 /** @brief Test a property value.
347 *
348 * Make a DBus call and test the value of any property.
349 */
350 bool eval(sdbusplus::message::message& msg) const override
351 {
Patrick Williams55f9eae2020-05-13 17:57:04 -0500352 std::variant<T> value;
Brad Bishop615b2a82018-03-29 10:32:41 -0400353 msg.read(value);
Patrick Williams26f86682020-05-13 11:36:19 -0500354 return _condition(std::forward<T>(std::get<T>(value)));
Brad Bishop615b2a82018-03-29 10:32:41 -0400355 }
Brad Bishopc1f47982017-02-09 01:27:38 -0500356
Matthew Barthf094d442018-09-26 15:06:15 -0500357 /** @brief Retrieve a property value from inventory and test it.
358 *
359 * Get a property from the inventory manager and test the value.
360 * Default to fail the test where no function is given to get the
361 * property from the inventory manager.
362 */
363 bool eval(Manager& mgr) const override
364 {
365 if (_getProperty)
366 {
367 auto variant = _getProperty(mgr);
Patrick Williams26f86682020-05-13 11:36:19 -0500368 auto value = std::get<T>(variant);
Matthew Barthf094d442018-09-26 15:06:15 -0500369 return _condition(std::forward<T>(value));
370 }
371 return false;
372 }
373
Brad Bishop615b2a82018-03-29 10:32:41 -0400374 private:
375 U _condition;
Matthew Barthf094d442018-09-26 15:06:15 -0500376 GetProperty<V> _getProperty;
Brad Bishopc1f47982017-02-09 01:27:38 -0500377};
378
Brad Bishop615b2a82018-03-29 10:32:41 -0400379/** @brief Implicit type deduction for constructing PropertyChangedCondition. */
Brad Bishopc1f47982017-02-09 01:27:38 -0500380template <typename T>
Brad Bishop615b2a82018-03-29 10:32:41 -0400381auto propertyChangedTo(const char* iface, const char* property, T&& val)
Brad Bishopc1f47982017-02-09 01:27:38 -0500382{
Patrick Venturea680d1e2018-10-14 13:34:26 -0700383 auto condition = [val = std::forward<T>(val)](T&& arg) {
Brad Bishopc1f47982017-02-09 01:27:38 -0500384 return arg == val;
385 };
386 using U = decltype(condition);
Brad Bishop615b2a82018-03-29 10:32:41 -0400387 return PropertyChangedCondition<T, U>(iface, property,
388 std::move(condition));
Brad Bishopc1f47982017-02-09 01:27:38 -0500389}
390
391/** @brief Implicit type deduction for constructing PropertyCondition. */
Matthew Barthf094d442018-09-26 15:06:15 -0500392template <typename T, typename V = InterfaceVariantType>
Brad Bishop615b2a82018-03-29 10:32:41 -0400393auto propertyIs(const char* path, const char* iface, const char* property,
Matthew Barthf094d442018-09-26 15:06:15 -0500394 T&& val, const char* service = nullptr,
395 GetProperty<V>&& getProperty = nullptr)
Brad Bishopc1f47982017-02-09 01:27:38 -0500396{
Patrick Venturea680d1e2018-10-14 13:34:26 -0700397 auto condition = [val = std::forward<T>(val)](T&& arg) {
Brad Bishopc1f47982017-02-09 01:27:38 -0500398 return arg == val;
399 };
400 using U = decltype(condition);
Matthew Barthf094d442018-09-26 15:06:15 -0500401 return PropertyCondition<T, U, V>(path, iface, property,
402 std::move(condition), service,
403 std::move(getProperty));
Brad Bishopc1f47982017-02-09 01:27:38 -0500404}
405} // namespace functor
406} // namespace manager
407} // namespace inventory
408} // namespace phosphor
409
410// vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4