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*, 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()(sdbusplus::message::message& msg, Manager&) const 125 { 126 std::map < 127 std::string, 128 sdbusplus::message::variant<T >> properties; 129 const char* iface = nullptr; 130 131 msg.read(iface); 132 if (!iface || strcmp(iface, _iface)) 133 { 134 return false; 135 } 136 137 msg.read(properties); 138 auto it = properties.find(_property); 139 if (it == properties.cend()) 140 { 141 return false; 142 } 143 144 return _condition( 145 std::forward<T>(it->second.template get<T>())); 146 } 147 148 private: 149 const char* _iface; 150 const char* _property; 151 U _condition; 152 }; 153 154 } // namespace property_condition 155 } // namespace details 156 157 /** @brief Implicit type deduction for constructing PropertyChangedCondition. */ 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)](T && arg) 165 { 166 return arg == val; 167 }; 168 using U = decltype(condition); 169 return details::property_condition::PropertyChangedCondition<T, U>( 170 iface, property, std::move(condition)); 171 } 172 173 } // namespace filters 174 } // namespace manager 175 } // namespace inventory 176 } // namespace phosphor 177 178 // vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 179