blob: 903cbd0a216881ceb26f0d490437c0743ece4b1f [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 */
Patrick Williams563306f2022-07-22 19:26:52 -0500211 bool operator()(sdbusplus::bus_t&, sdbusplus::message_t& msg,
Brad Bishop615b2a82018-03-29 10:32:41 -0400212 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. */
Patrick Williams563306f2022-07-22 19:26:52 -0500275 virtual bool eval(sdbusplus::message_t&) 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 */
Patrick Williams563306f2022-07-22 19:26:52 -0500284 bool operator()(sdbusplus::bus_t&, sdbusplus::message_t&, Manager&) const;
Brad Bishopc1f47982017-02-09 01:27:38 -0500285
Brad Bishop615b2a82018-03-29 10:32:41 -0400286 /** @brief Test a property value.
287 *
288 * Make a DBus call and test the value of any property.
289 */
Patrick Williams563306f2022-07-22 19:26:52 -0500290 bool operator()(const std::string&, sdbusplus::bus_t&, Manager&) const;
Brad Bishopd0f48ad2017-01-30 08:52:26 -0500291
Brad Bishop615b2a82018-03-29 10:32:41 -0400292 private:
293 std::string _path;
294 std::string _iface;
295 std::string _property;
296 const char* _service;
Brad Bishopc1f47982017-02-09 01:27:38 -0500297};
298
299/** @struct PropertyCondition
300 * @brief Match filter functor that tests a property value.
301 *
302 * @tparam T - The type of the property being tested.
303 * @tparam U - The type of the condition checking functor.
Matthew Barthf094d442018-09-26 15:06:15 -0500304 * @tparam V - The getProperty functor return type.
Brad Bishopc1f47982017-02-09 01:27:38 -0500305 */
Matthew Barthf094d442018-09-26 15:06:15 -0500306template <typename T, typename U, typename V>
Brad Bishopc1f47982017-02-09 01:27:38 -0500307struct PropertyCondition final : public PropertyConditionBase
308{
Brad Bishop615b2a82018-03-29 10:32:41 -0400309 PropertyCondition() = delete;
310 ~PropertyCondition() = default;
311 PropertyCondition(const PropertyCondition&) = default;
312 PropertyCondition& operator=(const PropertyCondition&) = default;
313 PropertyCondition(PropertyCondition&&) = default;
314 PropertyCondition& operator=(PropertyCondition&&) = default;
Brad Bishopc1f47982017-02-09 01:27:38 -0500315
Brad Bishop615b2a82018-03-29 10:32:41 -0400316 /** @brief Constructor
317 *
Matthew Barthf094d442018-09-26 15:06:15 -0500318 * The service & getProperty arguments can be nullptrs.
319 * If something else is provided the function will call the the
Brad Bishop615b2a82018-03-29 10:32:41 -0400320 * service directly. If omitted, the function will
321 * look up the service in the ObjectMapper.
Matthew Barthf094d442018-09-26 15:06:15 -0500322 * The getProperty function will be called to retrieve a property
323 * value when given and the property is hosted by inventory manager.
324 * When not given, the condition will default to return that the
325 * condition failed and will not be executed.
Brad Bishop615b2a82018-03-29 10:32:41 -0400326 *
327 * @param path - The path of the object containing
328 * the property to be tested.
329 * @param iface - The interface hosting the property
330 * to be tested.
331 * @param property - The property to be tested.
332 * @param condition - The test to run on the property.
333 * @param service - The DBus service hosting the object.
Matthew Barthf094d442018-09-26 15:06:15 -0500334 * @param getProperty - The function to get a property value
335 * for the condition.
Brad Bishop615b2a82018-03-29 10:32:41 -0400336 */
337 PropertyCondition(const char* path, const char* iface, const char* property,
Matthew Barthf094d442018-09-26 15:06:15 -0500338 U&& condition, const char* service,
339 GetProperty<V>&& getProperty = nullptr) :
Brad Bishop615b2a82018-03-29 10:32:41 -0400340 PropertyConditionBase(path, iface, property, service),
Matthew Barthf094d442018-09-26 15:06:15 -0500341 _condition(std::forward<decltype(condition)>(condition)),
342 _getProperty(getProperty)
Brad Bishopa83db302020-12-06 14:51:23 -0500343 {}
Brad Bishopc1f47982017-02-09 01:27:38 -0500344
Brad Bishop615b2a82018-03-29 10:32:41 -0400345 /** @brief Test a property value.
346 *
347 * Make a DBus call and test the value of any property.
348 */
Patrick Williams563306f2022-07-22 19:26:52 -0500349 bool eval(sdbusplus::message_t& msg) const override
Brad Bishop615b2a82018-03-29 10:32:41 -0400350 {
Patrick Williams55f9eae2020-05-13 17:57:04 -0500351 std::variant<T> value;
Brad Bishop615b2a82018-03-29 10:32:41 -0400352 msg.read(value);
Patrick Williams26f86682020-05-13 11:36:19 -0500353 return _condition(std::forward<T>(std::get<T>(value)));
Brad Bishop615b2a82018-03-29 10:32:41 -0400354 }
Brad Bishopc1f47982017-02-09 01:27:38 -0500355
Matthew Barthf094d442018-09-26 15:06:15 -0500356 /** @brief Retrieve a property value from inventory and test it.
357 *
358 * Get a property from the inventory manager and test the value.
359 * Default to fail the test where no function is given to get the
360 * property from the inventory manager.
361 */
362 bool eval(Manager& mgr) const override
363 {
364 if (_getProperty)
365 {
366 auto variant = _getProperty(mgr);
Patrick Williams26f86682020-05-13 11:36:19 -0500367 auto value = std::get<T>(variant);
Matthew Barthf094d442018-09-26 15:06:15 -0500368 return _condition(std::forward<T>(value));
369 }
370 return false;
371 }
372
Brad Bishop615b2a82018-03-29 10:32:41 -0400373 private:
374 U _condition;
Matthew Barthf094d442018-09-26 15:06:15 -0500375 GetProperty<V> _getProperty;
Brad Bishopc1f47982017-02-09 01:27:38 -0500376};
377
Brad Bishop615b2a82018-03-29 10:32:41 -0400378/** @brief Implicit type deduction for constructing PropertyChangedCondition. */
Brad Bishopc1f47982017-02-09 01:27:38 -0500379template <typename T>
Brad Bishop615b2a82018-03-29 10:32:41 -0400380auto propertyChangedTo(const char* iface, const char* property, T&& val)
Brad Bishopc1f47982017-02-09 01:27:38 -0500381{
Patrick Venturea680d1e2018-10-14 13:34:26 -0700382 auto condition = [val = std::forward<T>(val)](T&& arg) {
Brad Bishopc1f47982017-02-09 01:27:38 -0500383 return arg == val;
384 };
385 using U = decltype(condition);
Brad Bishop615b2a82018-03-29 10:32:41 -0400386 return PropertyChangedCondition<T, U>(iface, property,
387 std::move(condition));
Brad Bishopc1f47982017-02-09 01:27:38 -0500388}
389
390/** @brief Implicit type deduction for constructing PropertyCondition. */
Matthew Barthf094d442018-09-26 15:06:15 -0500391template <typename T, typename V = InterfaceVariantType>
Brad Bishop615b2a82018-03-29 10:32:41 -0400392auto propertyIs(const char* path, const char* iface, const char* property,
Matthew Barthf094d442018-09-26 15:06:15 -0500393 T&& val, const char* service = nullptr,
394 GetProperty<V>&& getProperty = nullptr)
Brad Bishopc1f47982017-02-09 01:27:38 -0500395{
Patrick Venturea680d1e2018-10-14 13:34:26 -0700396 auto condition = [val = std::forward<T>(val)](T&& arg) {
Brad Bishopc1f47982017-02-09 01:27:38 -0500397 return arg == val;
398 };
399 using U = decltype(condition);
Matthew Barthf094d442018-09-26 15:06:15 -0500400 return PropertyCondition<T, U, V>(path, iface, property,
401 std::move(condition), service,
402 std::move(getProperty));
Brad Bishopc1f47982017-02-09 01:27:38 -0500403}
404} // namespace functor
405} // namespace manager
406} // namespace inventory
407} // namespace phosphor
408
409// vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4