summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWilliam A. Kennington III <wak@google.com>2018-03-15 17:09:28 -0700
committerWilliam A. Kennington III <wak@google.com>2018-04-02 23:35:10 +0000
commite47fdfb5d79a32075ec10f5549c07a2e8310079f (patch)
tree1ce29b8f9b6a0ef219c42fe28dcf216c235288b5
parent25bc7ac647ce216b1d6a4f4dcb55beadb064ced6 (diff)
downloadphosphor-host-ipmid-e47fdfb5d79a32075ec10f5549c07a2e8310079f.tar.gz
phosphor-host-ipmid-e47fdfb5d79a32075ec10f5549c07a2e8310079f.zip
utils: Add a class to cache service lookups
Currently we are doing interface + path -> service lookups for each ipmi command sent to the daemon. For many types of commands this is not ideal as the daemon is unlikely to change often at runtime. Implement a basic cache with the ability to invalidate the service name at any time. This is used by code in a future commit. Change-Id: I85b04dd17ac19e31d49070f289704b429bd1e577 Signed-off-by: William A. Kennington III <wak@google.com>
-rw-r--r--utils.cpp41
-rw-r--r--utils.hpp61
2 files changed, 101 insertions, 1 deletions
diff --git a/utils.cpp b/utils.cpp
index bd8fade..31c219c 100644
--- a/utils.cpp
+++ b/utils.cpp
@@ -250,6 +250,47 @@ void setDbusProperty(sdbusplus::bus::bus& bus,
}
+ServiceCache::ServiceCache(const std::string& intf, const std::string& path)
+ : intf(intf), path(path), cachedService(std::experimental::nullopt),
+ cachedBusName(std::experimental::nullopt)
+{
+}
+
+ServiceCache::ServiceCache(std::string&& intf, std::string&& path)
+ : intf(std::move(intf)), path(std::move(path)),
+ cachedService(std::experimental::nullopt),
+ cachedBusName(std::experimental::nullopt)
+{
+}
+
+const std::string& ServiceCache::getService(sdbusplus::bus::bus& bus)
+{
+ if (!isValid(bus))
+ {
+ cachedBusName = bus.get_unique_name();
+ cachedService = ::ipmi::getService(bus, intf, path);
+ }
+ return cachedService.value();
+}
+
+void ServiceCache::invalidate()
+{
+ cachedBusName = std::experimental::nullopt;
+ cachedService = std::experimental::nullopt;
+}
+
+sdbusplus::message::message ServiceCache::newMethodCall(
+ sdbusplus::bus::bus& bus, const char *intf, const char *method)
+{
+ return bus.new_method_call(getService(bus).c_str(), path.c_str(),
+ intf, method);
+}
+
+bool ServiceCache::isValid(sdbusplus::bus::bus& bus) const
+{
+ return cachedService && cachedBusName == bus.get_unique_name();
+}
+
std::string getService(sdbusplus::bus::bus& bus,
const std::string& intf,
const std::string& path)
diff --git a/utils.hpp b/utils.hpp
index b4f090f..878b05a 100644
--- a/utils.hpp
+++ b/utils.hpp
@@ -1,7 +1,8 @@
#pragma once
+#include <experimental/optional>
+#include <sdbusplus/server.hpp>
#include "types.hpp"
-#include <sdbusplus/server.hpp>
namespace ipmi
{
@@ -20,6 +21,64 @@ constexpr auto METHOD_GET = "Get";
constexpr auto METHOD_GET_ALL = "GetAll";
constexpr auto METHOD_SET = "Set";
+/** @class ServiceCache
+ * @brief Caches lookups of service names from the object mapper.
+ * @details Most ipmi commands need to talk to other dbus daemons to perform
+ * their intended actions on the BMC. This usually means they will
+ * first look up the service name providing the interface they
+ * require. This class reduces the number of such calls by caching
+ * the lookup for a specific service.
+ */
+class ServiceCache {
+ public:
+ /** @brief Creates a new service cache for the given interface
+ * and path.
+ *
+ * @param[in] intf - The interface used for each lookup
+ * @param[in] path - The path used for each lookup
+ */
+ ServiceCache(const std::string& intf, const std::string& path);
+ ServiceCache(std::string&& intf, std::string&& path);
+
+ /** @brief Gets the service name from the cache or does in a
+ * lookup when invalid.
+ *
+ * @param[in] bus - The bus associated with and used for looking
+ * up the service.
+ */
+ const std::string& getService(sdbusplus::bus::bus& bus);
+
+ /** @brief Invalidates the current service name */
+ void invalidate();
+
+ /** @brief A wrapper around sdbusplus bus.new_method_call
+ *
+ * @param[in] bus - The bus used for calling the method
+ * @param[in] intf - The interface containing the method
+ * @param[in] method - The method name
+ * @return The message containing the method call.
+ */
+ sdbusplus::message::message newMethodCall(sdbusplus::bus::bus& bus,
+ const char *intf,
+ const char *method);
+ private:
+ /** @brief DBUS interface provided by the service */
+ const std::string intf;
+ /** @brief DBUS path provided by the service */
+ const std::string path;
+ /** @brief The name of the service if valid */
+ std::experimental::optional<std::string> cachedService;
+ /** @brief The name of the bus used in the service lookup */
+ std::experimental::optional<std::string> cachedBusName;
+
+ /** @brief Check to see if the current cache is valid
+ *
+ * @param[in] bus - The bus used for the service lookup
+ * @return True if the cache is valid false otherwise.
+ */
+ bool isValid(sdbusplus::bus::bus& bus) const;
+};
+
/**
* @brief Get the DBUS Service name for the input dbus path
*
OpenPOWER on IntegriCloud