Store and access zone object properties
Properties on the zone object require their event data to be stored for
retrieval when their value changes, which allows the use of the current
event handlers to update the cached value and trigger the event actions.
When any event is initialized, any signals where the match string is
empty performs a lookup for each group member to determine if they are
on the zone object. Each member found to be on the zone object is then
stored with the that event's data.
Tested:
Verified event data is stored for members on the zone object
Verified event initialization correctly accesses zone object
member's event data
Change-Id: Id34f60eb12330428eeb1041de4e9bd1a4a686f21
Signed-off-by: Matthew Barth <msbarth@us.ibm.com>
diff --git a/control/functor.hpp b/control/functor.hpp
index b96f650..71607c5 100644
--- a/control/functor.hpp
+++ b/control/functor.hpp
@@ -106,12 +106,7 @@
{
try
{
- auto service = zone.getService(_path, _iface);
- auto val = util::SDBusPlus::getProperty<T>(bus,
- service,
- _path,
- _iface,
- _property);
+ auto val = zone.getPropertyByName<T>(_path, _iface, _property);
_handler(zone, std::forward<T>(val));
}
catch (const sdbusplus::exception::SdBusError&)
diff --git a/control/zone.cpp b/control/zone.cpp
index bc40b7e..60d2947 100644
--- a/control/zone.cpp
+++ b/control/zone.cpp
@@ -51,6 +51,7 @@
ThermalObject(bus, path.c_str(), true),
_bus(bus),
_path(path),
+ _ifaces({"xyz.openbmc_project.Control.ThermalMode"}),
_fullSpeed(std::get<fullSpeedPos>(def)),
_zoneNum(std::get<zoneNumPos>(def)),
_defFloorSpeed(std::get<floorSpeedPos>(def)),
@@ -316,8 +317,6 @@
for (auto& sig : std::get<signalsPos>(event))
{
- // Initialize the event signal using handler
- std::get<sigHandlerPos>(sig)(_bus, nullMsg, *this);
// Setup signal matches of the property for event
std::unique_ptr<EventData> eventData =
std::make_unique<EventData>(
@@ -326,6 +325,37 @@
std::get<sigHandlerPos>(sig),
std::get<actionsPos>(event)
);
+
+ // When match is empty, handle if zone object member
+ if (std::get<sigMatchPos>(sig).empty())
+ {
+ fs::path path{CONTROL_OBJPATH};
+ path /= std::to_string(_zoneNum);
+
+ // Set event data for each host group member
+ for (auto it = std::get<groupPos>(event).begin();
+ it != std::get<groupPos>(event).end(); ++it)
+ {
+ if (it->first == path.string())
+ {
+ // Group member interface in list owned by zone
+ if (std::find(_ifaces.begin(), _ifaces.end(),
+ std::get<intfPos>(it->second)) != _ifaces.end())
+ {
+ // Store path,interface,property as a managed object
+ _objects[it->first]
+ [std::get<intfPos>(it->second)]
+ [std::get<propPos>(it->second)] =
+ eventData.get();
+ }
+ }
+ }
+ }
+
+ // Initialize the event signal using handler
+ std::get<sigHandlerPos>(sig)(_bus, nullMsg, *this);
+
+ // Subscribe to signal match
std::unique_ptr<sdbusplus::server::match::match> match = nullptr;
if (!std::get<sigMatchPos>(sig).empty())
{
@@ -338,6 +368,7 @@
eventData.get())
);
}
+
_signalEvents.emplace_back(std::move(eventData), std::move(match));
}
// Attach a timer to run the action of an event
diff --git a/control/zone.hpp b/control/zone.hpp
index 73761d0..2633902 100644
--- a/control/zone.hpp
+++ b/control/zone.hpp
@@ -7,6 +7,7 @@
#include <vector>
#include "fan.hpp"
#include "types.hpp"
+#include "sdbusplus.hpp"
#include "xyz/openbmc_project/Control/ThermalMode/server.hpp"
namespace phosphor
@@ -469,6 +470,57 @@
int32_t depth);
/**
+ * @brief Get a property value from the zone object or the bus when
+ * the property requested is not on the zone object
+ *
+ * @param[in] path - Path of object
+ * @param[in] intf - Object interface
+ * @param[in] prop - Object property
+ *
+ * @return - Property's value
+ */
+ template <typename T>
+ auto getPropertyByName(const std::string& path,
+ const std::string& intf,
+ const std::string& prop)
+ {
+ T value;
+ auto pathIter = _objects.find(path);
+ if (pathIter != _objects.end())
+ {
+ auto intfIter = pathIter->second.find(intf);
+ if (intfIter != pathIter->second.end())
+ {
+ if (intf == "xyz.openbmc_project.Control.ThermalMode")
+ {
+ auto var = ThermalMode::getPropertyByName(prop);
+ // Use visitor to determine if requested property
+ // type(T) is available on this interface and read it
+ std::visit([&value](auto&& val)
+ {
+ using V = std::decay_t<decltype(val)>;
+ if constexpr(std::is_same_v<T, V>)
+ {
+ value = val;
+ }
+ }, var);
+
+ return value;
+ }
+ }
+ }
+
+ auto service = getService(path, intf);
+ value = util::SDBusPlus::getProperty<T>(_bus,
+ service,
+ path,
+ intf,
+ prop);
+
+ return value;
+ };
+
+ /**
* @brief Overridden thermal object's set 'Current' property function
*
* @param[in] value - Value to set 'Current' to
@@ -490,6 +542,11 @@
const std::string _path;
/**
+ * Zone supported interfaces
+ */
+ const std::vector<std::string> _ifaces;
+
+ /**
* Full speed for the zone
*/
const uint64_t _fullSpeed;
@@ -588,6 +645,14 @@
PropertyVariantType>>> _properties;
/**
+ * @brief Map of zone objects
+ */
+ std::map<std::string,
+ std::map<std::string,
+ std::map<std::string,
+ EventData*>>> _objects;
+
+ /**
* @brief Map of active fan control allowed by groups
*/
std::map<const Group, bool> _active;