blob: 265e4679413c7490139f43e55fb890704e04c8df [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
48namespace functor
49{
50
51/** @brief Destroy objects action. */
52inline auto destroyObjects(std::vector<const char*>&& paths)
53{
54 return [ = ](auto&, auto & m)
55 {
56 m.destroyObjects(paths);
57 };
58}
59
60/** @brief Create objects action. */
61inline auto createObjects(
62 std::map<sdbusplus::message::object_path, Object>&& objs)
63{
64 return [ = ](auto&, auto & m)
65 {
66 m.createObjects(objs);
67 };
68}
69
70/** @brief Set a property action.
71 *
72 * Invoke the requested method with a reference to the requested
73 * sdbusplus server binding interface as a parameter.
74 *
75 * @tparam T - The sdbusplus server binding interface type.
76 * @tparam U - The type of the sdbusplus server binding member
77 * function that sets the property.
78 * @tparam V - The property value type.
79 *
80 * @param[in] paths - The DBus paths on which the property should
81 * be set.
82 * @param[in] iface - The DBus interface hosting the property.
83 * @param[in] member - Pointer to sdbusplus server binding member.
84 * @param[in] value - The value the property should be set to.
85 *
86 * @returns - A function object that sets the requested property
87 * to the requested value.
88 */
89template <typename T, typename U, typename V>
90auto setProperty(
91 std::vector<const char*>&& paths, const char* iface,
92 U&& member, V&& value)
93{
94 // The manager is the only parameter passed to actions.
95 // Bind the path, interface, interface member function pointer,
96 // and value to a lambda. When it is called, forward the
97 // path, interface and value on to the manager member function.
98 return [paths, iface, member,
99 value = std::forward<V>(value)](auto&, auto & m)
100 {
101 for (auto p : paths)
102 {
103 m.template invokeMethod<T>(
104 p, iface, member, value);
105 }
106 };
107}
108
109/** @struct PropertyChangedCondition
110 * @brief Match filter functor that tests a property value.
111 *
112 * @tparam T - The type of the property being tested.
113 * @tparam U - The type of the condition checking functor.
114 */
115template <typename T, typename U>
116struct PropertyChangedCondition
117{
118 PropertyChangedCondition() = delete;
119 ~PropertyChangedCondition() = default;
120 PropertyChangedCondition(const PropertyChangedCondition&) = default;
121 PropertyChangedCondition& operator=(const PropertyChangedCondition&) = default;
122 PropertyChangedCondition(PropertyChangedCondition&&) = default;
123 PropertyChangedCondition& operator=(PropertyChangedCondition&&) = default;
124 PropertyChangedCondition(const char* iface, const char* property,
125 U&& condition) :
126 _iface(iface),
127 _property(property),
128 _condition(std::forward<U>(condition)) { }
129
130 /** @brief Test a property value.
131 *
132 * Extract the property from the PropertiesChanged
133 * message and run the condition test.
134 */
135 bool operator()(
136 sdbusplus::bus::bus&,
137 sdbusplus::message::message& msg,
138 Manager&) const
139 {
140 std::map <
141 std::string,
142 sdbusplus::message::variant<T >> properties;
143 const char* iface = nullptr;
144
145 msg.read(iface);
146 if (!iface || strcmp(iface, _iface))
147 {
148 return false;
149 }
150
151 msg.read(properties);
152 auto it = properties.find(_property);
153 if (it == properties.cend())
154 {
155 return false;
156 }
157
158 return _condition(
159 std::forward<T>(it->second.template get<T>()));
160 }
161
162 private:
163 const char* _iface;
164 const char* _property;
165 U _condition;
166};
167
168/** @struct PropertyConditionBase
169 * @brief Match filter functor that tests a property value.
170 *
171 * Base class for PropertyCondition - factored out code that
172 * doesn't need to be templated.
173 */
174struct PropertyConditionBase
175{
176 PropertyConditionBase() = delete;
177 virtual ~PropertyConditionBase() = default;
178 PropertyConditionBase(const PropertyConditionBase&) = default;
179 PropertyConditionBase& operator=(const PropertyConditionBase&) = default;
180 PropertyConditionBase(PropertyConditionBase&&) = default;
181 PropertyConditionBase& operator=(PropertyConditionBase&&) = default;
182
183 /** @brief Constructor
184 *
185 * The service argument can be nullptr. If something
186 * else is provided the function will call the the
187 * service directly. If omitted, the function will
188 * look up the service in the ObjectMapper.
189 *
190 * @param path - The path of the object containing
191 * the property to be tested.
192 * @param iface - The interface hosting the property
193 * to be tested.
194 * @param property - The property to be tested.
195 * @param service - The DBus service hosting the object.
196 */
197 PropertyConditionBase(
198 const char* path,
199 const char* iface,
200 const char* property,
201 const char* service) :
202 _path(path),
203 _iface(iface),
204 _property(property),
205 _service(service) {}
206
207 /** @brief Forward comparison to type specific implementation. */
208 virtual bool eval(sdbusplus::message::message&) const = 0;
209
210 /** @brief Test a property value.
211 *
212 * Make a DBus call and test the value of any property.
213 */
214 bool operator()(
215 sdbusplus::bus::bus&,
216 sdbusplus::message::message&,
217 Manager&) const;
218
219 private:
220 std::string _path;
221 std::string _iface;
222 std::string _property;
223 const char* _service;
224};
225
226/** @struct PropertyCondition
227 * @brief Match filter functor that tests a property value.
228 *
229 * @tparam T - The type of the property being tested.
230 * @tparam U - The type of the condition checking functor.
231 */
232template <typename T, typename U>
233struct PropertyCondition final : public PropertyConditionBase
234{
235 PropertyCondition() = delete;
236 ~PropertyCondition() = default;
237 PropertyCondition(const PropertyCondition&) = default;
238 PropertyCondition& operator=(const PropertyCondition&) = default;
239 PropertyCondition(PropertyCondition&&) = default;
240 PropertyCondition& operator=(PropertyCondition&&) = default;
241
242 /** @brief Constructor
243 *
244 * The service argument can be nullptr. If something
245 * else is provided the function will call the the
246 * service directly. If omitted, the function will
247 * look up the service in the ObjectMapper.
248 *
249 * @param path - The path of the object containing
250 * the property to be tested.
251 * @param iface - The interface hosting the property
252 * to be tested.
253 * @param property - The property to be tested.
254 * @param condition - The test to run on the property.
255 * @param service - The DBus service hosting the object.
256 */
257 PropertyCondition(
258 const char* path,
259 const char* iface,
260 const char* property,
261 U&& condition,
262 const char* service) :
263 PropertyConditionBase(path, iface, property, service),
264 _condition(std::forward<decltype(condition)>(condition)) {}
265
266 /** @brief Test a property value.
267 *
268 * Make a DBus call and test the value of any property.
269 */
270 bool eval(sdbusplus::message::message& msg) const override
271 {
272 sdbusplus::message::variant<T> value;
273 msg.read(value);
274 return _condition(
275 std::forward<T>(value.template get<T>()));
276 }
277
278 private:
279 U _condition;
280};
281
282/** @brief Implicit type deduction for constructing PropertyChangedCondition. */
283template <typename T>
284auto propertyChangedTo(
285 const char* iface,
286 const char* property,
287 T&& val)
288{
289 auto condition = [val = std::forward<T>(val)](T && arg)
290 {
291 return arg == val;
292 };
293 using U = decltype(condition);
294 return PropertyChangedCondition<T, U>(
295 iface, property, std::move(condition));
296}
297
298/** @brief Implicit type deduction for constructing PropertyCondition. */
299template <typename T>
300auto propertyIs(
301 const char* path,
302 const char* iface,
303 const char* property,
304 T&& val,
305 const char* service = nullptr)
306{
307 auto condition = [val = std::forward<T>(val)](T && arg)
308 {
309 return arg == val;
310 };
311 using U = decltype(condition);
312 return PropertyCondition<T, U>(
313 path, iface, property, std::move(condition), service);
314}
315} // namespace functor
316} // namespace manager
317} // namespace inventory
318} // namespace phosphor
319
320// vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4