YARP
Yet Another Robot Platform
 
Loading...
Searching...
No Matches
ymanager.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT)
3 * SPDX-License-Identifier: LGPL-2.1-or-later
4 */
5
6#include "ymanager.h"
7
10#include <dirent.h>
13
14/*
15 * TODO: using stringstream should be avoided to keep
16 * the compatibility with GUI
17 */
18#include <sstream>
19
20#include <cstring>
21#include <csignal>
22
23using namespace yarp::os;
24using namespace yarp::manager;
25
26#if defined(_WIN32)
27# define HEADER ""
28# define OKBLUE ""
29# define OKGREEN ""
30# define WARNING ""
31# define FAIL ""
32# define INFO ""
33# define ENDC ""
34#else
35# include <unistd.h>
36# include <cerrno>
37# if defined(YARP_HAS_SYS_TYPES_H)
38# include <sys/types.h>
39# endif
40# if defined(YARP_HAS_SYS_WAIT_H)
41# include <sys/wait.h>
42# endif
43# if defined(YARP_HAS_SYS_PRCTL_H)
44# include <sys/prctl.h>
45# endif
46 std::string HEADER;
47 std::string OKBLUE;
48 std::string OKGREEN;
49 std::string WARNING;
50 std::string FAIL;
51 std::string INFO;
52 std::string ENDC;
53#endif
54
55
56#define CMD_COUNTS 24
57#ifdef YARP_HAS_Libedit
58 #include <editline/readline.h>
59 const char* commands[CMD_COUNTS] = {"help", "exit","list mod", "list app", "list res", "add mod",
60 "add app", "add res", "load app", "run", "stop", "kill",
61 "connect", "disconnect", "which", "check state",
62 "check con", "check dep", "set", "get", "export",
63 "show mod", "assign hosts", " "};
64 char* command_generator (const char* text, int state);
65 char* appname_generator (const char* text, int state);
66 char ** my_completion (const char* text, int start, int end);
67 std::vector<std::string> appnames;
68#endif
69
70#define DEF_CONFIG_FILE "ymanager.ini"
71
72#define LOGO_MESSAGE "\
73__ __\n\
74\\ \\ / / __ ___ __ _ _ __ __ _ __ _ ___ _ __ \n\
75 \\ V / '_ ` _ \\ / _` | '_ \\ / _` |/ _` |/ _ \\ '__|\n\
76 | || | | | | | (_| | | | | (_| | (_| | __/ |\n\
77 |_||_| |_| |_|\\__,_|_| |_|\\__,_|\\__, |\\___|_|\n\
78 |___/"
79
80#define WELCOME_MESSAGE "type \"help\" for more information."
81#define VERSION_MESSAGE "Version 1.1"
82
83#define HELP_MESSAGE "\
84Usage:\n\
85 yarpmanager-console [option...]\n\n\
86Options:\n\
87 --application <app> Load a specific application identified by its xml file\n\
88 --run Run the current application (should be used with --application)\n\
89 --stop Stop the current application (should be used with --application)\n\
90 --kill Kill the current application (should be used with --application)\n\
91 --connect Connect all connections from the current application (should be used with --application)\n\
92 --disconnect Disconnect all connections from the current application (should be used with --application)\n\
93 --assign_hosts Automatically assign modules to proper nodes using load balancer. (should be used with --application)\n\
94 --check_dep Check for all resource dependencies of the current application (should be used with --application)\n\
95 --check_state Check for running state of modules of the current application (should be used with --application) \n\
96 --check_con Check the connections states of the of the current application (should be used with --application)\n\
97 --silent Do not print the status messages (should be used with --application)\n\
98 --exit Immediately exit after executing the commands (should be used with --application)\n\
99 --from <conf> Configuration file name\n\
100 --elapsed_time if present the time stamp for log messages will be relative to the GUI start time\n\
101 --version Show current version\n\
102 --help Show help\n"
103
104
105#if defined(_WIN32)
106static Manager* __pManager = NULL;
107#endif
108
109 bool isAbsolute(const char *path) { //copied from yarp_OS ResourceFinder.cpp
110 if (path[0]=='/'||path[0]=='\\') {
111 return true;
112 }
113 std::string str(path);
114 if (str.length()>1) {
115 if (str[1]==':') {
116 return true;
117 }
118 }
119 return false;
120 }
121
126YConsoleManager::YConsoleManager(int argc, char* argv[]) : Manager()
127{
128
129#if defined(_WIN32)
130 __pManager = (Manager*) this;
131#endif
132
133 bShouldRun = false;
134
135 // Setup resource finder
137 rf.setDefaultContext("yarpmanager");
139 rf.configure(argc, argv);
140
141 yarp::os::Property config;
142 config.fromString(rf.toString());
143
144 if(config.check("help"))
145 {
146 std::cout<<HELP_MESSAGE<<'\n';
147 return;
148 }
149
150 if(config.check("version"))
151 {
152 std::cout<<VERSION_MESSAGE<<'\n';
153 return;
154 }
155
156 // I the option elapsed_time is not set, set the start time to 00:00:00 (For error and warning logging)
157 if(!config.check("elapsed_time"))
158 {
160 clock.setStartTime("00:00:00");
161 }
162
167 std::string inifile=rf.findFile("from");
168 std::string inipath;
169 size_t lastSlash=inifile.rfind('/');
170 if (lastSlash != std::string::npos) {
171 inipath=inifile.substr(0, lastSlash+1);
172 } else {
173 lastSlash=inifile.rfind('\\');
174 if (lastSlash != std::string::npos) {
175 inipath = inifile.substr(0, lastSlash + 1);
176 }
177 }
178
179// if(!config.check("ymanagerini_dir"))
180// config.put("ymanagerini_dir", inipath.c_str());
181
182 if (!config.check("apppath")) {
183 config.put("apppath", "./");
184 }
185
186 if (!config.check("modpath")) {
187 config.put("modpath", "./");
188 }
189
190 if (!config.check("respath")) {
191 config.put("respath", "./");
192 }
193
194 if (!config.check("load_subfolders")) {
195 config.put("load_subfolders", "no");
196 }
197
198 if (!config.check("watchdog")) {
199 config.put("watchdog", "no");
200 }
201
202 if (!config.check("module_failure")) {
203 config.put("module_failure", "prompt");
204 }
205
206 if (!config.check("connection_failure")) {
207 config.put("connection_failure", "prompt");
208 }
209
210 if (!config.check("auto_connect")) {
211 config.put("auto_connect", "no");
212 }
213
214 if (!config.check("auto_dependency")) {
215 config.put("auto_dependency", "no");
216 }
217
218 if (!config.check("color_theme")) {
219 config.put("color_theme", "light");
220 }
221
222
226 if (config.find("color_theme").asString() == "dark") {
227 setColorTheme(THEME_DARK);
228 } else if (config.find("color_theme").asString() == "light") {
229 setColorTheme(THEME_LIGHT);
230 } else {
231 setColorTheme(THEME_NONE);
232 }
233
234 if (config.find("watchdog").asString() == "yes") {
236 } else {
238 }
239
240 if (config.find("auto_dependency").asString() == "yes") {
242 } else {
244 }
245
246 if (config.find("auto_connect").asString() == "yes") {
248 } else {
250 }
251
252 if(!config.check("silent"))
253 {
254 std::cout<<'\n'<<OKGREEN<<LOGO_MESSAGE<<ENDC<<'\n';
255 std::cout<<'\n'<<WELCOME_MESSAGE<<'\n'<<'\n';
256 }
257
258 if(config.check("modpath"))
259 {
260 std::string strPath;
261 std::stringstream modPaths(config.find("modpath").asString());
262 while (getline(modPaths, strPath, ';'))
263 {
264 trimString(strPath);
265 if (!isAbsolute(strPath.c_str())) {
266 strPath = std::string(inipath).append(strPath);
267 }
268 addModules(strPath.c_str());
269 }
270 }
271
272 if(config.check("respath"))
273 {
274 std::string strPath;
275 std::stringstream resPaths(config.find("respath").asString());
276 while (getline(resPaths, strPath, ';'))
277 {
278 trimString(strPath);
279 if (!isAbsolute(strPath.c_str())) {
280 strPath = std::string(inipath).append(strPath);
281 }
282 addResources(strPath.c_str());
283 }
284 }
285
287 if(config.check("apppath"))
288 {
289 std::string strPath;
290 std::stringstream appPaths(config.find("apppath").asString());
291 while (getline(appPaths, strPath, ';'))
292 {
293 trimString(strPath);
294 if (!isAbsolute(strPath.c_str())) {
295 strPath = std::string(inipath).append(strPath);
296 }
297 if(config.find("load_subfolders").asString() == "yes")
298 {
299 if (!loadRecursiveApplications(strPath.c_str())) {
300 logger->addError("Cannot load the applications from " + strPath);
301 }
302 } else {
303 addApplications(strPath.c_str());
304 }
305 }
306 }
307
308 reportErrors();
309
310#ifdef YARP_HAS_Libedit
311 updateAppNames(&appnames);
312#endif
313
314
315#if defined(_WIN32)
316 ::signal(SIGINT, YConsoleManager::onSignal);
317 ::signal(SIGBREAK, YConsoleManager::onSignal);
318 ::signal(SIGTERM, YConsoleManager::onSignal);
319#else
320 struct sigaction new_action, old_action;
321
322 /* Set up the structure to specify the new action. */
323 new_action.sa_handler = YConsoleManager::onSignal;
324 sigemptyset (&new_action.sa_mask);
325 new_action.sa_flags = 0;
326
327 sigaction (SIGINT, nullptr, &old_action);
328 if (old_action.sa_handler != SIG_IGN) {
329 sigaction(SIGINT, &new_action, nullptr);
330 }
331 sigaction (SIGHUP, nullptr, &old_action);
332 if (old_action.sa_handler != SIG_IGN) {
333 sigaction(SIGHUP, &new_action, nullptr);
334 }
335 sigaction (SIGTERM, nullptr, &old_action);
336 if (old_action.sa_handler != SIG_IGN) {
337 sigaction(SIGTERM, &new_action, nullptr);
338 }
339#endif
340
341 if(config.check("application"))
342 {
343 XmlAppLoader appload(config.find("application").asString().c_str());
344 if(appload.init())
345 {
346 Application* application = appload.getNextApplication();
347 if(application)
348 {
349 // add this application to the manager if does not exist
350 if (!getKnowledgeBase()->getApplication(application->getName())) {
351 getKnowledgeBase()->addApplication(application);
352 }
353
354#ifdef YARP_HAS_Libedit
355 updateAppNames(&appnames);
356 #endif
357
358 if(loadApplication(application->getName()))
359 {
360 if (!config.check("silent")) {
361 which();
362 }
363
364 if (config.check("assign_hosts")) {
365 loadBalance();
366 }
367
368 if(config.check("run"))
369 {
370 if (config.check("connect")) {
372 }
373 bShouldRun = run();
374 } else if (config.check("connect")) {
375 connect();
376 }
377
378 if (config.check("disconnect")) {
379 disconnect();
380 }
381
382 if(config.check("stop"))
383 {
386 unsigned int id = 0;
387 bShouldRun = false;
388 for(moditr=modules.begin(); moditr<modules.end(); moditr++)
389 {
390 if (running(id)) {
391 stop(id);
392 }
393 id++;
394 }
395 bShouldRun = !suspended();
396 }
397
398 if(config.check("kill"))
399 {
400 bShouldRun = false;
401 kill();
402 }
403
404 if (config.check("check_con")) {
405 checkConnections();
406 }
407
408 if (config.check("check_state")) {
409 checkStates();
410 }
411
412 if (config.check("check_dep")) {
413 if (checkDependency()) {
414 std::cout << INFO << "All of resource dependencies are satisfied." << ENDC << '\n';
415 }
416 }
417 }
418 }
419 }
420 if (!config.check("silent")) {
421 reportErrors();
422 }
423 }
424
425 if (!config.check("exit")) {
426 YConsoleManager::myMain();
427 }
428}
429
431
432
433
434void YConsoleManager::onSignal(int signum)
435{
436#if defined(_WIN32)
437 std::cout<<INFO<<"[force exit] yarpmanager will terminate all of the running modules on exit.";
438 if( __pManager)
439 __pManager->kill();
440#else
441 std::cout<<'\n'<<INFO<<"use"<<OKGREEN<<" 'exit' "<<INFO<<"to quit!"<<ENDC<<'\n';
442#endif
443}
444
445
446void YConsoleManager::myMain()
447{
448
449
450#ifdef YARP_HAS_Libedit
452#endif
453
454 while(!std::cin.eof())
455 {
456 std::string temp;
457
458#ifdef YARP_HAS_Libedit
459 static char* szLine = (char*)nullptr;
460 if(szLine)
461 {
462 free(szLine);
463 szLine = (char*)nullptr;
464 }
465
466 szLine = readline(">>");
467 if(szLine && *szLine)
468 {
469 temp = szLine;
471 } else {
472 temp = "";
473 }
474#else
475 std::cout << ">> ";
476 getline(std::cin, temp);
477#endif
478
479 //Break string into separate strings on whitespace
480 std::vector<std::string> cmdList;
481 std::stringstream foo(temp);
482 std::string s;
483 while (foo >> s)
484 {
485 if (s[0] == '~') {
486 s = getenv("HOME") + s.substr(1);
487 }
488 cmdList.push_back(s);
489 }
490 if(!process(cmdList))
491 {
492 if(cmdList[0] == "exit")
493 {
494 if (YConsoleManager::exit()) {
495 break;
496 }
497 }
498 else
499 {
500 std::cout<<"'"<<cmdList[0]<<"'"<<INFO<<" is not correct. ";
501 std::cout<<"type \"help\" for more information."<<ENDC<<'\n';
502 }
503 }
504 }
505
506#if defined(_WIN32)
507 if(bShouldRun)
508 {
509 kill();
510 reportErrors();
511 }
512#endif
513 std::cout<<"bye."<<'\n';
514
515}
516
517bool YConsoleManager::exit()
518{
519 if (!bShouldRun) {
520 return true;
521 }
522
523 std::string ans;
524 std::cout<<WARNING<<"WARNING: ";
525 std::cout<<INFO<<"You have some running modules. You might not be able to recover them later. Are you sure? [No/yes] "<<ENDC;
526 getline(std::cin, ans);
527 if(compareString(ans.c_str(),"yes"))
528 {
529 bShouldRun = false;
530 //kill();
531 //reportErrors();
532 return true;
533 }
534 return false;
535}
536
537
538bool YConsoleManager::process(const std::vector<std::string> &cmdList)
539{
540 if (!cmdList.size() || cmdList[0] == "") {
541 return true;
542 }
543
547 if((cmdList.size() == 1) &&
548 (cmdList[0] == "help"))
549 {
550 help();
551 return true;
552 }
553
554
558 if((cmdList.size() == 3) &&
559 (cmdList[0] == "add") && (cmdList[1] == "app"))
560 {
561 if (addApplication(cmdList[2].c_str())) {
562 std::cout << INFO << cmdList[2] << " is successfully added." << ENDC << '\n';
563 }
564 reportErrors();
565 #ifdef YARP_HAS_Libedit
566 updateAppNames(&appnames);
567 #endif
568 return true;
569 }
570
574 if((cmdList.size() == 3) &&
575 (cmdList[0] == "add") && (cmdList[1] == "mod"))
576 {
577 if (addModule(cmdList[2].c_str())) {
578 std::cout << INFO << cmdList[2] << " is successfully added." << ENDC << '\n';
579 }
580 reportErrors();
581 return true;
582 }
583
587 if((cmdList.size() == 3) &&
588 (cmdList[0] == "add") && (cmdList[1] == "res"))
589 {
590 if (addResource(cmdList[2].c_str())) {
591 std::cout << INFO << cmdList[2] << " is successfully added." << ENDC << '\n';
592 }
593 reportErrors();
594 return true;
595 }
596
597
601 if((cmdList.size() == 3) &&
602 (cmdList[0] == "load") && (cmdList[1] == "app"))
603 {
604 if(loadApplication(cmdList[2].c_str()))
605 {
606 //std::cout<<cmdList[2]<<" is successfully loaded."<<'\n';
607 which();
608 }
609 reportErrors();
610 return true;
611 }
612
616 /*
617 if((cmdList.size() >= 3) &&
618 (cmdList[0] == "load") && (cmdList[1] == "mod"))
619 {
620 if(cmdList.size() > 3)
621 {
622 if(manager.loadModule(cmdList[2].c_str(), cmdList[3].c_str()))
623 std::cout<<cmdList[2]<<" is successfully loaded."<<'\n';
624 }
625 else
626 if(manager.loadModule(cmdList[2].c_str()))
627 std::cout<<cmdList[2]<<" is successfully loaded."<<'\n';
628 reportErrors();
629 return true;
630 }
631 */
632
636 if((cmdList.size() == 1) &&
637 (cmdList[0] == "run"))
638 {
639 bShouldRun = run();
640 reportErrors();
641 return true;
642 }
643 if((cmdList.size() >= 2) &&
644 (cmdList[0] == "run"))
645 {
646 bShouldRun = false;
647 for (unsigned int i = 1; i < cmdList.size(); i++) {
648 bShouldRun |= run(atoi(cmdList[i].c_str()));
649 }
650 reportErrors();
651 return true;
652 }
653
657 if((cmdList.size() == 1) &&
658 (cmdList[0] == "stop"))
659 {
660 bShouldRun = false;
661 stop();
662 reportErrors();
663 return true;
664 }
665 if((cmdList.size() >= 2) &&
666 (cmdList[0] == "stop"))
667 {
668 //bShouldRun = false;
669 for (unsigned int i = 1; i < cmdList.size(); i++) {
670 stop(atoi(cmdList[i].c_str()));
671 }
672 bShouldRun = !suspended();
673 reportErrors();
674 return true;
675 }
676
680 if((cmdList.size() == 1) &&
681 (cmdList[0] == "kill"))
682 {
683 bShouldRun = false;
684 kill();
685 reportErrors();
686 return true;
687 }
688 if((cmdList.size() >= 2) &&
689 (cmdList[0] == "kill"))
690 {
691 //bShouldRun = false;
692 for (unsigned int i = 1; i < cmdList.size(); i++) {
693 kill(atoi(cmdList[i].c_str()));
694 }
695 bShouldRun = !suspended();
696 reportErrors();
697 return true;
698 }
699
703 if((cmdList.size() == 1) &&
704 (cmdList[0] == "connect"))
705 {
706 connect();
707 reportErrors();
708 return true;
709 }
710 if((cmdList.size() >= 2) &&
711 (cmdList[0] == "connect"))
712 {
713 for (unsigned int i = 1; i < cmdList.size(); i++) {
714 connect(atoi(cmdList[i].c_str()));
715 }
716 reportErrors();
717 return true;
718 }
719
720
724 if((cmdList.size() == 1) &&
725 (cmdList[0] == "disconnect"))
726 {
727 disconnect();
728 reportErrors();
729 return true;
730 }
731 if((cmdList.size() >= 2) &&
732 (cmdList[0] == "disconnect"))
733 {
734 for (unsigned int i = 1; i < cmdList.size(); i++) {
735 disconnect(atoi(cmdList[i].c_str()));
736 }
737 reportErrors();
738 return true;
739 }
740
741
745 if((cmdList.size() == 1) &&
746 (cmdList[0] == "which"))
747 {
748 which();
749 return true;
750 }
751
755 if((cmdList.size() == 2) &&
756 (cmdList[0] == "check") && (cmdList[1] == "dep"))
757 {
758 if (checkDependency()) {
759 std::cout << INFO << "All of resource dependencies are satisfied." << ENDC << '\n';
760 }
761 reportErrors();
762 return true;
763 }
764
765
769 if((cmdList.size() == 3) &&
770 (cmdList[0] == "check") && (cmdList[1] == "state"))
771 {
773 auto id = (unsigned int)atoi(cmdList[2].c_str());
774 if(id>=modules.size())
775 {
776 std::cout<<FAIL<<"ERROR: "<<INFO<<"Module id is out of range."<<ENDC<<'\n';
777 return true;
778 }
779
780 if (running(id)) {
781 std::cout<<OKGREEN<<"<RUNNING> ";
782 } else {
783 std::cout << FAIL << "<STOPPED> ";
784 }
785 std::cout<<INFO<<"("<<id<<") ";
786 std::cout<<modules[id]->getCommand();
787 std::cout<<" ["<<modules[id]->getHost()<<"]"<<ENDC<<'\n';
788 reportErrors();
789 return true;
790 }
791 if((cmdList.size() == 2) &&
792 (cmdList[0] == "check") && (cmdList[1] == "state"))
793 {
794 checkStates();
795 reportErrors();
796 return true;
797 }
798
799
803 if((cmdList.size() == 3) &&
804 (cmdList[0] == "check") && (cmdList[1] == "con"))
805 {
806
807 CnnContainer connections = getConnections();
808 auto id = (unsigned int)atoi(cmdList[2].c_str());
809 if(id>=connections.size())
810 {
811 std::cout<<FAIL<<"ERROR: "<<INFO<<"Connection id is out of range."<<ENDC<<'\n';
812 return true;
813 }
814
815 if (connected(id)) {
816 std::cout<<OKGREEN<<"<CONNECTED> ";
817 } else {
818 std::cout << FAIL << "<DISCONNECTED> ";
819 }
820
821 std::cout<<INFO<<"("<<id<<") ";
822 std::cout<<connections[id].from()<<" - "<<connections[id].to();
823 std::cout<<" ["<<connections[id].carrier()<<"]"<<ENDC<<'\n';
824 reportErrors();
825 return true;
826 }
827 if((cmdList.size() == 2) &&
828 (cmdList[0] == "check") && (cmdList[1] == "con"))
829 {
830 checkConnections();
831 return true;
832 }
833
835
839 if((cmdList.size() == 2) &&
840 (cmdList[0] == "list") && (cmdList[1] == "mod"))
841 {
843 ModulePContainer mods = kb->getModules();
844 int id = 0;
845 for(auto& mod : mods)
846 {
847 std::string fname;
848 std::string fpath = mod->getXmlFile();
849
850 size_t pos = fpath.rfind(directorySeparator);
851 if (pos != std::string::npos) {
852 fname = fpath.substr(pos);
853 } else {
854 fname = fpath;
855 }
856 std::cout<<INFO<<"("<<id++<<") ";
857 std::cout<<OKBLUE<<mod->getName()<<ENDC;
858 std::cout<<INFO<<" ["<<fname<<"]"<<ENDC<<'\n';
859 }
860 return true;
861 }
862
863
867 if((cmdList.size() == 2) &&
868 (cmdList[0] == "list") && (cmdList[1] == "app"))
869 {
871 ApplicaitonPContainer apps = kb->getApplications();
872 int id = 0;
873 for(auto& app : apps)
874 {
875 std::string fname;
876 std::string fpath = app->getXmlFile();
877
878 size_t pos = fpath.rfind(directorySeparator);
879 if (pos != std::string::npos) {
880 fname = fpath.substr(pos);
881 } else {
882 fname = fpath;
883 }
884 std::cout<<INFO<<"("<<id++<<") ";
885 std::cout<<OKBLUE<<app->getName()<<ENDC;
886 std::cout<<INFO<<" ["<<fname<<"]"<<ENDC<<'\n';
887 }
888 return true;
889 }
890
894 if((cmdList.size() == 2) &&
895 (cmdList[0] == "list") && (cmdList[1] == "res"))
896 {
898 ResourcePContainer resources = kb->getResources();
899 int id = 0;
900 for(auto& resource : resources)
901 {
902 auto* comp = dynamic_cast<Computer*>(resource);
903 if(comp)
904 {
905 std::string fname;
906 std::string fpath = comp->getXmlFile();
907 size_t pos = fpath.rfind(directorySeparator);
908 if (pos != std::string::npos) {
909 fname = fpath.substr(pos);
910 } else {
911 fname = fpath;
912 }
913 std::cout<<INFO<<"("<<id++<<") ";
914 if (comp->getDisable()) {
915 std::cout<<WARNING<<comp->getName()<<ENDC;
916 } else {
917 std::cout << OKBLUE << comp->getName() << ENDC;
918 }
919 std::cout<<INFO<<" ["<<fname<<"]"<<ENDC<<'\n';
920 }
921 }
922 return true;
923 }
924
925
929 if((cmdList.size() == 2) &&
930 (cmdList[0] == "export") )
931 {
932 if (!exportDependencyGraph(cmdList[1].c_str())) {
933 std::cout << FAIL << "ERROR: " << INFO << "Cannot export graph to " << cmdList[1] << "." << ENDC << '\n';
934 }
935 return true;
936 }
937
938
942 if((cmdList.size() == 3) &&
943 (cmdList[0] == "show") && (cmdList[1] == "mod"))
944 {
946 if(!kb->getModule(cmdList[2].c_str()))
947 {
948 std::cout<<FAIL<<"ERROR: "<<INFO<<"'"<<cmdList[2].c_str()<<"' not found."<<ENDC<<'\n';
949 return true;
950 }
951 std::cout<<INFO;
952 PRINT_MODULE(kb->getModule(cmdList[2].c_str()));
953 std::cout<<ENDC;
954 return true;
955 }
956
960 if((cmdList.size() == 3) &&
961 (cmdList[0] == "set"))
962 {
963 config.unput(cmdList[1]);
964 config.put(cmdList[1], cmdList[2]);
965
966 if(cmdList[1] == std::string("watchdog"))
967 {
968 if (cmdList[2] == std::string("yes")) {
970 } else {
972 }
973 }
974
975 if(cmdList[1] == std::string("auto_dependency"))
976 {
977 if (cmdList[2] == std::string("yes")) {
979 } else {
981 }
982 }
983
984 if(cmdList[1] == std::string("auto_connect"))
985 {
986 if (cmdList[2] == std::string("yes")) {
988 } else {
990 }
991 }
992
993 if(cmdList[1] == std::string("color_theme"))
994 {
995 if (cmdList[2] == std::string("dark")) {
996 setColorTheme(THEME_DARK);
997 } else if (cmdList[2] == std::string("light")) {
998 setColorTheme(THEME_LIGHT);
999 } else {
1000 setColorTheme(THEME_NONE);
1001 }
1002 }
1003
1004 return true;
1005 }
1006
1007
1011 if((cmdList.size() == 2) &&
1012 (cmdList[0] == "get"))
1013 {
1014 if(config.check(cmdList[1]))
1015 {
1016 std::cout<<OKBLUE<<cmdList[1]<<INFO<<" = ";
1017 std::cout<<OKGREEN<<config.find(cmdList[1]).asString()<<ENDC<<'\n';
1018 } else {
1019 std::cout << FAIL << "ERROR: " << INFO << "'" << cmdList[1].c_str() << "' not found." << ENDC << '\n';
1020 }
1021 return true;
1022 }
1023
1027 if((cmdList.size() == 2) &&
1028 (cmdList[0] == "assign") && (cmdList[1] == "hosts"))
1029 {
1030 loadBalance();
1031 reportErrors();
1032 return true;
1033 }
1034
1035 return false;
1036}
1037
1038
1039void YConsoleManager::help()
1040{
1041 std::cout<<"Here is a list of YARP manager keywords.\n"<<'\n';
1042 std::cout<<OKGREEN<<"help"<<INFO<<" : show help."<<ENDC<<'\n';
1043 std::cout<<OKGREEN<<"exit"<<INFO<<" : exit yarp manager."<<ENDC<<'\n';
1044 std::cout<<OKGREEN<<"list mod"<<INFO<<" : list available modules."<<ENDC<<'\n';
1045 std::cout<<OKGREEN<<"list app"<<INFO<<" : list available applications."<<ENDC<<'\n';
1046 std::cout<<OKGREEN<<"list res"<<INFO<<" : list available resources. (i.e. nodes in a cluster)"<<ENDC<<'\n';
1047 std::cout<<OKGREEN<<"add mod <filename>"<<INFO<<" : add a module from its description file."<<ENDC<<'\n';
1048 std::cout<<OKGREEN<<"add app <filename>"<<INFO<<" : add an application from its description file."<<ENDC<<'\n';
1049 std::cout<<OKGREEN<<"add res <filename>"<<INFO<<" : add resources from a description file."<<ENDC<<'\n';
1050 std::cout<<OKGREEN<<"load app <application>"<<INFO<<" : load an application to run."<<'\n';
1051// std::cout<<"load mod <module> <host>: load a module to run on an optional host."<<'\n';
1052 std::cout<<OKGREEN<<"run [IDs]"<<INFO<<" : run application or a modules indicated by IDs."<<ENDC<<'\n';
1053 std::cout<<OKGREEN<<"stop [IDs]"<<INFO<<" : stop running application or modules indicated by IDs."<<ENDC<<'\n';
1054 std::cout<<OKGREEN<<"kill [IDs]"<<INFO<<" : kill running application or modules indicated by IDs."<<ENDC<<'\n';
1055 std::cout<<OKGREEN<<"connect [IDs]"<<INFO<<" : stablish all connections or just one connection indicated by IDs."<<ENDC<<'\n';
1056 std::cout<<OKGREEN<<"disconnect [IDs]"<<INFO<<" : remove all connections or just one connection indicated by IDs."<<ENDC<<'\n';
1057 std::cout<<OKGREEN<<"which"<<INFO<<" : list loaded modules, connections and resource dependencies."<<ENDC<<'\n';
1058 std::cout<<OKGREEN<<"check dep"<<INFO<<" : check for all resource dependencies."<<ENDC<<'\n';
1059 std::cout<<OKGREEN<<"check state [id]"<<INFO<<" : check for running state of application or a module indicated by id."<<ENDC<<'\n';
1060 std::cout<<OKGREEN<<"check con [id]"<<INFO<<" : check for all connections state or just one connection indicated by id."<<ENDC<<'\n';
1061 std::cout<<OKGREEN<<"set <option> <value>"<<INFO<<" : set value to an option."<<ENDC<<'\n';
1062 std::cout<<OKGREEN<<"get <option>"<<INFO<<" : show value of an option."<<ENDC<<'\n';
1063 std::cout<<OKGREEN<<"export <filename>"<<INFO<<" : export application's graph as Graphviz dot format."<<ENDC<<'\n';
1064// std::cout<<"edit mod <modname> : open module relevant xml file to edit."<<'\n';
1065// std::cout<<"edit app <appname> : open application relevant xml file to edit."<<'\n';
1066 std::cout<<OKGREEN<<"show mod <modname>"<<INFO<<" : display module information (description, input, output,...)."<<ENDC<<'\n';
1067 std::cout<<OKGREEN<<"assign hosts"<<INFO<<" : automatically assign modules to proper nodes using load balancer."<<ENDC<<'\n';
1068
1069 std::cout<<'\n';
1070}
1071
1072
1073void YConsoleManager::which()
1074{
1076 CnnContainer connections = getConnections();
1079
1080 std::cout<<'\n'<<HEADER<<"Application: "<<ENDC<<'\n';
1081 std::cout<<OKBLUE<<getApplicationName()<<ENDC<<'\n';
1082
1083 std::cout<<'\n'<<HEADER<<"Modules: "<<ENDC<<'\n';
1084 int id = 0;
1085 for(moditr=modules.begin(); moditr<modules.end(); moditr++)
1086 {
1087 std::cout<<INFO<<"("<<id++<<") ";
1088 std::cout<<OKBLUE<<(*moditr)->getCommand()<<INFO;
1089 std::cout<<" ["<<(*moditr)->getHost()<<"] ["<<(*moditr)->getParam()<<"]";
1090 std::cout<<" ["<<(*moditr)->getEnv()<<"]"<<ENDC<<'\n';
1091 }
1092 std::cout<<'\n'<<HEADER<<"Connections: "<<ENDC<<'\n';
1093 id = 0;
1094 for(cnnitr=connections.begin(); cnnitr<connections.end(); cnnitr++)
1095 {
1096 std::cout<<INFO<<"("<<id++<<") ";
1097 std::cout<<OKBLUE<<(*cnnitr).from()<<" - "<<(*cnnitr).to()<<INFO;
1098 std::cout<<" ["<<(*cnnitr).carrier()<<"]";
1099 std::cout<<ENDC<<'\n';
1100 }
1101
1102 std::cout<<'\n'<<HEADER<<"Resources:"<<ENDC<<'\n';
1103 id = 0;
1105 for(itrS=getResources().begin(); itrS!=getResources().end(); itrS++)
1106 {
1107 std::cout<<INFO<<"("<<id++<<") ";
1108 std::cout<<OKBLUE<<(*itrS)->getName()<<INFO<<" ["<<(*itrS)->getTypeName()<<"]"<<ENDC<<'\n';
1109 }
1110 std::cout<<'\n';
1111}
1112
1113void YConsoleManager::checkStates()
1114{
1117 unsigned int id = 0;
1118 bShouldRun = false;
1119 for(moditr=modules.begin(); moditr<modules.end(); moditr++)
1120 {
1121 if(running(id))
1122 {
1123 bShouldRun = true;
1124 std::cout<<OKGREEN<<"<RUNNING> ";
1125 } else {
1126 std::cout << FAIL << "<STOPPED> ";
1127 }
1128 std::cout<<INFO<<"("<<id<<") ";
1129 std::cout<<(*moditr)->getCommand();
1130 std::cout<<" ["<<(*moditr)->getHost()<<"]"<<ENDC<<'\n';
1131 id++;
1132 }
1133}
1134
1135void YConsoleManager::checkConnections()
1136{
1137 CnnContainer connections = getConnections();
1139 int id = 0;
1140 for(cnnitr=connections.begin(); cnnitr<connections.end(); cnnitr++)
1141 {
1142 if (connected(id)) {
1143 std::cout<<OKGREEN<<"<CONNECTED> ";
1144 } else {
1145 std::cout << FAIL << "<DISCONNECTED> ";
1146 }
1147
1148 std::cout<<INFO<<"("<<id<<") ";
1149 std::cout<<(*cnnitr).from()<<" - "<<(*cnnitr).to();
1150 std::cout<<" ["<<(*cnnitr).carrier()<<"]"<<ENDC<<'\n';
1151 id++;
1152 }
1153}
1154
1155void YConsoleManager::reportErrors()
1156{
1158 if(logger->errorCount() || logger->warningCount())
1159 {
1160 const char* msg;
1161 while ((msg = logger->getLastError())) {
1162 std::cout << FAIL << "ERROR: " << INFO << msg << ENDC << '\n';
1163 }
1164
1165 while ((msg = logger->getLastWarning())) {
1166 std::cout << WARNING << "WARNING: " << INFO << msg << ENDC << '\n';
1167 }
1168 }
1169}
1170
1171
1173
1175
1177
1179{
1180 auto* exe = (Executable*) which;
1181 if (config.find("module_failure").asString() == "prompt") {
1182 std::cout << exe->getCommand() << " from " << exe->getHost() << " is failed!" << '\n';
1183 }
1184
1185 if(config.find("module_failure").asString() == "recover")
1186 {
1187 std::cout<<'\n'<<exe->getCommand()<<" from "<<exe->getHost()<<" is failed! (restarting...)"<<'\n';
1188 exe->start();
1189 }
1190
1191 if(config.find("module_failure").asString() == "terminate")
1192 {
1193 std::cout<<'\n'<<exe->getCommand()<<" from "<<exe->getHost()<<" is failed! (terminating application...)"<<'\n';
1194 bShouldRun = false;
1195 stop();
1196 reportErrors();
1197 }
1198}
1199
1201
1203{
1204 auto* cnn = (Connection*) which;
1205 if (config.check("connection_failure") && config.find("connection_failure").asString() == "prompt") {
1206 std::cout << '\n'
1207 << "connection failed between " << cnn->from() << " and " << cnn->to() << '\n';
1208 }
1209
1210 if(bShouldRun && config.check("connection_failure") &&
1211 config.find("connection_failure").asString() == "terminate")
1212 {
1213 std::cout<<'\n'<<"connection failed between "<<cnn->from()<<" and "<<cnn->to()<<"(terminating application...)"<<'\n';
1214 bShouldRun = false;
1215 stop();
1216 reportErrors();
1217 }
1218}
1219
1220
1221bool YConsoleManager::loadRecursiveApplications(const char* szPath)
1222{
1224 std::string strPath = szPath;
1225 if ((strPath.rfind(directorySeparator) == std::string::npos) || (strPath.rfind(directorySeparator) != strPath.size() - 1)) {
1226 strPath = strPath + std::string(directorySeparator);
1227 }
1228
1229 DIR *dir;
1230 struct dirent *entry;
1231 if ((dir = opendir(strPath.c_str())) == nullptr) {
1232 return false;
1233 }
1234
1235 addApplications(strPath.c_str());
1236
1237 while((entry = readdir(dir)))
1238 {
1239 if((std::string(entry->d_name) != std::string("."))
1240 && (std::string(entry->d_name) != std::string("..")))
1241 {
1242 std::string name = strPath + std::string(entry->d_name);
1243 loadRecursiveApplications(name.c_str());
1244 }
1245 }
1246 closedir(dir);
1247 return true;
1248}
1249
1250
1251
1252void YConsoleManager::updateAppNames(std::vector<std::string>* names)
1253{
1254 names->clear();
1256 ApplicaitonPContainer apps = kb->getApplications();
1257 for (auto& app : apps) {
1258 names->push_back(app->getName());
1259 }
1260}
1261
1262
1263
1264void YConsoleManager::setColorTheme(ColorTheme theme)
1265{
1266
1267#if defined(_WIN32)
1268 // do nothing here
1269#else
1270 switch(theme) {
1271 case THEME_DARK : {
1272 HEADER = "\033[01;95m";
1273 OKBLUE = "\033[94m";
1274 OKGREEN = "\033[92m";
1275 WARNING = "\033[93m";
1276 FAIL = "\033[91m";
1277 INFO = "\033[37m";
1278 ENDC = "\033[0m";
1279 break;
1280 }
1281 case THEME_LIGHT: {
1282 HEADER = "\033[01;35m";
1283 OKBLUE = "\033[34m";
1284 OKGREEN = "\033[32m";
1285 WARNING = "\033[33m";
1286 FAIL = "\033[31m";
1287 INFO = "\033[0m";
1288 ENDC = "\033[0m";
1289 break;
1290 }
1291 default: {
1292 HEADER = "";
1293 OKBLUE = "";
1294 OKGREEN = "";
1295 WARNING = "";
1296 FAIL = "";
1297 INFO = "";
1298 ENDC = "";
1299 break;
1300 }
1301 };
1302#endif
1303
1304}
1305
1306
1307
1308#ifdef YARP_HAS_Libedit
1309
1310char* dupstr(char* s)
1311{
1312 char *r;
1313 r = (char*) malloc ((strlen (s) + 1));
1314 strcpy (r, s);
1315 return (r);
1316}
1317
1318/* Attempt to complete on the contents of TEXT. START and END show the
1319 region of TEXT that contains the word to complete. We can use the
1320 entire line in case we want to do some simple parsing. Return the
1321 array of matches, or NULL if there aren't any. */
1322char ** my_completion (const char* text, int start, int end)
1323{
1324 char **matches;
1325
1326 matches = (char **)nullptr;
1327
1328 /* If this word is at the start of the line, then it is a command
1329 to complete. Otherwise it is the name of a file in the current
1330 directory. */
1331 if (start == 0) {
1333 } else {
1335 }
1336
1337 return (matches);
1338}
1339
1340
1341/* Generator function for command completion. STATE lets us know whether
1342 to start from scratch; without any state (i.e. STATE == 0), then we
1343 start at the top of the list. */
1344char* command_generator (const char* text, int state)
1345{
1346 //printf("commmand_genrator\n");
1347
1348 static int list_index, len;
1349 char *name;
1350
1351 /* if this is a new word to complete, initialize now. this includes
1352 saving the length of text for efficiency, and initializing the index
1353 variable to 0. */
1354 if (!state)
1355 {
1356 list_index = 0;
1357 len = strlen (text);
1358 }
1359
1360 while ((list_index<CMD_COUNTS) && (name = (char*)commands[list_index]))
1361 {
1362 list_index++;
1363 if (strncmp(name, text, len) == 0) {
1364 return (dupstr(name));
1365 }
1366 }
1367
1368 /* if no names matched, then return null. */
1369 return ((char *)nullptr);
1370}
1371
1372
1373char* appname_generator (const char* text, int state)
1374{
1375
1376 static unsigned int list_index, len;
1377 char *name;
1378
1379 if (!state)
1380 {
1381 list_index = 0;
1382 len = strlen (text);
1383 }
1384
1385 while ((list_index<appnames.size()) && (name = (char*)appnames[list_index].c_str()))
1386 {
1387 list_index++;
1388 if (strncmp(name, text, len) == 0) {
1389 return (dupstr(name));
1390 }
1391 }
1392
1393 return ((char *)nullptr);
1394}
1395
1396#endif
void onCnnFailed(void *which) override
void onExecutableStop(void *which) override
~YConsoleManager() override
void onExecutableFailed(void *which) override
void onCnnStablished(void *which) override
void onExecutableStart(void *which) override
YConsoleManager(int argc, char *argv[])
Class YConsoleManager.
Definition ymanager.cpp:126
void onExecutableDied(void *which) override
Class Application.
Singleton class For storing execution start time.
Definition utility.h:86
static ClockStart & getInstance()
Definition utility.h:88
Singleton class ErrorLogger.
Definition utility.h:58
const char * getLastError()
Definition utility.cpp:148
void addError(const char *szError)
Definition utility.cpp:126
static ErrorLogger * Instance()
Singleton class ErrorLogger.
Definition utility.cpp:98
const char * getLastWarning()
Definition utility.cpp:167
Class Executable.
Definition executable.h:71
Class KnowledgeBase.
Definition kbase.h:32
bool addApplication(Application *application, char **szAppName_=nullptr, bool modifyName=false)
Definition kbase.cpp:76
Class Manager.
Definition manager.h:20
ExecutablePContainer & getExecutables()
Definition manager.h:82
bool addModule(const char *szFileName)
Definition manager.cpp:127
CnnContainer & getConnections()
Definition manager.h:85
ResourcePContainer & getResources()
Definition manager.h:86
bool addModules(const char *szPath)
Definition manager.cpp:141
const char * getApplicationName()
Definition manager.h:87
bool addResources(const char *szPath)
Definition manager.cpp:170
bool addApplication(const char *szFileName, char **szAppName_=nullptr, bool modifyName=false)
Definition manager.cpp:90
void disableAutoDependency()
Definition manager.h:96
bool addResource(const char *szFileName)
Definition manager.cpp:155
void enableAutoDependency()
Definition manager.h:95
bool addApplications(const char *szPath)
Definition manager.cpp:110
bool loadApplication(const char *szAppName)
Definition manager.cpp:240
bool exportDependencyGraph(const char *szFileName)
Definition manager.h:99
KnowledgeBase * getKnowledgeBase()
Definition manager.h:103
void disableAutoConnect()
Definition manager.h:94
Class XmlAppLoader.
A mini-server for performing network communication in the background.
std::string getName() const override
Get name of port.
A controller for an individual connection.
Definition Connection.h:26
A class for storing options and configuration information.
Definition Property.h:33
Value & find(const std::string &key) const override
Gets a value corresponding to a given keyword.
void fromString(const std::string &txt, bool wipe=true)
Interprets a string as a list of properties.
void put(const std::string &key, const std::string &value)
Associate the given key with the given string.
Definition Property.cpp:987
bool check(const std::string &key) const override
Check if there exists a property of the given name.
void unput(const std::string &key)
Remove the association from the given key to a value, if present.
Helper class for finding config files and other external resources.
bool setDefaultContext(const std::string &contextName)
Sets the context for the current ResourceFinder object.
bool configure(int argc, char *argv[], bool skipFirstArgument=true)
Sets up the ResourceFinder.
std::string toString() const override
Return a standard text representation of the content of the object.
std::string findFile(const std::string &name)
Find the full path to a file.
bool setDefaultConfigFile(const std::string &fname)
Provide a default value for the configuration file (can be overridden from command line with the –fro...
virtual std::string asString() const
Get string value.
Definition Value.cpp:234
#define LOGO_MESSAGE
Definition main.cpp:21
#define HELP_MESSAGE
Definition main.cpp:18
#define DEF_CONFIG_FILE
Definition main.cpp:40
#define PRINT_MODULE(m)
Definition module.h:234
static constexpr value_type preferred_separator
Definition filesystem.h:21
bool compareString(const char *szFirst, const char *szSecond)
Definition utility.cpp:326
std::vector< Executable * >::iterator ExecutablePIterator
Definition executable.h:167
void trimString(std::string &str)
Definition utility.cpp:403
std::vector< GenericResource * >::iterator ResourcePIterator
Definition resource.h:59
std::vector< Connection >::iterator CnnIterator
std::vector< Executable * > ExecutablePContainer
Definition executable.h:166
std::vector< Module * > ModulePContainer
Definition module.h:230
std::vector< GenericResource * > ResourcePContainer
Definition resource.h:58
std::vector< Application * > ApplicaitonPContainer
std::vector< Connection > CnnContainer
An interface to the operating system, including Port based communication.
const char * getenv(const char *var)
Portable wrapper for the getenv() function.
bool isAbsolute(const char *path)
std::string ENDC
Definition ymanager.cpp:52
bool isAbsolute(const char *path)
Definition ymanager.cpp:109
std::string OKGREEN
Definition ymanager.cpp:48
#define WELCOME_MESSAGE
Definition ymanager.cpp:80
std::string INFO
Definition ymanager.cpp:51
#define CMD_COUNTS
Definition ymanager.cpp:56
#define VERSION_MESSAGE
Definition ymanager.cpp:81
std::string WARNING
Definition ymanager.cpp:49
std::string HEADER
Definition ymanager.cpp:46
std::string FAIL
Definition ymanager.cpp:50
std::string OKBLUE
Definition ymanager.cpp:47
@ THEME_LIGHT
Definition ymanager.h:20
@ THEME_NONE
Definition ymanager.h:21
@ THEME_DARK
Definition ymanager.h:19