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>
1824424983SBrad Bishop #include <chrono>
199bbfcb18SBrad Bishop #include <log.hpp>
2049aefb31SBrad Bishop #include "manager.hpp"
2149aefb31SBrad Bishop 
2224424983SBrad Bishop using namespace std::literals::chrono_literals;
2324424983SBrad Bishop 
2449aefb31SBrad Bishop namespace phosphor
2549aefb31SBrad Bishop {
2649aefb31SBrad Bishop namespace inventory
2749aefb31SBrad Bishop {
2849aefb31SBrad Bishop namespace manager
2949aefb31SBrad Bishop {
3049aefb31SBrad Bishop /** @brief Fowrarding signal callback.
3149aefb31SBrad Bishop  *
3249aefb31SBrad Bishop  *  Extracts per-signal specific context and forwards the call to the manager
3349aefb31SBrad Bishop  *  instance.
3449aefb31SBrad Bishop  */
3549aefb31SBrad Bishop auto _signal(sd_bus_message* m, void* data, sd_bus_error* e) noexcept
3649aefb31SBrad Bishop {
377b33777bSBrad Bishop     try
387b33777bSBrad Bishop     {
3949aefb31SBrad Bishop         auto msg = sdbusplus::message::message(m);
4049aefb31SBrad Bishop         auto& args = *static_cast<Manager::SigArg*>(data);
4149aefb31SBrad Bishop         sd_bus_message_ref(m);
4249aefb31SBrad Bishop         auto& mgr = *std::get<0>(args);
4348547a85SBrad Bishop         mgr.handleEvent(
4468c80839SBrad Bishop             msg,
4512f8a3c8SBrad Bishop             static_cast<const DbusSignal&>(
4668c80839SBrad Bishop                 *std::get<1>(args)),
4768c80839SBrad Bishop             *std::get<2>(args));
4849aefb31SBrad Bishop     }
497b33777bSBrad Bishop     catch (const std::exception& e)
507b33777bSBrad Bishop     {
5149aefb31SBrad Bishop         std::cerr << e.what() << std::endl;
5249aefb31SBrad Bishop     }
5349aefb31SBrad Bishop 
5449aefb31SBrad Bishop     return 0;
5549aefb31SBrad Bishop }
5649aefb31SBrad Bishop 
5749aefb31SBrad Bishop Manager::Manager(
5849aefb31SBrad Bishop     sdbusplus::bus::bus&& bus,
5949aefb31SBrad Bishop     const char* busname,
6049aefb31SBrad Bishop     const char* root,
6149aefb31SBrad Bishop     const char* iface) :
6212f8a3c8SBrad Bishop     ServerObject<ManagerIface>(bus, root),
6349aefb31SBrad Bishop     _shutdown(false),
6449aefb31SBrad Bishop     _root(root),
6549aefb31SBrad Bishop     _bus(std::move(bus)),
6649aefb31SBrad Bishop     _manager(sdbusplus::server::manager::manager(_bus, root))
6749aefb31SBrad Bishop {
6868c80839SBrad Bishop     for (auto& group : _events)
6968c80839SBrad Bishop     {
7012f8a3c8SBrad Bishop         for (auto pEvent : std::get<std::vector<EventBasePtr>>(
7148547a85SBrad Bishop                  group))
7268c80839SBrad Bishop         {
734f20a3e3SBrad Bishop             if (pEvent->type !=
7412f8a3c8SBrad Bishop                 Event::Type::DBUS_SIGNAL)
757b33777bSBrad Bishop             {
764f20a3e3SBrad Bishop                 continue;
777b33777bSBrad Bishop             }
784f20a3e3SBrad Bishop 
7968c80839SBrad Bishop             // Create a callback context for this event group.
8012f8a3c8SBrad Bishop             auto dbusEvent = static_cast<DbusSignal*>(
8168c80839SBrad Bishop                                  pEvent.get());
8268c80839SBrad Bishop 
8368c80839SBrad Bishop             // Go ahead and store an iterator pointing at
8468c80839SBrad Bishop             // the event data to avoid lookups later since
8568c80839SBrad Bishop             // additional signal callbacks aren't added
8668c80839SBrad Bishop             // after the manager is constructed.
8749aefb31SBrad Bishop             _sigargs.emplace_back(
8849aefb31SBrad Bishop                 std::make_unique<SigArg>(
8949aefb31SBrad Bishop                     this,
9068c80839SBrad Bishop                     dbusEvent,
911ab880a1SBrad Bishop                     &group));
9268c80839SBrad Bishop 
9349aefb31SBrad Bishop             // Register our callback and the context for
9468c80839SBrad Bishop             // each signal event.
9549aefb31SBrad Bishop             _matches.emplace_back(
9649aefb31SBrad Bishop                 _bus,
9748547a85SBrad Bishop                 dbusEvent->signature,
9812f8a3c8SBrad Bishop                 _signal,
991ab880a1SBrad Bishop                 _sigargs.back().get());
10049aefb31SBrad Bishop         }
10168c80839SBrad Bishop     }
10249aefb31SBrad Bishop 
10349aefb31SBrad Bishop     _bus.request_name(busname);
10449aefb31SBrad Bishop }
10549aefb31SBrad Bishop 
10649aefb31SBrad Bishop void Manager::shutdown() noexcept
10749aefb31SBrad Bishop {
10849aefb31SBrad Bishop     _shutdown = true;
10949aefb31SBrad Bishop }
11049aefb31SBrad Bishop 
11149aefb31SBrad Bishop void Manager::run() noexcept
11249aefb31SBrad Bishop {
1133e4a19a3SBrad Bishop     sdbusplus::message::message unusedMsg{nullptr};
1143e4a19a3SBrad Bishop 
1153e4a19a3SBrad Bishop     // Run startup events.
1163e4a19a3SBrad Bishop     for (auto& group : _events)
1173e4a19a3SBrad Bishop     {
11812f8a3c8SBrad Bishop         for (auto pEvent : std::get<std::vector<EventBasePtr>>(
1193e4a19a3SBrad Bishop                  group))
1203e4a19a3SBrad Bishop         {
1213e4a19a3SBrad Bishop             if (pEvent->type ==
12212f8a3c8SBrad Bishop                 Event::Type::STARTUP)
1233e4a19a3SBrad Bishop             {
1243e4a19a3SBrad Bishop                 handleEvent(unusedMsg, *pEvent, group);
1253e4a19a3SBrad Bishop             }
1263e4a19a3SBrad Bishop         }
1273e4a19a3SBrad Bishop     }
1283e4a19a3SBrad Bishop 
1297b33777bSBrad Bishop     while (!_shutdown)
1307b33777bSBrad Bishop     {
1317b33777bSBrad Bishop         try
1327b33777bSBrad Bishop         {
13349aefb31SBrad Bishop             _bus.process_discard();
13424424983SBrad Bishop             _bus.wait((5000000us).count());
13549aefb31SBrad Bishop         }
1367b33777bSBrad Bishop         catch (const std::exception& e)
1377b33777bSBrad Bishop         {
13849aefb31SBrad Bishop             std::cerr << e.what() << std::endl;
13949aefb31SBrad Bishop         }
14049aefb31SBrad Bishop     }
14149aefb31SBrad Bishop }
14249aefb31SBrad Bishop 
14303f4cd95SBrad Bishop void Manager::notify(std::map<sdbusplus::message::object_path, Object> objs)
14449aefb31SBrad Bishop {
145*cda036f7SBrad Bishop     updateObjects(objs);
14649aefb31SBrad Bishop }
14749aefb31SBrad Bishop 
14848547a85SBrad Bishop void Manager::handleEvent(
14968c80839SBrad Bishop     sdbusplus::message::message& msg,
15012f8a3c8SBrad Bishop     const Event& event,
15168c80839SBrad Bishop     const EventInfo& info)
15249aefb31SBrad Bishop {
15368c80839SBrad Bishop     auto& actions = std::get<1>(info);
1543d57f507SBrad Bishop 
15548547a85SBrad Bishop     for (auto& f : event)
1567b33777bSBrad Bishop     {
15707934a64SBrad Bishop         if (!f(_bus, msg, *this))
158064c94a6SBrad Bishop         {
159064c94a6SBrad Bishop             return;
160064c94a6SBrad Bishop         }
161064c94a6SBrad Bishop     }
1629007432aSBrad Bishop     for (auto& action : actions)
1637b33777bSBrad Bishop     {
16407934a64SBrad Bishop         action(_bus, *this);
1653d57f507SBrad Bishop     }
16649aefb31SBrad Bishop }
16749aefb31SBrad Bishop 
1687b7e712cSBrad Bishop void Manager::destroyObjects(
1697b7e712cSBrad Bishop     const std::vector<const char*>& paths)
1707b7e712cSBrad Bishop {
171a5cc34c2SBrad Bishop     std::string p;
172a5cc34c2SBrad Bishop 
1737b7e712cSBrad Bishop     for (const auto& path : paths)
174656a7d00SBrad Bishop     {
175a5cc34c2SBrad Bishop         p.assign(_root);
176a5cc34c2SBrad Bishop         p.append(path);
177a5cc34c2SBrad Bishop         _bus.emit_object_removed(p.c_str());
178a5cc34c2SBrad Bishop         _refs.erase(p);
179656a7d00SBrad Bishop     }
1807b7e712cSBrad Bishop }
181656a7d00SBrad Bishop 
182eb68a687SBrad Bishop void Manager::createObjects(
183eb68a687SBrad Bishop     const std::map<sdbusplus::message::object_path, Object>& objs)
184eb68a687SBrad Bishop {
185*cda036f7SBrad Bishop     updateObjects(objs);
186eb68a687SBrad Bishop }
187eb68a687SBrad Bishop 
188150147aeSBrad Bishop any_ns::any& Manager::getInterfaceHolder(
189b83a21eaSBrad Bishop     const char* path, const char* interface)
190b83a21eaSBrad Bishop {
191150147aeSBrad Bishop     return const_cast<any_ns::any&>(
192150147aeSBrad Bishop                const_cast<const Manager*>(
193150147aeSBrad Bishop                    this)->getInterfaceHolder(path, interface));
194b83a21eaSBrad Bishop }
195b83a21eaSBrad Bishop 
196150147aeSBrad Bishop const any_ns::any& Manager::getInterfaceHolder(
197b83a21eaSBrad Bishop     const char* path, const char* interface) const
198b83a21eaSBrad Bishop {
199b83a21eaSBrad Bishop     std::string p{path};
200b83a21eaSBrad Bishop     auto oit = _refs.find(_root + p);
201b83a21eaSBrad Bishop     if (oit == _refs.end())
202b83a21eaSBrad Bishop         throw std::runtime_error(
203b83a21eaSBrad Bishop             _root + p + " was not found");
204b83a21eaSBrad Bishop 
205b83a21eaSBrad Bishop     auto& obj = oit->second;
206b83a21eaSBrad Bishop     auto iit = obj.find(interface);
207b83a21eaSBrad Bishop     if (iit == obj.end())
208b83a21eaSBrad Bishop         throw std::runtime_error(
209b83a21eaSBrad Bishop             "interface was not found");
210b83a21eaSBrad Bishop 
211150147aeSBrad Bishop     return iit->second;
212b83a21eaSBrad Bishop }
213b83a21eaSBrad Bishop 
21449aefb31SBrad Bishop } // namespace manager
21549aefb31SBrad Bishop } // namespace inventory
21649aefb31SBrad Bishop } // namespace phosphor
21749aefb31SBrad Bishop 
21849aefb31SBrad Bishop // vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
219