37# if defined(YARP_HAS_SYS_TYPES_H)
38# include <sys/types.h>
40# if defined(YARP_HAS_SYS_WAIT_H)
43# if defined(YARP_HAS_SYS_PRCTL_H)
44# include <sys/prctl.h>
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",
" "};
70#define DEF_CONFIG_FILE "ymanager.ini"
72#define LOGO_MESSAGE "\
74\\ \\ / / __ ___ __ _ _ __ __ _ __ _ ___ _ __ \n\
75 \\ V / '_ ` _ \\ / _` | '_ \\ / _` |/ _` |/ _ \\ '__|\n\
76 | || | | | | | (_| | | | | (_| | (_| | __/ |\n\
77 |_||_| |_| |_|\\__,_|_| |_|\\__,_|\\__, |\\___|_|\n\
80#define WELCOME_MESSAGE "type \"help\" for more information."
81#define VERSION_MESSAGE "Version 1.1"
83#define HELP_MESSAGE "\
85 yarpmanager-console [option...]\n\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\
110 if (path[0]==
'/'||path[0]==
'\\') {
113 std::string str(path);
114 if (str.length()>1) {
144 if(config.
check(
"help"))
150 if(config.
check(
"version"))
157 if(!config.
check(
"elapsed_time"))
160 clock.setStartTime(
"00:00:00");
182 if (!config.
check(
"apppath")) {
183 config.
put(
"apppath",
"./");
186 if (!config.
check(
"modpath")) {
187 config.
put(
"modpath",
"./");
190 if (!config.
check(
"respath")) {
191 config.
put(
"respath",
"./");
194 if (!config.
check(
"load_subfolders")) {
195 config.
put(
"load_subfolders",
"no");
198 if (!config.
check(
"watchdog")) {
199 config.
put(
"watchdog",
"no");
202 if (!config.
check(
"module_failure")) {
203 config.
put(
"module_failure",
"prompt");
206 if (!config.
check(
"connection_failure")) {
207 config.
put(
"connection_failure",
"prompt");
210 if (!config.
check(
"auto_connect")) {
211 config.
put(
"auto_connect",
"no");
214 if (!config.
check(
"auto_dependency")) {
215 config.
put(
"auto_dependency",
"no");
218 if (!config.
check(
"color_theme")) {
219 config.
put(
"color_theme",
"light");
228 }
else if (config.
find(
"color_theme").
asString() ==
"light") {
240 if (config.
find(
"auto_dependency").
asString() ==
"yes") {
252 if(!config.
check(
"silent"))
258 if(config.
check(
"modpath"))
266 strPath = std::string(
inipath).append(strPath);
272 if(config.
check(
"respath"))
280 strPath = std::string(
inipath).append(strPath);
287 if(config.
check(
"apppath"))
295 strPath = std::string(
inipath).append(strPath);
299 if (!loadRecursiveApplications(strPath.c_str())) {
300 logger->
addError(
"Cannot load the applications from " + strPath);
310#ifdef YARP_HAS_Libedit
316 ::signal(
SIGINT, YConsoleManager::onSignal);
317 ::signal(
SIGBREAK, YConsoleManager::onSignal);
318 ::signal(
SIGTERM, YConsoleManager::onSignal);
323 new_action.sa_handler = YConsoleManager::onSignal;
328 if (old_action.sa_handler !=
SIG_IGN) {
332 if (old_action.sa_handler !=
SIG_IGN) {
336 if (old_action.sa_handler !=
SIG_IGN) {
341 if(config.
check(
"application"))
354#ifdef YARP_HAS_Libedit
360 if (!config.
check(
"silent")) {
364 if (config.
check(
"assign_hosts")) {
368 if(config.
check(
"run"))
370 if (config.
check(
"connect")) {
374 }
else if (config.
check(
"connect")) {
378 if (config.
check(
"disconnect")) {
382 if(config.
check(
"stop"))
398 if(config.
check(
"kill"))
404 if (config.
check(
"check_con")) {
408 if (config.
check(
"check_state")) {
412 if (config.
check(
"check_dep")) {
414 std::cout <<
INFO <<
"All of resource dependencies are satisfied." <<
ENDC <<
'\n';
420 if (!config.
check(
"silent")) {
425 if (!config.
check(
"exit")) {
426 YConsoleManager::myMain();
434void YConsoleManager::onSignal(
int signum)
437 std::cout<<
INFO<<
"[force exit] yarpmanager will terminate all of the running modules on exit.";
446void YConsoleManager::myMain()
450#ifdef YARP_HAS_Libedit
454 while(!std::cin.
eof())
458#ifdef YARP_HAS_Libedit
459 static char*
szLine = (
char*)
nullptr;
480 std::vector<std::string> cmdList;
481 std::stringstream
foo(temp);
486 s =
getenv(
"HOME") + s.substr(1);
488 cmdList.push_back(s);
490 if(!process(cmdList))
492 if(cmdList[0] ==
"exit")
494 if (YConsoleManager::exit()) {
500 std::cout<<
"'"<<cmdList[0]<<
"'"<<
INFO<<
" is not correct. ";
501 std::cout<<
"type \"help\" for more information."<<
ENDC<<
'\n';
513 std::cout<<
"bye."<<
'\n';
517bool YConsoleManager::exit()
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;
538bool YConsoleManager::process(
const std::vector<std::string> &cmdList)
540 if (!cmdList.size() || cmdList[0] ==
"") {
547 if((cmdList.size() == 1) &&
548 (cmdList[0] ==
"help"))
558 if((cmdList.size() == 3) &&
559 (cmdList[0] ==
"add") && (cmdList[1] ==
"app"))
562 std::cout <<
INFO << cmdList[2] <<
" is successfully added." <<
ENDC <<
'\n';
565 #ifdef YARP_HAS_Libedit
574 if((cmdList.size() == 3) &&
575 (cmdList[0] ==
"add") && (cmdList[1] ==
"mod"))
578 std::cout <<
INFO << cmdList[2] <<
" is successfully added." <<
ENDC <<
'\n';
587 if((cmdList.size() == 3) &&
588 (cmdList[0] ==
"add") && (cmdList[1] ==
"res"))
591 std::cout <<
INFO << cmdList[2] <<
" is successfully added." <<
ENDC <<
'\n';
601 if((cmdList.size() == 3) &&
602 (cmdList[0] ==
"load") && (cmdList[1] ==
"app"))
636 if((cmdList.size() == 1) &&
637 (cmdList[0] ==
"run"))
643 if((cmdList.size() >= 2) &&
644 (cmdList[0] ==
"run"))
647 for (
unsigned int i = 1; i < cmdList.size(); i++) {
657 if((cmdList.size() == 1) &&
658 (cmdList[0] ==
"stop"))
665 if((cmdList.size() >= 2) &&
666 (cmdList[0] ==
"stop"))
669 for (
unsigned int i = 1; i < cmdList.size(); i++) {
680 if((cmdList.size() == 1) &&
681 (cmdList[0] ==
"kill"))
688 if((cmdList.size() >= 2) &&
689 (cmdList[0] ==
"kill"))
692 for (
unsigned int i = 1; i < cmdList.size(); i++) {
703 if((cmdList.size() == 1) &&
704 (cmdList[0] ==
"connect"))
710 if((cmdList.size() >= 2) &&
711 (cmdList[0] ==
"connect"))
713 for (
unsigned int i = 1; i < cmdList.size(); i++) {
724 if((cmdList.size() == 1) &&
725 (cmdList[0] ==
"disconnect"))
731 if((cmdList.size() >= 2) &&
732 (cmdList[0] ==
"disconnect"))
734 for (
unsigned int i = 1; i < cmdList.size(); i++) {
745 if((cmdList.size() == 1) &&
746 (cmdList[0] ==
"which"))
755 if((cmdList.size() == 2) &&
756 (cmdList[0] ==
"check") && (cmdList[1] ==
"dep"))
759 std::cout <<
INFO <<
"All of resource dependencies are satisfied." <<
ENDC <<
'\n';
769 if((cmdList.size() == 3) &&
770 (cmdList[0] ==
"check") && (cmdList[1] ==
"state"))
774 if(
id>=modules.size())
776 std::cout<<
FAIL<<
"ERROR: "<<
INFO<<
"Module id is out of range."<<
ENDC<<
'\n';
781 std::cout<<
OKGREEN<<
"<RUNNING> ";
783 std::cout <<
FAIL <<
"<STOPPED> ";
785 std::cout<<
INFO<<
"("<<
id<<
") ";
786 std::cout<<modules[id]->getCommand();
787 std::cout<<
" ["<<modules[id]->getHost()<<
"]"<<
ENDC<<
'\n';
791 if((cmdList.size() == 2) &&
792 (cmdList[0] ==
"check") && (cmdList[1] ==
"state"))
803 if((cmdList.size() == 3) &&
804 (cmdList[0] ==
"check") && (cmdList[1] ==
"con"))
809 if(
id>=connections.size())
811 std::cout<<
FAIL<<
"ERROR: "<<
INFO<<
"Connection id is out of range."<<
ENDC<<
'\n';
816 std::cout<<
OKGREEN<<
"<CONNECTED> ";
818 std::cout <<
FAIL <<
"<DISCONNECTED> ";
821 std::cout<<
INFO<<
"("<<
id<<
") ";
822 std::cout<<connections[id].from()<<
" - "<<connections[id].to();
823 std::cout<<
" ["<<connections[id].carrier()<<
"]"<<
ENDC<<
'\n';
827 if((cmdList.size() == 2) &&
828 (cmdList[0] ==
"check") && (cmdList[1] ==
"con"))
839 if((cmdList.size() == 2) &&
840 (cmdList[0] ==
"list") && (cmdList[1] ==
"mod"))
848 std::string
fpath =
mod->getXmlFile();
851 if (pos != std::string::npos) {
856 std::cout<<
INFO<<
"("<<
id++<<
") ";
867 if((cmdList.size() == 2) &&
868 (cmdList[0] ==
"list") && (cmdList[1] ==
"app"))
873 for(
auto& app : apps)
876 std::string
fpath = app->getXmlFile();
879 if (pos != std::string::npos) {
884 std::cout<<
INFO<<
"("<<
id++<<
") ";
894 if((cmdList.size() == 2) &&
895 (cmdList[0] ==
"list") && (cmdList[1] ==
"res"))
906 std::string
fpath = comp->getXmlFile();
908 if (pos != std::string::npos) {
913 std::cout<<
INFO<<
"("<<
id++<<
") ";
914 if (comp->getDisable()) {
917 std::cout <<
OKBLUE << comp->getName() <<
ENDC;
929 if((cmdList.size() == 2) &&
930 (cmdList[0] ==
"export") )
933 std::cout <<
FAIL <<
"ERROR: " <<
INFO <<
"Cannot export graph to " << cmdList[1] <<
"." <<
ENDC <<
'\n';
942 if((cmdList.size() == 3) &&
943 (cmdList[0] ==
"show") && (cmdList[1] ==
"mod"))
946 if(!
kb->getModule(cmdList[2].c_str()))
948 std::cout<<
FAIL<<
"ERROR: "<<
INFO<<
"'"<<cmdList[2].c_str()<<
"' not found."<<
ENDC<<
'\n';
960 if((cmdList.size() == 3) &&
961 (cmdList[0] ==
"set"))
963 config.
unput(cmdList[1]);
964 config.
put(cmdList[1], cmdList[2]);
966 if(cmdList[1] == std::string(
"watchdog"))
968 if (cmdList[2] == std::string(
"yes")) {
975 if(cmdList[1] == std::string(
"auto_dependency"))
977 if (cmdList[2] == std::string(
"yes")) {
984 if(cmdList[1] == std::string(
"auto_connect"))
986 if (cmdList[2] == std::string(
"yes")) {
993 if(cmdList[1] == std::string(
"color_theme"))
995 if (cmdList[2] == std::string(
"dark")) {
997 }
else if (cmdList[2] == std::string(
"light")) {
1011 if((cmdList.size() == 2) &&
1012 (cmdList[0] ==
"get"))
1014 if(config.
check(cmdList[1]))
1019 std::cout <<
FAIL <<
"ERROR: " <<
INFO <<
"'" << cmdList[1].c_str() <<
"' not found." <<
ENDC <<
'\n';
1027 if((cmdList.size() == 2) &&
1028 (cmdList[0] ==
"assign") && (cmdList[1] ==
"hosts"))
1039void YConsoleManager::help()
1041 std::cout<<
"Here is a list of YARP manager keywords.\n"<<
'\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';
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';
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';
1073void YConsoleManager::which()
1080 std::cout<<
'\n'<<
HEADER<<
"Application: "<<
ENDC<<
'\n';
1083 std::cout<<
'\n'<<
HEADER<<
"Modules: "<<
ENDC<<
'\n';
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';
1092 std::cout<<
'\n'<<
HEADER<<
"Connections: "<<
ENDC<<
'\n';
1096 std::cout<<
INFO<<
"("<<
id++<<
") ";
1097 std::cout<<
OKBLUE<<(*cnnitr).from()<<
" - "<<(*cnnitr).to()<<
INFO;
1098 std::cout<<
" ["<<(*cnnitr).carrier()<<
"]";
1099 std::cout<<
ENDC<<
'\n';
1102 std::cout<<
'\n'<<
HEADER<<
"Resources:"<<
ENDC<<
'\n';
1107 std::cout<<
INFO<<
"("<<
id++<<
") ";
1113void YConsoleManager::checkStates()
1117 unsigned int id = 0;
1124 std::cout<<
OKGREEN<<
"<RUNNING> ";
1126 std::cout <<
FAIL <<
"<STOPPED> ";
1128 std::cout<<
INFO<<
"("<<
id<<
") ";
1129 std::cout<<(*moditr)->getCommand();
1130 std::cout<<
" ["<<(*moditr)->getHost()<<
"]"<<
ENDC<<
'\n';
1135void YConsoleManager::checkConnections()
1143 std::cout<<
OKGREEN<<
"<CONNECTED> ";
1145 std::cout <<
FAIL <<
"<DISCONNECTED> ";
1148 std::cout<<
INFO<<
"("<<
id<<
") ";
1149 std::cout<<(*cnnitr).from()<<
" - "<<(*cnnitr).to();
1150 std::cout<<
" ["<<(*cnnitr).carrier()<<
"]"<<
ENDC<<
'\n';
1155void YConsoleManager::reportErrors()
1162 std::cout <<
FAIL <<
"ERROR: " <<
INFO << msg <<
ENDC <<
'\n';
1181 if (config.
find(
"module_failure").
asString() ==
"prompt") {
1182 std::cout <<
exe->getCommand() <<
" from " <<
exe->getHost() <<
" is failed!" <<
'\n';
1185 if(config.
find(
"module_failure").
asString() ==
"recover")
1187 std::cout<<
'\n'<<
exe->getCommand()<<
" from "<<
exe->getHost()<<
" is failed! (restarting...)"<<
'\n';
1191 if(config.
find(
"module_failure").
asString() ==
"terminate")
1193 std::cout<<
'\n'<<
exe->getCommand()<<
" from "<<
exe->getHost()<<
" is failed! (terminating application...)"<<
'\n';
1205 if (config.
check(
"connection_failure") && config.
find(
"connection_failure").
asString() ==
"prompt") {
1207 <<
"connection failed between " <<
cnn->from() <<
" and " <<
cnn->to() <<
'\n';
1210 if(bShouldRun && config.
check(
"connection_failure") &&
1211 config.
find(
"connection_failure").
asString() ==
"terminate")
1213 std::cout<<
'\n'<<
"connection failed between "<<
cnn->from()<<
" and "<<
cnn->to()<<
"(terminating application...)"<<
'\n';
1221bool YConsoleManager::loadRecursiveApplications(
const char*
szPath)
1224 std::string strPath =
szPath;
1231 if ((
dir =
opendir(strPath.c_str())) ==
nullptr) {
1239 if((std::string(
entry->d_name) != std::string(
"."))
1240 && (std::string(
entry->d_name) != std::string(
"..")))
1242 std::string name = strPath + std::string(
entry->d_name);
1243 loadRecursiveApplications(name.c_str());
1252void YConsoleManager::updateAppNames(std::vector<std::string>* names)
1257 for (
auto& app : apps) {
1258 names->push_back(app->getName());
1308#ifdef YARP_HAS_Libedit
1363 if (
strncmp(name, text, len) == 0) {
1369 return ((
char *)
nullptr);
1388 if (
strncmp(name, text, len) == 0) {
1393 return ((
char *)
nullptr);
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.
void onExecutableDied(void *which) override
Singleton class For storing execution start time.
static ClockStart & getInstance()
Singleton class ErrorLogger.
const char * getLastError()
void addError(const char *szError)
static ErrorLogger * Instance()
Singleton class ErrorLogger.
const char * getLastWarning()
bool addApplication(Application *application, char **szAppName_=nullptr, bool modifyName=false)
ExecutablePContainer & getExecutables()
bool addModule(const char *szFileName)
CnnContainer & getConnections()
ResourcePContainer & getResources()
bool addModules(const char *szPath)
const char * getApplicationName()
bool addResources(const char *szPath)
bool addApplication(const char *szFileName, char **szAppName_=nullptr, bool modifyName=false)
void disableAutoDependency()
bool addResource(const char *szFileName)
void enableAutoDependency()
bool addApplications(const char *szPath)
bool loadApplication(const char *szAppName)
bool exportDependencyGraph(const char *szFileName)
KnowledgeBase * getKnowledgeBase()
void disableAutoConnect()
A mini-server for performing network communication in the background.
std::string getName() const override
Get name of port.
BufferedPort()
Constructor.
A controller for an individual connection.
A class for storing options and configuration information.
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.
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.
static constexpr value_type preferred_separator
bool compareString(const char *szFirst, const char *szSecond)
std::vector< Executable * >::iterator ExecutablePIterator
void trimString(std::string &str)
std::vector< GenericResource * >::iterator ResourcePIterator
std::vector< Connection >::iterator CnnIterator
std::vector< Executable * > ExecutablePContainer
std::vector< Module * > ModulePContainer
std::vector< GenericResource * > ResourcePContainer
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)
bool isAbsolute(const char *path)