From e47fdfb5d79a32075ec10f5549c07a2e8310079f Mon Sep 17 00:00:00 2001 From: "William A. Kennington III" Date: Thu, 15 Mar 2018 17:09:28 -0700 Subject: 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 --- utils.cpp | 41 +++++++++++++++++++++++++++++++++++++++++ utils.hpp | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 101 insertions(+), 1 deletion(-) 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 +#include #include "types.hpp" -#include 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 cachedService; + /** @brief The name of the bus used in the service lookup */ + std::experimental::optional 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 * -- cgit v1.2.1