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> 18*24424983SBrad Bishop #include <chrono> 1949aefb31SBrad Bishop #include "manager.hpp" 2049aefb31SBrad Bishop 21*24424983SBrad Bishop using namespace std::literals::chrono_literals; 22*24424983SBrad 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(); 121*24424983SBrad 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 13049aefb31SBrad Bishop void Manager::notify(std::string path, Object object) 13149aefb31SBrad Bishop { 1327b33777bSBrad Bishop try 1337b33777bSBrad Bishop { 13449aefb31SBrad Bishop if (object.cbegin() == object.cend()) 13549aefb31SBrad Bishop throw std::runtime_error( 13649aefb31SBrad Bishop "No interfaces in " + path); 13749aefb31SBrad Bishop 13849aefb31SBrad Bishop path.insert(0, _root); 13949aefb31SBrad Bishop 14049aefb31SBrad Bishop auto obj = _refs.find(path); 14149aefb31SBrad Bishop if (obj != _refs.end()) 14249aefb31SBrad Bishop throw std::runtime_error( 14349aefb31SBrad Bishop obj->first + " already exists"); 14449aefb31SBrad Bishop 14549aefb31SBrad Bishop // Create an interface holder for each interface 14649aefb31SBrad Bishop // provided by the client and group them into 14749aefb31SBrad Bishop // a container. 14849aefb31SBrad Bishop InterfaceComposite ref; 14949aefb31SBrad Bishop 1507b33777bSBrad Bishop for (auto& x : object) 1517b33777bSBrad Bishop { 1525fbaa7feSBrad Bishop auto maker = _makers.find(x.first.c_str()); 15349aefb31SBrad Bishop 1545fbaa7feSBrad Bishop if (maker == _makers.end()) 15549aefb31SBrad Bishop throw std::runtime_error( 15649aefb31SBrad Bishop "Unimplemented interface: " + x.first); 15749aefb31SBrad Bishop 1581ab880a1SBrad Bishop ref.emplace(x.first, 1591ab880a1SBrad Bishop (maker->second)(_bus, path.c_str())); 16049aefb31SBrad Bishop } 16149aefb31SBrad Bishop 16249aefb31SBrad Bishop // Hang on to a reference to the object (interfaces) 16349aefb31SBrad Bishop // so it stays on the bus, and so we can make calls 16449aefb31SBrad Bishop // to it if needed. 16549aefb31SBrad Bishop _refs.emplace( 1661ab880a1SBrad Bishop path, std::move(ref)); 16749aefb31SBrad Bishop } 1687b33777bSBrad Bishop catch (const std::exception& e) 1697b33777bSBrad Bishop { 17049aefb31SBrad Bishop std::cerr << e.what() << std::endl; 17149aefb31SBrad Bishop } 17249aefb31SBrad Bishop } 17349aefb31SBrad Bishop 17468c80839SBrad Bishop void Manager::signal( 17568c80839SBrad Bishop sdbusplus::message::message& msg, 17668c80839SBrad Bishop const details::DbusSignal& event, 17768c80839SBrad Bishop const EventInfo& info) 17849aefb31SBrad Bishop { 17968c80839SBrad Bishop auto& filter = *std::get<1>(event); 18068c80839SBrad Bishop auto& actions = std::get<1>(info); 1813d57f507SBrad Bishop 1827b33777bSBrad Bishop if (filter(msg, *this)) 1837b33777bSBrad Bishop { 1849007432aSBrad Bishop for (auto& action : actions) 1857b33777bSBrad Bishop { 1869007432aSBrad Bishop (*action)(*this); 1873d57f507SBrad Bishop } 18849aefb31SBrad Bishop } 1897b33777bSBrad Bishop } 19049aefb31SBrad Bishop 191656a7d00SBrad Bishop void Manager::destroyObject(const char* path) 192656a7d00SBrad Bishop { 193656a7d00SBrad Bishop std::string p{path}; 194656a7d00SBrad Bishop _refs.erase(_root + p); 195656a7d00SBrad Bishop } 196656a7d00SBrad Bishop 197b83a21eaSBrad Bishop details::holder::Base& Manager::getInterfaceHolder( 198b83a21eaSBrad Bishop const char* path, const char* interface) 199b83a21eaSBrad Bishop { 200b83a21eaSBrad Bishop return const_cast<const Manager*>( 201b83a21eaSBrad Bishop this)->getInterfaceHolder(path, interface); 202b83a21eaSBrad Bishop } 203b83a21eaSBrad Bishop 204b83a21eaSBrad Bishop details::holder::Base& Manager::getInterfaceHolder( 205b83a21eaSBrad Bishop const char* path, const char* interface) const 206b83a21eaSBrad Bishop { 207b83a21eaSBrad Bishop std::string p{path}; 208b83a21eaSBrad Bishop auto oit = _refs.find(_root + p); 209b83a21eaSBrad Bishop if (oit == _refs.end()) 210b83a21eaSBrad Bishop throw std::runtime_error( 211b83a21eaSBrad Bishop _root + p + " was not found"); 212b83a21eaSBrad Bishop 213b83a21eaSBrad Bishop auto& obj = oit->second; 214b83a21eaSBrad Bishop auto iit = obj.find(interface); 215b83a21eaSBrad Bishop if (iit == obj.end()) 216b83a21eaSBrad Bishop throw std::runtime_error( 217b83a21eaSBrad Bishop "interface was not found"); 218b83a21eaSBrad Bishop 219b83a21eaSBrad Bishop return *iit->second; 220b83a21eaSBrad Bishop } 221b83a21eaSBrad Bishop 22249aefb31SBrad Bishop } // namespace manager 22349aefb31SBrad Bishop } // namespace inventory 22449aefb31SBrad Bishop } // namespace phosphor 22549aefb31SBrad Bishop 22649aefb31SBrad Bishop // vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 227