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> 1979ccaf77SBrad Bishop #include <algorithm> 20101d837cSSaqib Khan #include <phosphor-logging/log.hpp> 2149aefb31SBrad Bishop #include "manager.hpp" 2279ccaf77SBrad Bishop #include "errors.hpp" 2349aefb31SBrad Bishop 2424424983SBrad Bishop using namespace std::literals::chrono_literals; 2524424983SBrad Bishop 2649aefb31SBrad Bishop namespace phosphor 2749aefb31SBrad Bishop { 2849aefb31SBrad Bishop namespace inventory 2949aefb31SBrad Bishop { 3049aefb31SBrad Bishop namespace manager 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); 4548547a85SBrad Bishop mgr.handleEvent( 4668c80839SBrad Bishop msg, 4712f8a3c8SBrad Bishop static_cast<const 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 Manager::Manager( 6049aefb31SBrad Bishop sdbusplus::bus::bus&& bus, 6149aefb31SBrad Bishop const char* busname, 6249aefb31SBrad Bishop const char* root, 6349aefb31SBrad Bishop const char* iface) : 6412f8a3c8SBrad Bishop ServerObject<ManagerIface>(bus, root), 6549aefb31SBrad Bishop _shutdown(false), 6649aefb31SBrad Bishop _root(root), 6749aefb31SBrad Bishop _bus(std::move(bus)), 689b86483fSBrad Bishop _manager(_bus, root) 6949aefb31SBrad Bishop { 7068c80839SBrad Bishop for (auto& group : _events) 7168c80839SBrad Bishop { 7212f8a3c8SBrad Bishop for (auto pEvent : std::get<std::vector<EventBasePtr>>( 7348547a85SBrad Bishop group)) 7468c80839SBrad Bishop { 754f20a3e3SBrad Bishop if (pEvent->type != 7612f8a3c8SBrad Bishop Event::Type::DBUS_SIGNAL) 777b33777bSBrad Bishop { 784f20a3e3SBrad Bishop continue; 797b33777bSBrad Bishop } 804f20a3e3SBrad Bishop 8168c80839SBrad Bishop // Create a callback context for this event group. 8212f8a3c8SBrad Bishop auto dbusEvent = static_cast<DbusSignal*>( 8368c80839SBrad Bishop pEvent.get()); 8468c80839SBrad Bishop 8568c80839SBrad Bishop // Go ahead and store an iterator pointing at 8668c80839SBrad Bishop // the event data to avoid lookups later since 8768c80839SBrad Bishop // additional signal callbacks aren't added 8868c80839SBrad Bishop // after the manager is constructed. 8949aefb31SBrad Bishop _sigargs.emplace_back( 9049aefb31SBrad Bishop std::make_unique<SigArg>( 9149aefb31SBrad Bishop this, 9268c80839SBrad Bishop dbusEvent, 931ab880a1SBrad Bishop &group)); 9468c80839SBrad Bishop 9549aefb31SBrad Bishop // Register our callback and the context for 9668c80839SBrad Bishop // each signal event. 9749aefb31SBrad Bishop _matches.emplace_back( 9849aefb31SBrad Bishop _bus, 9948547a85SBrad Bishop dbusEvent->signature, 10012f8a3c8SBrad Bishop _signal, 1011ab880a1SBrad Bishop _sigargs.back().get()); 10249aefb31SBrad Bishop } 10368c80839SBrad Bishop } 10449aefb31SBrad Bishop 10549aefb31SBrad Bishop _bus.request_name(busname); 10649aefb31SBrad Bishop } 10749aefb31SBrad Bishop 10849aefb31SBrad Bishop void Manager::shutdown() noexcept 10949aefb31SBrad Bishop { 11049aefb31SBrad Bishop _shutdown = true; 11149aefb31SBrad Bishop } 11249aefb31SBrad Bishop 11349aefb31SBrad Bishop void Manager::run() noexcept 11449aefb31SBrad Bishop { 1153e4a19a3SBrad Bishop sdbusplus::message::message unusedMsg{nullptr}; 1163e4a19a3SBrad Bishop 1173e4a19a3SBrad Bishop // Run startup events. 1183e4a19a3SBrad Bishop for (auto& group : _events) 1193e4a19a3SBrad Bishop { 12012f8a3c8SBrad Bishop for (auto pEvent : std::get<std::vector<EventBasePtr>>( 1213e4a19a3SBrad Bishop group)) 1223e4a19a3SBrad Bishop { 1233e4a19a3SBrad Bishop if (pEvent->type == 12412f8a3c8SBrad Bishop Event::Type::STARTUP) 1253e4a19a3SBrad Bishop { 1263e4a19a3SBrad Bishop handleEvent(unusedMsg, *pEvent, group); 1273e4a19a3SBrad Bishop } 1283e4a19a3SBrad Bishop } 1293e4a19a3SBrad Bishop } 1303e4a19a3SBrad Bishop 1317b33777bSBrad Bishop while (!_shutdown) 1327b33777bSBrad Bishop { 1337b33777bSBrad Bishop try 1347b33777bSBrad Bishop { 13549aefb31SBrad Bishop _bus.process_discard(); 13624424983SBrad Bishop _bus.wait((5000000us).count()); 13749aefb31SBrad Bishop } 1387b33777bSBrad Bishop catch (const std::exception& e) 1397b33777bSBrad Bishop { 14049aefb31SBrad Bishop std::cerr << e.what() << std::endl; 14149aefb31SBrad Bishop } 14249aefb31SBrad Bishop } 14349aefb31SBrad Bishop } 14449aefb31SBrad Bishop 14579ccaf77SBrad Bishop void Manager::updateInterfaces( 14679ccaf77SBrad Bishop const sdbusplus::message::object_path& path, 14779ccaf77SBrad Bishop const Object& interfaces, 14879ccaf77SBrad Bishop ObjectReferences::iterator pos, 14979ccaf77SBrad Bishop bool newObject) 15079ccaf77SBrad Bishop { 15179ccaf77SBrad Bishop auto& refaces = pos->second; 15279ccaf77SBrad Bishop auto ifaceit = interfaces.cbegin(); 15379ccaf77SBrad Bishop auto opsit = _makers.cbegin(); 15479ccaf77SBrad Bishop auto refaceit = refaces.begin(); 15579ccaf77SBrad Bishop std::vector<std::string> signals; 15679ccaf77SBrad Bishop 15779ccaf77SBrad Bishop while (ifaceit != interfaces.cend()) 15879ccaf77SBrad Bishop { 15979ccaf77SBrad Bishop try 16079ccaf77SBrad Bishop { 16179ccaf77SBrad Bishop // Find the binding ops for this interface. 16279ccaf77SBrad Bishop opsit = std::lower_bound( 16379ccaf77SBrad Bishop opsit, 16479ccaf77SBrad Bishop _makers.cend(), 16579ccaf77SBrad Bishop ifaceit->first, 16679ccaf77SBrad Bishop compareFirst(_makers.key_comp())); 16779ccaf77SBrad Bishop 16879ccaf77SBrad Bishop if (opsit == _makers.cend() || opsit->first != ifaceit->first) 16979ccaf77SBrad Bishop { 17079ccaf77SBrad Bishop // This interface is not supported. 17179ccaf77SBrad Bishop throw InterfaceError( 17279ccaf77SBrad Bishop "Encountered unsupported interface.", 17379ccaf77SBrad Bishop ifaceit->first); 17479ccaf77SBrad Bishop } 17579ccaf77SBrad Bishop 17679ccaf77SBrad Bishop // Find the binding insertion point or the binding to update. 17779ccaf77SBrad Bishop refaceit = std::lower_bound( 17879ccaf77SBrad Bishop refaceit, 17979ccaf77SBrad Bishop refaces.end(), 18079ccaf77SBrad Bishop ifaceit->first, 18179ccaf77SBrad Bishop compareFirst(refaces.key_comp())); 18279ccaf77SBrad Bishop 18379ccaf77SBrad Bishop if (refaceit == refaces.end() || refaceit->first != ifaceit->first) 18479ccaf77SBrad Bishop { 18579ccaf77SBrad Bishop // Add the new interface. 18679ccaf77SBrad Bishop auto& ctor = std::get<MakerType>(opsit->second); 18779ccaf77SBrad Bishop refaceit = refaces.insert( 18879ccaf77SBrad Bishop refaceit, 18979ccaf77SBrad Bishop std::make_pair( 19079ccaf77SBrad Bishop ifaceit->first, 19179ccaf77SBrad Bishop ctor( 19279ccaf77SBrad Bishop _bus, 19379ccaf77SBrad Bishop path.str.c_str(), 19479ccaf77SBrad Bishop ifaceit->second))); 19579ccaf77SBrad Bishop signals.push_back(ifaceit->first); 19679ccaf77SBrad Bishop } 19779ccaf77SBrad Bishop else 19879ccaf77SBrad Bishop { 19979ccaf77SBrad Bishop // Set the new property values. 20079ccaf77SBrad Bishop auto& assign = std::get<AssignerType>(opsit->second); 20179ccaf77SBrad Bishop assign(ifaceit->second, refaceit->second); 20279ccaf77SBrad Bishop } 20379ccaf77SBrad Bishop } 20479ccaf77SBrad Bishop catch (const InterfaceError& e) 20579ccaf77SBrad Bishop { 20679ccaf77SBrad Bishop // Reset the binding ops iterator since we are 20779ccaf77SBrad Bishop // at the end. 20879ccaf77SBrad Bishop opsit = _makers.cbegin(); 20979ccaf77SBrad Bishop e.log(); 21079ccaf77SBrad Bishop } 21179ccaf77SBrad Bishop 21279ccaf77SBrad Bishop ++ifaceit; 21379ccaf77SBrad Bishop } 21479ccaf77SBrad Bishop 21579ccaf77SBrad Bishop if (newObject) 21679ccaf77SBrad Bishop { 21779ccaf77SBrad Bishop _bus.emit_object_added(path.str.c_str()); 21879ccaf77SBrad Bishop } 21979ccaf77SBrad Bishop else if (!signals.empty()) 22079ccaf77SBrad Bishop { 221*a8ff8154SGunnar Mills _bus.emit_interfaces_added(path.str.c_str(), signals); 22279ccaf77SBrad Bishop } 22379ccaf77SBrad Bishop } 22479ccaf77SBrad Bishop 22579ccaf77SBrad Bishop void Manager::updateObjects( 22679ccaf77SBrad Bishop const std::map<sdbusplus::message::object_path, Object>& objs) 22779ccaf77SBrad Bishop { 22879ccaf77SBrad Bishop auto objit = objs.cbegin(); 22979ccaf77SBrad Bishop auto refit = _refs.begin(); 23079ccaf77SBrad Bishop std::string absPath; 23179ccaf77SBrad Bishop bool newObj; 23279ccaf77SBrad Bishop 23379ccaf77SBrad Bishop while (objit != objs.cend()) 23479ccaf77SBrad Bishop { 23579ccaf77SBrad Bishop // Find the insertion point or the object to update. 23679ccaf77SBrad Bishop refit = std::lower_bound( 23779ccaf77SBrad Bishop refit, 23879ccaf77SBrad Bishop _refs.end(), 23979ccaf77SBrad Bishop objit->first, 24079ccaf77SBrad Bishop compareFirst(RelPathCompare(_root))); 24179ccaf77SBrad Bishop 24279ccaf77SBrad Bishop absPath.assign(_root); 24379ccaf77SBrad Bishop absPath.append(objit->first); 24479ccaf77SBrad Bishop 24579ccaf77SBrad Bishop newObj = false; 24679ccaf77SBrad Bishop if (refit == _refs.end() || refit->first != absPath) 24779ccaf77SBrad Bishop { 24879ccaf77SBrad Bishop refit = _refs.insert( 24979ccaf77SBrad Bishop refit, 25079ccaf77SBrad Bishop std::make_pair( 25179ccaf77SBrad Bishop absPath, 25279ccaf77SBrad Bishop decltype(_refs)::mapped_type())); 25379ccaf77SBrad Bishop newObj = true; 25479ccaf77SBrad Bishop } 25579ccaf77SBrad Bishop 25679ccaf77SBrad Bishop updateInterfaces(absPath, objit->second, refit, newObj); 25779ccaf77SBrad Bishop ++objit; 25879ccaf77SBrad Bishop } 25979ccaf77SBrad Bishop } 26079ccaf77SBrad Bishop 26103f4cd95SBrad Bishop void Manager::notify(std::map<sdbusplus::message::object_path, Object> objs) 26249aefb31SBrad Bishop { 263cda036f7SBrad Bishop updateObjects(objs); 26449aefb31SBrad Bishop } 26549aefb31SBrad Bishop 26648547a85SBrad Bishop void Manager::handleEvent( 26768c80839SBrad Bishop sdbusplus::message::message& msg, 26812f8a3c8SBrad Bishop const Event& event, 26968c80839SBrad Bishop const EventInfo& info) 27049aefb31SBrad Bishop { 27168c80839SBrad Bishop auto& actions = std::get<1>(info); 2723d57f507SBrad Bishop 27348547a85SBrad Bishop for (auto& f : event) 2747b33777bSBrad Bishop { 27507934a64SBrad Bishop if (!f(_bus, msg, *this)) 276064c94a6SBrad Bishop { 277064c94a6SBrad Bishop return; 278064c94a6SBrad Bishop } 279064c94a6SBrad Bishop } 2809007432aSBrad Bishop for (auto& action : actions) 2817b33777bSBrad Bishop { 28207934a64SBrad Bishop action(_bus, *this); 2833d57f507SBrad Bishop } 28449aefb31SBrad Bishop } 28549aefb31SBrad Bishop 2867b7e712cSBrad Bishop void Manager::destroyObjects( 2877b7e712cSBrad Bishop const std::vector<const char*>& paths) 2887b7e712cSBrad Bishop { 289a5cc34c2SBrad Bishop std::string p; 290a5cc34c2SBrad Bishop 2917b7e712cSBrad Bishop for (const auto& path : paths) 292656a7d00SBrad Bishop { 293a5cc34c2SBrad Bishop p.assign(_root); 294a5cc34c2SBrad Bishop p.append(path); 295a5cc34c2SBrad Bishop _bus.emit_object_removed(p.c_str()); 296a5cc34c2SBrad Bishop _refs.erase(p); 297656a7d00SBrad Bishop } 2987b7e712cSBrad Bishop } 299656a7d00SBrad Bishop 300eb68a687SBrad Bishop void Manager::createObjects( 301eb68a687SBrad Bishop const std::map<sdbusplus::message::object_path, Object>& objs) 302eb68a687SBrad Bishop { 303cda036f7SBrad Bishop updateObjects(objs); 304eb68a687SBrad Bishop } 305eb68a687SBrad Bishop 306150147aeSBrad Bishop any_ns::any& Manager::getInterfaceHolder( 307b83a21eaSBrad Bishop const char* path, const char* interface) 308b83a21eaSBrad Bishop { 309150147aeSBrad Bishop return const_cast<any_ns::any&>( 310150147aeSBrad Bishop const_cast<const Manager*>( 311150147aeSBrad Bishop this)->getInterfaceHolder(path, interface)); 312b83a21eaSBrad Bishop } 313b83a21eaSBrad Bishop 314150147aeSBrad Bishop const any_ns::any& Manager::getInterfaceHolder( 315b83a21eaSBrad Bishop const char* path, const char* interface) const 316b83a21eaSBrad Bishop { 317b83a21eaSBrad Bishop std::string p{path}; 318b83a21eaSBrad Bishop auto oit = _refs.find(_root + p); 319b83a21eaSBrad Bishop if (oit == _refs.end()) 320b83a21eaSBrad Bishop throw std::runtime_error( 321b83a21eaSBrad Bishop _root + p + " was not found"); 322b83a21eaSBrad Bishop 323b83a21eaSBrad Bishop auto& obj = oit->second; 324b83a21eaSBrad Bishop auto iit = obj.find(interface); 325b83a21eaSBrad Bishop if (iit == obj.end()) 326b83a21eaSBrad Bishop throw std::runtime_error( 327b83a21eaSBrad Bishop "interface was not found"); 328b83a21eaSBrad Bishop 329150147aeSBrad Bishop return iit->second; 330b83a21eaSBrad Bishop } 331b83a21eaSBrad Bishop 33249aefb31SBrad Bishop } // namespace manager 33349aefb31SBrad Bishop } // namespace inventory 33449aefb31SBrad Bishop } // namespace phosphor 33549aefb31SBrad Bishop 33649aefb31SBrad Bishop // vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 337