blob: 6409c9be9267b79fc8407534b0db7b75dd02cfe9 [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>
Patrick Benavoli68a91282011-08-31 11:23:23 +020041
42#define base CConfigurableElement
43
Patrick Benavoliec0f84e2011-10-27 14:34:38 +020044// A plugin file name is of the form:
45// lib<type>-subsystem.so
46// The plugin symbol is of the form:
47// get<TYPE>SusbystemBuilder
48
49// Plugin file naming
50const char* gpcPluginPattern = "-subsystem.so";
51const char* gpcLibraryPrefix = "lib";
52
53// Plugin symbol naming
54const char* gpcPluginSymbolPrefix = "get";
55const char* gpcPluginSymbolSuffix = "SusbystemBuilder";
56
Patrick Benavoli68a91282011-08-31 11:23:23 +020057// Used by subsystem plugins
58typedef void (*GetSusbystemBuilder)(CSubsystemLibrary*);
59
Patrick Benavoli95ac0342011-11-07 20:32:51 +010060CSystemClass::CSystemClass() : _pSubsystemLibrary(new CSubsystemLibrary)
Patrick Benavoli68a91282011-08-31 11:23:23 +020061{
62}
63
64CSystemClass::~CSystemClass()
65{
66 delete _pSubsystemLibrary;
67}
68
69bool CSystemClass::childrenAreDynamic() const
70{
71 return true;
72}
73
74string CSystemClass::getKind() const
75{
76 return "SystemClass";
77}
78
79bool CSystemClass::loadSubsystems(string& strError, const vector<string>& astrPluginFolderPaths)
80{
81 CAutoLog autoLlog(this, "Loading subsystem plugins");
82
83 // Plugin list
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +010084 list<string> lstrPluginFiles;
Patrick Benavoli68a91282011-08-31 11:23:23 +020085
86 uint32_t uiFolderLocation;
87
88 for (uiFolderLocation = 0; uiFolderLocation < astrPluginFolderPaths.size(); uiFolderLocation++) {
89
90 // Folder for current SystemClass
Patrick Benavoli95ac0342011-11-07 20:32:51 +010091 string strPluginPath = astrPluginFolderPaths[uiFolderLocation] + "/";
Patrick Benavoli68a91282011-08-31 11:23:23 +020092
93 // Get plugin list
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +010094 getPluginFiles(strPluginPath, lstrPluginFiles);
Patrick Benavoli68a91282011-08-31 11:23:23 +020095 }
96 // Check at least one subsystem plugin available
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +010097 if (!lstrPluginFiles.size()) {
Patrick Benavoli68a91282011-08-31 11:23:23 +020098
99 // No plugin found?
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100100 log("No subsystem plugin found");
Patrick Benavoli1387bda2011-08-31 11:23:24 +0200101
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100102 // Don't bail out now that we have virtual subsystems
Patrick Benavoli68a91282011-08-31 11:23:23 +0200103 }
104
Patrick Benavoli68a91282011-08-31 11:23:23 +0200105 // Start clean
106 _pSubsystemLibrary->clean();
107
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100108 // Actually load plugins
109 while (lstrPluginFiles.size()) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200110
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100111 // Because plugins might depend on one another, loading will be done
112 // as an iteration process that finishes successfully when the remaining
113 // list of plugins to load gets empty or unsuccessfully if the loading
114 // process failed to load at least one of them
Patrick Benavoli68a91282011-08-31 11:23:23 +0200115
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100116 // Attempt to load the complete list
117 if (!loadPlugins(lstrPluginFiles, strError)) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200118
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100119 // Display the list of plugins we were unable to load
Patrick Benavoli68a91282011-08-31 11:23:23 +0200120
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100121 // Leave clean
Patrick Benavoli68a91282011-08-31 11:23:23 +0200122 _pSubsystemLibrary->clean();
123
124 return false;
125 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200126 }
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100127 log("All subsystem plugins successfully loaded");
Patrick Benavoli68a91282011-08-31 11:23:23 +0200128
Patrick Benavoli6ccab9d2011-11-10 23:21:01 +0100129 // Add virtual subsystem builder
130 _pSubsystemLibrary->addElementBuilder(new TNamedElementBuilderTemplate<CVirtualSubsystem>("Virtual"));
131
Patrick Benavoli68a91282011-08-31 11:23:23 +0200132 return true;
133}
134
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100135// Subsystem plugins
136bool CSystemClass::getPluginFiles(const string& strPluginPath, list<string>& lstrPluginFiles) const
Patrick Benavoli68a91282011-08-31 11:23:23 +0200137{
138 log("Seeking subsystem plugins from folder \"%s\"", strPluginPath.c_str());
139
140 DIR *dirp;
141 struct dirent *dp;
142
143 if ((dirp = opendir(strPluginPath.c_str())) == NULL) {
144
145 return false;
146 }
147
Patrick Benavoliec0f84e2011-10-27 14:34:38 +0200148 const string strPluginPattern(gpcPluginPattern);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200149
150 // Parse it and load plugins
151 while ((dp = readdir(dirp)) != NULL) {
152
153 string strFileName(dp->d_name);
154
Patrick Benavoliec0f84e2011-10-27 14:34:38 +0200155 // Check file name ends with pattern
Patrick Benavoli68a91282011-08-31 11:23:23 +0200156 size_t uiPatternPos = strFileName.rfind(strPluginPattern, -1);
157
158 if (uiPatternPos != (size_t)-1 && uiPatternPos == strFileName.size() - strPluginPattern.size()) {
159 // Found plugin
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100160 lstrPluginFiles.push_back(strPluginPath + strFileName);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200161 }
162 }
163
164 // Close plugin folder
165 closedir(dirp);
166
167 return true;
168}
169
Patrick Benavoli9bed7ce2011-11-20 20:04:35 +0100170// Plugin symbol computation
171string CSystemClass::getPluginSymbol(const string& strPluginPath)
172{
173 // Extract plugin type out of file name
174 string strPluginPattern = gpcPluginPattern;
175 string strLibraryPrefix = gpcLibraryPrefix;
176
177 // Remove folder
178 int32_t iSlashPos = strPluginPath.rfind('/') + 1 + strLibraryPrefix.length();
179
180 // Get type
181 string strPluginType = strPluginPath.substr(iSlashPos, strPluginPath.length() - iSlashPos - strPluginPattern.length());
182
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
191bool CSystemClass::loadPlugins(list<string>& lstrPluginFiles, string& strError)
192{
193 assert(lstrPluginFiles.size());
194
195 bool bAtLeastOneSybsystemPluginSuccessfullyLoaded = false;
196
197 list<string>::iterator it = lstrPluginFiles.begin();
198
199 while (it != lstrPluginFiles.end()) {
200
201 string strPluginFileName = *it;
202
203 log("Attempting to load subsystem plugin path \"%s\"", strPluginFileName.c_str());
204
205 // Load attempt
206 void* lib_handle = dlopen(strPluginFileName.c_str(), RTLD_LAZY);
207
208 if (!lib_handle) {
209
210 // Failed
Patrick Benavoli68808c62012-02-02 17:12:41 +0100211 log("Plugin load failed: %s, proceeding on with remaining ones", 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
223 GetSusbystemBuilder pfnGetSusbystemBuilder = (GetSusbystemBuilder)dlsym(lib_handle, strPluginSymbol.c_str());
224
225 if (!pfnGetSusbystemBuilder) {
226
227 strError = "Subsystem plugin " + strPluginFileName + " does not contain " + strPluginSymbol + " symbol.";
228
229 return false;
230 }
231
232 // Fill library
233 pfnGetSusbystemBuilder(_pSubsystemLibrary);
234
235 // Account for this success
236 bAtLeastOneSybsystemPluginSuccessfullyLoaded = true;
237
238 // Remove successfully loaded plugin from list and select next
239 lstrPluginFiles.erase(it++);
240 }
241
242 // Check for success
243 if (!bAtLeastOneSybsystemPluginSuccessfullyLoaded) {
244
245 // Return list of plugins we were unable to load
246 strError = "Unable to load the following plugins:\n";
247
248 for (it = lstrPluginFiles.begin(); it != lstrPluginFiles.end(); ++it) {
249
250 strError += *it + "\n";
251 }
252
253 return false;
254 }
255
256 return true;
257}
258
Patrick Benavoli68a91282011-08-31 11:23:23 +0200259const CSubsystemLibrary* CSystemClass::getSubsystemLibrary() const
260{
261 return _pSubsystemLibrary;
262}
263
264bool CSystemClass::init(string& strError)
265{
266 return base::init(strError);
267}
268