1 #pragma once 2 3 #include <utility> 4 #include <memory> 5 #include <sdbusplus/message.hpp> 6 #include "utils.hpp" 7 8 namespace phosphor 9 { 10 namespace inventory 11 { 12 namespace manager 13 { 14 15 class Manager; 16 namespace details 17 { 18 using FilterBase = holder::CallableBase< 19 bool, sdbusplus::message::message&, Manager&>; 20 using FilterBasePtr = std::shared_ptr<FilterBase>; 21 template <typename T> 22 using Filter = holder::CallableHolder< 23 T, bool, sdbusplus::message::message&, Manager&>; 24 25 /** @struct Event 26 * @brief Event object interface. 27 */ 28 struct Event 29 { 30 enum class Type 31 { 32 DBUS_SIGNAL, 33 }; 34 35 virtual ~Event() = default; 36 Event(const Event&) = default; 37 Event& operator=(const Event&) = default; 38 Event(Event&&) = default; 39 Event& operator=(Event&&) = default; 40 explicit Event(Type t) : type(t) {} 41 42 Type type; 43 }; 44 45 using EventBasePtr = std::shared_ptr<Event>; 46 47 /** @struct DbusSignal 48 * @brief DBus signal event. 49 * 50 * DBus signal events are an association of a match signature 51 * and filtering function object. 52 */ 53 struct DbusSignal final : 54 public Event, 55 public std::tuple<const char *, FilterBasePtr> 56 { 57 virtual ~DbusSignal() = default; 58 DbusSignal(const DbusSignal&) = default; 59 DbusSignal & operator=(const DbusSignal&) = delete; 60 DbusSignal(DbusSignal&&) = default; 61 DbusSignal& operator=(DbusSignal&&) = default; 62 63 /** @brief Import from signature and filter constructor. 64 * 65 * @param[in] sig - The DBus match signature. 66 * @param[in] filter - A DBus signal match callback filtering function. 67 */ 68 DbusSignal(const char *sig, FilterBasePtr filter) : 69 Event(Type::DBUS_SIGNAL), 70 std::tuple<const char *, FilterBasePtr>( 71 sig, std::move(filter)) {} 72 }; 73 74 /** @brief make_filter 75 * 76 * Adapt a filter function object. 77 * 78 * @param[in] filter - The filter being adapted. 79 * @returns - The adapted filter. 80 * 81 * @tparam T - The type of the filter being adapted. 82 */ 83 template <typename T> 84 auto make_filter(T&& filter) 85 { 86 return Filter<T>::template make_shared<Filter<T>>( 87 std::forward<T>(filter)); 88 } 89 } // namespace details 90 91 namespace filters 92 { 93 namespace details 94 { 95 namespace property_condition 96 { 97 98 /** @struct PropertyCondition 99 * @brief Match filter functor that tests a property value. 100 * 101 * @tparam T - The type of the property being tested. 102 * @tparam U - The type of the condition checking functor. 103 */ 104 template <typename T, typename U> 105 struct PropertyCondition 106 { 107 PropertyCondition() = delete; 108 ~PropertyCondition() = default; 109 PropertyCondition(const PropertyCondition&) = default; 110 PropertyCondition & operator=(const PropertyCondition&) = delete; 111 PropertyCondition(PropertyCondition&&) = default; 112 PropertyCondition& operator=(PropertyCondition&&) = default; 113 PropertyCondition(const char *iface, const char *property, U &&condition) : 114 _iface(iface), 115 _property(property), 116 _condition(std::forward<U>(condition)) { } 117 118 /** @brief Test a property value. 119 * 120 * Extract the property from the PropertiesChanged 121 * message and run the condition test. 122 */ 123 bool operator()(sdbusplus::message::message &msg, Manager &) const 124 { 125 std::map< 126 std::string, 127 sdbusplus::message::variant<T>> properties; 128 const char *iface = nullptr; 129 130 msg.read(iface); 131 if(strcmp(iface, _iface)) 132 return false; 133 134 msg.read(properties); 135 auto it = properties.find(_property); 136 if(it == properties.cend()) 137 return false; 138 139 return _condition(it->second); 140 } 141 142 private: 143 const char *_iface; 144 const char *_property; 145 U _condition; 146 }; 147 148 } // namespace property_condition 149 } // namespace details 150 151 /** @brief The default filter. */ 152 inline bool none(sdbusplus::message::message &, Manager &) noexcept 153 { 154 return true; 155 } 156 157 /** @brief Implicit type deduction for constructing PropertyCondition. */ 158 template <typename T> 159 auto propertyChangedTo( 160 const char *iface, 161 const char *property, 162 T val) 163 { 164 auto condition = [val = std::move(val)](auto arg){return arg == val;}; 165 using U = decltype(condition); 166 return details::property_condition::PropertyCondition<T, U>( 167 iface, property, std::move(condition)); 168 } 169 170 } // namespace filters 171 } // namespace manager 172 } // namespace inventory 173 } // namespace phosphor 174 175 // vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 176