blob: d3e2973eb0ce071353fa96c04a35dbb83d5c6a49 [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);
Brad Bishop68c80832016-11-29 16:41:32 -050041 mgr.signal(
42 msg,
43 static_cast<const details::DbusSignal &>(
44 *std::get<1>(args)),
45 *std::get<2>(args));
Brad Bishop49aefb32016-10-19 11:54:14 -040046 }
47 catch (const std::exception &e) {
48 std::cerr << e.what() << std::endl;
49 }
50
51 return 0;
52}
53
54} // namespace details
55
56Manager::Manager(
57 sdbusplus::bus::bus &&bus,
58 const char *busname,
59 const char *root,
60 const char *iface) :
Brad Bishop451f8d92016-11-21 14:15:19 -050061 details::ServerObject<details::ManagerIface>(bus, root),
Brad Bishop49aefb32016-10-19 11:54:14 -040062 _shutdown(false),
63 _root(root),
64 _bus(std::move(bus)),
65 _manager(sdbusplus::server::manager::manager(_bus, root))
66{
Brad Bishop68c80832016-11-29 16:41:32 -050067 for (auto &group: _events)
68 {
69 for (auto pEvent: std::get<0>(group))
70 {
71 if (pEvent->type !=
72 details::Event::Type::DBUS_SIGNAL)
73 continue;
Brad Bishop4f20a3e2016-11-29 15:21:46 -050074
Brad Bishop68c80832016-11-29 16:41:32 -050075 // Create a callback context for this event group.
76 auto dbusEvent = static_cast<details::DbusSignal *>(
77 pEvent.get());
78
79 // Go ahead and store an iterator pointing at
80 // the event data to avoid lookups later since
81 // additional signal callbacks aren't added
82 // after the manager is constructed.
83 _sigargs.emplace_back(
84 std::make_unique<SigArg>(
85 std::make_tuple(
86 this,
87 dbusEvent,
88 &group)));
89
90 // Register our callback and the context for
91 // each signal event.
92 _matches.emplace_back(
93 sdbusplus::server::match::match(
94 _bus,
95 std::get<0>(*dbusEvent),
96 details::_signal,
97 _sigargs.back().get()));
98 }
Brad Bishop49aefb32016-10-19 11:54:14 -040099 }
100
101 _bus.request_name(busname);
102}
103
104void Manager::shutdown() noexcept
105{
106 _shutdown = true;
107}
108
109void Manager::run() noexcept
110{
111 while(!_shutdown) {
112 try {
113 _bus.process_discard();
114 _bus.wait(5000000);
115 }
116 catch (const std::exception &e) {
117 std::cerr << e.what() << std::endl;
118 }
119 }
120}
121
122void Manager::notify(std::string path, Object object)
123{
124 try {
Brad Bishop49aefb32016-10-19 11:54:14 -0400125 if(object.cbegin() == object.cend())
126 throw std::runtime_error(
127 "No interfaces in " + path);
128
Brad Bishop49aefb32016-10-19 11:54:14 -0400129 path.insert(0, _root);
130
131 auto obj = _refs.find(path);
132 if(obj != _refs.end())
133 throw std::runtime_error(
134 obj->first + " already exists");
135
136 // Create an interface holder for each interface
137 // provided by the client and group them into
138 // a container.
139 InterfaceComposite ref;
140
141 for (auto &x: object) {
Brad Bishop5fbaa7f2016-10-31 10:42:41 -0500142 auto maker = _makers.find(x.first.c_str());
Brad Bishop49aefb32016-10-19 11:54:14 -0400143
Brad Bishop5fbaa7f2016-10-31 10:42:41 -0500144 if(maker == _makers.end())
Brad Bishop49aefb32016-10-19 11:54:14 -0400145 throw std::runtime_error(
146 "Unimplemented interface: " + x.first);
147
148 ref.emplace(
149 std::make_pair(
150 x.first,
151 (maker->second)(_bus, path.c_str())));
152 }
153
154 // Hang on to a reference to the object (interfaces)
155 // so it stays on the bus, and so we can make calls
156 // to it if needed.
157 _refs.emplace(
158 std::make_pair(
159 path, std::move(ref)));
160 }
161 catch (const std::exception &e) {
162 std::cerr << e.what() << std::endl;
163 }
164}
165
Brad Bishop68c80832016-11-29 16:41:32 -0500166void Manager::signal(
167 sdbusplus::message::message &msg,
168 const details::DbusSignal &event,
169 const EventInfo &info)
Brad Bishop49aefb32016-10-19 11:54:14 -0400170{
Brad Bishop68c80832016-11-29 16:41:32 -0500171 auto &filter = *std::get<1>(event);
172 auto &actions = std::get<1>(info);
Brad Bishop3d57f502016-10-19 12:18:41 -0400173
Brad Bishopc0eae112016-10-19 21:59:47 -0400174 if(filter(msg, *this)) {
Brad Bishop90074322016-11-29 13:05:57 -0500175 for (auto &action: actions)
176 (*action)(*this);
Brad Bishop3d57f502016-10-19 12:18:41 -0400177 }
Brad Bishop49aefb32016-10-19 11:54:14 -0400178}
179
Brad Bishop656a7d02016-10-19 22:20:02 -0400180void Manager::destroyObject(const char *path)
181{
182 std::string p{path};
183 _refs.erase(_root + p);
184}
185
Brad Bishopb83a21e2016-11-30 13:43:37 -0500186details::holder::Base& Manager::getInterfaceHolder(
187 const char *path, const char *interface)
188{
189 return const_cast<const Manager *>(
190 this)->getInterfaceHolder(path, interface);
191}
192
193details::holder::Base& Manager::getInterfaceHolder(
194 const char *path, const char *interface) const
195{
196 std::string p{path};
197 auto oit = _refs.find(_root + p);
198 if(oit == _refs.end())
199 throw std::runtime_error(
200 _root + p + " was not found");
201
202 auto &obj = oit->second;
203 auto iit = obj.find(interface);
204 if(iit == obj.end())
205 throw std::runtime_error(
206 "interface was not found");
207
208 return *iit->second;
209}
210
Brad Bishop49aefb32016-10-19 11:54:14 -0400211} // namespace manager
212} // namespace inventory
213} // namespace phosphor
214
215// vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4