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