blob: 3a3077db4a40aa0eeef32ee7ad27ffafa45f0e16 [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
Brad Bishop615b2a82018-03-29 10:32:41 -040064template <typename T, typename... Args>
65auto callArrayWithStatus(T&& container, Args&&... args)
Brad Bishopd0f48ad2017-01-30 08:52:26 -050066{
67 for (auto f : container)
68 {
69 if (!f(std::forward<Args>(args)...))
70 {
71 return false;
72 }
73 }
74 return true;
75}
76
Brad Bishopc1f47982017-02-09 01:27:38 -050077namespace functor
78{
79
80/** @brief Destroy objects action. */
Brad Bishop615b2a82018-03-29 10:32:41 -040081inline auto destroyObjects(std::vector<const char*>&& paths,
82 std::vector<PathCondition>&& conditions)
Brad Bishopc1f47982017-02-09 01:27:38 -050083{
Brad Bishop615b2a82018-03-29 10:32:41 -040084 return [=](auto& b, auto& m) {
Brad Bishopd0f48ad2017-01-30 08:52:26 -050085 for (const auto& p : paths)
86 {
87 if (callArrayWithStatus(conditions, p, b, m))
88 {
89 m.destroyObjects({p});
90 }
91 }
Brad Bishopc1f47982017-02-09 01:27:38 -050092 };
93}
94
95/** @brief Create objects action. */
Brad Bishop615b2a82018-03-29 10:32:41 -040096inline auto
97 createObjects(std::map<sdbusplus::message::object_path, Object>&& objs)
Brad Bishopc1f47982017-02-09 01:27:38 -050098{
Brad Bishop615b2a82018-03-29 10:32:41 -040099 return [=](auto&, auto& m) { m.createObjects(objs); };
Brad Bishopc1f47982017-02-09 01:27:38 -0500100}
101
102/** @brief Set a property action.
103 *
104 * Invoke the requested method with a reference to the requested
105 * sdbusplus server binding interface as a parameter.
106 *
107 * @tparam T - The sdbusplus server binding interface type.
108 * @tparam U - The type of the sdbusplus server binding member
109 * function that sets the property.
110 * @tparam V - The property value type.
111 *
112 * @param[in] paths - The DBus paths on which the property should
113 * be set.
114 * @param[in] iface - The DBus interface hosting the property.
115 * @param[in] member - Pointer to sdbusplus server binding member.
116 * @param[in] value - The value the property should be set to.
117 *
118 * @returns - A function object that sets the requested property
119 * to the requested value.
120 */
121template <typename T, typename U, typename V>
Brad Bishop615b2a82018-03-29 10:32:41 -0400122auto setProperty(std::vector<const char*>&& paths,
123 std::vector<PathCondition>&& conditions, const char* iface,
124 U&& member, V&& value)
Brad Bishopc1f47982017-02-09 01:27:38 -0500125{
126 // The manager is the only parameter passed to actions.
127 // Bind the path, interface, interface member function pointer,
128 // and value to a lambda. When it is called, forward the
129 // path, interface and value on to the manager member function.
Patrick Venturea680d1e2018-10-14 13:34:26 -0700130 return [paths, conditions = conditions, iface, member,
131 value = std::forward<V>(value)](auto& b, auto& m) {
Brad Bishopc1f47982017-02-09 01:27:38 -0500132 for (auto p : paths)
133 {
Brad Bishopd0f48ad2017-01-30 08:52:26 -0500134 if (callArrayWithStatus(conditions, p, b, m))
135 {
Brad Bishop615b2a82018-03-29 10:32:41 -0400136 m.template invokeMethod<T>(p, iface, member, value);
Brad Bishopd0f48ad2017-01-30 08:52:26 -0500137 }
Brad Bishopc1f47982017-02-09 01:27:38 -0500138 }
139 };
140}
141
142/** @struct PropertyChangedCondition
143 * @brief Match filter functor that tests a property value.
144 *
145 * @tparam T - The type of the property being tested.
146 * @tparam U - The type of the condition checking functor.
147 */
Patrick Venturea680d1e2018-10-14 13:34:26 -0700148template <typename T, typename U>
149struct PropertyChangedCondition
Brad Bishopc1f47982017-02-09 01:27:38 -0500150{
Brad Bishop615b2a82018-03-29 10:32:41 -0400151 PropertyChangedCondition() = delete;
152 ~PropertyChangedCondition() = default;
153 PropertyChangedCondition(const PropertyChangedCondition&) = default;
154 PropertyChangedCondition&
155 operator=(const PropertyChangedCondition&) = default;
156 PropertyChangedCondition(PropertyChangedCondition&&) = default;
157 PropertyChangedCondition& operator=(PropertyChangedCondition&&) = default;
158 PropertyChangedCondition(const char* iface, const char* property,
159 U&& condition) :
160 _iface(iface),
161 _property(property), _condition(std::forward<U>(condition))
162 {
163 }
Brad Bishopc1f47982017-02-09 01:27:38 -0500164
Brad Bishop615b2a82018-03-29 10:32:41 -0400165 /** @brief Test a property value.
166 *
167 * Extract the property from the PropertiesChanged
168 * message and run the condition test.
169 */
170 bool operator()(sdbusplus::bus::bus&, sdbusplus::message::message& msg,
171 Manager&) const
172 {
173 std::map<std::string, sdbusplus::message::variant<T>> properties;
174 const char* iface = nullptr;
175
176 msg.read(iface);
177 if (!iface || strcmp(iface, _iface))
Brad Bishopc1f47982017-02-09 01:27:38 -0500178 {
Brad Bishop615b2a82018-03-29 10:32:41 -0400179 return false;
Brad Bishopc1f47982017-02-09 01:27:38 -0500180 }
181
Brad Bishop615b2a82018-03-29 10:32:41 -0400182 msg.read(properties);
183 auto it = properties.find(_property);
184 if (it == properties.cend())
185 {
186 return false;
187 }
188
189 return _condition(std::forward<T>(it->second.template get<T>()));
190 }
191
192 private:
193 const char* _iface;
194 const char* _property;
195 U _condition;
Brad Bishopc1f47982017-02-09 01:27:38 -0500196};
197
198/** @struct PropertyConditionBase
199 * @brief Match filter functor that tests a property value.
200 *
201 * Base class for PropertyCondition - factored out code that
202 * doesn't need to be templated.
203 */
204struct PropertyConditionBase
205{
Brad Bishop615b2a82018-03-29 10:32:41 -0400206 PropertyConditionBase() = delete;
207 virtual ~PropertyConditionBase() = default;
208 PropertyConditionBase(const PropertyConditionBase&) = default;
209 PropertyConditionBase& operator=(const PropertyConditionBase&) = default;
210 PropertyConditionBase(PropertyConditionBase&&) = default;
211 PropertyConditionBase& operator=(PropertyConditionBase&&) = default;
Brad Bishopc1f47982017-02-09 01:27:38 -0500212
Brad Bishop615b2a82018-03-29 10:32:41 -0400213 /** @brief Constructor
214 *
215 * The service argument can be nullptr. If something
216 * else is provided the function will call the the
217 * service directly. If omitted, the function will
218 * look up the service in the ObjectMapper.
219 *
220 * @param path - The path of the object containing
221 * the property to be tested.
222 * @param iface - The interface hosting the property
223 * to be tested.
224 * @param property - The property to be tested.
225 * @param service - The DBus service hosting the object.
226 */
227 PropertyConditionBase(const char* path, const char* iface,
228 const char* property, const char* service) :
229 _path(path ? path : std::string()),
230 _iface(iface), _property(property), _service(service)
231 {
232 }
Brad Bishopc1f47982017-02-09 01:27:38 -0500233
Brad Bishop615b2a82018-03-29 10:32:41 -0400234 /** @brief Forward comparison to type specific implementation. */
235 virtual bool eval(sdbusplus::message::message&) const = 0;
Brad Bishopc1f47982017-02-09 01:27:38 -0500236
Brad Bishop615b2a82018-03-29 10:32:41 -0400237 /** @brief Test a property value.
238 *
239 * Make a DBus call and test the value of any property.
240 */
241 bool operator()(sdbusplus::bus::bus&, sdbusplus::message::message&,
242 Manager&) const;
Brad Bishopc1f47982017-02-09 01:27:38 -0500243
Brad Bishop615b2a82018-03-29 10:32:41 -0400244 /** @brief Test a property value.
245 *
246 * Make a DBus call and test the value of any property.
247 */
248 bool operator()(const std::string&, sdbusplus::bus::bus&, Manager&) const;
Brad Bishopd0f48ad2017-01-30 08:52:26 -0500249
Brad Bishop615b2a82018-03-29 10:32:41 -0400250 private:
251 std::string _path;
252 std::string _iface;
253 std::string _property;
254 const char* _service;
Brad Bishopc1f47982017-02-09 01:27:38 -0500255};
256
257/** @struct PropertyCondition
258 * @brief Match filter functor that tests a property value.
259 *
260 * @tparam T - The type of the property being tested.
261 * @tparam U - The type of the condition checking functor.
262 */
263template <typename T, typename U>
264struct PropertyCondition final : public PropertyConditionBase
265{
Brad Bishop615b2a82018-03-29 10:32:41 -0400266 PropertyCondition() = delete;
267 ~PropertyCondition() = default;
268 PropertyCondition(const PropertyCondition&) = default;
269 PropertyCondition& operator=(const PropertyCondition&) = default;
270 PropertyCondition(PropertyCondition&&) = default;
271 PropertyCondition& operator=(PropertyCondition&&) = default;
Brad Bishopc1f47982017-02-09 01:27:38 -0500272
Brad Bishop615b2a82018-03-29 10:32:41 -0400273 /** @brief Constructor
274 *
275 * The service argument can be nullptr. If something
276 * else is provided the function will call the the
277 * service directly. If omitted, the function will
278 * look up the service in the ObjectMapper.
279 *
280 * @param path - The path of the object containing
281 * the property to be tested.
282 * @param iface - The interface hosting the property
283 * to be tested.
284 * @param property - The property to be tested.
285 * @param condition - The test to run on the property.
286 * @param service - The DBus service hosting the object.
287 */
288 PropertyCondition(const char* path, const char* iface, const char* property,
289 U&& condition, const char* service) :
290 PropertyConditionBase(path, iface, property, service),
291 _condition(std::forward<decltype(condition)>(condition))
292 {
293 }
Brad Bishopc1f47982017-02-09 01:27:38 -0500294
Brad Bishop615b2a82018-03-29 10:32:41 -0400295 /** @brief Test a property value.
296 *
297 * Make a DBus call and test the value of any property.
298 */
299 bool eval(sdbusplus::message::message& msg) const override
300 {
301 sdbusplus::message::variant<T> value;
302 msg.read(value);
303 return _condition(std::forward<T>(value.template get<T>()));
304 }
Brad Bishopc1f47982017-02-09 01:27:38 -0500305
Brad Bishop615b2a82018-03-29 10:32:41 -0400306 private:
307 U _condition;
Brad Bishopc1f47982017-02-09 01:27:38 -0500308};
309
Brad Bishop615b2a82018-03-29 10:32:41 -0400310/** @brief Implicit type deduction for constructing PropertyChangedCondition. */
Brad Bishopc1f47982017-02-09 01:27:38 -0500311template <typename T>
Brad Bishop615b2a82018-03-29 10:32:41 -0400312auto propertyChangedTo(const char* iface, const char* property, T&& val)
Brad Bishopc1f47982017-02-09 01:27:38 -0500313{
Patrick Venturea680d1e2018-10-14 13:34:26 -0700314 auto condition = [val = std::forward<T>(val)](T&& arg) {
Brad Bishopc1f47982017-02-09 01:27:38 -0500315 return arg == val;
316 };
317 using U = decltype(condition);
Brad Bishop615b2a82018-03-29 10:32:41 -0400318 return PropertyChangedCondition<T, U>(iface, property,
319 std::move(condition));
Brad Bishopc1f47982017-02-09 01:27:38 -0500320}
321
322/** @brief Implicit type deduction for constructing PropertyCondition. */
323template <typename T>
Brad Bishop615b2a82018-03-29 10:32:41 -0400324auto propertyIs(const char* path, const char* iface, const char* property,
325 T&& val, const char* service = nullptr)
Brad Bishopc1f47982017-02-09 01:27:38 -0500326{
Patrick Venturea680d1e2018-10-14 13:34:26 -0700327 auto condition = [val = std::forward<T>(val)](T&& arg) {
Brad Bishopc1f47982017-02-09 01:27:38 -0500328 return arg == val;
329 };
330 using U = decltype(condition);
Brad Bishop615b2a82018-03-29 10:32:41 -0400331 return PropertyCondition<T, U>(path, iface, property, std::move(condition),
332 service);
Brad Bishopc1f47982017-02-09 01:27:38 -0500333}
334} // namespace functor
335} // namespace manager
336} // namespace inventory
337} // namespace phosphor
338
339// vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4