blob: 264037fa8a50b762bcf46cf6cea9aebaf8a7f3f5 [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 Bishop68c80832016-11-29 16:41:32 -050045 mgr.signal(
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 Bishop7b337772017-01-12 16:11:24 -050074 for (auto pEvent : std::get<0>(group))
Brad Bishop68c80832016-11-29 16:41:32 -050075 {
76 if (pEvent->type !=
Brad Bishop7b337772017-01-12 16:11:24 -050077 details::Event::Type::DBUS_SIGNAL)
78 {
Brad Bishop68c80832016-11-29 16:41:32 -050079 continue;
Brad Bishop7b337772017-01-12 16:11:24 -050080 }
Brad Bishop4f20a3e2016-11-29 15:21:46 -050081
Brad Bishop68c80832016-11-29 16:41:32 -050082 // Create a callback context for this event group.
Brad Bishop7b337772017-01-12 16:11:24 -050083 auto dbusEvent = static_cast<details::DbusSignal*>(
84 pEvent.get());
Brad Bishop68c80832016-11-29 16:41:32 -050085
86 // Go ahead and store an iterator pointing at
87 // the event data to avoid lookups later since
88 // additional signal callbacks aren't added
89 // after the manager is constructed.
90 _sigargs.emplace_back(
Brad Bishop7b337772017-01-12 16:11:24 -050091 std::make_unique<SigArg>(
92 this,
93 dbusEvent,
94 &group));
Brad Bishop68c80832016-11-29 16:41:32 -050095
96 // Register our callback and the context for
97 // each signal event.
98 _matches.emplace_back(
Brad Bishop7b337772017-01-12 16:11:24 -050099 _bus,
100 std::get<0>(*dbusEvent),
101 details::_signal,
102 _sigargs.back().get());
Brad Bishop68c80832016-11-29 16:41:32 -0500103 }
Brad Bishop49aefb32016-10-19 11:54:14 -0400104 }
105
106 _bus.request_name(busname);
107}
108
109void Manager::shutdown() noexcept
110{
111 _shutdown = true;
112}
113
114void Manager::run() noexcept
115{
Brad Bishop7b337772017-01-12 16:11:24 -0500116 while (!_shutdown)
117 {
118 try
119 {
Brad Bishop49aefb32016-10-19 11:54:14 -0400120 _bus.process_discard();
Brad Bishop24424982017-01-13 16:37:14 -0500121 _bus.wait((5000000us).count());
Brad Bishop49aefb32016-10-19 11:54:14 -0400122 }
Brad Bishop7b337772017-01-12 16:11:24 -0500123 catch (const std::exception& e)
124 {
Brad Bishop49aefb32016-10-19 11:54:14 -0400125 std::cerr << e.what() << std::endl;
126 }
127 }
128}
129
Brad Bishop9aa5e2f2017-01-15 19:45:40 -0500130void Manager::notify(sdbusplus::message::object_path path, Object object)
Brad Bishop49aefb32016-10-19 11:54:14 -0400131{
Brad Bishop7b337772017-01-12 16:11:24 -0500132 try
133 {
Brad Bishop9aa5e2f2017-01-15 19:45:40 -0500134
Brad Bishop7b337772017-01-12 16:11:24 -0500135 if (object.cbegin() == object.cend())
Brad Bishop49aefb32016-10-19 11:54:14 -0400136 throw std::runtime_error(
Brad Bishop9aa5e2f2017-01-15 19:45:40 -0500137 "No interfaces in " + path.str);
Brad Bishop49aefb32016-10-19 11:54:14 -0400138
Brad Bishop9aa5e2f2017-01-15 19:45:40 -0500139 path.str.insert(0, _root);
Brad Bishop49aefb32016-10-19 11:54:14 -0400140
141 auto obj = _refs.find(path);
Brad Bishop7b337772017-01-12 16:11:24 -0500142 if (obj != _refs.end())
Brad Bishop49aefb32016-10-19 11:54:14 -0400143 throw std::runtime_error(
Brad Bishop7b337772017-01-12 16:11:24 -0500144 obj->first + " already exists");
Brad Bishop49aefb32016-10-19 11:54:14 -0400145
146 // Create an interface holder for each interface
147 // provided by the client and group them into
148 // a container.
149 InterfaceComposite ref;
150
Brad Bishop6676c122017-01-15 20:38:39 -0500151 auto i = object.size();
Brad Bishop7b337772017-01-12 16:11:24 -0500152 for (auto& x : object)
153 {
Brad Bishop6676c122017-01-15 20:38:39 -0500154 // Defer sending any signals until the last interface.
155 auto deferSignals = --i != 0;
Brad Bishop5fbaa7f2016-10-31 10:42:41 -0500156 auto maker = _makers.find(x.first.c_str());
Brad Bishop49aefb32016-10-19 11:54:14 -0400157
Brad Bishop7b337772017-01-12 16:11:24 -0500158 if (maker == _makers.end())
Brad Bishop49aefb32016-10-19 11:54:14 -0400159 throw std::runtime_error(
Brad Bishop7b337772017-01-12 16:11:24 -0500160 "Unimplemented interface: " + x.first);
Brad Bishop49aefb32016-10-19 11:54:14 -0400161
Brad Bishop1ab880a2016-12-05 15:49:31 -0500162 ref.emplace(x.first,
Brad Bishop6676c122017-01-15 20:38:39 -0500163 (maker->second)(_bus, path.str.c_str(), deferSignals));
Brad Bishop49aefb32016-10-19 11:54:14 -0400164 }
165
Brad Bishop9d10fb22017-01-15 20:15:20 -0500166 if (!ref.empty())
167 {
168 // Hang on to a reference to the object (interfaces)
169 // so it stays on the bus, and so we can make calls
170 // to it if needed.
171 _refs.emplace(
172 path, std::move(ref));
173 }
Brad Bishop49aefb32016-10-19 11:54:14 -0400174 }
Brad Bishop7b337772017-01-12 16:11:24 -0500175 catch (const std::exception& e)
176 {
Brad Bishop49aefb32016-10-19 11:54:14 -0400177 std::cerr << e.what() << std::endl;
178 }
179}
180
Brad Bishop68c80832016-11-29 16:41:32 -0500181void Manager::signal(
Brad Bishop7b337772017-01-12 16:11:24 -0500182 sdbusplus::message::message& msg,
183 const details::DbusSignal& event,
184 const EventInfo& info)
Brad Bishop49aefb32016-10-19 11:54:14 -0400185{
Brad Bishop7b337772017-01-12 16:11:24 -0500186 auto& filter = *std::get<1>(event);
187 auto& actions = std::get<1>(info);
Brad Bishop3d57f502016-10-19 12:18:41 -0400188
Brad Bishop7b337772017-01-12 16:11:24 -0500189 if (filter(msg, *this))
190 {
191 for (auto& action : actions)
192 {
Brad Bishop90074322016-11-29 13:05:57 -0500193 (*action)(*this);
Brad Bishop7b337772017-01-12 16:11:24 -0500194 }
Brad Bishop3d57f502016-10-19 12:18:41 -0400195 }
Brad Bishop49aefb32016-10-19 11:54:14 -0400196}
197
Brad Bishop7b337772017-01-12 16:11:24 -0500198void Manager::destroyObject(const char* path)
Brad Bishop656a7d02016-10-19 22:20:02 -0400199{
200 std::string p{path};
201 _refs.erase(_root + p);
202}
203
Brad Bishopb83a21e2016-11-30 13:43:37 -0500204details::holder::Base& Manager::getInterfaceHolder(
Brad Bishop7b337772017-01-12 16:11:24 -0500205 const char* path, const char* interface)
Brad Bishopb83a21e2016-11-30 13:43:37 -0500206{
Brad Bishop7b337772017-01-12 16:11:24 -0500207 return const_cast<const Manager*>(
208 this)->getInterfaceHolder(path, interface);
Brad Bishopb83a21e2016-11-30 13:43:37 -0500209}
210
211details::holder::Base& Manager::getInterfaceHolder(
Brad Bishop7b337772017-01-12 16:11:24 -0500212 const char* path, const char* interface) const
Brad Bishopb83a21e2016-11-30 13:43:37 -0500213{
214 std::string p{path};
215 auto oit = _refs.find(_root + p);
Brad Bishop7b337772017-01-12 16:11:24 -0500216 if (oit == _refs.end())
Brad Bishopb83a21e2016-11-30 13:43:37 -0500217 throw std::runtime_error(
Brad Bishop7b337772017-01-12 16:11:24 -0500218 _root + p + " was not found");
Brad Bishopb83a21e2016-11-30 13:43:37 -0500219
Brad Bishop7b337772017-01-12 16:11:24 -0500220 auto& obj = oit->second;
Brad Bishopb83a21e2016-11-30 13:43:37 -0500221 auto iit = obj.find(interface);
Brad Bishop7b337772017-01-12 16:11:24 -0500222 if (iit == obj.end())
Brad Bishopb83a21e2016-11-30 13:43:37 -0500223 throw std::runtime_error(
Brad Bishop7b337772017-01-12 16:11:24 -0500224 "interface was not found");
Brad Bishopb83a21e2016-11-30 13:43:37 -0500225
226 return *iit->second;
227}
228
Brad Bishop49aefb32016-10-19 11:54:14 -0400229} // namespace manager
230} // namespace inventory
231} // namespace phosphor
232
233// vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4