blob: f3477c60f671cf48a28f747bfd28a8f7eb9eb240 [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
Frédéric Boisnardd5679ac2013-07-31 17:40:57 +020039/**
40 * A plugin file name is of the form:
41 * lib<type>-subsystem.so or lib<type>-subsystem._host.so
42 *
43 * The plugin symbol is of the form:
44 * get<TYPE>SubsystemBuilder
45*/
Patrick Benavoliec0f84e2011-10-27 14:34:38 +020046// Plugin file naming
Frédéric Boisnardd5679ac2013-07-31 17:40:57 +020047const char* gpcPluginSuffix = "-subsystem";
48const char* gpcPluginPrefix = "lib";
Patrick Benavoliec0f84e2011-10-27 14:34:38 +020049
50// Plugin symbol naming
51const char* gpcPluginSymbolPrefix = "get";
Frédéric Boisnard487ce852013-07-19 17:17:52 +020052const char* gpcPluginSymbolSuffix = "SubsystemBuilder";
Patrick Benavoliec0f84e2011-10-27 14:34:38 +020053
Patrick Benavoli68a91282011-08-31 11:23:23 +020054// Used by subsystem plugins
Frédéric Boisnard487ce852013-07-19 17:17:52 +020055typedef void (*GetSubsystemBuilder)(CSubsystemLibrary*);
Patrick Benavoli68a91282011-08-31 11:23:23 +020056
Patrick Benavoli95ac0342011-11-07 20:32:51 +010057CSystemClass::CSystemClass() : _pSubsystemLibrary(new CSubsystemLibrary)
Patrick Benavoli68a91282011-08-31 11:23:23 +020058{
59}
60
61CSystemClass::~CSystemClass()
62{
63 delete _pSubsystemLibrary;
64}
65
66bool CSystemClass::childrenAreDynamic() const
67{
68 return true;
69}
70
71string CSystemClass::getKind() const
72{
73 return "SystemClass";
74}
75
Guillaume Denneulina4ec15d2012-02-17 14:38:14 +010076bool CSystemClass::loadSubsystems(string& strError, const CSubsystemPlugins* pSubsystemPlugins)
Patrick Benavoli68a91282011-08-31 11:23:23 +020077{
Kevin Rocardace81f82012-12-11 16:19:17 +010078 CAutoLog autoLlog_info(this, "Loading subsystem plugins");
Patrick Benavoli68a91282011-08-31 11:23:23 +020079
80 // Plugin list
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +010081 list<string> lstrPluginFiles;
Patrick Benavoli68a91282011-08-31 11:23:23 +020082
Guillaume Denneulina4ec15d2012-02-17 14:38:14 +010083 uint32_t uiPluginLocation;
Patrick Benavoli68a91282011-08-31 11:23:23 +020084
Guillaume Denneulina4ec15d2012-02-17 14:38:14 +010085 for (uiPluginLocation = 0; uiPluginLocation < pSubsystemPlugins->getNbChildren(); uiPluginLocation++) {
Patrick Benavoli68a91282011-08-31 11:23:23 +020086
Guillaume Denneulina4ec15d2012-02-17 14:38:14 +010087 // Get Folder for current Plugin Location
88 const CPluginLocation* pPluginLocation = static_cast<const CPluginLocation*>(pSubsystemPlugins->getChild(uiPluginLocation));
Patrick Benavoli68a91282011-08-31 11:23:23 +020089
Guillaume Denneulina4ec15d2012-02-17 14:38:14 +010090 const string& strFolder = pPluginLocation->getFolder();
91
92 // Iterator on Plugin List:
93 list<string>::const_iterator it;
94
95 const list<string>& pluginList = pPluginLocation->getPluginList();
96
97 for (it = pluginList.begin(); it != pluginList.end(); ++it) {
98
99 // Fill Plugin files list
100 lstrPluginFiles.push_back(strFolder + "/" + *it);
101 }
102
Patrick Benavoli68a91282011-08-31 11:23:23 +0200103 }
104 // Check at least one subsystem plugin available
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100105 if (!lstrPluginFiles.size()) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200106
107 // No plugin found?
Kevin Rocardace81f82012-12-11 16:19:17 +0100108 log_warning("No subsystem plugin found");
Patrick Benavoli1387bda2011-08-31 11:23:24 +0200109
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100110 // Don't bail out now that we have virtual subsystems
Patrick Benavoli68a91282011-08-31 11:23:23 +0200111 }
112
Patrick Benavoli68a91282011-08-31 11:23:23 +0200113 // Start clean
114 _pSubsystemLibrary->clean();
115
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100116 // Actually load plugins
117 while (lstrPluginFiles.size()) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200118
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100119 // Because plugins might depend on one another, loading will be done
120 // as an iteration process that finishes successfully when the remaining
121 // list of plugins to load gets empty or unsuccessfully if the loading
122 // process failed to load at least one of them
Patrick Benavoli68a91282011-08-31 11:23:23 +0200123
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100124 // Attempt to load the complete list
125 if (!loadPlugins(lstrPluginFiles, strError)) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200126
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100127 // Display the list of plugins we were unable to load
Patrick Benavoli68a91282011-08-31 11:23:23 +0200128
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100129 // Leave clean
Patrick Benavoli68a91282011-08-31 11:23:23 +0200130 _pSubsystemLibrary->clean();
131
132 return false;
133 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200134 }
Kevin Rocardace81f82012-12-11 16:19:17 +0100135 log_info("All subsystem plugins successfully loaded");
Patrick Benavoli68a91282011-08-31 11:23:23 +0200136
Patrick Benavoli6ccab9d2011-11-10 23:21:01 +0100137 // Add virtual subsystem builder
Kevin Rocarda7b69602013-08-07 16:15:33 +0200138 _pSubsystemLibrary->addElementBuilder("Virtual",
139 new TNamedElementBuilderTemplate<CVirtualSubsystem>());
Patrick Benavoli6ccab9d2011-11-10 23:21:01 +0100140
Patrick Benavoli68a91282011-08-31 11:23:23 +0200141 return true;
142}
143
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100144// Plugin symbol computation
145string CSystemClass::getPluginSymbol(const string& strPluginPath)
146{
147 // Extract plugin type out of file name
Frédéric Boisnardd5679ac2013-07-31 17:40:57 +0200148 string strPluginSuffix = gpcPluginSuffix;
149 string strPluginPrefix = gpcPluginPrefix;
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100150
Frédéric Boisnardd5679ac2013-07-31 17:40:57 +0200151 // Remove folder and library prefix
152 size_t iPluginTypePos = strPluginPath.rfind('/') + 1 + strPluginPrefix.length();
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100153
Frédéric Boisnardd5679ac2013-07-31 17:40:57 +0200154 // Get index of -subsystem.so or -subsystem_host.so suffix
155 size_t iSubsystemPos = strPluginPath.find(strPluginSuffix, iPluginTypePos);
156
157 // Get type (between iPluginTypePos and iSubsystemPos)
158 string strPluginType = strPluginPath.substr(iPluginTypePos, iSubsystemPos - iPluginTypePos);
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100159
160 // Make it upper case
161 std::transform(strPluginType.begin(), strPluginType.end(), strPluginType.begin(), ::toupper);
162
163 // Get plugin symbol
164 return gpcPluginSymbolPrefix + strPluginType + gpcPluginSymbolSuffix;
165}
166
167// Plugin loading
168bool CSystemClass::loadPlugins(list<string>& lstrPluginFiles, string& strError)
169{
170 assert(lstrPluginFiles.size());
171
172 bool bAtLeastOneSybsystemPluginSuccessfullyLoaded = false;
173
174 list<string>::iterator it = lstrPluginFiles.begin();
175
176 while (it != lstrPluginFiles.end()) {
177
178 string strPluginFileName = *it;
179
Kevin Rocardace81f82012-12-11 16:19:17 +0100180 log_info("Attempting to load subsystem plugin path \"%s\"", strPluginFileName.c_str());
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100181
182 // Load attempt
183 void* lib_handle = dlopen(strPluginFileName.c_str(), RTLD_LAZY);
184
185 if (!lib_handle) {
186
187 // Failed
Kevin Rocardace81f82012-12-11 16:19:17 +0100188 log_warning("Plugin load failed: %s, proceeding on with remaining ones", dlerror());
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100189
190 // Next plugin
191 ++it;
192
193 continue;
194 }
195
196 // Get plugin symbol
197 string strPluginSymbol = getPluginSymbol(strPluginFileName);
198
199 // Load symbol from library
Frédéric Boisnard487ce852013-07-19 17:17:52 +0200200 GetSubsystemBuilder pfnGetSubsystemBuilder = (GetSubsystemBuilder)dlsym(lib_handle, strPluginSymbol.c_str());
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100201
Frédéric Boisnard487ce852013-07-19 17:17:52 +0200202 if (!pfnGetSubsystemBuilder) {
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100203
204 strError = "Subsystem plugin " + strPluginFileName + " does not contain " + strPluginSymbol + " symbol.";
205
206 return false;
207 }
208
209 // Fill library
Frédéric Boisnard487ce852013-07-19 17:17:52 +0200210 pfnGetSubsystemBuilder(_pSubsystemLibrary);
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100211
212 // Account for this success
213 bAtLeastOneSybsystemPluginSuccessfullyLoaded = true;
214
215 // Remove successfully loaded plugin from list and select next
216 lstrPluginFiles.erase(it++);
217 }
218
219 // Check for success
220 if (!bAtLeastOneSybsystemPluginSuccessfullyLoaded) {
221
222 // Return list of plugins we were unable to load
223 strError = "Unable to load the following plugins:\n";
224
225 for (it = lstrPluginFiles.begin(); it != lstrPluginFiles.end(); ++it) {
226
227 strError += *it + "\n";
228 }
229
230 return false;
231 }
232
233 return true;
234}
235
Patrick Benavoli68a91282011-08-31 11:23:23 +0200236const CSubsystemLibrary* CSystemClass::getSubsystemLibrary() const
237{
238 return _pSubsystemLibrary;
239}
240
Guillaume Denneulinf2fd15a2012-12-20 17:53:29 +0100241void CSystemClass::checkForSubsystemsToResync(CSyncerSet& syncerSet)
242{
243 uint32_t uiNbChildren = getNbChildren();
244 uint32_t uiChild;
245
246 for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
247
248 CSubsystem* pSubsystem = static_cast<CSubsystem*>(getChild(uiChild));
249
250 // Collect and consume the need for a resync
251 if (pSubsystem->needResync(true)) {
252
253 log_info("Resynchronizing subsystem: %s", pSubsystem->getName().c_str());
254 // get all subsystem syncers
255 pSubsystem->fillSyncerSet(syncerSet);
256 }
257 }
258}
259
Kevin Rocard2fbe6e82013-03-26 17:09:29 +0100260void CSystemClass::cleanSubsystemsNeedToResync()
261{
262 uint32_t uiNbChildren = getNbChildren();
263 uint32_t uiChild;
264
265 for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
266
267 CSubsystem* pSubsystem = static_cast<CSubsystem*>(getChild(uiChild));
268
269 // Consume the need for a resync
270 pSubsystem->needResync(true);
271 }
272}
273
Patrick Benavoli68a91282011-08-31 11:23:23 +0200274bool CSystemClass::init(string& strError)
275{
276 return base::init(strError);
277}
278
Georges-Henri Baron326a31d2012-06-28 12:05:09 +0200279// From IXmlSource
280void CSystemClass::toXml(CXmlElement& xmlElement, CXmlSerializingContext& serializingContext) const
281{
282 // Set the name of system class
283 xmlElement.setNameAttribute(getName());
284
285 base::toXml(xmlElement, serializingContext);
286}