source: pacpusframework/branches/2.0-beta1/src/PacpusLib/ComponentManager.cpp@ 169

Last change on this file since 169 was 162, checked in by Marek Kurdej, 11 years ago

Update: merged changes from trunk.

  • Property svn:executable set to *
File size: 13.7 KB
RevLine 
[89]1// %pacpus:license{
2// This file is part of the PACPUS framework distributed under the
3// CECILL-C License, Version 1.0.
4// %pacpus:license}
[162]5/// @author Gerald Dherbomez <firstname.surname@utc.fr>
[89]6/// @version $Id: ComponentManager.cpp 76 2013-01-10 17:05:10Z kurdejma $
7
[162]8#include <Pacpus/kernel/ComponentFactoryBase.h>
[89]9#include <Pacpus/kernel/ComponentManager.h>
10#include <Pacpus/kernel/ComponentBase.h>
[110]11#include <Pacpus/kernel/ConnectionBase.h>
[89]12#include <Pacpus/kernel/Log.h>
13#include <QObject>
14#include <QDomNodeList>
15
16using namespace pacpus;
17
18DECLARE_STATIC_LOGGER("pacpus.core.ComponentManager");
19
20ComponentManager * ComponentManager::mInstance = NULL;
21
22ComponentManager * ComponentManager::create()
23{
24 return getInstance();
25}
26
27ComponentManager * ComponentManager::getInstance()
28{
29 LOG_TRACE("getInstance()");
[146]30 LOG_TRACE("before: mInstance = " << mInstance);
[89]31
[146]32 if (!mInstance) {
[89]33 LOG_INFO("creating new instance...");
34 mInstance = new ComponentManager();
35 LOG_DEBUG("mInstance = " << mInstance);
36 }
37
[146]38 LOG_TRACE("after : mInstance = " << mInstance);
[89]39 return mInstance;
40}
41
42void ComponentManager::destroy()
43{
44 LOG_TRACE("destroy");
45
[146]46 LOG_TRACE("before: mInstance = " << mInstance);
[89]47 delete mInstance;
48 mInstance = NULL;
[146]49 LOG_TRACE("after : mInstance = " << mInstance);
[89]50}
51
52ComponentManager::ComponentManager()
53{
54 LOG_TRACE("constructor");
55
56 xmlTree_ = XmlConfigFile::create();
57 LOG_DEBUG("component manager was created");
58}
59
60ComponentManager::~ComponentManager()
61{
62 LOG_TRACE("destructor");
63
[146]64 for (ComponentMap::iterator it = componentMap_.begin(), itend = componentMap_.end(); it != itend; ++it) {
65 bool unregisteredSuccessfully = unregisterComponent(it.key());
66 }
[89]67
68 LOG_DEBUG("component manager was deleted");
69}
70
71bool ComponentManager::registerComponentFactory(ComponentFactoryBase* addr, const QString& type)
72{
73 LOG_TRACE("registerComponentFactory(type="<< type << ")");
74
75 if (factoryMap_.contains(type))
76 {
77 LOG_WARN("cannot register a component factory of type '" << type << "'. It already belongs to the manager");
78 return false;
79 }
80
81 factoryMap_[type] = addr;
82 LOG_INFO("registered component factory '" << type << "'");
83
84 return true;
85}
86
[146]87bool ComponentManager::unregisterComponentFactory(const QString& type)
[89]88{
[146]89 LOG_TRACE("unregisterComponentFactory(type="<< type << ")");
[89]90
[146]91 if (!factoryMap_.contains(type)) {
[89]92 LOG_WARN("cannot unregister component factory '" << type << "'. It was not registered");
93 return false;
94 }
95
96 factoryMap_.remove(type);
97 LOG_INFO("unregistered component factory '" << type << "'");
98
99 return true;
100}
101
102bool ComponentManager::registerComponent(ComponentBase* addr, const QString& name)
103{
104 LOG_TRACE("registerComponent(name="<< name << ")");
105
106 if (componentMap_.contains(name))
107 {
108 LOG_WARN("cannot register component '" << name << "'. A component with the same name exists already");
109 return false;
110 }
111
112 componentMap_[name] = addr;
113 LOG_INFO("registered component " << name);
114
115 return true;
116}
117
[146]118bool ComponentManager::unregisterComponent(const QString& name)
[89]119{
[146]120 LOG_TRACE("unregisterComponent(name="<< name << ")");
[89]121
[146]122 if (!componentMap_.contains(name)) {
[89]123 LOG_WARN("cannot unregister component '" << name << "'. It was not registered");
124 return false;
125 }
126
127 // FIXME: delete component
[146]128 ComponentBase* component = componentMap_.value(name, NULL);
129 //delete component;
130
131 // FIXME: remove from map (causes segfault in QMap::qMapLessThanKey on Windows)
132 //componentMap_.remove(name);
[89]133 LOG_INFO("unregistered component '" << name << "'");
134
135 return true;
136}
137
138bool ComponentManager::createComponent(const QString& type, const QString& name)
139{
140 LOG_TRACE("createComponent(type=" << type << ", " << "name="<< name << ")");
141
[146]142 if (factoryMap_.contains(type)) {
143 ComponentFactoryBase* factory = factoryMap_.value(type);
144 assert(factory);
145 factory->addComponent(name);
[89]146 return true;
147 }
148
149 LOG_WARN("cannot create component '" << name << "'"
150 << ". Component factory for type '" << type << "'"
151 << " does not exist or was not registered"
152 );
153 return false;
154}
155
156bool ComponentManager::loadPlugin(const QString& filename)
157{
158 LOG_TRACE("loadPlugin(filename=" << filename << ")");
159
160 pluginLoader_.setFileName(filename);
161
162 if (!pluginLoader_.load()) {
163 LOG_ERROR("cannot load plugin '" << filename << "'"
164 << ". Plugin loader returned error: " << pluginLoader_.errorString()
165 );
166 return false;
167 }
168
169 QObject * plugin = pluginLoader_.instance();
170 if (NULL == plugin) {
171 LOG_WARN("cannot create an instance of the plugin '" << filename << "'"
172 << ". Plugin loader returned error: " << pluginLoader_.errorString()
173 );
174 return false;
175 }
176 pluginList_.append(plugin);
177 LOG_INFO("loaded plugin '" << qobject_cast<PacpusPluginInterface*>(plugin)->name() << "'"
178 << " from file '" << pluginLoader_.fileName() << "'"
179 );
180 return true;
181}
182
183bool ComponentManager::createConnection(const QString& outputSignature, const QString& inputSignature, const QString& type, int priority = 0)
184{
185 QStringList output = outputSignature.split(".");
186 QStringList input = inputSignature.split(".");
187
188 if(getComponent(output[0])==NULL) {
189 LOG_WARN("cannot make connection : component " << output[0] << " not found");
190 return false;}
191 if(getComponent(output[0])->getOutput(output[1]) == NULL) {
192 LOG_WARN("cannot make connection : component " << output[0] << " doesn't have output " << output[1]);
193 return false;}
194 if(getComponent(input[0])==NULL) {
195 LOG_WARN("cannot make connection : component " << input[0] << " not found");
196 return false;}
197 if(getComponent(input[0])->getInput(input[1]) == NULL) {
198 LOG_WARN("cannot make connection : component " << input[0] << " doesn't have intput " << input[1]);
199 return false;}
200
[96]201 // NOTE Create communicationInterface if needed ??
[89]202
[96]203 return connectInterface(getComponent(output[0])->getOutput(output[1]), getComponent(input[0])->getInput(input[1]), priority);
[89]204
205}
206
207std::size_t ComponentManager::loadComponents(const QString& configFilename)
208{
209 LOG_TRACE("loadComponents(filename=" << configFilename << ")");
210
211 // load the components tree in memory
212 xmlTree_->loadFile(configFilename);
213
214 {
215 // Load the plugins containing the components
[146]216 QStringList plugins = xmlTree_->getAllPluginsNames();
[89]217 Q_FOREACH (QString plugin, plugins) {
218 if (!loadPlugin(plugin)) {
219 LOG_WARN("cannot load plugin '" << plugin << "'");
[146]220 } else {
221 LOG_INFO("successfully loaded plugin '" << plugin << "'");
[89]222 }
223 }
224 }
225
226 QDomNodeList componentsNodeList = xmlTree_->getAllComponents();
227 XmlComponentConfig cfg;
228
229 // First, create all the components in the XML list
230 for (int i = 0; i < componentsNodeList.size(); ++i) {
231 cfg.localCopy(componentsNodeList.item(i).toElement());
232 QString componentType = cfg.getComponentType();
233 QString componentName = cfg.getComponentName();
[110]234 LOG_DEBUG("try to create component '" << componentName << "'");
235
[89]236 // create the component and automatically add it to the component manager list
237 if (!createComponent(componentType, componentName)) {
238 LOG_ERROR("cannot create component '" << componentName << "'");
239 continue;
240 }
241 }
242
243 int componentsToConfigureCount = componentMap_.count();
244
245 // Second, try to configure the components without regarding the dependencies
246 for (int i = 0; i < componentsNodeList.size(); ++i) {
247 cfg.localCopy(componentsNodeList.item(i).toElement());
248 QString componentName = cfg.getComponentName();
[110]249 LOG_DEBUG("try to configure component '" << componentName << "'");
[89]250
251 // copy locally the config parameters of the component
252 ComponentBase * component = getComponent(componentName);
253 if (NULL == component) {
254 LOG_WARN("component '" << componentName << "' does not exist");
255 } else {
256 component->param.localCopy(cfg.qDomElement());
[152]257 component->setConfigurationState(component->configureComponent(cfg));
[89]258 }
259 } // for
260
261 // Third, if some components requested a delayed configuration, retry
262 for (int i = 0; i < componentsNodeList.size(); ++i) {
263 cfg.localCopy(componentsNodeList.item(i).toElement());
264 QString componentName = cfg.getComponentName();
265
266 ComponentBase * component = getComponent(componentName);
267 if (NULL == component) {
268 LOG_WARN("component '" << componentName << "' does not exist");
269 } else {
[152]270 // Pacpus 2.0 : add inputs and outputs
271 component->addInputs();
272 component->addOutputs();
[120]273
[152]274 if (ComponentBase::CONFIGURATION_DELAYED == component->configurationState()) {
[110]275 LOG_DEBUG("try to configure component '" << componentName << "'");
[89]276
277 // copy locally the config parameters of the component
278 component->param.localCopy(cfg.qDomElement());
[152]279 component->setConfigurationState(component->configureComponent(cfg));
[89]280 }
281
[152]282 if (ComponentBase::CONFIGURED_OK == component->configurationState()) {
[89]283 --componentsToConfigureCount;
284 } else {
[110]285 LOG_ERROR("cannot configure component '" << componentName << "'"
[89]286 << ". Dependencies with other components are too complex"
287 << ". It was not configured, please review your configuration and/or your component"
[110]288 );
[152]289 component->setConfigurationState(ComponentBase::CONFIGURED_FAILED);
[89]290 }
291 }
292 } // for
293
294 LOG_INFO(componentMap_.count() << " component(s) were loaded");
295 if (componentsToConfigureCount > 0) {
296 LOG_WARN(componentsToConfigureCount << " component(s) were not configured");
297 }
298
299 // Fourthly, create connections find in the XML list
300 QDomNodeList connectionsNodeList = xmlTree_->getAllConnections();
301
302 for (int i = 0; i < connectionsNodeList.size(); ++i) {
303 cfg.localCopy(connectionsNodeList.item(i).toElement());
304 QString connectionInput = cfg.getConnectionInput();
305 QString connectionOutput = cfg.getConnectionOutput();
306 QString connectionType = cfg.getConnectionType();
307 int connectionPriority = cfg.getConnectionPriority();
308
[120]309 //TODO set connection mode from string
310
311 //InputInterfaceBase::GetLast;
312 //InputInterfaceBase::NeverSkip;
313 //InputInterfaceBase::TimeBounded;
314
[89]315 if (!createConnection(connectionOutput, connectionInput, connectionType,connectionPriority)) {
316 LOG_ERROR("cannot create connection '" << connectionOutput+"=>"+connectionInput << "'");
317 continue;
318 }
[120]319 } // for
[89]320
321 return componentMap_.count();
322}
323
324bool ComponentManager::start()
325{
326 LOG_TRACE("start()");
327
328 bool result = true;
[146]329 for (ComponentMap::iterator it = componentMap_.begin(), itend = componentMap_.end(); it != itend; ++it) {
[89]330 result &= start(it.key());
[146]331 }
[89]332
333 return result;
334}
335
336bool ComponentManager::start(const QString& componentName)
337{
338 LOG_TRACE("start(component=" << componentName << ")");
339
340 ComponentBase* component = getComponent(componentName);
[153]341 if (!component) {
[89]342 LOG_WARN("cannot start component '" << componentName << "'. It does not exist!");
343 return false;
344 }
345
346 LOG_INFO("starting component '" << componentName << "'...");
[141]347 if (!component->startComponent()) {
[89]348 LOG_WARN("cannot start component '" << componentName << "'. It can already be started");
[141]349 }
[153]350 LOG_INFO("successfully started component '" << componentName << "'");
[89]351 return true;
352}
353
354bool ComponentManager::stop()
355{
356 LOG_TRACE("stop()");
357
358 bool result = true;
[146]359 for (ComponentMap::iterator it = componentMap_.begin(), itend = componentMap_.end(); it != itend; ++it) {
360 result &= stop(*it);
361 }
[89]362
363 return result;
364}
365
[146]366bool ComponentManager::stop(ComponentBase* component) const
367{
368 if (!component) {
369 LOG_WARN("NULL component pointer");
370 return false;
371 }
372 if (!component->stopComponent()) {
373 return false;
374 }
375 return true;
376}
377
[89]378bool ComponentManager::stop(const QString& componentName)
379{
380 LOG_TRACE("stop(component=" << componentName << ")");
381
382 ComponentBase* component = getComponent(componentName);
[146]383 if (!component) {
[89]384 LOG_WARN("cannot stop component '" << componentName << "'" << ". It does not exist");
385 return false;
386 }
387
388 LOG_INFO("stopping component '" << componentName << "'...");
[146]389 if (!stop(component)) {
[89]390 LOG_WARN("cannot stop component '" << componentName << "'" << ". It can be already stopped");
[141]391 }
[89]392
393 return true;
394}
395
396ComponentBase* ComponentManager::getComponent(const QString& name)
397{
398 LOG_TRACE("getComponent(name=" << name << ")");
399
400 ComponentMap::iterator it = componentMap_.find(name);
[141]401 if (it != componentMap_.end()) {
[89]402 return *it;
[141]403 }
[89]404
405 LOG_WARN("cannot retrieve component '" << name << "'" << ". It does not exist");
406 return NULL;
407}
408
409QStringList ComponentManager::getAllComponentsName() const
410{
411 LOG_TRACE("getAllComponentsName()");
412 return xmlTree_->getAllComponentsNames();
413}
Note: See TracBrowser for help on using the repository browser.