YARP
Yet Another Robot Platform
kbase.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2006-2020 Istituto Italiano di Tecnologia (IIT)
3  * All rights reserved.
4  *
5  * This software may be modified and distributed under the terms of the
6  * BSD-3-Clause license. See the accompanying LICENSE file for details.
7  */
8 
9 #include <yarp/manager/kbase.h>
10 #include <yarp/manager/utility.h>
11 #include <yarp/manager/resource.h>
12 
13 #include <cstdio>
14 #include <cctype>
15 #include <string>
16 #include <cstring>
17 
18 
19 using namespace std;
20 using namespace yarp::manager;
21 
22 
23 bool KnowledgeBase::createFrom(ModuleLoader* _mloader,
24  AppLoader* _apploader, ResourceLoader* _resloader)
25 {
26  modloader = _mloader;
27  apploader = _apploader;
28  resloader = _resloader;
29 
33  kbGraph.clear();
34  tmpGraph.clear();
35  selconnections.clear();
36  selmodules.clear();
37  selapplications.clear();
38  selresources.clear();
39 
40  /*
41  * Loading resources
42  */
43  if(resloader)
44  {
45  GenericResource* resource;
46  resloader->reset();
47  while((resource=resloader->getNextResource()))
48  addResource(resource);
49  }
50 
54  if(modloader)
55  {
56  Module* module;
57  modloader->reset();
58  while((module=modloader->getNextModule()))
59  addModule(module);
60  }
61 
65  if(apploader)
66  {
67  Application* application;
68  apploader->reset();
69  while((application = apploader->getNextApplication()))
70  addApplication(application);
71  }
72 
73  return true;
74 }
75 
76 
77 bool KnowledgeBase::addApplication(Application* app, char** szAppName_, bool modifyName)
78 {
79  __CHECK_NULLPTR(app);
80  ErrorLogger* logger = ErrorLogger::Instance();
81  static map<string, int> mapId;
82  app->setLabel(app->getName());
83  if(kbGraph.hasNode(app))
84  {
85  if(mapId.find(string(app->getName()))==mapId.end())
86  mapId[app->getName()] = 1;
87  else
88  mapId[app->getName()] = mapId[app->getName()] + 1;
89  OSTRINGSTREAM newlable;
90  newlable<<app->getLabel()<<"("<<mapId[app->getName()]<<")";
91  OSTRINGSTREAM msg;
92  msg<<app->getName()<<" from "<<app->getXmlFile()<<" already exists.";
93  logger->addWarning(msg);
94  app->setName(newlable.str().c_str());
95  app->setLabel(newlable.str().c_str());
96  }
97 
98  if(modifyName){
99  if (*szAppName_)
100  {
101  delete [] *szAppName_;
102  *szAppName_ = nullptr;
103  }
104  size_t len = app->getNameLenght();
105  *szAppName_ = new char[len + 1];
106  strncpy(*szAppName_, app->getName(), len);
107  (*szAppName_)[len] = '\0';
108  }
109  if(!kbGraph.addNode(app))
110  {
111  OSTRINGSTREAM msg;
112  msg<<"Application "<<app->getName()<<" cannot be added to the graph.";
113  logger->addError(msg);
114  return false;
115  }
116  return true;
117 }
118 
119 
120 bool KnowledgeBase::addModule(Module* mod)
121 {
122  __CHECK_NULLPTR(mod);
123 
124  ErrorLogger* logger = ErrorLogger::Instance();
125  mod->setLabel(mod->getName());
126  if(kbGraph.hasNode(mod))
127  {
128  OSTRINGSTREAM msg;
129  msg<<"Module "<<mod->getName()<<" already exists.";
130  logger->addWarning(msg);
131  return false;
132  }
133  if(!addModuleToGraph(kbGraph, mod))
134  {
135  OSTRINGSTREAM msg;
136  msg<<"Module "<<mod->getName()<<" cannot be added to the graph.";
137  logger->addError(msg);
138  return false;
139  }
140  return true;
141 }
142 
143 
144 bool KnowledgeBase::addResource(GenericResource* res)
145 {
146  __CHECK_NULLPTR(res);
147 
148  // a disabled resource should not be used.
149  //if(res->getDisable())
150  // return true;
151 
152  ErrorLogger* logger = ErrorLogger::Instance();
153  res->setLabel(res->getName());
154  if(kbGraph.hasNode(res))
155  {
156  OSTRINGSTREAM msg;
157  msg<<"Resource "<<res->getName()<<" already exists.";
158  logger->addWarning(msg);
159  return false;
160  }
161  if(!kbGraph.addNode(res))
162  {
163  OSTRINGSTREAM msg;
164  msg<<"Resource "<<res->getName()<<" cannot be added to the graph.";
165  logger->addError(msg);
166  return false;
167  }
168  return true;
169 }
170 
171 
172 bool KnowledgeBase::removeApplication(Application* app)
173 {
174  return kbGraph.removeNode(app);
175 }
176 
177 bool KnowledgeBase::removeModule(Module* mod)
178 {
179  return removeModuleFromGraph(kbGraph, mod);
180 }
181 
182 bool KnowledgeBase::removeResource(GenericResource* res)
183 {
184  return kbGraph.removeNode(res);
185 }
186 
187 
188 const ApplicaitonPContainer& KnowledgeBase::getApplications(Application* parent)
189 {
190  dummyApplications.clear();
191  if(parent)
192  {
193  for(GraphIterator itr=tmpGraph.begin(); itr!=tmpGraph.end(); itr++)
194  {
195  auto* app = dynamic_cast<Application*>(*itr);
196  if(app && (app->owner() == parent))
197  dummyApplications.push_back(app);
198  }
199  }
200  else
201  {
202  for(GraphIterator itr=kbGraph.begin(); itr!=kbGraph.end(); itr++)
203  {
204  auto* app = dynamic_cast<Application*>(*itr);
205  if(app)
206  dummyApplications.push_back(app);
207  }
208  }
209 
210  sort(dummyApplications.begin(), dummyApplications.end(), sortApplication());
211  return dummyApplications;
212 }
213 
214 
215 const ModulePContainer& KnowledgeBase::getModules(Application* parent)
216 {
217  dummyModules.clear();
218  if(parent)
219  {
220  for(GraphIterator itr=tmpGraph.begin(); itr!=tmpGraph.end(); itr++)
221  {
222  auto* mod = dynamic_cast<Module*>(*itr);
223  if(mod && (mod->owner() == parent))
224  dummyModules.push_back(mod);
225  }
226  }
227  else
228  {
229  for(GraphIterator itr=kbGraph.begin(); itr!=kbGraph.end(); itr++)
230  {
231  auto* mod = dynamic_cast<Module*>(*itr);
232  if(mod)
233  dummyModules.push_back(mod);
234  }
235  }
236  sort(dummyModules.begin(), dummyModules.end(), sortModules());
237  return dummyModules;
238 }
239 
240 //TODO: dummyConnections should be changed to return connections from all
241 // nested applications recursively
242 const CnnContainer& KnowledgeBase::getConnections(Application* parent)
243 {
244  dummyConnections.clear();
245  if(parent)
246  {
247  for(int i=0; i<parent->connectionCount(); i++)
248  dummyConnections.push_back(parent->getConnectionAt(i));
249  }
250  else
251  dummyConnections = selconnections;
252  //sort(dummyConnections.begin(), dummyConnections.end(), sortConnections());
253  return dummyConnections;
254 }
255 
256 const ResourcePContainer& KnowledgeBase::getResources(Application* parent)
257 {
258  dummyResources.clear();
259  for(GraphIterator itr=kbGraph.begin(); itr!=kbGraph.end(); itr++)
260  {
261  auto* res = dynamic_cast<Computer*>(*itr);
262  if(res)
263  {
264  bool bHas = false;
265  for(auto& dummyResource : dummyResources)
266  if(string(dummyResource->getName()) == string(res->getName()))
267  {
268  bHas = true;
269  break;
270  }
271  if(!bHas)
272  dummyResources.push_back(res);
273  }
274  }
275 
276  for(GraphIterator itr=tmpGraph.begin(); itr!=tmpGraph.end(); itr++)
277  {
278  auto* res = dynamic_cast<Computer*>(*itr);
279  if(res)
280  {
281  bool bHas = false;
282  for(auto& dummyResource : dummyResources)
283  if(string(dummyResource->getName()) == string(res->getName()))
284  {
285  bHas = true;
286  break;
287  }
288  if(!bHas)
289  dummyResources.push_back(res);
290  }
291  }
292  sort(dummyResources.begin(), dummyResources.end(), sortResources());
293  return dummyResources;
294 }
295 
296 const ArbContainer& KnowledgeBase::getArbitrators(Application* parent)
297 {
298  dummyArbitrators.clear();
299  if(parent)
300  {
301  for(int i=0; i<parent->arbitratorCount(); i++)
302  dummyArbitrators.push_back(parent->getArbitratorAt(i));
303  }
304  return dummyArbitrators;
305 }
306 
307 
308 const InputContainer& KnowledgeBase::getInputCandidates(OutputData* output)
309 {
310  static InputContainer inputs;
311  inputs.clear();
312  for(GraphIterator itr=kbGraph.begin(); itr!=kbGraph.end(); itr++)
313  if((*itr)->getType() == INPUTD &&
314  (*itr)->hasSuc(output))
315  inputs.push_back(*((InputData*)(*itr)));
316  return inputs;
317 }
318 
319 
320 const OutputContainer& KnowledgeBase::getOutputCandidates(InputData* input)
321 {
322  static OutputContainer outputs;
323  outputs.clear();
324  for(int i=0; i<input->sucCount(); i++)
325  outputs.push_back(*((OutputData*)input->getLinkAt(i).to()));
326  return outputs;
327 }
328 
329 
333 bool KnowledgeBase::makeupApplication(Application* application)
334 {
335  ErrorLogger* logger = ErrorLogger::Instance();
336  if(!application)
337  return false;
341  for(int i=0; i<application->iapplicationCount(); i++)
342  {
343  ApplicationInterface interfaceApp = application->getIapplicationAt(i);
344  if(string(interfaceApp.getName()) == string(application->getName()))
345  {
346  OSTRINGSTREAM msg;
347  msg<<"Application "<<interfaceApp.getName()<<" cannot be called from itself.";
348  logger->addWarning(msg);
349  }
350  else
351  {
352  auto* repapp = dynamic_cast<Application*>(kbGraph.getNode(interfaceApp.getName()));
353  if(!repapp)
354  {
355  OSTRINGSTREAM msg;
356  msg<<"Application "<<interfaceApp.getName()<<" not found.";
357  logger->addWarning(msg);
358  }
359  else
360  {
361 
362  if(appList.find(string(interfaceApp.getName()))==appList.end())
363  appList[interfaceApp.getName()] = 1;
364  OSTRINGSTREAM newname;
365  newname<<application->getName()<<":";
366  newname<<interfaceApp.getName()<<":"<<appList[interfaceApp.getName()];
367 
368  repapp = replicateApplication(tmpGraph, repapp, newname.str().c_str());
369 
370  // setting application base prefix
371  repapp->setBasePrefix(interfaceApp.getPrefix());
372 
373  // adding applicattion prefix to child application
374  if( strlen(application->getPrefix()) )
375  {
376  string strPrefix = string(application->getPrefix()) +
377  string(interfaceApp.getPrefix());
378  interfaceApp.setPrefix(strPrefix.c_str());
379  }
380 
381  // updating Application with ApplicationInterface
382  updateApplication(repapp, &interfaceApp);
383  appList[interfaceApp.getName()] = appList[interfaceApp.getName()] + 1;
384 
385  //Adding child application as an successor to the application
386  tmpGraph.addLink(application, repapp, 0, false);
387  repapp->setOwner(application);
388  // recursive call to make up child application
389  makeupApplication(repapp);
390  }
391  }
392  }
393 
394 
398  //map<string, int> modList;
399  for(int i=0; i<application->imoduleCount(); i++)
400  {
401  ModuleInterface &mod = application->getImoduleAt(i);
402  addIModuleToApplication(application, mod);
403  } // end of for loop
404 
405 
406  /*
407  * updating extera connections with application prefix
408  * and connections owner
409  */
410  for(int i=0; i<application->connectionCount(); i++)
411  {
412  Connection* cnn = &application->getConnectionAt(i);
413  cnn->setOwner(application);
414  if(!cnn->isExternalFrom())
415  {
416  string strPort = string(application->getPrefix()) + string(cnn->from());
417  cnn->setFrom(strPort.c_str());
418  }
419 
420  if(!cnn->isExternalTo())
421  {
422  string strPort = string(application->getPrefix()) + string(cnn->to());
423  cnn->setTo(strPort.c_str());
424  }
425  }
426 
435  if(application->resourcesCount())
436  {
437  MultiResource mres;
438  OSTRINGSTREAM strLabel;
439  strLabel<<application->getLabel()<<":MultipleResource";
440  mres.setLabel(strLabel.str().c_str());
441  mres.setName("MultipleResource");
442  mres.setOwner(application);
443  for(int i=0; i<application->resourcesCount(); i++)
444  mres.addResource(application->getResourceAt(i));
445  Node* node = tmpGraph.addNode(&mres);
446  tmpGraph.addLink(application, node, 0);
447  }
448 
449  return true;
450 }
451 
452 bool KnowledgeBase::setModulePrefix(Module* module, const char* szPrefix, bool updateBasePrefix)
453 {
455  __CHECK_NULLPTR(szPrefix);
456 
457  module->setPrefix(szPrefix);
458  if(updateBasePrefix)
459  module->setBasePrefix(szPrefix);
460 
461  // updating port's prefix
462  // TODO: check if this is required anymore
463  /*
464  for(int i=0; i<module->sucCount(); i++)
465  {
466  InputData* input = dynamic_cast<InputData*>(module->getLinkAt(i).to());
467  if(input)
468  {
469  string strPort = string(szPrefix) + string(input->getPort());
470  input->setPort(strPort.c_str());
471  }
472  }
473 
474  for(GraphIterator itr=tmpGraph.begin(); itr!=tmpGraph.end(); itr++)
475  {
476  if((*itr)->getType() == OUTPUTD)
477  {
478  OutputData* output = (OutputData*)(*itr);
479  Module* producer = dynamic_cast<Module*>(output->getLinkAt(0).to());
480  if(producer == module)
481  {
482  string strPort = string(szPrefix) + string(output->getPort());
483  output->setPort(strPort.c_str());
484  }
485  }
486  }
487  */
488  return true;
489 }
490 
491 bool KnowledgeBase::setApplicationPrefix(Application* application, const char* szPrefix, bool updateBasePrefix)
492 {
493  __CHECK_NULLPTR(application);
494  __CHECK_NULLPTR(szPrefix);
495 
496  application->setPrefix(szPrefix);
497  if(updateBasePrefix)
498  application->setBasePrefix(szPrefix);
499 
503  for(int i=0; i<application->sucCount(); i++)
504  {
505  auto* nestedApp = dynamic_cast<Application*>(application->getLinkAt(i).to());
506  if(nestedApp)
507  {
508  string strPrefix = string(szPrefix) + string(nestedApp->getBasePrefix());
509  setApplicationPrefix(nestedApp, strPrefix.c_str(), false);
510  }
511  else
512  {
513  auto* module = dynamic_cast<Module*>(application->getLinkAt(i).to());
514  if(module)
515  {
516  string strPrefix = string(szPrefix) + string(module->getBasePrefix());
517  setModulePrefix(module, strPrefix.c_str(), false);
518  }
519  }
520  }
521 
525  /*
526  for(int i=0; i<application->connectionCount(); i++)
527  {
528  Connection* cnn = &application->getConnectionAt(i);
529  if(!cnn->isExternalFrom())
530  {
531  string strPort = string(szPrefix) + string(cnn->from());
532  cnn->setFrom(strPort.c_str());
533  }
534 
535  if(!cnn->isExternalTo())
536  {
537  string strPort = string(szPrefix) + string(cnn->to());
538  cnn->setTo(strPort.c_str());
539  }
540  }
541  */
542  return true;
543 }
544 
545 Connection& KnowledgeBase::addConnectionToApplication(Application* application,
546  Connection &cnn)
547 {
548  cnn.setOwner(application);
549  for(int i=0; i<application->connectionCount(); i++)
550  {
551  Connection* con = &application->getConnectionAt(i);
552  if(*con == cnn)
553  {
554  *con = cnn;
555  return *con;
556  }
557  }
558 
559  selconnections.push_back(cnn);
560  return application->addConnection(cnn);
561 }
562 
563 Arbitrator& KnowledgeBase::addArbitratorToApplication(Application* application,
564  Arbitrator &arb)
565 {
566  arb.setOwner(application);
567  for(int i=0; i<application->arbitratorCount(); i++)
568  {
569  Arbitrator* parb = &application->getArbitratorAt(i);
570  if(*parb == arb)
571  {
572  *parb = arb;
573  return *parb;
574  }
575  }
576  return application->addArbitrator(arb);
577 }
578 
579 
580 
581 bool KnowledgeBase::updateConnectionOfApplication(Application* application,
582  Connection& prev, Connection& con )
583 {
584  __CHECK_NULLPTR(application);
585 
586  for(int i=0; i<application->connectionCount(); i++)
587  {
588  Connection* pcon = &application->getConnectionAt(i);
589  if(*pcon == prev)
590  {
591  *pcon = con;
592  break;
593  }
594  }
595 
596  CnnIterator citr;
597  for(citr=selconnections.begin(); citr<selconnections.end(); citr++)
598  {
599  if((*citr) == prev)
600  {
601  (*citr) = con;
602  break;
603  }
604  }
605 
606  return true;
607 }
608 
609 bool KnowledgeBase::removeArbitratorFromApplication(Application* application, Arbitrator &arb)
610 {
611  //printf("[%d] %s\n",__LINE__, __PRETTY_FUNCTION__ );
612  __CHECK_NULLPTR(application);
613  return application->removeArbitrator(arb);
614 }
615 
616 
617 bool KnowledgeBase::removeConnectionFromApplication(Application* application, Connection &cnn)
618 {
619  __CHECK_NULLPTR(application);
620 
621  CnnIterator citr;
622  for(citr=selconnections.begin(); citr<selconnections.end(); citr++)
623  {
624  if((*citr) == cnn)
625  {
626  selconnections.erase(citr);
627  break;
628  }
629  }
630  return application->removeConnection(cnn);
631 }
632 
633 const std::string KnowledgeBase::getUniqueAppID(Application* parent, const char* szAppName)
634 {
635  if(appList.find(string(szAppName)) == appList.end())
636  appList[szAppName] = 1;
637  OSTRINGSTREAM newname;
638  newname<<parent->getName()<<":";
639  newname<<szAppName<<":"<<appList[szAppName];
640  return newname.str();
641 }
642 
643 Application* KnowledgeBase::addIApplicationToApplication(Application* application,
644  ApplicationInterface &interfaceApp, bool isNew)
645 {
646  __CHECK_NULLPTR(application);
647 
648  Application* repapp = nullptr;
649 
650  ErrorLogger* logger = ErrorLogger::Instance();
651  if(string(interfaceApp.getName()) == string(application->getName()))
652  {
653  OSTRINGSTREAM msg;
654  msg<<"Application "<<interfaceApp.getName()<<" cannot be called from itself.";
655  logger->addWarning(msg);
656  }
657  else
658  {
659  repapp = dynamic_cast<Application*>(kbGraph.getNode(interfaceApp.getName()));
660  if(!repapp)
661  {
662  OSTRINGSTREAM msg;
663  msg<<"Application "<<interfaceApp.getName()<<" not found.";
664  logger->addWarning(msg);
665  }
666  else
667  {
668  if(appList.find(string(interfaceApp.getName()))==appList.end())
669  appList[interfaceApp.getName()] = 1;
670  OSTRINGSTREAM newname;
671  newname<<application->getName()<<":";
672  newname<<interfaceApp.getName()<<":"<<appList[interfaceApp.getName()];
673  repapp = replicateApplication(tmpGraph, repapp, newname.str().c_str());
674  // setting application base prefix
675  repapp->setBasePrefix(interfaceApp.getPrefix());
676 
677  // adding application prefix to child application
678  if( strlen(application->getPrefix()) )
679  {
680  string strPrefix = string(application->getPrefix()) +
681  string(interfaceApp.getPrefix());
682  interfaceApp.setPrefix(strPrefix.c_str());
683  }
684 
685  // updating Application with ApplicationInterface
686  updateApplication(repapp, &interfaceApp);
687  appList[interfaceApp.getName()] = appList[interfaceApp.getName()] + 1;
688 
689  //Adding child application as an successor to the application
690  tmpGraph.addLink(application, repapp, 0, false);
691  repapp->setOwner(application);
692  // recursive call to make up child application
693  makeupApplication(repapp);
694  }
695  }
696  return repapp;
697 }
698 
699 
700 Module* KnowledgeBase::addIModuleToApplication(Application* application,
701  ModuleInterface &mod, bool isNew)
702 {
703  __CHECK_NULLPTR(application);
704 
705  Module* module;
706 
707  if(application->modList.find(string(mod.getName()))==application->modList.end())
708  application->modList[mod.getName()] = 1;
709  OSTRINGSTREAM newname;
710  newname<<application->getLabel()<<":"<<mod.getName()<<":"<<application->modList[mod.getName()];
711 
712  auto* repmod = dynamic_cast<Module*>(kbGraph.getNode(mod.getName()));
713  if(repmod)
714  module = replicateModule(tmpGraph, repmod, newname.str().c_str());
715  else
716  {
717  Module newmod(mod.getName());
718  newmod.setLabel(newname.str().c_str());
719  module = addModuleToGraph(tmpGraph, &newmod);
720  }
721 
722  mod.setTag(newname.str().c_str());
723 
724  // setting module base prefix
725  module->setBasePrefix(mod.getPrefix());
726 
727  // adding application prefix to module prefix
728  if( strlen(application->getPrefix()) )
729  {
730  string strPrefix = string(application->getPrefix()) +
731  string(mod.getPrefix());
732  mod.setPrefix(strPrefix.c_str());
733  }
734 
735  //updating Module with ModuleInterface
736  updateModule(module, &mod);
737  application->modList[mod.getName()] = application->modList[mod.getName()] + 1;
738 
739  // adding module's resources to application resource list
740  ResourceIterator itr;
741  for(itr=mod.getResources().begin();
742  itr!=mod.getResources().end(); itr++)
743  {
744  (*itr).setOwner(module);
745  application->addResource(*itr);
746  }
747 
748  //Adding the module as an successor to the application
749  tmpGraph.addLink(application, module, 0, false);
750  module->setOwner(application);
751 
752  if(isNew)
753  application->addImodule(mod);
754  return module;
755 }
756 
757 
758 
759 bool KnowledgeBase::removeIModuleFromApplication(Application* application, const char* szModTag)
760 {
761  __CHECK_NULLPTR(application);
762 
763  auto* module = dynamic_cast<Module*>(tmpGraph.getNode(szModTag));
764  if(module)
765  removeModuleFromGraph(tmpGraph, module);
766  for(int i=0; i<application->imoduleCount(); i++)
767  {
768  if(strcmp(application->getImoduleAt(i).getTag(), szModTag) == 0)
769  {
770  application->removeImodule(application->getImoduleAt(i));
771  return true;
772  }
773  }
774  return false;
775 }
776 
777 //TODO: check if we should free application memory
778 //
779 bool KnowledgeBase::removeIApplicationFromApplication(Application* application, const char* szAppTag)
780 {
781  __CHECK_NULLPTR(application);
782  auto* app = dynamic_cast<Application*>(tmpGraph.getNode(szAppTag));
783  if(!app)
784  return false;
785 
786  // removing all nested applications recursively
787  for(GraphIterator itr=tmpGraph.begin(); itr!=tmpGraph.end(); itr++)
788  {
789  auto* nestedApp = dynamic_cast<Application*>(*itr);
790  if(nestedApp && (nestedApp->owner() == app))
791  removeIApplicationFromApplication(app, nestedApp->getLabel());
792  }
793 
794  for(GraphIterator itr=tmpGraph.begin(); itr!=tmpGraph.end(); itr++)
795  {
796  auto* mod = dynamic_cast<Module*>(*itr);
797  if(mod && (mod->owner() == app))
798  removeModuleFromGraph(tmpGraph, mod);
799  else
800  {
801  auto* res = dynamic_cast<MultiResource*>(*itr);
802  if(res && (res->owner() == app))
803  {
804  tmpGraph.removeLink(app, res);
805  tmpGraph.removeNode(res);
806  }
807  }
808  }
809 
810  for(int i=0; i<application->iapplicationCount(); i++)
811  {
812  if(strcmp(application->getIapplicationAt(i).getName(), szAppTag) == 0)
813  {
814  application->removeIapplication(application->getIapplicationAt(i));
815  break;
816  }
817  }
818 
819  tmpGraph.removeLink(application, app);
820  tmpGraph.removeNode(app);
821  return true;
822 }
823 
824 
825 
826 GenericResource* KnowledgeBase::findResByName(Graph& graph, const char* szName)
827 {
828  for(GraphIterator itr=graph.begin(); itr!=graph.end(); itr++)
829  {
830  auto* res = dynamic_cast<GenericResource*>(*itr);
831  if(res)
832  if(string(res->getName()) == string(szName))
833  return res;
834  }
835  return nullptr;
836 }
837 
838 
839 InputData* KnowledgeBase::findInputByPort(Graph& graph, const char* szPort)
840 {
841  for(GraphIterator itr=graph.begin(); itr!=graph.end(); itr++)
842  {
843  if((*itr)->getType() == INPUTD )
844  {
845  auto* input = (InputData*)(*itr);
846  if(compareString(input->getPort(), szPort))
847  return input;
848  }
849  }
850  return nullptr;
851 }
852 
853 
854 OutputData* KnowledgeBase::findOutputByPort(Graph& graph, const char* szPort)
855 {
856  for(GraphIterator itr=graph.begin(); itr!=graph.end(); itr++)
857  {
858  if((*itr)->getType() == OUTPUTD)
859  {
860  auto* output = (OutputData*)(*itr);
861  if(compareString(output->getPort(), szPort))
862  return output;
863  }
864  }
865  return nullptr;
866 }
867 
868 bool KnowledgeBase::reasolveDependency(const char* szAppName,
869  bool bAutoDependancy, bool bSilent)
870 {
871  ErrorLogger* logger = ErrorLogger::Instance();
872  auto* app = dynamic_cast<Application*>(kbGraph.getNode(szAppName));
873  if(!app)
874  {
875  OSTRINGSTREAM msg;
876  msg<<"Application "<<string(szAppName)<<" not found.";
877  logger->addError(msg.str().c_str());
878  mainApplication = nullptr;
879  return false;
880  }
881 
882  return reasolveDependency(app, bAutoDependancy, bSilent);
883 }
884 
885 bool KnowledgeBase::reasolveDependency(Application* app,
886  bool bAutoDependancy, bool bSilent)
887 {
888  ErrorLogger* logger = ErrorLogger::Instance();
889 
890  if(!kbGraph.hasNode(app))
891  {
892  OSTRINGSTREAM msg;
893  msg<<"Application "<<app->getName()<<" not found.";
894  logger->addError(msg.str().c_str());
895  mainApplication = nullptr;
896  return false;
897  }
898 
899  tmpGraph.clear();
900  // Adding application to tmpGraph
901  mainApplication = replicateApplication(tmpGraph,
902  app,
903  app->getLabel());
904 
905  //internally used by makeup application and addIApplicationToApplication
906  appList.clear();
907  // extend application to its child applications and modules
908  if(!makeupApplication(mainApplication))
909  {
910  mainApplication = nullptr;
911  return false;
912  }
913 
914  // Adding all resources which are providers to tmpGraph
915  // providers are those with no owner.
916  for(GraphIterator itr=kbGraph.begin(); itr!=kbGraph.end(); itr++)
917  if(dynamic_cast<GenericResource*>(*itr))
918  {
919 
920  if(!dynamic_cast<GenericResource*>(*itr)->owner())
921  replicateResource(tmpGraph,
922  (GenericResource*)(*itr),
923  (*itr)->getLabel());
924  }
925 
926  // make resources links
927  makeResourceLinks(tmpGraph);
928 
929  ResourcePContainer resources;
930  ModulePContainer modules;
931  ApplicaitonPContainer applications;
932  CnnContainer connections;
933  tmpGraph.setSatisfied(false);
934  bool ret = reason(&tmpGraph, mainApplication,
935  applications, modules, resources, connections,
936  bAutoDependancy, bSilent);
937 
938  // removing double nodes
939  selconnections.clear();
940  selmodules.clear();
941  selapplications.clear();
942  selresources.clear();
943 
944  for(auto& resource : resources)
945  {
946  auto* mres = dynamic_cast<MultiResource*>(resource);
947  if(mres)
948  {
949  for(int i=0; i<mres->resourceCount(); i++)
950  {
951  auto* yres = dynamic_cast<ResYarpPort*>(&mres->getResourceAt(i));
952  if(yres && (find(selresources.begin(), selresources.end(), yres)
953  == selresources.end()))
954  selresources.push_back(yres);
955 
956  // adding ResYarpPort from modules dependencies
957  /*
958  Computer* comp = dynamic_cast<Computer*>(&mres->getResourceAt(i));
959  if(comp)
960  {
961  for(int j=0; j<comp->peripheralCount(); j++)
962  {
963  ResYarpPort* yres = dynamic_cast<ResYarpPort*>(&comp->getPeripheralAt(j));
964  if(yres && (find(selresources.begin(), selresources.end(), yres)
965  == selresources.end()))
966  selresources.push_back(yres);
967  }
968 
969  }*/
970  }
971  }
972  else
973  {
974  if(find(selresources.begin(), selresources.end(), resource)
975  == selresources.end())
976  selresources.push_back(resource);
977  }
978  }
979 
980  for(auto& module : modules)
981  {
982  if(find(selmodules.begin(), selmodules.end(), module)
983  == selmodules.end())
984  selmodules.push_back(module);
985  }
986 
987  for(auto& application : applications)
988  {
989  if(find(selapplications.begin(), selapplications.end(), application)
990  == selapplications.end())
991  selapplications.push_back(application);
992  }
993 
994 
995  selconnections = connections;
996 
997  /*
998  cout<<"Modules: "<<endl;
999  for(ModulePIterator mod = selmodules.begin(); mod != selmodules.end(); mod++)
1000  cout<<(*mod)->getName()<<" on "<<(*mod)->getHost()<<endl;
1001 
1002  cout<<"Resources: "<<endl;
1003  for(ResourcePIterator res = selresources.begin(); res != selresources.end(); res++)
1004  cout<<(*res)->getName()<<endl;
1005 
1006  cout<<"Connections: "<<endl;
1007  for(CnnIterator con = selconnections.begin(); con != selconnections.end(); con++)
1008  cout<<(*con).from()<<", "<<(*con).to()<<endl;
1009  */
1010 
1011  /*
1012  if(bAutoDependancy)
1013  {
1014  updateNodesLink(tmpGraph, NODELINK_DEEP);
1015 
1016  if(!checkConsistency())
1017  {
1018  logger->addError("Knowledge base is not consistent.");
1019  return false;
1020  }
1021  }
1022  else
1023  updateNodesLink(tmpGraph, NODELINK_SUPERFICIAL);
1024 
1025 
1026  // updating extra node links
1027  updateExtraLink(tmpGraph, &selconnections);
1028 
1029  tmpGraph.setSatisfied(false);
1030  if(!bestDependancyPath(application, &selnodes, bAutoDependancy))
1031  {
1032  logger->addError("No solution found.");
1033  return false;
1034  }
1035 
1036  NodePVIterator itr;
1037  for(itr=selnodes.begin(); itr!=selnodes.end(); itr++)
1038  {
1039  if((*itr)->getType() == MODULE)
1040  {
1041  if(find(selmodules.begin(), selmodules.end(),
1042  (Module*)(*itr)) == selmodules.end())
1043  selmodules.push_back((Module*)(*itr));
1044  }
1045  }
1046 
1047  OutputData* from = NULL;
1048  InputData* to = NULL;
1049  for(itr=selnodes.begin(); itr!=selnodes.end(); itr++)
1050  {
1051  if((*itr)->getType() == INPUTD)
1052  to = (InputData*)(*itr);
1053  if((*itr)->getType() == OUTPUTD)
1054  from = (OutputData*)(*itr);
1055  if(from && to)
1056  {
1057  Connection cnn(from->getPort(), to->getPort(),
1058  from->getCarrier());
1059  if(find(selconnections.begin(), selconnections.end(),
1060  cnn) == selconnections.end())
1061  {
1062  cnn.setPriority(to->withPriority());
1063  cnn.setOwner(findOwner(tmpGraph, to));
1064  selconnections.push_back(cnn);
1065  }
1066  from = NULL;
1067  to = NULL;
1068  }
1069  }
1070 
1071  for(itr=selnodes.begin(); itr!=selnodes.end(); itr++)
1072  {
1073  if((*itr)->getType() == RESOURCE)
1074  {
1075  if(find(selresources.begin(), selresources.end(),
1076  (ResYarpPort*)(*itr)) == selresources.end())
1077  selresources.push_back((ResYarpPort*)(*itr));
1078  }
1079  }
1080  */
1081  return ret;
1082 }
1083 
1084 
1085 bool KnowledgeBase::updateApplication(Application* app,
1086  ApplicationInterface* iapp )
1087 {
1088  __CHECK_NULLPTR(app);
1089  __CHECK_NULLPTR(iapp);
1090 
1091  if(strlen(iapp->getPrefix()))
1092  app->setPrefix(iapp->getPrefix());
1093  app->setModelBase(iapp->getModelBase());
1094  return true;
1095 }
1096 
1097 bool KnowledgeBase::updateModule(Module* module, ModuleInterface* imod )
1098 {
1100  __CHECK_NULLPTR(imod);
1101 
1102  if(strlen(imod->getHost()))
1103  {
1104  module->setHost(imod->getHost());
1105  module->setForced(true);
1106  }
1107 
1108  if(strlen(imod->getParam()))
1109  module->setParam(imod->getParam());
1110  if(imod->getRank()>0)
1111  module->setRank(imod->getRank());
1112  if(strlen(imod->getBroker()))
1113  module->setBroker(imod->getBroker());
1114  if(strlen(imod->getStdio()))
1115  module->setStdio(imod->getStdio());
1116  if(strlen(imod->getWorkDir()))
1117  module->setWorkDir(imod->getWorkDir());
1118  if(strlen(imod->getDisplay()))
1119  module->setDisplay(imod->getDisplay());
1120  if(strlen(imod->getEnvironment()))
1121  module->setEnvironment(imod->getEnvironment());
1122  module->setPostExecWait(imod->getPostExecWait());
1123  module->setPostStopWait(imod->getPostStopWait());
1124  module->setModelBase(imod->getModelBase());
1125 
1126 
1127  // updating module prefix
1128  if(strlen(imod->getPrefix()))
1129  setModulePrefix(module, imod->getPrefix(), false);
1130  return true;
1131 }
1132 
1133 /*
1134  * Replicate a module from graph to tmpgraph
1135  */
1136 Module* KnowledgeBase::replicateModule(Graph& graph,
1137  Module* module, const char* szLabel)
1138 {
1140  auto* newmod = (Module*) module->clone();
1141  newmod->setLabel(szLabel);
1142  newmod->setBasePrefix(module->getPrefix());
1143  newmod->removeAllSuc();
1144  if(!addModuleToGraph(graph, newmod))
1145  {
1146  delete newmod;
1147  return nullptr;
1148  }
1149 
1150  delete newmod;
1151  return (Module*)graph.getNode(szLabel);
1152 }
1153 
1154 
1155 /*
1156  * Replicate an application from graph to tmpgraph
1157  */
1158 Application* KnowledgeBase::replicateApplication(Graph& graph,
1159  Application* app, const char* szLabel)
1160 {
1161  __CHECK_NULLPTR(app);
1162  auto* newapp = (Application*) app->clone();
1163  newapp->setLabel(szLabel);
1164  newapp->setBasePrefix(app->getPrefix());
1165  newapp->removeAllSuc();
1166  /*Adding new application to the graph */
1167  auto* application = (Application*)graph.addNode(newapp);
1168  delete newapp;
1169  return application;
1170 }
1171 
1172 
1173 /*
1174  * Replicate a resource from graph to tmpgraph
1175  */
1176 GenericResource* KnowledgeBase::replicateResource(Graph& graph,
1177  GenericResource* res, const char* szLabel)
1178 {
1179  __CHECK_NULLPTR(res);
1180  auto* newres = (GenericResource*) res->clone();
1181  newres->setLabel(szLabel);
1182  newres->removeAllSuc();
1183  /*Adding new resource to the graph */
1184  auto* resource = (GenericResource*)graph.addNode(newres);
1185  delete newres;
1186  return resource;
1187 }
1188 
1189 
1190 Module* KnowledgeBase::addModuleToGraph(Graph& graph, Module* module)
1191 {
1192  ErrorLogger* logger = ErrorLogger::Instance();
1193 
1194  if(!moduleCompleteness(module))
1195  return nullptr;
1196 
1197  /*Adding module to the graph */
1198  if(!(module = (Module*)graph.addNode(module)))
1199  return nullptr;
1200 
1201  /* Adding inputs nodes to the graph*/
1202  for(int i=0; i<module->inputCount(); i++)
1203  {
1204  InputData* input = &(module->getInputAt(i));
1205  input->setLabel(createDataLabel(module->getLabel(),
1206  input->getPort(), ":I"));
1207  input->setOwner(module);
1208  if((input=(InputData*)graph.addNode(input)))
1209  graph.addLink(module, input, 0,
1210  !(input->isRequired()));
1211  else
1212  {
1213  input = &(module->getInputAt(i));
1214  module->removeInput(*input);
1215  OSTRINGSTREAM msg;
1216  msg<<"Input ";
1217  msg<<createDataLabel(module->getLabel(),
1218  input->getPort(), ":I");
1219  msg<<" already exists.";
1220  logger->addWarning(msg);
1221  }
1222  }
1223 
1224  /* Adding output nodes to the graph*/
1225  for(int i=0; i<module->outputCount(); i++)
1226  {
1227  OutputData* output = &(module->getOutputAt(i));
1228  output->setLabel(createDataLabel(module->getLabel(),
1229  output->getPort(), ":O"));
1230  output->setOwner(module);
1231  if((output=(OutputData*)graph.addNode(output)))
1232  graph.addLink(output, module, 0);
1233  else
1234  {
1235  output = &(module->getOutputAt(i));
1236  module->removeOutput(*output);
1237  OSTRINGSTREAM msg;
1238  msg<<"Output ";
1239  msg<<createDataLabel(module->getLabel(),
1240  output->getPort(), ":O");
1241  msg<<" already exists.";
1242  logger->addWarning(msg);
1243  }
1244  }
1245 
1246  /* Adding resources to the graph
1247  * all multiple resources will be add as single MultiResource entity
1248  */
1249  MultiResource mres;
1250  OSTRINGSTREAM strLabel;
1251  strLabel<<module->getLabel()<<":MultipleResource";
1252  mres.setLabel(strLabel.str().c_str());
1253  mres.setName("MultipleResource");
1254  mres.setOwner(module);
1255  for(int i=0; i<module->resourceCount(); i++)
1256  mres.addResource(module->getResourceAt(i));
1257  Node* node = graph.addNode(&mres);
1258  graph.addLink(module, node, 0);
1259 
1260  return module;
1261 }
1262 
1263 bool KnowledgeBase::saveApplication(AppSaver* appSaver, Application* application)
1264 {
1265  // updating iApplication
1266  application->removeAllIapplications();
1267  for(GraphIterator itr=tmpGraph.begin(); itr!=tmpGraph.end(); itr++)
1268  {
1269  auto* embApp = dynamic_cast<Application*>(*itr);
1270  if(embApp && (embApp != application) && (embApp->owner() == application))
1271  {
1272  ApplicationInterface iapp(embApp->getName());
1273  iapp.setPrefix(embApp->getBasePrefix());
1274  if(embApp->getModel())
1275  iapp.setModelBase(*embApp->getModel());
1276  else
1277  iapp.setModelBase(embApp->getModelBase());
1278  application->addIapplication(iapp);
1279  }
1280  }
1281 
1282  //updating imodules
1283  application->removeAllImodules();
1284  for(GraphIterator itr=tmpGraph.begin(); itr!=tmpGraph.end(); itr++)
1285  {
1286  auto* module = dynamic_cast<Module*>(*itr);
1287  if(module && (module->owner() == application))
1288  {
1289  ModuleInterface imod(module);
1290  imod.setPrefix(module->getBasePrefix());
1291  application->addImodule(imod);
1292  }
1293  }
1294 
1295  // updating connections modelBase with Model if exists
1296  for(int i=0; i<application->connectionCount(); i++)
1297  {
1298  Connection* pcon = &application->getConnectionAt(i);
1299  if(pcon->getModel())
1300  pcon->setModelBase(*pcon->getModel());
1301  }
1302 
1303  // updating arbitrators modelBase with Model if exists
1304  for(int i=0; i<application->arbitratorCount(); i++)
1305  {
1306  Arbitrator* parb = &application->getArbitratorAt(i);
1307  if(parb->getModel())
1308  parb->setModelBase(*parb->getModel());
1309  }
1310 
1311  return appSaver->save(application);
1312 }
1313 
1314 bool KnowledgeBase::removeModuleFromGraph(Graph& graph, Module* mod)
1315 {
1316 
1317  // removing inputs and outputs and resource
1318  GraphIterator itr=graph.begin();
1319 
1320  while(itr!=graph.end())
1321  {
1322  auto* input = dynamic_cast<InputData*>(*itr);
1323  if(input && (input->owner() == mod))
1324  {
1325  graph.removeNode(input);
1326  itr=graph.begin();
1327  }
1328  else
1329  {
1330  auto* output = dynamic_cast<OutputData*>(*itr);
1331  if(output && (output->owner() == mod))
1332  {
1333  graph.removeNode(output);
1334  itr=graph.begin();
1335  }
1336  else
1337  {
1338  auto* res = dynamic_cast<MultiResource*>(*itr);
1339  if(res && (res->owner() == mod))
1340  {
1341  graph.removeNode(res);
1342  itr=graph.begin();
1343  }
1344  else
1345  itr++;
1346  }
1347  }
1348  //itr++;
1349  }
1350 
1351  // removing module
1352  return graph.removeNode(mod);
1353 }
1354 
1355 
1356 bool KnowledgeBase::moduleCompleteness(Module* module)
1357 {
1358  ErrorLogger* logger = ErrorLogger::Instance();
1359 
1360  /* Checking module name */
1361  if(strlen(module->getName()) == 0)
1362  {
1363  logger->addWarning("Module has no name.");
1364  return false;
1365  }
1366 
1367  /* Checking inputs name and port */
1368  for(int i=0; i<module->inputCount(); i++)
1369  {
1370  const char* szType = module->getInputAt(i).getName();
1371  const char* szPort = module->getInputAt(i).getPort();
1372  if(!strlen(szType))
1373  logger->addWarning(string(module->getName()) + string(" has an input with no type."));
1374  if(!strlen(szPort))
1375  logger->addWarning(string(module->getName()) + string(" has an input with no port."));
1376  }
1377 
1378  /* Checking outputs name and port */
1379  for(int i=0; i<module->outputCount(); i++)
1380  {
1381  const char* szType = module->getOutputAt(i).getName();
1382  const char* szPort = module->getOutputAt(i).getPort();
1383  if(!strlen(szType))
1384  logger->addWarning(string(module->getName()) + string(" has an output with no type."));
1385  if(!strlen(szPort))
1386  logger->addWarning(string(module->getName()) + string(" has an output with no port."));
1387  }
1388  return true;
1389 }
1390 
1391 
1392 Module* KnowledgeBase::findOwner(Graph& graph, InputData* input)
1393 {
1394  for(GraphIterator itr=graph.begin(); itr!=graph.end(); itr++)
1395  {
1396  if((*itr)->getType() == MODULE)
1397  {
1398  auto* module = (Module*)(*itr);
1399  for(int i=0; i<module->sucCount(); i++)
1400  {
1401  Link l = module->getLinkAt(i);
1402  if((InputData*)l.to() == input)
1403  return module;
1404  }
1405  }
1406  }
1407  return nullptr;
1408 }
1409 
1410 
1411 /*
1412 void KnowledgeBase::updateExtraLink(Graph& graph, CnnContainer* connections)
1413 {
1414  // update graph with external connection
1415  CnnIterator itrC;
1416  for(itrC=connections->begin(); itrC!=connections->end(); itrC++)
1417  {
1418  Connection cnn = (*itrC);
1419 
1420  GenericResource* res = findResByName(graph, cnn.from());
1421  OutputData* output = findOutputByPort(graph, cnn.from());
1422  InputData* input = findInputByPort(graph, cnn.to());
1423  if(res && input)
1424  {
1425  res->setOwner(findOwner(graph, input));
1426  (*itrC).setOwner(findOwner(graph, input));
1427  input->addSuc(res, 0.0);
1428  }
1429  else if(output && input)
1430  {
1431  (*itrC).setOwner(findOwner(graph, input));
1432  input->addSuc(output, 0.0);
1433  }
1434  }
1435 }
1436 */
1437 
1438 void KnowledgeBase::updateNodesLink(Graph& graph, int level)
1439 {
1443  for(GraphIterator itr=graph.begin(); itr!=graph.end(); itr++)
1444  {
1445  if((*itr)->getType() == INPUTD)
1446  {
1447  auto* input = (InputData*)(*itr);
1451  for(GraphIterator itr2=graph.begin(); itr2!=graph.end(); itr2++)
1452  {
1453  if((*itr2)->getType() == RESOURCE)
1454  {
1455  auto* res = (ResYarpPort*)(*itr2);
1456  if(compareString(res->getName(), input->getName()))
1457  graph.addLink(input, res, 0.0, false);
1458  }
1459  }
1460 
1464  if(level==NODELINK_DEEP)
1465  linkToOutputs(graph, input);
1466  }
1467  }
1468 }
1469 
1470 void KnowledgeBase::updateResourceWeight(Graph& graph,
1471  GenericResource* resource, float weight)
1472 {
1473  for(GraphIterator itr=graph.begin(); itr!=graph.end(); itr++)
1474  {
1475  for(int i=0; i<(*itr)->sucCount(); i++)
1476  if((*itr)->getLinkAt(i).to() == resource)
1477  (*itr)->getLinkAt(i).setWeight(weight);
1478  }
1479 
1480 }
1481 
1482 void KnowledgeBase::makeResourceLinks(Graph& graph)
1483 {
1487  for(GraphIterator itr=graph.begin(); itr!=graph.end(); itr++)
1488  {
1489  auto* resource = dynamic_cast<GenericResource*>(*itr);
1490  if(resource && resource->owner())
1491  {
1492  resource->removeAllSuc();
1493  auto* module = dynamic_cast<Module*>(resource->owner());
1494  if(module && module->getForced())
1495  {
1496  // we should create a provider resource with host name and
1497  // connect it to resource
1498  GenericResource* provider = findResByName(graph, module->getHost());
1499  if(!provider)
1500  {
1501  Computer comp;
1502  comp.setLabel(module->getHost());
1503  comp.setName(module->getHost());
1504  provider = (GenericResource*) graph.addNode(&comp);
1505  }
1506  float w = 0.0;
1507  if(dynamic_cast<Computer*>(provider))
1508  w = calculateLoad((Computer*)provider);
1509  graph.addLink(resource, provider, w, false);
1510  }
1511  else if((module && !module->getForced()))
1512  {
1513  // linking resource providers to the relevant resources
1514  for(GraphIterator itr2=graph.begin(); itr2!=graph.end(); itr2++)
1515  {
1516  auto* provider = dynamic_cast<GenericResource*>(*itr2);
1517  if(provider && !provider->owner())
1518  if(provider->satisfy(resource))
1519  {
1520  float w = 0.0;
1521  if(dynamic_cast<Computer*>(provider))
1522  w = calculateLoad((Computer*)provider);
1523  graph.addLink(resource, provider, w, false);
1524  }
1525  }
1526  }
1527  }
1528  }
1529 }
1530 
1531 
1532 float KnowledgeBase::calculateLoad(Computer* comp)
1533 {
1534  LoadAvg load = comp->getProcessor().getCPULoad();
1535  int siblings = comp->getProcessor().getSiblings();
1536  if(siblings == 0) siblings = 1;
1537  //cout<<comp->getName()<<": "<<load.loadAverage1<<", "<<load.loadAverage5<<", "<<load.loadAverage15;
1538  //cout<<" ("<<siblings<<")"<<endl;
1539  auto lavg = (float)((load.loadAverage1*15.0 +
1540  load.loadAverage5*10.0 +
1541  load.loadAverage15*1.0) / 26.0);
1542  return (lavg/(float)siblings);
1543 }
1544 
1545 
1546 void KnowledgeBase::linkToOutputs(Graph& graph, InputData* input)
1547 {
1548  for(GraphIterator itr=graph.begin(); itr!=graph.end(); itr++)
1549  {
1550  if((*itr)->getType() == OUTPUTD)
1551  {
1552  auto* output = (OutputData*)(*itr);
1553  auto* producer = (Module*)output->getLinkAt(0).to();
1554  if(compareString(output->getName(), input->getName())
1555  &&(producer != findOwner(graph, input)))
1556  graph.addLink(input, output,
1557  (float)getProducerRank(graph, output),
1558  !input->isRequired());
1559  }
1560  }
1561 }
1562 
1567 int KnowledgeBase::getProducerRank(Graph& graph, OutputData* output)
1568 {
1569  if(output->sucCount())
1570  {
1571  auto* module = (Module*)output->getLinkAt(0).to();
1572  return module->getRank();
1573  }
1574  return 0;
1575 }
1576 
1577 
1578 bool KnowledgeBase::checkConsistency()
1579 {
1580  //ErrorLogger* logger = ErrorLogger::Instance();
1581 
1585  /*
1586  if(!application)
1587  {
1588  logger->addError("No application found.");
1589  return false;
1590  }
1591  */
1592 
1597  /*
1598  if(application->isLeaf())
1599  {
1600  logger->addWarning("Empty application.");
1601  //return false;
1602  }
1603  */
1604  return true;
1605 }
1606 
1607 Node* KnowledgeBase::getNode(string appName)
1608 {
1609  return kbGraph.getNode(appName.c_str());
1610 }
1611 
1612 bool KnowledgeBase::constrainSatisfied(Node* node,
1613  bool bAutoDependancy,
1614  bool bSilent)
1615 {
1616  ErrorLogger* logger = ErrorLogger::Instance();
1617 
1618  // if it's a dependency resource with no provider
1619  auto* resource = dynamic_cast<GenericResource*>(node);
1620  if(resource && resource->isLeaf() &&
1621  dynamic_cast<Module*>(resource->owner()))
1622  {
1623  if(!bSilent)
1624  {
1625  OSTRINGSTREAM msg;
1626  msg<<"Some resource dependencies of ";
1627  msg<<dynamic_cast<Module*>(resource->owner())->getName();
1628  msg<<" are not satisfied.";
1629  logger->addWarning(msg);
1630  }
1631  return false;
1632  }
1633 
1634  return true;
1635 }
1636 
1637 /*
1638 bool KnowledgeBase::constrainSatisfied(Node* node, bool bAutoDependancy)
1639 {
1640  ErrorLogger* logger = ErrorLogger::Instance();
1641 
1642  switch(node->getType()) {
1643  case INPUTD: {
1644  if( ((InputData*)node)->isRequired() && node->isLeaf() )
1645  {
1646  OSTRINGSTREAM msg;
1647  msg<<"Unsatisfied constrain. ";
1648  msg<<node->getLabel()<<" has no output candidate!";
1649  logger->addWarning(msg);
1650  if(bAutoDependancy)
1651  return false;
1652  }
1653  break;
1654  }
1655  default:
1656  break;
1657  };
1658  return true;
1659 }
1660 */
1661 
1662 
1663 bool KnowledgeBase::reason(Graph* graph, Node* initial,
1664  ApplicaitonPContainer &applications,
1665  ModulePContainer &modules,
1666  ResourcePContainer &resources,
1667  CnnContainer &connections,
1668  bool bAutoDependancy, bool bSilent)
1669 {
1670  if(!constrainSatisfied(initial, bAutoDependancy, bSilent))
1671  {
1672  /* if it's a resource dependency */
1673  auto* resource = dynamic_cast<GenericResource*>(initial);
1674  if(resource && resource->owner())
1675  resources.push_back(resource);
1676  return false;
1677  }
1678 
1679  if(initial->isLeaf())
1680  {
1681  // adding resource
1682  if(dynamic_cast<GenericResource*>(initial))
1683  resources.push_back(dynamic_cast<GenericResource*>(initial));
1684 
1685  // adding connections
1686  auto* application = dynamic_cast<Application*>(initial);
1687  if(application)
1688  {
1689  applications.push_back(application);
1690  for(int i=0; i<application->connectionCount(); i++)
1691  connections.push_back(application->getConnectionAt(i));
1692  }
1693  initial->setSatisfied(true);
1694  initial->setVisited(false);
1695  return true;
1696  }
1697 
1698  /* now we are visiting this node */
1699  initial->setVisited(true);
1700  bool bPathFound = false;
1701 
1702  Link* candidateLink = nullptr;
1703  float weight = -1.0;
1704 
1705  for(int i=0; i<initial->sucCount(); i++)
1706  {
1707  Link l = initial->getLinkAt(i);
1708  Node* current = l.to();
1709 
1710  /* we are not interested in virtual links
1711  * and we are not meeting a visited node to avoid looping
1712  */
1713  if(!l.isVirtual() && !current->isVisited())
1714  {
1715  ModulePContainer subModules;
1716  ApplicaitonPContainer subApplications;
1717  ResourcePContainer subResources;
1718  CnnContainer subConnections;
1719  bool ret = reason(graph, current,
1720  subApplications, subModules, subResources, subConnections,
1721  bAutoDependancy, bSilent);
1722  if(ret)
1723  bPathFound = true;
1724  else if(dynamic_cast<Application*>(initial) ||
1725  dynamic_cast<Module*>(initial))
1726  bPathFound = false;
1727 
1728  /* we meet a conjunctive node and we need to copy all the
1729  * selected successors
1730  */
1731  if (dynamic_cast<Application*>(initial) ||
1732  dynamic_cast<Module*>(initial))
1733  {
1734  applications.insert(applications.end(), subApplications.begin(), subApplications.end());
1735  modules.insert(modules.end(), subModules.begin(), subModules.end());
1736  resources.insert(resources.end(), subResources.begin(), subResources.end());
1737  connections.insert(connections.end(), subConnections.begin(), subConnections.end());
1738  }
1739 
1740  /* A disjunctive node; we should choose the best path */
1741  else if((weight<0.0) || (l.weight() < weight))
1742  {
1743  weight = l.weight();
1744  candidateLink = &initial->getLinkAt(i);
1745  modules = subModules;
1746  applications = subApplications;
1747  resources = subResources;
1748  connections = subConnections;
1749  }
1750 
1751  }
1752  } // end for
1753 
1754  /* if it's a resource dependency with a solution */
1755  auto* resource = dynamic_cast<GenericResource*>(initial);
1756  if(resource && resource->owner() && candidateLink)
1757  {
1758  auto* module = dynamic_cast<Module*>(resource->owner());
1759  auto* provider = dynamic_cast<GenericResource*>(candidateLink->to());
1760  if(module && provider)
1761  {
1762  // setting module's host property
1763  module->setHost(provider->getName());
1764 
1765  // we need to update the weight of all links to the selected provider
1766  // with load balancer tunning value;
1767  // It will help for better load distribution among nodes
1768  auto* comp = dynamic_cast<Computer*>(provider);
1769  float default_tunning = 0.1F;
1770  if(comp && (comp->getProcessor().getSiblings() > 0))
1771  default_tunning = 1.0F / (float)comp->getProcessor().getSiblings();
1772  float tunner = (module->getRank()<10)? default_tunning : (float)module->getRank()/100.0F;
1773  updateResourceWeight(*graph, provider, candidateLink->weight()+tunner);
1774  }
1775  resources.push_back(resource);
1776  }
1777 
1778  /* adding current module to the modules list.*/
1779  if(dynamic_cast<Module*>(initial))
1780  modules.push_back(dynamic_cast<Module*>(initial));
1781 
1782  /* we should add all the connections */
1783  auto* application = dynamic_cast<Application*>(initial);
1784  if(application)
1785  {
1786  applications.push_back(dynamic_cast<Application*>(initial));
1787  for(int i=0; i<application->connectionCount(); i++)
1788  connections.push_back(application->getConnectionAt(i));
1789  }
1790  initial->setSatisfied(bPathFound);
1791  initial->setVisited(false);
1792  return bPathFound;
1793 }
1794 
1795 
1796 const char* KnowledgeBase::createDataLabel(const char* modlabel,
1797  const char* port,
1798  const char* postfix)
1799 {
1800  static string name;
1801  name.clear();
1802  name = string(modlabel) + string(port);
1803  if(postfix)
1804  name += string(postfix);
1805  return name.c_str();
1806 }
yarp::manager::OUTPUTD
@ OUTPUTD
Definition: ymm-types.h:24
yarp::manager::Application
Class Application.
Definition: application.h:292
yarp::manager::ApplicaitonPContainer
std::vector< Application * > ApplicaitonPContainer
Definition: application.h:409
yarp::manager::Connection::from
const char * from()
Definition: application.h:79
yarp::manager::Connection::isExternalTo
bool isExternalTo()
Definition: application.h:97
yarp::manager::ModuleInterface::getModelBase
GraphicModel & getModelBase()
Definition: application.h:221
yarp::manager::OutputData::owner
Node * owner()
Definition: data.h:96
yarp::manager::Graph::end
GraphIterator end()
Definition: graph.cpp:164
yarp::manager::Arbitrator::setOwner
void setOwner(Node *owner)
Definition: arbitrator.h:58
yarp::manager::Application::addConnection
Connection & addConnection(Connection &cnn)
Definition: application.cpp:133
yarp::manager::Processor::getCPULoad
const LoadAvg & getCPULoad()
Definition: primresource.h:130
yarp::manager::Connection::setFrom
void setFrom(const char *szFrom)
Definition: application.h:84
yarp::manager::Processor::getSiblings
size_t getSiblings()
Definition: primresource.h:128
yarp::manager::Application::getName
const char * getName()
Definition: application.h:306
yarp::manager::AppSaver
Definition: manifestloader.h:41
yarp::manager::ModuleInterface::setTag
void setTag(const char *szTag)
Definition: application.h:185
yarp::manager::Application::resourcesCount
int resourcesCount()
Definition: application.h:329
yarp::manager::GraphIterator
Class GraphIterator.
Definition: graph.h:70
yarp::manager::MultiResource::resourceCount
int resourceCount() const
Definition: resource.h:81
yarp::manager::Graph::getNode
Node * getNode(const char *szLabel)
Definition: graph.cpp:78
yarp::manager::sortModules
Definition: kbase.h:211
yarp::manager::ModuleInterface::setPrefix
void setPrefix(const char *szPrefix)
Definition: application.h:183
yarp::manager::Connection
Class Connection.
Definition: application.h:60
yarp::manager::ApplicationInterface::setModelBase
void setModelBase(GraphicModel &mdl)
Definition: application.h:274
yarp::manager::Arbitrator
Class port Arbitrator.
Definition: arbitrator.h:28
yarp::manager::CnnContainer
std::vector< Connection > CnnContainer
Definition: application.h:153
yarp::manager::Application::removeArbitrator
bool removeArbitrator(Arbitrator &arb)
Definition: application.cpp:158
yarp::manager::Application::setName
void setName(const char *szName)
Definition: application.h:299
yarp::manager::MultiResource::getResourceAt
GenericResource & getResourceAt(int index) const
Definition: resource.h:82
yarp::manager::Application::getImoduleAt
ModuleInterface & getImoduleAt(int index)
Definition: application.h:318
yarp::manager::Application::getResourceAt
ResYarpPort & getResourceAt(int index)
Definition: application.h:330
yarp::manager::InputData::getPort
const char * getPort()
Definition: data.h:40
yarp::manager::Node::getLabel
const char * getLabel()
Definition: node.h:97
yarp::manager::OSTRINGSTREAM
std::stringstream OSTRINGSTREAM
Definition: utility.h:52
yarp::manager::Computer
Definition: primresource.h:155
yarp::manager::Application::getPrefix
const char * getPrefix()
Definition: application.h:335
yarp::manager::Node::setLabel
void setLabel(const char *szLabel)
Definition: node.h:96
yarp::manager
Definition: application.h:24
yarp::manager::Node::clone
virtual Node * clone()=0
yarp::manager::ArbContainer
std::vector< Arbitrator > ArbContainer
Definition: arbitrator.h:94
yarp::manager::ErrorLogger
Singleton class ErrorLogger.
Definition: utility.h:60
yarp::manager::Node::setVisited
void setVisited(bool vis)
Definition: node.h:89
yarp::manager::Arbitrator::getModel
GraphicModel * getModel()
Definition: arbitrator.h:49
yarp::manager::Application::removeAllImodules
void removeAllImodules()
Definition: application.h:321
yarp::manager::Application::getConnectionAt
Connection & getConnectionAt(int index)
Definition: application.h:344
yarp::manager::ResourcePContainer
std::vector< GenericResource * > ResourcePContainer
Definition: resource.h:62
yarp::manager::Connection::setModelBase
void setModelBase(GraphicModel &mdl)
Definition: application.h:122
utility.h
ret
bool ret
Definition: ImplementAxisInfo.cpp:72
yarp::manager::Node::sucCount
int sucCount()
Definition: node.h:98
yarp::manager::Graph
Class Graph.
Definition: graph.h:31
yarp::manager::CnnIterator
std::vector< Connection >::iterator CnnIterator
Definition: application.h:154
yarp::manager::ModuleInterface
Class ModuleInterface.
Definition: application.h:164
yarp::manager::Application::setOwner
void setOwner(Node *owner)
Definition: application.h:354
yarp::manager::compareString
bool compareString(const char *szFirst, const char *szSecond)
Definition: utility.cpp:305
yarp::manager::Node::removeAllSuc
void removeAllSuc()
Definition: node.cpp:42
yarp::manager::InputData::owner
Node * owner()
Definition: data.h:52
yarp::manager::ApplicationInterface::getModelBase
GraphicModel & getModelBase()
Definition: application.h:273
yarp::manager::Application::getArbitratorAt
Arbitrator & getArbitratorAt(int index)
Definition: application.h:350
yarp::manager::ResourceLoader
Abstract Class ResourceLoader.
Definition: manifestloader.h:77
yarp::manager::OutputData::getPort
const char * getPort()
Definition: data.h:87
yarp::manager::ModuleInterface::getDisplay
const char * getDisplay()
Definition: application.h:198
yarp::manager::Application::arbitratorCount
int arbitratorCount()
Definition: application.h:349
yarp::manager::GenericResource::satisfy
virtual bool satisfy(GenericResource *resource)=0
yarp::manager::Application::getIapplicationAt
ApplicationInterface & getIapplicationAt(int index)
Definition: application.h:324
yarp::manager::Module
Class Module.
Definition: module.h:103
NODELINK_DEEP
#define NODELINK_DEEP
Definition: kbase.h:27
yarp::manager::RESOURCE
@ RESOURCE
Definition: ymm-types.h:29
yarp::manager::Connection::to
const char * to()
Definition: application.h:80
yarp::manager::ModuleInterface::getHost
const char * getHost()
Definition: application.h:189
yarp::manager::Computer::getProcessor
Processor & getProcessor()
Definition: primresource.h:173
yarp::manager::Application::imoduleCount
int imoduleCount()
Definition: application.h:317
yarp::manager::Node::isLeaf
bool isLeaf()
Definition: node.h:91
yarp::manager::OutputData
Definition: data.h:72
yarp::manager::ModuleInterface::getWorkDir
const char * getWorkDir()
Definition: application.h:192
yarp::manager::InputContainer
std::vector< InputData > InputContainer
Definition: module.h:89
yarp::manager::_LoadAvg::loadAverage15
double loadAverage15
Definition: primresource.h:104
yarp::manager::ApplicationInterface::setPrefix
void setPrefix(const char *szPrefix)
Definition: application.h:263
yarp::manager::MODULE
@ MODULE
Definition: ymm-types.h:22
yarp::manager::Application::iapplicationCount
int iapplicationCount()
Definition: application.h:323
yarp::manager::OutputContainer
std::vector< OutputData > OutputContainer
Definition: module.h:90
yarp::manager::ApplicationInterface
Class ApplicationInterface.
Definition: application.h:256
yarp::manager::AppSaver::save
virtual bool save(Application *application)=0
yarp::manager::Application::modList
std::map< std::string, int > modList
Definition: application.h:378
yarp::manager::ApplicationInterface::getName
const char * getName()
Definition: application.h:264
yarp::manager::Connection::setTo
void setTo(const char *szTo)
Definition: application.h:85
yarp::manager::ModuleInterface::getRank
int getRank()
Definition: application.h:191
yarp::manager::Node
a Node of a Graph
Definition: node.h:68
resource.h
yarp::manager::ErrorLogger::addError
void addError(const char *szError)
Definition: utility.cpp:121
yarp::manager::GenericResource::owner
Node * owner()
Definition: resource.h:38
yarp::manager::Application::addArbitrator
Arbitrator & addArbitrator(Arbitrator &arb)
Definition: application.cpp:151
yarp::manager::ModuleInterface::getPrefix
const char * getPrefix()
Definition: application.h:195
yarp::manager::Graph::removeNode
bool removeNode(Node *node)
Definition: graph.cpp:33
yarp::manager::ModuleInterface::getStdio
const char * getStdio()
Definition: application.h:193
yarp::manager::Application::removeImodule
bool removeImodule(ModuleInterface &imod)
Definition: application.cpp:123
yarp::manager::ResYarpPort
Definition: logicresource.h:47
module
static RFModule * module
Definition: RFModule.cpp:234
yarp::manager::InputData::isRequired
bool isRequired()
Definition: data.h:45
yarp::manager::_LoadAvg
Definition: primresource.h:100
yarp::manager::OutputData::setOwner
void setOwner(Node *owner)
Definition: data.h:95
yarp::manager::GenericResource::setOwner
void setOwner(Node *owner)
Definition: resource.h:37
yarp::manager::Application::setBasePrefix
void setBasePrefix(const char *szPrefix)
Definition: application.h:336
yarp::manager::Application::addImodule
bool addImodule(ModuleInterface &imod)
Definition: application.cpp:116
yarp::manager::ApplicationInterface::getPrefix
const char * getPrefix()
Definition: application.h:265
yarp::manager::ErrorLogger::addWarning
void addWarning(const char *szWarning)
Definition: utility.cpp:108
yarp::manager::Connection::isExternalFrom
bool isExternalFrom()
Definition: application.h:96
yarp::manager::MultiResource
Class MultiResource.
Definition: resource.h:71
__CHECK_NULLPTR
#define __CHECK_NULLPTR(_ptr)
Definition: ymm-types.h:83
yarp::manager::Application::setPrefix
void setPrefix(const char *szPrefix)
Definition: application.h:334
yarp::manager::InputData::setOwner
void setOwner(Node *owner)
Definition: data.h:51
yarp::manager::ModuleInterface::getParam
const char * getParam()
Definition: application.h:190
yarp::manager::ModuleLoader
Abstract Class ModuleLoader.
Definition: manifestloader.h:57
yarp::manager::Application::removeConnection
bool removeConnection(Connection &cnn)
Definition: application.cpp:141
yarp::manager::Node::getLinkAt
Link & getLinkAt(int index)
Definition: node.h:99
yarp::manager::Application::connectionCount
int connectionCount()
Definition: application.h:343
yarp::manager::GenericResource
Definition: resource.h:21
yarp::manager::Application::removeIapplication
bool removeIapplication(ApplicationInterface &iapp)
Definition: application.cpp:197
yarp::manager::Application::removeAllIapplications
void removeAllIapplications()
Definition: application.h:327
kbase.h
yarp::manager::Connection::getModel
GraphicModel * getModel()
Definition: application.h:115
yarp::manager::_LoadAvg::loadAverage5
double loadAverage5
Definition: primresource.h:103
yarp::manager::Application::setModelBase
void setModelBase(GraphicModel &mdl)
Definition: application.h:378
yarp::manager::InputData::getName
const char * getName()
Definition: data.h:38
yarp::manager::Arbitrator::setModelBase
void setModelBase(GraphicModel &mdl)
Definition: arbitrator.h:56
yarp::manager::Application::clone
Node * clone() override
Definition: application.cpp:109
yarp::manager::ModuleInterface::getBroker
const char * getBroker()
Definition: application.h:194
yarp::manager::ModuleInterface::getPostExecWait
double getPostExecWait()
Definition: application.h:208
yarp::manager::Application::addResource
bool addResource(ResYarpPort &res)
Definition: application.cpp:206
yarp::manager::Graph::begin
GraphIterator begin()
Definition: graph.cpp:157
yarp::manager::Application::addIapplication
bool addIapplication(ApplicationInterface &iapp)
Definition: application.cpp:190
yarp::manager::ModulePContainer
std::vector< Module * > ModulePContainer
Definition: module.h:234
yarp::manager::_LoadAvg::loadAverage1
double loadAverage1
Definition: primresource.h:102
yarp::manager::ModuleInterface::getTag
const char * getTag()
Definition: application.h:197
yarp::manager::ModuleInterface::getResources
ResourceContainer & getResources()
Definition: application.h:205
yarp::manager::INPUTD
@ INPUTD
Definition: ymm-types.h:23
yarp::manager::ModuleInterface::getName
const char * getName()
Definition: application.h:188
yarp::manager::Node::setSatisfied
void setSatisfied(bool sat)
Definition: node.h:87
yarp::manager::MultiResource::addResource
bool addResource(GenericResource &res)
Definition: resource.cpp:60
yarp::manager::ModuleInterface::getPostStopWait
double getPostStopWait()
Definition: application.h:210
yarp::manager::Connection::setOwner
void setOwner(Node *owner)
Definition: application.h:104
yarp::manager::Application::getXmlFile
const char * getXmlFile()
Definition: application.h:341
yarp::manager::GenericResource::setName
void setName(const char *szName)
Definition: resource.h:31
yarp::manager::Graph::addNode
Node * addNode(Node *node)
Definition: graph.cpp:20
yarp::manager::Module::getName
const char * getName()
Definition: module.h:132
yarp::manager::GenericResource::getName
const char * getName()
Definition: resource.h:32
yarp::manager::Node::isVisited
bool isVisited()
Definition: node.h:90
yarp::manager::ResourceIterator
std::vector< ResYarpPort >::iterator ResourceIterator
Definition: application.h:157
yarp::manager::ModuleInterface::getEnvironment
const char * getEnvironment()
Definition: application.h:196
yarp::manager::InputData
Class InputData.
Definition: data.h:25
yarp::manager::Application::getNameLenght
size_t getNameLenght()
Definition: application.h:307
yarp::manager::AppLoader
Abstract Class AppLoader.
Definition: manifestloader.h:24
yarp::manager::OutputData::getName
const char * getName()
Definition: data.h:85
yarp::manager::Graph::addLink
bool addLink(Node *first, Node *second, float weight, bool _virtual=false)
Definition: graph.cpp:86
yarp::manager::sortApplication
Definition: kbase.h:195
yarp::manager::sortResources
Definition: kbase.h:227