1 /** 2 * Copyright © 2016 IBM Corporation 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #include <iostream> 17 #include <exception> 18 #include "manager.hpp" 19 20 namespace phosphor 21 { 22 namespace inventory 23 { 24 namespace manager 25 { 26 namespace details 27 { 28 29 /** @brief Fowrarding signal callback. 30 * 31 * Extracts per-signal specific context and forwards the call to the manager 32 * instance. 33 */ 34 auto _signal(sd_bus_message *m, void *data, sd_bus_error *e) noexcept 35 { 36 try { 37 auto msg = sdbusplus::message::message(m); 38 auto &args = *static_cast<Manager::SigArg*>(data); 39 sd_bus_message_ref(m); 40 auto &mgr = *std::get<0>(args); 41 mgr.signal(msg, *std::get<1>(args)); 42 } 43 catch (const std::exception &e) { 44 std::cerr << e.what() << std::endl; 45 } 46 47 return 0; 48 } 49 50 } // namespace details 51 52 Manager::Manager( 53 sdbusplus::bus::bus &&bus, 54 const char *busname, 55 const char *root, 56 const char *iface) : 57 details::ServerObject<details::ManagerIface>(bus, root), 58 _shutdown(false), 59 _root(root), 60 _bus(std::move(bus)), 61 _manager(sdbusplus::server::manager::manager(_bus, root)) 62 { 63 for (auto &x: _events) { 64 // Create a callback context for each event. 65 _sigargs.emplace_back( 66 std::make_unique<SigArg>( 67 std::make_tuple( 68 this, 69 &x))); 70 // Register our callback and the context for 71 // each event. 72 _matches.emplace_back( 73 sdbusplus::server::match::match( 74 _bus, 75 std::get<0>(x), 76 details::_signal, 77 _sigargs.back().get())); 78 } 79 80 _bus.request_name(busname); 81 } 82 83 void Manager::shutdown() noexcept 84 { 85 _shutdown = true; 86 } 87 88 void Manager::run() noexcept 89 { 90 while(!_shutdown) { 91 try { 92 _bus.process_discard(); 93 _bus.wait(5000000); 94 } 95 catch (const std::exception &e) { 96 std::cerr << e.what() << std::endl; 97 } 98 } 99 } 100 101 void Manager::notify(std::string path, Object object) 102 { 103 try { 104 if(object.cbegin() == object.cend()) 105 throw std::runtime_error( 106 "No interfaces in " + path); 107 108 path.insert(0, _root); 109 110 auto obj = _refs.find(path); 111 if(obj != _refs.end()) 112 throw std::runtime_error( 113 obj->first + " already exists"); 114 115 // Create an interface holder for each interface 116 // provided by the client and group them into 117 // a container. 118 InterfaceComposite ref; 119 120 for (auto &x: object) { 121 auto maker = _makers.find(x.first.c_str()); 122 123 if(maker == _makers.end()) 124 throw std::runtime_error( 125 "Unimplemented interface: " + x.first); 126 127 ref.emplace( 128 std::make_pair( 129 x.first, 130 (maker->second)(_bus, path.c_str()))); 131 } 132 133 // Hang on to a reference to the object (interfaces) 134 // so it stays on the bus, and so we can make calls 135 // to it if needed. 136 _refs.emplace( 137 std::make_pair( 138 path, std::move(ref))); 139 } 140 catch (const std::exception &e) { 141 std::cerr << e.what() << std::endl; 142 } 143 } 144 145 void Manager::signal(sdbusplus::message::message &msg, auto &args) 146 { 147 auto &filter = *std::get<1>(args); 148 auto &actions = std::get<2>(args); 149 150 if(filter(msg, *this)) { 151 for (auto &action: actions) 152 (*action)(*this); 153 } 154 } 155 156 void Manager::destroyObject(const char *path) 157 { 158 std::string p{path}; 159 _refs.erase(_root + p); 160 } 161 162 } // namespace manager 163 } // namespace inventory 164 } // namespace phosphor 165 166 // vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 167