Add support to handle InterfacesAdded signals
Set speed events can not subscribe to InterfaceAdded signals for
properties that are created after fan control initializes the event. Fan
control subscribes to property changed signals for all events upon
startup where any properties that do not exist are unable to be
subscribed to and be notified when their property changes. Therefore,
subscribing to the InterfacesAdded signals for properties as well allows
any property defined within a set speed event that may not exist upon
starting the fan control application get added or updated when the
interface it resides on is added.
When a subscribed InterfacesAdded signal is caught, the same setProperty
handler function will be used to add the property value for the object
path, interface, and property name defined to be subscribed to for
property change signals.
Change-Id: If6fe97288140b83e2e2d735fdf61d52de1ec2e88
Signed-off-by: Matthew Barth <msbarth@us.ibm.com>
diff --git a/control/functor.hpp b/control/functor.hpp
index 2b36445..a5044da 100644
--- a/control/functor.hpp
+++ b/control/functor.hpp
@@ -117,6 +117,100 @@
return PropertyChanged<T, U>(iface, property, std::forward<U>(handler));
}
+/**
+ * @struct Interface Added
+ * @brief A match filter functor for Dbus interface added signals
+ *
+ * @tparam T - The type of the property value
+ * @tparam U - The type of the handler
+ */
+template <typename T, typename U>
+struct InterfaceAdded
+{
+ InterfaceAdded() = delete;
+ ~InterfaceAdded() = default;
+ InterfaceAdded(const InterfaceAdded&) = default;
+ InterfaceAdded& operator=(const InterfaceAdded&) = default;
+ InterfaceAdded(InterfaceAdded&&) = default;
+ InterfaceAdded& operator=(InterfaceAdded&&) = default;
+ InterfaceAdded(const char* path,
+ const char* iface,
+ const char* property,
+ U&& handler) :
+ _path(path),
+ _iface(iface),
+ _property(property),
+ _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::bus&,
+ sdbusplus::message::message& msg,
+ Zone& zone) const
+ {
+ std::map<std::string,
+ std::map<std::string,
+ sdbusplus::message::variant<T>>> intfProp;
+ sdbusplus::message::object_path op;
+
+ msg.read(op);
+ auto objPath = static_cast<const std::string&>(op).c_str();
+ if (!objPath || strcmp(objPath, _path))
+ {
+ // Object path does not match this handler's path
+ return;
+ }
+
+ msg.read(intfProp);
+ auto itIntf = intfProp.find(_iface);
+ if (itIntf == intfProp.cend())
+ {
+ // Interface not found on this handler's path
+ return;
+ }
+ auto itProp = itIntf->second.find(_property);
+ if (itProp == itIntf->second.cend())
+ {
+ // Property not found on this handler's path
+ return;
+ }
+
+ _handler(zone, std::forward<T>(itProp->second.template get<T>()));
+ }
+
+private:
+ const char* _path;
+ const char* _iface;
+ const char* _property;
+ U _handler;
+};
+
+/**
+ * @brief Used to process a Dbus interface added signal event
+ *
+ * @param[in] path - Object path
+ * @param[in] iface - Object interface
+ * @param[in] property - 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 objectSignal(const char* path,
+ const char* iface,
+ const char* property,
+ U&& handler)
+{
+ return InterfaceAdded<T, U>(path,
+ iface,
+ property,
+ std::forward<U>(handler));
+}
+
} // namespace control
} // namespace fan
} // namespace phosphor