diff --git a/utils/solvers/c++/GmshSocket.h b/utils/solvers/c++/GmshSocket.h index 312d160a188ac9876705409101a0c2d5465be6bc..d32bc63e1188e176f43e0cde0811f5d5e9dad33b 100644 --- a/utils/solvers/c++/GmshSocket.h +++ b/utils/solvers/c++/GmshSocket.h @@ -82,6 +82,7 @@ class GmshSocket{ GMSH_PARAMETER_CLEAR = 31, GMSH_PARAMETER_UPDATE = 32, GMSH_OPEN_PROJECT = 33, + GMSH_CLIENT_CHANGED = 34, GMSH_OPTION_1 = 100, GMSH_OPTION_2 = 101, GMSH_OPTION_3 = 102, @@ -323,11 +324,11 @@ class GmshServer : public GmshSocket{ public: GmshServer() : GmshSocket(), _portno(-1) {} virtual ~GmshServer(){} - virtual int NonBlockingSystemCall(const char *str) = 0; + virtual int NonBlockingSystemCall(const char *exe, const char *args) = 0; virtual int NonBlockingWait(double waitint, double timeout, int socket=-1) = 0; - // start the client by launching "command" (command is supposed to contain + // start the client by launching "exe args" (args is supposed to contain // '%s' where the socket name should appear) - int Start(const char *command, const char *sockname, double timeout) + int Start(const char *exe, const char *args, const char *sockname, double timeout) { if(!sockname) throw "Invalid (null) socket name"; _sockname = sockname; @@ -392,10 +393,10 @@ class GmshServer : public GmshSocket{ } } - if(command && strlen(command)){ - char cmd[1024]; - sprintf(cmd, command, _sockname.c_str()); - NonBlockingSystemCall(cmd); // starts the solver + if((exe && strlen(exe)) || (args && strlen(args))){ + char s[1024]; + sprintf(s, args, _sockname.c_str()); + NonBlockingSystemCall(exe, s); // starts the solver } else{ timeout = 0.; // no command launched: don't set a timeout diff --git a/utils/solvers/c++/onelab.h b/utils/solvers/c++/onelab.h index 615b4da960f4f404d6e48efdd441fd346b1d21bf..fafc38a39c52457f06a5e7c5d8233b9274f5f988 100644 --- a/utils/solvers/c++/onelab.h +++ b/utils/solvers/c++/onelab.h @@ -38,10 +38,19 @@ #include <sstream> #include "GmshSocket.h" +#ifdef HAVE_ONELAB2 +#include "NetworkUtils.h" +#include "OnelabAttributes.h" +#endif + namespace onelab{ // The base parameter class. - class parameter{ +#ifdef HAVE_ONELAB2 + class parameter : public OnelabAttr{ +#else + class parameter { +#endif private: // the name of the parameter, including its '/'-separated path in the // parameter hierarchy. Parameters or subpaths can start with numbers to @@ -292,6 +301,86 @@ namespace onelab{ } return true; } +#ifdef HAVE_ONELAB2 + static UInt16 attributeType() {return 0x05;} + virtual inline UInt16 getAttributeType() const {return this->attributeType();} + virtual inline UInt16 getAttributeLength() const { + UInt16 len = _name.length()+_label.length()+_help.length()+10; + for(std::map<std::string, bool>::const_iterator it = getClients().begin(); it != getClients().end(); it++) + len += it->first.size()+2; + for(std::map<std::string, std::string>::const_iterator it = _attributes.begin(); it != _attributes.end(); it++) + len += it->first.size()+it->second.size()+2; + return len; + } + virtual UInt8 *encodeAttribute(UInt8 *dst) + { + dst = encode(dst, getAttributeType()); + dst = encode(dst, getAttributeLength()); + + dst = encode(dst, (UInt8 *)_name.c_str(), this->_name.length()+1); + dst = encode(dst, (UInt8 *)_label.c_str(), this->_label.length()+1); + dst = encode(dst, (UInt8 *)_help.c_str(), this->_help.length()+1); + dst = encode(dst, (UInt8)_readOnly); + dst = encode(dst, (UInt8)_neverChanged); + dst = encode(dst, (UInt8)_visible); + + dst = encode(dst, (UInt16)_attributes.size()); + for(std::map<std::string, std::string>::const_iterator it = _attributes.begin(); it != _attributes.end(); it++) { + dst = encode(dst, (UInt8 *)it->first.c_str(), it->first.size()+1); + dst = encode(dst, (UInt8 *)it->second.c_str(), it->second.size()+1); + } + + dst = encode(dst, (UInt16)_clients.size()); + for(std::map<std::string, bool>::const_iterator it = getClients().begin(); it != getClients().end(); it++) { + dst = encode(dst, (UInt8 *)it->first.c_str(), it->first.size()+1); + dst = encode(dst, (UInt8)it->second); + } + + return dst; + } + virtual UInt8 *parseAttribute(UInt8 *src, UInt32 length) + { + UInt8 tmp; + UInt16 n; + + src = parse(src, _name, '\0'); + src = parse(src, _label, '\0'); + src = parse(src, _help, '\0'); + src = parse(src, tmp); + this->_readOnly = (bool)tmp; + src = parse(src, tmp); + this->_neverChanged = (bool)tmp; + src = parse(src, tmp); + this->_visible = (bool)tmp; + + src = parse(src, n); + for(int i=0; i<n; i++) { + std::string key, value; + src = parse(src, key, '\0'); + src = parse(src, value, '\0'); + setAttribute(key, value); + } + + src = parse(src, n); + for(int i=0; i<n; i++) { + std::string client; + src = parse(src, client, '\0'); + src = parse(src, tmp); + addClient(client, (bool)tmp); + } + + return src; + } + void showAttribute() const + { + std::cout << "Name: " << getName() << std::endl + << "Label: " << getLabel() << std::endl + << "Help: " << getHelp() << std::endl + << "Never changed: " << getNeverChanged() << std::endl + << "Changed: " << getChanged() << std::endl + << "Visible: " << getVisible() << std::endl; + } +#endif }; class parameterLessThan{ @@ -412,6 +501,73 @@ namespace onelab{ } return pos; } +#ifdef HAVE_ONELAB2 + static UInt16 attributeType() {return 0x06;} + virtual inline UInt16 getAttributeType() const {return this->attributeType();} + virtual inline UInt16 getAttributeLength() const { + UInt16 len = parameter::getAttributeLength()+sizeof(double)*4+8+sizeof(double)*_choices.size(); + for(std::map<double, std::string>::const_iterator it = _valueLabels.begin(); it != _valueLabels.end(); it++) + len += it->second.size()+1+sizeof(double); + return len; + } + UInt8 *encodeAttribute(UInt8 *dst) + { + dst = parameter::encodeAttribute(dst); + + dst = encode(dst, _value); + dst = encode(dst, _min); + dst = encode(dst, _max); + dst = encode(dst, _step); + dst = encode(dst, (UInt32)_index); + + dst = encode(dst, (UInt16)_choices.size()); + for(unsigned int i = 0; i < _choices.size(); i++) + dst = encode(dst, _choices[i]); + + dst = encode(dst, (UInt16)_valueLabels.size()); + for(std::map<double, std::string>::const_iterator it = _valueLabels.begin(); it != _valueLabels.end(); it++) { + dst = encode(dst, it->first); + dst = encode(dst, (UInt8 *)it->second.c_str(), it->second.size()+1); + } + + return dst; + } + UInt8 *parseAttribute(UInt8 *src, UInt32 length) + { + UInt16 n; + + src = parameter::parseAttribute(src, length); + + src = parse(src, _value); + src = parse(src, _min); + src = parse(src, _max); + src = parse(src, _step); + src = parse(src, *(UInt32 *)&_index); + + src = parse(src, n); + _choices.resize(n); + for(unsigned int i = 0; i < n; i++) + src = parse(src, _choices[i]); + + src = parse(src, n); + for(int i=0; i<n; i++) { + double value; + std::string label; + src = parse(src, value); + src = parse(src, label, '\0'); + setValueLabel(value, label); + } + + return src; + } + void showAttribute() const + { + parameter::showAttribute(); + std::cout << "Value: " << this->_value << std::endl + << "Min: " << this->_min << std::endl + << "Max: " << this->_max << std::endl; + } +#endif }; // The string class. A string has a mutable "kind": we do not derive @@ -476,6 +632,51 @@ namespace onelab{ _choices[i] = getNextToken(msg, pos); return pos; } +#ifdef HAVE_ONELAB2 + static UInt16 attributeType() {return 0x07;} + virtual inline UInt16 getAttributeType() const {return this->attributeType();} + virtual inline UInt16 getAttributeLength() const + { + UInt16 len = parameter::getAttributeLength(); + len += _value.size()+_kind.size()+4; + for(unsigned int i = 0; i < _choices.size(); i++) + len += _choices[i].size()+1; + return len; + } + UInt8 *encodeAttribute(UInt8 *dst) + { + dst = parameter::encodeAttribute(dst); + + dst = encode(dst, (UInt8 *)_value.c_str(), _value.size()+1); + dst = encode(dst, (UInt8 *)_kind.c_str(), _kind.size()+1); + + dst = encode(dst, (UInt16)_choices.size()); + for(unsigned int i = 0; i < _choices.size(); i++) + dst = encode(dst, (UInt8 *)_choices[i].c_str(), _choices[i].size()+1); + + return dst; + } + UInt8 *parseAttribute(UInt8 *src, UInt32 length) + { + UInt16 n; + src = parameter::parseAttribute(src, length); + src = parse(src, _value, '\0'); + src = parse(src, _kind, '\0'); + + src = parse(src, n); + _choices.resize(n); + for(unsigned int i=0; i<n; i++) { + src = parse(src, _choices[i], '\0'); + } + + return src; + } + void showAttribute() const + { + parameter::showAttribute(); + std::cout << "Value: " << this->_value << std::endl; + } +#endif }; // The region class. A region can be any kind of geometrical entity, @@ -558,6 +759,63 @@ namespace onelab{ } return pos; } +#ifdef HAVE_ONELAB2 + static UInt16 attributeType() {return 0x08;} + virtual inline UInt16 getAttributeType() const {return this->attributeType();} + virtual inline UInt16 getAttributeLength() const { + UInt16 len = parameter::getAttributeLength(); + len += 2; + for(std::set<std::string>::const_iterator it = _value.begin(); it != _value.end(); it++) + len += it->size()+1; + len += 4; + len += 2; + for(unsigned int i = 0; i < _choices.size(); i++){ + len += 2; + for(std::set<std::string>::const_iterator it = _choices[i].begin(); it != _choices[i].end(); it++) + len += it->size()+1; + } + return len; + } + UInt8 *encodeAttribute(UInt8 *dst) + { + dst = parameter::encodeAttribute(dst); + dst = encode(dst, (UInt16)this->_value.size()); + for(std::set<std::string>::const_iterator it = _value.begin(); it != _value.end(); it++) + dst = encode(dst, (UInt8 *)it->c_str(), it->size()+1); + dst = encode(dst, (UInt32)_dimension); + dst = encode(dst, (UInt16)_choices.size()); + for(unsigned int i = 0; i < _choices.size(); i++){ + dst = encode(dst, (UInt16)_choices[i].size()); + for(std::set<std::string>::const_iterator it = _choices[i].begin(); it != _choices[i].end(); it++) + dst = encode(dst, (UInt8 *)it->c_str(), it->size()+1); + } + return dst; + } + UInt8 *parseAttribute(UInt8 *src, UInt32 len) + { + src = parameter::parseAttribute(src, len); + UInt16 m = 0, n = 0; + std::string value; + src = parse(src, n); + for(int i=0; i<n; i++) { + src = parse(src, value, '\0'); + _value.insert(value); + } + src = parse(src, *(UInt32 *)&_dimension); + src = parse(src, n); + _choices.resize(n); + for(int i=0; i<n; i++) { + src = parse(src, m); + for(int j=0; j<m; j++) { + src = parse(src, value, '\0'); + _choices[i].insert(value); + } + } + return src; + } + void showAttribute() const {} +#endif + }; // The (possibly piece-wise defined on regions) function class. Functions are @@ -642,6 +900,69 @@ namespace onelab{ } return pos; } +#ifdef HAVE_ONELAB2 + static UInt16 attributeType() {return 0x09;} + virtual inline UInt16 getAttributeType() const {return this->attributeType();} + virtual inline UInt16 getAttributeLength() const { + UInt16 len = parameter::getAttributeLength(); + len += 2; + for(std::map<std::string, std::string>::const_iterator it = _value.begin(); + it != _value.end(); it++) + len += 2+it->first.size()+it->second.size(); + for(unsigned int i = 0; i < _choices.size(); i++){ + len += 2; + for(std::map<std::string, std::string>::const_iterator it = _choices[i].begin(); + it != _choices[i].end(); it++) { + len += 2+it->first.size()+it->second.size(); + } + } + return len; + } + UInt8 *encodeAttribute(UInt8 *dst) + { + dst = parameter::encodeAttribute(dst), + dst = encode(dst, (UInt16)this->_value.size()); + for(std::map<std::string, std::string>::const_iterator it = _value.begin(); + it != _value.end(); it++) { + dst = encode(dst, (UInt8 *)it->first.c_str(), it->first.size()+1); + dst = encode(dst, (UInt8 *)it->second.c_str(), it->second.size()+1); + } + dst = encode(dst, (UInt16)_choices.size()); + for(unsigned int i = 0; i < _choices.size(); i++){ + dst = encode(dst, (UInt16)_choices[i].size()); + for(std::map<std::string, std::string>::const_iterator it = _choices[i].begin(); + it != _choices[i].end(); it++) { + dst = encode(dst, (UInt8 *)it->first.c_str(), it->first.size()+1); + dst = encode(dst, (UInt8 *)it->second.c_str(), it->second.size()+1); + } + } + return dst; + } + UInt8 *parseAttribute(UInt8 *src, UInt32 len) + { + src = parameter::parseAttribute(src, len); + UInt16 m = 0, n = 0; + std::string key, value; + src = parse(src, n); + for(int i=0; i<n; i++) { + src = parse(src, key, '\0'); + src = parse(src, value, '\0'); + _value[key] = value; + } + src = parse(src, n); + _choices.resize(n); + for(int i=0; i<n; i++) { + src = parse(src, m); + for(int j=0; j<m; j++) { + src = parse(src, key, '\0'); + src = parse(src, value, '\0'); + _choices[i][key] = value; + } + } + return src; + } + void showAttribute() const {} +#endif }; // The parameter space, i.e., the set of parameters stored and handled by the @@ -695,6 +1016,9 @@ namespace onelab{ } else{ T* newp = new T(p); +#ifdef HAVE_ONELAB2 + newp->isInDatabase(true); +#endif if(client.size()) newp->addClient(client, true); ps.insert(newp); } @@ -724,6 +1048,16 @@ namespace onelab{ } return true; } + template <class T> T* _getPtr(std::string name, const std::string client, std::set<T*, parameterLessThan> ps) + { + T tmp(name); + typename std::set<T*, parameterLessThan>::iterator it = ps.find(&tmp); + if(it != ps.end()){ + if(client.size()) (*it)->addClient(client, true); + return *it; + } + return NULL; + } void _getAllParameters(std::set<parameter*, parameterLessThan> &ps) const { ps.insert(_numbers.begin(), _numbers.end()); @@ -770,6 +1104,21 @@ namespace onelab{ const std::string &client=""){ return _get(ps, name, client, _regions); } bool get(std::vector<function> &ps, const std::string &name="", const std::string &client=""){ return _get(ps, name, client, _functions); } + void getPtr(number **ptr, const std::string name, const std::string client="") + {*ptr = _getPtr(name, client, _numbers);} + void getPtr(string **ptr, const std::string name, const std::string client="") + {*ptr = _getPtr(name, client, _strings);} + void getPtr(region **ptr, const std::string name, const std::string client="") + {*ptr = _getPtr(name, client, _regions);} + void getPtr(function **ptr, const std::string name, const std::string client="") + {*ptr = _getPtr(name, client, _functions);} + void getAllParameters(std::set<parameter*, parameterLessThan> &ps) const + { + ps.insert(_numbers.begin(), _numbers.end()); + ps.insert(_strings.begin(), _strings.end()); + ps.insert(_regions.begin(), _regions.end()); + ps.insert(_functions.begin(), _functions.end()); + } unsigned int getNumParameters() { return (int)(_numbers.size() + _strings.size() + _regions.size() + _functions.size()); @@ -798,7 +1147,7 @@ namespace onelab{ } return false; } - // set the changed flag for all the parameters that depend on the give + // set the changed flag for all the parameters that depend on the given // client (or for all parameters if no client name is provided) void setChanged(bool changed, const std::string &client="") { @@ -935,7 +1284,6 @@ namespace onelab{ return false; } }; - // The onelab server: a singleton that stores the parameter space and // interacts with onelab clients. class server{ @@ -989,6 +1337,10 @@ namespace onelab{ { return _parameterSpace.getChanged(client); } + bool isRegistered(const std::string &client) + { + return _clients.count(client); + } unsigned int getNumParameters(){ return _parameterSpace.getNumParameters(); } std::vector<std::string> toChar(const std::string &client="") { @@ -1057,6 +1409,10 @@ namespace onelab{ private: // executable of the client (including filesystem path, if necessary) std::string _executable; + // treat the executable name as a full command line (will prevent the + // escaping of the exe name, and will assume that the command line has been + // correcly escaped) + bool _treatExecutableAsFullCommandLine; // command to login to a remote host (if necessary) std::string _remoteLogin; // command line option to specify socket @@ -1067,14 +1423,21 @@ namespace onelab{ GmshServer *_gmshServer; public: localNetworkClient(const std::string &name, const std::string &executable, - const std::string &remoteLogin="") - : localClient(name), _executable(executable), _remoteLogin(remoteLogin), - _socketSwitch("-onelab"), _pid(-1), _gmshServer(0) {} + const std::string &remoteLogin="", + bool treatExecutableAsFullCommandLine=false) + : localClient(name), _executable(executable), + _treatExecutableAsFullCommandLine(treatExecutableAsFullCommandLine), + _remoteLogin(remoteLogin), _socketSwitch("-onelab"), _pid(-1), + _gmshServer(0) {} virtual ~localNetworkClient(){} virtual bool isNetworkClient(){ return true; } const std::string &getExecutable(){ return _executable; } void setExecutable(const std::string &s){ _executable = s; } const std::string &getRemoteLogin(){ return _remoteLogin; } + const bool treatExecutableAsFullCommandLine() + { + return _treatExecutableAsFullCommandLine; + } void setRemoteLogin(const std::string &s){ _remoteLogin = s; } const std::string &getSocketSwitch(){ return _socketSwitch; } void setSocketSwitch(const std::string &s){ _socketSwitch = s; }