diff options
author | Brad Bishop <bradleyb@fuzziesquirrel.com> | 2017-01-22 16:00:50 -0500 |
---|---|---|
committer | Patrick Williams <patrick@stwcx.xyz> | 2017-02-15 17:43:19 +0000 |
commit | 79ccaf779deebb20e10d9ea99945bb9734195ddc (patch) | |
tree | 735c27138cd0b016480db185cc98d8009cbcfe28 | |
parent | 865215878a00008099bf72ebc96247b8be20d200 (diff) | |
download | phosphor-inventory-manager-79ccaf779deebb20e10d9ea99945bb9734195ddc.tar.gz phosphor-inventory-manager-79ccaf779deebb20e10d9ea99945bb9734195ddc.zip |
Add object/interface update methods
Add methods that handle both adding/updating
objects/interfaces.
Change-Id: I3c682365aad18f439babfb0413f29af05327eead
Signed-off-by: Brad Bishop <bradleyb@fuzziesquirrel.com>
-rw-r--r-- | Makefile.am | 4 | ||||
-rw-r--r-- | configure.ac | 7 | ||||
-rw-r--r-- | generated.mako.cpp | 5 | ||||
-rw-r--r-- | manager.cpp | 118 | ||||
-rw-r--r-- | manager.hpp | 54 |
5 files changed, 176 insertions, 12 deletions
diff --git a/Makefile.am b/Makefile.am index 1243e21..1e7ed65 100644 --- a/Makefile.am +++ b/Makefile.am @@ -16,8 +16,8 @@ libmanagercommon_la_SOURCES = \ errors.cpp \ functor.cpp \ manager.cpp -libmanagercommon_la_LIBADD = $(SDBUSPLUS_LIBS) $(PHOSPHOR_DBUS_INTERFACES_LIBS) -libmanagercommon_la_CFLAGS = $(SDBUSPLUS_CFLAGS) $(PHOSPHOR_DBUS_INTERACES_CFLAGS) +libmanagercommon_la_LIBADD = $(SDBUSPLUS_LIBS) $(PHOSPHOR_DBUS_INTERFACES_LIBS) $(PHOSPHOR_LOGGING_LIBS) +libmanagercommon_la_CFLAGS = $(SDBUSPLUS_CFLAGS) $(PHOSPHOR_DBUS_INTERACES_CFLAGS) $(PHOSPHOR_LOGGING_CFLAGS) libmanager_la_SOURCES = \ extra_ifaces.cpp \ diff --git a/configure.ac b/configure.ac index 83d063e..47d70d4 100644 --- a/configure.ac +++ b/configure.ac @@ -21,10 +21,9 @@ AM_PATH_PYTHON([2.7], # Checks for libraries. PKG_CHECK_MODULES([SYSTEMD], [libsystemd >= 221]) -PKG_CHECK_MODULES([SDBUSPLUS], [sdbusplus],, - AC_MSG_ERROR(["Requires sdbusplus package."])) -PKG_CHECK_MODULES([PHOSPHOR_DBUS_INTERFACES], [phosphor-dbus-interfaces],, - AC_MSG_ERROR(["Requires phosphor-dbus-interfaces package."])) +PKG_CHECK_MODULES([SDBUSPLUS], [sdbusplus],, AC_MSG_ERROR(["Requires sdbusplus package."])) +PKG_CHECK_MODULES([PHOSPHOR_DBUS_INTERFACES], [phosphor-dbus-interfaces],, AC_MSG_ERROR(["Requires phosphor-dbus-interfaces package."])) +PKG_CHECK_MODULES([PHOSPHOR_LOGGING], [phosphor-logging],, AC_MSG_ERROR(["Requires phosphor-logging."])) # Checks for typedefs, structures, and compiler characteristics. AX_CXX_COMPILE_STDCXX_14([noext]) diff --git a/generated.mako.cpp b/generated.mako.cpp index 235e58a..7a9a38e 100644 --- a/generated.mako.cpp +++ b/generated.mako.cpp @@ -24,7 +24,10 @@ const Manager::Makers Manager::_makers{ std::make_tuple( MakeInterface< ServerObject< - ${i.namespace()}>>::make + ${i.namespace()}>>::make, + MakeInterface< + ServerObject< + ${i.namespace()}>>::assign ) }, % endfor diff --git a/manager.cpp b/manager.cpp index 0c6831e..820eb62 100644 --- a/manager.cpp +++ b/manager.cpp @@ -16,8 +16,10 @@ #include <iostream> #include <exception> #include <chrono> +#include <algorithm> #include <log.hpp> #include "manager.hpp" +#include "errors.hpp" using namespace std::literals::chrono_literals; @@ -140,6 +142,122 @@ void Manager::run() noexcept } } +void Manager::updateInterfaces( + const sdbusplus::message::object_path& path, + const Object& interfaces, + ObjectReferences::iterator pos, + bool newObject) +{ + auto& refaces = pos->second; + auto ifaceit = interfaces.cbegin(); + auto opsit = _makers.cbegin(); + auto refaceit = refaces.begin(); + std::vector<std::string> signals; + + while (ifaceit != interfaces.cend()) + { + try + { + // Find the binding ops for this interface. + opsit = std::lower_bound( + opsit, + _makers.cend(), + ifaceit->first, + compareFirst(_makers.key_comp())); + + if (opsit == _makers.cend() || opsit->first != ifaceit->first) + { + // This interface is not supported. + throw InterfaceError( + "Encountered unsupported interface.", + ifaceit->first); + } + + // Find the binding insertion point or the binding to update. + refaceit = std::lower_bound( + refaceit, + refaces.end(), + ifaceit->first, + compareFirst(refaces.key_comp())); + + if (refaceit == refaces.end() || refaceit->first != ifaceit->first) + { + // Add the new interface. + auto& ctor = std::get<MakerType>(opsit->second); + refaceit = refaces.insert( + refaceit, + std::make_pair( + ifaceit->first, + ctor( + _bus, + path.str.c_str(), + ifaceit->second))); + signals.push_back(ifaceit->first); + } + else + { + // Set the new property values. + auto& assign = std::get<AssignerType>(opsit->second); + assign(ifaceit->second, refaceit->second); + } + } + catch (const InterfaceError& e) + { + // Reset the binding ops iterator since we are + // at the end. + opsit = _makers.cbegin(); + e.log(); + } + + ++ifaceit; + } + + if (newObject) + { + _bus.emit_object_added(path.str.c_str()); + } + else if (!signals.empty()) + { + // TODO: emit an interfaces added signal + } +} + +void Manager::updateObjects( + const std::map<sdbusplus::message::object_path, Object>& objs) +{ + auto objit = objs.cbegin(); + auto refit = _refs.begin(); + std::string absPath; + bool newObj; + + while (objit != objs.cend()) + { + // Find the insertion point or the object to update. + refit = std::lower_bound( + refit, + _refs.end(), + objit->first, + compareFirst(RelPathCompare(_root))); + + absPath.assign(_root); + absPath.append(objit->first); + + newObj = false; + if (refit == _refs.end() || refit->first != absPath) + { + refit = _refs.insert( + refit, + std::make_pair( + absPath, + decltype(_refs)::mapped_type())); + newObj = true; + } + + updateInterfaces(absPath, objit->second, refit, newObj); + ++objit; + } +} + void Manager::notify(std::map<sdbusplus::message::object_path, Object> objs) { updateObjects(objs); diff --git a/manager.hpp b/manager.hpp index 797880b..11750b8 100644 --- a/manager.hpp +++ b/manager.hpp @@ -23,6 +23,27 @@ using ServerObject = T; using ManagerIface = sdbusplus::xyz::openbmc_project::Inventory::server::Manager; +/** @struct PropertiesVariant + * @brief Wrapper for sdbusplus PropertiesVariant. + * + * A wrapper is useful since MakeInterface is instantiated with 'int' + * to deduce the return type of its methods, which does not depend + * on T. + * + * @tparam T - The sdbusplus server binding type. + */ +template <typename T, typename Enable = void> +struct PropertiesVariant {}; + +template <typename T> +struct PropertiesVariant<T, typename std::enable_if<std::is_object<T>::value>::type> +{ + using Type = typename T::PropertiesVariant; +}; + +template <typename T> +using PropertiesVariantType = typename PropertiesVariant<T>::Type; + /** @struct MakeInterface * @brief Adapt an sdbusplus interface proxy. * @@ -31,6 +52,7 @@ using ManagerIface = * * @tparam T - The type of the interface being adapted. */ + template <typename T> struct MakeInterface { @@ -39,9 +61,8 @@ struct MakeInterface const char* path, const Interface& props) { - using PropertiesVariant = typename T::PropertiesVariant; using InterfaceVariant = - std::map<std::string, PropertiesVariant>; + std::map<std::string, PropertiesVariantType<T>>; InterfaceVariant v; @@ -49,11 +70,21 @@ struct MakeInterface { v.emplace( p.first, - convertVariant<PropertiesVariant>(p.second)); + convertVariant<PropertiesVariantType<T>>(p.second)); } return any_ns::any(std::make_shared<T>(bus, path, v)); } + + static void assign(const Interface& props, any_ns::any& holder) + { + auto& iface = *any_ns::any_cast<std::shared_ptr<T> &>(holder); + for (const auto& p : props) + { + iface.setPropertyByName( + p.first, convertVariant<PropertiesVariantType<T>>(p.second)); + } + } }; /** @class Manager @@ -110,6 +141,10 @@ class Manager final : void createObjects( const std::map<sdbusplus::message::object_path, Object>& objs); + /** @brief Add or update objects on DBus. */ + void updateObjects( + const std::map<sdbusplus::message::object_path, Object>& objs); + /** @brief Invoke an sdbusplus server binding method. * * Invoke the requested method with a reference to the requested @@ -149,11 +184,13 @@ class Manager final : using ObjectReferences = std::map<std::string, InterfaceComposite>; using Events = std::vector<EventInfo>; - // The int instantiation is safe since the signature of these + // The int instantiations are safe since the signature of these // functions don't change from one instantiation to the next. using MakerType = std::add_pointer_t < decltype(MakeInterface<int>::make) >; - using Makers = std::map<std::string, std::tuple<MakerType>>; + using AssignerType = std::add_pointer_t < + decltype(MakeInterface<int>::assign) >; + using Makers = std::map<std::string, std::tuple<MakerType, AssignerType>>; /** @brief Provides weak references to interface holders. * @@ -195,6 +232,13 @@ class Manager final : return *any_ns::any_cast<T>(holder); } + /** @brief Add or update interfaces on DBus. */ + void updateInterfaces( + const sdbusplus::message::object_path& path, + const Object& interfaces, + ObjectReferences::iterator pos, + bool emitSignals = true); + /** @brief Provided for testing only. */ volatile bool _shutdown; |