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> 1949aefb31SBrad Bishop #include "manager.hpp" 2049aefb31SBrad Bishop 2124424983SBrad Bishop using namespace std::literals::chrono_literals; 2224424983SBrad Bishop 2349aefb31SBrad Bishop namespace phosphor 2449aefb31SBrad Bishop { 2549aefb31SBrad Bishop namespace inventory 2649aefb31SBrad Bishop { 2749aefb31SBrad Bishop namespace manager 2849aefb31SBrad Bishop { 2949aefb31SBrad Bishop namespace details 3049aefb31SBrad Bishop { 3149aefb31SBrad Bishop 3249aefb31SBrad Bishop /** @brief Fowrarding signal callback. 3349aefb31SBrad Bishop * 3449aefb31SBrad Bishop * Extracts per-signal specific context and forwards the call to the manager 3549aefb31SBrad Bishop * instance. 3649aefb31SBrad Bishop */ 3749aefb31SBrad Bishop auto _signal(sd_bus_message* m, void* data, sd_bus_error* e) noexcept 3849aefb31SBrad Bishop { 397b33777bSBrad Bishop try 407b33777bSBrad Bishop { 4149aefb31SBrad Bishop auto msg = sdbusplus::message::message(m); 4249aefb31SBrad Bishop auto& args = *static_cast<Manager::SigArg*>(data); 4349aefb31SBrad Bishop sd_bus_message_ref(m); 4449aefb31SBrad Bishop auto& mgr = *std::get<0>(args); 45*48547a85SBrad Bishop mgr.handleEvent( 4668c80839SBrad Bishop msg, 4768c80839SBrad Bishop static_cast<const details::DbusSignal&>( 4868c80839SBrad Bishop *std::get<1>(args)), 4968c80839SBrad Bishop *std::get<2>(args)); 5049aefb31SBrad Bishop } 517b33777bSBrad Bishop catch (const std::exception& e) 527b33777bSBrad Bishop { 5349aefb31SBrad Bishop std::cerr << e.what() << std::endl; 5449aefb31SBrad Bishop } 5549aefb31SBrad Bishop 5649aefb31SBrad Bishop return 0; 5749aefb31SBrad Bishop } 5849aefb31SBrad Bishop 5949aefb31SBrad Bishop } // namespace details 6049aefb31SBrad Bishop 6149aefb31SBrad Bishop Manager::Manager( 6249aefb31SBrad Bishop sdbusplus::bus::bus&& bus, 6349aefb31SBrad Bishop const char* busname, 6449aefb31SBrad Bishop const char* root, 6549aefb31SBrad Bishop const char* iface) : 66451f8d93SBrad Bishop details::ServerObject<details::ManagerIface>(bus, root), 6749aefb31SBrad Bishop _shutdown(false), 6849aefb31SBrad Bishop _root(root), 6949aefb31SBrad Bishop _bus(std::move(bus)), 7049aefb31SBrad Bishop _manager(sdbusplus::server::manager::manager(_bus, root)) 7149aefb31SBrad Bishop { 7268c80839SBrad Bishop for (auto& group : _events) 7368c80839SBrad Bishop { 74*48547a85SBrad Bishop for (auto pEvent : std::get<std::vector<details::EventBasePtr>>( 75*48547a85SBrad Bishop group)) 7668c80839SBrad Bishop { 774f20a3e3SBrad Bishop if (pEvent->type != 784f20a3e3SBrad Bishop details::Event::Type::DBUS_SIGNAL) 797b33777bSBrad Bishop { 804f20a3e3SBrad Bishop continue; 817b33777bSBrad Bishop } 824f20a3e3SBrad Bishop 8368c80839SBrad Bishop // Create a callback context for this event group. 8468c80839SBrad Bishop auto dbusEvent = static_cast<details::DbusSignal*>( 8568c80839SBrad Bishop pEvent.get()); 8668c80839SBrad Bishop 8768c80839SBrad Bishop // Go ahead and store an iterator pointing at 8868c80839SBrad Bishop // the event data to avoid lookups later since 8968c80839SBrad Bishop // additional signal callbacks aren't added 9068c80839SBrad Bishop // after the manager is constructed. 9149aefb31SBrad Bishop _sigargs.emplace_back( 9249aefb31SBrad Bishop std::make_unique<SigArg>( 9349aefb31SBrad Bishop this, 9468c80839SBrad Bishop dbusEvent, 951ab880a1SBrad Bishop &group)); 9668c80839SBrad Bishop 9749aefb31SBrad Bishop // Register our callback and the context for 9868c80839SBrad Bishop // each signal event. 9949aefb31SBrad Bishop _matches.emplace_back( 10049aefb31SBrad Bishop _bus, 101*48547a85SBrad Bishop dbusEvent->signature, 10249aefb31SBrad Bishop details::_signal, 1031ab880a1SBrad Bishop _sigargs.back().get()); 10449aefb31SBrad Bishop } 10568c80839SBrad Bishop } 10649aefb31SBrad Bishop 10749aefb31SBrad Bishop _bus.request_name(busname); 10849aefb31SBrad Bishop } 10949aefb31SBrad Bishop 11049aefb31SBrad Bishop void Manager::shutdown() noexcept 11149aefb31SBrad Bishop { 11249aefb31SBrad Bishop _shutdown = true; 11349aefb31SBrad Bishop } 11449aefb31SBrad Bishop 11549aefb31SBrad Bishop void Manager::run() noexcept 11649aefb31SBrad Bishop { 1177b33777bSBrad Bishop while (!_shutdown) 1187b33777bSBrad Bishop { 1197b33777bSBrad Bishop try 1207b33777bSBrad Bishop { 12149aefb31SBrad Bishop _bus.process_discard(); 12224424983SBrad Bishop _bus.wait((5000000us).count()); 12349aefb31SBrad Bishop } 1247b33777bSBrad Bishop catch (const std::exception& e) 1257b33777bSBrad Bishop { 12649aefb31SBrad Bishop std::cerr << e.what() << std::endl; 12749aefb31SBrad Bishop } 12849aefb31SBrad Bishop } 12949aefb31SBrad Bishop } 13049aefb31SBrad Bishop 1319aa5e2f2SBrad Bishop void Manager::notify(sdbusplus::message::object_path path, Object object) 13249aefb31SBrad Bishop { 1337b33777bSBrad Bishop try 1347b33777bSBrad Bishop { 1359aa5e2f2SBrad Bishop 13649aefb31SBrad Bishop if (object.cbegin() == object.cend()) 13749aefb31SBrad Bishop throw std::runtime_error( 1389aa5e2f2SBrad Bishop "No interfaces in " + path.str); 13949aefb31SBrad Bishop 1409aa5e2f2SBrad Bishop path.str.insert(0, _root); 14149aefb31SBrad Bishop 14249aefb31SBrad Bishop auto obj = _refs.find(path); 14349aefb31SBrad Bishop if (obj != _refs.end()) 14449aefb31SBrad Bishop throw std::runtime_error( 14549aefb31SBrad Bishop obj->first + " already exists"); 14649aefb31SBrad Bishop 14749aefb31SBrad Bishop // Create an interface holder for each interface 14849aefb31SBrad Bishop // provided by the client and group them into 14949aefb31SBrad Bishop // a container. 15049aefb31SBrad Bishop InterfaceComposite ref; 15149aefb31SBrad Bishop 1526676c12dSBrad Bishop auto i = object.size(); 1537b33777bSBrad Bishop for (auto& x : object) 1547b33777bSBrad Bishop { 1556676c12dSBrad Bishop // Defer sending any signals until the last interface. 1566676c12dSBrad Bishop auto deferSignals = --i != 0; 1575fbaa7feSBrad Bishop auto maker = _makers.find(x.first.c_str()); 15849aefb31SBrad Bishop 1595fbaa7feSBrad Bishop if (maker == _makers.end()) 16049aefb31SBrad Bishop throw std::runtime_error( 16149aefb31SBrad Bishop "Unimplemented interface: " + x.first); 16249aefb31SBrad Bishop 1631ab880a1SBrad Bishop ref.emplace(x.first, 1646676c12dSBrad Bishop (maker->second)(_bus, path.str.c_str(), deferSignals)); 16549aefb31SBrad Bishop } 16649aefb31SBrad Bishop 1679d10fb21SBrad Bishop if (!ref.empty()) 1689d10fb21SBrad Bishop { 16949aefb31SBrad Bishop // Hang on to a reference to the object (interfaces) 17049aefb31SBrad Bishop // so it stays on the bus, and so we can make calls 17149aefb31SBrad Bishop // to it if needed. 17249aefb31SBrad Bishop _refs.emplace( 1731ab880a1SBrad Bishop path, std::move(ref)); 17449aefb31SBrad Bishop } 1759d10fb21SBrad Bishop } 1767b33777bSBrad Bishop catch (const std::exception& e) 1777b33777bSBrad Bishop { 17849aefb31SBrad Bishop std::cerr << e.what() << std::endl; 17949aefb31SBrad Bishop } 18049aefb31SBrad Bishop } 18149aefb31SBrad Bishop 182*48547a85SBrad Bishop void Manager::handleEvent( 18368c80839SBrad Bishop sdbusplus::message::message& msg, 184*48547a85SBrad Bishop const details::Event& event, 18568c80839SBrad Bishop const EventInfo& info) 18649aefb31SBrad Bishop { 18768c80839SBrad Bishop auto& actions = std::get<1>(info); 1883d57f507SBrad Bishop 189*48547a85SBrad Bishop for (auto& f : event) 1907b33777bSBrad Bishop { 19123719000SBrad Bishop if (!(*f)(_bus, msg, *this)) 192064c94a6SBrad Bishop { 193064c94a6SBrad Bishop return; 194064c94a6SBrad Bishop } 195064c94a6SBrad Bishop } 1969007432aSBrad Bishop for (auto& action : actions) 1977b33777bSBrad Bishop { 19823719000SBrad Bishop (*action)(_bus, *this); 1993d57f507SBrad Bishop } 20049aefb31SBrad Bishop } 20149aefb31SBrad Bishop 2027b7e712cSBrad Bishop void Manager::destroyObjects( 2037b7e712cSBrad Bishop const std::vector<const char*>& paths) 2047b7e712cSBrad Bishop { 2057b7e712cSBrad Bishop for (const auto& path : paths) 206656a7d00SBrad Bishop { 207656a7d00SBrad Bishop std::string p{path}; 208656a7d00SBrad Bishop _refs.erase(_root + p); 209656a7d00SBrad Bishop } 2107b7e712cSBrad Bishop } 211656a7d00SBrad Bishop 212b83a21eaSBrad Bishop details::holder::Base& Manager::getInterfaceHolder( 213b83a21eaSBrad Bishop const char* path, const char* interface) 214b83a21eaSBrad Bishop { 215b83a21eaSBrad Bishop return const_cast<const Manager*>( 216b83a21eaSBrad Bishop this)->getInterfaceHolder(path, interface); 217b83a21eaSBrad Bishop } 218b83a21eaSBrad Bishop 219b83a21eaSBrad Bishop details::holder::Base& Manager::getInterfaceHolder( 220b83a21eaSBrad Bishop const char* path, const char* interface) const 221b83a21eaSBrad Bishop { 222b83a21eaSBrad Bishop std::string p{path}; 223b83a21eaSBrad Bishop auto oit = _refs.find(_root + p); 224b83a21eaSBrad Bishop if (oit == _refs.end()) 225b83a21eaSBrad Bishop throw std::runtime_error( 226b83a21eaSBrad Bishop _root + p + " was not found"); 227b83a21eaSBrad Bishop 228b83a21eaSBrad Bishop auto& obj = oit->second; 229b83a21eaSBrad Bishop auto iit = obj.find(interface); 230b83a21eaSBrad Bishop if (iit == obj.end()) 231b83a21eaSBrad Bishop throw std::runtime_error( 232b83a21eaSBrad Bishop "interface was not found"); 233b83a21eaSBrad Bishop 234b83a21eaSBrad Bishop return *iit->second; 235b83a21eaSBrad Bishop } 236b83a21eaSBrad Bishop 23749aefb31SBrad Bishop } // namespace manager 23849aefb31SBrad Bishop } // namespace inventory 23949aefb31SBrad Bishop } // namespace phosphor 24049aefb31SBrad Bishop 24149aefb31SBrad Bishop // vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 242