blob: 5d435d7aebcff68e9501de865251396d47f266dd [file] [log] [blame]
Kevin Rocardee7ceed2013-07-05 10:56:27 +02001/*
Patrick Benavoli68a91282011-08-31 11:23:23 +02002 * INTEL CONFIDENTIAL
Kevin Rocardee7ceed2013-07-05 10:56:27 +02003 * Copyright © 2011 Intel
Patrick Benavoli68a91282011-08-31 11:23:23 +02004 * Corporation All Rights Reserved.
Kevin Rocardee7ceed2013-07-05 10:56:27 +02005 *
Patrick Benavoli68a91282011-08-31 11:23:23 +02006 * The source code contained or described herein and all documents related to
7 * the source code ("Material") are owned by Intel Corporation or its suppliers
8 * or licensors. Title to the Material remains with Intel Corporation or its
9 * suppliers and licensors. The Material contains trade secrets and proprietary
10 * and confidential information of Intel or its suppliers and licensors. The
11 * Material is protected by worldwide copyright and trade secret laws and
12 * treaty provisions. No part of the Material may be used, copied, reproduced,
13 * modified, published, uploaded, posted, transmitted, distributed, or
14 * disclosed in any way without Intel’s prior express written permission.
Kevin Rocardee7ceed2013-07-05 10:56:27 +020015 *
Patrick Benavoli68a91282011-08-31 11:23:23 +020016 * No license under any patent, copyright, trade secret or other intellectual
17 * property right is granted to or conferred upon you by disclosure or delivery
18 * of the Materials, either expressly, by implication, inducement, estoppel or
19 * otherwise. Any license under such intellectual property rights must be
20 * express and approved by Intel in writing.
Kevin Rocardee7ceed2013-07-05 10:56:27 +020021 *
Patrick Benavoli68a91282011-08-31 11:23:23 +020022 * CREATED: 2011-06-01
23 * UPDATED: 2011-07-27
Patrick Benavoli68a91282011-08-31 11:23:23 +020024 */
25#include <dlfcn.h>
26#include <dirent.h>
Patrick Benavoliec0f84e2011-10-27 14:34:38 +020027#include <algorithm>
28#include <ctype.h>
Patrick Benavoli68a91282011-08-31 11:23:23 +020029#include "SystemClass.h"
30#include "SubsystemLibrary.h"
31#include "AutoLog.h"
Patrick Benavoli6ccab9d2011-11-10 23:21:01 +010032#include "VirtualSubsystem.h"
33#include "NamedElementBuilderTemplate.h"
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +010034#include <assert.h>
Guillaume Denneulina4ec15d2012-02-17 14:38:14 +010035#include "PluginLocation.h"
Kevin Rocardee7ceed2013-07-05 10:56:27 +020036#include "Utility.h"
Patrick Benavoli68a91282011-08-31 11:23:23 +020037
38#define base CConfigurableElement
39
Frédéric Boisnardd5679ac2013-07-31 17:40:57 +020040/**
41 * A plugin file name is of the form:
42 * lib<type>-subsystem.so or lib<type>-subsystem._host.so
43 *
44 * The plugin symbol is of the form:
45 * get<TYPE>SubsystemBuilder
46*/
Patrick Benavoliec0f84e2011-10-27 14:34:38 +020047// Plugin file naming
Frédéric Boisnardd5679ac2013-07-31 17:40:57 +020048const char* gpcPluginSuffix = "-subsystem";
49const char* gpcPluginPrefix = "lib";
Patrick Benavoliec0f84e2011-10-27 14:34:38 +020050
51// Plugin symbol naming
52const char* gpcPluginSymbolPrefix = "get";
Frédéric Boisnard487ce852013-07-19 17:17:52 +020053const char* gpcPluginSymbolSuffix = "SubsystemBuilder";
Patrick Benavoliec0f84e2011-10-27 14:34:38 +020054
Patrick Benavoli68a91282011-08-31 11:23:23 +020055// Used by subsystem plugins
Frédéric Boisnard487ce852013-07-19 17:17:52 +020056typedef void (*GetSubsystemBuilder)(CSubsystemLibrary*);
Patrick Benavoli68a91282011-08-31 11:23:23 +020057
Patrick Benavoli95ac0342011-11-07 20:32:51 +010058CSystemClass::CSystemClass() : _pSubsystemLibrary(new CSubsystemLibrary)
Patrick Benavoli68a91282011-08-31 11:23:23 +020059{
60}
61
62CSystemClass::~CSystemClass()
63{
64 delete _pSubsystemLibrary;
65}
66
67bool CSystemClass::childrenAreDynamic() const
68{
69 return true;
70}
71
72string CSystemClass::getKind() const
73{
74 return "SystemClass";
75}
76
Kevin Rocardee7ceed2013-07-05 10:56:27 +020077bool CSystemClass::loadSubsystems(string& strError,
Kevin Rocard6be80352013-07-11 12:42:23 +020078 const CSubsystemPlugins* pSubsystemPlugins,
79 bool bVirtualSubsystemFallback)
Patrick Benavoli68a91282011-08-31 11:23:23 +020080{
Kevin Rocardee7ceed2013-07-05 10:56:27 +020081 CAutoLog autoLog_info(this, "Loading subsystem plugins");
Patrick Benavoli68a91282011-08-31 11:23:23 +020082
Kevin Rocard6be80352013-07-11 12:42:23 +020083 // Start clean
84 _pSubsystemLibrary->clean();
85
86 // Add virtual subsystem builder
87 _pSubsystemLibrary->addElementBuilder("Virtual",
88 new TNamedElementBuilderTemplate<CVirtualSubsystem>());
89 // Set virtual subsytem as builder fallback if required
90 _pSubsystemLibrary->enableDefaultMechanism(bVirtualSubsystemFallback);
91
92 // Add subsystem defined in shared libraries
93 list<string> lstrError;
94 bool bLoadPluginsSuccess = loadSubsystemsFromSharedLibraries(lstrError, pSubsystemPlugins);
95
96 if (bLoadPluginsSuccess) {
97 log_info("All subsystem plugins successfully loaded");
98 } else {
99 // Log plugin as warning if no fallback available
100 log_table(!bVirtualSubsystemFallback, lstrError);
101 }
102
103 if (!bVirtualSubsystemFallback) {
104 // Any problem reported is an error as there is no fallback.
105 // Fill strError for caller.
106 CUtility::asString(lstrError, strError);
107 }
108
109 return bLoadPluginsSuccess || bVirtualSubsystemFallback;
110}
111
112bool CSystemClass::loadSubsystemsFromSharedLibraries(list<string>& lstrError,
113 const CSubsystemPlugins* pSubsystemPlugins)
114{
Patrick Benavoli68a91282011-08-31 11:23:23 +0200115 // Plugin list
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100116 list<string> lstrPluginFiles;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200117
Guillaume Denneulina4ec15d2012-02-17 14:38:14 +0100118 uint32_t uiPluginLocation;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200119
Guillaume Denneulina4ec15d2012-02-17 14:38:14 +0100120 for (uiPluginLocation = 0; uiPluginLocation < pSubsystemPlugins->getNbChildren(); uiPluginLocation++) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200121
Guillaume Denneulina4ec15d2012-02-17 14:38:14 +0100122 // Get Folder for current Plugin Location
123 const CPluginLocation* pPluginLocation = static_cast<const CPluginLocation*>(pSubsystemPlugins->getChild(uiPluginLocation));
Patrick Benavoli68a91282011-08-31 11:23:23 +0200124
Guillaume Denneulina4ec15d2012-02-17 14:38:14 +0100125 const string& strFolder = pPluginLocation->getFolder();
126
127 // Iterator on Plugin List:
128 list<string>::const_iterator it;
129
130 const list<string>& pluginList = pPluginLocation->getPluginList();
131
132 for (it = pluginList.begin(); it != pluginList.end(); ++it) {
133
134 // Fill Plugin files list
135 lstrPluginFiles.push_back(strFolder + "/" + *it);
136 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200137 }
138
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100139 // Actually load plugins
Kevin Rocard6be80352013-07-11 12:42:23 +0200140 while (!lstrPluginFiles.empty()) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200141
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100142 // Because plugins might depend on one another, loading will be done
143 // as an iteration process that finishes successfully when the remaining
144 // list of plugins to load gets empty or unsuccessfully if the loading
145 // process failed to load at least one of them
Patrick Benavoli68a91282011-08-31 11:23:23 +0200146
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100147 // Attempt to load the complete list
Kevin Rocardee7ceed2013-07-05 10:56:27 +0200148 if (!loadPlugins(lstrPluginFiles, lstrError)) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200149
Kevin Rocardee7ceed2013-07-05 10:56:27 +0200150 // Unable to load at least one plugin
151 break;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200152 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200153 }
Kevin Rocardee7ceed2013-07-05 10:56:27 +0200154
Kevin Rocard6be80352013-07-11 12:42:23 +0200155 if (!lstrPluginFiles.empty()) {
156 // Unable to load at least one plugin
157 string strPluginUnloaded;
158 CUtility::asString(lstrPluginFiles, strPluginUnloaded, ", ");
159
160 lstrError.push_back("Unable to load the folowings plugings: " + strPluginUnloaded + ".");
161 return false;
Kevin Rocardee7ceed2013-07-05 10:56:27 +0200162 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200163
Kevin Rocard6be80352013-07-11 12:42:23 +0200164 return true;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200165}
166
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100167// Plugin symbol computation
168string CSystemClass::getPluginSymbol(const string& strPluginPath)
169{
170 // Extract plugin type out of file name
Frédéric Boisnardd5679ac2013-07-31 17:40:57 +0200171 string strPluginSuffix = gpcPluginSuffix;
172 string strPluginPrefix = gpcPluginPrefix;
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100173
Frédéric Boisnardd5679ac2013-07-31 17:40:57 +0200174 // Remove folder and library prefix
175 size_t iPluginTypePos = strPluginPath.rfind('/') + 1 + strPluginPrefix.length();
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100176
Frédéric Boisnardd5679ac2013-07-31 17:40:57 +0200177 // Get index of -subsystem.so or -subsystem_host.so suffix
178 size_t iSubsystemPos = strPluginPath.find(strPluginSuffix, iPluginTypePos);
179
180 // Get type (between iPluginTypePos and iSubsystemPos)
181 string strPluginType = strPluginPath.substr(iPluginTypePos, iSubsystemPos - iPluginTypePos);
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100182
183 // Make it upper case
184 std::transform(strPluginType.begin(), strPluginType.end(), strPluginType.begin(), ::toupper);
185
186 // Get plugin symbol
187 return gpcPluginSymbolPrefix + strPluginType + gpcPluginSymbolSuffix;
188}
189
190// Plugin loading
Kevin Rocardee7ceed2013-07-05 10:56:27 +0200191bool CSystemClass::loadPlugins(list<string>& lstrPluginFiles, list<string>& lstrError)
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100192{
193 assert(lstrPluginFiles.size());
194
Kevin Rocardee7ceed2013-07-05 10:56:27 +0200195 bool bAtLeastOneSubsystemPluginSuccessfullyLoaded = false;
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100196
197 list<string>::iterator it = lstrPluginFiles.begin();
198
199 while (it != lstrPluginFiles.end()) {
200
201 string strPluginFileName = *it;
202
Kevin Rocardace81f82012-12-11 16:19:17 +0100203 log_info("Attempting to load subsystem plugin path \"%s\"", strPluginFileName.c_str());
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100204
205 // Load attempt
206 void* lib_handle = dlopen(strPluginFileName.c_str(), RTLD_LAZY);
207
208 if (!lib_handle) {
209
210 // Failed
Kevin Rocardee7ceed2013-07-05 10:56:27 +0200211 lstrError.push_back("Plugin load failed: " + string(dlerror()));
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100212
213 // Next plugin
214 ++it;
215
216 continue;
217 }
218
219 // Get plugin symbol
220 string strPluginSymbol = getPluginSymbol(strPluginFileName);
221
222 // Load symbol from library
Frédéric Boisnard487ce852013-07-19 17:17:52 +0200223 GetSubsystemBuilder pfnGetSubsystemBuilder = (GetSubsystemBuilder)dlsym(lib_handle, strPluginSymbol.c_str());
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100224
Frédéric Boisnard487ce852013-07-19 17:17:52 +0200225 if (!pfnGetSubsystemBuilder) {
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100226
Kevin Rocardee7ceed2013-07-05 10:56:27 +0200227 lstrError.push_back("Subsystem plugin " + strPluginFileName +
228 " does not contain " + strPluginSymbol + " symbol.");
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100229
Kevin Rocardee7ceed2013-07-05 10:56:27 +0200230 continue;
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100231 }
232
Kevin Rocardee7ceed2013-07-05 10:56:27 +0200233 // Account for this success
234 bAtLeastOneSubsystemPluginSuccessfullyLoaded = true;
235
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100236 // Fill library
Frédéric Boisnard487ce852013-07-19 17:17:52 +0200237 pfnGetSubsystemBuilder(_pSubsystemLibrary);
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100238
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100239 // Remove successfully loaded plugin from list and select next
240 lstrPluginFiles.erase(it++);
241 }
242
Kevin Rocardee7ceed2013-07-05 10:56:27 +0200243 return bAtLeastOneSubsystemPluginSuccessfullyLoaded;
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100244}
245
Patrick Benavoli68a91282011-08-31 11:23:23 +0200246const CSubsystemLibrary* CSystemClass::getSubsystemLibrary() const
247{
248 return _pSubsystemLibrary;
249}
250
Guillaume Denneulinf2fd15a2012-12-20 17:53:29 +0100251void CSystemClass::checkForSubsystemsToResync(CSyncerSet& syncerSet)
252{
253 uint32_t uiNbChildren = getNbChildren();
254 uint32_t uiChild;
255
256 for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
257
258 CSubsystem* pSubsystem = static_cast<CSubsystem*>(getChild(uiChild));
259
260 // Collect and consume the need for a resync
261 if (pSubsystem->needResync(true)) {
262
263 log_info("Resynchronizing subsystem: %s", pSubsystem->getName().c_str());
264 // get all subsystem syncers
265 pSubsystem->fillSyncerSet(syncerSet);
266 }
267 }
268}
269
Kevin Rocard2fbe6e82013-03-26 17:09:29 +0100270void CSystemClass::cleanSubsystemsNeedToResync()
271{
272 uint32_t uiNbChildren = getNbChildren();
273 uint32_t uiChild;
274
275 for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
276
277 CSubsystem* pSubsystem = static_cast<CSubsystem*>(getChild(uiChild));
278
279 // Consume the need for a resync
280 pSubsystem->needResync(true);
281 }
282}
283
Patrick Benavoli68a91282011-08-31 11:23:23 +0200284bool CSystemClass::init(string& strError)
285{
286 return base::init(strError);
287}
288
Georges-Henri Baron326a31d2012-06-28 12:05:09 +0200289// From IXmlSource
290void CSystemClass::toXml(CXmlElement& xmlElement, CXmlSerializingContext& serializingContext) const
291{
292 // Set the name of system class
293 xmlElement.setNameAttribute(getName());
294
295 base::toXml(xmlElement, serializingContext);
296}