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 { 133 return false; 134 } 135 136 msg.read(properties); 137 auto it = properties.find(_property); 138 if (it == properties.cend()) 139 { 140 return false; 141 } 142 143 return _condition(it->second.template get<T>()); 144 } 145 146 private: 147 const char* _iface; 148 const char* _property; 149 U _condition; 150 }; 151 152 } // namespace property_condition 153 } // namespace details 154 155 /** @brief The default filter. */ 156 inline bool none(sdbusplus::message::message&, Manager&) noexcept 157 { 158 return true; 159 } 160 161 /** @brief Implicit type deduction for constructing PropertyCondition. */ 162 template <typename T> 163 auto propertyChangedTo( 164 const char* iface, 165 const char* property, 166 T val) 167 { 168 auto condition = [val = std::move(val)](const std::string & arg) 169 { 170 return arg == val; 171 }; 172 using U = decltype(condition); 173 return details::property_condition::PropertyCondition<T, U>( 174 iface, property, std::move(condition)); 175 } 176 177 } // namespace filters 178 } // namespace manager 179 } // namespace inventory 180 } // namespace phosphor 181 182 // vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 183