summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad Bishop <bradleyb@fuzziesquirrel.com>2017-01-22 16:00:50 -0500
committerPatrick Williams <patrick@stwcx.xyz>2017-02-15 17:43:19 +0000
commit79ccaf779deebb20e10d9ea99945bb9734195ddc (patch)
tree735c27138cd0b016480db185cc98d8009cbcfe28
parent865215878a00008099bf72ebc96247b8be20d200 (diff)
downloadphosphor-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.am4
-rw-r--r--configure.ac7
-rw-r--r--generated.mako.cpp5
-rw-r--r--manager.cpp118
-rw-r--r--manager.hpp54
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;
OpenPOWER on IntegriCloud