control: remove NaN from D-Bus properties
When sensors are offline, its possible for some driver parameters to
appear as NaN. These values are prevented from being stored in fan
control and are removed if they are detected in the cache.
Signed-off-by: Mike Capps <mikepcapps@gmail.com>
Change-Id: I22aa0c551faffdfc83eb1992b1242ac477d08180
diff --git a/control/json/manager.cpp b/control/json/manager.cpp
index 978fde4..5bfa07c 100644
--- a/control/json/manager.cpp
+++ b/control/json/manager.cpp
@@ -475,6 +475,21 @@
return paths;
}
+void Manager::insertFilteredObjects(ManagedObjects& ref)
+{
+ for (auto& [path, pathMap] : ref)
+ {
+ for (auto& [intf, intfMap] : pathMap)
+ {
+ // for each property on this path+interface
+ for (auto& [prop, value] : intfMap)
+ {
+ setProperty(path, intf, prop, value);
+ }
+ }
+ }
+}
+
void Manager::addObjects(const std::string& path, const std::string& intf,
const std::string& prop)
{
@@ -494,58 +509,22 @@
{
// No object manager interface provided by service?
// Attempt to retrieve property directly
- auto variant = util::SDBusPlus::getPropertyVariant<PropertyVariantType>(
+ auto value = util::SDBusPlus::getPropertyVariant<PropertyVariantType>(
_bus, service, path, intf, prop);
- _objects[path][intf][prop] = variant;
+
+ setProperty(path, intf, prop, value);
return;
}
for (const auto& objMgrPath : objMgrPaths)
{
// Get all managed objects of service
+ // want to filter here...
auto objects = util::SDBusPlus::getManagedObjects<PropertyVariantType>(
_bus, service, objMgrPath);
- // Add what's returned to the cache of objects
- for (auto& object : objects)
- {
- auto itPath = _objects.find(object.first);
- if (itPath != _objects.end())
- {
- // Path found in cache
- for (auto& interface : itPath->second)
- {
- auto itIntf = itPath->second.find(interface.first);
- if (itIntf != itPath->second.end())
- {
- // Interface found in cache
- for (auto& property : itIntf->second)
- {
- auto itProp = itIntf->second.find(property.first);
- if (itProp != itIntf->second.end())
- {
- // Property found, update value
- itProp->second = property.second;
- }
- else
- {
- itIntf->second.insert(property);
- }
- }
- }
- else
- {
- // Interface not found in cache
- itPath->second.insert(interface);
- }
- }
- }
- else
- {
- // Path not found in cache
- _objects.insert(object);
- }
- }
+ // insert all objects but remove any NaN values
+ insertFilteredObjects(objects);
}
}
@@ -572,6 +551,25 @@
return std::nullopt;
}
+void Manager::setProperty(const std::string& path, const std::string& intf,
+ const std::string& prop, PropertyVariantType value)
+{
+ // filter NaNs out of the cache
+ if (PropertyContainsNan(value))
+ {
+ // dont use operator [] if paths dont exist
+ if (_objects.find(path) != _objects.end() &&
+ _objects[path].find(intf) != _objects[path].end())
+ {
+ _objects[path][intf].erase(prop);
+ }
+ }
+ else
+ {
+ _objects[path][intf][prop] = std::move(value);
+ }
+}
+
void Manager::addTimer(const TimerType type,
const std::chrono::microseconds interval,
std::unique_ptr<TimerPkg> pkg)
diff --git a/control/json/manager.hpp b/control/json/manager.hpp
index 23dda2b..a11bc5e 100644
--- a/control/json/manager.hpp
+++ b/control/json/manager.hpp
@@ -114,6 +114,20 @@
std::unique_ptr<sdbusplus::bus::match_t>>;
/**
+ * Package of data from a D-Bus call to get managed objects
+ * Tuple constructed of:
+ * std::map<Path, // D-Bus Path
+ * std::map<Intf, // D-Bus Interface
+ * std::map<Property, // D-Bus Property
+ * std::variant>>> // Variant value of that property
+ */
+using Path_v = sdbusplus::message::object_path;
+using Intf_v = std::string;
+using Prop_v = std::string;
+using ManagedObjects =
+ std::map<Path_v, std::map<Intf_v, std::map<Prop_v, PropertyVariantType>>>;
+
+/**
* @class Manager - Represents the fan control manager's configuration
*
* A fan control manager configuration is optional, therefore the "manager.json"
@@ -339,10 +353,7 @@
* @param[in] value - Dbus object's property value
*/
void setProperty(const std::string& path, const std::string& intf,
- const std::string& prop, PropertyVariantType value)
- {
- _objects[path][intf][prop] = std::move(value);
- }
+ const std::string& prop, PropertyVariantType value);
/**
* @brief Remove an object's interface
@@ -488,6 +499,26 @@
static const std::string dumpFile;
private:
+ /**
+ * @brief Helper to detect when a property's double contains a NaN
+ * (not-a-number) value.
+ *
+ * @param[in] value - The property to test
+ */
+ static bool PropertyContainsNan(const PropertyVariantType& value)
+ {
+ return (std::holds_alternative<double>(value) &&
+ std::isnan(std::get<double>(value)));
+ }
+
+ /**
+ * @brief Insert managed objects into cache, but filter out properties
+ * containing unwanted NaN (not-a-number) values.
+ *
+ * @param[in] ref - The map of ManagedObjects to insert into cache
+ */
+ void insertFilteredObjects(ManagedObjects& ref);
+
/* The sdbusplus bus object to use */
sdbusplus::bus::bus& _bus;