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

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

Fixed: C4996 unchecked iterator warning on MSVC.

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