| #pragma once |
| |
| #include "sdbusplus.hpp" |
| #include "types.hpp" |
| #include "zone.hpp" |
| |
| #include <phosphor-logging/log.hpp> |
| |
| namespace phosphor |
| { |
| namespace fan |
| { |
| namespace control |
| { |
| class Zone; |
| |
| using namespace phosphor::fan; |
| using namespace sdbusplus::bus::match; |
| using namespace phosphor::logging; |
| |
| /** |
| * @brief Create a zone handler function object |
| * |
| * @param[in] handler - The handler being created |
| * |
| * @return - The created zone handler function object |
| */ |
| template <typename T> |
| auto make_zoneHandler(T&& handler) |
| { |
| return ZoneHandler(std::forward<T>(handler)); |
| } |
| |
| /** |
| * @brief Create a trigger function object |
| * |
| * @param[in] trigger - The trigger being created |
| * |
| * @return - The created trigger function object |
| */ |
| template <typename T> |
| auto make_trigger(T&& trigger) |
| { |
| return Trigger(std::forward<T>(trigger)); |
| } |
| |
| /** |
| * @brief Create a handler function object |
| * |
| * @param[in] handler - The handler being created |
| * |
| * @return - The created handler function object |
| */ |
| template <typename T, typename U> |
| auto make_handler(U&& handler) |
| { |
| return T(std::forward<U>(handler)); |
| } |
| |
| /** |
| * @brief Create an action function object |
| * |
| * @param[in] action - The action being created |
| * |
| * @return - The created action function object |
| */ |
| template <typename T> |
| auto make_action(T&& action) |
| { |
| return Action(std::forward<T>(action)); |
| } |
| |
| /** |
| * @struct Properties |
| * @brief A set of match filter functors for Dbus property values. Each |
| * functor provides an associated process for retrieving the value |
| * for a given property and providing it to the given handler function. |
| * |
| * @tparam T - The type of the property value |
| * @tparam U - The type of the handler |
| */ |
| template <typename T, typename U> |
| struct Properties |
| { |
| Properties() = delete; |
| ~Properties() = default; |
| Properties(const Properties&) = default; |
| Properties& operator=(const Properties&) = default; |
| Properties(Properties&&) = default; |
| Properties& operator=(Properties&&) = default; |
| explicit Properties(U&& handler) : |
| _path(""), _intf(""), _prop(""), _handler(std::forward<U>(handler)) |
| {} |
| Properties(const char* path, const char* intf, const char* prop, |
| U&& handler) : |
| _path(path), _intf(intf), _prop(prop), |
| _handler(std::forward<U>(handler)) |
| {} |
| |
| /** @brief Run signal handler function |
| * |
| * Extract the property from the PropertiesChanged |
| * message and run the handler function. |
| */ |
| void operator()(sdbusplus::bus_t&, sdbusplus::message_t& msg, |
| Zone& zone) const |
| { |
| if (msg) |
| { |
| std::string intf; |
| msg.read(intf); |
| if (intf != _intf) |
| { |
| // Interface name does not match on object |
| return; |
| } |
| |
| std::map<std::string, PropertyVariantType> props; |
| msg.read(props); |
| auto it = props.find(_prop); |
| if (it == props.cend()) |
| { |
| // Property not included in dictionary of properties changed |
| return; |
| } |
| |
| // Retrieve the property's value applying any visitors necessary |
| auto value = |
| zone.getPropertyValueVisitor<T>(_intf, _prop, it->second); |
| |
| _handler(zone, _path, _intf, _prop, std::forward<T>(value)); |
| } |
| else |
| { |
| try |
| { |
| auto val = zone.getPropertyByName<T>(_path, _intf, _prop); |
| _handler(zone, _path, _intf, _prop, std::forward<T>(val)); |
| } |
| catch (const sdbusplus::exception_t&) |
| { |
| // Property will not be used unless a property changed |
| // signal message is received for this property. |
| } |
| catch (const util::DBusError&) |
| { |
| // Property will not be used unless a property changed |
| // signal message is received for this property. |
| } |
| } |
| } |
| |
| /** @brief Run init handler function |
| * |
| * Get the property from each member object of the group |
| * and run the handler function. |
| */ |
| void operator()(Zone& zone, const Group& group) const |
| { |
| std::for_each( |
| group.begin(), group.end(), |
| [&zone, handler = std::move(_handler)](const auto& member) { |
| auto path = std::get<pathPos>(member); |
| auto intf = std::get<intfPos>(member); |
| auto prop = std::get<propPos>(member); |
| try |
| { |
| auto val = zone.getPropertyByName<T>(path, intf, prop); |
| handler(zone, path, intf, prop, std::forward<T>(val)); |
| } |
| catch (const sdbusplus::exception_t&) |
| { |
| // Property value not sent to handler |
| } |
| catch (const util::DBusError&) |
| { |
| // Property value not sent to handler |
| } |
| }); |
| } |
| |
| private: |
| const char* _path; |
| const char* _intf; |
| const char* _prop; |
| U _handler; |
| }; |
| |
| /** |
| * @brief Used to process a Dbus properties changed signal event |
| * |
| * @param[in] path - Object path |
| * @param[in] intf - Object interface |
| * @param[in] prop - Object property |
| * @param[in] handler - Handler function to perform |
| * |
| * @tparam T - The type of the property |
| * @tparam U - The type of the handler |
| */ |
| template <typename T, typename U> |
| auto propertiesChanged(const char* path, const char* intf, const char* prop, |
| U&& handler) |
| { |
| return Properties<T, U>(path, intf, prop, std::forward<U>(handler)); |
| } |
| |
| /** |
| * @brief Used to get the properties of an event's group |
| * |
| * @param[in] handler - Handler function to perform |
| * |
| * @tparam T - The type of all the properties |
| * @tparam U - The type of the handler |
| */ |
| template <typename T, typename U> |
| auto getProperties(U&& handler) |
| { |
| return Properties<T, U>(std::forward<U>(handler)); |
| } |
| |
| /** |
| * @struct Interfaces Added |
| * @brief A match filter functor for Dbus interfaces added signals |
| * |
| * @tparam T - The type of the property value |
| * @tparam U - The type of the handler |
| */ |
| template <typename T, typename U> |
| struct InterfacesAdded |
| { |
| InterfacesAdded() = delete; |
| ~InterfacesAdded() = default; |
| InterfacesAdded(const InterfacesAdded&) = default; |
| InterfacesAdded& operator=(const InterfacesAdded&) = default; |
| InterfacesAdded(InterfacesAdded&&) = default; |
| InterfacesAdded& operator=(InterfacesAdded&&) = default; |
| InterfacesAdded(const char* path, const char* intf, const char* prop, |
| U&& handler) : |
| _path(path), _intf(intf), _prop(prop), |
| _handler(std::forward<U>(handler)) |
| {} |
| |
| /** @brief Run signal handler function |
| * |
| * Extract the property from the InterfacesAdded |
| * message and run the handler function. |
| */ |
| void operator()(sdbusplus::bus_t&, sdbusplus::message_t& msg, |
| Zone& zone) const |
| { |
| if (msg) |
| { |
| sdbusplus::message::object_path op; |
| |
| msg.read(op); |
| if (static_cast<const std::string&>(op) != _path) |
| { |
| // Object path does not match this handler's path |
| return; |
| } |
| |
| std::map<std::string, std::map<std::string, PropertyVariantType>> |
| intfProp; |
| msg.read(intfProp); |
| auto itIntf = intfProp.find(_intf); |
| if (itIntf == intfProp.cend()) |
| { |
| // Interface not found on this handler's path |
| return; |
| } |
| auto itProp = itIntf->second.find(_prop); |
| if (itProp == itIntf->second.cend()) |
| { |
| // Property not found on this handler's path |
| return; |
| } |
| |
| // Retrieve the property's value applying any visitors necessary |
| auto value = |
| zone.getPropertyValueVisitor<T>(_intf, _prop, itProp->second); |
| |
| _handler(zone, _path, _intf, _prop, std::forward<T>(value)); |
| } |
| } |
| |
| private: |
| const char* _path; |
| const char* _intf; |
| const char* _prop; |
| U _handler; |
| }; |
| |
| /** |
| * @brief Used to process a Dbus interfaces added signal event |
| * |
| * @param[in] path - Object path |
| * @param[in] intf - Object interface |
| * @param[in] prop - Object property |
| * @param[in] handler - Handler function to perform |
| * |
| * @tparam T - The type of the property |
| * @tparam U - The type of the handler |
| */ |
| template <typename T, typename U> |
| auto interfacesAdded(const char* path, const char* intf, const char* prop, |
| U&& handler) |
| { |
| return InterfacesAdded<T, U>(path, intf, prop, std::forward<U>(handler)); |
| } |
| |
| /** |
| * @struct Interfaces Removed |
| * @brief A match filter functor for Dbus interfaces removed signals |
| * |
| * @tparam U - The type of the handler |
| */ |
| template <typename U> |
| struct InterfacesRemoved |
| { |
| InterfacesRemoved() = delete; |
| ~InterfacesRemoved() = default; |
| InterfacesRemoved(const InterfacesRemoved&) = default; |
| InterfacesRemoved& operator=(const InterfacesRemoved&) = default; |
| InterfacesRemoved(InterfacesRemoved&&) = default; |
| InterfacesRemoved& operator=(InterfacesRemoved&&) = default; |
| InterfacesRemoved(const char* path, const char* intf, U&& handler) : |
| _path(path), _intf(intf), _handler(std::forward<U>(handler)) |
| {} |
| |
| /** @brief Run signal handler function |
| * |
| * Extract the interfaces from the InterfacesRemoved |
| * message and run the handler function. |
| */ |
| void operator()(sdbusplus::bus_t&, sdbusplus::message_t& msg, |
| Zone& zone) const |
| { |
| if (msg) |
| { |
| std::vector<std::string> intfs; |
| sdbusplus::message::object_path op; |
| |
| msg.read(op); |
| if (static_cast<const std::string&>(op) != _path) |
| { |
| // Object path does not match this handler's path |
| return; |
| } |
| |
| msg.read(intfs); |
| auto itIntf = std::find(intfs.begin(), intfs.end(), _intf); |
| if (itIntf == intfs.cend()) |
| { |
| // Interface not found on this handler's path |
| return; |
| } |
| |
| _handler(zone); |
| } |
| } |
| |
| private: |
| const char* _path; |
| const char* _intf; |
| U _handler; |
| }; |
| |
| /** |
| * @brief Used to process a Dbus interfaces removed signal event |
| * |
| * @param[in] path - Object path |
| * @param[in] intf - Object interface |
| * @param[in] handler - Handler function to perform |
| * |
| * @tparam U - The type of the handler |
| */ |
| template <typename U> |
| auto interfacesRemoved(const char* path, const char* intf, U&& handler) |
| { |
| return InterfacesRemoved<U>(path, intf, std::forward<U>(handler)); |
| } |
| |
| /** |
| * @struct Name Owner |
| * @brief A functor for Dbus name owner signals and methods |
| * |
| * @tparam U - The type of the handler |
| */ |
| template <typename U> |
| struct NameOwner |
| { |
| NameOwner() = delete; |
| ~NameOwner() = default; |
| NameOwner(const NameOwner&) = default; |
| NameOwner& operator=(const NameOwner&) = default; |
| NameOwner(NameOwner&&) = default; |
| NameOwner& operator=(NameOwner&&) = default; |
| explicit NameOwner(U&& handler) : _handler(std::forward<U>(handler)) {} |
| |
| /** @brief Run signal handler function |
| * |
| * Extract the name owner from the NameOwnerChanged |
| * message and run the handler function. |
| */ |
| void operator()(sdbusplus::bus_t&, sdbusplus::message_t& msg, |
| Zone& zone) const |
| { |
| if (msg) |
| { |
| std::string name; |
| bool hasOwner = false; |
| |
| // Handle NameOwnerChanged signals |
| msg.read(name); |
| |
| std::string oldOwn; |
| msg.read(oldOwn); |
| |
| std::string newOwn; |
| msg.read(newOwn); |
| if (!newOwn.empty()) |
| { |
| hasOwner = true; |
| } |
| _handler(zone, name, hasOwner); |
| } |
| } |
| |
| void operator()(Zone& zone, const Group& group) const |
| { |
| std::string name = ""; |
| bool hasOwner = false; |
| std::for_each( |
| group.begin(), group.end(), |
| [&zone, &group, &name, &hasOwner, |
| handler = std::move(_handler)](const auto& member) { |
| auto path = std::get<pathPos>(member); |
| auto intf = std::get<intfPos>(member); |
| try |
| { |
| auto servName = zone.getService(path, intf); |
| if (name != servName) |
| { |
| name = servName; |
| hasOwner = util::SDBusPlus::callMethodAndRead<bool>( |
| zone.getBus(), "org.freedesktop.DBus", |
| "/org/freedesktop/DBus", "org.freedesktop.DBus", |
| "NameHasOwner", name); |
| // Update service name owner state list of a group |
| handler(zone, name, hasOwner); |
| } |
| } |
| catch (const util::DBusMethodError& e) |
| { |
| // Failed to get service name owner state |
| name = ""; |
| hasOwner = false; |
| } |
| }); |
| } |
| |
| private: |
| U _handler; |
| }; |
| |
| /** |
| * @brief Used to process a Dbus name owner changed signal event |
| * |
| * @param[in] handler - Handler function to perform |
| * |
| * @tparam U - The type of the handler |
| * |
| * @return - The NameOwnerChanged signal struct |
| */ |
| template <typename U> |
| auto nameOwnerChanged(U&& handler) |
| { |
| return NameOwner<U>(std::forward<U>(handler)); |
| } |
| |
| /** |
| * @brief Used to process the init of a name owner event |
| * |
| * @param[in] handler - Handler function to perform |
| * |
| * @tparam U - The type of the handler |
| * |
| * @return - The NameOwnerChanged signal struct |
| */ |
| template <typename U> |
| auto nameHasOwner(U&& handler) |
| { |
| return NameOwner<U>(std::forward<U>(handler)); |
| } |
| |
| } // namespace control |
| } // namespace fan |
| } // namespace phosphor |