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); 4568c80839SBrad Bishop mgr.signal( 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 { 7468c80839SBrad Bishop for (auto pEvent : std::get<0>(group)) 7568c80839SBrad Bishop { 764f20a3e3SBrad Bishop if (pEvent->type != 774f20a3e3SBrad Bishop details::Event::Type::DBUS_SIGNAL) 787b33777bSBrad Bishop { 794f20a3e3SBrad Bishop continue; 807b33777bSBrad Bishop } 814f20a3e3SBrad Bishop 8268c80839SBrad Bishop // Create a callback context for this event group. 8368c80839SBrad Bishop auto dbusEvent = static_cast<details::DbusSignal*>( 8468c80839SBrad Bishop pEvent.get()); 8568c80839SBrad Bishop 8668c80839SBrad Bishop // Go ahead and store an iterator pointing at 8768c80839SBrad Bishop // the event data to avoid lookups later since 8868c80839SBrad Bishop // additional signal callbacks aren't added 8968c80839SBrad Bishop // after the manager is constructed. 9049aefb31SBrad Bishop _sigargs.emplace_back( 9149aefb31SBrad Bishop std::make_unique<SigArg>( 9249aefb31SBrad Bishop this, 9368c80839SBrad Bishop dbusEvent, 941ab880a1SBrad Bishop &group)); 9568c80839SBrad Bishop 9649aefb31SBrad Bishop // Register our callback and the context for 9768c80839SBrad Bishop // each signal event. 9849aefb31SBrad Bishop _matches.emplace_back( 9949aefb31SBrad Bishop _bus, 10068c80839SBrad Bishop std::get<0>(*dbusEvent), 10149aefb31SBrad Bishop details::_signal, 1021ab880a1SBrad Bishop _sigargs.back().get()); 10349aefb31SBrad Bishop } 10468c80839SBrad Bishop } 10549aefb31SBrad Bishop 10649aefb31SBrad Bishop _bus.request_name(busname); 10749aefb31SBrad Bishop } 10849aefb31SBrad Bishop 10949aefb31SBrad Bishop void Manager::shutdown() noexcept 11049aefb31SBrad Bishop { 11149aefb31SBrad Bishop _shutdown = true; 11249aefb31SBrad Bishop } 11349aefb31SBrad Bishop 11449aefb31SBrad Bishop void Manager::run() noexcept 11549aefb31SBrad Bishop { 1167b33777bSBrad Bishop while (!_shutdown) 1177b33777bSBrad Bishop { 1187b33777bSBrad Bishop try 1197b33777bSBrad Bishop { 12049aefb31SBrad Bishop _bus.process_discard(); 12124424983SBrad Bishop _bus.wait((5000000us).count()); 12249aefb31SBrad Bishop } 1237b33777bSBrad Bishop catch (const std::exception& e) 1247b33777bSBrad Bishop { 12549aefb31SBrad Bishop std::cerr << e.what() << std::endl; 12649aefb31SBrad Bishop } 12749aefb31SBrad Bishop } 12849aefb31SBrad Bishop } 12949aefb31SBrad Bishop 1309aa5e2f2SBrad Bishop void Manager::notify(sdbusplus::message::object_path path, Object object) 13149aefb31SBrad Bishop { 1327b33777bSBrad Bishop try 1337b33777bSBrad Bishop { 1349aa5e2f2SBrad Bishop 13549aefb31SBrad Bishop if (object.cbegin() == object.cend()) 13649aefb31SBrad Bishop throw std::runtime_error( 1379aa5e2f2SBrad Bishop "No interfaces in " + path.str); 13849aefb31SBrad Bishop 1399aa5e2f2SBrad Bishop path.str.insert(0, _root); 14049aefb31SBrad Bishop 14149aefb31SBrad Bishop auto obj = _refs.find(path); 14249aefb31SBrad Bishop if (obj != _refs.end()) 14349aefb31SBrad Bishop throw std::runtime_error( 14449aefb31SBrad Bishop obj->first + " already exists"); 14549aefb31SBrad Bishop 14649aefb31SBrad Bishop // Create an interface holder for each interface 14749aefb31SBrad Bishop // provided by the client and group them into 14849aefb31SBrad Bishop // a container. 14949aefb31SBrad Bishop InterfaceComposite ref; 15049aefb31SBrad Bishop 151*6676c12dSBrad Bishop auto i = object.size(); 1527b33777bSBrad Bishop for (auto& x : object) 1537b33777bSBrad Bishop { 154*6676c12dSBrad Bishop // Defer sending any signals until the last interface. 155*6676c12dSBrad Bishop auto deferSignals = --i != 0; 1565fbaa7feSBrad Bishop auto maker = _makers.find(x.first.c_str()); 15749aefb31SBrad Bishop 1585fbaa7feSBrad Bishop if (maker == _makers.end()) 15949aefb31SBrad Bishop throw std::runtime_error( 16049aefb31SBrad Bishop "Unimplemented interface: " + x.first); 16149aefb31SBrad Bishop 1621ab880a1SBrad Bishop ref.emplace(x.first, 163*6676c12dSBrad Bishop (maker->second)(_bus, path.str.c_str(), deferSignals)); 16449aefb31SBrad Bishop } 16549aefb31SBrad Bishop 1669d10fb21SBrad Bishop if (!ref.empty()) 1679d10fb21SBrad Bishop { 16849aefb31SBrad Bishop // Hang on to a reference to the object (interfaces) 16949aefb31SBrad Bishop // so it stays on the bus, and so we can make calls 17049aefb31SBrad Bishop // to it if needed. 17149aefb31SBrad Bishop _refs.emplace( 1721ab880a1SBrad Bishop path, std::move(ref)); 17349aefb31SBrad Bishop } 1749d10fb21SBrad Bishop } 1757b33777bSBrad Bishop catch (const std::exception& e) 1767b33777bSBrad Bishop { 17749aefb31SBrad Bishop std::cerr << e.what() << std::endl; 17849aefb31SBrad Bishop } 17949aefb31SBrad Bishop } 18049aefb31SBrad Bishop 18168c80839SBrad Bishop void Manager::signal( 18268c80839SBrad Bishop sdbusplus::message::message& msg, 18368c80839SBrad Bishop const details::DbusSignal& event, 18468c80839SBrad Bishop const EventInfo& info) 18549aefb31SBrad Bishop { 18668c80839SBrad Bishop auto& filter = *std::get<1>(event); 18768c80839SBrad Bishop auto& actions = std::get<1>(info); 1883d57f507SBrad Bishop 1897b33777bSBrad Bishop if (filter(msg, *this)) 1907b33777bSBrad Bishop { 1919007432aSBrad Bishop for (auto& action : actions) 1927b33777bSBrad Bishop { 1939007432aSBrad Bishop (*action)(*this); 1943d57f507SBrad Bishop } 19549aefb31SBrad Bishop } 1967b33777bSBrad Bishop } 19749aefb31SBrad Bishop 198656a7d00SBrad Bishop void Manager::destroyObject(const char* path) 199656a7d00SBrad Bishop { 200656a7d00SBrad Bishop std::string p{path}; 201656a7d00SBrad Bishop _refs.erase(_root + p); 202656a7d00SBrad Bishop } 203656a7d00SBrad Bishop 204b83a21eaSBrad Bishop details::holder::Base& Manager::getInterfaceHolder( 205b83a21eaSBrad Bishop const char* path, const char* interface) 206b83a21eaSBrad Bishop { 207b83a21eaSBrad Bishop return const_cast<const Manager*>( 208b83a21eaSBrad Bishop this)->getInterfaceHolder(path, interface); 209b83a21eaSBrad Bishop } 210b83a21eaSBrad Bishop 211b83a21eaSBrad Bishop details::holder::Base& Manager::getInterfaceHolder( 212b83a21eaSBrad Bishop const char* path, const char* interface) const 213b83a21eaSBrad Bishop { 214b83a21eaSBrad Bishop std::string p{path}; 215b83a21eaSBrad Bishop auto oit = _refs.find(_root + p); 216b83a21eaSBrad Bishop if (oit == _refs.end()) 217b83a21eaSBrad Bishop throw std::runtime_error( 218b83a21eaSBrad Bishop _root + p + " was not found"); 219b83a21eaSBrad Bishop 220b83a21eaSBrad Bishop auto& obj = oit->second; 221b83a21eaSBrad Bishop auto iit = obj.find(interface); 222b83a21eaSBrad Bishop if (iit == obj.end()) 223b83a21eaSBrad Bishop throw std::runtime_error( 224b83a21eaSBrad Bishop "interface was not found"); 225b83a21eaSBrad Bishop 226b83a21eaSBrad Bishop return *iit->second; 227b83a21eaSBrad Bishop } 228b83a21eaSBrad Bishop 22949aefb31SBrad Bishop } // namespace manager 23049aefb31SBrad Bishop } // namespace inventory 23149aefb31SBrad Bishop } // namespace phosphor 23249aefb31SBrad Bishop 23349aefb31SBrad Bishop // vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 234