blob: d00ec489bf5844f73d41f73abfc1072da0ceb977 [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
William A. Kennington III6e94b652018-11-06 17:11:28 -0800230 return _condition(std::forward<T>(
231 sdbusplus::message::variant_ns::get<T>(it->second)));
Brad Bishop615b2a82018-03-29 10:32:41 -0400232 }
233
234 private:
235 const char* _iface;
236 const char* _property;
237 U _condition;
Brad Bishopc1f47982017-02-09 01:27:38 -0500238};
239
240/** @struct PropertyConditionBase
241 * @brief Match filter functor that tests a property value.
242 *
243 * Base class for PropertyCondition - factored out code that
244 * doesn't need to be templated.
245 */
246struct PropertyConditionBase
247{
Brad Bishop615b2a82018-03-29 10:32:41 -0400248 PropertyConditionBase() = delete;
249 virtual ~PropertyConditionBase() = default;
250 PropertyConditionBase(const PropertyConditionBase&) = default;
251 PropertyConditionBase& operator=(const PropertyConditionBase&) = default;
252 PropertyConditionBase(PropertyConditionBase&&) = default;
253 PropertyConditionBase& operator=(PropertyConditionBase&&) = default;
Brad Bishopc1f47982017-02-09 01:27:38 -0500254
Brad Bishop615b2a82018-03-29 10:32:41 -0400255 /** @brief Constructor
256 *
257 * The service argument can be nullptr. If something
258 * else is provided the function will call the the
259 * service directly. If omitted, the function will
260 * look up the service in the ObjectMapper.
261 *
262 * @param path - The path of the object containing
263 * the property to be tested.
264 * @param iface - The interface hosting the property
265 * to be tested.
266 * @param property - The property to be tested.
267 * @param service - The DBus service hosting the object.
268 */
269 PropertyConditionBase(const char* path, const char* iface,
270 const char* property, const char* service) :
271 _path(path ? path : std::string()),
272 _iface(iface), _property(property), _service(service)
273 {
274 }
Brad Bishopc1f47982017-02-09 01:27:38 -0500275
Brad Bishop615b2a82018-03-29 10:32:41 -0400276 /** @brief Forward comparison to type specific implementation. */
277 virtual bool eval(sdbusplus::message::message&) const = 0;
Brad Bishopc1f47982017-02-09 01:27:38 -0500278
Matthew Barthf094d442018-09-26 15:06:15 -0500279 /** @brief Forward comparison to type specific implementation. */
280 virtual bool eval(Manager&) const = 0;
281
Brad Bishop615b2a82018-03-29 10:32:41 -0400282 /** @brief Test a property value.
283 *
284 * Make a DBus call and test the value of any property.
285 */
286 bool operator()(sdbusplus::bus::bus&, sdbusplus::message::message&,
287 Manager&) const;
Brad Bishopc1f47982017-02-09 01:27:38 -0500288
Brad Bishop615b2a82018-03-29 10:32:41 -0400289 /** @brief Test a property value.
290 *
291 * Make a DBus call and test the value of any property.
292 */
293 bool operator()(const std::string&, sdbusplus::bus::bus&, Manager&) const;
Brad Bishopd0f48ad2017-01-30 08:52:26 -0500294
Brad Bishop615b2a82018-03-29 10:32:41 -0400295 private:
296 std::string _path;
297 std::string _iface;
298 std::string _property;
299 const char* _service;
Brad Bishopc1f47982017-02-09 01:27:38 -0500300};
301
302/** @struct PropertyCondition
303 * @brief Match filter functor that tests a property value.
304 *
305 * @tparam T - The type of the property being tested.
306 * @tparam U - The type of the condition checking functor.
Matthew Barthf094d442018-09-26 15:06:15 -0500307 * @tparam V - The getProperty functor return type.
Brad Bishopc1f47982017-02-09 01:27:38 -0500308 */
Matthew Barthf094d442018-09-26 15:06:15 -0500309template <typename T, typename U, typename V>
Brad Bishopc1f47982017-02-09 01:27:38 -0500310struct PropertyCondition final : public PropertyConditionBase
311{
Brad Bishop615b2a82018-03-29 10:32:41 -0400312 PropertyCondition() = delete;
313 ~PropertyCondition() = default;
314 PropertyCondition(const PropertyCondition&) = default;
315 PropertyCondition& operator=(const PropertyCondition&) = default;
316 PropertyCondition(PropertyCondition&&) = default;
317 PropertyCondition& operator=(PropertyCondition&&) = default;
Brad Bishopc1f47982017-02-09 01:27:38 -0500318
Brad Bishop615b2a82018-03-29 10:32:41 -0400319 /** @brief Constructor
320 *
Matthew Barthf094d442018-09-26 15:06:15 -0500321 * The service & getProperty arguments can be nullptrs.
322 * If something else is provided the function will call the the
Brad Bishop615b2a82018-03-29 10:32:41 -0400323 * service directly. If omitted, the function will
324 * look up the service in the ObjectMapper.
Matthew Barthf094d442018-09-26 15:06:15 -0500325 * The getProperty function will be called to retrieve a property
326 * value when given and the property is hosted by inventory manager.
327 * When not given, the condition will default to return that the
328 * condition failed and will not be executed.
Brad Bishop615b2a82018-03-29 10:32:41 -0400329 *
330 * @param path - The path of the object containing
331 * the property to be tested.
332 * @param iface - The interface hosting the property
333 * to be tested.
334 * @param property - The property to be tested.
335 * @param condition - The test to run on the property.
336 * @param service - The DBus service hosting the object.
Matthew Barthf094d442018-09-26 15:06:15 -0500337 * @param getProperty - The function to get a property value
338 * for the condition.
Brad Bishop615b2a82018-03-29 10:32:41 -0400339 */
340 PropertyCondition(const char* path, const char* iface, const char* property,
Matthew Barthf094d442018-09-26 15:06:15 -0500341 U&& condition, const char* service,
342 GetProperty<V>&& getProperty = nullptr) :
Brad Bishop615b2a82018-03-29 10:32:41 -0400343 PropertyConditionBase(path, iface, property, service),
Matthew Barthf094d442018-09-26 15:06:15 -0500344 _condition(std::forward<decltype(condition)>(condition)),
345 _getProperty(getProperty)
Brad Bishop615b2a82018-03-29 10:32:41 -0400346 {
347 }
Brad Bishopc1f47982017-02-09 01:27:38 -0500348
Brad Bishop615b2a82018-03-29 10:32:41 -0400349 /** @brief Test a property value.
350 *
351 * Make a DBus call and test the value of any property.
352 */
353 bool eval(sdbusplus::message::message& msg) const override
354 {
355 sdbusplus::message::variant<T> value;
356 msg.read(value);
William A. Kennington III6e94b652018-11-06 17:11:28 -0800357 return _condition(
358 std::forward<T>(sdbusplus::message::variant_ns::get<T>(value)));
Brad Bishop615b2a82018-03-29 10:32:41 -0400359 }
Brad Bishopc1f47982017-02-09 01:27:38 -0500360
Matthew Barthf094d442018-09-26 15:06:15 -0500361 /** @brief Retrieve a property value from inventory and test it.
362 *
363 * Get a property from the inventory manager and test the value.
364 * Default to fail the test where no function is given to get the
365 * property from the inventory manager.
366 */
367 bool eval(Manager& mgr) const override
368 {
369 if (_getProperty)
370 {
371 auto variant = _getProperty(mgr);
372 auto value = sdbusplus::message::variant_ns::get<T>(variant);
373 return _condition(std::forward<T>(value));
374 }
375 return false;
376 }
377
Brad Bishop615b2a82018-03-29 10:32:41 -0400378 private:
379 U _condition;
Matthew Barthf094d442018-09-26 15:06:15 -0500380 GetProperty<V> _getProperty;
Brad Bishopc1f47982017-02-09 01:27:38 -0500381};
382
Brad Bishop615b2a82018-03-29 10:32:41 -0400383/** @brief Implicit type deduction for constructing PropertyChangedCondition. */
Brad Bishopc1f47982017-02-09 01:27:38 -0500384template <typename T>
Brad Bishop615b2a82018-03-29 10:32:41 -0400385auto propertyChangedTo(const char* iface, const char* property, T&& val)
Brad Bishopc1f47982017-02-09 01:27:38 -0500386{
Patrick Venturea680d1e2018-10-14 13:34:26 -0700387 auto condition = [val = std::forward<T>(val)](T&& arg) {
Brad Bishopc1f47982017-02-09 01:27:38 -0500388 return arg == val;
389 };
390 using U = decltype(condition);
Brad Bishop615b2a82018-03-29 10:32:41 -0400391 return PropertyChangedCondition<T, U>(iface, property,
392 std::move(condition));
Brad Bishopc1f47982017-02-09 01:27:38 -0500393}
394
395/** @brief Implicit type deduction for constructing PropertyCondition. */
Matthew Barthf094d442018-09-26 15:06:15 -0500396template <typename T, typename V = InterfaceVariantType>
Brad Bishop615b2a82018-03-29 10:32:41 -0400397auto propertyIs(const char* path, const char* iface, const char* property,
Matthew Barthf094d442018-09-26 15:06:15 -0500398 T&& val, const char* service = nullptr,
399 GetProperty<V>&& getProperty = nullptr)
Brad Bishopc1f47982017-02-09 01:27:38 -0500400{
Patrick Venturea680d1e2018-10-14 13:34:26 -0700401 auto condition = [val = std::forward<T>(val)](T&& arg) {
Brad Bishopc1f47982017-02-09 01:27:38 -0500402 return arg == val;
403 };
404 using U = decltype(condition);
Matthew Barthf094d442018-09-26 15:06:15 -0500405 return PropertyCondition<T, U, V>(path, iface, property,
406 std::move(condition), service,
407 std::move(getProperty));
Brad Bishopc1f47982017-02-09 01:27:38 -0500408}
409} // namespace functor
410} // namespace manager
411} // namespace inventory
412} // namespace phosphor
413
414// vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4