summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad Bishop <bradleyb@fuzziesquirrel.com>2017-01-22 00:58:54 -0500
committerBrad Bishop <bradleyb@fuzziesquirrel.com>2017-02-01 16:28:34 -0500
commiteb68a687575b31d5d69a8ed9a26a2a0877ebec57 (patch)
tree72b3b071e737a6ab9adce5a83a42bf3ba01007d3
parentdb92c28ac9f354833753b451e4fba081c75d2564 (diff)
downloadphosphor-inventory-manager-eb68a687575b31d5d69a8ed9a26a2a0877ebec57.tar.gz
phosphor-inventory-manager-eb68a687575b31d5d69a8ed9a26a2a0877ebec57.zip
Add support for createObjects action
Change-Id: I999a5e506a236eac8ca0944b0e2b003c57612e54 Signed-off-by: Brad Bishop <bradleyb@fuzziesquirrel.com>
-rw-r--r--actions.hpp11
-rw-r--r--example/events.d/match1.yaml47
-rw-r--r--manager.cpp109
-rw-r--r--manager.hpp4
-rw-r--r--test/test.cpp45
5 files changed, 168 insertions, 48 deletions
diff --git a/actions.hpp b/actions.hpp
index dfa1d00..634cbc9 100644
--- a/actions.hpp
+++ b/actions.hpp
@@ -3,6 +3,7 @@
#include <utility>
#include <memory>
#include "utils.hpp"
+#include "types.hpp"
namespace phosphor
{
@@ -48,6 +49,16 @@ inline auto destroyObjects(std::vector<const char*> paths)
};
}
+/** @brief Create objects action. */
+inline auto createObjects(
+ const std::map<sdbusplus::message::object_path, Object>& objs)
+{
+ return [&objs](auto&, auto & m)
+ {
+ m.createObjects(objs);
+ };
+}
+
/** @brief Set a property action.
*
* Invoke the requested method with a reference to the requested
diff --git a/example/events.d/match1.yaml b/example/events.d/match1.yaml
index 2219c9f..0d53657 100644
--- a/example/events.d/match1.yaml
+++ b/example/events.d/match1.yaml
@@ -2,7 +2,7 @@ description: >
An example inventory match rule.
events:
- - name: Example Match(1)
+ - name: Example Match
description: >
Sets the value of ExampleProperty1 on /changeme
when the value of ExampleProperty2 on
@@ -29,4 +29,49 @@ events:
type: string
value: changed
+ - name: Example Match
+ description: >
+ Create /createme1 and /createme2 when the value of
+ ExampleProperty2 on /testing/trigger5 changes to abc123.
+ type: match
+ signatures:
+ - type: signal
+ interface: org.freedesktop.DBus.Properties
+ path: /testing/trigger5
+ member: PropertiesChanged
+ filters:
+ - name: propertyChangedTo
+ interface: xyz.openbmc_project.Example.Iface2
+ property: ExampleProperty2
+ value:
+ type: string
+ value: abc123
+ actions:
+ - name: createObjects
+ objs:
+ /createme1:
+ xyz.openbmc_project.Example.Iface1:
+ ExampleProperty1:
+ value: foo
+ type: string
+ xyz.openbmc_project.Example.Iface2:
+ ExampleProperty2:
+ value: bar
+ type: string
+ ExampleProperty3:
+ value: 999
+ type: int64
+ /createme2:
+ xyz.openbmc_project.Example.Iface1:
+ ExampleProperty1:
+ value: bar
+ type: string
+ xyz.openbmc_project.Example.Iface2:
+ ExampleProperty2:
+ value: foo
+ type: string
+ ExampleProperty3:
+ value: 888
+ type: int64
+
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
diff --git a/manager.cpp b/manager.cpp
index 83ca75f..1ebcb7f 100644
--- a/manager.cpp
+++ b/manager.cpp
@@ -132,52 +132,7 @@ void Manager::notify(sdbusplus::message::object_path path, Object object)
{
try
{
-
- if (object.cbegin() == object.cend())
- throw std::runtime_error(
- "No interfaces in " + path.str);
-
- path.str.insert(0, _root);
-
- auto obj = _refs.find(path);
- if (obj != _refs.end())
- throw std::runtime_error(
- obj->first + " already exists");
-
- // Create an interface holder for each interface
- // provided by the client and group them into
- // a container.
- InterfaceComposite ref;
-
- auto i = object.size();
- for (auto& x : object)
- {
- // Defer sending any signals until the last interface.
- auto deferSignals = --i != 0;
- auto pMakers = _makers.find(x.first.c_str());
-
- if (pMakers == _makers.end())
- throw std::runtime_error(
- "Unimplemented interface: " + x.first);
-
- auto& maker = std::get<MakerType>(pMakers->second);
-
- auto& props = x.second;
- ref.emplace(x.first, maker(
- _bus,
- path.str.c_str(),
- props,
- deferSignals));
- }
-
- if (!ref.empty())
- {
- // Hang on to a reference to the object (interfaces)
- // so it stays on the bus, and so we can make calls
- // to it if needed.
- _refs.emplace(
- path, std::move(ref));
- }
+ createObjects({std::make_pair(path, object)});
}
catch (const std::exception& e)
{
@@ -215,6 +170,68 @@ void Manager::destroyObjects(
}
}
+void Manager::createObjects(
+ const std::map<sdbusplus::message::object_path, Object>& objs)
+{
+ std::string absPath;
+
+ for (auto& o : objs)
+ {
+ auto& relPath = o.first;
+ auto& ifaces = o.second;
+
+ absPath.assign(_root);
+ absPath.append(relPath);
+
+ auto obj = _refs.find(absPath);
+ if (obj != _refs.end())
+ {
+ // This object already exists...skip.
+ continue;
+ }
+
+ // Create an interface holder for each interface
+ // provided by the client and group them into
+ // a container.
+ InterfaceComposite ref;
+
+ auto i = ifaces.size();
+ for (auto& iface : ifaces)
+ {
+ auto& props = iface.second;
+
+ // Defer sending any signals until the last interface.
+ auto deferSignals = --i != 0;
+ auto pMakers = _makers.find(iface.first.c_str());
+
+ if (pMakers == _makers.end())
+ {
+ // This interface is not known.
+ continue;
+ }
+
+ auto& maker = std::get<MakerType>(pMakers->second);
+
+ ref.emplace(
+ iface.first,
+ maker(
+ _bus,
+ absPath.c_str(),
+ props,
+ deferSignals));
+ }
+
+ if (!ref.empty())
+ {
+ // Hang on to a reference to the object (interfaces)
+ // so it stays on the bus, and so we can make calls
+ // to it if needed.
+ _refs.emplace(
+ absPath, std::move(ref));
+ }
+ }
+}
+
details::holder::Base& Manager::getInterfaceHolder(
const char* path, const char* interface)
{
diff --git a/manager.hpp b/manager.hpp
index 7a01bee..e6c08bf 100644
--- a/manager.hpp
+++ b/manager.hpp
@@ -103,6 +103,10 @@ class Manager final :
void destroyObjects(
const std::vector<const char*>& paths);
+ /** @brief Add objects to DBus. */
+ void createObjects(
+ 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
diff --git a/test/test.cpp b/test/test.cpp
index 21f89e2..816d471 100644
--- a/test/test.cpp
+++ b/test/test.cpp
@@ -40,7 +40,8 @@ const auto trigger3 = sdbusplus::message::object_path(EXAMPLE_ROOT +
"/trigger3"s);
const auto trigger4 = sdbusplus::message::object_path(EXAMPLE_ROOT +
"/trigger4"s);
-
+const auto trigger5 = sdbusplus::message::object_path(EXAMPLE_ROOT +
+ "/trigger5"s);
const sdbusplus::message::object_path relDeleteMeOne{"/deleteme1"};
const sdbusplus::message::object_path relDeleteMeTwo{"/deleteme2"};
@@ -78,6 +79,8 @@ struct ExampleService
ExampleIface1, ExampleIface2 > t3(bus, trigger3.str.c_str());
sdbusplus::server::object::object <
ExampleIface1, ExampleIface2 > t4(bus, trigger4.str.c_str());
+ sdbusplus::server::object::object <
+ ExampleIface1, ExampleIface2 > t5(bus, trigger5.str.c_str());
while (!shutdown)
{
@@ -456,6 +459,46 @@ void runTests()
}
}
}
+
+ // Validate the create object action.
+ {
+ sdbusplus::message::object_path relCreateMe1{"/createme1"};
+ sdbusplus::message::object_path relCreateMe2{"/createme2"};
+ std::string createMe1{root + relCreateMe1.str};
+ std::string createMe2{root + relCreateMe2.str};
+
+ // Trigger the action.
+ {
+ sdbusplus::message::object_path signalPath;
+ Object signalObject;
+
+ SignalQueue queue(
+ "path='" + root + "',member='InterfacesAdded'");
+
+ auto m = set(trigger5.str);
+ m.append("xyz.openbmc_project.Example.Iface2");
+ m.append("ExampleProperty2");
+ m.append(sdbusplus::message::variant<std::string>("abc123"));
+ b.call(m);
+ {
+ auto sig{queue.pop()};
+ assert(sig);
+ sig.read(signalPath);
+ assert(createMe1 == signalPath.str);
+ sig.read(signalObject);
+ }
+ {
+ auto sig{queue.pop()};
+ assert(sig);
+ sig.read(signalPath);
+ assert(createMe2 == signalPath.str);
+ sig.read(signalObject);
+ }
+
+ auto moreSignals{queue.pop()};
+ assert(!moreSignals);
+ }
+ }
}
int main()
OpenPOWER on IntegriCloud