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> 19*79ccaf77SBrad Bishop #include <algorithm> 209bbfcb18SBrad Bishop #include <log.hpp> 2149aefb31SBrad Bishop #include "manager.hpp" 22*79ccaf77SBrad 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)), 6849aefb31SBrad Bishop _manager(sdbusplus::server::manager::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 145*79ccaf77SBrad Bishop void Manager::updateInterfaces( 146*79ccaf77SBrad Bishop const sdbusplus::message::object_path& path, 147*79ccaf77SBrad Bishop const Object& interfaces, 148*79ccaf77SBrad Bishop ObjectReferences::iterator pos, 149*79ccaf77SBrad Bishop bool newObject) 150*79ccaf77SBrad Bishop { 151*79ccaf77SBrad Bishop auto& refaces = pos->second; 152*79ccaf77SBrad Bishop auto ifaceit = interfaces.cbegin(); 153*79ccaf77SBrad Bishop auto opsit = _makers.cbegin(); 154*79ccaf77SBrad Bishop auto refaceit = refaces.begin(); 155*79ccaf77SBrad Bishop std::vector<std::string> signals; 156*79ccaf77SBrad Bishop 157*79ccaf77SBrad Bishop while (ifaceit != interfaces.cend()) 158*79ccaf77SBrad Bishop { 159*79ccaf77SBrad Bishop try 160*79ccaf77SBrad Bishop { 161*79ccaf77SBrad Bishop // Find the binding ops for this interface. 162*79ccaf77SBrad Bishop opsit = std::lower_bound( 163*79ccaf77SBrad Bishop opsit, 164*79ccaf77SBrad Bishop _makers.cend(), 165*79ccaf77SBrad Bishop ifaceit->first, 166*79ccaf77SBrad Bishop compareFirst(_makers.key_comp())); 167*79ccaf77SBrad Bishop 168*79ccaf77SBrad Bishop if (opsit == _makers.cend() || opsit->first != ifaceit->first) 169*79ccaf77SBrad Bishop { 170*79ccaf77SBrad Bishop // This interface is not supported. 171*79ccaf77SBrad Bishop throw InterfaceError( 172*79ccaf77SBrad Bishop "Encountered unsupported interface.", 173*79ccaf77SBrad Bishop ifaceit->first); 174*79ccaf77SBrad Bishop } 175*79ccaf77SBrad Bishop 176*79ccaf77SBrad Bishop // Find the binding insertion point or the binding to update. 177*79ccaf77SBrad Bishop refaceit = std::lower_bound( 178*79ccaf77SBrad Bishop refaceit, 179*79ccaf77SBrad Bishop refaces.end(), 180*79ccaf77SBrad Bishop ifaceit->first, 181*79ccaf77SBrad Bishop compareFirst(refaces.key_comp())); 182*79ccaf77SBrad Bishop 183*79ccaf77SBrad Bishop if (refaceit == refaces.end() || refaceit->first != ifaceit->first) 184*79ccaf77SBrad Bishop { 185*79ccaf77SBrad Bishop // Add the new interface. 186*79ccaf77SBrad Bishop auto& ctor = std::get<MakerType>(opsit->second); 187*79ccaf77SBrad Bishop refaceit = refaces.insert( 188*79ccaf77SBrad Bishop refaceit, 189*79ccaf77SBrad Bishop std::make_pair( 190*79ccaf77SBrad Bishop ifaceit->first, 191*79ccaf77SBrad Bishop ctor( 192*79ccaf77SBrad Bishop _bus, 193*79ccaf77SBrad Bishop path.str.c_str(), 194*79ccaf77SBrad Bishop ifaceit->second))); 195*79ccaf77SBrad Bishop signals.push_back(ifaceit->first); 196*79ccaf77SBrad Bishop } 197*79ccaf77SBrad Bishop else 198*79ccaf77SBrad Bishop { 199*79ccaf77SBrad Bishop // Set the new property values. 200*79ccaf77SBrad Bishop auto& assign = std::get<AssignerType>(opsit->second); 201*79ccaf77SBrad Bishop assign(ifaceit->second, refaceit->second); 202*79ccaf77SBrad Bishop } 203*79ccaf77SBrad Bishop } 204*79ccaf77SBrad Bishop catch (const InterfaceError& e) 205*79ccaf77SBrad Bishop { 206*79ccaf77SBrad Bishop // Reset the binding ops iterator since we are 207*79ccaf77SBrad Bishop // at the end. 208*79ccaf77SBrad Bishop opsit = _makers.cbegin(); 209*79ccaf77SBrad Bishop e.log(); 210*79ccaf77SBrad Bishop } 211*79ccaf77SBrad Bishop 212*79ccaf77SBrad Bishop ++ifaceit; 213*79ccaf77SBrad Bishop } 214*79ccaf77SBrad Bishop 215*79ccaf77SBrad Bishop if (newObject) 216*79ccaf77SBrad Bishop { 217*79ccaf77SBrad Bishop _bus.emit_object_added(path.str.c_str()); 218*79ccaf77SBrad Bishop } 219*79ccaf77SBrad Bishop else if (!signals.empty()) 220*79ccaf77SBrad Bishop { 221*79ccaf77SBrad Bishop // TODO: emit an interfaces added signal 222*79ccaf77SBrad Bishop } 223*79ccaf77SBrad Bishop } 224*79ccaf77SBrad Bishop 225*79ccaf77SBrad Bishop void Manager::updateObjects( 226*79ccaf77SBrad Bishop const std::map<sdbusplus::message::object_path, Object>& objs) 227*79ccaf77SBrad Bishop { 228*79ccaf77SBrad Bishop auto objit = objs.cbegin(); 229*79ccaf77SBrad Bishop auto refit = _refs.begin(); 230*79ccaf77SBrad Bishop std::string absPath; 231*79ccaf77SBrad Bishop bool newObj; 232*79ccaf77SBrad Bishop 233*79ccaf77SBrad Bishop while (objit != objs.cend()) 234*79ccaf77SBrad Bishop { 235*79ccaf77SBrad Bishop // Find the insertion point or the object to update. 236*79ccaf77SBrad Bishop refit = std::lower_bound( 237*79ccaf77SBrad Bishop refit, 238*79ccaf77SBrad Bishop _refs.end(), 239*79ccaf77SBrad Bishop objit->first, 240*79ccaf77SBrad Bishop compareFirst(RelPathCompare(_root))); 241*79ccaf77SBrad Bishop 242*79ccaf77SBrad Bishop absPath.assign(_root); 243*79ccaf77SBrad Bishop absPath.append(objit->first); 244*79ccaf77SBrad Bishop 245*79ccaf77SBrad Bishop newObj = false; 246*79ccaf77SBrad Bishop if (refit == _refs.end() || refit->first != absPath) 247*79ccaf77SBrad Bishop { 248*79ccaf77SBrad Bishop refit = _refs.insert( 249*79ccaf77SBrad Bishop refit, 250*79ccaf77SBrad Bishop std::make_pair( 251*79ccaf77SBrad Bishop absPath, 252*79ccaf77SBrad Bishop decltype(_refs)::mapped_type())); 253*79ccaf77SBrad Bishop newObj = true; 254*79ccaf77SBrad Bishop } 255*79ccaf77SBrad Bishop 256*79ccaf77SBrad Bishop updateInterfaces(absPath, objit->second, refit, newObj); 257*79ccaf77SBrad Bishop ++objit; 258*79ccaf77SBrad Bishop } 259*79ccaf77SBrad Bishop } 260*79ccaf77SBrad 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