/* * Copyright (c) 2011-2015, Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include <algorithm> #include "SystemClass.h" #include "SubsystemLibrary.h" #include "VirtualSubsystem.h" #include "LoggingElementBuilderTemplate.h" #include <cassert> #include "PluginLocation.h" #include "DynamicLibrary.hpp" #include "Utility.h" #include "Memory.hpp" #define base CConfigurableElement #ifndef PARAMETER_FRAMEWORK_PLUGIN_ENTRYPOINT_V1 #error Missing PARAMETER_FRAMEWORK_PLUGIN_ENTRYPOINT_V1 macro definition #endif #define QUOTE(X) #X #define MACRO_TO_STR(X) QUOTE(X) const char CSystemClass::entryPointSymbol[] = MACRO_TO_STR(PARAMETER_FRAMEWORK_PLUGIN_ENTRYPOINT_V1); using PluginEntryPointV1 = void (*)(CSubsystemLibrary *, core::log::Logger &); using std::list; using std::string; // FIXME: integrate SystemClass to core namespace using namespace core; CSystemClass::CSystemClass(log::Logger &logger) : _pSubsystemLibrary(new CSubsystemLibrary()), _logger(logger) { } CSystemClass::~CSystemClass() { delete _pSubsystemLibrary; // Destroy child subsystems *before* unloading the libraries (otherwise crashes will occur // as unmapped code will be referenced) clean(); } bool CSystemClass::childrenAreDynamic() const { return true; } string CSystemClass::getKind() const { return "SystemClass"; } bool CSystemClass::getMappingData(const std::string & /*strKey*/, const std::string *& /*pStrValue*/) const { // Although it could make sense to have mapping in the system class, // just like at subsystem level, it is currently not supported. return false; } string CSystemClass::getFormattedMapping() const { return ""; } bool CSystemClass::loadSubsystems(string &strError, const CSubsystemPlugins *pSubsystemPlugins, bool bVirtualSubsystemFallback) { // Start clean _pSubsystemLibrary->clean(); typedef TLoggingElementBuilderTemplate<CVirtualSubsystem> VirtualSubsystemBuilder; // Add virtual subsystem builder _pSubsystemLibrary->addElementBuilder("Virtual", new VirtualSubsystemBuilder(_logger)); // Set virtual subsytem as builder fallback if required if (bVirtualSubsystemFallback) { _pSubsystemLibrary->setDefaultBuilder( utility::make_unique<VirtualSubsystemBuilder>(_logger)); } // Add subsystem defined in shared libraries core::Results errors; bool bLoadPluginsSuccess = loadSubsystemsFromSharedLibraries(errors, pSubsystemPlugins); // Fill strError for caller, he has to decide if there is a problem depending on // bVirtualSubsystemFallback value strError = utility::asString(errors); return bLoadPluginsSuccess || bVirtualSubsystemFallback; } bool CSystemClass::loadSubsystemsFromSharedLibraries(core::Results &errors, const CSubsystemPlugins *pSubsystemPlugins) { // Plugin list list<string> lstrPluginFiles; size_t pluginLocation; for (pluginLocation = 0; pluginLocation < pSubsystemPlugins->getNbChildren(); pluginLocation++) { // Get Folder for current Plugin Location const CPluginLocation *pPluginLocation = static_cast<const CPluginLocation *>(pSubsystemPlugins->getChild(pluginLocation)); string strFolder(pPluginLocation->getFolder()); if (!strFolder.empty()) { strFolder += "/"; } // Iterator on Plugin List: list<string>::const_iterator it; const list<string> &pluginList = pPluginLocation->getPluginList(); for (it = pluginList.begin(); it != pluginList.end(); ++it) { // Fill Plugin files list lstrPluginFiles.push_back(strFolder + *it); } } // Actually load plugins while (!lstrPluginFiles.empty()) { // Because plugins might depend on one another, loading will be done // as an iteration process that finishes successfully when the remaining // list of plugins to load gets empty or unsuccessfully if the loading // process failed to load at least one of them // Attempt to load the complete list if (!loadPlugins(lstrPluginFiles, errors)) { // Unable to load at least one plugin break; } } if (!lstrPluginFiles.empty()) { // Unable to load at least one plugin errors.push_back("Unable to load the following plugins: " + utility::asString(lstrPluginFiles, ", ") + "."); return false; } return true; } // Plugin loading bool CSystemClass::loadPlugins(list<string> &lstrPluginFiles, core::Results &errors) { assert(lstrPluginFiles.size()); bool bAtLeastOneSubsystemPluginSuccessfullyLoaded = false; list<string>::iterator it = lstrPluginFiles.begin(); while (it != lstrPluginFiles.end()) { string strPluginFileName = *it; // Load attempt try { auto library = utility::make_unique<DynamicLibrary>(strPluginFileName); // Load symbol from library auto subSystemBuilder = library->getSymbol<PluginEntryPointV1>(entryPointSymbol); // Store libraries handles _subsystemLibraryHandleList.push_back(std::move(library)); // Fill library subSystemBuilder(_pSubsystemLibrary, _logger); } catch (std::exception &e) { errors.push_back(e.what()); // Next plugin ++it; continue; } // Account for this success bAtLeastOneSubsystemPluginSuccessfullyLoaded = true; // Remove successfully loaded plugin from list and select next lstrPluginFiles.erase(it++); } return bAtLeastOneSubsystemPluginSuccessfullyLoaded; } const CSubsystemLibrary *CSystemClass::getSubsystemLibrary() const { return _pSubsystemLibrary; } void CSystemClass::checkForSubsystemsToResync(CSyncerSet &syncerSet, core::Results &infos) { size_t uiNbChildren = getNbChildren(); size_t uiChild; for (uiChild = 0; uiChild < uiNbChildren; uiChild++) { CSubsystem *pSubsystem = static_cast<CSubsystem *>(getChild(uiChild)); // Collect and consume the need for a resync if (pSubsystem->needResync(true)) { infos.push_back("Resynchronizing subsystem: " + pSubsystem->getName()); // get all subsystem syncers pSubsystem->fillSyncerSet(syncerSet); } } } void CSystemClass::cleanSubsystemsNeedToResync() { size_t uiNbChildren = getNbChildren(); size_t uiChild; for (uiChild = 0; uiChild < uiNbChildren; uiChild++) { CSubsystem *pSubsystem = static_cast<CSubsystem *>(getChild(uiChild)); // Consume the need for a resync pSubsystem->needResync(true); } }