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