xref: /openbmc/phosphor-inventory-manager/functor.hpp (revision a680d1eff9ee796a294761dbdffe62cae4cda161)
1c1f4798dSBrad Bishop #pragma once
2c1f4798dSBrad Bishop 
3*a680d1efSPatrick Venture #include "types.hpp"
4*a680d1efSPatrick Venture #include "utils.hpp"
5*a680d1efSPatrick Venture 
6c1f4798dSBrad Bishop #include <memory>
7c1f4798dSBrad Bishop #include <sdbusplus/bus.hpp>
8*a680d1efSPatrick Venture #include <utility>
9c1f4798dSBrad Bishop 
10c1f4798dSBrad Bishop namespace phosphor
11c1f4798dSBrad Bishop {
12c1f4798dSBrad Bishop namespace inventory
13c1f4798dSBrad Bishop {
14c1f4798dSBrad Bishop namespace manager
15c1f4798dSBrad Bishop {
16c1f4798dSBrad Bishop 
17c1f4798dSBrad Bishop class Manager;
18c1f4798dSBrad Bishop 
19c1f4798dSBrad Bishop /** @brief make_action
20c1f4798dSBrad Bishop  *
21c1f4798dSBrad Bishop  *  Adapt an action function object.
22c1f4798dSBrad Bishop  *
23c1f4798dSBrad Bishop  *  @param[in] action - The action being adapted.
24c1f4798dSBrad Bishop  *  @returns - The adapted action.
25c1f4798dSBrad Bishop  *
26c1f4798dSBrad Bishop  *  @tparam T - The type of the action being adapted.
27c1f4798dSBrad Bishop  */
28*a680d1efSPatrick Venture template <typename T>
29*a680d1efSPatrick Venture auto make_action(T&& action)
30c1f4798dSBrad Bishop {
31c1f4798dSBrad Bishop     return Action(std::forward<T>(action));
32c1f4798dSBrad Bishop }
33c1f4798dSBrad Bishop 
34c1f4798dSBrad Bishop /** @brief make_filter
35c1f4798dSBrad Bishop  *
36c1f4798dSBrad Bishop  *  Adapt a filter function object.
37c1f4798dSBrad Bishop  *
38c1f4798dSBrad Bishop  *  @param[in] filter - The filter being adapted.
39c1f4798dSBrad Bishop  *  @returns - The adapted filter.
40c1f4798dSBrad Bishop  *
41c1f4798dSBrad Bishop  *  @tparam T - The type of the filter being adapted.
42c1f4798dSBrad Bishop  */
43*a680d1efSPatrick Venture template <typename T>
44*a680d1efSPatrick Venture auto make_filter(T&& filter)
45c1f4798dSBrad Bishop {
46c1f4798dSBrad Bishop     return Filter(std::forward<T>(filter));
47c1f4798dSBrad Bishop }
48c1f4798dSBrad Bishop 
49d0f48adcSBrad Bishop /** @brief make_path_condition
50d0f48adcSBrad Bishop  *
51d0f48adcSBrad Bishop  *  Adapt a path_condition function object.
52d0f48adcSBrad Bishop  *
53d0f48adcSBrad Bishop  *  @param[in] filter - The functor being adapted.
54d0f48adcSBrad Bishop  *  @returns - The adapted functor.
55d0f48adcSBrad Bishop  *
56d0f48adcSBrad Bishop  *  @tparam T - The type of the functor being adapted.
57d0f48adcSBrad Bishop  */
58*a680d1efSPatrick Venture template <typename T>
59*a680d1efSPatrick Venture auto make_path_condition(T&& condition)
60d0f48adcSBrad Bishop {
61d0f48adcSBrad Bishop     return PathCondition(std::forward<T>(condition));
62d0f48adcSBrad Bishop }
63d0f48adcSBrad Bishop 
64d0f48adcSBrad Bishop template <typename T, typename... Args>
65d0f48adcSBrad Bishop auto callArrayWithStatus(T&& container, Args&&... args)
66d0f48adcSBrad Bishop {
67d0f48adcSBrad Bishop     for (auto f : container)
68d0f48adcSBrad Bishop     {
69d0f48adcSBrad Bishop         if (!f(std::forward<Args>(args)...))
70d0f48adcSBrad Bishop         {
71d0f48adcSBrad Bishop             return false;
72d0f48adcSBrad Bishop         }
73d0f48adcSBrad Bishop     }
74d0f48adcSBrad Bishop     return true;
75d0f48adcSBrad Bishop }
76d0f48adcSBrad Bishop 
77c1f4798dSBrad Bishop namespace functor
78c1f4798dSBrad Bishop {
79c1f4798dSBrad Bishop 
80c1f4798dSBrad Bishop /** @brief Destroy objects action.  */
81615b2a8fSBrad Bishop inline auto destroyObjects(std::vector<const char*>&& paths,
82d0f48adcSBrad Bishop                            std::vector<PathCondition>&& conditions)
83c1f4798dSBrad Bishop {
84615b2a8fSBrad Bishop     return [=](auto& b, auto& m) {
85d0f48adcSBrad Bishop         for (const auto& p : paths)
86d0f48adcSBrad Bishop         {
87d0f48adcSBrad Bishop             if (callArrayWithStatus(conditions, p, b, m))
88d0f48adcSBrad Bishop             {
89d0f48adcSBrad Bishop                 m.destroyObjects({p});
90d0f48adcSBrad Bishop             }
91d0f48adcSBrad Bishop         }
92c1f4798dSBrad Bishop     };
93c1f4798dSBrad Bishop }
94c1f4798dSBrad Bishop 
95c1f4798dSBrad Bishop /** @brief Create objects action.  */
96615b2a8fSBrad Bishop inline auto
97615b2a8fSBrad Bishop     createObjects(std::map<sdbusplus::message::object_path, Object>&& objs)
98c1f4798dSBrad Bishop {
99615b2a8fSBrad Bishop     return [=](auto&, auto& m) { m.createObjects(objs); };
100c1f4798dSBrad Bishop }
101c1f4798dSBrad Bishop 
102c1f4798dSBrad Bishop /** @brief Set a property action.
103c1f4798dSBrad Bishop  *
104c1f4798dSBrad Bishop  *  Invoke the requested method with a reference to the requested
105c1f4798dSBrad Bishop  *  sdbusplus server binding interface as a parameter.
106c1f4798dSBrad Bishop  *
107c1f4798dSBrad Bishop  *  @tparam T - The sdbusplus server binding interface type.
108c1f4798dSBrad Bishop  *  @tparam U - The type of the sdbusplus server binding member
109c1f4798dSBrad Bishop  *      function that sets the property.
110c1f4798dSBrad Bishop  *  @tparam V - The property value type.
111c1f4798dSBrad Bishop  *
112c1f4798dSBrad Bishop  *  @param[in] paths - The DBus paths on which the property should
113c1f4798dSBrad Bishop  *      be set.
114c1f4798dSBrad Bishop  *  @param[in] iface - The DBus interface hosting the property.
115c1f4798dSBrad Bishop  *  @param[in] member - Pointer to sdbusplus server binding member.
116c1f4798dSBrad Bishop  *  @param[in] value - The value the property should be set to.
117c1f4798dSBrad Bishop  *
118c1f4798dSBrad Bishop  *  @returns - A function object that sets the requested property
119c1f4798dSBrad Bishop  *      to the requested value.
120c1f4798dSBrad Bishop  */
121c1f4798dSBrad Bishop template <typename T, typename U, typename V>
122615b2a8fSBrad Bishop auto setProperty(std::vector<const char*>&& paths,
123615b2a8fSBrad Bishop                  std::vector<PathCondition>&& conditions, const char* iface,
124615b2a8fSBrad Bishop                  U&& member, V&& value)
125c1f4798dSBrad Bishop {
126c1f4798dSBrad Bishop     // The manager is the only parameter passed to actions.
127c1f4798dSBrad Bishop     // Bind the path, interface, interface member function pointer,
128c1f4798dSBrad Bishop     // and value to a lambda.  When it is called, forward the
129c1f4798dSBrad Bishop     // path, interface and value on to the manager member function.
130*a680d1efSPatrick Venture     return [paths, conditions = conditions, iface, member,
131*a680d1efSPatrick Venture             value = std::forward<V>(value)](auto& b, auto& m) {
132c1f4798dSBrad Bishop         for (auto p : paths)
133c1f4798dSBrad Bishop         {
134d0f48adcSBrad Bishop             if (callArrayWithStatus(conditions, p, b, m))
135d0f48adcSBrad Bishop             {
136615b2a8fSBrad Bishop                 m.template invokeMethod<T>(p, iface, member, value);
137c1f4798dSBrad Bishop             }
138d0f48adcSBrad Bishop         }
139c1f4798dSBrad Bishop     };
140c1f4798dSBrad Bishop }
141c1f4798dSBrad Bishop 
142c1f4798dSBrad Bishop /** @struct PropertyChangedCondition
143c1f4798dSBrad Bishop  *  @brief Match filter functor that tests a property value.
144c1f4798dSBrad Bishop  *
145c1f4798dSBrad Bishop  *  @tparam T - The type of the property being tested.
146c1f4798dSBrad Bishop  *  @tparam U - The type of the condition checking functor.
147c1f4798dSBrad Bishop  */
148*a680d1efSPatrick Venture template <typename T, typename U>
149*a680d1efSPatrick Venture struct PropertyChangedCondition
150c1f4798dSBrad Bishop {
151c1f4798dSBrad Bishop     PropertyChangedCondition() = delete;
152c1f4798dSBrad Bishop     ~PropertyChangedCondition() = default;
153c1f4798dSBrad Bishop     PropertyChangedCondition(const PropertyChangedCondition&) = default;
154615b2a8fSBrad Bishop     PropertyChangedCondition&
155615b2a8fSBrad Bishop         operator=(const PropertyChangedCondition&) = default;
156c1f4798dSBrad Bishop     PropertyChangedCondition(PropertyChangedCondition&&) = default;
157c1f4798dSBrad Bishop     PropertyChangedCondition& operator=(PropertyChangedCondition&&) = default;
158c1f4798dSBrad Bishop     PropertyChangedCondition(const char* iface, const char* property,
159c1f4798dSBrad Bishop                              U&& condition) :
160c1f4798dSBrad Bishop         _iface(iface),
161615b2a8fSBrad Bishop         _property(property), _condition(std::forward<U>(condition))
162615b2a8fSBrad Bishop     {
163615b2a8fSBrad Bishop     }
164c1f4798dSBrad Bishop 
165c1f4798dSBrad Bishop     /** @brief Test a property value.
166c1f4798dSBrad Bishop      *
167c1f4798dSBrad Bishop      * Extract the property from the PropertiesChanged
168c1f4798dSBrad Bishop      * message and run the condition test.
169c1f4798dSBrad Bishop      */
170615b2a8fSBrad Bishop     bool operator()(sdbusplus::bus::bus&, sdbusplus::message::message& msg,
171c1f4798dSBrad Bishop                     Manager&) const
172c1f4798dSBrad Bishop     {
173615b2a8fSBrad Bishop         std::map<std::string, sdbusplus::message::variant<T>> properties;
174c1f4798dSBrad Bishop         const char* iface = nullptr;
175c1f4798dSBrad Bishop 
176c1f4798dSBrad Bishop         msg.read(iface);
177c1f4798dSBrad Bishop         if (!iface || strcmp(iface, _iface))
178c1f4798dSBrad Bishop         {
179c1f4798dSBrad Bishop             return false;
180c1f4798dSBrad Bishop         }
181c1f4798dSBrad Bishop 
182c1f4798dSBrad Bishop         msg.read(properties);
183c1f4798dSBrad Bishop         auto it = properties.find(_property);
184c1f4798dSBrad Bishop         if (it == properties.cend())
185c1f4798dSBrad Bishop         {
186c1f4798dSBrad Bishop             return false;
187c1f4798dSBrad Bishop         }
188c1f4798dSBrad Bishop 
189615b2a8fSBrad Bishop         return _condition(std::forward<T>(it->second.template get<T>()));
190c1f4798dSBrad Bishop     }
191c1f4798dSBrad Bishop 
192c1f4798dSBrad Bishop   private:
193c1f4798dSBrad Bishop     const char* _iface;
194c1f4798dSBrad Bishop     const char* _property;
195c1f4798dSBrad Bishop     U _condition;
196c1f4798dSBrad Bishop };
197c1f4798dSBrad Bishop 
198c1f4798dSBrad Bishop /** @struct PropertyConditionBase
199c1f4798dSBrad Bishop  *  @brief Match filter functor that tests a property value.
200c1f4798dSBrad Bishop  *
201c1f4798dSBrad Bishop  *  Base class for PropertyCondition - factored out code that
202c1f4798dSBrad Bishop  *  doesn't need to be templated.
203c1f4798dSBrad Bishop  */
204c1f4798dSBrad Bishop struct PropertyConditionBase
205c1f4798dSBrad Bishop {
206c1f4798dSBrad Bishop     PropertyConditionBase() = delete;
207c1f4798dSBrad Bishop     virtual ~PropertyConditionBase() = default;
208c1f4798dSBrad Bishop     PropertyConditionBase(const PropertyConditionBase&) = default;
209c1f4798dSBrad Bishop     PropertyConditionBase& operator=(const PropertyConditionBase&) = default;
210c1f4798dSBrad Bishop     PropertyConditionBase(PropertyConditionBase&&) = default;
211c1f4798dSBrad Bishop     PropertyConditionBase& operator=(PropertyConditionBase&&) = default;
212c1f4798dSBrad Bishop 
213c1f4798dSBrad Bishop     /** @brief Constructor
214c1f4798dSBrad Bishop      *
215c1f4798dSBrad Bishop      *  The service argument can be nullptr.  If something
216c1f4798dSBrad Bishop      *  else is provided the function will call the the
217c1f4798dSBrad Bishop      *  service directly.  If omitted, the function will
218c1f4798dSBrad Bishop      *  look up the service in the ObjectMapper.
219c1f4798dSBrad Bishop      *
220c1f4798dSBrad Bishop      *  @param path - The path of the object containing
221c1f4798dSBrad Bishop      *     the property to be tested.
222c1f4798dSBrad Bishop      *  @param iface - The interface hosting the property
223c1f4798dSBrad Bishop      *     to be tested.
224c1f4798dSBrad Bishop      *  @param property - The property to be tested.
225c1f4798dSBrad Bishop      *  @param service - The DBus service hosting the object.
226c1f4798dSBrad Bishop      */
227615b2a8fSBrad Bishop     PropertyConditionBase(const char* path, const char* iface,
228615b2a8fSBrad Bishop                           const char* property, const char* service) :
229d0f48adcSBrad Bishop         _path(path ? path : std::string()),
230615b2a8fSBrad Bishop         _iface(iface), _property(property), _service(service)
231615b2a8fSBrad Bishop     {
232615b2a8fSBrad Bishop     }
233c1f4798dSBrad Bishop 
234c1f4798dSBrad Bishop     /** @brief Forward comparison to type specific implementation. */
235c1f4798dSBrad Bishop     virtual bool eval(sdbusplus::message::message&) const = 0;
236c1f4798dSBrad Bishop 
237c1f4798dSBrad Bishop     /** @brief Test a property value.
238c1f4798dSBrad Bishop      *
239c1f4798dSBrad Bishop      * Make a DBus call and test the value of any property.
240c1f4798dSBrad Bishop      */
241615b2a8fSBrad Bishop     bool operator()(sdbusplus::bus::bus&, sdbusplus::message::message&,
242c1f4798dSBrad Bishop                     Manager&) const;
243c1f4798dSBrad Bishop 
244d0f48adcSBrad Bishop     /** @brief Test a property value.
245d0f48adcSBrad Bishop      *
246d0f48adcSBrad Bishop      * Make a DBus call and test the value of any property.
247d0f48adcSBrad Bishop      */
248615b2a8fSBrad Bishop     bool operator()(const std::string&, sdbusplus::bus::bus&, Manager&) const;
249d0f48adcSBrad Bishop 
250c1f4798dSBrad Bishop   private:
251c1f4798dSBrad Bishop     std::string _path;
252c1f4798dSBrad Bishop     std::string _iface;
253c1f4798dSBrad Bishop     std::string _property;
254c1f4798dSBrad Bishop     const char* _service;
255c1f4798dSBrad Bishop };
256c1f4798dSBrad Bishop 
257c1f4798dSBrad Bishop /** @struct PropertyCondition
258c1f4798dSBrad Bishop  *  @brief Match filter functor that tests a property value.
259c1f4798dSBrad Bishop  *
260c1f4798dSBrad Bishop  *  @tparam T - The type of the property being tested.
261c1f4798dSBrad Bishop  *  @tparam U - The type of the condition checking functor.
262c1f4798dSBrad Bishop  */
263c1f4798dSBrad Bishop template <typename T, typename U>
264c1f4798dSBrad Bishop struct PropertyCondition final : public PropertyConditionBase
265c1f4798dSBrad Bishop {
266c1f4798dSBrad Bishop     PropertyCondition() = delete;
267c1f4798dSBrad Bishop     ~PropertyCondition() = default;
268c1f4798dSBrad Bishop     PropertyCondition(const PropertyCondition&) = default;
269c1f4798dSBrad Bishop     PropertyCondition& operator=(const PropertyCondition&) = default;
270c1f4798dSBrad Bishop     PropertyCondition(PropertyCondition&&) = default;
271c1f4798dSBrad Bishop     PropertyCondition& operator=(PropertyCondition&&) = default;
272c1f4798dSBrad Bishop 
273c1f4798dSBrad Bishop     /** @brief Constructor
274c1f4798dSBrad Bishop      *
275c1f4798dSBrad Bishop      *  The service argument can be nullptr.  If something
276c1f4798dSBrad Bishop      *  else is provided the function will call the the
277c1f4798dSBrad Bishop      *  service directly.  If omitted, the function will
278c1f4798dSBrad Bishop      *  look up the service in the ObjectMapper.
279c1f4798dSBrad Bishop      *
280c1f4798dSBrad Bishop      *  @param path - The path of the object containing
281c1f4798dSBrad Bishop      *     the property to be tested.
282c1f4798dSBrad Bishop      *  @param iface - The interface hosting the property
283c1f4798dSBrad Bishop      *     to be tested.
284c1f4798dSBrad Bishop      *  @param property - The property to be tested.
285c1f4798dSBrad Bishop      *  @param condition - The test to run on the property.
286c1f4798dSBrad Bishop      *  @param service - The DBus service hosting the object.
287c1f4798dSBrad Bishop      */
288615b2a8fSBrad Bishop     PropertyCondition(const char* path, const char* iface, const char* property,
289615b2a8fSBrad Bishop                       U&& condition, const char* service) :
290c1f4798dSBrad Bishop         PropertyConditionBase(path, iface, property, service),
291615b2a8fSBrad Bishop         _condition(std::forward<decltype(condition)>(condition))
292615b2a8fSBrad Bishop     {
293615b2a8fSBrad Bishop     }
294c1f4798dSBrad Bishop 
295c1f4798dSBrad Bishop     /** @brief Test a property value.
296c1f4798dSBrad Bishop      *
297c1f4798dSBrad Bishop      * Make a DBus call and test the value of any property.
298c1f4798dSBrad Bishop      */
299c1f4798dSBrad Bishop     bool eval(sdbusplus::message::message& msg) const override
300c1f4798dSBrad Bishop     {
301c1f4798dSBrad Bishop         sdbusplus::message::variant<T> value;
302c1f4798dSBrad Bishop         msg.read(value);
303615b2a8fSBrad Bishop         return _condition(std::forward<T>(value.template get<T>()));
304c1f4798dSBrad Bishop     }
305c1f4798dSBrad Bishop 
306c1f4798dSBrad Bishop   private:
307c1f4798dSBrad Bishop     U _condition;
308c1f4798dSBrad Bishop };
309c1f4798dSBrad Bishop 
310c1f4798dSBrad Bishop /** @brief Implicit type deduction for constructing PropertyChangedCondition. */
311c1f4798dSBrad Bishop template <typename T>
312615b2a8fSBrad Bishop auto propertyChangedTo(const char* iface, const char* property, T&& val)
313c1f4798dSBrad Bishop {
314*a680d1efSPatrick Venture     auto condition = [val = std::forward<T>(val)](T&& arg) {
315c1f4798dSBrad Bishop         return arg == val;
316c1f4798dSBrad Bishop     };
317c1f4798dSBrad Bishop     using U = decltype(condition);
318615b2a8fSBrad Bishop     return PropertyChangedCondition<T, U>(iface, property,
319615b2a8fSBrad Bishop                                           std::move(condition));
320c1f4798dSBrad Bishop }
321c1f4798dSBrad Bishop 
322c1f4798dSBrad Bishop /** @brief Implicit type deduction for constructing PropertyCondition.  */
323c1f4798dSBrad Bishop template <typename T>
324615b2a8fSBrad Bishop auto propertyIs(const char* path, const char* iface, const char* property,
325615b2a8fSBrad Bishop                 T&& val, const char* service = nullptr)
326c1f4798dSBrad Bishop {
327*a680d1efSPatrick Venture     auto condition = [val = std::forward<T>(val)](T&& arg) {
328c1f4798dSBrad Bishop         return arg == val;
329c1f4798dSBrad Bishop     };
330c1f4798dSBrad Bishop     using U = decltype(condition);
331615b2a8fSBrad Bishop     return PropertyCondition<T, U>(path, iface, property, std::move(condition),
332615b2a8fSBrad Bishop                                    service);
333c1f4798dSBrad Bishop }
334c1f4798dSBrad Bishop } // namespace functor
335c1f4798dSBrad Bishop } // namespace manager
336c1f4798dSBrad Bishop } // namespace inventory
337c1f4798dSBrad Bishop } // namespace phosphor
338c1f4798dSBrad Bishop 
339c1f4798dSBrad Bishop // vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
340