source: pacpusframework/trunk/src/PacpusLib/ComponentManager.cpp@ 183

Last change on this file since 183 was 182, checked in by Marek Kurdej, 12 years ago

Fixed: dependencies in InputOutputBase, ConnectionBase.

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