blob: 50fdcfabdc0d184ef760b36e8e98db9e19336317 [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 */
27template <typename T>
28auto make_action(T&& action)
29{
30 return Action(std::forward<T>(action));
31}
32
33/** @brief make_filter
34 *
35 * Adapt a filter function object.
36 *
37 * @param[in] filter - The filter being adapted.
38 * @returns - The adapted filter.
39 *
40 * @tparam T - The type of the filter being adapted.
41 */
42template <typename T>
43auto make_filter(T&& filter)
44{
45 return Filter(std::forward<T>(filter));
46}
47
Brad Bishopd0f48ad2017-01-30 08:52:26 -050048/** @brief make_path_condition
49 *
50 * Adapt a path_condition function object.
51 *
52 * @param[in] filter - The functor being adapted.
53 * @returns - The adapted functor.
54 *
55 * @tparam T - The type of the functor being adapted.
56 */
57template <typename T>
58auto make_path_condition(T&& condition)
59{
60 return PathCondition(std::forward<T>(condition));
61}
62
63template <typename T, typename ...Args>
64auto callArrayWithStatus(T&& container, Args&& ...args)
65{
66 for (auto f : container)
67 {
68 if (!f(std::forward<Args>(args)...))
69 {
70 return false;
71 }
72 }
73 return true;
74}
75
Brad Bishopc1f47982017-02-09 01:27:38 -050076namespace functor
77{
78
79/** @brief Destroy objects action. */
Brad Bishopd0f48ad2017-01-30 08:52:26 -050080inline auto destroyObjects(
81 std::vector<const char*>&& paths,
82 std::vector<PathCondition>&& conditions)
Brad Bishopc1f47982017-02-09 01:27:38 -050083{
Brad Bishopd0f48ad2017-01-30 08:52:26 -050084 return [ = ](auto & b, auto & m)
Brad Bishopc1f47982017-02-09 01:27:38 -050085 {
Brad Bishopd0f48ad2017-01-30 08:52:26 -050086 for (const auto& p : paths)
87 {
88 if (callArrayWithStatus(conditions, p, b, m))
89 {
90 m.destroyObjects({p});
91 }
92 }
Brad Bishopc1f47982017-02-09 01:27:38 -050093 };
94}
95
96/** @brief Create objects action. */
97inline auto createObjects(
98 std::map<sdbusplus::message::object_path, Object>&& objs)
99{
100 return [ = ](auto&, auto & m)
101 {
102 m.createObjects(objs);
103 };
104}
105
106/** @brief Set a property action.
107 *
108 * Invoke the requested method with a reference to the requested
109 * sdbusplus server binding interface as a parameter.
110 *
111 * @tparam T - The sdbusplus server binding interface type.
112 * @tparam U - The type of the sdbusplus server binding member
113 * function that sets the property.
114 * @tparam V - The property value type.
115 *
116 * @param[in] paths - The DBus paths on which the property should
117 * be set.
118 * @param[in] iface - The DBus interface hosting the property.
119 * @param[in] member - Pointer to sdbusplus server binding member.
120 * @param[in] value - The value the property should be set to.
121 *
122 * @returns - A function object that sets the requested property
123 * to the requested value.
124 */
125template <typename T, typename U, typename V>
126auto setProperty(
Brad Bishopd0f48ad2017-01-30 08:52:26 -0500127 std::vector<const char*>&& paths,
128 std::vector<PathCondition>&& conditions,
129 const char* iface,
130 U&& member,
131 V&& value)
Brad Bishopc1f47982017-02-09 01:27:38 -0500132{
133 // The manager is the only parameter passed to actions.
134 // Bind the path, interface, interface member function pointer,
135 // and value to a lambda. When it is called, forward the
136 // path, interface and value on to the manager member function.
Brad Bishopd0f48ad2017-01-30 08:52:26 -0500137 return [paths, conditions = conditions, iface,
138 member,
139 value = std::forward<V>(value)](auto & b, auto & m)
Brad Bishopc1f47982017-02-09 01:27:38 -0500140 {
141 for (auto p : paths)
142 {
Brad Bishopd0f48ad2017-01-30 08:52:26 -0500143 if (callArrayWithStatus(conditions, p, b, m))
144 {
145 m.template invokeMethod<T>(
146 p, iface, member, value);
147 }
Brad Bishopc1f47982017-02-09 01:27:38 -0500148 }
149 };
150}
151
152/** @struct PropertyChangedCondition
153 * @brief Match filter functor that tests a property value.
154 *
155 * @tparam T - The type of the property being tested.
156 * @tparam U - The type of the condition checking functor.
157 */
158template <typename T, typename U>
159struct PropertyChangedCondition
160{
161 PropertyChangedCondition() = delete;
162 ~PropertyChangedCondition() = default;
163 PropertyChangedCondition(const PropertyChangedCondition&) = default;
164 PropertyChangedCondition& operator=(const PropertyChangedCondition&) = default;
165 PropertyChangedCondition(PropertyChangedCondition&&) = default;
166 PropertyChangedCondition& operator=(PropertyChangedCondition&&) = default;
167 PropertyChangedCondition(const char* iface, const char* property,
168 U&& condition) :
169 _iface(iface),
170 _property(property),
171 _condition(std::forward<U>(condition)) { }
172
173 /** @brief Test a property value.
174 *
175 * Extract the property from the PropertiesChanged
176 * message and run the condition test.
177 */
178 bool operator()(
179 sdbusplus::bus::bus&,
180 sdbusplus::message::message& msg,
181 Manager&) const
182 {
183 std::map <
184 std::string,
185 sdbusplus::message::variant<T >> properties;
186 const char* iface = nullptr;
187
188 msg.read(iface);
189 if (!iface || strcmp(iface, _iface))
190 {
191 return false;
192 }
193
194 msg.read(properties);
195 auto it = properties.find(_property);
196 if (it == properties.cend())
197 {
198 return false;
199 }
200
201 return _condition(
202 std::forward<T>(it->second.template get<T>()));
203 }
204
205 private:
206 const char* _iface;
207 const char* _property;
208 U _condition;
209};
210
211/** @struct PropertyConditionBase
212 * @brief Match filter functor that tests a property value.
213 *
214 * Base class for PropertyCondition - factored out code that
215 * doesn't need to be templated.
216 */
217struct PropertyConditionBase
218{
219 PropertyConditionBase() = delete;
220 virtual ~PropertyConditionBase() = default;
221 PropertyConditionBase(const PropertyConditionBase&) = default;
222 PropertyConditionBase& operator=(const PropertyConditionBase&) = default;
223 PropertyConditionBase(PropertyConditionBase&&) = default;
224 PropertyConditionBase& operator=(PropertyConditionBase&&) = default;
225
226 /** @brief Constructor
227 *
228 * The service argument can be nullptr. If something
229 * else is provided the function will call the the
230 * service directly. If omitted, the function will
231 * look up the service in the ObjectMapper.
232 *
233 * @param path - The path of the object containing
234 * the property to be tested.
235 * @param iface - The interface hosting the property
236 * to be tested.
237 * @param property - The property to be tested.
238 * @param service - The DBus service hosting the object.
239 */
240 PropertyConditionBase(
241 const char* path,
242 const char* iface,
243 const char* property,
244 const char* service) :
Brad Bishopd0f48ad2017-01-30 08:52:26 -0500245 _path(path ? path : std::string()),
Brad Bishopc1f47982017-02-09 01:27:38 -0500246 _iface(iface),
247 _property(property),
248 _service(service) {}
249
250 /** @brief Forward comparison to type specific implementation. */
251 virtual bool eval(sdbusplus::message::message&) const = 0;
252
253 /** @brief Test a property value.
254 *
255 * Make a DBus call and test the value of any property.
256 */
257 bool operator()(
258 sdbusplus::bus::bus&,
259 sdbusplus::message::message&,
260 Manager&) const;
261
Brad Bishopd0f48ad2017-01-30 08:52:26 -0500262 /** @brief Test a property value.
263 *
264 * Make a DBus call and test the value of any property.
265 */
266 bool operator()(
267 const std::string&,
268 sdbusplus::bus::bus&,
269 Manager&) const;
270
Brad Bishopc1f47982017-02-09 01:27:38 -0500271 private:
272 std::string _path;
273 std::string _iface;
274 std::string _property;
275 const char* _service;
276};
277
278/** @struct PropertyCondition
279 * @brief Match filter functor that tests a property value.
280 *
281 * @tparam T - The type of the property being tested.
282 * @tparam U - The type of the condition checking functor.
283 */
284template <typename T, typename U>
285struct PropertyCondition final : public PropertyConditionBase
286{
287 PropertyCondition() = delete;
288 ~PropertyCondition() = default;
289 PropertyCondition(const PropertyCondition&) = default;
290 PropertyCondition& operator=(const PropertyCondition&) = default;
291 PropertyCondition(PropertyCondition&&) = default;
292 PropertyCondition& operator=(PropertyCondition&&) = default;
293
294 /** @brief Constructor
295 *
296 * The service argument can be nullptr. If something
297 * else is provided the function will call the the
298 * service directly. If omitted, the function will
299 * look up the service in the ObjectMapper.
300 *
301 * @param path - The path of the object containing
302 * the property to be tested.
303 * @param iface - The interface hosting the property
304 * to be tested.
305 * @param property - The property to be tested.
306 * @param condition - The test to run on the property.
307 * @param service - The DBus service hosting the object.
308 */
309 PropertyCondition(
310 const char* path,
311 const char* iface,
312 const char* property,
313 U&& condition,
314 const char* service) :
315 PropertyConditionBase(path, iface, property, service),
316 _condition(std::forward<decltype(condition)>(condition)) {}
317
318 /** @brief Test a property value.
319 *
320 * Make a DBus call and test the value of any property.
321 */
322 bool eval(sdbusplus::message::message& msg) const override
323 {
324 sdbusplus::message::variant<T> value;
325 msg.read(value);
326 return _condition(
327 std::forward<T>(value.template get<T>()));
328 }
329
330 private:
331 U _condition;
332};
333
334/** @brief Implicit type deduction for constructing PropertyChangedCondition. */
335template <typename T>
336auto propertyChangedTo(
337 const char* iface,
338 const char* property,
339 T&& val)
340{
341 auto condition = [val = std::forward<T>(val)](T && arg)
342 {
343 return arg == val;
344 };
345 using U = decltype(condition);
346 return PropertyChangedCondition<T, U>(
347 iface, property, std::move(condition));
348}
349
350/** @brief Implicit type deduction for constructing PropertyCondition. */
351template <typename T>
352auto propertyIs(
353 const char* path,
354 const char* iface,
355 const char* property,
356 T&& val,
357 const char* service = nullptr)
358{
359 auto condition = [val = std::forward<T>(val)](T && arg)
360 {
361 return arg == val;
362 };
363 using U = decltype(condition);
364 return PropertyCondition<T, U>(
365 path, iface, property, std::move(condition), service);
366}
367} // namespace functor
368} // namespace manager
369} // namespace inventory
370} // namespace phosphor
371
372// vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4