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