blob: 8026bf0b4f75b3809593737e8fc1fd8112defba5 [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>
Brad Bishop24424982017-01-13 16:37:14 -050018#include <chrono>
Brad Bishop49aefb32016-10-19 11:54:14 -040019#include "manager.hpp"
20
Brad Bishop24424982017-01-13 16:37:14 -050021using namespace std::literals::chrono_literals;
22
Brad Bishop49aefb32016-10-19 11:54:14 -040023namespace phosphor
24{
25namespace inventory
26{
27namespace manager
28{
29namespace details
30{
31
32/** @brief Fowrarding signal callback.
33 *
34 * Extracts per-signal specific context and forwards the call to the manager
35 * instance.
36 */
Brad Bishop7b337772017-01-12 16:11:24 -050037auto _signal(sd_bus_message* m, void* data, sd_bus_error* e) noexcept
Brad Bishop49aefb32016-10-19 11:54:14 -040038{
Brad Bishop7b337772017-01-12 16:11:24 -050039 try
40 {
Brad Bishop49aefb32016-10-19 11:54:14 -040041 auto msg = sdbusplus::message::message(m);
Brad Bishop7b337772017-01-12 16:11:24 -050042 auto& args = *static_cast<Manager::SigArg*>(data);
Brad Bishop49aefb32016-10-19 11:54:14 -040043 sd_bus_message_ref(m);
Brad Bishop7b337772017-01-12 16:11:24 -050044 auto& mgr = *std::get<0>(args);
Brad Bishop48547a82017-01-19 15:12:50 -050045 mgr.handleEvent(
Brad Bishop7b337772017-01-12 16:11:24 -050046 msg,
47 static_cast<const details::DbusSignal&>(
48 *std::get<1>(args)),
49 *std::get<2>(args));
Brad Bishop49aefb32016-10-19 11:54:14 -040050 }
Brad Bishop7b337772017-01-12 16:11:24 -050051 catch (const std::exception& e)
52 {
Brad Bishop49aefb32016-10-19 11:54:14 -040053 std::cerr << e.what() << std::endl;
54 }
55
56 return 0;
57}
58
59} // namespace details
60
61Manager::Manager(
Brad Bishop7b337772017-01-12 16:11:24 -050062 sdbusplus::bus::bus&& bus,
63 const char* busname,
64 const char* root,
65 const char* iface) :
Brad Bishop451f8d92016-11-21 14:15:19 -050066 details::ServerObject<details::ManagerIface>(bus, root),
Brad Bishop49aefb32016-10-19 11:54:14 -040067 _shutdown(false),
68 _root(root),
69 _bus(std::move(bus)),
70 _manager(sdbusplus::server::manager::manager(_bus, root))
71{
Brad Bishop7b337772017-01-12 16:11:24 -050072 for (auto& group : _events)
Brad Bishop68c80832016-11-29 16:41:32 -050073 {
Brad Bishop48547a82017-01-19 15:12:50 -050074 for (auto pEvent : std::get<std::vector<details::EventBasePtr>>(
75 group))
Brad Bishop68c80832016-11-29 16:41:32 -050076 {
77 if (pEvent->type !=
Brad Bishop7b337772017-01-12 16:11:24 -050078 details::Event::Type::DBUS_SIGNAL)
79 {
Brad Bishop68c80832016-11-29 16:41:32 -050080 continue;
Brad Bishop7b337772017-01-12 16:11:24 -050081 }
Brad Bishop4f20a3e2016-11-29 15:21:46 -050082
Brad Bishop68c80832016-11-29 16:41:32 -050083 // Create a callback context for this event group.
Brad Bishop7b337772017-01-12 16:11:24 -050084 auto dbusEvent = static_cast<details::DbusSignal*>(
85 pEvent.get());
Brad Bishop68c80832016-11-29 16:41:32 -050086
87 // Go ahead and store an iterator pointing at
88 // the event data to avoid lookups later since
89 // additional signal callbacks aren't added
90 // after the manager is constructed.
91 _sigargs.emplace_back(
Brad Bishop7b337772017-01-12 16:11:24 -050092 std::make_unique<SigArg>(
93 this,
94 dbusEvent,
95 &group));
Brad Bishop68c80832016-11-29 16:41:32 -050096
97 // Register our callback and the context for
98 // each signal event.
99 _matches.emplace_back(
Brad Bishop7b337772017-01-12 16:11:24 -0500100 _bus,
Brad Bishop48547a82017-01-19 15:12:50 -0500101 dbusEvent->signature,
Brad Bishop7b337772017-01-12 16:11:24 -0500102 details::_signal,
103 _sigargs.back().get());
Brad Bishop68c80832016-11-29 16:41:32 -0500104 }
Brad Bishop49aefb32016-10-19 11:54:14 -0400105 }
106
107 _bus.request_name(busname);
108}
109
110void Manager::shutdown() noexcept
111{
112 _shutdown = true;
113}
114
115void Manager::run() noexcept
116{
Brad Bishop3e4a19a2017-01-21 22:17:09 -0500117 sdbusplus::message::message unusedMsg{nullptr};
118
119 // Run startup events.
120 for (auto& group : _events)
121 {
122 for (auto pEvent : std::get<std::vector<details::EventBasePtr>>(
123 group))
124 {
125 if (pEvent->type ==
126 details::Event::Type::STARTUP)
127 {
128 handleEvent(unusedMsg, *pEvent, group);
129 }
130 }
131 }
132
Brad Bishop7b337772017-01-12 16:11:24 -0500133 while (!_shutdown)
134 {
135 try
136 {
Brad Bishop49aefb32016-10-19 11:54:14 -0400137 _bus.process_discard();
Brad Bishop24424982017-01-13 16:37:14 -0500138 _bus.wait((5000000us).count());
Brad Bishop49aefb32016-10-19 11:54:14 -0400139 }
Brad Bishop7b337772017-01-12 16:11:24 -0500140 catch (const std::exception& e)
141 {
Brad Bishop49aefb32016-10-19 11:54:14 -0400142 std::cerr << e.what() << std::endl;
143 }
144 }
145}
146
Brad Bishop9aa5e2f2017-01-15 19:45:40 -0500147void Manager::notify(sdbusplus::message::object_path path, Object object)
Brad Bishop49aefb32016-10-19 11:54:14 -0400148{
Brad Bishop7b337772017-01-12 16:11:24 -0500149 try
150 {
Brad Bishopeb68a682017-01-22 00:58:54 -0500151 createObjects({std::make_pair(path, object)});
Brad Bishop49aefb32016-10-19 11:54:14 -0400152 }
Brad Bishop7b337772017-01-12 16:11:24 -0500153 catch (const std::exception& e)
154 {
Brad Bishop49aefb32016-10-19 11:54:14 -0400155 std::cerr << e.what() << std::endl;
156 }
157}
158
Brad Bishop48547a82017-01-19 15:12:50 -0500159void Manager::handleEvent(
Brad Bishop7b337772017-01-12 16:11:24 -0500160 sdbusplus::message::message& msg,
Brad Bishop48547a82017-01-19 15:12:50 -0500161 const details::Event& event,
Brad Bishop7b337772017-01-12 16:11:24 -0500162 const EventInfo& info)
Brad Bishop49aefb32016-10-19 11:54:14 -0400163{
Brad Bishop7b337772017-01-12 16:11:24 -0500164 auto& actions = std::get<1>(info);
Brad Bishop3d57f502016-10-19 12:18:41 -0400165
Brad Bishop48547a82017-01-19 15:12:50 -0500166 for (auto& f : event)
Brad Bishop7b337772017-01-12 16:11:24 -0500167 {
Brad Bishop23719002017-01-24 21:08:46 -0500168 if (!(*f)(_bus, msg, *this))
Brad Bishop7b337772017-01-12 16:11:24 -0500169 {
Brad Bishop064c94a2017-01-21 21:33:30 -0500170 return;
Brad Bishop7b337772017-01-12 16:11:24 -0500171 }
Brad Bishop3d57f502016-10-19 12:18:41 -0400172 }
Brad Bishop064c94a2017-01-21 21:33:30 -0500173 for (auto& action : actions)
174 {
Brad Bishop23719002017-01-24 21:08:46 -0500175 (*action)(_bus, *this);
Brad Bishop064c94a2017-01-21 21:33:30 -0500176 }
Brad Bishop49aefb32016-10-19 11:54:14 -0400177}
178
Brad Bishop7b7e7122017-01-21 21:21:46 -0500179void Manager::destroyObjects(
180 const std::vector<const char*>& paths)
Brad Bishop656a7d02016-10-19 22:20:02 -0400181{
Brad Bishop7b7e7122017-01-21 21:21:46 -0500182 for (const auto& path : paths)
183 {
184 std::string p{path};
185 _refs.erase(_root + p);
186 }
Brad Bishop656a7d02016-10-19 22:20:02 -0400187}
188
Brad Bishopeb68a682017-01-22 00:58:54 -0500189void Manager::createObjects(
190 const std::map<sdbusplus::message::object_path, Object>& objs)
191{
192 std::string absPath;
193
194 for (auto& o : objs)
195 {
196 auto& relPath = o.first;
197 auto& ifaces = o.second;
198
199 absPath.assign(_root);
200 absPath.append(relPath);
201
202 auto obj = _refs.find(absPath);
203 if (obj != _refs.end())
204 {
205 // This object already exists...skip.
206 continue;
207 }
208
209 // Create an interface holder for each interface
210 // provided by the client and group them into
211 // a container.
212 InterfaceComposite ref;
213
214 auto i = ifaces.size();
215 for (auto& iface : ifaces)
216 {
217 auto& props = iface.second;
218
219 // Defer sending any signals until the last interface.
220 auto deferSignals = --i != 0;
221 auto pMakers = _makers.find(iface.first.c_str());
222
223 if (pMakers == _makers.end())
224 {
225 // This interface is not known.
226 continue;
227 }
228
229 auto& maker = std::get<MakerType>(pMakers->second);
230
231 ref.emplace(
232 iface.first,
233 maker(
234 _bus,
235 absPath.c_str(),
236 props,
237 deferSignals));
238 }
239
240 if (!ref.empty())
241 {
242 // Hang on to a reference to the object (interfaces)
243 // so it stays on the bus, and so we can make calls
244 // to it if needed.
245 _refs.emplace(
246 absPath, std::move(ref));
247 }
248 }
249}
250
Brad Bishopb83a21e2016-11-30 13:43:37 -0500251details::holder::Base& Manager::getInterfaceHolder(
Brad Bishop7b337772017-01-12 16:11:24 -0500252 const char* path, const char* interface)
Brad Bishopb83a21e2016-11-30 13:43:37 -0500253{
Brad Bishop7b337772017-01-12 16:11:24 -0500254 return const_cast<const Manager*>(
255 this)->getInterfaceHolder(path, interface);
Brad Bishopb83a21e2016-11-30 13:43:37 -0500256}
257
258details::holder::Base& Manager::getInterfaceHolder(
Brad Bishop7b337772017-01-12 16:11:24 -0500259 const char* path, const char* interface) const
Brad Bishopb83a21e2016-11-30 13:43:37 -0500260{
261 std::string p{path};
262 auto oit = _refs.find(_root + p);
Brad Bishop7b337772017-01-12 16:11:24 -0500263 if (oit == _refs.end())
Brad Bishopb83a21e2016-11-30 13:43:37 -0500264 throw std::runtime_error(
Brad Bishop7b337772017-01-12 16:11:24 -0500265 _root + p + " was not found");
Brad Bishopb83a21e2016-11-30 13:43:37 -0500266
Brad Bishop7b337772017-01-12 16:11:24 -0500267 auto& obj = oit->second;
Brad Bishopb83a21e2016-11-30 13:43:37 -0500268 auto iit = obj.find(interface);
Brad Bishop7b337772017-01-12 16:11:24 -0500269 if (iit == obj.end())
Brad Bishopb83a21e2016-11-30 13:43:37 -0500270 throw std::runtime_error(
Brad Bishop7b337772017-01-12 16:11:24 -0500271 "interface was not found");
Brad Bishopb83a21e2016-11-30 13:43:37 -0500272
273 return *iit->second;
274}
275
Brad Bishop49aefb32016-10-19 11:54:14 -0400276} // namespace manager
277} // namespace inventory
278} // namespace phosphor
279
280// vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4