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