blob: 1d1f778954a3d98e7c4074e373ff82c656a245a6 [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{
Brad Bishop49aefb32016-10-19 11:54:14 -040029/** @brief Fowrarding signal callback.
30 *
31 * Extracts per-signal specific context and forwards the call to the manager
32 * instance.
33 */
Brad Bishop7b337772017-01-12 16:11:24 -050034auto _signal(sd_bus_message* m, void* data, sd_bus_error* e) noexcept
Brad Bishop49aefb32016-10-19 11:54:14 -040035{
Brad Bishop7b337772017-01-12 16:11:24 -050036 try
37 {
Brad Bishop49aefb32016-10-19 11:54:14 -040038 auto msg = sdbusplus::message::message(m);
Brad Bishop7b337772017-01-12 16:11:24 -050039 auto& args = *static_cast<Manager::SigArg*>(data);
Brad Bishop49aefb32016-10-19 11:54:14 -040040 sd_bus_message_ref(m);
Brad Bishop7b337772017-01-12 16:11:24 -050041 auto& mgr = *std::get<0>(args);
Brad Bishop48547a82017-01-19 15:12:50 -050042 mgr.handleEvent(
Brad Bishop7b337772017-01-12 16:11:24 -050043 msg,
Brad Bishop12f8a3c2017-02-09 00:02:00 -050044 static_cast<const DbusSignal&>(
Brad Bishop7b337772017-01-12 16:11:24 -050045 *std::get<1>(args)),
46 *std::get<2>(args));
Brad Bishop49aefb32016-10-19 11:54:14 -040047 }
Brad Bishop7b337772017-01-12 16:11:24 -050048 catch (const std::exception& e)
49 {
Brad Bishop49aefb32016-10-19 11:54:14 -040050 std::cerr << e.what() << std::endl;
51 }
52
53 return 0;
54}
55
Brad Bishop49aefb32016-10-19 11:54:14 -040056Manager::Manager(
Brad Bishop7b337772017-01-12 16:11:24 -050057 sdbusplus::bus::bus&& bus,
58 const char* busname,
59 const char* root,
60 const char* iface) :
Brad Bishop12f8a3c2017-02-09 00:02:00 -050061 ServerObject<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 Bishop7b337772017-01-12 16:11:24 -050067 for (auto& group : _events)
Brad Bishop68c80832016-11-29 16:41:32 -050068 {
Brad Bishop12f8a3c2017-02-09 00:02:00 -050069 for (auto pEvent : std::get<std::vector<EventBasePtr>>(
Brad Bishop48547a82017-01-19 15:12:50 -050070 group))
Brad Bishop68c80832016-11-29 16:41:32 -050071 {
72 if (pEvent->type !=
Brad Bishop12f8a3c2017-02-09 00:02:00 -050073 Event::Type::DBUS_SIGNAL)
Brad Bishop7b337772017-01-12 16:11:24 -050074 {
Brad Bishop68c80832016-11-29 16:41:32 -050075 continue;
Brad Bishop7b337772017-01-12 16:11:24 -050076 }
Brad Bishop4f20a3e2016-11-29 15:21:46 -050077
Brad Bishop68c80832016-11-29 16:41:32 -050078 // Create a callback context for this event group.
Brad Bishop12f8a3c2017-02-09 00:02:00 -050079 auto dbusEvent = static_cast<DbusSignal*>(
Brad Bishop7b337772017-01-12 16:11:24 -050080 pEvent.get());
Brad Bishop68c80832016-11-29 16:41:32 -050081
82 // Go ahead and store an iterator pointing at
83 // the event data to avoid lookups later since
84 // additional signal callbacks aren't added
85 // after the manager is constructed.
86 _sigargs.emplace_back(
Brad Bishop7b337772017-01-12 16:11:24 -050087 std::make_unique<SigArg>(
88 this,
89 dbusEvent,
90 &group));
Brad Bishop68c80832016-11-29 16:41:32 -050091
92 // Register our callback and the context for
93 // each signal event.
94 _matches.emplace_back(
Brad Bishop7b337772017-01-12 16:11:24 -050095 _bus,
Brad Bishop48547a82017-01-19 15:12:50 -050096 dbusEvent->signature,
Brad Bishop12f8a3c2017-02-09 00:02:00 -050097 _signal,
Brad Bishop7b337772017-01-12 16:11:24 -050098 _sigargs.back().get());
Brad Bishop68c80832016-11-29 16:41:32 -050099 }
Brad Bishop49aefb32016-10-19 11:54:14 -0400100 }
101
102 _bus.request_name(busname);
103}
104
105void Manager::shutdown() noexcept
106{
107 _shutdown = true;
108}
109
110void Manager::run() noexcept
111{
Brad Bishop3e4a19a2017-01-21 22:17:09 -0500112 sdbusplus::message::message unusedMsg{nullptr};
113
114 // Run startup events.
115 for (auto& group : _events)
116 {
Brad Bishop12f8a3c2017-02-09 00:02:00 -0500117 for (auto pEvent : std::get<std::vector<EventBasePtr>>(
Brad Bishop3e4a19a2017-01-21 22:17:09 -0500118 group))
119 {
120 if (pEvent->type ==
Brad Bishop12f8a3c2017-02-09 00:02:00 -0500121 Event::Type::STARTUP)
Brad Bishop3e4a19a2017-01-21 22:17:09 -0500122 {
123 handleEvent(unusedMsg, *pEvent, group);
124 }
125 }
126 }
127
Brad Bishop7b337772017-01-12 16:11:24 -0500128 while (!_shutdown)
129 {
130 try
131 {
Brad Bishop49aefb32016-10-19 11:54:14 -0400132 _bus.process_discard();
Brad Bishop24424982017-01-13 16:37:14 -0500133 _bus.wait((5000000us).count());
Brad Bishop49aefb32016-10-19 11:54:14 -0400134 }
Brad Bishop7b337772017-01-12 16:11:24 -0500135 catch (const std::exception& e)
136 {
Brad Bishop49aefb32016-10-19 11:54:14 -0400137 std::cerr << e.what() << std::endl;
138 }
139 }
140}
141
Brad Bishop03f4cd92017-02-03 15:17:21 -0500142void Manager::notify(std::map<sdbusplus::message::object_path, Object> objs)
Brad Bishop49aefb32016-10-19 11:54:14 -0400143{
Brad Bishop7b337772017-01-12 16:11:24 -0500144 try
145 {
Brad Bishop03f4cd92017-02-03 15:17:21 -0500146 createObjects(objs);
Brad Bishop49aefb32016-10-19 11:54:14 -0400147 }
Brad Bishop7b337772017-01-12 16:11:24 -0500148 catch (const std::exception& e)
149 {
Brad Bishop49aefb32016-10-19 11:54:14 -0400150 std::cerr << e.what() << std::endl;
151 }
152}
153
Brad Bishop48547a82017-01-19 15:12:50 -0500154void Manager::handleEvent(
Brad Bishop7b337772017-01-12 16:11:24 -0500155 sdbusplus::message::message& msg,
Brad Bishop12f8a3c2017-02-09 00:02:00 -0500156 const Event& event,
Brad Bishop7b337772017-01-12 16:11:24 -0500157 const EventInfo& info)
Brad Bishop49aefb32016-10-19 11:54:14 -0400158{
Brad Bishop7b337772017-01-12 16:11:24 -0500159 auto& actions = std::get<1>(info);
Brad Bishop3d57f502016-10-19 12:18:41 -0400160
Brad Bishop48547a82017-01-19 15:12:50 -0500161 for (auto& f : event)
Brad Bishop7b337772017-01-12 16:11:24 -0500162 {
Brad Bishop07934a62017-02-08 23:34:59 -0500163 if (!f(_bus, msg, *this))
Brad Bishop7b337772017-01-12 16:11:24 -0500164 {
Brad Bishop064c94a2017-01-21 21:33:30 -0500165 return;
Brad Bishop7b337772017-01-12 16:11:24 -0500166 }
Brad Bishop3d57f502016-10-19 12:18:41 -0400167 }
Brad Bishop064c94a2017-01-21 21:33:30 -0500168 for (auto& action : actions)
169 {
Brad Bishop07934a62017-02-08 23:34:59 -0500170 action(_bus, *this);
Brad Bishop064c94a2017-01-21 21:33:30 -0500171 }
Brad Bishop49aefb32016-10-19 11:54:14 -0400172}
173
Brad Bishop7b7e7122017-01-21 21:21:46 -0500174void Manager::destroyObjects(
175 const std::vector<const char*>& paths)
Brad Bishop656a7d02016-10-19 22:20:02 -0400176{
Brad Bishopa5cc34c2017-02-03 20:57:36 -0500177 std::string p;
178
Brad Bishop7b7e7122017-01-21 21:21:46 -0500179 for (const auto& path : paths)
180 {
Brad Bishopa5cc34c2017-02-03 20:57:36 -0500181 p.assign(_root);
182 p.append(path);
183 _bus.emit_object_removed(p.c_str());
184 _refs.erase(p);
Brad Bishop7b7e7122017-01-21 21:21:46 -0500185 }
Brad Bishop656a7d02016-10-19 22:20:02 -0400186}
187
Brad Bishopeb68a682017-01-22 00:58:54 -0500188void Manager::createObjects(
189 const std::map<sdbusplus::message::object_path, Object>& objs)
190{
191 std::string absPath;
192
193 for (auto& o : objs)
194 {
195 auto& relPath = o.first;
196 auto& ifaces = o.second;
197
198 absPath.assign(_root);
199 absPath.append(relPath);
200
201 auto obj = _refs.find(absPath);
202 if (obj != _refs.end())
203 {
204 // This object already exists...skip.
205 continue;
206 }
207
208 // Create an interface holder for each interface
209 // provided by the client and group them into
210 // a container.
211 InterfaceComposite ref;
212
Brad Bishopeb68a682017-01-22 00:58:54 -0500213 for (auto& iface : ifaces)
214 {
215 auto& props = iface.second;
Brad Bishopeb68a682017-01-22 00:58:54 -0500216 auto pMakers = _makers.find(iface.first.c_str());
217
218 if (pMakers == _makers.end())
219 {
220 // This interface is not known.
221 continue;
222 }
223
224 auto& maker = std::get<MakerType>(pMakers->second);
225
226 ref.emplace(
227 iface.first,
228 maker(
229 _bus,
230 absPath.c_str(),
Brad Bishopa5cc34c2017-02-03 20:57:36 -0500231 props));
Brad Bishopeb68a682017-01-22 00:58:54 -0500232 }
233
234 if (!ref.empty())
235 {
236 // Hang on to a reference to the object (interfaces)
237 // so it stays on the bus, and so we can make calls
238 // to it if needed.
239 _refs.emplace(
240 absPath, std::move(ref));
Brad Bishopa5cc34c2017-02-03 20:57:36 -0500241 _bus.emit_object_added(absPath.c_str());
Brad Bishopeb68a682017-01-22 00:58:54 -0500242 }
243 }
244}
245
Brad Bishop150147a2017-02-08 23:57:46 -0500246any_ns::any& Manager::getInterfaceHolder(
Brad Bishop7b337772017-01-12 16:11:24 -0500247 const char* path, const char* interface)
Brad Bishopb83a21e2016-11-30 13:43:37 -0500248{
Brad Bishop150147a2017-02-08 23:57:46 -0500249 return const_cast<any_ns::any&>(
250 const_cast<const Manager*>(
251 this)->getInterfaceHolder(path, interface));
Brad Bishopb83a21e2016-11-30 13:43:37 -0500252}
253
Brad Bishop150147a2017-02-08 23:57:46 -0500254const any_ns::any& Manager::getInterfaceHolder(
Brad Bishop7b337772017-01-12 16:11:24 -0500255 const char* path, const char* interface) const
Brad Bishopb83a21e2016-11-30 13:43:37 -0500256{
257 std::string p{path};
258 auto oit = _refs.find(_root + p);
Brad Bishop7b337772017-01-12 16:11:24 -0500259 if (oit == _refs.end())
Brad Bishopb83a21e2016-11-30 13:43:37 -0500260 throw std::runtime_error(
Brad Bishop7b337772017-01-12 16:11:24 -0500261 _root + p + " was not found");
Brad Bishopb83a21e2016-11-30 13:43:37 -0500262
Brad Bishop7b337772017-01-12 16:11:24 -0500263 auto& obj = oit->second;
Brad Bishopb83a21e2016-11-30 13:43:37 -0500264 auto iit = obj.find(interface);
Brad Bishop7b337772017-01-12 16:11:24 -0500265 if (iit == obj.end())
Brad Bishopb83a21e2016-11-30 13:43:37 -0500266 throw std::runtime_error(
Brad Bishop7b337772017-01-12 16:11:24 -0500267 "interface was not found");
Brad Bishopb83a21e2016-11-30 13:43:37 -0500268
Brad Bishop150147a2017-02-08 23:57:46 -0500269 return iit->second;
Brad Bishopb83a21e2016-11-30 13:43:37 -0500270}
271
Brad Bishop49aefb32016-10-19 11:54:14 -0400272} // namespace manager
273} // namespace inventory
274} // namespace phosphor
275
276// vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4