diff --git a/Common/Gmsh.cpp b/Common/Gmsh.cpp index 38af13f28624f90d62529125bb75e6026e691994..c676b9732fce2e08207c377ebc5249cb7551934c 100644 --- a/Common/Gmsh.cpp +++ b/Common/Gmsh.cpp @@ -16,7 +16,7 @@ #include "CommandLine.h" #include "OS.h" #include "Context.h" -#include "ConnectionManager.h" +#include "onelab.h" #include "robustPredicates.h" #if defined(HAVE_MESH) @@ -252,8 +252,9 @@ int GmshFLTK(int argc, char **argv) // listen to external solvers if(CTX::instance()->solver.listen){ - ConnectionManager::get(-1)->name = "unknown"; - ConnectionManager::get(-1)->run(""); + onelab::localNetworkClient *c = new onelab::localNetworkClient("Listen", ""); + onelab::server::instance()->registerClient(c); + c->run(""); } // loop diff --git a/Common/onelab.h b/Common/onelab.h index 42ac105f3e5abd0c0e6e6ed5ef0edfdeac6aea9c..0f6e353ee7bdbd1f694bcea889c55da966254a01 100644 --- a/Common/onelab.h +++ b/Common/onelab.h @@ -449,10 +449,14 @@ namespace onelab{ protected: // the name of the client std::string _name; + // the id of the client, used to create a unique socket for this client + int _id; public: client(const std::string &name) : _name(name){} virtual ~client(){} std::string getName(){ return _name; } + void setId(int id){ _id = id; } + int getId(){ return _id; } virtual bool run(const std::string &what){ return false; } virtual bool isNetworkClient(){ return false; } virtual bool kill(){ return false; } @@ -507,6 +511,7 @@ namespace onelab{ { if(_clients.count(c->getName())) return false; _clients[c->getName()] = c; + c->setId(_clients.size()); return true; } typedef std::map<std::string, client*>::iterator citer; @@ -569,15 +574,19 @@ namespace onelab{ std::string _commandLine; // pid of the remote network client int _pid; + // underlying GmshServer + GmshServer *_gmshServer; public: localNetworkClient(const std::string &name, const std::string &commandLine) - : localClient(name), _commandLine(commandLine), _pid(-1) {} + : localClient(name), _commandLine(commandLine), _pid(-1), _gmshServer(0) {} virtual ~localNetworkClient(){} virtual bool isNetworkClient(){ return true; } const std::string &getCommandLine(){ return _commandLine; } void setCommandLine(const std::string &s){ _commandLine = s; } int getPid(){ return _pid; } void setPid(int pid){ _pid = pid; } + GmshServer const *getServer(){ return _gmshServer; } + void setServer(GmshServer *server){ _gmshServer = server; } virtual bool run(const std::string &what); virtual bool kill(); }; diff --git a/Fltk/onelabWindow.cpp b/Fltk/onelabWindow.cpp index a955597dc10c25c8e710449175178afabf2466e9..c06db6bac0bd66c320d4f32c5495bc14b348bfa8 100644 --- a/Fltk/onelabWindow.cpp +++ b/Fltk/onelabWindow.cpp @@ -46,8 +46,9 @@ class onelabGmshServer : public GmshServer{ if(timeout > 0 && GetTimeInSeconds() - start > timeout) return 2; // timout - if(_client->getPid() < 0) - return 1; // process has been killed + if(_client->getPid() < 0 || + (_client->getCommandLine().empty() && !CTX::instance()->solver.listen)) + return 1; // process has been killed or we stopped listening // check if there is data (call select with a zero timeout to // return immediately, i.e., do polling) @@ -64,6 +65,7 @@ class onelabGmshServer : public GmshServer{ else{ // an error happened _client->setPid(-1); + _client->setServer(0); return 1; } } @@ -72,29 +74,38 @@ class onelabGmshServer : public GmshServer{ bool onelab::localNetworkClient::run(const std::string &what) { + new_connection: _pid = 0; + _gmshServer = 0; + onelabGmshServer *server = new onelabGmshServer(this); - + std::string sockname; + std::ostringstream tmp; if(!strstr(CTX::instance()->solver.socketName.c_str(), ":")){ // Unix socket - std::ostringstream tmp; - tmp << CTX::instance()->homeDir << CTX::instance()->solver.socketName; + tmp << CTX::instance()->homeDir << CTX::instance()->solver.socketName << getId(); sockname = FixWindowsPath(tmp.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; + if(CTX::instance()->solver.socketName.size() && + CTX::instance()->solver.socketName[0] == ':') + tmp << GetHostName(); // prepend hostname if only port is given + tmp << CTX::instance()->solver.socketName << getId(); + sockname = tmp.str(); } - std::string prog = FixWindowsPath(_commandLine); - std::string command = prog + " " + what + " -onelab " + sockname; + std::string command = FixWindowsPath(_commandLine); + if(command.size()){ + command += " " + what + " -onelab " + sockname; #if !defined(WIN32) - command += " &"; + command += " &"; #endif + } + else{ + Msg::Info("Listening on socket '%s'", sockname.c_str()); + } int sock; try{ @@ -116,10 +127,15 @@ bool onelab::localNetworkClient::run(const std::string &what) while(1) { - if(_pid < 0) break; + if(_pid < 0 || (command.empty() && !CTX::instance()->solver.listen)) + break; int stop = server->NonBlockingWait(sock, 0.1, 0.); - if(stop || _pid < 0) break; + + if(stop || _pid < 0 || (command.empty() && !CTX::instance()->solver.listen)) + break; + + double timer = GetTimeInSeconds(); int type, length, swap; if(!server->ReceiveHeader(&type, &length, &swap)){ @@ -136,9 +152,11 @@ bool onelab::localNetworkClient::run(const std::string &what) switch (type) { case GmshSocket::GMSH_START: _pid = atoi(message.c_str()); + _gmshServer = server; break; case GmshSocket::GMSH_STOP: _pid = -1; + _gmshServer = 0; break; case GmshSocket::GMSH_PARAMETER: { @@ -215,7 +233,11 @@ bool onelab::localNetworkClient::run(const std::string &what) ParseString(message); drawContext::global()->draw(); break; - /* FIXME need to change PViewDataRemote to work without ConnectionManager + case GmshSocket::GMSH_SPEED_TEST: + Msg::Info("got %d Mb message in %g seconds", + length / 1024 / 1024, GetTimeInSeconds() - timer); + break; + /* FIXME PViewDataRemote should store the onelab::localNetworkClient case GmshSocket::GMSH_VERTEX_ARRAY: { int n = PView::list.size(); @@ -233,10 +255,17 @@ bool onelab::localNetworkClient::run(const std::string &what) FlGui::instance()->check(); } + _gmshServer = 0; server->Shutdown(); delete server; Msg::StatusBar(2, true, "Done running '%s'", _name.c_str()); + + if(command.empty()){ + Msg::Info("Client disconnected: starting new connection"); + goto new_connection; + } + return true; } @@ -336,7 +365,10 @@ void onelab_cb(Fl_Widget *w, void *data) for(onelab::server::citer it = onelab::server::instance()->firstClient(); it != onelab::server::instance()->lastClient(); it++){ onelab::client *c = it->second; - if(c->getName() == "Gmsh") continue; + if(c->getName() == "Gmsh" || // local Gmsh client + c->getName() == "Listen" || // unknown client connecting through "-listen" + c->getName() == "GmshRemote") // distant post-processing Gmsh client + continue; std::string what = FlGui::instance()->onelab->getModelName(); if(action == "initial check" || action == "check"){ c->run(what); @@ -609,4 +641,3 @@ void solver_cb(Fl_Widget *w, void *data) } #endif - diff --git a/utils/solvers/c++/GmshSocket.h b/utils/solvers/c++/GmshSocket.h index 0f67ad37b67730c14ba55b37f8efcd904a5d25ef..fbabdb473c0a91d661519225529da6923e670964 100644 --- a/utils/solvers/c++/GmshSocket.h +++ b/utils/solvers/c++/GmshSocket.h @@ -61,21 +61,23 @@ class GmshSocket{ // receive data from a machine with a different byte ordering, and // we swap the bytes in the payload) enum MessageType{ - GMSH_START = 1, - GMSH_STOP = 2, - GMSH_INFO = 10, - GMSH_WARNING = 11, - GMSH_ERROR = 12, - GMSH_PROGRESS = 13, - GMSH_MERGE_FILE = 20, - GMSH_PARSE_STRING = 21, - GMSH_VERTEX_ARRAY = 22, - GMSH_SPEED_TEST = 30, - GMSH_OPTION_1 = 100, - GMSH_OPTION_2 = 101, - GMSH_OPTION_3 = 102, - GMSH_OPTION_4 = 103, - GMSH_OPTION_5 = 104}; + GMSH_START = 1, + GMSH_STOP = 2, + GMSH_INFO = 10, + GMSH_WARNING = 11, + GMSH_ERROR = 12, + GMSH_PROGRESS = 13, + GMSH_MERGE_FILE = 20, + GMSH_PARSE_STRING = 21, + GMSH_VERTEX_ARRAY = 22, + GMSH_PARAMETER = 23, + GMSH_PARAMETER_QUERY = 24, + GMSH_SPEED_TEST = 30, + GMSH_OPTION_1 = 100, + GMSH_OPTION_2 = 101, + GMSH_OPTION_3 = 102, + GMSH_OPTION_4 = 103, + GMSH_OPTION_5 = 104}; protected: // the socket descriptor int _sock; @@ -204,6 +206,11 @@ class GmshSocket{ } return 0; } + int ReceiveMessage(int len, void *buffer) + { + if(_ReceiveData(buffer, len) == len) return 1; + return 0; + } // str should be allocated with size (len+1) int ReceiveString(int len, char *str) { @@ -365,7 +372,7 @@ class GmshServer : public GmshSocket{ } if(command && strlen(command)){ - SystemCall(command); // Start the solver + SystemCall(command); // start the solver } else{ timeout = 0.; // no command launched: don't set a timeout diff --git a/utils/solvers/c++/interactive.cpp b/utils/solvers/c++/interactive.cpp index ed55291257d97b1e339202f61461a5d83b211015..b42ee0136fbcc2cf357dd1ac4f4b515c2139fc2d 100644 --- a/utils/solvers/c++/interactive.cpp +++ b/utils/solvers/c++/interactive.cpp @@ -25,7 +25,7 @@ class GmshInteractiveClient{ _client.Stop(); _client.Disconnect(); } - void read(char *prompt) + void read(const char *prompt) { // pre-load a few commands in the history: add_history("lc = 1.;");