1ee7ceed5cca416718c70f3ca55fe41b8eb1e11a3Kevin Rocard/*
2b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner * Copyright (c) 2011-2014, Intel Corporation
3b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner * All rights reserved.
4ee7ceed5cca416718c70f3ca55fe41b8eb1e11a3Kevin Rocard *
5b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner * Redistribution and use in source and binary forms, with or without modification,
6b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner * are permitted provided that the following conditions are met:
7ee7ceed5cca416718c70f3ca55fe41b8eb1e11a3Kevin Rocard *
8b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner * 1. Redistributions of source code must retain the above copyright notice, this
9b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner * list of conditions and the following disclaimer.
10ee7ceed5cca416718c70f3ca55fe41b8eb1e11a3Kevin Rocard *
11b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner * 2. Redistributions in binary form must reproduce the above copyright notice,
12b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner * this list of conditions and the following disclaimer in the documentation and/or
13b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner * other materials provided with the distribution.
14b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner *
15b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner * 3. Neither the name of the copyright holder nor the names of its contributors
16b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner * may be used to endorse or promote products derived from this software without
17b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner * specific prior written permission.
18b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner *
19b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
23b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2968a912857707864bbaaff9808717813105072a6ePatrick Benavoli */
3068a912857707864bbaaff9808717813105072a6ePatrick Benavoli#include <dlfcn.h>
3168a912857707864bbaaff9808717813105072a6ePatrick Benavoli#include <dirent.h>
32ec0f84e3f601ac4ffb029b903c06007956c4b02aPatrick Benavoli#include <algorithm>
33ec0f84e3f601ac4ffb029b903c06007956c4b02aPatrick Benavoli#include <ctype.h>
3468a912857707864bbaaff9808717813105072a6ePatrick Benavoli#include "SystemClass.h"
3568a912857707864bbaaff9808717813105072a6ePatrick Benavoli#include "SubsystemLibrary.h"
3668a912857707864bbaaff9808717813105072a6ePatrick Benavoli#include "AutoLog.h"
376ccab9d382c08323fb1f000d859a696f05719c92Patrick Benavoli#include "VirtualSubsystem.h"
386ccab9d382c08323fb1f000d859a696f05719c92Patrick Benavoli#include "NamedElementBuilderTemplate.h"
399bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli#include <assert.h>
40a4ec15d5d5e84fbee3faa46a66e7b1eb90816ce2Guillaume Denneulin#include "PluginLocation.h"
41ee7ceed5cca416718c70f3ca55fe41b8eb1e11a3Kevin Rocard#include "Utility.h"
4268a912857707864bbaaff9808717813105072a6ePatrick Benavoli
4368a912857707864bbaaff9808717813105072a6ePatrick Benavoli#define base CConfigurableElement
4468a912857707864bbaaff9808717813105072a6ePatrick Benavoli
45d9526499d6ab53b7d13d1434f748f6f2161c2e0aSebastien Gonzalveusing std::list;
46d9526499d6ab53b7d13d1434f748f6f2161c2e0aSebastien Gonzalveusing std::string;
47d9526499d6ab53b7d13d1434f748f6f2161c2e0aSebastien Gonzalve
48d5679acf4b38db415bd25b0c3664d69cec5f43d4Frédéric Boisnard/**
49d5679acf4b38db415bd25b0c3664d69cec5f43d4Frédéric Boisnard * A plugin file name is of the form:
50d5679acf4b38db415bd25b0c3664d69cec5f43d4Frédéric Boisnard * lib<type>-subsystem.so or lib<type>-subsystem._host.so
51d5679acf4b38db415bd25b0c3664d69cec5f43d4Frédéric Boisnard *
52d5679acf4b38db415bd25b0c3664d69cec5f43d4Frédéric Boisnard * The plugin symbol is of the form:
53d5679acf4b38db415bd25b0c3664d69cec5f43d4Frédéric Boisnard * get<TYPE>SubsystemBuilder
54d5679acf4b38db415bd25b0c3664d69cec5f43d4Frédéric Boisnard*/
55ec0f84e3f601ac4ffb029b903c06007956c4b02aPatrick Benavoli// Plugin file naming
56d5679acf4b38db415bd25b0c3664d69cec5f43d4Frédéric Boisnardconst char* gpcPluginSuffix = "-subsystem";
57d5679acf4b38db415bd25b0c3664d69cec5f43d4Frédéric Boisnardconst char* gpcPluginPrefix = "lib";
58ec0f84e3f601ac4ffb029b903c06007956c4b02aPatrick Benavoli
59ec0f84e3f601ac4ffb029b903c06007956c4b02aPatrick Benavoli// Plugin symbol naming
60ec0f84e3f601ac4ffb029b903c06007956c4b02aPatrick Benavoliconst char* gpcPluginSymbolPrefix = "get";
61487ce850cc5f884f7689a2bfd55a7e1cf6eb3053Frédéric Boisnardconst char* gpcPluginSymbolSuffix = "SubsystemBuilder";
62ec0f84e3f601ac4ffb029b903c06007956c4b02aPatrick Benavoli
6368a912857707864bbaaff9808717813105072a6ePatrick Benavoli// Used by subsystem plugins
64487ce850cc5f884f7689a2bfd55a7e1cf6eb3053Frédéric Boisnardtypedef void (*GetSubsystemBuilder)(CSubsystemLibrary*);
6568a912857707864bbaaff9808717813105072a6ePatrick Benavoli
6695ac034b72580306e9246f7efa3f7ba709a02183Patrick BenavoliCSystemClass::CSystemClass() : _pSubsystemLibrary(new CSubsystemLibrary)
6768a912857707864bbaaff9808717813105072a6ePatrick Benavoli{
6868a912857707864bbaaff9808717813105072a6ePatrick Benavoli}
6968a912857707864bbaaff9808717813105072a6ePatrick Benavoli
7068a912857707864bbaaff9808717813105072a6ePatrick BenavoliCSystemClass::~CSystemClass()
7168a912857707864bbaaff9808717813105072a6ePatrick Benavoli{
7268a912857707864bbaaff9808717813105072a6ePatrick Benavoli    delete _pSubsystemLibrary;
731b8b3ca093ecd7dc8c1877352625508ca4a81728Renaud de Chivre
7479694d5d0a632ed4ca04ea42f19fb09c3fba0cdbPatrick Benavoli    // Destroy child subsystems *before* unloading the libraries (otherwise crashes will occur
7579694d5d0a632ed4ca04ea42f19fb09c3fba0cdbPatrick Benavoli    // as unmapped code will be referenced)
7679694d5d0a632ed4ca04ea42f19fb09c3fba0cdbPatrick Benavoli    clean();
7779694d5d0a632ed4ca04ea42f19fb09c3fba0cdbPatrick Benavoli
7879694d5d0a632ed4ca04ea42f19fb09c3fba0cdbPatrick Benavoli    // Close all previously opened subsystem libraries
7979694d5d0a632ed4ca04ea42f19fb09c3fba0cdbPatrick Benavoli    list<void*>::const_iterator it;
8079694d5d0a632ed4ca04ea42f19fb09c3fba0cdbPatrick Benavoli
8179694d5d0a632ed4ca04ea42f19fb09c3fba0cdbPatrick Benavoli    for (it = _subsystemLibraryHandleList.begin(); it != _subsystemLibraryHandleList.end(); ++it) {
8279694d5d0a632ed4ca04ea42f19fb09c3fba0cdbPatrick Benavoli
8379694d5d0a632ed4ca04ea42f19fb09c3fba0cdbPatrick Benavoli        dlclose(*it);
841b8b3ca093ecd7dc8c1877352625508ca4a81728Renaud de Chivre    }
8568a912857707864bbaaff9808717813105072a6ePatrick Benavoli}
8668a912857707864bbaaff9808717813105072a6ePatrick Benavoli
8768a912857707864bbaaff9808717813105072a6ePatrick Benavolibool CSystemClass::childrenAreDynamic() const
8868a912857707864bbaaff9808717813105072a6ePatrick Benavoli{
8968a912857707864bbaaff9808717813105072a6ePatrick Benavoli    return true;
9068a912857707864bbaaff9808717813105072a6ePatrick Benavoli}
9168a912857707864bbaaff9808717813105072a6ePatrick Benavoli
9268a912857707864bbaaff9808717813105072a6ePatrick Benavolistring CSystemClass::getKind() const
9368a912857707864bbaaff9808717813105072a6ePatrick Benavoli{
9468a912857707864bbaaff9808717813105072a6ePatrick Benavoli    return "SystemClass";
9568a912857707864bbaaff9808717813105072a6ePatrick Benavoli}
9668a912857707864bbaaff9808717813105072a6ePatrick Benavoli
97ee7ceed5cca416718c70f3ca55fe41b8eb1e11a3Kevin Rocardbool CSystemClass::loadSubsystems(string& strError,
986be8035935a21661833bddd3803e279652e81416Kevin Rocard                                  const CSubsystemPlugins* pSubsystemPlugins,
996be8035935a21661833bddd3803e279652e81416Kevin Rocard                                  bool bVirtualSubsystemFallback)
10068a912857707864bbaaff9808717813105072a6ePatrick Benavoli{
101ee7ceed5cca416718c70f3ca55fe41b8eb1e11a3Kevin Rocard    CAutoLog autoLog_info(this, "Loading subsystem plugins");
10268a912857707864bbaaff9808717813105072a6ePatrick Benavoli
1036be8035935a21661833bddd3803e279652e81416Kevin Rocard    // Start clean
1046be8035935a21661833bddd3803e279652e81416Kevin Rocard    _pSubsystemLibrary->clean();
1056be8035935a21661833bddd3803e279652e81416Kevin Rocard
1066be8035935a21661833bddd3803e279652e81416Kevin Rocard    // Add virtual subsystem builder
1076be8035935a21661833bddd3803e279652e81416Kevin Rocard    _pSubsystemLibrary->addElementBuilder("Virtual",
1086be8035935a21661833bddd3803e279652e81416Kevin Rocard                                          new TNamedElementBuilderTemplate<CVirtualSubsystem>());
1096be8035935a21661833bddd3803e279652e81416Kevin Rocard    // Set virtual subsytem as builder fallback if required
1106be8035935a21661833bddd3803e279652e81416Kevin Rocard    _pSubsystemLibrary->enableDefaultMechanism(bVirtualSubsystemFallback);
1116be8035935a21661833bddd3803e279652e81416Kevin Rocard
1126be8035935a21661833bddd3803e279652e81416Kevin Rocard    // Add subsystem defined in shared libraries
1136be8035935a21661833bddd3803e279652e81416Kevin Rocard    list<string> lstrError;
1146be8035935a21661833bddd3803e279652e81416Kevin Rocard    bool bLoadPluginsSuccess = loadSubsystemsFromSharedLibraries(lstrError, pSubsystemPlugins);
1156be8035935a21661833bddd3803e279652e81416Kevin Rocard
1166be8035935a21661833bddd3803e279652e81416Kevin Rocard    if (bLoadPluginsSuccess) {
1176be8035935a21661833bddd3803e279652e81416Kevin Rocard        log_info("All subsystem plugins successfully loaded");
1186be8035935a21661833bddd3803e279652e81416Kevin Rocard    } else {
1196be8035935a21661833bddd3803e279652e81416Kevin Rocard        // Log plugin as warning if no fallback available
1206be8035935a21661833bddd3803e279652e81416Kevin Rocard        log_table(!bVirtualSubsystemFallback, lstrError);
1216be8035935a21661833bddd3803e279652e81416Kevin Rocard    }
1226be8035935a21661833bddd3803e279652e81416Kevin Rocard
1236be8035935a21661833bddd3803e279652e81416Kevin Rocard    if (!bVirtualSubsystemFallback) {
1246be8035935a21661833bddd3803e279652e81416Kevin Rocard        // Any problem reported is an error as there is no fallback.
1256be8035935a21661833bddd3803e279652e81416Kevin Rocard        // Fill strError for caller.
1266be8035935a21661833bddd3803e279652e81416Kevin Rocard        CUtility::asString(lstrError, strError);
1276be8035935a21661833bddd3803e279652e81416Kevin Rocard    }
1286be8035935a21661833bddd3803e279652e81416Kevin Rocard
1296be8035935a21661833bddd3803e279652e81416Kevin Rocard    return bLoadPluginsSuccess || bVirtualSubsystemFallback;
1306be8035935a21661833bddd3803e279652e81416Kevin Rocard}
1316be8035935a21661833bddd3803e279652e81416Kevin Rocard
1326be8035935a21661833bddd3803e279652e81416Kevin Rocardbool CSystemClass::loadSubsystemsFromSharedLibraries(list<string>& lstrError,
1336be8035935a21661833bddd3803e279652e81416Kevin Rocard                                                     const CSubsystemPlugins* pSubsystemPlugins)
1346be8035935a21661833bddd3803e279652e81416Kevin Rocard{
13568a912857707864bbaaff9808717813105072a6ePatrick Benavoli    // Plugin list
1369bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli    list<string> lstrPluginFiles;
13768a912857707864bbaaff9808717813105072a6ePatrick Benavoli
138a4ec15d5d5e84fbee3faa46a66e7b1eb90816ce2Guillaume Denneulin    uint32_t uiPluginLocation;
13968a912857707864bbaaff9808717813105072a6ePatrick Benavoli
140a4ec15d5d5e84fbee3faa46a66e7b1eb90816ce2Guillaume Denneulin    for (uiPluginLocation = 0; uiPluginLocation <  pSubsystemPlugins->getNbChildren(); uiPluginLocation++) {
14168a912857707864bbaaff9808717813105072a6ePatrick Benavoli
142a4ec15d5d5e84fbee3faa46a66e7b1eb90816ce2Guillaume Denneulin        // Get Folder for current Plugin Location
143a4ec15d5d5e84fbee3faa46a66e7b1eb90816ce2Guillaume Denneulin        const CPluginLocation* pPluginLocation = static_cast<const CPluginLocation*>(pSubsystemPlugins->getChild(uiPluginLocation));
144a4ec15d5d5e84fbee3faa46a66e7b1eb90816ce2Guillaume Denneulin
145fdcbfb9476ce68a5b899a61775ed9b168c3232a0Louis Le Gall        string strFolder(pPluginLocation->getFolder());
146fdcbfb9476ce68a5b899a61775ed9b168c3232a0Louis Le Gall        if (!strFolder.empty()) {
147fdcbfb9476ce68a5b899a61775ed9b168c3232a0Louis Le Gall            strFolder += "/";
148fdcbfb9476ce68a5b899a61775ed9b168c3232a0Louis Le Gall        }
149a4ec15d5d5e84fbee3faa46a66e7b1eb90816ce2Guillaume Denneulin        // Iterator on Plugin List:
150a4ec15d5d5e84fbee3faa46a66e7b1eb90816ce2Guillaume Denneulin        list<string>::const_iterator it;
151a4ec15d5d5e84fbee3faa46a66e7b1eb90816ce2Guillaume Denneulin
152a4ec15d5d5e84fbee3faa46a66e7b1eb90816ce2Guillaume Denneulin        const list<string>& pluginList = pPluginLocation->getPluginList();
153a4ec15d5d5e84fbee3faa46a66e7b1eb90816ce2Guillaume Denneulin
154a4ec15d5d5e84fbee3faa46a66e7b1eb90816ce2Guillaume Denneulin        for (it = pluginList.begin(); it != pluginList.end(); ++it) {
155a4ec15d5d5e84fbee3faa46a66e7b1eb90816ce2Guillaume Denneulin
156a4ec15d5d5e84fbee3faa46a66e7b1eb90816ce2Guillaume Denneulin            // Fill Plugin files list
157fdcbfb9476ce68a5b899a61775ed9b168c3232a0Louis Le Gall            lstrPluginFiles.push_back(strFolder + *it);
158a4ec15d5d5e84fbee3faa46a66e7b1eb90816ce2Guillaume Denneulin        }
15968a912857707864bbaaff9808717813105072a6ePatrick Benavoli    }
16068a912857707864bbaaff9808717813105072a6ePatrick Benavoli
1619bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli    // Actually load plugins
1626be8035935a21661833bddd3803e279652e81416Kevin Rocard    while (!lstrPluginFiles.empty()) {
163ec0f84e3f601ac4ffb029b903c06007956c4b02aPatrick Benavoli
1649bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli        // Because plugins might depend on one another, loading will be done
1659bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli        // as an iteration process that finishes successfully when the remaining
1669bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli        // list of plugins to load gets empty or unsuccessfully if the loading
1679bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli        // process failed to load at least one of them
16868a912857707864bbaaff9808717813105072a6ePatrick Benavoli
1699bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli        // Attempt to load the complete list
170ee7ceed5cca416718c70f3ca55fe41b8eb1e11a3Kevin Rocard        if (!loadPlugins(lstrPluginFiles, lstrError)) {
17168a912857707864bbaaff9808717813105072a6ePatrick Benavoli
172ee7ceed5cca416718c70f3ca55fe41b8eb1e11a3Kevin Rocard            // Unable to load at least one plugin
173ee7ceed5cca416718c70f3ca55fe41b8eb1e11a3Kevin Rocard            break;
17468a912857707864bbaaff9808717813105072a6ePatrick Benavoli        }
17568a912857707864bbaaff9808717813105072a6ePatrick Benavoli    }
176ee7ceed5cca416718c70f3ca55fe41b8eb1e11a3Kevin Rocard
1776be8035935a21661833bddd3803e279652e81416Kevin Rocard    if (!lstrPluginFiles.empty()) {
1786be8035935a21661833bddd3803e279652e81416Kevin Rocard        // Unable to load at least one plugin
1796be8035935a21661833bddd3803e279652e81416Kevin Rocard        string strPluginUnloaded;
1806be8035935a21661833bddd3803e279652e81416Kevin Rocard        CUtility::asString(lstrPluginFiles, strPluginUnloaded, ", ");
1816ccab9d382c08323fb1f000d859a696f05719c92Patrick Benavoli
182ecddaa31a64a2f62f8685578faf3467dbdf5ffe5Frédéric Boisnard        lstrError.push_back("Unable to load the following plugins: " + strPluginUnloaded + ".");
1836be8035935a21661833bddd3803e279652e81416Kevin Rocard        return false;
1846be8035935a21661833bddd3803e279652e81416Kevin Rocard    }
185ee7ceed5cca416718c70f3ca55fe41b8eb1e11a3Kevin Rocard
1866be8035935a21661833bddd3803e279652e81416Kevin Rocard    return true;
18768a912857707864bbaaff9808717813105072a6ePatrick Benavoli}
18868a912857707864bbaaff9808717813105072a6ePatrick Benavoli
1899bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli// Plugin symbol computation
1909bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavolistring CSystemClass::getPluginSymbol(const string& strPluginPath)
1919bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli{
1929bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli    // Extract plugin type out of file name
193d5679acf4b38db415bd25b0c3664d69cec5f43d4Frédéric Boisnard    string strPluginSuffix = gpcPluginSuffix;
194d5679acf4b38db415bd25b0c3664d69cec5f43d4Frédéric Boisnard    string strPluginPrefix = gpcPluginPrefix;
195d5679acf4b38db415bd25b0c3664d69cec5f43d4Frédéric Boisnard
196d5679acf4b38db415bd25b0c3664d69cec5f43d4Frédéric Boisnard    // Remove folder and library prefix
197d5679acf4b38db415bd25b0c3664d69cec5f43d4Frédéric Boisnard    size_t iPluginTypePos = strPluginPath.rfind('/') + 1 + strPluginPrefix.length();
1989bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli
199d5679acf4b38db415bd25b0c3664d69cec5f43d4Frédéric Boisnard    // Get index of -subsystem.so or -subsystem_host.so suffix
200d5679acf4b38db415bd25b0c3664d69cec5f43d4Frédéric Boisnard    size_t iSubsystemPos = strPluginPath.find(strPluginSuffix, iPluginTypePos);
2019bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli
202d5679acf4b38db415bd25b0c3664d69cec5f43d4Frédéric Boisnard    // Get type (between iPluginTypePos and iSubsystemPos)
203d5679acf4b38db415bd25b0c3664d69cec5f43d4Frédéric Boisnard    string strPluginType = strPluginPath.substr(iPluginTypePos, iSubsystemPos - iPluginTypePos);
2049bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli
2059bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli    // Make it upper case
2069bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli    std::transform(strPluginType.begin(), strPluginType.end(), strPluginType.begin(), ::toupper);
2079bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli
2089bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli    // Get plugin symbol
2099bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli    return gpcPluginSymbolPrefix + strPluginType + gpcPluginSymbolSuffix;
2109bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli}
2119bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli
2129bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli// Plugin loading
213ee7ceed5cca416718c70f3ca55fe41b8eb1e11a3Kevin Rocardbool CSystemClass::loadPlugins(list<string>& lstrPluginFiles, list<string>& lstrError)
2149bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli{
2159bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli    assert(lstrPluginFiles.size());
2169bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli
217ee7ceed5cca416718c70f3ca55fe41b8eb1e11a3Kevin Rocard    bool bAtLeastOneSubsystemPluginSuccessfullyLoaded = false;
2189bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli
2199bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli    list<string>::iterator it = lstrPluginFiles.begin();
2209bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli
2219bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli    while (it != lstrPluginFiles.end()) {
2229bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli
2239bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli        string strPluginFileName = *it;
2249bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli
225ace81f873b910493ab884dc5a6a38ba6ec3d56d3Kevin Rocard        log_info("Attempting to load subsystem plugin path \"%s\"", strPluginFileName.c_str());
2269bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli
2279bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli        // Load attempt
2289bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli        void* lib_handle = dlopen(strPluginFileName.c_str(), RTLD_LAZY);
2299bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli
2309bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli        if (!lib_handle) {
2319bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli
23230095b3c0b84e85caf253a27e41254eaf35e4ca7Eduardo Mendi            const char *err = dlerror();
2339bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli            // Failed
23430095b3c0b84e85caf253a27e41254eaf35e4ca7Eduardo Mendi            if (err == NULL) {
23530095b3c0b84e85caf253a27e41254eaf35e4ca7Eduardo Mendi                lstrError.push_back("dlerror failed");
23630095b3c0b84e85caf253a27e41254eaf35e4ca7Eduardo Mendi            } else {
23730095b3c0b84e85caf253a27e41254eaf35e4ca7Eduardo Mendi                lstrError.push_back("Plugin load failed: " + string(err));
23830095b3c0b84e85caf253a27e41254eaf35e4ca7Eduardo Mendi            }
2399bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli            // Next plugin
2409bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli            ++it;
2419bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli
2429bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli            continue;
2439bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli        }
2449bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli
2451b8b3ca093ecd7dc8c1877352625508ca4a81728Renaud de Chivre        // Store libraries handles
24679694d5d0a632ed4ca04ea42f19fb09c3fba0cdbPatrick Benavoli        _subsystemLibraryHandleList.push_back(lib_handle);
2471b8b3ca093ecd7dc8c1877352625508ca4a81728Renaud de Chivre
2489bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli        // Get plugin symbol
2499bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli        string strPluginSymbol = getPluginSymbol(strPluginFileName);
2509bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli
2519bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli        // Load symbol from library
252487ce850cc5f884f7689a2bfd55a7e1cf6eb3053Frédéric Boisnard        GetSubsystemBuilder pfnGetSubsystemBuilder = (GetSubsystemBuilder)dlsym(lib_handle, strPluginSymbol.c_str());
2539bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli
254487ce850cc5f884f7689a2bfd55a7e1cf6eb3053Frédéric Boisnard        if (!pfnGetSubsystemBuilder) {
2559bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli
256ee7ceed5cca416718c70f3ca55fe41b8eb1e11a3Kevin Rocard            lstrError.push_back("Subsystem plugin " + strPluginFileName +
257ee7ceed5cca416718c70f3ca55fe41b8eb1e11a3Kevin Rocard                                " does not contain " + strPluginSymbol + " symbol.");
2589bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli
259ee7ceed5cca416718c70f3ca55fe41b8eb1e11a3Kevin Rocard            continue;
2609bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli        }
2619bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli
262ee7ceed5cca416718c70f3ca55fe41b8eb1e11a3Kevin Rocard        // Account for this success
263ee7ceed5cca416718c70f3ca55fe41b8eb1e11a3Kevin Rocard        bAtLeastOneSubsystemPluginSuccessfullyLoaded = true;
264ee7ceed5cca416718c70f3ca55fe41b8eb1e11a3Kevin Rocard
2659bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli        // Fill library
266487ce850cc5f884f7689a2bfd55a7e1cf6eb3053Frédéric Boisnard        pfnGetSubsystemBuilder(_pSubsystemLibrary);
2679bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli
2689bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli        // Remove successfully loaded plugin from list and select next
2699bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli        lstrPluginFiles.erase(it++);
2709bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli    }
2719bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli
272ee7ceed5cca416718c70f3ca55fe41b8eb1e11a3Kevin Rocard    return bAtLeastOneSubsystemPluginSuccessfullyLoaded;
2739bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli}
2749bed7cea60c371df60ab53c2e7ade186f04266f3Patrick Benavoli
27568a912857707864bbaaff9808717813105072a6ePatrick Benavoliconst CSubsystemLibrary* CSystemClass::getSubsystemLibrary() const
27668a912857707864bbaaff9808717813105072a6ePatrick Benavoli{
27768a912857707864bbaaff9808717813105072a6ePatrick Benavoli    return _pSubsystemLibrary;
27868a912857707864bbaaff9808717813105072a6ePatrick Benavoli}
27968a912857707864bbaaff9808717813105072a6ePatrick Benavoli
280f2fd15a331fd3b5b63f0dc6f492651330adcedf9Guillaume Denneulinvoid CSystemClass::checkForSubsystemsToResync(CSyncerSet& syncerSet)
281f2fd15a331fd3b5b63f0dc6f492651330adcedf9Guillaume Denneulin{
282911844b16c6b627f421bc3368de427de3ca9f60cPatrick Benavoli    size_t uiNbChildren = getNbChildren();
283911844b16c6b627f421bc3368de427de3ca9f60cPatrick Benavoli    size_t uiChild;
284f2fd15a331fd3b5b63f0dc6f492651330adcedf9Guillaume Denneulin
285f2fd15a331fd3b5b63f0dc6f492651330adcedf9Guillaume Denneulin    for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
286f2fd15a331fd3b5b63f0dc6f492651330adcedf9Guillaume Denneulin
287f2fd15a331fd3b5b63f0dc6f492651330adcedf9Guillaume Denneulin        CSubsystem* pSubsystem = static_cast<CSubsystem*>(getChild(uiChild));
288f2fd15a331fd3b5b63f0dc6f492651330adcedf9Guillaume Denneulin
289f2fd15a331fd3b5b63f0dc6f492651330adcedf9Guillaume Denneulin        // Collect and consume the need for a resync
290f2fd15a331fd3b5b63f0dc6f492651330adcedf9Guillaume Denneulin        if (pSubsystem->needResync(true)) {
291f2fd15a331fd3b5b63f0dc6f492651330adcedf9Guillaume Denneulin
292f2fd15a331fd3b5b63f0dc6f492651330adcedf9Guillaume Denneulin            log_info("Resynchronizing subsystem: %s", pSubsystem->getName().c_str());
293f2fd15a331fd3b5b63f0dc6f492651330adcedf9Guillaume Denneulin            // get all subsystem syncers
294f2fd15a331fd3b5b63f0dc6f492651330adcedf9Guillaume Denneulin            pSubsystem->fillSyncerSet(syncerSet);
295f2fd15a331fd3b5b63f0dc6f492651330adcedf9Guillaume Denneulin        }
296f2fd15a331fd3b5b63f0dc6f492651330adcedf9Guillaume Denneulin    }
297f2fd15a331fd3b5b63f0dc6f492651330adcedf9Guillaume Denneulin}
298f2fd15a331fd3b5b63f0dc6f492651330adcedf9Guillaume Denneulin
2992fbe6e8d585e3f4d1f9134f6954615f616bb7815Kevin Rocardvoid CSystemClass::cleanSubsystemsNeedToResync()
3002fbe6e8d585e3f4d1f9134f6954615f616bb7815Kevin Rocard{
301911844b16c6b627f421bc3368de427de3ca9f60cPatrick Benavoli    size_t uiNbChildren = getNbChildren();
302911844b16c6b627f421bc3368de427de3ca9f60cPatrick Benavoli    size_t uiChild;
3032fbe6e8d585e3f4d1f9134f6954615f616bb7815Kevin Rocard
3042fbe6e8d585e3f4d1f9134f6954615f616bb7815Kevin Rocard    for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
3052fbe6e8d585e3f4d1f9134f6954615f616bb7815Kevin Rocard
3062fbe6e8d585e3f4d1f9134f6954615f616bb7815Kevin Rocard        CSubsystem* pSubsystem = static_cast<CSubsystem*>(getChild(uiChild));
3072fbe6e8d585e3f4d1f9134f6954615f616bb7815Kevin Rocard
3082fbe6e8d585e3f4d1f9134f6954615f616bb7815Kevin Rocard        // Consume the need for a resync
3092fbe6e8d585e3f4d1f9134f6954615f616bb7815Kevin Rocard        pSubsystem->needResync(true);
3102fbe6e8d585e3f4d1f9134f6954615f616bb7815Kevin Rocard    }
3112fbe6e8d585e3f4d1f9134f6954615f616bb7815Kevin Rocard}
312