You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
260 lines
8.2 KiB
260 lines
8.2 KiB
/*
|
|
* 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;
|
|
|
|
auto 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);
|
|
}
|
|
}
|