blob: bf98cb15a052bc6ea33016d7a7877b3bd1b6d0aa [file] [log] [blame]
Kevin Rocard93250d12012-07-19 17:48:30 +02001/*
Patrick Benavoli68a91282011-08-31 11:23:23 +02002 * INTEL CONFIDENTIAL
3 * Copyright © 2011 Intel
4 * Corporation All Rights Reserved.
5 *
6 * 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.
15 *
16 * 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.
21 *
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"
Patrick Benavoli68a91282011-08-31 11:23:23 +020036
37#define base CConfigurableElement
38
Patrick Benavoliec0f84e2011-10-27 14:34:38 +020039// A plugin file name is of the form:
40// lib<type>-subsystem.so
41// The plugin symbol is of the form:
42// get<TYPE>SusbystemBuilder
43
44// Plugin file naming
45const char* gpcPluginPattern = "-subsystem.so";
46const char* gpcLibraryPrefix = "lib";
47
48// Plugin symbol naming
49const char* gpcPluginSymbolPrefix = "get";
50const char* gpcPluginSymbolSuffix = "SusbystemBuilder";
51
Patrick Benavoli68a91282011-08-31 11:23:23 +020052// Used by subsystem plugins
53typedef void (*GetSusbystemBuilder)(CSubsystemLibrary*);
54
Patrick Benavoli95ac0342011-11-07 20:32:51 +010055CSystemClass::CSystemClass() : _pSubsystemLibrary(new CSubsystemLibrary)
Patrick Benavoli68a91282011-08-31 11:23:23 +020056{
57}
58
59CSystemClass::~CSystemClass()
60{
61 delete _pSubsystemLibrary;
62}
63
64bool CSystemClass::childrenAreDynamic() const
65{
66 return true;
67}
68
69string CSystemClass::getKind() const
70{
71 return "SystemClass";
72}
73
Guillaume Denneulina4ec15d2012-02-17 14:38:14 +010074bool CSystemClass::loadSubsystems(string& strError, const CSubsystemPlugins* pSubsystemPlugins)
Patrick Benavoli68a91282011-08-31 11:23:23 +020075{
Kevin Rocardace81f82012-12-11 16:19:17 +010076 CAutoLog autoLlog_info(this, "Loading subsystem plugins");
Patrick Benavoli68a91282011-08-31 11:23:23 +020077
78 // Plugin list
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +010079 list<string> lstrPluginFiles;
Patrick Benavoli68a91282011-08-31 11:23:23 +020080
Guillaume Denneulina4ec15d2012-02-17 14:38:14 +010081 uint32_t uiPluginLocation;
Patrick Benavoli68a91282011-08-31 11:23:23 +020082
Guillaume Denneulina4ec15d2012-02-17 14:38:14 +010083 for (uiPluginLocation = 0; uiPluginLocation < pSubsystemPlugins->getNbChildren(); uiPluginLocation++) {
Patrick Benavoli68a91282011-08-31 11:23:23 +020084
Guillaume Denneulina4ec15d2012-02-17 14:38:14 +010085 // Get Folder for current Plugin Location
86 const CPluginLocation* pPluginLocation = static_cast<const CPluginLocation*>(pSubsystemPlugins->getChild(uiPluginLocation));
Patrick Benavoli68a91282011-08-31 11:23:23 +020087
Guillaume Denneulina4ec15d2012-02-17 14:38:14 +010088 const string& strFolder = pPluginLocation->getFolder();
89
90 // Iterator on Plugin List:
91 list<string>::const_iterator it;
92
93 const list<string>& pluginList = pPluginLocation->getPluginList();
94
95 for (it = pluginList.begin(); it != pluginList.end(); ++it) {
96
97 // Fill Plugin files list
98 lstrPluginFiles.push_back(strFolder + "/" + *it);
99 }
100
Patrick Benavoli68a91282011-08-31 11:23:23 +0200101 }
102 // Check at least one subsystem plugin available
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100103 if (!lstrPluginFiles.size()) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200104
105 // No plugin found?
Kevin Rocardace81f82012-12-11 16:19:17 +0100106 log_warning("No subsystem plugin found");
Patrick Benavoli1387bda2011-08-31 11:23:24 +0200107
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100108 // Don't bail out now that we have virtual subsystems
Patrick Benavoli68a91282011-08-31 11:23:23 +0200109 }
110
Patrick Benavoli68a91282011-08-31 11:23:23 +0200111 // Start clean
112 _pSubsystemLibrary->clean();
113
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100114 // Actually load plugins
115 while (lstrPluginFiles.size()) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200116
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100117 // Because plugins might depend on one another, loading will be done
118 // as an iteration process that finishes successfully when the remaining
119 // list of plugins to load gets empty or unsuccessfully if the loading
120 // process failed to load at least one of them
Patrick Benavoli68a91282011-08-31 11:23:23 +0200121
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100122 // Attempt to load the complete list
123 if (!loadPlugins(lstrPluginFiles, strError)) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200124
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100125 // Display the list of plugins we were unable to load
Patrick Benavoli68a91282011-08-31 11:23:23 +0200126
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100127 // Leave clean
Patrick Benavoli68a91282011-08-31 11:23:23 +0200128 _pSubsystemLibrary->clean();
129
130 return false;
131 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200132 }
Kevin Rocardace81f82012-12-11 16:19:17 +0100133 log_info("All subsystem plugins successfully loaded");
Patrick Benavoli68a91282011-08-31 11:23:23 +0200134
Patrick Benavoli6ccab9d2011-11-10 23:21:01 +0100135 // Add virtual subsystem builder
136 _pSubsystemLibrary->addElementBuilder(new TNamedElementBuilderTemplate<CVirtualSubsystem>("Virtual"));
137
Patrick Benavoli68a91282011-08-31 11:23:23 +0200138 return true;
139}
140
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100141// Plugin symbol computation
142string CSystemClass::getPluginSymbol(const string& strPluginPath)
143{
144 // Extract plugin type out of file name
145 string strPluginPattern = gpcPluginPattern;
146 string strLibraryPrefix = gpcLibraryPrefix;
147
148 // Remove folder
149 int32_t iSlashPos = strPluginPath.rfind('/') + 1 + strLibraryPrefix.length();
150
151 // Get type
152 string strPluginType = strPluginPath.substr(iSlashPos, strPluginPath.length() - iSlashPos - strPluginPattern.length());
153
154 // Make it upper case
155 std::transform(strPluginType.begin(), strPluginType.end(), strPluginType.begin(), ::toupper);
156
157 // Get plugin symbol
158 return gpcPluginSymbolPrefix + strPluginType + gpcPluginSymbolSuffix;
159}
160
161// Plugin loading
162bool CSystemClass::loadPlugins(list<string>& lstrPluginFiles, string& strError)
163{
164 assert(lstrPluginFiles.size());
165
166 bool bAtLeastOneSybsystemPluginSuccessfullyLoaded = false;
167
168 list<string>::iterator it = lstrPluginFiles.begin();
169
170 while (it != lstrPluginFiles.end()) {
171
172 string strPluginFileName = *it;
173
Kevin Rocardace81f82012-12-11 16:19:17 +0100174 log_info("Attempting to load subsystem plugin path \"%s\"", strPluginFileName.c_str());
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100175
176 // Load attempt
177 void* lib_handle = dlopen(strPluginFileName.c_str(), RTLD_LAZY);
178
179 if (!lib_handle) {
180
181 // Failed
Kevin Rocardace81f82012-12-11 16:19:17 +0100182 log_warning("Plugin load failed: %s, proceeding on with remaining ones", dlerror());
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100183
184 // Next plugin
185 ++it;
186
187 continue;
188 }
189
190 // Get plugin symbol
191 string strPluginSymbol = getPluginSymbol(strPluginFileName);
192
193 // Load symbol from library
194 GetSusbystemBuilder pfnGetSusbystemBuilder = (GetSusbystemBuilder)dlsym(lib_handle, strPluginSymbol.c_str());
195
196 if (!pfnGetSusbystemBuilder) {
197
198 strError = "Subsystem plugin " + strPluginFileName + " does not contain " + strPluginSymbol + " symbol.";
199
200 return false;
201 }
202
203 // Fill library
204 pfnGetSusbystemBuilder(_pSubsystemLibrary);
205
206 // Account for this success
207 bAtLeastOneSybsystemPluginSuccessfullyLoaded = true;
208
209 // Remove successfully loaded plugin from list and select next
210 lstrPluginFiles.erase(it++);
211 }
212
213 // Check for success
214 if (!bAtLeastOneSybsystemPluginSuccessfullyLoaded) {
215
216 // Return list of plugins we were unable to load
217 strError = "Unable to load the following plugins:\n";
218
219 for (it = lstrPluginFiles.begin(); it != lstrPluginFiles.end(); ++it) {
220
221 strError += *it + "\n";
222 }
223
224 return false;
225 }
226
227 return true;
228}
229
Patrick Benavoli68a91282011-08-31 11:23:23 +0200230const CSubsystemLibrary* CSystemClass::getSubsystemLibrary() const
231{
232 return _pSubsystemLibrary;
233}
234
Guillaume Denneulinf2fd15a2012-12-20 17:53:29 +0100235// Fill syncer-set with syncers from subsytems that need resync
236void CSystemClass::checkForSubsystemsToResync(CSyncerSet& syncerSet)
237{
238 uint32_t uiNbChildren = getNbChildren();
239 uint32_t uiChild;
240
241 for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
242
243 CSubsystem* pSubsystem = static_cast<CSubsystem*>(getChild(uiChild));
244
245 // Collect and consume the need for a resync
246 if (pSubsystem->needResync(true)) {
247
248 log_info("Resynchronizing subsystem: %s", pSubsystem->getName().c_str());
249 // get all subsystem syncers
250 pSubsystem->fillSyncerSet(syncerSet);
251 }
252 }
253}
254
Patrick Benavoli68a91282011-08-31 11:23:23 +0200255bool CSystemClass::init(string& strError)
256{
257 return base::init(strError);
258}
259
Georges-Henri Baron326a31d2012-06-28 12:05:09 +0200260// From IXmlSource
261void CSystemClass::toXml(CXmlElement& xmlElement, CXmlSerializingContext& serializingContext) const
262{
263 // Set the name of system class
264 xmlElement.setNameAttribute(getName());
265
266 base::toXml(xmlElement, serializingContext);
267}