Home | History | Annotate | Download | only in parameter
      1 /*
      2  * Copyright (c) 2011-2015, Intel Corporation
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without modification,
      6  * are permitted provided that the following conditions are met:
      7  *
      8  * 1. Redistributions of source code must retain the above copyright notice, this
      9  * list of conditions and the following disclaimer.
     10  *
     11  * 2. Redistributions in binary form must reproduce the above copyright notice,
     12  * this list of conditions and the following disclaimer in the documentation and/or
     13  * other materials provided with the distribution.
     14  *
     15  * 3. Neither the name of the copyright holder nor the names of its contributors
     16  * may be used to endorse or promote products derived from this software without
     17  * specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
     20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     22  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
     23  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
     26  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 #include <algorithm>
     31 #include "SystemClass.h"
     32 #include "SubsystemLibrary.h"
     33 #include "VirtualSubsystem.h"
     34 #include "LoggingElementBuilderTemplate.h"
     35 #include <cassert>
     36 #include "PluginLocation.h"
     37 #include "DynamicLibrary.hpp"
     38 #include "Utility.h"
     39 #include "Memory.hpp"
     40 
     41 #define base CConfigurableElement
     42 
     43 #ifndef PARAMETER_FRAMEWORK_PLUGIN_ENTRYPOINT_V1
     44 #error Missing PARAMETER_FRAMEWORK_PLUGIN_ENTRYPOINT_V1 macro definition
     45 #endif
     46 #define QUOTE(X) #X
     47 #define MACRO_TO_STR(X) QUOTE(X)
     48 const char CSystemClass::entryPointSymbol[] =
     49     MACRO_TO_STR(PARAMETER_FRAMEWORK_PLUGIN_ENTRYPOINT_V1);
     50 using PluginEntryPointV1 = void (*)(CSubsystemLibrary *, core::log::Logger &);
     51 
     52 using std::list;
     53 using std::string;
     54 
     55 // FIXME: integrate SystemClass to core namespace
     56 using namespace core;
     57 
     58 CSystemClass::CSystemClass(log::Logger &logger)
     59     : _pSubsystemLibrary(new CSubsystemLibrary()), _logger(logger)
     60 {
     61 }
     62 
     63 CSystemClass::~CSystemClass()
     64 {
     65     delete _pSubsystemLibrary;
     66 
     67     // Destroy child subsystems *before* unloading the libraries (otherwise crashes will occur
     68     // as unmapped code will be referenced)
     69     clean();
     70 }
     71 
     72 bool CSystemClass::childrenAreDynamic() const
     73 {
     74     return true;
     75 }
     76 
     77 string CSystemClass::getKind() const
     78 {
     79     return "SystemClass";
     80 }
     81 
     82 bool CSystemClass::getMappingData(const std::string & /*strKey*/,
     83                                   const std::string *& /*pStrValue*/) const
     84 {
     85     // Although it could make sense to have mapping in the system class,
     86     // just like at subsystem level, it is currently not supported.
     87     return false;
     88 }
     89 
     90 string CSystemClass::getFormattedMapping() const
     91 {
     92     return "";
     93 }
     94 
     95 bool CSystemClass::loadSubsystems(string &strError, const CSubsystemPlugins *pSubsystemPlugins,
     96                                   bool bVirtualSubsystemFallback)
     97 {
     98     // Start clean
     99     _pSubsystemLibrary->clean();
    100 
    101     typedef TLoggingElementBuilderTemplate<CVirtualSubsystem> VirtualSubsystemBuilder;
    102     // Add virtual subsystem builder
    103     _pSubsystemLibrary->addElementBuilder("Virtual", new VirtualSubsystemBuilder(_logger));
    104     // Set virtual subsytem as builder fallback if required
    105     if (bVirtualSubsystemFallback) {
    106         _pSubsystemLibrary->setDefaultBuilder(
    107             utility::make_unique<VirtualSubsystemBuilder>(_logger));
    108     }
    109 
    110     // Add subsystem defined in shared libraries
    111     core::Results errors;
    112     bool bLoadPluginsSuccess = loadSubsystemsFromSharedLibraries(errors, pSubsystemPlugins);
    113 
    114     // Fill strError for caller, he has to decide if there is a problem depending on
    115     // bVirtualSubsystemFallback value
    116     strError = utility::asString(errors);
    117 
    118     return bLoadPluginsSuccess || bVirtualSubsystemFallback;
    119 }
    120 
    121 bool CSystemClass::loadSubsystemsFromSharedLibraries(core::Results &errors,
    122                                                      const CSubsystemPlugins *pSubsystemPlugins)
    123 {
    124     // Plugin list
    125     list<string> lstrPluginFiles;
    126 
    127     size_t pluginLocation;
    128 
    129     for (pluginLocation = 0; pluginLocation < pSubsystemPlugins->getNbChildren();
    130          pluginLocation++) {
    131 
    132         // Get Folder for current Plugin Location
    133         const CPluginLocation *pPluginLocation =
    134             static_cast<const CPluginLocation *>(pSubsystemPlugins->getChild(pluginLocation));
    135 
    136         string strFolder(pPluginLocation->getFolder());
    137         if (!strFolder.empty()) {
    138             strFolder += "/";
    139         }
    140         // Iterator on Plugin List:
    141         list<string>::const_iterator it;
    142 
    143         const list<string> &pluginList = pPluginLocation->getPluginList();
    144 
    145         for (it = pluginList.begin(); it != pluginList.end(); ++it) {
    146 
    147             // Fill Plugin files list
    148             lstrPluginFiles.push_back(strFolder + *it);
    149         }
    150     }
    151 
    152     // Actually load plugins
    153     while (!lstrPluginFiles.empty()) {
    154 
    155         // Because plugins might depend on one another, loading will be done
    156         // as an iteration process that finishes successfully when the remaining
    157         // list of plugins to load gets empty or unsuccessfully if the loading
    158         // process failed to load at least one of them
    159 
    160         // Attempt to load the complete list
    161         if (!loadPlugins(lstrPluginFiles, errors)) {
    162 
    163             // Unable to load at least one plugin
    164             break;
    165         }
    166     }
    167 
    168     if (!lstrPluginFiles.empty()) {
    169         // Unable to load at least one plugin
    170         errors.push_back("Unable to load the following plugins: " +
    171                          utility::asString(lstrPluginFiles, ", ") + ".");
    172         return false;
    173     }
    174 
    175     return true;
    176 }
    177 
    178 // Plugin loading
    179 bool CSystemClass::loadPlugins(list<string> &lstrPluginFiles, core::Results &errors)
    180 {
    181     assert(lstrPluginFiles.size());
    182 
    183     bool bAtLeastOneSubsystemPluginSuccessfullyLoaded = false;
    184 
    185     list<string>::iterator it = lstrPluginFiles.begin();
    186 
    187     while (it != lstrPluginFiles.end()) {
    188 
    189         string strPluginFileName = *it;
    190 
    191         // Load attempt
    192         try {
    193             auto library = utility::make_unique<DynamicLibrary>(strPluginFileName);
    194 
    195             // Load symbol from library
    196             auto subSystemBuilder = library->getSymbol<PluginEntryPointV1>(entryPointSymbol);
    197 
    198             // Store libraries handles
    199             _subsystemLibraryHandleList.push_back(std::move(library));
    200 
    201             // Fill library
    202             subSystemBuilder(_pSubsystemLibrary, _logger);
    203 
    204         } catch (std::exception &e) {
    205             errors.push_back(e.what());
    206 
    207             // Next plugin
    208             ++it;
    209 
    210             continue;
    211         }
    212 
    213         // Account for this success
    214         bAtLeastOneSubsystemPluginSuccessfullyLoaded = true;
    215 
    216         // Remove successfully loaded plugin from list and select next
    217         lstrPluginFiles.erase(it++);
    218     }
    219 
    220     return bAtLeastOneSubsystemPluginSuccessfullyLoaded;
    221 }
    222 
    223 const CSubsystemLibrary *CSystemClass::getSubsystemLibrary() const
    224 {
    225     return _pSubsystemLibrary;
    226 }
    227 
    228 void CSystemClass::checkForSubsystemsToResync(CSyncerSet &syncerSet, core::Results &infos)
    229 {
    230     size_t uiNbChildren = getNbChildren();
    231     size_t uiChild;
    232 
    233     for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
    234 
    235         CSubsystem *pSubsystem = static_cast<CSubsystem *>(getChild(uiChild));
    236 
    237         // Collect and consume the need for a resync
    238         if (pSubsystem->needResync(true)) {
    239 
    240             infos.push_back("Resynchronizing subsystem: " + pSubsystem->getName());
    241             // get all subsystem syncers
    242             pSubsystem->fillSyncerSet(syncerSet);
    243         }
    244     }
    245 }
    246 
    247 void CSystemClass::cleanSubsystemsNeedToResync()
    248 {
    249     size_t uiNbChildren = getNbChildren();
    250     size_t uiChild;
    251 
    252     for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
    253 
    254         CSubsystem *pSubsystem = static_cast<CSubsystem *>(getChild(uiChild));
    255 
    256         // Consume the need for a resync
    257         pSubsystem->needResync(true);
    258     }
    259 }
    260