blob: c516d4010df66004cb0058b7e8adb08a2a00bef8 [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 */
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 Bishop68c80832016-11-29 16:41:32 -050042 mgr.signal(
Brad Bishop7b337772017-01-12 16:11:24 -050043 msg,
44 static_cast<const details::DbusSignal&>(
45 *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
56} // namespace details
57
58Manager::Manager(
Brad Bishop7b337772017-01-12 16:11:24 -050059 sdbusplus::bus::bus&& bus,
60 const char* busname,
61 const char* root,
62 const char* iface) :
Brad Bishop451f8d92016-11-21 14:15:19 -050063 details::ServerObject<details::ManagerIface>(bus, root),
Brad Bishop49aefb32016-10-19 11:54:14 -040064 _shutdown(false),
65 _root(root),
66 _bus(std::move(bus)),
67 _manager(sdbusplus::server::manager::manager(_bus, root))
68{
Brad Bishop7b337772017-01-12 16:11:24 -050069 for (auto& group : _events)
Brad Bishop68c80832016-11-29 16:41:32 -050070 {
Brad Bishop7b337772017-01-12 16:11:24 -050071 for (auto pEvent : std::get<0>(group))
Brad Bishop68c80832016-11-29 16:41:32 -050072 {
73 if (pEvent->type !=
Brad Bishop7b337772017-01-12 16:11:24 -050074 details::Event::Type::DBUS_SIGNAL)
75 {
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 Bishop7b337772017-01-12 16:11:24 -050080 auto dbusEvent = static_cast<details::DbusSignal*>(
81 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,
97 std::get<0>(*dbusEvent),
98 details::_signal,
99 _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 Bishop7b337772017-01-12 16:11:24 -0500113 while (!_shutdown)
114 {
115 try
116 {
Brad Bishop49aefb32016-10-19 11:54:14 -0400117 _bus.process_discard();
118 _bus.wait(5000000);
119 }
Brad Bishop7b337772017-01-12 16:11:24 -0500120 catch (const std::exception& e)
121 {
Brad Bishop49aefb32016-10-19 11:54:14 -0400122 std::cerr << e.what() << std::endl;
123 }
124 }
125}
126
127void Manager::notify(std::string path, Object object)
128{
Brad Bishop7b337772017-01-12 16:11:24 -0500129 try
130 {
131 if (object.cbegin() == object.cend())
Brad Bishop49aefb32016-10-19 11:54:14 -0400132 throw std::runtime_error(
Brad Bishop7b337772017-01-12 16:11:24 -0500133 "No interfaces in " + path);
Brad Bishop49aefb32016-10-19 11:54:14 -0400134
Brad Bishop49aefb32016-10-19 11:54:14 -0400135 path.insert(0, _root);
136
137 auto obj = _refs.find(path);
Brad Bishop7b337772017-01-12 16:11:24 -0500138 if (obj != _refs.end())
Brad Bishop49aefb32016-10-19 11:54:14 -0400139 throw std::runtime_error(
Brad Bishop7b337772017-01-12 16:11:24 -0500140 obj->first + " already exists");
Brad Bishop49aefb32016-10-19 11:54:14 -0400141
142 // Create an interface holder for each interface
143 // provided by the client and group them into
144 // a container.
145 InterfaceComposite ref;
146
Brad Bishop7b337772017-01-12 16:11:24 -0500147 for (auto& x : object)
148 {
Brad Bishop5fbaa7f2016-10-31 10:42:41 -0500149 auto maker = _makers.find(x.first.c_str());
Brad Bishop49aefb32016-10-19 11:54:14 -0400150
Brad Bishop7b337772017-01-12 16:11:24 -0500151 if (maker == _makers.end())
Brad Bishop49aefb32016-10-19 11:54:14 -0400152 throw std::runtime_error(
Brad Bishop7b337772017-01-12 16:11:24 -0500153 "Unimplemented interface: " + x.first);
Brad Bishop49aefb32016-10-19 11:54:14 -0400154
Brad Bishop1ab880a2016-12-05 15:49:31 -0500155 ref.emplace(x.first,
Brad Bishop7b337772017-01-12 16:11:24 -0500156 (maker->second)(_bus, path.c_str()));
Brad Bishop49aefb32016-10-19 11:54:14 -0400157 }
158
159 // Hang on to a reference to the object (interfaces)
160 // so it stays on the bus, and so we can make calls
161 // to it if needed.
162 _refs.emplace(
Brad Bishop7b337772017-01-12 16:11:24 -0500163 path, std::move(ref));
Brad Bishop49aefb32016-10-19 11:54:14 -0400164 }
Brad Bishop7b337772017-01-12 16:11:24 -0500165 catch (const std::exception& e)
166 {
Brad Bishop49aefb32016-10-19 11:54:14 -0400167 std::cerr << e.what() << std::endl;
168 }
169}
170
Brad Bishop68c80832016-11-29 16:41:32 -0500171void Manager::signal(
Brad Bishop7b337772017-01-12 16:11:24 -0500172 sdbusplus::message::message& msg,
173 const details::DbusSignal& event,
174 const EventInfo& info)
Brad Bishop49aefb32016-10-19 11:54:14 -0400175{
Brad Bishop7b337772017-01-12 16:11:24 -0500176 auto& filter = *std::get<1>(event);
177 auto& actions = std::get<1>(info);
Brad Bishop3d57f502016-10-19 12:18:41 -0400178
Brad Bishop7b337772017-01-12 16:11:24 -0500179 if (filter(msg, *this))
180 {
181 for (auto& action : actions)
182 {
Brad Bishop90074322016-11-29 13:05:57 -0500183 (*action)(*this);
Brad Bishop7b337772017-01-12 16:11:24 -0500184 }
Brad Bishop3d57f502016-10-19 12:18:41 -0400185 }
Brad Bishop49aefb32016-10-19 11:54:14 -0400186}
187
Brad Bishop7b337772017-01-12 16:11:24 -0500188void Manager::destroyObject(const char* path)
Brad Bishop656a7d02016-10-19 22:20:02 -0400189{
190 std::string p{path};
191 _refs.erase(_root + p);
192}
193
Brad Bishopb83a21e2016-11-30 13:43:37 -0500194details::holder::Base& Manager::getInterfaceHolder(
Brad Bishop7b337772017-01-12 16:11:24 -0500195 const char* path, const char* interface)
Brad Bishopb83a21e2016-11-30 13:43:37 -0500196{
Brad Bishop7b337772017-01-12 16:11:24 -0500197 return const_cast<const Manager*>(
198 this)->getInterfaceHolder(path, interface);
Brad Bishopb83a21e2016-11-30 13:43:37 -0500199}
200
201details::holder::Base& Manager::getInterfaceHolder(
Brad Bishop7b337772017-01-12 16:11:24 -0500202 const char* path, const char* interface) const
Brad Bishopb83a21e2016-11-30 13:43:37 -0500203{
204 std::string p{path};
205 auto oit = _refs.find(_root + p);
Brad Bishop7b337772017-01-12 16:11:24 -0500206 if (oit == _refs.end())
Brad Bishopb83a21e2016-11-30 13:43:37 -0500207 throw std::runtime_error(
Brad Bishop7b337772017-01-12 16:11:24 -0500208 _root + p + " was not found");
Brad Bishopb83a21e2016-11-30 13:43:37 -0500209
Brad Bishop7b337772017-01-12 16:11:24 -0500210 auto& obj = oit->second;
Brad Bishopb83a21e2016-11-30 13:43:37 -0500211 auto iit = obj.find(interface);
Brad Bishop7b337772017-01-12 16:11:24 -0500212 if (iit == obj.end())
Brad Bishopb83a21e2016-11-30 13:43:37 -0500213 throw std::runtime_error(
Brad Bishop7b337772017-01-12 16:11:24 -0500214 "interface was not found");
Brad Bishopb83a21e2016-11-30 13:43:37 -0500215
216 return *iit->second;
217}
218
Brad Bishop49aefb32016-10-19 11:54:14 -0400219} // namespace manager
220} // namespace inventory
221} // namespace phosphor
222
223// vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4