charon-core  0.3.1
PluginManager.cpp
Go to the documentation of this file.
1 /* This file is part of Charon.
2 
3  Charon is free software: you can redistribute it and/or modify
4  it under the terms of the GNU Lesser General Public License as published by
5  the Free Software Foundation, either version 3 of the License, or
6  (at your option) any later version.
7 
8  Charon is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU Lesser General Public License for more details.
12 
13  You should have received a copy of the GNU Lesser General Public License
14  along with Charon. If not, see <http://www.gnu.org/licenses/>.
15  */
22 #include <cassert>
23 #include <cstdlib>
24 #include <set>
25 #include <algorithm>
26 #include "../include/charon-core/PluginManager.h"
27 #include "../include/charon-core/ParameteredObject.hxx"
28 #include "../include/charon-core/ParameteredGroupObject.h"
29 #include <sstream>
30 
32  const std::vector<std::string>& paths, bool dbg,bool initializeOnLoad, PluginVersionCheckLevel versionInfo):
33  _defaultTemplateType(ParameteredObject::TYPE_DOUBLE),
34  _versionInfo(versionInfo)
35 {
36  if(paths.size() == 0) {
37  throw std::invalid_argument("PluginLoader: Empty paths list given!");
38  }
39  pluginPaths = paths;
40  libSuffix = dbg ? "_d" : "";
41  _initializePluginOnLoad=initializeOnLoad;
42 }
43 
45  const std::string& path1, const std::string& path2,
46  bool dbg, bool initializeOnLoad, PluginVersionCheckLevel versionInfo) :
47  _defaultTemplateType(ParameteredObject::TYPE_DOUBLE),
48  _versionInfo(versionInfo)
49 {
50  if (path2.size() > 0) {
51  // put local path (if any) in front of global path
52  pluginPaths.push_back(path2);
53  }
54  if (path1.size() == 0) {
55  throw std::invalid_argument(
56  "PluginManger: at least one non-emtpy path has to be given!");
57  }
58  pluginPaths.push_back(path1);
59  libSuffix = dbg ? "_d" : "";
60  _initializePluginOnLoad=initializeOnLoad;
61 }
62 
64  std::vector<ParameteredObject *> v;
65 
66  // Collect items to destroy
67  for (std::map<ParameteredObject *, PLUGIN_LOADER *>::iterator it =
68  _instances.begin(); it != _instances.end(); it++) {
69  if (it->second == loader) {
70  v.push_back(it->first);
71  }
72  }
73 
74  // Destroy items
75  for (unsigned int i = 0; i < v.size(); i++) {
76  objects.erase(v[i]->getName());
77  loader->destroyInstance(v[i]);
78  _instances.erase(v[i]);
79  }
80 }
81 
83  // destroy instances in reverse execution order
84  std::list<ParameteredObject*> ordered = determineExecutionOrder();
85  while (!ordered.empty()) {
86  destroyInstance(ordered.back());
87  ordered.pop_back();
88  }
89  // unload plugins
90  for (std::map<std::string, PLUGIN_LOADER *>::iterator it =
91  _loadedPlugins.begin(); it != _loadedPlugins.end(); it++) {
92  _unloadPlugin(it->second, false);
93  }
94  objects.clear();
95  _instances.clear();
96  _loadedPlugins.clear();
97 }
98 
99 void PluginManager::_unloadPlugin(PLUGIN_LOADER * loader, bool erase) {
100  _destroyAllInstances(loader);
101 
102  loader->unload();
103  if (erase) {
104  std::string nameL = StringTool::toLowerCase(loader->getName());
105  _loadedPlugins.erase(nameL);
106  }
107  delete loader;
108 }
109 
110 void PluginManager::loadPlugin(std::string name)
112  name = StringTool::toLowerCase(name);
113  if (!isLoaded(name)) {
114  PLUGIN_LOADER * newPlugin = new PLUGIN_LOADER(
115  name, pluginPaths, libSuffix, _versionInfo);
116 
117  try {
118  newPlugin->load();
119  } catch (const AbstractPluginLoader::PluginException& e) {
120  delete newPlugin;
121  throw e;
122  }
123 
124  _loadedPlugins[name] = newPlugin;
125  sout << "(DD) Plugin \"" << name << "\" loaded successfully."
126  << std::endl;
127  } else {
129  "A Plugin with the same name (\"" + name
130  + "\") is already loaded.", name,
132  }
133 }
134 
135 void PluginManager::unloadPlugin(const std::string & name)
137  std::string nameL = StringTool::toLowerCase(name);
138  if (_loadedPlugins.find(nameL) != _loadedPlugins.end()) {
139  _unloadPlugin(_loadedPlugins[nameL]);
140  } else {
142  "There is no Plugin loaded with the name \"" + name + "\".",
144  }
145 }
146 
147 bool PluginManager::isLoaded(const std::string & name) const {
148  std::string nameL = StringTool::toLowerCase(name);
149  return _loadedPlugins.find(nameL) != _loadedPlugins.end();
150 }
151 
153  return _loadedPlugins.size();
154 }
155 
157  return _instances.size();
158 }
159 
161  const std::string & instanceName) const
163  std::map<std::string, ParameteredObject *>::const_iterator objIt =
164  objects.find((instanceName));
165  if (objIt != objects.end()) {
166  return objIt->second;
167  } else {
168  throw(AbstractPluginLoader::PluginException("The instance \""
169  + instanceName + "\" does not exist.", "unknown",
171  }
172 }
173 
175  std::string pluginName, ParameteredObject::template_type t,
176  std::string instanceName)
178  pluginName = StringTool::toLowerCase(pluginName);
179  if (instanceName == "") {
180  // generate generic name
181  instanceName = pluginName + "1";
182  int instNumber = 1;
183  while (objects.find(instanceName) != objects.end()) {
184  std::ostringstream nameGen;
185  nameGen << pluginName << ++instNumber;
186  instanceName = nameGen.str();
187  }
188  }
189  if (instanceName == "" || objects.find(instanceName) == objects.end()) {
190  if (_loadedPlugins.find(pluginName) == _loadedPlugins.end()) {
191  try {
192  loadPlugin(pluginName);
194  throw e;
195  }
196  }
197  PLUGIN_LOADER * loader = _loadedPlugins[pluginName];
198  ParameteredObject * newInstance =
199  loader->createInstance(instanceName, t);
200  _instances[newInstance] = loader;
201  objects[newInstance->getName()] = newInstance;
202  sout << "(DD) Created Instance \"" << newInstance->getName()
203  << "\" of the plugin \"" << pluginName << "\", type "
204  << newInstance->getTemplateType() << std::endl;
205  return newInstance;
206  } else {
208  "An instance with the name \"" + instanceName
209  + "\" already exists.", pluginName,
211  }
212 }
213 
215  const std::string & pluginName, const std::string & instanceName)
217  return createInstance(pluginName, _defaultTemplateType, instanceName);
218 }
219 
222  if(isInternal(toDestroy))
223  {
224  sout<<"(II) Object "<<toDestroy->getName()<<" is an internal object"<<std::endl;
225  delete toDestroy;
226  return;
227  }
228  std::string cur = toDestroy->getName(), curPlugin;
229  if (_instances.find(toDestroy) != _instances.end()) {
230  objects.erase(toDestroy->getName());
231  curPlugin = _instances[toDestroy]->getName();
232  _instances[toDestroy]->destroyInstance(toDestroy);
233  _instances.erase(toDestroy);
234  } else {
235  if(objects.find(toDestroy->getName())!=objects.end())
236  {
237  objects.erase(toDestroy->getName());
238  delete toDestroy;
239  }
240  else
241  {
243  "This instance does not exist.", "unknown",
245  }
246  }
247  sout << "(DD) Deleted Instance \"" << cur << "\" of the plugin \""
248  << curPlugin << "\"" << std::endl;
249 }
250 
252  reset();
253 
254  // Determine default template type
255  if (paramFile.isSet("global.templatetype")) {
256  std::string templateType = paramFile.get<std::string> (
257  "global.templatetype");
258  if (templateType == "int") {
260  } else if (templateType == "float") {
262  } else {
264  }
265  }
266 
267  std::vector<std::string> keys = paramFile.getKeyList();
268 
269  try {
270  // Load Plugins and create _instances
271  for (unsigned int i = 0; i < keys.size(); i++) {
272  if (keys[i].substr(keys[i].find_last_of(".") + 1,
273  keys[i].find_first_of(" ")) == "type") {
274  std::string pluginName = paramFile.get<std::string> (keys[i]);
275  if (!isLoaded(pluginName)) {
276  loadPlugin(pluginName);
277  }
278  std::string instanceName = keys[i].substr(0,
279  keys[i].find_first_of("."));
280 
281  ParameteredObject::template_type templateType =
283  if (paramFile.isSet(instanceName + ".templatetype")) {
284  std::string type = paramFile.get<std::string> (
285  instanceName + ".templatetype");
286  if (type == "int") {
287  templateType = ParameteredObject::TYPE_INT;
288  } else if (type == "float") {
289  templateType = ParameteredObject::TYPE_FLOAT;
290  } else {
291  templateType = ParameteredObject::TYPE_DOUBLE;
292  }
293  }
295  pluginName, templateType, instanceName);
296  obj->prepareDynamicInterface(paramFile);
297  obj->clearMetadata();
298  }
299  }
301  sout << "(EE) Error during load: " << e.what() << std::endl;
302  } catch (std::string s) {
303  sout << "(EE) Error during load: " << s << std::endl;
304  } catch (...) {
305  sout << "(EE) caught unknown exception during load" << std::endl;
306  }
307 
308  // load parameters and connect slots for all objects
309  std::map<std::string, ParameteredObject*>::const_iterator objIter;
310 
311  for (objIter = objects.begin(); objIter != objects.end(); objIter++) {
312  objIter->second->loadParameters(paramFile);
313  objIter->second->loadSlots(paramFile, this);
314  }
315 }
316 
317 void PluginManager::loadParameterFile(const std::string & path) {
319 }
320 
322  pf.set<std::string> ("global.templatetype",
324 
325  // load list of all connected objects
326  if (objects.size() > 0) {
327  std::map<std::string, ParameteredObject*>::const_iterator objIter;
328 
329  // save parameters and slots for all these objects
330  for (objIter = objects.begin(); objIter != objects.end(); objIter++) {
331  //Save template type parameter if unqeual to _defaultTemplateType
332  if (objIter->second->getTemplateType()
334  pf.set<std::string> (objIter->second->getName()
335  + ".templatetype", objIter->second->getTemplateType());
336  }
337  //Save other parameters and slots
338  objIter->second->save(pf);
339  }
340  }
341 }
342 
343 void PluginManager::saveParameterFile(const std::string & path) const {
344  ParameterFile pf;
345  saveParameterFile(pf);
346  pf.save(path);
347 }
348 
350  return _defaultTemplateType;
351 }
352 
354  if (t < 3) {
356  }
357 }
358 
360  std::list<ParameteredObject*> tPoints = _determineTargetPoints();
361  std::list<ParameteredObject*>::const_iterator iter;
362 
363  if (tPoints.empty()) {
365  "Could not execute workflow:\n\t"
366  "No valid target point found.\n\tPlease check if "
367  "all required plugins could be loaded,\n\tthen check if this is "
368  "a valid parameter file.", "unknown",
370  }
371 
372  for (iter = tPoints.begin(); iter != tPoints.end(); iter++) {
373  (*iter)->run();
374  }
375 }
376 
377 void PluginManager::_getConnected(std::set<std::string>& visited,
378  const std::set<std::string>& cur) const {
379  // nothing to do, if current list empty
380  if (!cur.size())
381  return;
382 
383  std::set<std::string>::const_iterator curIter;
384  std::set<std::string>::const_iterator tmpIter;
385  std::set<std::string> newCur;
386  std::set<std::string> tmp;
387 
388  // mark current objects as visited
389  visited.insert(cur.begin(), cur.end());
390 
391  // iterate over all current items
392  for (curIter = cur.begin(); curIter != cur.end(); curIter++) {
393  // search new neighbours (which are not yet visited)
394  tmp = getNeighbours(*curIter);
395  for (tmpIter = tmp.begin(); tmpIter != tmp.end(); tmpIter++) {
396  if (visited.find(*tmpIter) == visited.end())
397  newCur.insert(*tmpIter);
398  }
399  }
400  // and apply the same procedure to these new items
401  _getConnected(visited, newCur);
402 }
403 
404 void PluginManager::_getConnected(std::set<std::string>& visited,
405  const std::set<std::string>& cur, const ParameterFile& pf) const {
406  // nothing to do, if current list empty
407  if (!cur.size())
408  return;
409 
410  std::set<std::string>::const_iterator curIter;
411  std::set<std::string>::const_iterator tmpIter;
412  std::set<std::string> newCur;
413  std::set<std::string> tmp;
414 
415  // mark current objects as visited
416  visited.insert(cur.begin(), cur.end());
417 
418  // iterate over all current items
419  for (curIter = cur.begin(); curIter != cur.end(); curIter++) {
420  // search new neighbours (which are not yet visited)
421  tmp = getNeighbours(*curIter, pf);
422  for (tmpIter = tmp.begin(); tmpIter != tmp.end(); tmpIter++) {
423  if (visited.find(*tmpIter) == visited.end())
424  newCur.insert(*tmpIter);
425  }
426  }
427  // and apply the same procedure to these new items
428  _getConnected(visited, newCur, pf);
429 }
430 
431 std::set<std::string> PluginManager::getNeighbours(
432  const std::string& rootStr) const {
433  std::map<std::string, ParameteredObject*>::const_iterator rootIter;
434  rootIter = objects.find(rootStr);
435  assert(rootIter != objects.end());
436  const ParameteredObject* root = rootIter->second;
437  return root->getNeighbours();
438 }
439 
440 std::set<std::string> PluginManager::getNeighbours(
441  const std::string& rootStr,
442  const ParameterFile& pf) const {
443  std::map<std::string, ParameteredObject*>::const_iterator rootIter;
444  rootIter = objects.find(rootStr);
445  assert(rootIter != objects.end());
446  const ParameteredObject* root = rootIter->second;
447  return root->getNeighbours(pf);
448 }
449 
450 std::set<std::string> PluginManager::getConnected(
451  const std::string& root,
452  const ParameterFile& pf) const {
453  std::set<std::string> visited;
454  visited.insert(root);
455  std::set<std::string> cur = getNeighbours(root, pf);
456  _getConnected(visited, cur, pf);
457  return visited;
458 }
459 
460 std::set<std::string> PluginManager::getConnected(
461  const std::string& root) const {
462  std::set<std::string> visited;
463  visited.insert(root);
464  std::set<std::string> cur = getNeighbours(root);
465  _getConnected(visited, cur);
466  return visited;
467 }
468 
469 bool PluginManager::connect(Slot& slot1, Slot& slot2) {
470  ParameteredObject& obj1 = slot1.getParent();
471  ParameteredObject& obj2 = slot2.getParent();
472 
473  // check if connection between input and output slot
474  const std::map<std::string, Slot*>& mIn1 = obj1.getInputSlots();
475  const std::map<std::string, Slot*>& mIn2 = obj2.getInputSlots();
476  const std::map<std::string, Slot*>& mOu1 = obj1.getOutputSlots();
477  const std::map<std::string, Slot*>& mOu2 = obj2.getOutputSlots();
478  bool invalid = false;
479 
480  if (
481  (mIn1.find(slot1.getName()) == mIn1.end()) &&
482  (mIn2.find(slot2.getName()) == mIn2.end())) {
483  sout << "(WW) attempt to connect output/output" << std::endl;
484  invalid = true;
485  }
486  if (
487  ((mOu1.find(slot1.getName()) == mOu1.end()) &&
488  (mOu2.find(slot2.getName()) == mOu2.end()))) {
489  sout << "(WW) attempt to connect input/input" << std::endl;
490  invalid = true;
491  }
492  if (invalid) {
493  slot1.printWarning("source of invalid connection");
494  slot2.printWarning("target of invalid connection");
495  return false;
496  }
497 
498  // connect those objects
499  return slot1.connect(slot2);
500 }
501 
502 bool PluginManager::connect(Slot * slot1, Slot * slot2) {
503  return connect(*slot1, *slot2);
504 }
505 
507  const std::string& slot1, const std::string& slot2) {
508  // extract objects and slots
509  std::string::size_type pos = slot1.find(".");
510  assert(pos != std::string::npos);
511  std::string obj1st = slot1.substr(0, pos);
512  std::string obj1sl = slot1.substr(pos + 1);
513 
514  pos = slot2.find(".");
515  assert(pos != std::string::npos);
516  std::string obj2st = slot2.substr(0, pos);
517  std::string obj2sl = slot2.substr(pos + 1);
518 
519  // find the corresponding objects
520  std::map<std::string, ParameteredObject*>::const_iterator objIter;
521  objIter = objects.find(obj1st);
522  assert(objIter != objects.end());
523  ParameteredObject* obj1 = objIter->second;
524  objIter = objects.find(obj2st);
525  assert(objIter != objects.end());
526  ParameteredObject* obj2 = objIter->second;
527 
528  // find the corresponding slots
529  const std::map<std::string, Slot*>& mIn1 = obj1->getInputSlots();
530  const std::map<std::string, Slot*>& mIn2 = obj2->getInputSlots();
531  const std::map<std::string, Slot*>& mOu1 = obj1->getOutputSlots();
532  const std::map<std::string, Slot*>& mOu2 = obj2->getOutputSlots();
533  Slot *slotP1, *slotP2;
534  if (mIn1.find(obj1sl) != mIn1.end()) {
535  slotP1 = mIn1.find(obj1sl)->second;
536  if (mOu2.find(obj2sl) == mOu2.end()) {
537  slotP1->printWarning(
538  "target slot ("+slot2+") not found or no output slot");
539  return false;
540  }
541  slotP2 = mOu2.find(obj2sl)->second;
542  }
543  else if (mOu1.find(obj1sl) != mOu1.end()) {
544  slotP1 = mOu1.find(obj1sl)->second;
545  if (mIn2.find(obj2sl) == mIn2.end()) {
546  slotP1->printWarning(
547  "target slot ("+slot2+") not found or no input slot");
548  return false;
549  }
550  slotP2 = mIn2.find(obj2sl)->second;
551  }
552  else {
553  sout << "(WW) slot not found: " << slot1 << std::endl;
554  return false;
555  }
556 
557  // connect those slots
558  return connect(*slotP1,*slotP2);
559 }
560 
561 bool PluginManager::disconnect(Slot& slot1, Slot& slot2) {
562  return slot1.disconnect(slot2);
563 }
564 
565 bool PluginManager::disconnect(const std::string& slot1,
566  const std::string& slot2) {
567  // extract objects and slots
568  std::string::size_type pos = slot1.find(".");
569  assert(pos != std::string::npos);
570  std::string obj1st = slot1.substr(0, pos);
571  std::string obj1sl = slot1.substr(pos + 1);
572 
573  pos = slot2.find(".");
574  assert(pos != std::string::npos);
575  std::string obj2st = slot2.substr(0, pos);
576  std::string obj2sl = slot2.substr(pos + 1);
577 
578  // find the corresponding objects
579  std::map<std::string, ParameteredObject*>::const_iterator objIter;
580  objIter = objects.find(obj1st);
581  assert(objIter != objects.end());
582  ParameteredObject* obj1 = objIter->second;
583  objIter = objects.find(obj2st);
584  assert(objIter != objects.end());
585  ParameteredObject* obj2 = objIter->second;
586 
587  // find the corresponding slots
588  const std::map<std::string, Slot*>& mIn1 = obj1->getInputSlots();
589  const std::map<std::string, Slot*>& mIn2 = obj2->getInputSlots();
590  const std::map<std::string, Slot*>& mOu1 = obj1->getOutputSlots();
591  const std::map<std::string, Slot*>& mOu2 = obj2->getOutputSlots();
592  Slot *slotP1, *slotP2;
593  if (mIn1.find(obj1sl) != mIn1.end()) {
594  slotP1 = mIn1.find(obj1sl)->second;
595  if (mOu2.find(obj2sl) == mOu2.end()) {
596  slotP1->printWarning(
597  "target slot ("+slot2+") not found or no output slot");
598  return false;
599  }
600  slotP2 = mOu2.find(obj2sl)->second;
601  }
602  else if (mOu1.find(obj1sl) != mOu1.end()) {
603  slotP1 = mOu1.find(obj1sl)->second;
604  if (mIn2.find(obj2sl) == mIn2.end()) {
605  slotP1->printWarning(
606  "target slot ("+slot2+") not found or no input slot");
607  return false;
608  }
609  slotP2 = mIn2.find(obj2sl)->second;
610  }
611  else {
612  sout << "(WW) slot not found: " << slot1 << std::endl;
613  return false;
614  }
615 
616  return disconnect(*slotP1,*slotP2);
617 }
618 
619 //std::vector<std::string> PluginManager::_excludeList;
620 
621 void PluginManager::createMetadata(const std::string& targetPath) {
622 #ifndef MSVC
623  int start = 3; //on non-dll platforms the plugin library name will start with "lib"
624 #else
625  int start = 0;
626 #endif
627 
628  // avoid double metadata generation (e.g. if lib and lib_d found)
629  std::set<std::string> pluginsU;
630 
631  // Create metadata for all plugin paths
632  std::string pathBackup = FileTool::getCurrentDir();
633  for (std::vector<std::string>::const_iterator cur =
634  pluginPaths.begin();
635  cur!=pluginPaths.end(); cur++) {
636  FileTool::changeDir(*cur);
637 
638  // Fetch list of existing plugins
639  std::vector<std::string> plugins =
641  std::vector<std::string>::iterator pIterW;
642  for (pIterW=plugins.begin(); pIterW != plugins.end(); pIterW++) {
643  // extract plugin name
644  std::string& pName = *pIterW;
645  pName = pName.substr(start, pName.rfind(PLUGIN_EXTENSION)-start);
646  // strip debug extension, if any
647  if (pName.substr(pName.size()-2) == "_d") {
648  pName = pName.substr(0, pName.size()-2);
649  }
650  }
651  // insert plugin names to plugin name set
652  pluginsU.insert(plugins.begin(),plugins.end());
653  }
654  FileTool::changeDir(pathBackup);
655 
656  int pluginCount = 0 ;
657  // Now generate metadata for all (unique) plugin names
658  // skipping the names from the exclude list.
659  // Which dll file to use is then handled by the plugin loader.
660  std::set<std::string>::const_iterator pIterU;
661  std::list<std::string> skipped;
662  for (pIterU=pluginsU.begin(); pIterU != pluginsU.end(); pIterU++) {
663  if (std::find(_excludeList.begin(),_excludeList.end(),*pIterU)
664  == _excludeList.end()) {
665  // not in exclude list
666  if(_generateMetadataForPlugin(*pIterU,targetPath+"/"+*pIterU+".wrp"))
667  pluginCount ++ ;
668  sout << "(DD) " << std::endl;
669  }
670  else {
671  skipped.push_back(*pIterU);
672  }
673  }
674 #ifndef NDEBUG
675  // only displayed in debug mode to check
676  // if the exclude list works as expected.
677  // identical output will be shown by tuchulcha-run
678  // during generation of the exclude list from
679  // tuchulcha's list with wildcards
680  if (skipped.size() > 0) {
681  sout << "(DD) The following libraries matched the exclude list:"
682  << std::endl;
683  }
684  std::list<std::string>::const_iterator skipIter;
685  for (skipIter=skipped.begin();skipIter!=skipped.end();skipIter++) {
686  sout << "(DD) \t" << *skipIter << std::endl;
687  }
688 #endif
689 
690  sout << "(II) Finished generating metadata\n"
691  << "(II) Loaded " << pluginCount << " plugins" << std::endl ;
692 }
693 
694 void PluginManager::setExcludeList(const std::vector<std::string>& list) {
695  _excludeList = list;
696 }
697 
699  const std::string& pluginName, const std::string& filename) {
700  if (!pluginName.size()) {
701  sout << "(EE) " << __FILE__ << ":" << __LINE__ << "\t"
702  << "emtpy pluginName given (metadata generation)!\n" << std::endl;
703  return false;
704  }
705  try {
706  bool alreadyLoaded = isLoaded(pluginName);
707 
708  if (!alreadyLoaded) {
709  loadPlugin(pluginName);
710  }
711  ParameteredObject* curInst = createInstance(pluginName);
712  curInst->getMetadata().save(filename);
713  destroyInstance(curInst);
714 
715  if (!alreadyLoaded) {
716  unloadPlugin(pluginName);
717  }
718  return true ;
719  } catch (const AbstractPluginLoader::PluginException& e) {
720  std::string errMsg = e.what();
721  switch(e.getErrorCode()) {
724  for (size_t pos = errMsg.find("\n"); pos != std::string::npos;
725  pos=errMsg.find("\n",pos+1)) {
726  errMsg.replace(pos,1,"\n(DD) \t");
727  }
728  sout << "(DD) \"" << e.getPluginName()
729  << "\" is no charon plugin:\n(DD) \t"
730  << e.what() << std::endl;
731  break;
732  default:
733  for (size_t pos = errMsg.find("\n"); pos != std::string::npos;
734  pos=errMsg.find("\n",pos+1)) {
735  errMsg.replace(pos,1,"\n(EE) \t");
736  }
737  sout << "(EE) Could not generate metadata for module \""
738  << e.getPluginName()
739  << "\":\n(EE) \t"
740  << errMsg << std::endl;
741  break;
742  }
743  } catch(const std::exception& e) {
744  sout << "(EE) Could not generate metadata for plugin \""
745  << pluginName << "\":\n(EE) \t"
746  << "Possible execption in plugin constructor:\n(EE)\t"
747  << e.what() << std::endl ;
748  } catch(...) {
749  sout << "(EE) Could not generate metadata for plugin \""
750  << pluginName << "\":\n(EE) \t"
751  << "Possible non-standard execption in plugin constructor!"
752  << std::endl ;
753  }
754  return false ;
755 }
756 
760 }
761 
762 std::list<ParameteredObject*> PluginManager::_determineTargetPoints() {
763  std::list<ParameteredObject*> targetPoints;
764  std::map<std::string, ParameteredObject *>::const_iterator it;
765  for (it = objects.begin(); it != objects.end(); it++) {
766  if (it->second->_active){ // checks whether the plugin is active
767  bool connected = false;
768  bool activeTest = false;
769  std::map<std::string, Slot *> outputslots =
770  it->second->getOutputSlots();
771  std::map<std::string, Slot *>::const_iterator slotIter;
772  for (slotIter = outputslots.begin(); !connected && slotIter
773  != outputslots.end(); slotIter++) {
774  connected = slotIter->second->connected();
775  const std::set<Slot*>& listOfTargets = slotIter->second->getTargets();
776  std::set<Slot*>::const_iterator tmp = listOfTargets.begin();
777  for (; tmp!=listOfTargets.end();tmp++) {
778  if ((*tmp)->getParent()._active){
779  activeTest = true;
780  }
781  }
782  }
783  if (!connected || !(activeTest)) { // verifies whether the next plugin is active
784  sout << "(DD) Found target point \"" << it->second->getName()
785  << "\"" << std::endl;
786  targetPoints.push_back(it->second);
787  }
788  }
789  }
790  return targetPoints;
791 }
792 
793 std::list<ParameteredObject*> PluginManager::determineExecutionOrder() {
794  std::list<ParameteredObject*> waiting = _determineTargetPoints();
795  std::reverse(waiting.begin(), waiting.end());
796  std::list<ParameteredObject*> finished;
797  ParameteredObject* cur;
798 
799  // start with target points as sinks
800  while(!waiting.empty()) {
801  // mark object as finished and replace
802  // by preceeding objects in waiting stack
803  finished.push_front(cur = waiting.front());
804  waiting.pop_front();
805  const std::map<std::string, Slot*>& inputs = cur->getInputSlots();
806  std::map<std::string, Slot*>::const_iterator sIter;
807  std::set<Slot*>::const_iterator tIter;
808  for (sIter = inputs.begin(); sIter != inputs.end(); sIter++) {
809  const std::set<Slot*>& targets = sIter->second->getTargets();
810  for (tIter = targets.begin(); tIter != targets.end(); tIter++) {
811  waiting.push_front(&((*tIter)->getParent()));
812  }
813  }
814  }
815 
816  // now remove duplicate entries, keeping the first one
817  std::list<ParameteredObject*>::iterator iBegin = finished.begin();
818  std::list<ParameteredObject*>::iterator iEnd = finished.end();
819  std::list<ParameteredObject*>::iterator iter = iBegin;
820  while (iter != iEnd) {
821  const ParameteredObject* curObj = *iter;
822  iEnd = std::remove(++iter, iEnd, curObj);
823  }
824 
825  // remove tail that may contain bogus elements
826  if (iEnd != finished.end())
827  finished.erase(iEnd, finished.end());
828 
829  // return resulting list
830  return finished;
831 }
832 
834  reset();
835 }
836 
837 const std::vector<std::string>& PluginManager::getPluginPaths() const {
838 
839  return pluginPaths;
840 }
841 
843  assert(instance);
844  if (objects.find(instance->getName()) != objects.end()) {
845  throw std::runtime_error(
846  std::string("attempt to insert an instance named ")
847  + instance->getName()
848  + "to a PluginManager that already handles "
849  "an instance with the same name!");
850  }
851  objects.insert(std::pair<std::string,ParameteredObject*>(
852  instance->getName(),instance));
853 }
854 
856  //if(dynamic_cast<SlotBundle*>(obj))
857  //return true;
858  // else if(dynamic_cast<ParameteredGroupObject*>(obj))
859  // return true;
860  return false;
861 }
862 
864 
865  std::map<std::string, ParameteredObject *>::const_iterator iter;
866 
867  if (objects.empty()) {
869  "Could not reset executed flags in workflow:\n\t"
870  "No valid target point found.\n\t"
871  "Please check if all required plugins could be loaded,\n\t"
872  "then check if this is a valid parameter file.", "unknown",
874  }
875 
876  for (iter = objects.begin(); iter != objects.end(); iter++) {
877 // if(isGroup((*iter)))
878 // {
879 // AbstractBaseGroupIntf* grpIntf=dynamic_cast<AbstractBaseGroupIntf*>((*iter));
880 // grpIntf->loadWorkflow(AbstractPluginLoader::pluginPaths);
881 // }
882  (*iter).second->setExecuted(false);
883  }
884 }
885 
887  const std::string& filePrefix) {
888 
889  // Determine default template type
890  if (paramFile.isSet("global.templatetype")) {
891  std::string templateType = paramFile.get<std::string> (
892  "global.templatetype");
893  if (templateType == "int") {
895  } else if (templateType == "float") {
897  } else {
899  }
900  }
901 
902  std::vector<std::string> keys = paramFile.getKeyList();
903 
904  try {
905  // Load Plugins and create _instances
906  for (unsigned int i = 0; i < keys.size(); i++) {
907  if (keys[i].substr(keys[i].find_last_of(".") + 1,
908  keys[i].find_first_of(" ")) == "type") {
909  std::string pluginName = paramFile.get<std::string> (keys[i]);
910  bool alreadyLoaded = isLoaded(pluginName);
911  if (!alreadyLoaded) {
912  loadPlugin(pluginName);
913  }
914  std::string instanceName = keys[i].substr(0,
915  keys[i].find_first_of("."));
916 
918  pluginName, instanceName);
919  if (obj->isDynamic()) {
920  obj->prepareDynamicInterface(paramFile);
921  std::string targetFileName =
922  filePrefix + "_" + instanceName + ".wrp";
923  sout << "(DD) saving dynamic metadata for module to "
924  << targetFileName << std::endl;
925  obj->getMetadata().save(targetFileName);
926  }
927  destroyInstance(obj);
928  if (!alreadyLoaded) {
929  unloadPlugin(pluginName);
930  }
931  }
932  }
934  sout << "(EE) Error during load: " << e.what() << std::endl;
935  } catch (std::string s) {
936  sout << "(EE) Error during load: " << s << std::endl;
937  } catch (...) {
938  sout << "(EE) caught unknown exception during load" << std::endl;
939  }
940  sout << std::endl;
941 }
942 
943 void PluginManager::createDynamicMetadata(const std::string& pluginName,
944  const ParameterFile& paramFile, const std::string& fileName) {
945 
946  if (!pluginName.size()) {
947  sout << "(EE) " << __FILE__ << ":" << __LINE__ << "\t"
948  << "emtpy pluginName given (dynamic metadata generation)!\n"
949  << std::endl;
950  return;
951  }
952  try {
953  bool alreadyLoaded = isLoaded(pluginName);
954  if (!alreadyLoaded) {
955  loadPlugin(pluginName);
956  }
957 
958  ParameteredObject* obj = createInstance(pluginName);
959  obj->prepareDynamicInterface(paramFile);
960  obj->getMetadata().save(fileName);
961  destroyInstance(obj);
962 
963  if (!alreadyLoaded) {
964  unloadPlugin(pluginName);
965  }
966  } catch (const AbstractPluginLoader::PluginException& e) {
967  switch(e.getErrorCode()) {
969  sout << "(WW) \"" << e.getPluginName()
970  << "\" is no charon plugin:\n(WW) \t"
971  << e.what() << std::endl;
972  break;
973  default:
974  sout << "(EE) Exception during (dynamic) metadata generation of \""
975  << e.getPluginName()
976  << "\":\n(EE) \t"
977  << e.what() << std::endl;
978  break;
979  }
980  }
981  sout << std::endl;
982 }
983 
984 bool PluginManager::initializePluginOnLoad() const {
985  return _initializePluginOnLoad;
986 }
987 
988 void PluginManager::setInitiailizePluginOnLoad(bool initOnLoad) {
989  _initializePluginOnLoad = initOnLoad;
990 }
991 
994  switch (t) {
996  return "double";
998  return "float";
1000  return "int";
1001  default:
1002  return "double";
1003  }
1004 }
1005 
void saveParameterFile(ParameterFile &paramFile) const
save parameters and connections of all managed plugins
A plugin with the same name is already loaded.
File is a shared object but misses required functions.
void clearMetadata()
delete metadata cache to save some space
size_t getLoadedPluginsCount() const
number of loaded plugins
bool isInternal(ParameteredObject *obj)
Check if parametered object is an internal object.
virtual const std::string getTemplateType() const
get template type as string
bool _generateMetadataForPlugin(const std::string &pluginName, const std::string &filename)
Creates metadata information for a specific plugin.
std::string libSuffix
Lib suffix e.g. _d for debug builds.
This class serves to store parameters used within the Charon Project.
Definition: ParameterFile.h:68
std::set< std::string > getNeighbours(const std::string &root) const
Convenience function to get neighbours of given object.
#define PLUGIN_EXTENSION
system plugin file extension (dll,so,dylib)
Definition: PluginManager.h:47
const std::string & getPluginName() const
Get Plugin Name.
The template type of the instance is float.
SplitStream sout
Dummy instance for usage in other files (for interface too).
template_type
Integer which represents a template type.
std::vector< std::string > charon_core_DLL_PUBLIC getFilesWithSuffix(std::string suffix)
Search files with given suffix.
Definition: FileTool.cpp:104
bool disconnect()
Remove all slot targets.
Definition: Slots.cpp:104
void setDefaultTemplateType(ParameteredObject::template_type t)
Set the default template type property.
virtual std::string templateTypeToString(ParameteredObject::template_type t) const
Converts template_type to std::string.
Base class for serializable objects.
ErrorCode getErrorCode() const
Plugin Exception Error Code.
virtual std::set< std::string > getConnected(const std::string &root, const ParameterFile &pf) const
Recurse into object list and find connected objects.
const ParameterFile & getMetadata()
get metadata
void createMetadata(const std::string &targetPath="")
generate plugin metadata and store to given path
ParameteredObject::template_type _defaultTemplateType
current default template type.
ParameteredObject & getParent()
get parent object
Definition: Slots.cpp:65
void unloadPlugin(const std::string &name)
Unloads a plugin.
void _destroyAllInstances(PLUGIN_LOADER *p)
Deletes all instances of a loaded plugin.
void _getConnected(std::set< std::string > &visited, const std::set< std::string > &cur) const
Recurse into object list and find connected objects.
std::map< std::string, ParameteredObject * > objects
currently existing instances that are handled by this PluginManager
The template type of the instance is double.
bool connect(Slot &slot1, Slot &slot2)
Connect slots.
std::vector< std::string > getKeyList(std::string beginsWith="") const
Look for parameters beginning with a given string.
bool isLoaded(const std::string &name) const
Checks if a plugin is loaded.
int charon_core_DLL_PUBLIC changeDir(const std::string &dir)
Change current working directory.
Definition: FileTool.cpp:91
void setExcludeList(const std::vector< std::string > &list)
set exclude list
const std::map< std::string, Slot * > & getOutputSlots() const
Get all output slots as map.
void _unloadPlugin(PLUGIN_LOADER *p, bool erase=true)
Unloads a plugin and destroys instances.
size_t getInstancesCount() const
number of handled instances
virtual std::string getName() const
Get slot name.
Definition: Slots.cpp:73
std::map< ParameteredObject *, PLUGIN_LOADER * > _instances
Links the instances to their PluginLoader.
void _unloadAllPlugins()
Unloads all Plugins and destroys all instances.
int charon_core_DLL_PUBLIC remove(const std::string &file)
Remove file.
Definition: FileTool.cpp:159
void set(std::string parameter, const T &value=T())
Set a parameter to the given single value.
virtual ~PluginManager()
default destructor
The template type of the instance is integer.
const std::vector< std::string > & getPluginPaths() const
Gets the plugin paths.
std::map< std::string, PLUGIN_LOADER * > _loadedPlugins
Saves the currently loaded plugins.
void loadPlugin(std::string name)
Loads a plugin stored in the previously declared folder.
void reset()
reset plugin manager
std::string charon_core_DLL_PUBLIC getCurrentDir()
Get current working directory.
Definition: FileTool.cpp:95
T get(std::string parameter) const
Get the value of a specified parameter.
bool isSet(std::string parameter) const
Check if a givem parameter has already been set.
ParameteredObject * createInstance(std::string pluginName, ParameteredObject::template_type t, std::string instanceName="")
Create a new instance of a plugin.
PluginVersionCheckLevel
info how to handle version information
std::list< ParameteredObject * > determineExecutionOrder()
Determine execution order.
std::vector< std::string > pluginPaths
Paths where the plugins are stored.
While unloading a plugin or deleting an instance: The plugin is not loaded.
const std::map< std::string, Slot * > & getInputSlots() const
Get all input slots as map.
void runWorkflow()
run whole workflow
charon_core_DLL_PUBLIC std::string type(const std::string &typeInfo)
Get type representation.
Commom properties of slot objects.
Definition: Slots.h:47
An instance with the same name already exists.
std::vector< std::string > _excludeList
exclude list for metadata generation
void printWarning(const std::string &msg) const
print warning message with slot name to sout
Definition: Slots.cpp:134
virtual void prepareDynamicInterface(const ParameterFile &file)
prepare interface of parameters and slots
ParameteredObject * getInstance(const std::string &instanceName) const
get an existing instance of a loaded plugin.
void destroyInstance(ParameteredObject *toDestroy)
Delete an instance of a loaded plugin.
Version information for the plugin is missing while explicit version check was requested.
bool disconnect(Slot &slot1, Slot &slot2)
Disconnect slots.
bool save(std::string fileName) const
Save parameters and values to a plain text file.
const std::string & getName() const
instance name
ParameteredObject::template_type getDefaultTemplateType() const
Get the default template type property.
std::string charon_core_DLL_PUBLIC toLowerCase(std::string s)
Convert a string to lowercase.
Definition: StringTool.cpp:55
void resetExecuted()
Set the executed flags of the objects to false.
void insertInstance(ParameteredObject *instance)
Insert an existing parametered object instance.
PluginManager(const std::vector< std::string > &pluginPaths, bool debugSuffix=DEFAULT_DEBUG_SUFFIX, bool initializeOnLoad=false, PluginVersionCheckLevel versionInfo=PluginVersionIgnore)
default constructor
void createDynamicMetadata(const ParameterFile &paramFile, const std::string &filePrefix)
generate plugin metadata for dynamic plugins and store to given path
std::list< ParameteredObject * > _determineTargetPoints()
Look for execution target points.
bool connect(Slot &target)
Connect with given slot.
Definition: Slots.cpp:94
void loadParameterFile(const ParameterFile &pf)
Reads a parameter file.
#define PLUGIN_LOADER
plugin loader classname (unix/win)
Definition: PluginManager.h:42