diff options
Diffstat (limited to 'upstream/parameter/SystemClass.cpp')
| -rw-r--r-- | upstream/parameter/SystemClass.cpp | 259 |
1 files changed, 259 insertions, 0 deletions
diff --git a/upstream/parameter/SystemClass.cpp b/upstream/parameter/SystemClass.cpp new file mode 100644 index 0000000..21c7a86 --- /dev/null +++ b/upstream/parameter/SystemClass.cpp @@ -0,0 +1,259 @@ +/* + * 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); + } +} |
