control: Get property from cache and add objects
Add the ability to get a property from the cached set of dbus objects.
In the case that the property is not found in the cache, objects can be
added using the getManagedObjects method to retrieve all objects for a
given service. The service for the missing dbus object is attempted to
be retrieved from the cached set of services (and added if not cached),
then the path where the ObjectManager interface exists for the service
is determined so the getManagedObjects method call can be made. In the
case that the ObjectManager interface is not present on the service, the
individual dbus object is cached from dbus directly.
Change-Id: I3ddcf34cfba906ef3d78a755dec96a91971bc27f
Signed-off-by: Matthew Barth <msbarth@us.ibm.com>
diff --git a/control/json/manager.cpp b/control/json/manager.cpp
index 3582bf5..3457d3c 100644
--- a/control/json/manager.cpp
+++ b/control/json/manager.cpp
@@ -277,6 +277,142 @@
return serviceName;
}
+std::vector<std::string> Manager::findPaths(const std::string& serv,
+ const std::string& intf)
+{
+ std::vector<std::string> paths;
+
+ for (const auto& path : _servTree)
+ {
+ auto itServ = path.second.find(serv);
+ if (itServ != path.second.end())
+ {
+ if (std::find(itServ->second.second.begin(),
+ itServ->second.second.end(),
+ intf) != itServ->second.second.end())
+ {
+ if (std::find(paths.begin(), paths.end(), path.first) ==
+ paths.end())
+ {
+ paths.push_back(path.first);
+ }
+ }
+ }
+ }
+
+ return paths;
+}
+
+std::vector<std::string> Manager::getPaths(const std::string& serv,
+ const std::string& intf)
+{
+ auto paths = findPaths(serv, intf);
+ if (paths.empty())
+ {
+ addServices(intf, 0);
+ return findPaths(serv, intf);
+ }
+
+ return paths;
+}
+
+void Manager::addObjects(const std::string& path, const std::string& intf,
+ const std::string& prop)
+{
+ auto service = getService(path, intf);
+ if (service.empty())
+ {
+ // Log service not found for object
+ log<level::ERR>(
+ fmt::format("Unable to get service name for path {}, interface {}",
+ path, intf)
+ .c_str());
+ return;
+ }
+
+ auto objMgrPaths = getPaths(service, "org.freedesktop.DBus.ObjectManager");
+ if (objMgrPaths.empty())
+ {
+ // No object manager interface provided by service?
+ // Attempt to retrieve property directly
+ auto variant = util::SDBusPlus::getPropertyVariant<PropertyVariantType>(
+ _bus, service, path, intf, prop);
+ _objects[path][intf][prop] = variant;
+ return;
+ }
+
+ for (const auto& objMgrPath : objMgrPaths)
+ {
+ // Get all managed objects of service
+ 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);
+ }
+ }
+ }
+}
+
+const std::optional<PropertyVariantType>
+ Manager::getProperty(const std::string& path, const std::string& intf,
+ const std::string& prop)
+{
+ // TODO Objects hosted by fan control (i.e. ThermalMode) are required to
+ // update the cache upon being set/updated
+ auto itPath = _objects.find(path);
+ if (itPath != _objects.end())
+ {
+ auto itIntf = itPath->second.find(intf);
+ if (itIntf != itPath->second.end())
+ {
+ auto itProp = itIntf->second.find(prop);
+ if (itProp != itIntf->second.end())
+ {
+ return itProp->second;
+ }
+ }
+ }
+
+ return std::nullopt;
+}
+
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 88a2b1f..b414c62 100644
--- a/control/json/manager.hpp
+++ b/control/json/manager.hpp
@@ -260,6 +260,48 @@
const std::string& intf);
/**
+ * @brief Get all the object paths for a given service and interface from
+ * the cached dataset and try to add all the services for the given
+ * interface when no paths are found and then attempt to get all the object
+ * paths again
+ *
+ * @param[in] serv - Service name to get paths for
+ * @param[in] intf - Interface to get paths for
+ *
+ * @return The cached object paths
+ */
+ std::vector<std::string> getPaths(const std::string& serv,
+ const std::string& intf);
+
+ /**
+ * @brief Add objects to the cached dataset by first using
+ * `getManagedObjects` for the same service providing the given path and
+ * interface or just add the single object of the given path, interface, and
+ * property if that fails.
+ *
+ * @param[in] path - Dbus object's path
+ * @param[in] intf - Dbus object's interface
+ * @param[in] prop - Dbus object's property
+ *
+ * @throws - DBusMethodError
+ * Throws a DBusMethodError when the the service is failed to be found or
+ * when the `getManagedObjects` method call fails
+ */
+ void addObjects(const std::string& path, const std::string& intf,
+ const std::string& prop);
+
+ /**
+ * @brief Get an object's property value
+ *
+ * @param[in] path - Dbus object's path
+ * @param[in] intf - Dbus object's interface
+ * @param[in] prop - Dbus object's property
+ */
+ const std::optional<PropertyVariantType>
+ getProperty(const std::string& path, const std::string& intf,
+ const std::string& prop);
+
+ /**
* @brief Set/update an object's property value
*
* @param[in] path - Dbus object's path
@@ -420,6 +462,18 @@
const std::string& intf);
/**
+ * @brief Find all the paths for a given service and interface from the
+ * cached dataset
+ *
+ * @param[in] serv - Service name to get paths for
+ * @param[in] intf - Interface to get paths for
+ *
+ * @return - The cached object paths
+ */
+ std::vector<std::string> findPaths(const std::string& serv,
+ const std::string& intf);
+
+ /**
* @brief Parse and set the configured profiles from the profiles JSON file
*
* Retrieves the optional profiles JSON configuration file, parses it, and