/* -------------------------------------------------------------------------- */ /* Copyright 2002-2019, OpenNebula Project, OpenNebula Systems */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); you may */ /* not use this file except in compliance with the License. You may obtain */ /* a copy of the License at */ /* */ /* http://www.apache.org/licenses/LICENSE-2.0 */ /* */ /* Unless required by applicable law or agreed to in writing, software */ /* distributed under the License is distributed on an "AS IS" BASIS, */ /* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ /* See the License for the specific language governing permissions and */ /* limitations under the License. */ /* -------------------------------------------------------------------------- */ #ifndef DRIVER_MANAGER_H_ #define DRIVER_MANAGER_H_ #include "Driver.h" #include "Attribute.h" #include "NebulaLog.h" #include template class DriverManager { public: explicit DriverManager(const string& mad_location) : mad_location(mad_location) { } virtual ~DriverManager() = default; int load_drivers(const vector& mads_config); D * get_driver(const std::string& name) const; /** * Register an action for a given message type. The action is registered * for all installed drivers. Must be called after load_drivers method. */ void register_action(E t, std::function>)> a); /** * Start all drivers */ int start(std::string& error); /** * Stop all drivers * @param secs to wait for each driver before killing it */ void stop(int secs); private: std::map> drivers; string mad_location; }; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ template int DriverManager::load_drivers(const vector& mads_config) { NebulaLog::info("DrM", "Loading drivers."); for (const auto& vattr : mads_config) { auto name = vattr->vector_value("NAME"); auto exec = vattr->vector_value("EXECUTABLE"); auto args = vattr->vector_value("ARGUMENTS"); int threads; vattr->vector_value("THREADS", threads, 0); NebulaLog::info("InM", "Loading driver: " + name); if (exec.empty()) { NebulaLog::error("InM", "\tEmpty executable for driver: " + name); return -1; } if (exec[0] != '/') //Look in ONE_LOCATION/lib/mads or in "/usr/lib/one/mads" { exec = mad_location + exec; } if (access(exec.c_str(), F_OK) != 0) { NebulaLog::error("InM", "File not exists: " + exec); return -1; } auto rc = drivers.insert(std::make_pair(name, std::unique_ptr(new D(exec, args, threads)))); if (rc.second) { NebulaLog::info("InM", "\tDriver loaded: " + name); } else { NebulaLog::error("InM", "\tDriver already exists: " + name); return -1; } } return 0; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ template D * DriverManager::get_driver(const std::string& name) const { auto driver = drivers.find(name); if (driver == drivers.end()) { return nullptr; } return driver->second.get(); } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ template void DriverManager::register_action(E t, std::function>)> a) { for (auto& driver : drivers) { driver.second->register_action(t, a); } } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ template int DriverManager::start(std::string& error) { for (auto& driver : drivers) { auto rc = driver.second->start(error); if (rc != 0) { NebulaLog::error("DrM", "Unable to start driver: " + error); return rc; } } return 0; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ template void DriverManager::stop(int secs) { vector threads; for (auto& driver : drivers) { int _secs = secs; threads.push_back(thread([_secs, &driver] () { driver.second->stop(_secs); })); } for (auto& thr : threads) { thr.join(); } } #endif // DRIVER_MANAGER_H_