blob: 5dcd9e57be8680b5756e77c1d360b49bbff17fdf [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 Bishop9bbfcb12017-02-04 10:51:06 -050019#include <log.hpp>
Brad Bishop49aefb32016-10-19 11:54:14 -040020#include "manager.hpp"
21
Brad Bishop24424982017-01-13 16:37:14 -050022using namespace std::literals::chrono_literals;
23
Brad Bishop49aefb32016-10-19 11:54:14 -040024namespace phosphor
25{
26namespace inventory
27{
28namespace manager
29{
Brad Bishop49aefb32016-10-19 11:54:14 -040030/** @brief Fowrarding signal callback.
31 *
32 * Extracts per-signal specific context and forwards the call to the manager
33 * instance.
34 */
Brad Bishop7b337772017-01-12 16:11:24 -050035auto _signal(sd_bus_message* m, void* data, sd_bus_error* e) noexcept
Brad Bishop49aefb32016-10-19 11:54:14 -040036{
Brad Bishop7b337772017-01-12 16:11:24 -050037 try
38 {
Brad Bishop49aefb32016-10-19 11:54:14 -040039 auto msg = sdbusplus::message::message(m);
Brad Bishop7b337772017-01-12 16:11:24 -050040 auto& args = *static_cast<Manager::SigArg*>(data);
Brad Bishop49aefb32016-10-19 11:54:14 -040041 sd_bus_message_ref(m);
Brad Bishop7b337772017-01-12 16:11:24 -050042 auto& mgr = *std::get<0>(args);
Brad Bishop48547a82017-01-19 15:12:50 -050043 mgr.handleEvent(
Brad Bishop7b337772017-01-12 16:11:24 -050044 msg,
Brad Bishop12f8a3c2017-02-09 00:02:00 -050045 static_cast<const DbusSignal&>(
Brad Bishop7b337772017-01-12 16:11:24 -050046 *std::get<1>(args)),
47 *std::get<2>(args));
Brad Bishop49aefb32016-10-19 11:54:14 -040048 }
Brad Bishop7b337772017-01-12 16:11:24 -050049 catch (const std::exception& e)
50 {
Brad Bishop49aefb32016-10-19 11:54:14 -040051 std::cerr << e.what() << std::endl;
52 }
53
54 return 0;
55}
56
Brad Bishop49aefb32016-10-19 11:54:14 -040057Manager::Manager(
Brad Bishop7b337772017-01-12 16:11:24 -050058 sdbusplus::bus::bus&& bus,
59 const char* busname,
60 const char* root,
61 const char* iface) :
Brad Bishop12f8a3c2017-02-09 00:02:00 -050062 ServerObject<ManagerIface>(bus, root),
Brad Bishop49aefb32016-10-19 11:54:14 -040063 _shutdown(false),
64 _root(root),
65 _bus(std::move(bus)),
66 _manager(sdbusplus::server::manager::manager(_bus, root))
67{
Brad Bishop7b337772017-01-12 16:11:24 -050068 for (auto& group : _events)
Brad Bishop68c80832016-11-29 16:41:32 -050069 {
Brad Bishop12f8a3c2017-02-09 00:02:00 -050070 for (auto pEvent : std::get<std::vector<EventBasePtr>>(
Brad Bishop48547a82017-01-19 15:12:50 -050071 group))
Brad Bishop68c80832016-11-29 16:41:32 -050072 {
73 if (pEvent->type !=
Brad Bishop12f8a3c2017-02-09 00:02:00 -050074 Event::Type::DBUS_SIGNAL)
Brad Bishop7b337772017-01-12 16:11:24 -050075 {
Brad Bishop68c80832016-11-29 16:41:32 -050076 continue;
Brad Bishop7b337772017-01-12 16:11:24 -050077 }
Brad Bishop4f20a3e2016-11-29 15:21:46 -050078
Brad Bishop68c80832016-11-29 16:41:32 -050079 // Create a callback context for this event group.
Brad Bishop12f8a3c2017-02-09 00:02:00 -050080 auto dbusEvent = static_cast<DbusSignal*>(
Brad Bishop7b337772017-01-12 16:11:24 -050081 pEvent.get());
Brad Bishop68c80832016-11-29 16:41:32 -050082
83 // Go ahead and store an iterator pointing at
84 // the event data to avoid lookups later since
85 // additional signal callbacks aren't added
86 // after the manager is constructed.
87 _sigargs.emplace_back(
Brad Bishop7b337772017-01-12 16:11:24 -050088 std::make_unique<SigArg>(
89 this,
90 dbusEvent,
91 &group));
Brad Bishop68c80832016-11-29 16:41:32 -050092
93 // Register our callback and the context for
94 // each signal event.
95 _matches.emplace_back(
Brad Bishop7b337772017-01-12 16:11:24 -050096 _bus,
Brad Bishop48547a82017-01-19 15:12:50 -050097 dbusEvent->signature,
Brad Bishop12f8a3c2017-02-09 00:02:00 -050098 _signal,
Brad Bishop7b337772017-01-12 16:11:24 -050099 _sigargs.back().get());
Brad Bishop68c80832016-11-29 16:41:32 -0500100 }
Brad Bishop49aefb32016-10-19 11:54:14 -0400101 }
102
103 _bus.request_name(busname);
104}
105
106void Manager::shutdown() noexcept
107{
108 _shutdown = true;
109}
110
111void Manager::run() noexcept
112{
Brad Bishop3e4a19a2017-01-21 22:17:09 -0500113 sdbusplus::message::message unusedMsg{nullptr};
114
115 // Run startup events.
116 for (auto& group : _events)
117 {
Brad Bishop12f8a3c2017-02-09 00:02:00 -0500118 for (auto pEvent : std::get<std::vector<EventBasePtr>>(
Brad Bishop3e4a19a2017-01-21 22:17:09 -0500119 group))
120 {
121 if (pEvent->type ==
Brad Bishop12f8a3c2017-02-09 00:02:00 -0500122 Event::Type::STARTUP)
Brad Bishop3e4a19a2017-01-21 22:17:09 -0500123 {
124 handleEvent(unusedMsg, *pEvent, group);
125 }
126 }
127 }
128
Brad Bishop7b337772017-01-12 16:11:24 -0500129 while (!_shutdown)
130 {
131 try
132 {
Brad Bishop49aefb32016-10-19 11:54:14 -0400133 _bus.process_discard();
Brad Bishop24424982017-01-13 16:37:14 -0500134 _bus.wait((5000000us).count());
Brad Bishop49aefb32016-10-19 11:54:14 -0400135 }
Brad Bishop7b337772017-01-12 16:11:24 -0500136 catch (const std::exception& e)
137 {
Brad Bishop49aefb32016-10-19 11:54:14 -0400138 std::cerr << e.what() << std::endl;
139 }
140 }
141}
142
Brad Bishop03f4cd92017-02-03 15:17:21 -0500143void Manager::notify(std::map<sdbusplus::message::object_path, Object> objs)
Brad Bishop49aefb32016-10-19 11:54:14 -0400144{
Brad Bishop7b337772017-01-12 16:11:24 -0500145 try
146 {
Brad Bishop03f4cd92017-02-03 15:17:21 -0500147 createObjects(objs);
Brad Bishop49aefb32016-10-19 11:54:14 -0400148 }
Brad Bishop7b337772017-01-12 16:11:24 -0500149 catch (const std::exception& e)
150 {
Brad Bishop49aefb32016-10-19 11:54:14 -0400151 std::cerr << e.what() << std::endl;
152 }
153}
154
Brad Bishop48547a82017-01-19 15:12:50 -0500155void Manager::handleEvent(
Brad Bishop7b337772017-01-12 16:11:24 -0500156 sdbusplus::message::message& msg,
Brad Bishop12f8a3c2017-02-09 00:02:00 -0500157 const Event& event,
Brad Bishop7b337772017-01-12 16:11:24 -0500158 const EventInfo& info)
Brad Bishop49aefb32016-10-19 11:54:14 -0400159{
Brad Bishop7b337772017-01-12 16:11:24 -0500160 auto& actions = std::get<1>(info);
Brad Bishop3d57f502016-10-19 12:18:41 -0400161
Brad Bishop48547a82017-01-19 15:12:50 -0500162 for (auto& f : event)
Brad Bishop7b337772017-01-12 16:11:24 -0500163 {
Brad Bishop07934a62017-02-08 23:34:59 -0500164 if (!f(_bus, msg, *this))
Brad Bishop7b337772017-01-12 16:11:24 -0500165 {
Brad Bishop064c94a2017-01-21 21:33:30 -0500166 return;
Brad Bishop7b337772017-01-12 16:11:24 -0500167 }
Brad Bishop3d57f502016-10-19 12:18:41 -0400168 }
Brad Bishop064c94a2017-01-21 21:33:30 -0500169 for (auto& action : actions)
170 {
Brad Bishop07934a62017-02-08 23:34:59 -0500171 action(_bus, *this);
Brad Bishop064c94a2017-01-21 21:33:30 -0500172 }
Brad Bishop49aefb32016-10-19 11:54:14 -0400173}
174
Brad Bishop7b7e7122017-01-21 21:21:46 -0500175void Manager::destroyObjects(
176 const std::vector<const char*>& paths)
Brad Bishop656a7d02016-10-19 22:20:02 -0400177{
Brad Bishopa5cc34c2017-02-03 20:57:36 -0500178 std::string p;
179
Brad Bishop7b7e7122017-01-21 21:21:46 -0500180 for (const auto& path : paths)
181 {
Brad Bishopa5cc34c2017-02-03 20:57:36 -0500182 p.assign(_root);
183 p.append(path);
184 _bus.emit_object_removed(p.c_str());
185 _refs.erase(p);
Brad Bishop7b7e7122017-01-21 21:21:46 -0500186 }
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 {
Brad Bishop9bbfcb12017-02-04 10:51:06 -0500196 try
Brad Bishopeb68a682017-01-22 00:58:54 -0500197 {
Brad Bishop9bbfcb12017-02-04 10:51:06 -0500198 auto& relPath = o.first;
199 auto& ifaces = o.second;
Brad Bishopeb68a682017-01-22 00:58:54 -0500200
Brad Bishop9bbfcb12017-02-04 10:51:06 -0500201 absPath.assign(_root);
202 absPath.append(relPath);
Brad Bishopeb68a682017-01-22 00:58:54 -0500203
Brad Bishop9bbfcb12017-02-04 10:51:06 -0500204 auto obj = _refs.find(absPath);
205 if (obj != _refs.end())
Brad Bishopeb68a682017-01-22 00:58:54 -0500206 {
Brad Bishop9bbfcb12017-02-04 10:51:06 -0500207 // This object already exists...skip.
Brad Bishopeb68a682017-01-22 00:58:54 -0500208 continue;
209 }
210
Brad Bishop9bbfcb12017-02-04 10:51:06 -0500211 // Create an interface holder for each interface
212 // provided by the client and group them into
213 // a container.
214 InterfaceComposite ref;
Brad Bishopeb68a682017-01-22 00:58:54 -0500215
Brad Bishop9bbfcb12017-02-04 10:51:06 -0500216 for (auto& iface : ifaces)
217 {
218 auto& props = iface.second;
219 auto pMakers = _makers.find(iface.first.c_str());
220
221 if (pMakers == _makers.end())
222 {
223 // This interface is not known.
224 continue;
225 }
226
227 auto& maker = std::get<MakerType>(pMakers->second);
228
229 ref.emplace(
230 iface.first,
231 maker(
232 _bus,
233 absPath.c_str(),
234 props));
235 }
236
237 if (!ref.empty())
238 {
239 // Hang on to a reference to the object (interfaces)
240 // so it stays on the bus, and so we can make calls
241 // to it if needed.
242 _refs.emplace(
243 absPath, std::move(ref));
244 _bus.emit_object_added(absPath.c_str());
245 }
Brad Bishopeb68a682017-01-22 00:58:54 -0500246 }
Brad Bishop9bbfcb12017-02-04 10:51:06 -0500247 catch (const std::exception& e)
Brad Bishopeb68a682017-01-22 00:58:54 -0500248 {
Brad Bishop9bbfcb12017-02-04 10:51:06 -0500249 logging::log<logging::level::ERR>(e.what());
Brad Bishopeb68a682017-01-22 00:58:54 -0500250 }
251 }
252}
253
Brad Bishop150147a2017-02-08 23:57:46 -0500254any_ns::any& Manager::getInterfaceHolder(
Brad Bishop7b337772017-01-12 16:11:24 -0500255 const char* path, const char* interface)
Brad Bishopb83a21e2016-11-30 13:43:37 -0500256{
Brad Bishop150147a2017-02-08 23:57:46 -0500257 return const_cast<any_ns::any&>(
258 const_cast<const Manager*>(
259 this)->getInterfaceHolder(path, interface));
Brad Bishopb83a21e2016-11-30 13:43:37 -0500260}
261
Brad Bishop150147a2017-02-08 23:57:46 -0500262const any_ns::any& Manager::getInterfaceHolder(
Brad Bishop7b337772017-01-12 16:11:24 -0500263 const char* path, const char* interface) const
Brad Bishopb83a21e2016-11-30 13:43:37 -0500264{
265 std::string p{path};
266 auto oit = _refs.find(_root + p);
Brad Bishop7b337772017-01-12 16:11:24 -0500267 if (oit == _refs.end())
Brad Bishopb83a21e2016-11-30 13:43:37 -0500268 throw std::runtime_error(
Brad Bishop7b337772017-01-12 16:11:24 -0500269 _root + p + " was not found");
Brad Bishopb83a21e2016-11-30 13:43:37 -0500270
Brad Bishop7b337772017-01-12 16:11:24 -0500271 auto& obj = oit->second;
Brad Bishopb83a21e2016-11-30 13:43:37 -0500272 auto iit = obj.find(interface);
Brad Bishop7b337772017-01-12 16:11:24 -0500273 if (iit == obj.end())
Brad Bishopb83a21e2016-11-30 13:43:37 -0500274 throw std::runtime_error(
Brad Bishop7b337772017-01-12 16:11:24 -0500275 "interface was not found");
Brad Bishopb83a21e2016-11-30 13:43:37 -0500276
Brad Bishop150147a2017-02-08 23:57:46 -0500277 return iit->second;
Brad Bishopb83a21e2016-11-30 13:43:37 -0500278}
279
Brad Bishop49aefb32016-10-19 11:54:14 -0400280} // namespace manager
281} // namespace inventory
282} // namespace phosphor
283
284// vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4