control: Handle updating service states
Add the necessary functions to handle updating the cached services tree
with the service names and owner states for any give path and interface.
A future commit is going to shift the manager's service handling
functions away from being static once all the required objects get an
ability to retrieve their associated manager object.
Change-Id: I6d1c80c3eeaffa6c38d527680454fd98432e8e03
Signed-off-by: Matthew Barth <msbarth@us.ibm.com>
diff --git a/control/json/manager.cpp b/control/json/manager.cpp
index b0dc6e3..ec15d18 100644
--- a/control/json/manager.cpp
+++ b/control/json/manager.cpp
@@ -47,7 +47,7 @@
std::vector<std::string> Manager::_activeProfiles;
std::map<std::string,
- std::map<std::pair<std::string, bool>, std::vector<std::string>>>
+ std::map<std::string, std::pair<bool, std::vector<std::string>>>>
Manager::_servTree;
std::map<std::string,
std::map<std::string, std::map<std::string, PropertyVariantType>>>
@@ -148,21 +148,136 @@
// Path not found in cache, therefore owner missing
return false;
}
- for (const auto& serv : itServ->second)
+ for (const auto& service : itServ->second)
{
auto itIntf = std::find_if(
- serv.second.begin(), serv.second.end(),
+ service.second.second.begin(), service.second.second.end(),
[&intf](const auto& interface) { return intf == interface; });
- if (itIntf != std::end(serv.second))
+ if (itIntf != std::end(service.second.second))
{
// Service found, return owner state
- return serv.first.second;
+ return service.second.first;
}
}
// Interface not found in cache, therefore owner missing
return false;
}
+void Manager::setOwner(const std::string& path, const std::string& serv,
+ const std::string& intf, bool isOwned)
+{
+ auto itServ = _servTree.find(path);
+ if (itServ == _servTree.end())
+ {
+ auto intfs = {intf};
+ _servTree[path] = {{serv, std::make_pair(isOwned, intfs)}};
+ return;
+ }
+ for (auto& service : itServ->second)
+ {
+ auto itIntf = std::find_if(
+ service.second.second.begin(), service.second.second.end(),
+ [&intf](const auto& interface) { return intf == interface; });
+ if (itIntf != std::end(service.second.second))
+ {
+ if (service.first == serv)
+ {
+ service.second.first = isOwned;
+ return;
+ }
+ }
+ }
+ auto intfs = {intf};
+ itServ->second[serv] = std::make_pair(isOwned, intfs);
+}
+
+const std::string& Manager::findService(const std::string& path,
+ const std::string& intf)
+{
+ static const std::string empty = "";
+
+ auto itServ = _servTree.find(path);
+ if (itServ != _servTree.end())
+ {
+ for (const auto& service : itServ->second)
+ {
+ auto itIntf = std::find_if(
+ service.second.second.begin(), service.second.second.end(),
+ [&intf](const auto& interface) { return intf == interface; });
+ if (itIntf != std::end(service.second.second))
+ {
+ // Service found, return service name
+ return service.first;
+ }
+ }
+ }
+
+ return empty;
+}
+
+void Manager::addServices(const std::string& path, const std::string& intf,
+ int32_t depth)
+{
+ // Get all subtree objects for the given interface
+ auto objects = util::SDBusPlus::getSubTree(util::SDBusPlus::getBus(), "/",
+ intf, depth);
+ // Add what's returned to the cache of path->services
+ for (auto& itPath : objects)
+ {
+ auto pathIter = _servTree.find(itPath.first);
+ if (pathIter != _servTree.end())
+ {
+ // Path found in cache
+ for (auto& itServ : itPath.second)
+ {
+ auto servIter = pathIter->second.find(itServ.first);
+ if (servIter != pathIter->second.end())
+ {
+ // Service found in cache
+ for (auto& itIntf : itServ.second)
+ {
+ if (std::find(servIter->second.second.begin(),
+ servIter->second.second.end(),
+ itIntf) == servIter->second.second.end())
+ {
+ // Add interface to cache
+ servIter->second.second.emplace_back(itIntf);
+ }
+ }
+ }
+ else
+ {
+ // Service not found in cache
+ auto intfs = {intf};
+ pathIter->second[itServ.first] =
+ std::make_pair(true, intfs);
+ }
+ }
+ }
+ else
+ {
+ // Path not found in cache
+ auto intfs = {intf};
+ _servTree[itPath.first] = {
+ {itPath.second.begin()->first, std::make_pair(true, intfs)}};
+ }
+ }
+}
+
+const std::string& Manager::getService(const std::string& path,
+ const std::string& intf)
+{
+ // Retrieve service from cache
+ const auto& serviceName = findService(path, intf);
+ if (serviceName.empty())
+ {
+ addServices(path, intf, 0);
+ return findService(path, intf);
+ }
+
+ return serviceName;
+}
+
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 eab11a6..420551e 100644
--- a/control/json/manager.hpp
+++ b/control/json/manager.hpp
@@ -188,6 +188,47 @@
static bool hasOwner(const std::string& path, const std::string& intf);
/**
+ * @brief Sets the dbus service owner state of a given object
+ *
+ * @param[in] path - Dbus object path
+ * @param[in] serv - Dbus service name
+ * @param[in] intf - Dbus object interface
+ * @param[in] isOwned - Dbus service owner state
+ */
+ void setOwner(const std::string& path, const std::string& serv,
+ const std::string& intf, bool isOwned);
+
+ /**
+ * @brief Add a set of services for a path and interface by retrieving all
+ * the path subtrees to the given depth from root for the interface
+ *
+ * @param[in] path - Path to add services for
+ * @param[in] intf - Interface to add services for
+ * @param[in] depth - Depth of tree traversal from root path
+ *
+ * @throws - DBusMethodError
+ * Throws a DBusMethodError when the `getSubTree` method call fails
+ */
+ static void addServices(const std::string& path, const std::string& intf,
+ int32_t depth);
+
+ /**
+ * @brief Get the service for a given path and interface from cached
+ * dataset and attempt to add all the services for the given path/interface
+ * when it's not found
+ *
+ * @param[in] path - Path to get service for
+ * @param[in] intf - Interface to get service for
+ *
+ * @return - The now cached service name
+ *
+ * @throws - DBusMethodError
+ * Ripples up a DBusMethodError exception from calling addServices
+ */
+ static const std::string& getService(const std::string& path,
+ const std::string& intf);
+
+ /**
* @brief Get the object's property value as a variant
*
* @param[in] path - Path of the object containing the property
@@ -252,9 +293,10 @@
/* List of active profiles */
static std::vector<std::string> _activeProfiles;
- /* Subtree map of paths to services (with ownership state) of interfaces */
- static std::map<std::string, std::map<std::pair<std::string, bool>,
- std::vector<std::string>>>
+ /* Subtree map of paths to services of interfaces(with ownership state) */
+ static std::map<
+ std::string,
+ std::map<std::string, std::pair<bool, std::vector<std::string>>>>
_servTree;
/* Object map of paths to interfaces of properties and their values */
@@ -273,6 +315,18 @@
std::map<configKey, std::unique_ptr<Event>> _events;
/**
+ * @brief Find the service name for a given path and interface from the
+ * cached dataset
+ *
+ * @param[in] path - Path to get service for
+ * @param[in] intf - Interface to get service for
+ *
+ * @return - The cached service name
+ */
+ static const std::string& findService(const std::string& path,
+ 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