diff --git a/Common/GmshDaemon.cpp b/Common/GmshDaemon.cpp index 9acecb88b5281e4b2d0628b7bf3d1d10b4b7ba7c..d5ef10b4c3f645a5bb4f479fa88edd01f44e2119 100644 --- a/Common/GmshDaemon.cpp +++ b/Common/GmshDaemon.cpp @@ -17,34 +17,48 @@ int GmshDaemon(std::string socket) return 1; } client.Start(); - + + // read large data file, + // initialize mpi job, + // then wait for commands to execute: while(1){ - // wait (at most 10ms) until data is available to read - if(!client.Select(0, 10000)){ + // wait at most 1 second for data + if(!client.Select(1, 0)){ int type, length; if(client.ReceiveHeader(&type, &length)){ - Msg::Info("Received header: type=%d length=%d", type, length); - char *msg = new char[length]; + char *msg = new char[length + 1]; if(client.ReceiveString(length, msg)){ - Msg::Info("received string: %s", msg); - Msg::Info("replying by sending post data"); std::ostringstream tmp; - tmp<<"View \"test\" {\n"; - for(int i= 0; i < 100; i++){ - for(int j= 0; j < 100; j++){ - tmp << "SQ("<<i<<","<<j<<",0, "<<i+1<<","<<j<<",0, " + tmp << "Hello! I've received msg type=" << type << " len=" << length + << " str=" << msg; + client.Info(tmp.str().c_str()); + if(type == GmshSocket::STOP){ + client.Info("Stopping connection!"); + delete [] msg; + break; + } + else{ + std::ostringstream v; + v << "View \"test\" {\n"; + for(int i= 0; i < 100; i++){ + for(int j= 0; j < 100; j++){ + v << "SQ("<<i<<","<<j<<",0, "<<i+1<<","<<j<<",0, " <<i+1<<","<<j+1<<",0, "<<i<<","<<j+1<<",0){" <<i+j<<","<<i+j<<","<<i+j<<","<<i+j<<"};\n"; + } } + v << "};BoundingBox;\n"; + client.ParseString(v.str().c_str()); } - tmp<<"};BoundingBox;\n"; - client.ParseString(tmp.str().c_str()); } delete [] msg; - //printf("stopping connection!\n"); - //break; } } + else{ + // ping the server so we automatically crash of it goes down :-) + printf("printf ping!\n"); + client.Info("Ping!"); + } } client.Stop(); diff --git a/Common/GmshSocket.h b/Common/GmshSocket.h index 6eb55f0d45225934382f9e9c87025b0c88cb7ba8..f9e95eb1c69a1f9b0fee07020bf856facb6bd0c7 100644 --- a/Common/GmshSocket.h +++ b/Common/GmshSocket.h @@ -40,20 +40,20 @@ class GmshSocket{ // receive data from a machine with a different byte ordering, and // we swap the bytes in the payload) enum MessageType{ - CLIENT_START = 1, - CLIENT_STOP = 2, - CLIENT_INFO = 10, - CLIENT_WARNING = 11, - CLIENT_ERROR = 12, - CLIENT_PROGRESS = 13, - CLIENT_MERGE_FILE = 20, // old name: CLIENT_VIEW - CLIENT_PARSE_STRING = 21, - CLIENT_SPEED_TEST = 30, - CLIENT_OPTION_1 = 100, - CLIENT_OPTION_2 = 101, - CLIENT_OPTION_3 = 102, - CLIENT_OPTION_4 = 103, - CLIENT_OPTION_5 = 104}; + START = 1, + STOP = 2, + INFO = 10, + WARNING = 11, + ERROR = 12, + PROGRESS = 13, + MERGE_FILE = 20, + PARSE_STRING = 21, + SPEED_TEST = 30, + OPTION_1 = 100, + OPTION_2 = 101, + OPTION_3 = 102, + OPTION_4 = 103, + OPTION_5 = 104}; protected: // the socket descriptor int _sock; @@ -181,6 +181,10 @@ class GmshSocket{ closesocket(s); #endif } + void ShutdownSocket(int s) + { + shutdown(s, SHUT_RDWR); + } }; class GmshClient : public GmshSocket { @@ -189,8 +193,8 @@ class GmshClient : public GmshSocket { ~GmshClient(){} int Connect(const char *sockname) { - // slight delay to be sure that the socket is bound by the - // server before we attempt to connect to it... + // slight delay to make sure that the socket is bound by the + // server before we attempt to connect to it _Sleep(100); if(strstr(sockname, "/") || strstr(sockname, "\\") || !strstr(sockname, ":")){ @@ -257,23 +261,21 @@ class GmshClient : public GmshSocket { #else sprintf(tmp, "%d", _getpid()); #endif - SendString(CLIENT_START, tmp); + SendString(START, tmp); } - void Stop(){ SendString(CLIENT_STOP, "Goodbye!"); } - void Info(const char *str){ SendString(CLIENT_INFO, str); } - void Warning(const char *str){ SendString(CLIENT_WARNING, str); } - void Error(const char *str){ SendString(CLIENT_ERROR, str); } - void Progress(const char *str){ SendString(CLIENT_PROGRESS, str); } - // deprecated: use MergeFile instead - void View(const char *str){ SendString(CLIENT_MERGE_FILE, str); } - void MergeFile(const char *str){ SendString(CLIENT_MERGE_FILE, str); } - void ParseString(const char *str){ SendString(CLIENT_PARSE_STRING, str); } - void SpeedTest(const char *str){ SendString(CLIENT_SPEED_TEST, str); } + void Stop(){ SendString(STOP, "Goodbye!"); } + void Info(const char *str){ SendString(INFO, str); } + void Warning(const char *str){ SendString(WARNING, str); } + void Error(const char *str){ SendString(ERROR, str); } + void Progress(const char *str){ SendString(PROGRESS, str); } + void MergeFile(const char *str){ SendString(MERGE_FILE, str); } + void ParseString(const char *str){ SendString(PARSE_STRING, str); } + void SpeedTest(const char *str){ SendString(SPEED_TEST, str); } void Option(int num, const char *str) { if(num < 1) num = 1; if(num > 5) num = 5; - SendString(CLIENT_OPTION_1 + num - 1, str); + SendString(OPTION_1 + num - 1, str); } void Disconnect(){ CloseSocket(_sock); } }; @@ -394,12 +396,13 @@ class GmshServer : public GmshSocket{ return -5; // Error: Socket accept failed return _sock; } - int StopClient() + int Shutdown() { #if !defined(WIN32) || defined(__CYGWIN__) if(_portno < 0) unlink(_sockname); #endif + ShutdownSocket(_sock); CloseSocket(_sock); return 0; } diff --git a/Fltk/Solvers.cpp b/Fltk/Solvers.cpp index 695be45f4b8e079129a0bd64dfb194479982b0a3..8769423c32880ca8465aa79e156e085ecfd7d155 100644 --- a/Fltk/Solvers.cpp +++ b/Fltk/Solvers.cpp @@ -5,6 +5,7 @@ #include <string.h> #include <string> +#include <sstream> #include "FlGui.h" #include "solverWindow.h" #include "menuWindow.h" @@ -18,7 +19,7 @@ #include "Context.h" #include "OS.h" -SolverInfo SINFO[MAX_NUM_SOLVERS]; +SolverInfo SINFO[MAX_NUM_SOLVERS + 1]; class myGmshServer : public GmshServer{ public: @@ -64,6 +65,26 @@ class myGmshServer : public GmshServer{ } }; +std::string GetSocketName(int num) +{ + std::string sockname; + if(!strstr(CTX::instance()->solver.socketName.c_str(), ":")){ + // Unix socket + std::ostringstream tmp; + tmp << CTX::instance()->homeDir << CTX::instance()->solver.socketName; + if(num >= 0) tmp << "-" << num; + sockname = FixWindowsPath(tmp.str().c_str()); + } + else{ + // TCP/IP socket + sockname = CTX::instance()->solver.socketName; + // if only the port is given, prepend the host name + if(sockname.size() && sockname[0] == ':') + sockname = GetHostName() + sockname; + } + return sockname; +} + // This routine either launches a solver and waits for some answer (if // num >= 0), or simply waits for messages (if num < 0) @@ -95,25 +116,7 @@ int Solver(int num, const char *args) prog = command = ""; } - if(!strstr(CTX::instance()->solver.socketName.c_str(), ":")){ - // Unix socket - char tmp[1024]; - if(num >= 0) - sprintf(tmp, "%s%s-%d", CTX::instance()->homeDir.c_str(), - CTX::instance()->solver.socketName.c_str(), - num); - else - sprintf(tmp, "%s%s", CTX::instance()->homeDir.c_str(), - CTX::instance()->solver.socketName.c_str()); - sockname = FixWindowsPath(tmp); - } - else{ - // TCP/IP socket - sockname = CTX::instance()->solver.socketName; - // if only the port is given, prepend the host name - if(sockname.size() && sockname[0] == ':') - sockname = GetHostName() + sockname; - } + sockname = GetSocketName(num); if(num >= 0){ std::string tmp2 = "\"" + sockname + "\""; @@ -147,7 +150,7 @@ int Solver(int num, const char *args) break; case -6: Msg::Info("Stopped listening for solver connections"); - server->StopClient(); + server->Shutdown(); break; case -7: Msg::Error("Unix sockets not available on Windows without Cygwin"); @@ -190,26 +193,26 @@ int Solver(int num, const char *args) char *message = new char[length + 1]; if(server->ReceiveString(length, message)){ switch (type) { - case GmshServer::CLIENT_START: + case GmshSocket::START: if(num >= 0){ SINFO[num].pid = atoi(message); SINFO[num].server = server; } break; - case GmshServer::CLIENT_STOP: + case GmshSocket::STOP: stop = 1; if(num >= 0){ SINFO[num].pid = -1; SINFO[num].server = 0; } break; - case GmshServer::CLIENT_PROGRESS: + case GmshSocket::PROGRESS: if(num >= 0) Msg::StatusBar(2, false, "%s %s", SINFO[num].name.c_str(), message); else Msg::StatusBar(2, false, "%s", message); break; - case GmshServer::CLIENT_OPTION_1: + case GmshSocket::OPTION_1: if(initOption[0]){ SINFO[num].option[0].clear(); initOption[0] = false; @@ -217,7 +220,7 @@ int Solver(int num, const char *args) if(num >= 0) SINFO[num].option[0].push_back(message); break; - case GmshServer::CLIENT_OPTION_2: + case GmshSocket::OPTION_2: if(initOption[1]){ SINFO[num].option[1].clear(); initOption[1] = false; @@ -225,7 +228,7 @@ int Solver(int num, const char *args) if(num >= 0) SINFO[num].option[1].push_back(message); break; - case GmshServer::CLIENT_OPTION_3: + case GmshSocket::OPTION_3: if(initOption[2]){ SINFO[num].option[2].clear(); initOption[2] = false; @@ -233,7 +236,7 @@ int Solver(int num, const char *args) if(num >= 0) SINFO[num].option[2].push_back(message); break; - case GmshServer::CLIENT_OPTION_4: + case GmshSocket::OPTION_4: if(initOption[3]){ SINFO[num].option[3].clear(); initOption[3] = false; @@ -241,7 +244,7 @@ int Solver(int num, const char *args) if(num >= 0) SINFO[num].option[3].push_back(message); break; - case GmshServer::CLIENT_OPTION_5: + case GmshSocket::OPTION_5: if(initOption[4]){ SINFO[num].option[4].clear(); initOption[4] = false; @@ -249,7 +252,7 @@ int Solver(int num, const char *args) if(num >= 0) SINFO[num].option[4].push_back(message); break; - case GmshServer::CLIENT_MERGE_FILE: + case GmshSocket::MERGE_FILE: if(num < 0 || (num >= 0 && SINFO[num].merge_views)) { int n = PView::list.size(); MergeFile(message); @@ -258,23 +261,23 @@ int Solver(int num, const char *args) FlGui::instance()->menu->setContext(menu_post, 0); } break; - case GmshServer::CLIENT_PARSE_STRING: + case GmshSocket::PARSE_STRING: ParseString(message); drawContext::global()->draw(); break; - case GmshServer::CLIENT_INFO: + case GmshSocket::INFO: Msg::Direct("%-8.8s: %s", num >= 0 ? SINFO[num].name.c_str() : "Client", message); break; - case GmshServer::CLIENT_WARNING: + case GmshSocket::WARNING: Msg::Direct(2, "%-8.8s: %s", num >= 0 ? SINFO[num].name.c_str() : "Client", message); break; - case GmshServer::CLIENT_ERROR: + case GmshSocket::ERROR: Msg::Direct(1, "%-8.8s: %s", num >= 0 ? SINFO[num].name.c_str() : "Client", message); break; - case GmshServer::CLIENT_SPEED_TEST: + case GmshSocket::SPEED_TEST: Msg::Info("got %d Mb message in %g seconds", strlen(message) / 1024 / 1024, GetTimeInSeconds() - timer); break; @@ -311,7 +314,7 @@ int Solver(int num, const char *args) } } - server->StopClient(); + server->Shutdown(); if(num >= 0){ Msg::StatusBar(2, false, ""); diff --git a/Fltk/Solvers.h b/Fltk/Solvers.h index 62189a6c147b20a4c3fcb34d2bf8b06d0fbefb42..062a530ae872e00edb26e6f12ffbe9c22a5c0b8a 100644 --- a/Fltk/Solvers.h +++ b/Fltk/Solvers.h @@ -30,8 +30,9 @@ typedef struct{ GmshServer *server; } SolverInfo ; -extern SolverInfo SINFO[MAX_NUM_SOLVERS]; +extern SolverInfo SINFO[MAX_NUM_SOLVERS + 1]; +std::string GetSocketName(int num); int Solver(int num, const char *args); #endif diff --git a/Fltk/menuWindow.cpp b/Fltk/menuWindow.cpp index 3e89232aaf4f5f125b41429e98806a994a3f0fab..33926dedd9268aff75520615da6d0e48168b128b 100644 --- a/Fltk/menuWindow.cpp +++ b/Fltk/menuWindow.cpp @@ -47,6 +47,7 @@ #include "GeoStringInterface.h" #include "Options.h" #include "Context.h" +#include "GmshSocket.h" static void file_new_cb(Fl_Widget *w, void *data) { @@ -145,6 +146,45 @@ static void file_clear_cb(Fl_Widget *w, void *data) drawContext::global()->draw(); } +static void file_remote_cb(Fl_Widget *w, void *data) +{ + std::string str((const char*)data); + + if(str == "connect"){ + Msg::Info("Starting remote Gmsh"); + if(SINFO[MAX_NUM_SOLVERS].server){ + Msg::Info("A server is already running, trying to stop it first"); + SINFO[MAX_NUM_SOLVERS].server->SendString(GmshSocket::STOP, "DISCONNECTING!"); + } + SINFO[MAX_NUM_SOLVERS].name = "Gmsh Daemon"; + SINFO[MAX_NUM_SOLVERS].executable_name = "./gmsh"; + SINFO[MAX_NUM_SOLVERS].socket_command = "-socket %s"; + SINFO[MAX_NUM_SOLVERS].nboptions = 0; + SINFO[MAX_NUM_SOLVERS].client_server = 1; + SINFO[MAX_NUM_SOLVERS].popup_messages = 1; + SINFO[MAX_NUM_SOLVERS].merge_views = 1; + Solver(MAX_NUM_SOLVERS, ""); + } + else if(str == "disconnect"){ + if(SINFO[MAX_NUM_SOLVERS].server){ + Msg::Info("Stopping remote Gmsh"); + SINFO[MAX_NUM_SOLVERS].server->SendString(GmshSocket::STOP, "DISCONNECTING!"); + } + else{ + Msg::Warning("Cannot disconnect remote Gmsh: server not running"); + } + } + else if(str == "test"){ + if(SINFO[MAX_NUM_SOLVERS].server){ + Msg::Info("Testing remote Gmsh daemon"); + SINFO[MAX_NUM_SOLVERS].server->SendString(9999, "GENERATE A VIEW!"); + } + else{ + Msg::Warning("Cannot test remote Gmsh: must be connected first!"); + } + } +} + static void file_window_cb(Fl_Widget *w, void *data) { std::string str((const char*)data); @@ -2197,6 +2237,11 @@ static Fl_Menu_Item sysbar_table[] = { {"Vertically", 0, (Fl_Callback *)file_window_cb, (void*)"split_v"}, {"Clear", 0, (Fl_Callback *)file_window_cb, (void*)"split_u"}, {0}, +#if 0 // test remote gmsh daemon + {"Connect...", 0, (Fl_Callback *)file_remote_cb, (void*)"connect"}, + {"Test remote!", 0, (Fl_Callback *)file_remote_cb, (void*)"test"}, + {"Disconnect", 0, (Fl_Callback *)file_remote_cb, (void*)"disconnect", FL_MENU_DIVIDER}, +#endif {"Rename...", FL_META+'r', (Fl_Callback *)file_rename_cb, 0}, {"Save As...", FL_META+'s', (Fl_Callback *)file_save_as_cb, 0}, {"Save Mesh", FL_META+FL_SHIFT+'s', (Fl_Callback *)mesh_save_cb, 0},