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::bus::bus&, sdbusplus::message::message&, Manager& >; 20 using FilterBasePtr = std::shared_ptr<FilterBase>; 21 template <typename T> 22 using Filter = holder::CallableHolder < 23 T, bool, sdbusplus::bus::bus&, 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*, std::vector<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, const std::vector<FilterBasePtr>& filters) : 69 Event(Type::DBUS_SIGNAL), 70 std::tuple<const char*, std::vector<FilterBasePtr>>( 71 sig, std::move(filters)) {} 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 PropertyChangedCondition 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 PropertyChangedCondition 106 { 107 PropertyChangedCondition() = delete; 108 ~PropertyChangedCondition() = default; 109 PropertyChangedCondition(const PropertyChangedCondition&) = default; 110 PropertyChangedCondition& operator=(const PropertyChangedCondition&) = delete; 111 PropertyChangedCondition(PropertyChangedCondition&&) = default; 112 PropertyChangedCondition& operator=(PropertyChangedCondition&&) = default; 113 PropertyChangedCondition(const char* iface, const char* property, 114 U&& condition) : 115 _iface(iface), 116 _property(property), 117 _condition(std::forward<U>(condition)) { } 118 119 /** @brief Test a property value. 120 * 121 * Extract the property from the PropertiesChanged 122 * message and run the condition test. 123 */ 124 bool operator()( 125 sdbusplus::bus::bus&, 126 sdbusplus::message::message& msg, 127 Manager&) const 128 { 129 std::map < 130 std::string, 131 sdbusplus::message::variant<T >> properties; 132 const char* iface = nullptr; 133 134 msg.read(iface); 135 if (!iface || strcmp(iface, _iface)) 136 { 137 return false; 138 } 139 140 msg.read(properties); 141 auto it = properties.find(_property); 142 if (it == properties.cend()) 143 { 144 return false; 145 } 146 147 return _condition( 148 std::forward<T>(it->second.template get<T>())); 149 } 150 151 private: 152 const char* _iface; 153 const char* _property; 154 U _condition; 155 }; 156 157 } // namespace property_condition 158 } // namespace details 159 160 /** @brief Implicit type deduction for constructing PropertyChangedCondition. */ 161 template <typename T> 162 auto propertyChangedTo( 163 const char* iface, 164 const char* property, 165 T&& val) 166 { 167 auto condition = [val = std::move(val)](T && arg) 168 { 169 return arg == val; 170 }; 171 using U = decltype(condition); 172 return details::property_condition::PropertyChangedCondition<T, U>( 173 iface, property, std::move(condition)); 174 } 175 176 } // namespace filters 177 } // namespace manager 178 } // namespace inventory 179 } // namespace phosphor 180 181 // vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 182