| /* |
| * 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); |
| } |
| } |