1 #pragma once 2 3 #include "sdbusplus.hpp" 4 #include "types.hpp" 5 6 #include <phosphor-logging/log.hpp> 7 8 namespace phosphor 9 { 10 namespace fan 11 { 12 namespace control 13 { 14 class Zone; 15 16 using namespace phosphor::fan; 17 using namespace sdbusplus::bus::match; 18 using namespace phosphor::logging; 19 20 /** 21 * @brief Create a zone handler function object 22 * 23 * @param[in] handler - The handler being created 24 * 25 * @return - The created zone handler function object 26 */ 27 template <typename T> 28 auto make_zoneHandler(T&& handler) 29 { 30 return ZoneHandler(std::forward<T>(handler)); 31 } 32 33 /** 34 * @brief Create a trigger function object 35 * 36 * @param[in] trigger - The trigger being created 37 * 38 * @return - The created trigger function object 39 */ 40 template <typename T> 41 auto make_trigger(T&& trigger) 42 { 43 return Trigger(std::forward<T>(trigger)); 44 } 45 46 /** 47 * @brief Create a handler function object 48 * 49 * @param[in] handler - The handler being created 50 * 51 * @return - The created handler function object 52 */ 53 template <typename T, typename U> 54 auto make_handler(U&& handler) 55 { 56 return T(std::forward<U>(handler)); 57 } 58 59 /** 60 * @brief Create an action function object 61 * 62 * @param[in] action - The action being created 63 * 64 * @return - The created action function object 65 */ 66 template <typename T> 67 auto make_action(T&& action) 68 { 69 return Action(std::forward<T>(action)); 70 } 71 72 /** 73 * @struct Properties 74 * @brief A set of match filter functors for Dbus property values. Each 75 * functor provides an associated process for retrieving the value 76 * for a given property and providing it to the given handler function. 77 * 78 * @tparam T - The type of the property value 79 * @tparam U - The type of the handler 80 */ 81 template <typename T, typename U> 82 struct Properties 83 { 84 Properties() = delete; 85 ~Properties() = default; 86 Properties(const Properties&) = default; 87 Properties& operator=(const Properties&) = default; 88 Properties(Properties&&) = default; 89 Properties& operator=(Properties&&) = default; 90 explicit Properties(U&& handler) : 91 _path(""), _intf(""), _prop(""), _handler(std::forward<U>(handler)) 92 {} 93 Properties(const char* path, const char* intf, const char* prop, 94 U&& handler) : 95 _path(path), 96 _intf(intf), _prop(prop), _handler(std::forward<U>(handler)) 97 {} 98 99 /** @brief Run signal handler function 100 * 101 * Extract the property from the PropertiesChanged 102 * message and run the handler function. 103 */ 104 void operator()(sdbusplus::bus::bus& bus, sdbusplus::message::message& msg, 105 Zone& zone) const 106 { 107 if (msg) 108 { 109 std::string intf; 110 msg.read(intf); 111 if (intf != _intf) 112 { 113 // Interface name does not match on object 114 return; 115 } 116 117 std::map<std::string, PropertyVariantType> props; 118 msg.read(props); 119 auto it = props.find(_prop); 120 if (it == props.cend()) 121 { 122 // Property not included in dictionary of properties changed 123 return; 124 } 125 126 // Retrieve the property's value applying any visitors necessary 127 auto value = 128 zone.getPropertyValueVisitor<T>(_intf, _prop, it->second); 129 130 _handler(zone, _path, _intf, _prop, std::forward<T>(value)); 131 } 132 else 133 { 134 try 135 { 136 auto val = zone.getPropertyByName<T>(_path, _intf, _prop); 137 _handler(zone, _path, _intf, _prop, std::forward<T>(val)); 138 } 139 catch (const sdbusplus::exception::SdBusError&) 140 { 141 // Property will not be used unless a property changed 142 // signal message is received for this property. 143 } 144 catch (const util::DBusError&) 145 { 146 // Property will not be used unless a property changed 147 // signal message is received for this property. 148 } 149 } 150 } 151 152 /** @brief Run init handler function 153 * 154 * Get the property from each member object of the group 155 * and run the handler function. 156 */ 157 void operator()(Zone& zone, const Group& group) const 158 { 159 std::for_each( 160 group.begin(), group.end(), 161 [&zone, handler = std::move(_handler)](auto const& member) { 162 auto path = std::get<pathPos>(member); 163 auto intf = std::get<intfPos>(member); 164 auto prop = std::get<propPos>(member); 165 try 166 { 167 auto val = zone.getPropertyByName<T>(path, intf, prop); 168 handler(zone, path, intf, prop, std::forward<T>(val)); 169 } 170 catch (const sdbusplus::exception::SdBusError&) 171 { 172 // Property value not sent to handler 173 } 174 catch (const util::DBusError&) 175 { 176 // Property value not sent to handler 177 } 178 }); 179 } 180 181 private: 182 const char* _path; 183 const char* _intf; 184 const char* _prop; 185 U _handler; 186 }; 187 188 /** 189 * @brief Used to process a Dbus properties changed signal event 190 * 191 * @param[in] path - Object path 192 * @param[in] intf - Object interface 193 * @param[in] prop - Object property 194 * @param[in] handler - Handler function to perform 195 * 196 * @tparam T - The type of the property 197 * @tparam U - The type of the handler 198 */ 199 template <typename T, typename U> 200 auto propertiesChanged(const char* path, const char* intf, const char* prop, 201 U&& handler) 202 { 203 return Properties<T, U>(path, intf, prop, std::forward<U>(handler)); 204 } 205 206 /** 207 * @brief Used to get the properties of an event's group 208 * 209 * @param[in] handler - Handler function to perform 210 * 211 * @tparam T - The type of all the properties 212 * @tparam U - The type of the handler 213 */ 214 template <typename T, typename U> 215 auto getProperties(U&& handler) 216 { 217 return Properties<T, U>(std::forward<U>(handler)); 218 } 219 220 /** 221 * @struct Interfaces Added 222 * @brief A match filter functor for Dbus interfaces added signals 223 * 224 * @tparam T - The type of the property value 225 * @tparam U - The type of the handler 226 */ 227 template <typename T, typename U> 228 struct InterfacesAdded 229 { 230 InterfacesAdded() = delete; 231 ~InterfacesAdded() = default; 232 InterfacesAdded(const InterfacesAdded&) = default; 233 InterfacesAdded& operator=(const InterfacesAdded&) = default; 234 InterfacesAdded(InterfacesAdded&&) = default; 235 InterfacesAdded& operator=(InterfacesAdded&&) = default; 236 InterfacesAdded(const char* path, const char* intf, const char* prop, 237 U&& handler) : 238 _path(path), 239 _intf(intf), _prop(prop), _handler(std::forward<U>(handler)) 240 {} 241 242 /** @brief Run signal handler function 243 * 244 * Extract the property from the InterfacesAdded 245 * message and run the handler function. 246 */ 247 void operator()(sdbusplus::bus::bus&, sdbusplus::message::message& msg, 248 Zone& zone) const 249 { 250 if (msg) 251 { 252 sdbusplus::message::object_path op; 253 254 msg.read(op); 255 if (static_cast<const std::string&>(op) != _path) 256 { 257 // Object path does not match this handler's path 258 return; 259 } 260 261 std::map<std::string, std::map<std::string, PropertyVariantType>> 262 intfProp; 263 msg.read(intfProp); 264 auto itIntf = intfProp.find(_intf); 265 if (itIntf == intfProp.cend()) 266 { 267 // Interface not found on this handler's path 268 return; 269 } 270 auto itProp = itIntf->second.find(_prop); 271 if (itProp == itIntf->second.cend()) 272 { 273 // Property not found on this handler's path 274 return; 275 } 276 277 // Retrieve the property's value applying any visitors necessary 278 auto value = 279 zone.getPropertyValueVisitor<T>(_intf, _prop, itProp->second); 280 281 _handler(zone, _path, _intf, _prop, std::forward<T>(value)); 282 } 283 } 284 285 private: 286 const char* _path; 287 const char* _intf; 288 const char* _prop; 289 U _handler; 290 }; 291 292 /** 293 * @brief Used to process a Dbus interfaces added signal event 294 * 295 * @param[in] path - Object path 296 * @param[in] intf - Object interface 297 * @param[in] prop - Object property 298 * @param[in] handler - Handler function to perform 299 * 300 * @tparam T - The type of the property 301 * @tparam U - The type of the handler 302 */ 303 template <typename T, typename U> 304 auto interfacesAdded(const char* path, const char* intf, const char* prop, 305 U&& handler) 306 { 307 return InterfacesAdded<T, U>(path, intf, prop, std::forward<U>(handler)); 308 } 309 310 /** 311 * @struct Interfaces Removed 312 * @brief A match filter functor for Dbus interfaces removed signals 313 * 314 * @tparam U - The type of the handler 315 */ 316 template <typename U> 317 struct InterfacesRemoved 318 { 319 InterfacesRemoved() = delete; 320 ~InterfacesRemoved() = default; 321 InterfacesRemoved(const InterfacesRemoved&) = default; 322 InterfacesRemoved& operator=(const InterfacesRemoved&) = default; 323 InterfacesRemoved(InterfacesRemoved&&) = default; 324 InterfacesRemoved& operator=(InterfacesRemoved&&) = default; 325 InterfacesRemoved(const char* path, const char* intf, U&& handler) : 326 _path(path), _intf(intf), _handler(std::forward<U>(handler)) 327 {} 328 329 /** @brief Run signal handler function 330 * 331 * Extract the interfaces from the InterfacesRemoved 332 * message and run the handler function. 333 */ 334 void operator()(sdbusplus::bus::bus&, sdbusplus::message::message& msg, 335 Zone& zone) const 336 { 337 if (msg) 338 { 339 std::vector<std::string> intfs; 340 sdbusplus::message::object_path op; 341 342 msg.read(op); 343 if (static_cast<const std::string&>(op) != _path) 344 { 345 // Object path does not match this handler's path 346 return; 347 } 348 349 msg.read(intfs); 350 auto itIntf = std::find(intfs.begin(), intfs.end(), _intf); 351 if (itIntf == intfs.cend()) 352 { 353 // Interface not found on this handler's path 354 return; 355 } 356 357 _handler(zone); 358 } 359 } 360 361 private: 362 const char* _path; 363 const char* _intf; 364 U _handler; 365 }; 366 367 /** 368 * @brief Used to process a Dbus interfaces removed signal event 369 * 370 * @param[in] path - Object path 371 * @param[in] intf - Object interface 372 * @param[in] handler - Handler function to perform 373 * 374 * @tparam U - The type of the handler 375 */ 376 template <typename U> 377 auto interfacesRemoved(const char* path, const char* intf, U&& handler) 378 { 379 return InterfacesRemoved<U>(path, intf, std::forward<U>(handler)); 380 } 381 382 /** 383 * @struct Name Owner 384 * @brief A functor for Dbus name owner signals and methods 385 * 386 * @tparam U - The type of the handler 387 */ 388 template <typename U> 389 struct NameOwner 390 { 391 NameOwner() = delete; 392 ~NameOwner() = default; 393 NameOwner(const NameOwner&) = default; 394 NameOwner& operator=(const NameOwner&) = default; 395 NameOwner(NameOwner&&) = default; 396 NameOwner& operator=(NameOwner&&) = default; 397 explicit NameOwner(U&& handler) : _handler(std::forward<U>(handler)) 398 {} 399 400 /** @brief Run signal handler function 401 * 402 * Extract the name owner from the NameOwnerChanged 403 * message and run the handler function. 404 */ 405 void operator()(sdbusplus::bus::bus& bus, sdbusplus::message::message& msg, 406 Zone& zone) const 407 { 408 if (msg) 409 { 410 std::string name; 411 bool hasOwner = false; 412 413 // Handle NameOwnerChanged signals 414 msg.read(name); 415 416 std::string oldOwn; 417 msg.read(oldOwn); 418 419 std::string newOwn; 420 msg.read(newOwn); 421 if (!newOwn.empty()) 422 { 423 hasOwner = true; 424 } 425 _handler(zone, name, hasOwner); 426 } 427 } 428 429 void operator()(Zone& zone, const Group& group) const 430 { 431 std::string name = ""; 432 bool hasOwner = false; 433 std::for_each( 434 group.begin(), group.end(), 435 [&zone, &group, &name, &hasOwner, 436 handler = std::move(_handler)](auto const& member) { 437 auto path = std::get<pathPos>(member); 438 auto intf = std::get<intfPos>(member); 439 try 440 { 441 auto servName = zone.getService(path, intf); 442 if (name != servName) 443 { 444 name = servName; 445 hasOwner = util::SDBusPlus::callMethodAndRead<bool>( 446 zone.getBus(), "org.freedesktop.DBus", 447 "/org/freedesktop/DBus", "org.freedesktop.DBus", 448 "NameHasOwner", name); 449 // Update service name owner state list of a group 450 handler(zone, name, hasOwner); 451 } 452 } 453 catch (const util::DBusMethodError& e) 454 { 455 // Failed to get service name owner state 456 name = ""; 457 hasOwner = false; 458 } 459 }); 460 } 461 462 private: 463 U _handler; 464 }; 465 466 /** 467 * @brief Used to process a Dbus name owner changed signal event 468 * 469 * @param[in] handler - Handler function to perform 470 * 471 * @tparam U - The type of the handler 472 * 473 * @return - The NameOwnerChanged signal struct 474 */ 475 template <typename U> 476 auto nameOwnerChanged(U&& handler) 477 { 478 return NameOwner<U>(std::forward<U>(handler)); 479 } 480 481 /** 482 * @brief Used to process the init of a name owner event 483 * 484 * @param[in] handler - Handler function to perform 485 * 486 * @tparam U - The type of the handler 487 * 488 * @return - The NameOwnerChanged signal struct 489 */ 490 template <typename U> 491 auto nameHasOwner(U&& handler) 492 { 493 return NameOwner<U>(std::forward<U>(handler)); 494 } 495 496 } // namespace control 497 } // namespace fan 498 } // namespace phosphor 499