blob: d733dbd04dc942160673750b151bfaeabea21095 [file] [log] [blame]
Patrick Benavoli68a91282011-08-31 11:23:23 +02001/* <auto_header>
2 * <FILENAME>
3 *
4 * INTEL CONFIDENTIAL
5 * Copyright © 2011 Intel
6 * Corporation All Rights Reserved.
7 *
8 * The source code contained or described herein and all documents related to
9 * the source code ("Material") are owned by Intel Corporation or its suppliers
10 * or licensors. Title to the Material remains with Intel Corporation or its
11 * suppliers and licensors. The Material contains trade secrets and proprietary
12 * and confidential information of Intel or its suppliers and licensors. The
13 * Material is protected by worldwide copyright and trade secret laws and
14 * treaty provisions. No part of the Material may be used, copied, reproduced,
15 * modified, published, uploaded, posted, transmitted, distributed, or
16 * disclosed in any way without Intel’s prior express written permission.
17 *
18 * No license under any patent, copyright, trade secret or other intellectual
19 * property right is granted to or conferred upon you by disclosure or delivery
20 * of the Materials, either expressly, by implication, inducement, estoppel or
21 * otherwise. Any license under such intellectual property rights must be
22 * express and approved by Intel in writing.
23 *
24 * AUTHOR: Patrick Benavoli (patrickx.benavoli@intel.com)
25 * CREATED: 2011-06-01
26 * UPDATED: 2011-07-27
27 *
28 *
29 * </auto_header>
30 */
31#include <dlfcn.h>
32#include <dirent.h>
Patrick Benavoliec0f84e2011-10-27 14:34:38 +020033#include <algorithm>
34#include <ctype.h>
Patrick Benavoli68a91282011-08-31 11:23:23 +020035#include "SystemClass.h"
36#include "SubsystemLibrary.h"
37#include "AutoLog.h"
Patrick Benavoli6ccab9d2011-11-10 23:21:01 +010038#include "VirtualSubsystem.h"
39#include "NamedElementBuilderTemplate.h"
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +010040#include <assert.h>
Guillaume Denneulina4ec15d2012-02-17 14:38:14 +010041#include "PluginLocation.h"
Patrick Benavoli68a91282011-08-31 11:23:23 +020042
43#define base CConfigurableElement
44
Patrick Benavoliec0f84e2011-10-27 14:34:38 +020045// A plugin file name is of the form:
46// lib<type>-subsystem.so
47// The plugin symbol is of the form:
48// get<TYPE>SusbystemBuilder
49
50// Plugin file naming
51const char* gpcPluginPattern = "-subsystem.so";
52const char* gpcLibraryPrefix = "lib";
53
54// Plugin symbol naming
55const char* gpcPluginSymbolPrefix = "get";
56const char* gpcPluginSymbolSuffix = "SusbystemBuilder";
57
Patrick Benavoli68a91282011-08-31 11:23:23 +020058// Used by subsystem plugins
59typedef void (*GetSusbystemBuilder)(CSubsystemLibrary*);
60
Patrick Benavoli95ac0342011-11-07 20:32:51 +010061CSystemClass::CSystemClass() : _pSubsystemLibrary(new CSubsystemLibrary)
Patrick Benavoli68a91282011-08-31 11:23:23 +020062{
63}
64
65CSystemClass::~CSystemClass()
66{
67 delete _pSubsystemLibrary;
68}
69
70bool CSystemClass::childrenAreDynamic() const
71{
72 return true;
73}
74
75string CSystemClass::getKind() const
76{
77 return "SystemClass";
78}
79
Guillaume Denneulina4ec15d2012-02-17 14:38:14 +010080bool CSystemClass::loadSubsystems(string& strError, const CSubsystemPlugins* pSubsystemPlugins)
Patrick Benavoli68a91282011-08-31 11:23:23 +020081{
82 CAutoLog autoLlog(this, "Loading subsystem plugins");
83
84 // Plugin list
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +010085 list<string> lstrPluginFiles;
Patrick Benavoli68a91282011-08-31 11:23:23 +020086
Guillaume Denneulina4ec15d2012-02-17 14:38:14 +010087 uint32_t uiPluginLocation;
Patrick Benavoli68a91282011-08-31 11:23:23 +020088
Guillaume Denneulina4ec15d2012-02-17 14:38:14 +010089 for (uiPluginLocation = 0; uiPluginLocation < pSubsystemPlugins->getNbChildren(); uiPluginLocation++) {
Patrick Benavoli68a91282011-08-31 11:23:23 +020090
Guillaume Denneulina4ec15d2012-02-17 14:38:14 +010091 // Get Folder for current Plugin Location
92 const CPluginLocation* pPluginLocation = static_cast<const CPluginLocation*>(pSubsystemPlugins->getChild(uiPluginLocation));
Patrick Benavoli68a91282011-08-31 11:23:23 +020093
Guillaume Denneulina4ec15d2012-02-17 14:38:14 +010094 const string& strFolder = pPluginLocation->getFolder();
95
96 // Iterator on Plugin List:
97 list<string>::const_iterator it;
98
99 const list<string>& pluginList = pPluginLocation->getPluginList();
100
101 for (it = pluginList.begin(); it != pluginList.end(); ++it) {
102
103 // Fill Plugin files list
104 lstrPluginFiles.push_back(strFolder + "/" + *it);
105 }
106
Patrick Benavoli68a91282011-08-31 11:23:23 +0200107 }
108 // Check at least one subsystem plugin available
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100109 if (!lstrPluginFiles.size()) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200110
111 // No plugin found?
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100112 log("No subsystem plugin found");
Patrick Benavoli1387bda2011-08-31 11:23:24 +0200113
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100114 // Don't bail out now that we have virtual subsystems
Patrick Benavoli68a91282011-08-31 11:23:23 +0200115 }
116
Patrick Benavoli68a91282011-08-31 11:23:23 +0200117 // Start clean
118 _pSubsystemLibrary->clean();
119
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100120 // Actually load plugins
121 while (lstrPluginFiles.size()) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200122
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100123 // Because plugins might depend on one another, loading will be done
124 // as an iteration process that finishes successfully when the remaining
125 // list of plugins to load gets empty or unsuccessfully if the loading
126 // process failed to load at least one of them
Patrick Benavoli68a91282011-08-31 11:23:23 +0200127
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100128 // Attempt to load the complete list
129 if (!loadPlugins(lstrPluginFiles, strError)) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200130
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100131 // Display the list of plugins we were unable to load
Patrick Benavoli68a91282011-08-31 11:23:23 +0200132
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100133 // Leave clean
Patrick Benavoli68a91282011-08-31 11:23:23 +0200134 _pSubsystemLibrary->clean();
135
136 return false;
137 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200138 }
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100139 log("All subsystem plugins successfully loaded");
Patrick Benavoli68a91282011-08-31 11:23:23 +0200140
Patrick Benavoli6ccab9d2011-11-10 23:21:01 +0100141 // Add virtual subsystem builder
142 _pSubsystemLibrary->addElementBuilder(new TNamedElementBuilderTemplate<CVirtualSubsystem>("Virtual"));
143
Patrick Benavoli68a91282011-08-31 11:23:23 +0200144 return true;
145}
146
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100147// Plugin symbol computation
148string CSystemClass::getPluginSymbol(const string& strPluginPath)
149{
150 // Extract plugin type out of file name
151 string strPluginPattern = gpcPluginPattern;
152 string strLibraryPrefix = gpcLibraryPrefix;
153
154 // Remove folder
155 int32_t iSlashPos = strPluginPath.rfind('/') + 1 + strLibraryPrefix.length();
156
157 // Get type
158 string strPluginType = strPluginPath.substr(iSlashPos, strPluginPath.length() - iSlashPos - strPluginPattern.length());
159
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
180 log("Attempting to load subsystem plugin path \"%s\"", strPluginFileName.c_str());
181
182 // Load attempt
183 void* lib_handle = dlopen(strPluginFileName.c_str(), RTLD_LAZY);
184
185 if (!lib_handle) {
186
187 // Failed
Patrick Benavoli68808c62012-02-02 17:12:41 +0100188 log("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
200 GetSusbystemBuilder pfnGetSusbystemBuilder = (GetSusbystemBuilder)dlsym(lib_handle, strPluginSymbol.c_str());
201
202 if (!pfnGetSusbystemBuilder) {
203
204 strError = "Subsystem plugin " + strPluginFileName + " does not contain " + strPluginSymbol + " symbol.";
205
206 return false;
207 }
208
209 // Fill library
210 pfnGetSusbystemBuilder(_pSubsystemLibrary);
211
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
241bool CSystemClass::init(string& strError)
242{
243 return base::init(strError);
244}
245