149aefb31SBrad Bishop /**
249aefb31SBrad Bishop  * Copyright © 2016 IBM Corporation
349aefb31SBrad Bishop  *
449aefb31SBrad Bishop  * Licensed under the Apache License, Version 2.0 (the "License");
549aefb31SBrad Bishop  * you may not use this file except in compliance with the License.
649aefb31SBrad Bishop  * You may obtain a copy of the License at
749aefb31SBrad Bishop  *
849aefb31SBrad Bishop  *     http://www.apache.org/licenses/LICENSE-2.0
949aefb31SBrad Bishop  *
1049aefb31SBrad Bishop  * Unless required by applicable law or agreed to in writing, software
1149aefb31SBrad Bishop  * distributed under the License is distributed on an "AS IS" BASIS,
1249aefb31SBrad Bishop  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1349aefb31SBrad Bishop  * See the License for the specific language governing permissions and
1449aefb31SBrad Bishop  * limitations under the License.
1549aefb31SBrad Bishop  */
1649aefb31SBrad Bishop #include <iostream>
1749aefb31SBrad Bishop #include <exception>
1849aefb31SBrad Bishop #include "manager.hpp"
1949aefb31SBrad Bishop 
2049aefb31SBrad Bishop namespace phosphor
2149aefb31SBrad Bishop {
2249aefb31SBrad Bishop namespace inventory
2349aefb31SBrad Bishop {
2449aefb31SBrad Bishop namespace manager
2549aefb31SBrad Bishop {
2649aefb31SBrad Bishop namespace details
2749aefb31SBrad Bishop {
2849aefb31SBrad Bishop 
2949aefb31SBrad Bishop /** @brief Fowrarding signal callback.
3049aefb31SBrad Bishop  *
3149aefb31SBrad Bishop  *  Extracts per-signal specific context and forwards the call to the manager
3249aefb31SBrad Bishop  *  instance.
3349aefb31SBrad Bishop  */
3449aefb31SBrad Bishop auto _signal(sd_bus_message *m, void *data, sd_bus_error *e) noexcept
3549aefb31SBrad Bishop {
3649aefb31SBrad Bishop     try {
3749aefb31SBrad Bishop         auto msg = sdbusplus::message::message(m);
3849aefb31SBrad Bishop         auto &args = *static_cast<Manager::SigArg*>(data);
3949aefb31SBrad Bishop         sd_bus_message_ref(m);
4049aefb31SBrad Bishop         auto &mgr = *std::get<0>(args);
4168c80839SBrad Bishop         mgr.signal(
4268c80839SBrad Bishop                 msg,
4368c80839SBrad Bishop                 static_cast<const details::DbusSignal &>(
4468c80839SBrad Bishop                     *std::get<1>(args)),
4568c80839SBrad Bishop                 *std::get<2>(args));
4649aefb31SBrad Bishop     }
4749aefb31SBrad Bishop     catch (const std::exception &e) {
4849aefb31SBrad Bishop         std::cerr << e.what() << std::endl;
4949aefb31SBrad Bishop     }
5049aefb31SBrad Bishop 
5149aefb31SBrad Bishop     return 0;
5249aefb31SBrad Bishop }
5349aefb31SBrad Bishop 
5449aefb31SBrad Bishop } // namespace details
5549aefb31SBrad Bishop 
5649aefb31SBrad Bishop Manager::Manager(
5749aefb31SBrad Bishop         sdbusplus::bus::bus &&bus,
5849aefb31SBrad Bishop         const char *busname,
5949aefb31SBrad Bishop         const char *root,
6049aefb31SBrad Bishop         const char *iface) :
61451f8d93SBrad Bishop     details::ServerObject<details::ManagerIface>(bus, root),
6249aefb31SBrad Bishop     _shutdown(false),
6349aefb31SBrad Bishop     _root(root),
6449aefb31SBrad Bishop     _bus(std::move(bus)),
6549aefb31SBrad Bishop     _manager(sdbusplus::server::manager::manager(_bus, root))
6649aefb31SBrad Bishop {
6768c80839SBrad Bishop     for (auto &group: _events)
6868c80839SBrad Bishop     {
6968c80839SBrad Bishop         for (auto pEvent: std::get<0>(group))
7068c80839SBrad Bishop         {
714f20a3e3SBrad Bishop             if (pEvent->type !=
724f20a3e3SBrad Bishop                     details::Event::Type::DBUS_SIGNAL)
734f20a3e3SBrad Bishop                 continue;
744f20a3e3SBrad Bishop 
7568c80839SBrad Bishop             // Create a callback context for this event group.
7668c80839SBrad Bishop             auto dbusEvent = static_cast<details::DbusSignal *>(
7768c80839SBrad Bishop                     pEvent.get());
7868c80839SBrad Bishop 
7968c80839SBrad Bishop             // Go ahead and store an iterator pointing at
8068c80839SBrad Bishop             // the event data to avoid lookups later since
8168c80839SBrad Bishop             // additional signal callbacks aren't added
8268c80839SBrad Bishop             // after the manager is constructed.
8349aefb31SBrad Bishop             _sigargs.emplace_back(
8449aefb31SBrad Bishop                     std::make_unique<SigArg>(
8549aefb31SBrad Bishop                             this,
8668c80839SBrad Bishop                             dbusEvent,
87*1ab880a1SBrad Bishop                             &group));
8868c80839SBrad Bishop 
8949aefb31SBrad Bishop             // Register our callback and the context for
9068c80839SBrad Bishop             // each signal event.
9149aefb31SBrad Bishop             _matches.emplace_back(
9249aefb31SBrad Bishop                         _bus,
9368c80839SBrad Bishop                         std::get<0>(*dbusEvent),
9449aefb31SBrad Bishop                         details::_signal,
95*1ab880a1SBrad Bishop                         _sigargs.back().get());
9649aefb31SBrad Bishop         }
9768c80839SBrad Bishop     }
9849aefb31SBrad Bishop 
9949aefb31SBrad Bishop     _bus.request_name(busname);
10049aefb31SBrad Bishop }
10149aefb31SBrad Bishop 
10249aefb31SBrad Bishop void Manager::shutdown() noexcept
10349aefb31SBrad Bishop {
10449aefb31SBrad Bishop     _shutdown = true;
10549aefb31SBrad Bishop }
10649aefb31SBrad Bishop 
10749aefb31SBrad Bishop void Manager::run() noexcept
10849aefb31SBrad Bishop {
10949aefb31SBrad Bishop     while(!_shutdown) {
11049aefb31SBrad Bishop         try {
11149aefb31SBrad Bishop             _bus.process_discard();
11249aefb31SBrad Bishop             _bus.wait(5000000);
11349aefb31SBrad Bishop         }
11449aefb31SBrad Bishop         catch (const std::exception &e) {
11549aefb31SBrad Bishop             std::cerr << e.what() << std::endl;
11649aefb31SBrad Bishop         }
11749aefb31SBrad Bishop     }
11849aefb31SBrad Bishop }
11949aefb31SBrad Bishop 
12049aefb31SBrad Bishop void Manager::notify(std::string path, Object object)
12149aefb31SBrad Bishop {
12249aefb31SBrad Bishop     try {
12349aefb31SBrad Bishop         if(object.cbegin() == object.cend())
12449aefb31SBrad Bishop             throw std::runtime_error(
12549aefb31SBrad Bishop                     "No interfaces in " + path);
12649aefb31SBrad Bishop 
12749aefb31SBrad Bishop         path.insert(0, _root);
12849aefb31SBrad Bishop 
12949aefb31SBrad Bishop         auto obj = _refs.find(path);
13049aefb31SBrad Bishop         if(obj != _refs.end())
13149aefb31SBrad Bishop             throw std::runtime_error(
13249aefb31SBrad Bishop                     obj->first + " already exists");
13349aefb31SBrad Bishop 
13449aefb31SBrad Bishop         // Create an interface holder for each interface
13549aefb31SBrad Bishop         // provided by the client and group them into
13649aefb31SBrad Bishop         // a container.
13749aefb31SBrad Bishop         InterfaceComposite ref;
13849aefb31SBrad Bishop 
13949aefb31SBrad Bishop         for (auto &x: object) {
1405fbaa7feSBrad Bishop             auto maker = _makers.find(x.first.c_str());
14149aefb31SBrad Bishop 
1425fbaa7feSBrad Bishop             if(maker == _makers.end())
14349aefb31SBrad Bishop                 throw std::runtime_error(
14449aefb31SBrad Bishop                         "Unimplemented interface: " + x.first);
14549aefb31SBrad Bishop 
146*1ab880a1SBrad Bishop             ref.emplace(x.first,
147*1ab880a1SBrad Bishop                     (maker->second)(_bus, path.c_str()));
14849aefb31SBrad Bishop         }
14949aefb31SBrad Bishop 
15049aefb31SBrad Bishop         // Hang on to a reference to the object (interfaces)
15149aefb31SBrad Bishop         // so it stays on the bus, and so we can make calls
15249aefb31SBrad Bishop         // to it if needed.
15349aefb31SBrad Bishop         _refs.emplace(
154*1ab880a1SBrad Bishop                 path, std::move(ref));
15549aefb31SBrad Bishop     }
15649aefb31SBrad Bishop     catch (const std::exception &e) {
15749aefb31SBrad Bishop         std::cerr << e.what() << std::endl;
15849aefb31SBrad Bishop     }
15949aefb31SBrad Bishop }
16049aefb31SBrad Bishop 
16168c80839SBrad Bishop void Manager::signal(
16268c80839SBrad Bishop         sdbusplus::message::message &msg,
16368c80839SBrad Bishop         const details::DbusSignal &event,
16468c80839SBrad Bishop         const EventInfo &info)
16549aefb31SBrad Bishop {
16668c80839SBrad Bishop     auto &filter = *std::get<1>(event);
16768c80839SBrad Bishop     auto &actions = std::get<1>(info);
1683d57f507SBrad Bishop 
169c0eae117SBrad Bishop     if(filter(msg, *this)) {
1709007432aSBrad Bishop         for (auto &action: actions)
1719007432aSBrad Bishop             (*action)(*this);
1723d57f507SBrad Bishop     }
17349aefb31SBrad Bishop }
17449aefb31SBrad Bishop 
175656a7d00SBrad Bishop void Manager::destroyObject(const char *path)
176656a7d00SBrad Bishop {
177656a7d00SBrad Bishop     std::string p{path};
178656a7d00SBrad Bishop     _refs.erase(_root + p);
179656a7d00SBrad Bishop }
180656a7d00SBrad Bishop 
181b83a21eaSBrad Bishop details::holder::Base& Manager::getInterfaceHolder(
182b83a21eaSBrad Bishop         const char *path, const char *interface)
183b83a21eaSBrad Bishop {
184b83a21eaSBrad Bishop     return const_cast<const Manager *>(
185b83a21eaSBrad Bishop             this)->getInterfaceHolder(path, interface);
186b83a21eaSBrad Bishop }
187b83a21eaSBrad Bishop 
188b83a21eaSBrad Bishop details::holder::Base& Manager::getInterfaceHolder(
189b83a21eaSBrad Bishop         const char *path, const char *interface) const
190b83a21eaSBrad Bishop {
191b83a21eaSBrad Bishop     std::string p{path};
192b83a21eaSBrad Bishop     auto oit = _refs.find(_root + p);
193b83a21eaSBrad Bishop     if(oit == _refs.end())
194b83a21eaSBrad Bishop         throw std::runtime_error(
195b83a21eaSBrad Bishop                 _root + p + " was not found");
196b83a21eaSBrad Bishop 
197b83a21eaSBrad Bishop     auto &obj = oit->second;
198b83a21eaSBrad Bishop     auto iit = obj.find(interface);
199b83a21eaSBrad Bishop     if(iit == obj.end())
200b83a21eaSBrad Bishop         throw std::runtime_error(
201b83a21eaSBrad Bishop                 "interface was not found");
202b83a21eaSBrad Bishop 
203b83a21eaSBrad Bishop     return *iit->second;
204b83a21eaSBrad Bishop }
205b83a21eaSBrad Bishop 
20649aefb31SBrad Bishop } // namespace manager
20749aefb31SBrad Bishop } // namespace inventory
20849aefb31SBrad Bishop } // namespace phosphor
20949aefb31SBrad Bishop 
21049aefb31SBrad Bishop // vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
211