blob: fc763e55cba0b8d890117052a235b3c616e83e98 [file] [log] [blame]
Brad Bishopc1f47982017-02-09 01:27:38 -05001#pragma once
2
3#include <utility>
4#include <memory>
5#include <sdbusplus/bus.hpp>
6#include "utils.hpp"
7#include "types.hpp"
8
9namespace phosphor
10{
11namespace inventory
12{
13namespace manager
14{
15
16class Manager;
17
18/** @brief make_action
19 *
20 * Adapt an action function object.
21 *
22 * @param[in] action - The action being adapted.
23 * @returns - The adapted action.
24 *
25 * @tparam T - The type of the action being adapted.
26 */
Brad Bishop615b2a82018-03-29 10:32:41 -040027template <typename T> auto make_action(T&& action)
Brad Bishopc1f47982017-02-09 01:27:38 -050028{
29 return Action(std::forward<T>(action));
30}
31
32/** @brief make_filter
33 *
34 * Adapt a filter function object.
35 *
36 * @param[in] filter - The filter being adapted.
37 * @returns - The adapted filter.
38 *
39 * @tparam T - The type of the filter being adapted.
40 */
Brad Bishop615b2a82018-03-29 10:32:41 -040041template <typename T> auto make_filter(T&& filter)
Brad Bishopc1f47982017-02-09 01:27:38 -050042{
43 return Filter(std::forward<T>(filter));
44}
45
Brad Bishopd0f48ad2017-01-30 08:52:26 -050046/** @brief make_path_condition
47 *
48 * Adapt a path_condition function object.
49 *
50 * @param[in] filter - The functor being adapted.
51 * @returns - The adapted functor.
52 *
53 * @tparam T - The type of the functor being adapted.
54 */
Brad Bishop615b2a82018-03-29 10:32:41 -040055template <typename T> auto make_path_condition(T&& condition)
Brad Bishopd0f48ad2017-01-30 08:52:26 -050056{
57 return PathCondition(std::forward<T>(condition));
58}
59
Brad Bishop615b2a82018-03-29 10:32:41 -040060template <typename T, typename... Args>
61auto callArrayWithStatus(T&& container, Args&&... args)
Brad Bishopd0f48ad2017-01-30 08:52:26 -050062{
63 for (auto f : container)
64 {
65 if (!f(std::forward<Args>(args)...))
66 {
67 return false;
68 }
69 }
70 return true;
71}
72
Brad Bishopc1f47982017-02-09 01:27:38 -050073namespace functor
74{
75
76/** @brief Destroy objects action. */
Brad Bishop615b2a82018-03-29 10:32:41 -040077inline auto destroyObjects(std::vector<const char*>&& paths,
78 std::vector<PathCondition>&& conditions)
Brad Bishopc1f47982017-02-09 01:27:38 -050079{
Brad Bishop615b2a82018-03-29 10:32:41 -040080 return [=](auto& b, auto& m) {
Brad Bishopd0f48ad2017-01-30 08:52:26 -050081 for (const auto& p : paths)
82 {
83 if (callArrayWithStatus(conditions, p, b, m))
84 {
85 m.destroyObjects({p});
86 }
87 }
Brad Bishopc1f47982017-02-09 01:27:38 -050088 };
89}
90
91/** @brief Create objects action. */
Brad Bishop615b2a82018-03-29 10:32:41 -040092inline auto
93 createObjects(std::map<sdbusplus::message::object_path, Object>&& objs)
Brad Bishopc1f47982017-02-09 01:27:38 -050094{
Brad Bishop615b2a82018-03-29 10:32:41 -040095 return [=](auto&, auto& m) { m.createObjects(objs); };
Brad Bishopc1f47982017-02-09 01:27:38 -050096}
97
98/** @brief Set a property action.
99 *
100 * Invoke the requested method with a reference to the requested
101 * sdbusplus server binding interface as a parameter.
102 *
103 * @tparam T - The sdbusplus server binding interface type.
104 * @tparam U - The type of the sdbusplus server binding member
105 * function that sets the property.
106 * @tparam V - The property value type.
107 *
108 * @param[in] paths - The DBus paths on which the property should
109 * be set.
110 * @param[in] iface - The DBus interface hosting the property.
111 * @param[in] member - Pointer to sdbusplus server binding member.
112 * @param[in] value - The value the property should be set to.
113 *
114 * @returns - A function object that sets the requested property
115 * to the requested value.
116 */
117template <typename T, typename U, typename V>
Brad Bishop615b2a82018-03-29 10:32:41 -0400118auto setProperty(std::vector<const char*>&& paths,
119 std::vector<PathCondition>&& conditions, const char* iface,
120 U&& member, V&& value)
Brad Bishopc1f47982017-02-09 01:27:38 -0500121{
122 // The manager is the only parameter passed to actions.
123 // Bind the path, interface, interface member function pointer,
124 // and value to a lambda. When it is called, forward the
125 // path, interface and value on to the manager member function.
Brad Bishop615b2a82018-03-29 10:32:41 -0400126 return [
127 paths, conditions = conditions, iface, member,
128 value = std::forward<V>(value)
129 ](auto& b, auto& m)
Brad Bishopc1f47982017-02-09 01:27:38 -0500130 {
131 for (auto p : paths)
132 {
Brad Bishopd0f48ad2017-01-30 08:52:26 -0500133 if (callArrayWithStatus(conditions, p, b, m))
134 {
Brad Bishop615b2a82018-03-29 10:32:41 -0400135 m.template invokeMethod<T>(p, iface, member, value);
Brad Bishopd0f48ad2017-01-30 08:52:26 -0500136 }
Brad Bishopc1f47982017-02-09 01:27:38 -0500137 }
138 };
139}
140
141/** @struct PropertyChangedCondition
142 * @brief Match filter functor that tests a property value.
143 *
144 * @tparam T - The type of the property being tested.
145 * @tparam U - The type of the condition checking functor.
146 */
Brad Bishop615b2a82018-03-29 10:32:41 -0400147template <typename T, typename U> struct PropertyChangedCondition
Brad Bishopc1f47982017-02-09 01:27:38 -0500148{
Brad Bishop615b2a82018-03-29 10:32:41 -0400149 PropertyChangedCondition() = delete;
150 ~PropertyChangedCondition() = default;
151 PropertyChangedCondition(const PropertyChangedCondition&) = default;
152 PropertyChangedCondition&
153 operator=(const PropertyChangedCondition&) = default;
154 PropertyChangedCondition(PropertyChangedCondition&&) = default;
155 PropertyChangedCondition& operator=(PropertyChangedCondition&&) = default;
156 PropertyChangedCondition(const char* iface, const char* property,
157 U&& condition) :
158 _iface(iface),
159 _property(property), _condition(std::forward<U>(condition))
160 {
161 }
Brad Bishopc1f47982017-02-09 01:27:38 -0500162
Brad Bishop615b2a82018-03-29 10:32:41 -0400163 /** @brief Test a property value.
164 *
165 * Extract the property from the PropertiesChanged
166 * message and run the condition test.
167 */
168 bool operator()(sdbusplus::bus::bus&, sdbusplus::message::message& msg,
169 Manager&) const
170 {
171 std::map<std::string, sdbusplus::message::variant<T>> properties;
172 const char* iface = nullptr;
173
174 msg.read(iface);
175 if (!iface || strcmp(iface, _iface))
Brad Bishopc1f47982017-02-09 01:27:38 -0500176 {
Brad Bishop615b2a82018-03-29 10:32:41 -0400177 return false;
Brad Bishopc1f47982017-02-09 01:27:38 -0500178 }
179
Brad Bishop615b2a82018-03-29 10:32:41 -0400180 msg.read(properties);
181 auto it = properties.find(_property);
182 if (it == properties.cend())
183 {
184 return false;
185 }
186
187 return _condition(std::forward<T>(it->second.template get<T>()));
188 }
189
190 private:
191 const char* _iface;
192 const char* _property;
193 U _condition;
Brad Bishopc1f47982017-02-09 01:27:38 -0500194};
195
196/** @struct PropertyConditionBase
197 * @brief Match filter functor that tests a property value.
198 *
199 * Base class for PropertyCondition - factored out code that
200 * doesn't need to be templated.
201 */
202struct PropertyConditionBase
203{
Brad Bishop615b2a82018-03-29 10:32:41 -0400204 PropertyConditionBase() = delete;
205 virtual ~PropertyConditionBase() = default;
206 PropertyConditionBase(const PropertyConditionBase&) = default;
207 PropertyConditionBase& operator=(const PropertyConditionBase&) = default;
208 PropertyConditionBase(PropertyConditionBase&&) = default;
209 PropertyConditionBase& operator=(PropertyConditionBase&&) = default;
Brad Bishopc1f47982017-02-09 01:27:38 -0500210
Brad Bishop615b2a82018-03-29 10:32:41 -0400211 /** @brief Constructor
212 *
213 * The service argument can be nullptr. If something
214 * else is provided the function will call the the
215 * service directly. If omitted, the function will
216 * look up the service in the ObjectMapper.
217 *
218 * @param path - The path of the object containing
219 * the property to be tested.
220 * @param iface - The interface hosting the property
221 * to be tested.
222 * @param property - The property to be tested.
223 * @param service - The DBus service hosting the object.
224 */
225 PropertyConditionBase(const char* path, const char* iface,
226 const char* property, const char* service) :
227 _path(path ? path : std::string()),
228 _iface(iface), _property(property), _service(service)
229 {
230 }
Brad Bishopc1f47982017-02-09 01:27:38 -0500231
Brad Bishop615b2a82018-03-29 10:32:41 -0400232 /** @brief Forward comparison to type specific implementation. */
233 virtual bool eval(sdbusplus::message::message&) const = 0;
Brad Bishopc1f47982017-02-09 01:27:38 -0500234
Brad Bishop615b2a82018-03-29 10:32:41 -0400235 /** @brief Test a property value.
236 *
237 * Make a DBus call and test the value of any property.
238 */
239 bool operator()(sdbusplus::bus::bus&, sdbusplus::message::message&,
240 Manager&) const;
Brad Bishopc1f47982017-02-09 01:27:38 -0500241
Brad Bishop615b2a82018-03-29 10:32:41 -0400242 /** @brief Test a property value.
243 *
244 * Make a DBus call and test the value of any property.
245 */
246 bool operator()(const std::string&, sdbusplus::bus::bus&, Manager&) const;
Brad Bishopd0f48ad2017-01-30 08:52:26 -0500247
Brad Bishop615b2a82018-03-29 10:32:41 -0400248 private:
249 std::string _path;
250 std::string _iface;
251 std::string _property;
252 const char* _service;
Brad Bishopc1f47982017-02-09 01:27:38 -0500253};
254
255/** @struct PropertyCondition
256 * @brief Match filter functor that tests a property value.
257 *
258 * @tparam T - The type of the property being tested.
259 * @tparam U - The type of the condition checking functor.
260 */
261template <typename T, typename U>
262struct PropertyCondition final : public PropertyConditionBase
263{
Brad Bishop615b2a82018-03-29 10:32:41 -0400264 PropertyCondition() = delete;
265 ~PropertyCondition() = default;
266 PropertyCondition(const PropertyCondition&) = default;
267 PropertyCondition& operator=(const PropertyCondition&) = default;
268 PropertyCondition(PropertyCondition&&) = default;
269 PropertyCondition& operator=(PropertyCondition&&) = default;
Brad Bishopc1f47982017-02-09 01:27:38 -0500270
Brad Bishop615b2a82018-03-29 10:32:41 -0400271 /** @brief Constructor
272 *
273 * The service argument can be nullptr. If something
274 * else is provided the function will call the the
275 * service directly. If omitted, the function will
276 * look up the service in the ObjectMapper.
277 *
278 * @param path - The path of the object containing
279 * the property to be tested.
280 * @param iface - The interface hosting the property
281 * to be tested.
282 * @param property - The property to be tested.
283 * @param condition - The test to run on the property.
284 * @param service - The DBus service hosting the object.
285 */
286 PropertyCondition(const char* path, const char* iface, const char* property,
287 U&& condition, const char* service) :
288 PropertyConditionBase(path, iface, property, service),
289 _condition(std::forward<decltype(condition)>(condition))
290 {
291 }
Brad Bishopc1f47982017-02-09 01:27:38 -0500292
Brad Bishop615b2a82018-03-29 10:32:41 -0400293 /** @brief Test a property value.
294 *
295 * Make a DBus call and test the value of any property.
296 */
297 bool eval(sdbusplus::message::message& msg) const override
298 {
299 sdbusplus::message::variant<T> value;
300 msg.read(value);
301 return _condition(std::forward<T>(value.template get<T>()));
302 }
Brad Bishopc1f47982017-02-09 01:27:38 -0500303
Brad Bishop615b2a82018-03-29 10:32:41 -0400304 private:
305 U _condition;
Brad Bishopc1f47982017-02-09 01:27:38 -0500306};
307
Brad Bishop615b2a82018-03-29 10:32:41 -0400308/** @brief Implicit type deduction for constructing PropertyChangedCondition. */
Brad Bishopc1f47982017-02-09 01:27:38 -0500309template <typename T>
Brad Bishop615b2a82018-03-29 10:32:41 -0400310auto propertyChangedTo(const char* iface, const char* property, T&& val)
Brad Bishopc1f47982017-02-09 01:27:38 -0500311{
312 auto condition = [val = std::forward<T>(val)](T && arg)
313 {
314 return arg == val;
315 };
316 using U = decltype(condition);
Brad Bishop615b2a82018-03-29 10:32:41 -0400317 return PropertyChangedCondition<T, U>(iface, property,
318 std::move(condition));
Brad Bishopc1f47982017-02-09 01:27:38 -0500319}
320
321/** @brief Implicit type deduction for constructing PropertyCondition. */
322template <typename T>
Brad Bishop615b2a82018-03-29 10:32:41 -0400323auto propertyIs(const char* path, const char* iface, const char* property,
324 T&& val, const char* service = nullptr)
Brad Bishopc1f47982017-02-09 01:27:38 -0500325{
326 auto condition = [val = std::forward<T>(val)](T && arg)
327 {
328 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