| Brad Bishop | 3d57f50 | 2016-10-19 12:18:41 -0400 | [diff] [blame] | 1 | #pragma once | 
 | 2 |  | 
 | 3 | #include <utility> | 
 | 4 | #include <memory> | 
 | 5 | #include <sdbusplus/message.hpp> | 
| Brad Bishop | 65ffffa | 2016-11-29 12:31:31 -0500 | [diff] [blame] | 6 | #include "utils.hpp" | 
| Brad Bishop | 3d57f50 | 2016-10-19 12:18:41 -0400 | [diff] [blame] | 7 |  | 
 | 8 | namespace phosphor | 
 | 9 | { | 
 | 10 | namespace inventory | 
 | 11 | { | 
 | 12 | namespace manager | 
 | 13 | { | 
| Brad Bishop | c0eae11 | 2016-10-19 21:59:47 -0400 | [diff] [blame] | 14 |  | 
 | 15 | class Manager; | 
| Brad Bishop | 65ffffa | 2016-11-29 12:31:31 -0500 | [diff] [blame] | 16 | namespace details | 
 | 17 | { | 
| Brad Bishop | 7b33777 | 2017-01-12 16:11:24 -0500 | [diff] [blame] | 18 | using FilterBase = holder::CallableBase < | 
| Brad Bishop | 2371900 | 2017-01-24 21:08:46 -0500 | [diff] [blame] | 19 |                    bool, sdbusplus::bus::bus&, sdbusplus::message::message&, Manager& >; | 
| Brad Bishop | 65ffffa | 2016-11-29 12:31:31 -0500 | [diff] [blame] | 20 | using FilterBasePtr = std::shared_ptr<FilterBase>; | 
 | 21 | template <typename T> | 
| Brad Bishop | 7b33777 | 2017-01-12 16:11:24 -0500 | [diff] [blame] | 22 | using Filter = holder::CallableHolder < | 
| Brad Bishop | 2371900 | 2017-01-24 21:08:46 -0500 | [diff] [blame] | 23 |                T, bool, sdbusplus::bus::bus&, sdbusplus::message::message&, Manager& >; | 
| Brad Bishop | 65ffffa | 2016-11-29 12:31:31 -0500 | [diff] [blame] | 24 |  | 
| Brad Bishop | 4f20a3e | 2016-11-29 15:21:46 -0500 | [diff] [blame] | 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, | 
| Brad Bishop | 064c94a | 2017-01-21 21:33:30 -0500 | [diff] [blame] | 55 |     public std::tuple<const char*, std::vector<FilterBasePtr>> | 
| Brad Bishop | 4f20a3e | 2016-11-29 15:21:46 -0500 | [diff] [blame] | 56 | { | 
 | 57 |     virtual ~DbusSignal() = default; | 
 | 58 |     DbusSignal(const DbusSignal&) = default; | 
| Brad Bishop | 7b33777 | 2017-01-12 16:11:24 -0500 | [diff] [blame] | 59 |     DbusSignal& operator=(const DbusSignal&) = delete; | 
| Brad Bishop | 4f20a3e | 2016-11-29 15:21:46 -0500 | [diff] [blame] | 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 |      */ | 
| Brad Bishop | 064c94a | 2017-01-21 21:33:30 -0500 | [diff] [blame] | 68 |     DbusSignal(const char* sig, const std::vector<FilterBasePtr>& filters) : | 
| Brad Bishop | 4f20a3e | 2016-11-29 15:21:46 -0500 | [diff] [blame] | 69 |         Event(Type::DBUS_SIGNAL), | 
| Brad Bishop | 064c94a | 2017-01-21 21:33:30 -0500 | [diff] [blame] | 70 |         std::tuple<const char*, std::vector<FilterBasePtr>>( | 
 | 71 |                     sig, std::move(filters)) {} | 
| Brad Bishop | 4f20a3e | 2016-11-29 15:21:46 -0500 | [diff] [blame] | 72 | }; | 
 | 73 |  | 
| Brad Bishop | 65ffffa | 2016-11-29 12:31:31 -0500 | [diff] [blame] | 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 |  | 
| Brad Bishop | 3d57f50 | 2016-10-19 12:18:41 -0400 | [diff] [blame] | 91 | namespace filters | 
 | 92 | { | 
 | 93 | namespace details | 
 | 94 | { | 
| Brad Bishop | bf5aa9c | 2016-10-19 21:19:04 -0400 | [diff] [blame] | 95 | namespace property_condition | 
 | 96 | { | 
 | 97 |  | 
| Brad Bishop | 143522e | 2017-01-19 09:12:54 -0500 | [diff] [blame] | 98 | /** @struct PropertyChangedCondition | 
| Brad Bishop | bf5aa9c | 2016-10-19 21:19:04 -0400 | [diff] [blame] | 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> | 
| Brad Bishop | 143522e | 2017-01-19 09:12:54 -0500 | [diff] [blame] | 105 | struct PropertyChangedCondition | 
| Brad Bishop | bf5aa9c | 2016-10-19 21:19:04 -0400 | [diff] [blame] | 106 | { | 
| Brad Bishop | 143522e | 2017-01-19 09:12:54 -0500 | [diff] [blame] | 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) : | 
| Brad Bishop | 7b33777 | 2017-01-12 16:11:24 -0500 | [diff] [blame] | 115 |             _iface(iface), | 
 | 116 |             _property(property), | 
 | 117 |             _condition(std::forward<U>(condition)) { } | 
| Brad Bishop | bf5aa9c | 2016-10-19 21:19:04 -0400 | [diff] [blame] | 118 |  | 
| Brad Bishop | 7b33777 | 2017-01-12 16:11:24 -0500 | [diff] [blame] | 119 |         /** @brief Test a property value. | 
 | 120 |          * | 
 | 121 |          * Extract the property from the PropertiesChanged | 
 | 122 |          * message and run the condition test. | 
 | 123 |          */ | 
| Brad Bishop | 2371900 | 2017-01-24 21:08:46 -0500 | [diff] [blame] | 124 |         bool operator()( | 
 | 125 |             sdbusplus::bus::bus&, | 
 | 126 |             sdbusplus::message::message& msg, | 
 | 127 |             Manager&) const | 
| Brad Bishop | 7b33777 | 2017-01-12 16:11:24 -0500 | [diff] [blame] | 128 |         { | 
 | 129 |             std::map < | 
| Brad Bishop | bf5aa9c | 2016-10-19 21:19:04 -0400 | [diff] [blame] | 130 |             std::string, | 
| Brad Bishop | 7b33777 | 2017-01-12 16:11:24 -0500 | [diff] [blame] | 131 |                 sdbusplus::message::variant<T >> properties; | 
 | 132 |             const char* iface = nullptr; | 
| Brad Bishop | bf5aa9c | 2016-10-19 21:19:04 -0400 | [diff] [blame] | 133 |  | 
| Brad Bishop | 7b33777 | 2017-01-12 16:11:24 -0500 | [diff] [blame] | 134 |             msg.read(iface); | 
| Brad Bishop | 064c94a | 2017-01-21 21:33:30 -0500 | [diff] [blame] | 135 |             if (!iface || strcmp(iface, _iface)) | 
| Brad Bishop | 7b33777 | 2017-01-12 16:11:24 -0500 | [diff] [blame] | 136 |             { | 
| Brad Bishop | bf5aa9c | 2016-10-19 21:19:04 -0400 | [diff] [blame] | 137 |                 return false; | 
| Brad Bishop | 7b33777 | 2017-01-12 16:11:24 -0500 | [diff] [blame] | 138 |             } | 
| Brad Bishop | bf5aa9c | 2016-10-19 21:19:04 -0400 | [diff] [blame] | 139 |  | 
| Brad Bishop | 7b33777 | 2017-01-12 16:11:24 -0500 | [diff] [blame] | 140 |             msg.read(properties); | 
 | 141 |             auto it = properties.find(_property); | 
 | 142 |             if (it == properties.cend()) | 
 | 143 |             { | 
 | 144 |                 return false; | 
 | 145 |             } | 
| Brad Bishop | bf5aa9c | 2016-10-19 21:19:04 -0400 | [diff] [blame] | 146 |  | 
| Brad Bishop | fb083c2 | 2017-01-19 09:22:04 -0500 | [diff] [blame] | 147 |             return _condition( | 
 | 148 |                        std::forward<T>(it->second.template get<T>())); | 
| Brad Bishop | 7b33777 | 2017-01-12 16:11:24 -0500 | [diff] [blame] | 149 |         } | 
| Brad Bishop | bf5aa9c | 2016-10-19 21:19:04 -0400 | [diff] [blame] | 150 |  | 
 | 151 |     private: | 
| Brad Bishop | 7b33777 | 2017-01-12 16:11:24 -0500 | [diff] [blame] | 152 |         const char* _iface; | 
 | 153 |         const char* _property; | 
 | 154 |         U _condition; | 
| Brad Bishop | bf5aa9c | 2016-10-19 21:19:04 -0400 | [diff] [blame] | 155 | }; | 
 | 156 |  | 
| Brad Bishop | fa51da7 | 2017-01-19 11:06:51 -0500 | [diff] [blame] | 157 | /** @struct PropertyConditionBase | 
 | 158 |  *  @brief Match filter functor that tests a property value. | 
 | 159 |  * | 
 | 160 |  *  Base class for PropertyCondition - factored out code that | 
 | 161 |  *  doesn't need to be templated. | 
 | 162 |  */ | 
 | 163 | struct PropertyConditionBase | 
 | 164 | { | 
 | 165 |         PropertyConditionBase() = delete; | 
 | 166 |         virtual ~PropertyConditionBase() = default; | 
 | 167 |         PropertyConditionBase(const PropertyConditionBase&) = delete; | 
 | 168 |         PropertyConditionBase& operator=(const PropertyConditionBase&) = delete; | 
 | 169 |         PropertyConditionBase(PropertyConditionBase&&) = default; | 
 | 170 |         PropertyConditionBase& operator=(PropertyConditionBase&&) = default; | 
 | 171 |  | 
 | 172 |         /** @brief Constructor | 
 | 173 |          * | 
 | 174 |          *  The service argument can be nullptr.  If something | 
 | 175 |          *  else is provided the function will call the the | 
 | 176 |          *  service directly.  If omitted, the function will | 
 | 177 |          *  look up the service in the ObjectMapper. | 
 | 178 |          * | 
 | 179 |          *  @param path - The path of the object containing | 
 | 180 |          *     the property to be tested. | 
 | 181 |          *  @param iface - The interface hosting the property | 
 | 182 |          *     to be tested. | 
 | 183 |          *  @param property - The property to be tested. | 
 | 184 |          *  @param service - The DBus service hosting the object. | 
 | 185 |          */ | 
 | 186 |         PropertyConditionBase( | 
 | 187 |             const char* path, | 
 | 188 |             const char* iface, | 
 | 189 |             const char* property, | 
 | 190 |             const char* service) : | 
 | 191 |             _path(path), | 
 | 192 |             _iface(iface), | 
 | 193 |             _property(property), | 
 | 194 |             _service(service) {} | 
 | 195 |  | 
 | 196 |         /** @brief Forward comparison to type specific implementation. */ | 
 | 197 |         virtual bool eval(sdbusplus::message::message&) const = 0; | 
 | 198 |  | 
 | 199 |         /** @brief Test a property value. | 
 | 200 |          * | 
 | 201 |          * Make a DBus call and test the value of any property. | 
 | 202 |          */ | 
 | 203 |         bool operator()( | 
 | 204 |             sdbusplus::bus::bus&, | 
 | 205 |             sdbusplus::message::message&, | 
 | 206 |             Manager&) const; | 
 | 207 |  | 
 | 208 |     private: | 
 | 209 |         std::string _path; | 
 | 210 |         std::string _iface; | 
 | 211 |         std::string _property; | 
 | 212 |         const char* _service; | 
 | 213 | }; | 
 | 214 |  | 
 | 215 | /** @struct PropertyCondition | 
 | 216 |  *  @brief Match filter functor that tests a property value. | 
 | 217 |  * | 
 | 218 |  *  @tparam T - The type of the property being tested. | 
 | 219 |  *  @tparam U - The type of the condition checking functor. | 
 | 220 |  */ | 
 | 221 | template <typename T, typename U> | 
 | 222 | struct PropertyCondition final : public PropertyConditionBase | 
 | 223 | { | 
 | 224 |         PropertyCondition() = delete; | 
 | 225 |         ~PropertyCondition() = default; | 
 | 226 |         PropertyCondition(const PropertyCondition&) = delete; | 
 | 227 |         PropertyCondition& operator=(const PropertyCondition&) = delete; | 
 | 228 |         PropertyCondition(PropertyCondition&&) = default; | 
 | 229 |         PropertyCondition& operator=(PropertyCondition&&) = default; | 
 | 230 |  | 
 | 231 |         /** @brief Constructor | 
 | 232 |          * | 
 | 233 |          *  The service argument can be nullptr.  If something | 
 | 234 |          *  else is provided the function will call the the | 
 | 235 |          *  service directly.  If omitted, the function will | 
 | 236 |          *  look up the service in the ObjectMapper. | 
 | 237 |          * | 
 | 238 |          *  @param path - The path of the object containing | 
 | 239 |          *     the property to be tested. | 
 | 240 |          *  @param iface - The interface hosting the property | 
 | 241 |          *     to be tested. | 
 | 242 |          *  @param property - The property to be tested. | 
 | 243 |          *  @param condition - The test to run on the property. | 
 | 244 |          *  @param service - The DBus service hosting the object. | 
 | 245 |          */ | 
 | 246 |         PropertyCondition( | 
 | 247 |             const char* path, | 
 | 248 |             const char* iface, | 
 | 249 |             const char* property, | 
 | 250 |             U&& condition, | 
 | 251 |             const char* service) : | 
 | 252 |             PropertyConditionBase(path, iface, property, service), | 
 | 253 |             _condition(std::forward<decltype(condition)>(condition)) {} | 
 | 254 |  | 
 | 255 |         /** @brief Test a property value. | 
 | 256 |          * | 
 | 257 |          * Make a DBus call and test the value of any property. | 
 | 258 |          */ | 
 | 259 |         bool eval(sdbusplus::message::message& msg) const override | 
 | 260 |         { | 
 | 261 |             sdbusplus::message::variant<T> value; | 
 | 262 |             msg.read(value); | 
 | 263 |             return _condition( | 
 | 264 |                        std::forward<T>(value.template get<T>())); | 
 | 265 |         } | 
 | 266 |  | 
 | 267 |     private: | 
 | 268 |         U _condition; | 
 | 269 | }; | 
 | 270 |  | 
| Brad Bishop | bf5aa9c | 2016-10-19 21:19:04 -0400 | [diff] [blame] | 271 | } // namespace property_condition | 
| Brad Bishop | 3d57f50 | 2016-10-19 12:18:41 -0400 | [diff] [blame] | 272 | } // namespace details | 
 | 273 |  | 
| Brad Bishop | 143522e | 2017-01-19 09:12:54 -0500 | [diff] [blame] | 274 | /** @brief Implicit type deduction for constructing PropertyChangedCondition.  */ | 
| Brad Bishop | bf5aa9c | 2016-10-19 21:19:04 -0400 | [diff] [blame] | 275 | template <typename T> | 
 | 276 | auto propertyChangedTo( | 
| Brad Bishop | 7b33777 | 2017-01-12 16:11:24 -0500 | [diff] [blame] | 277 |     const char* iface, | 
 | 278 |     const char* property, | 
| Brad Bishop | fb083c2 | 2017-01-19 09:22:04 -0500 | [diff] [blame] | 279 |     T&& val) | 
| Brad Bishop | bf5aa9c | 2016-10-19 21:19:04 -0400 | [diff] [blame] | 280 | { | 
| Brad Bishop | 76e2f6a | 2017-01-31 14:05:22 -0500 | [diff] [blame^] | 281 |     auto condition = [val = std::forward<T>(val)](T && arg) | 
| Brad Bishop | d1bbf3a | 2016-12-01 00:03:26 -0500 | [diff] [blame] | 282 |     { | 
 | 283 |         return arg == val; | 
 | 284 |     }; | 
| Brad Bishop | bf5aa9c | 2016-10-19 21:19:04 -0400 | [diff] [blame] | 285 |     using U = decltype(condition); | 
| Brad Bishop | 143522e | 2017-01-19 09:12:54 -0500 | [diff] [blame] | 286 |     return details::property_condition::PropertyChangedCondition<T, U>( | 
| Brad Bishop | 7b33777 | 2017-01-12 16:11:24 -0500 | [diff] [blame] | 287 |                iface, property, std::move(condition)); | 
| Brad Bishop | bf5aa9c | 2016-10-19 21:19:04 -0400 | [diff] [blame] | 288 | } | 
 | 289 |  | 
| Brad Bishop | fa51da7 | 2017-01-19 11:06:51 -0500 | [diff] [blame] | 290 | /** @brief Implicit type deduction for constructing PropertyCondition.  */ | 
 | 291 | template <typename T> | 
 | 292 | auto propertyIs( | 
 | 293 |     const char* path, | 
 | 294 |     const char* iface, | 
 | 295 |     const char* property, | 
 | 296 |     T&& val, | 
 | 297 |     const char* service = nullptr) | 
 | 298 | { | 
 | 299 |     auto condition = [val = std::forward<T>(val)](T && arg) | 
 | 300 |     { | 
 | 301 |         return arg == val; | 
 | 302 |     }; | 
 | 303 |     using U = decltype(condition); | 
 | 304 |     return details::property_condition::PropertyCondition<T, U>( | 
 | 305 |                path, iface, property, std::move(condition), service); | 
 | 306 | } | 
 | 307 |  | 
| Brad Bishop | 3d57f50 | 2016-10-19 12:18:41 -0400 | [diff] [blame] | 308 | } // namespace filters | 
 | 309 | } // namespace manager | 
 | 310 | } // namespace inventory | 
 | 311 | } // namespace phosphor | 
 | 312 |  | 
 | 313 | // vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 |