blob: 07d3d3130c7d73fa3ab620c268cb2491666b467a [file] [log] [blame]
Brad Bishop49aefb32016-10-19 11:54:14 -04001/**
2 * Copyright © 2016 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#include <iostream>
17#include <exception>
18#include "manager.hpp"
19
20namespace phosphor
21{
22namespace inventory
23{
24namespace manager
25{
26namespace details
27{
28
29/** @brief Fowrarding signal callback.
30 *
31 * Extracts per-signal specific context and forwards the call to the manager
32 * instance.
33 */
34auto _signal(sd_bus_message *m, void *data, sd_bus_error *e) noexcept
35{
36 try {
37 auto msg = sdbusplus::message::message(m);
38 auto &args = *static_cast<Manager::SigArg*>(data);
39 sd_bus_message_ref(m);
40 auto &mgr = *std::get<0>(args);
41 mgr.signal(msg, *std::get<1>(args));
42 }
43 catch (const std::exception &e) {
44 std::cerr << e.what() << std::endl;
45 }
46
47 return 0;
48}
49
50} // namespace details
51
52Manager::Manager(
53 sdbusplus::bus::bus &&bus,
54 const char *busname,
55 const char *root,
56 const char *iface) :
Brad Bishop451f8d92016-11-21 14:15:19 -050057 details::ServerObject<details::ManagerIface>(bus, root),
Brad Bishop49aefb32016-10-19 11:54:14 -040058 _shutdown(false),
59 _root(root),
60 _bus(std::move(bus)),
61 _manager(sdbusplus::server::manager::manager(_bus, root))
62{
63 for (auto &x: _events) {
Brad Bishop4f20a3e2016-11-29 15:21:46 -050064 auto pEvent = std::get<0>(x);
65 if (pEvent->type !=
66 details::Event::Type::DBUS_SIGNAL)
67 continue;
68
Brad Bishop49aefb32016-10-19 11:54:14 -040069 // Create a callback context for each event.
70 _sigargs.emplace_back(
71 std::make_unique<SigArg>(
72 std::make_tuple(
73 this,
Brad Bishop370421b2016-11-29 14:30:16 -050074 &x)));
Brad Bishop49aefb32016-10-19 11:54:14 -040075 // Register our callback and the context for
76 // each event.
Brad Bishop4f20a3e2016-11-29 15:21:46 -050077 auto &dbusEvent = static_cast<details::DbusSignal &>(
78 *pEvent);
Brad Bishop49aefb32016-10-19 11:54:14 -040079 _matches.emplace_back(
80 sdbusplus::server::match::match(
81 _bus,
Brad Bishop4f20a3e2016-11-29 15:21:46 -050082 std::get<0>(dbusEvent),
Brad Bishop49aefb32016-10-19 11:54:14 -040083 details::_signal,
84 _sigargs.back().get()));
85 }
86
87 _bus.request_name(busname);
88}
89
90void Manager::shutdown() noexcept
91{
92 _shutdown = true;
93}
94
95void Manager::run() noexcept
96{
97 while(!_shutdown) {
98 try {
99 _bus.process_discard();
100 _bus.wait(5000000);
101 }
102 catch (const std::exception &e) {
103 std::cerr << e.what() << std::endl;
104 }
105 }
106}
107
108void Manager::notify(std::string path, Object object)
109{
110 try {
Brad Bishop49aefb32016-10-19 11:54:14 -0400111 if(object.cbegin() == object.cend())
112 throw std::runtime_error(
113 "No interfaces in " + path);
114
Brad Bishop49aefb32016-10-19 11:54:14 -0400115 path.insert(0, _root);
116
117 auto obj = _refs.find(path);
118 if(obj != _refs.end())
119 throw std::runtime_error(
120 obj->first + " already exists");
121
122 // Create an interface holder for each interface
123 // provided by the client and group them into
124 // a container.
125 InterfaceComposite ref;
126
127 for (auto &x: object) {
Brad Bishop5fbaa7f2016-10-31 10:42:41 -0500128 auto maker = _makers.find(x.first.c_str());
Brad Bishop49aefb32016-10-19 11:54:14 -0400129
Brad Bishop5fbaa7f2016-10-31 10:42:41 -0500130 if(maker == _makers.end())
Brad Bishop49aefb32016-10-19 11:54:14 -0400131 throw std::runtime_error(
132 "Unimplemented interface: " + x.first);
133
134 ref.emplace(
135 std::make_pair(
136 x.first,
137 (maker->second)(_bus, path.c_str())));
138 }
139
140 // Hang on to a reference to the object (interfaces)
141 // so it stays on the bus, and so we can make calls
142 // to it if needed.
143 _refs.emplace(
144 std::make_pair(
145 path, std::move(ref)));
146 }
147 catch (const std::exception &e) {
148 std::cerr << e.what() << std::endl;
149 }
150}
151
152void Manager::signal(sdbusplus::message::message &msg, auto &args)
153{
Brad Bishop4f20a3e2016-11-29 15:21:46 -0500154 auto &event = std::get<0>(args);
155 auto &actions = std::get<1>(args);
156 auto &filter = *std::get<1>(static_cast<details::DbusSignal &>(*event));
Brad Bishop3d57f502016-10-19 12:18:41 -0400157
Brad Bishopc0eae112016-10-19 21:59:47 -0400158 if(filter(msg, *this)) {
Brad Bishop90074322016-11-29 13:05:57 -0500159 for (auto &action: actions)
160 (*action)(*this);
Brad Bishop3d57f502016-10-19 12:18:41 -0400161 }
Brad Bishop49aefb32016-10-19 11:54:14 -0400162}
163
Brad Bishop656a7d02016-10-19 22:20:02 -0400164void Manager::destroyObject(const char *path)
165{
166 std::string p{path};
167 _refs.erase(_root + p);
168}
169
Brad Bishop49aefb32016-10-19 11:54:14 -0400170} // namespace manager
171} // namespace inventory
172} // namespace phosphor
173
174// vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4