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