From ea5dc8622278b247ec54f916d1ff58c71610b040 Mon Sep 17 00:00:00 2001 From: barate Date: Thu, 30 Apr 2009 08:38:10 +0000 Subject: [PATCH] Added Windows implementation for local submission based on sh and rsh (partial and experimental support) --- src/Local/Batch_BatchManager_Local.cxx | 212 ++++++++++++++++----- src/Local/Batch_BatchManager_Local.hxx | 38 ++-- src/Local/Batch_BatchManager_Local_RSH.cxx | 53 ++++-- src/Local/Batch_BatchManager_Local_RSH.hxx | 21 +- src/Local/Batch_BatchManager_Local_SH.cxx | 29 ++- src/Local/Batch_BatchManager_Local_SH.hxx | 17 +- src/Local/Batch_BatchManager_Local_SSH.cxx | 11 +- src/Local/Batch_BatchManager_Local_SSH.hxx | 21 +- src/Local/Test/CMakeLists.txt | 5 + src/Local/Test/Test_Local_RSH.cxx | 3 +- src/Local/Test/Test_Local_SH.cxx | 4 +- src/Local/Test/Test_Local_config.h.in | 3 + src/Python/Test/Test_Python_Local_SH.py | 2 +- 13 files changed, 307 insertions(+), 112 deletions(-) diff --git a/src/Local/Batch_BatchManager_Local.cxx b/src/Local/Batch_BatchManager_Local.cxx index 3b726d6..77241a9 100644 --- a/src/Local/Batch_BatchManager_Local.cxx +++ b/src/Local/Batch_BatchManager_Local.cxx @@ -38,6 +38,7 @@ #include #ifdef WIN32 # include +#include "Batch_RunTimeException.hxx" #else # include # include @@ -56,10 +57,10 @@ namespace Batch { // Constructeur - BatchManager_Local::BatchManager_Local(const FactBatchManager * parent, const char * host) throw(InvalidArgumentException,ConnexionFailureException) : BatchManager(parent, host), _connect(0), _threads_mutex(), _threads(), _thread_id_id_association_mutex(), _thread_id_id_association_cond() -#ifndef WIN32 //TODO: porting of following functionality - ,_thread_id_id_association() -#endif + BatchManager_Local::BatchManager_Local(const FactBatchManager * parent, const char * host) + throw(InvalidArgumentException,ConnexionFailureException) + : BatchManager(parent, host), _connect(0), _threads_mutex(), _threads(), _thread_id_id_association_mutex(), + _thread_id_id_association_cond(), _thread_id_id_association() { pthread_mutex_init(&_threads_mutex, NULL); pthread_mutex_init(&_thread_id_id_association_mutex, NULL); @@ -268,17 +269,22 @@ namespace Batch { // Retourne l'Id enregistre dans l'association Thread_id / Id et le detruit immediatement BatchManager_Local::Id BatchManager_Local::getIdByThread_id(pthread_t thread_id) { - Id id = -1; - // @@@ --------> SECTION CRITIQUE <-------- @@@ pthread_mutex_lock(&_thread_id_id_association_mutex); -#ifndef WIN32 //TODO: porting of following functionality - while (_thread_id_id_association.find(thread_id) == _thread_id_id_association.end()) - pthread_cond_wait(&_thread_id_id_association_cond, &_thread_id_id_association_mutex); + bool threadIdFound = false; + std::list::iterator it; + while (!threadIdFound) { + for (it = _thread_id_id_association.begin() ; + it != _thread_id_id_association.end() && !pthread_equal(it->threadId, thread_id) ; + it++); + if (it == _thread_id_id_association.end()) + pthread_cond_wait(&_thread_id_id_association_cond, &_thread_id_id_association_mutex); + else + threadIdFound = true; + } - id = _thread_id_id_association[thread_id]; - _thread_id_id_association.erase(thread_id); -#endif + Id id = it->id; + _thread_id_id_association.erase(it); pthread_mutex_unlock(&_thread_id_id_association_mutex); // @@@ --------> SECTION CRITIQUE <-------- @@@ @@ -295,15 +301,20 @@ namespace Batch { // @@@ --------> SECTION CRITIQUE <-------- @@@ pthread_mutex_lock(&_thread_id_id_association_mutex); -#ifndef WIN32 //TODO: porting of following functionality - if (_thread_id_id_association.find(thread_id) == _thread_id_id_association.end()) { - id = _thread_id_id_association[thread_id] = nextId(); + std::list::iterator it; + for (it = _thread_id_id_association.begin() ; + it != _thread_id_id_association.end() && !pthread_equal(it->threadId, thread_id) ; + it++); + if (it == _thread_id_id_association.end()) { + struct ThreadIdIdAssociation newAssociation; + id = newAssociation.id = nextId(); + newAssociation.threadId = thread_id; + _thread_id_id_association.push_back(newAssociation); pthread_cond_signal(&_thread_id_id_association_cond); } else { UNDER_LOCK( cerr << "ERROR : Pthread Inconstency. Two threads own the same thread_id." << endl ); } -#endif pthread_mutex_unlock(&_thread_id_id_association_mutex); // @@@ --------> SECTION CRITIQUE <-------- @@@ @@ -324,11 +335,12 @@ namespace Batch { // Methode d'execution du thread void * BatchManager_Local::ThreadAdapter::run(void * arg) { -#ifndef WIN32 //TODO: porting of following functionality +#ifndef WIN32 // On bloque tous les signaux pour ce thread sigset_t setmask; sigfillset(&setmask); pthread_sigmask(SIG_BLOCK, &setmask, NULL); +#endif // On autorise la terminaison differee du thread // (ces valeurs sont les valeurs par defaut mais on les force par precaution) @@ -338,7 +350,7 @@ namespace Batch { // On enregistre la fonction de suppression du fils en cas d'arret du thread // Cette fontion sera automatiquement appelee lorsqu'une demande d'annulation // sera prise en compte par pthread_testcancel() - pid_t child; + Process child; pthread_cleanup_push(BatchManager_Local::kill_child_on_exit, static_cast (&child)); pthread_cleanup_push(BatchManager_Local::delete_on_exit, arg); @@ -376,6 +388,10 @@ namespace Batch { } string executionhost = string(param[EXECUTIONHOST]); + string user; + if ( (it = param.find(USER)) != param.end() ) { + user = string(it->second); + } if ( (it = param.find(INFILE)) != param.end() ) { Versatile V = (*it).second; @@ -387,8 +403,12 @@ namespace Batch { string local = cp.getLocal(); string remote = cp.getRemote(); - string copy_cmd = p_ta->getBatchManager().copy_command("", local, executionhost, workdir + "/" + remote); + string copy_cmd = p_ta->getBatchManager().copy_command("", "", local, user, + executionhost, workdir + "/" + remote); UNDER_LOCK( cout << "Copying : " << copy_cmd << endl ); +#ifdef WIN32 + copy_cmd = string("\"") + copy_cmd + string("\""); +#endif if (system(copy_cmd.c_str()) ) { // Echec de la copie @@ -404,13 +424,13 @@ namespace Batch { -#ifdef WIN32 - //TODO - //Using CreateThread instead fork() POSIX function -#else // On forke/exec un nouveau process pour pouvoir controler le fils // (plus finement qu'avec un appel system) // int rc = system(commande.c_str()); +#ifdef WIN32 + child = p_ta->launchWin32ChildProcess(); + p_ta->pere(child); +#else child = fork(); if (child < 0) { // erreur UNDER_LOCK( cerr << "Fork impossible (rc=" << child << ")" << endl ); @@ -424,7 +444,6 @@ namespace Batch { #endif - // On copie les fichiers de sortie du fils if ( (it = param.find(OUTFILE)) != param.end() ) { Versatile V = (*it).second; @@ -436,8 +455,12 @@ namespace Batch { string local = cp.getLocal(); string remote = cp.getRemote(); - string copy_cmd = p_ta->getBatchManager().copy_command(executionhost, workdir + "/" + remote, "", local); + string copy_cmd = p_ta->getBatchManager().copy_command(user, executionhost, workdir + "/" + remote, + "", "", local); UNDER_LOCK( cout << "Copying : " << copy_cmd << endl ); +#ifdef WIN32 + copy_cmd = string("\"") + copy_cmd + string("\""); +#endif if (system(copy_cmd.c_str()) ) { // Echec de la copie @@ -455,8 +478,11 @@ namespace Batch { if ( (rc == 0) || (child < 0) ) { std::vector::const_iterator it; for(it=files_to_delete.begin(); it!=files_to_delete.end(); it++) { - string remove_cmd = p_ta->getBatchManager().remove_command(executionhost, *it); + string remove_cmd = p_ta->getBatchManager().remove_command(user, executionhost, *it); UNDER_LOCK( cout << "Removing : " << remove_cmd << endl ); +#ifdef WIN32 + remove_cmd = string("\"") + remove_cmd + string("\""); +#endif system(remove_cmd.c_str()); } } @@ -476,16 +502,14 @@ namespace Batch { UNDER_LOCK( cout << "Father is leaving" << endl ); pthread_exit(NULL); -#endif return NULL; } - void BatchManager_Local::ThreadAdapter::pere(pid_t child) + void BatchManager_Local::ThreadAdapter::pere(Process child) { -#ifndef WIN32 //TODO: porting of following functionality time_t child_starttime = time(NULL); // On enregistre le fils dans la table des threads @@ -499,12 +523,16 @@ namespace Batch { thread_id_sst << id; param[ID] = thread_id_sst.str(); param[STATE] = "Running"; +#ifndef WIN32 param[PID] = child; +#endif // @@@ --------> SECTION CRITIQUE <-------- @@@ pthread_mutex_lock(&_bm._threads_mutex); _bm._threads[id].thread_id = thread_id; +#ifndef WIN32 _bm._threads[id].pid = child; +#endif _bm._threads[id].status = RUNNING; _bm._threads[id].param = param; _bm._threads[id].env = env; @@ -515,9 +543,21 @@ namespace Batch { - // on boucle en attendant que le fils ait termine while (1) { +#ifdef WIN32 + DWORD exitCode; + BOOL res = GetExitCodeProcess(child, &exitCode); + if (exitCode != STILL_ACTIVE) { + pthread_mutex_lock(&_bm._threads_mutex); + _bm._threads[id].status = DONE; + _bm._threads[id].param[STATE] = "Done"; + pthread_mutex_unlock(&_bm._threads_mutex); + // @@@ --------> SECTION CRITIQUE <-------- @@@ + UNDER_LOCK( cout << "Father sees his child is DONE: exit code = " << exitCode << endl ); + break; + } +#else int child_rc = 0; pid_t child_wait_rc = waitpid(child, &child_rc, WNOHANG /* | WUNTRACED */); if (child_wait_rc > 0) { @@ -560,8 +600,7 @@ namespace Batch { UNDER_LOCK( cout << "Father sees his child is DEAD : " << child_wait_rc << " (Reason : " << strerror(errno) << ")" << endl ); break; } - - +#endif // On teste si le thread doit etre detruit pthread_testcancel(); @@ -615,7 +654,7 @@ namespace Batch { case NOP: UNDER_LOCK( cout << "Father does nothing to his child" << endl ); break; - +#ifndef WIN32 case HOLD: UNDER_LOCK( cout << "Father is sending SIGSTOP signal to his child" << endl ); kill(child, SIGSTOP); @@ -635,7 +674,7 @@ namespace Batch { UNDER_LOCK( cout << "Father is sending SIGKILL signal to his child" << endl ); kill(child, SIGKILL); break; - +#endif case ALTER: break; @@ -649,34 +688,27 @@ namespace Batch { // @@@ --------> SECTION CRITIQUE <-------- @@@ // On fait une petite pause pour ne pas surcharger inutilement le processeur +#ifdef WIN32 + Sleep(1000); +#else sleep(1); - - } #endif + } } +#ifndef WIN32 void BatchManager_Local::ThreadAdapter::fils() { -#ifndef WIN32 //TODO: porting of following functionality Parametre param = _job.getParametre(); Parametre::iterator it; try { - // On se place dans le repertoire de travail - if ( (it = param.find(WORKDIR)) != param.end() ) { - string workdir = static_cast( (*it).second ); - chdir(workdir.c_str()); - } - - - - // EXECUTABLE is MANDATORY, if missing, we exit with failure notification char * execpath = NULL; if (param.find(EXECUTABLE) != param.end()) { @@ -718,9 +750,11 @@ namespace Batch { + // Create the environment for the new process. Note (RB): Here we change the environment for + // the process launched in local. It would seem more logical to set the environment for the + // remote process. Environnement env = _job.getEnvironnement(); - char ** envp = NULL; if(env.size() > 0) { envp = new char * [env.size() + 1]; // 1 pour le NULL terminal @@ -795,10 +829,92 @@ namespace Batch { } exit(99); -#endif } +#else + + BatchManager_Local::Process BatchManager_Local::ThreadAdapter::launchWin32ChildProcess() + { + Parametre param = _job.getParametre(); + Parametre::iterator it; + PROCESS_INFORMATION pi; + + try { + + // EXECUTABLE is MANDATORY, if missing, we throw an exception + string exec_command; + if (param.find(EXECUTABLE) != param.end()) { + exec_command = _bm.exec_command(param); + } else { + throw RunTimeException("Parameter \"EXECUTABLE\" is mandatory for local batch submission"); + } + + string name = (param.find(NAME) != param.end()) ? param[NAME] : param[EXECUTABLE]; + + if (param.find(ARGUMENTS) != param.end()) { + Versatile V = param[ARGUMENTS]; + + for(Versatile::const_iterator it=V.begin() ; it!=V.end() ; it++) { + StringType argt = * static_cast(*it); + exec_command += string(" ") + string(argt); + } + } + + UNDER_LOCK( cout << "*** exec_command = " << exec_command << endl ); + + + // Create the environment for the new process. Note (RB): Here we change the environment for + // the process launched in local. It would seem more logical to set the environment for the + // remote process. + // Note that if no environment is specified, we reuse the current environment. + Environnement env = _job.getEnvironnement(); + char * chNewEnv = NULL; + + if(env.size() > 0) { + chNewEnv = new char[4096]; + LPTSTR lpszCurrentVariable = chNewEnv; + for(Environnement::const_iterator it=env.begin() ; it!=env.end() ; it++) { + const string & key = (*it).first; + const string & value = (*it).second; + string envvar = key + "=" + value; + envvar.copy(lpszCurrentVariable, envvar.size()); + lpszCurrentVariable[envvar.size()] = '\0'; + lpszCurrentVariable += lstrlen(lpszCurrentVariable) + 1; + } + // Terminate the block with a NULL byte. + *lpszCurrentVariable = '\0'; + } + + + STARTUPINFO si; + ZeroMemory( &si, sizeof(si) ); + si.cb = sizeof(si); + ZeroMemory( &pi, sizeof(pi) ); + + // Copy the command to a non-const buffer + size_t str_size = exec_command.size(); + char buffer[str_size+1]; + exec_command.copy(buffer,str_size); + buffer[str_size]='\0'; + + // launch the new process + BOOL res = CreateProcess(NULL, buffer, NULL, NULL, FALSE, + 0, chNewEnv, NULL, &si, &pi); + + if (!res) throw RunTimeException("Error while creating new process"); + + CloseHandle(pi.hThread); + + } catch (GenericException & e) { + + std::cerr << "Caught exception : " << e.type << " : " << e.message << std::endl; + } + + return pi.hProcess; + } + +#endif void BatchManager_Local::kill_child_on_exit(void * p_pid) diff --git a/src/Local/Batch_BatchManager_Local.hxx b/src/Local/Batch_BatchManager_Local.hxx index 33f9dfa..a7e70de 100644 --- a/src/Local/Batch_BatchManager_Local.hxx +++ b/src/Local/Batch_BatchManager_Local.hxx @@ -34,7 +34,7 @@ #include "Batch_Defines.hxx" -#include +#include #include #include #include @@ -56,6 +56,11 @@ namespace Batch { class BATCH_EXPORT BatchManager_Local : public BatchManager { private: +#ifdef WIN32 + typedef HANDLE Process; +#else + typedef pid_t Process; +#endif friend class ThreadAdapter; class ThreadAdapter{ public: @@ -68,8 +73,12 @@ namespace Batch { const Job_Local _job; private: - void pere(pid_t child); + void pere(Process child); +#ifndef WIN32 void fils(); +#else + Process launchWin32ChildProcess(); +#endif }; @@ -133,19 +142,27 @@ namespace Batch { std::map _threads; // Methode abstraite qui renvoie la commande de copie du fichier source en destination - virtual std::string copy_command( const std::string & host_source, - const std::string & source, - const std::string & host_destination, - const std::string & destination) const = 0; + virtual std::string copy_command( const std::string & user_source, + const std::string & host_source, + const std::string & source, + const std::string & user_destination, + const std::string & host_destination, + const std::string & destination) const = 0; // Methode abstraite qui renvoie la commande a executer virtual std::string exec_command(Parametre & param) const = 0; // Methode abstraite qui renvoie la commande d'effacement du fichier - virtual std::string remove_command( const std::string & host_destination, - const std::string & destination) const = 0; + virtual std::string remove_command( const std::string & user_destination, + const std::string & host_destination, + const std::string & destination) const = 0; private: + struct ThreadIdIdAssociation { + pthread_t threadId; + Id id; + }; + virtual pthread_t submit(const Job_Local & job); virtual void cancel(pthread_t thread_id); static void kill_child_on_exit(void * p_pid); @@ -155,10 +172,7 @@ namespace Batch { Id registerThread_id(pthread_t thread_id); pthread_mutex_t _thread_id_id_association_mutex; pthread_cond_t _thread_id_id_association_cond; -#ifndef WIN32 //TODO: porting of following functionality - //reason: pthread_t on win32 is a struct of pointer and int members - std::map _thread_id_id_association; -#endif + std::list _thread_id_id_association; #ifdef SWIG public: diff --git a/src/Local/Batch_BatchManager_Local_RSH.cxx b/src/Local/Batch_BatchManager_Local_RSH.cxx index 56c6e45..54cae55 100644 --- a/src/Local/Batch_BatchManager_Local_RSH.cxx +++ b/src/Local/Batch_BatchManager_Local_RSH.cxx @@ -52,10 +52,6 @@ #include "Batch_config.h" -#ifndef RM -#error "RM undefined. You must set RM to a valid path to a rm-like command." -#endif - #ifndef RCP #error "RCP undefined. You must set RCP to a valid path to a rcp-like command." #endif @@ -81,22 +77,43 @@ namespace Batch { // Methode abstraite qui renvoie la commande de copie du fichier source en destination - string BatchManager_Local_RSH::copy_command(const string & host_source, const string & source, const string & host_destination, const string & destination) const + string BatchManager_Local_RSH::copy_command(const std::string & user_source, + const std::string & host_source, + const std::string & source, + const std::string & user_destination, + const std::string & host_destination, + const std::string & destination) const { ostringstream fullsource; if (host_source.size() != 0) { - fullsource << host_source << ":"; + if (user_source.size() != 0) { +#ifdef WIN32 + fullsource << host_source << "." << user_source << ":"; +#else + fullsource << user_source << "@" << host_source << ":"; +#endif + } else { + fullsource << host_source << ":"; + } } fullsource << source; ostringstream fulldestination; if (host_destination.size() != 0) { - fulldestination << host_destination << ":"; + if (user_destination.size() != 0) { +#ifdef WIN32 + fulldestination << host_destination << "." << user_destination << ":"; +#else + fulldestination << user_destination << "@" << host_destination << ":"; +#endif + } else { + fulldestination << host_destination << ":"; + } } fulldestination << destination; ostringstream copy_cmd; - copy_cmd << RCP << " " << fullsource.str() << " " << fulldestination.str(); + copy_cmd << "\"" << RCP << "\" " << fullsource.str() << " " << fulldestination.str(); return copy_cmd.str(); } @@ -104,8 +121,7 @@ namespace Batch { string BatchManager_Local_RSH::exec_command(Parametre & param) const { ostringstream exec_sub_cmd; - exec_sub_cmd << "cd " << param[WORKDIR] << ";"; - exec_sub_cmd << param[EXECUTABLE]; + exec_sub_cmd << "cd " << param[WORKDIR] << " && " << param[EXECUTABLE]; if (param.find(ARGUMENTS) != param.end()) { Versatile V = param[ARGUMENTS]; @@ -139,12 +155,23 @@ namespace Batch { } // Methode qui renvoie la commande d'effacement du fichier - string BatchManager_Local_RSH::remove_command(const string & host_destination, const string & destination) const + string BatchManager_Local_RSH::remove_command(const std::string & user_destination, + const std::string & host_destination, + const std::string & destination) const { - string host = (host_destination.size()) ? host_destination : "localhost:"; + string fulldestination = (host_destination.size()) ? host_destination : "localhost"; + if (user_destination.size() != 0) { + fulldestination += " -l " + user_destination; + } + // We consider here that the remote system is UNIX-like and has a "rm" command. Using the + // RM macro would be pointless here since the remote system is different from the local one. ostringstream remove_cmd; - remove_cmd << RSH << " " << host << " \"" << RM << " " << destination << "\""; + remove_cmd << "\"" << RSH << "\" " << fulldestination; +#ifdef WIN32 + remove_cmd << " -n"; +#endif + remove_cmd << " rm " << destination; return remove_cmd.str(); } } diff --git a/src/Local/Batch_BatchManager_Local_RSH.hxx b/src/Local/Batch_BatchManager_Local_RSH.hxx index c5c6604..235e3d8 100644 --- a/src/Local/Batch_BatchManager_Local_RSH.hxx +++ b/src/Local/Batch_BatchManager_Local_RSH.hxx @@ -20,7 +20,7 @@ // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // /* - * BatchManager_Local_RSH.hxx : + * BatchManager_Local_RSH.hxx : * * Auteur : Ivan DUTKA-MALEN - EDF R&D * Mail : mailto:ivan.dutka-malen@der.edf.fr @@ -62,18 +62,21 @@ namespace Batch { virtual ~BatchManager_Local_RSH(); protected: - // Methode abstraite qui renvoie la commande de copie du fichier source en destination - virtual std::string copy_command( const std::string & host_source, - const std::string & source, - const std::string & host_destination, - const std::string & destination) const; + // Methode qui renvoie la commande de copie du fichier source en destination + virtual std::string copy_command( const std::string & user_source, + const std::string & host_source, + const std::string & source, + const std::string & user_destination, + const std::string & host_destination, + const std::string & destination) const; - // Methode abstraite qui renvoie la commande a executer + // Methode qui renvoie la commande a executer virtual std::string exec_command(Parametre & param) const; // Methode qui renvoie la commande d'effacement du fichier - virtual std::string remove_command( const std::string & host_destination, - const std::string & destination) const; + virtual std::string remove_command( const std::string & user_destination, + const std::string & host_destination, + const std::string & destination) const; }; diff --git a/src/Local/Batch_BatchManager_Local_SH.cxx b/src/Local/Batch_BatchManager_Local_SH.cxx index c71847b..db4e9cc 100644 --- a/src/Local/Batch_BatchManager_Local_SH.cxx +++ b/src/Local/Batch_BatchManager_Local_SH.cxx @@ -81,10 +81,15 @@ namespace Batch { // Methode qui renvoie la commande de copie du fichier source en destination - string BatchManager_Local_SH::copy_command(const string & host_source, const string & source, const string & host_destination, const string & destination) const + string BatchManager_Local_SH::copy_command(const std::string & user_source, + const std::string & host_source, + const std::string & source, + const std::string & user_destination, + const std::string & host_destination, + const std::string & destination) const { ostringstream copy_cmd; - copy_cmd << CP << " " << source << " " << destination; + copy_cmd << "\"" << CP << "\" \"" << source << "\" \"" << destination << "\""; return copy_cmd.str(); } @@ -92,16 +97,22 @@ namespace Batch { string BatchManager_Local_SH::exec_command(Parametre & param) const { ostringstream exec_sub_cmd; - exec_sub_cmd << param[EXECUTABLE]; +#ifdef WIN32 + exec_sub_cmd << "\""; +#endif + exec_sub_cmd << "cd " << param[WORKDIR] << " && " << param[EXECUTABLE]; if (param.find(ARGUMENTS) != param.end()) { Versatile V = param[ARGUMENTS]; for(Versatile::const_iterator it=V.begin(); it!=V.end(); it++) { - StringType argt = * static_cast(*it); - string arg = argt; - exec_sub_cmd << " " << arg; + StringType argt = * static_cast(*it); + string arg = argt; + exec_sub_cmd << " " << arg; } } +#ifdef WIN32 + exec_sub_cmd << "\""; +#endif param[ARGUMENTS] = "-c"; param[ARGUMENTS] += exec_sub_cmd.str(); @@ -110,10 +121,12 @@ namespace Batch { } // Methode qui renvoie la commande d'effacement du fichier - string BatchManager_Local_SH::remove_command(const string & host_destination, const string & destination) const + string BatchManager_Local_SH::remove_command(const std::string & user_destination, + const std::string & host_destination, + const std::string & destination) const { ostringstream remove_cmd; - remove_cmd << RM << " " << destination; + remove_cmd << "\"" << RM << "\" \"" << destination << "\""; return remove_cmd.str(); } diff --git a/src/Local/Batch_BatchManager_Local_SH.hxx b/src/Local/Batch_BatchManager_Local_SH.hxx index 23b5909..34c02ec 100644 --- a/src/Local/Batch_BatchManager_Local_SH.hxx +++ b/src/Local/Batch_BatchManager_Local_SH.hxx @@ -20,7 +20,7 @@ // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // /* - * BatchManager_Local_SH.hxx : + * BatchManager_Local_SH.hxx : * * Auteur : Ivan DUTKA-MALEN - EDF R&D * Mail : mailto:ivan.dutka-malen@der.edf.fr @@ -63,17 +63,20 @@ namespace Batch { protected: // Methode qui renvoie la commande de copie du fichier source en destination - virtual std::string copy_command( const std::string & host_source, - const std::string & source, - const std::string & host_destination, - const std::string & destination) const; + virtual std::string copy_command( const std::string & user_source, + const std::string & host_source, + const std::string & source, + const std::string & user_destination, + const std::string & host_destination, + const std::string & destination) const; // Methode qui renvoie la commande a executer virtual std::string exec_command(Parametre & param) const; // Methode qui renvoie la commande d'effacement du fichier - virtual std::string remove_command( const std::string & host_destination, - const std::string & destination) const; + virtual std::string remove_command( const std::string & user_destination, + const std::string & host_destination, + const std::string & destination) const; }; diff --git a/src/Local/Batch_BatchManager_Local_SSH.cxx b/src/Local/Batch_BatchManager_Local_SSH.cxx index 70b0d9e..f829d60 100644 --- a/src/Local/Batch_BatchManager_Local_SSH.cxx +++ b/src/Local/Batch_BatchManager_Local_SSH.cxx @@ -82,7 +82,12 @@ namespace Batch { // Methode abstraite qui renvoie la commande de copie du fichier source en destination - string BatchManager_Local_SSH::copy_command(const string & host_source, const string & source, const string & host_destination, const string & destination) const + string BatchManager_Local_SSH::copy_command(const std::string & user_source, + const std::string & host_source, + const std::string & source, + const std::string & user_destination, + const std::string & host_destination, + const std::string & destination) const { ostringstream fullsource; if (host_source.size() != 0) { @@ -142,7 +147,9 @@ namespace Batch { } // Methode qui renvoie la commande d'effacement du fichier - string BatchManager_Local_SSH::remove_command(const string & host_destination, const string & destination) const + string BatchManager_Local_SSH::remove_command(const std::string & user_destination, + const std::string & host_destination, + const std::string & destination) const { string host = (host_destination.size()) ? host_destination : "localhost:"; diff --git a/src/Local/Batch_BatchManager_Local_SSH.hxx b/src/Local/Batch_BatchManager_Local_SSH.hxx index 12772fb..c5afaae 100644 --- a/src/Local/Batch_BatchManager_Local_SSH.hxx +++ b/src/Local/Batch_BatchManager_Local_SSH.hxx @@ -20,7 +20,7 @@ // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // /* - * BatchManager_Local_SSH.hxx : + * BatchManager_Local_SSH.hxx : * * Auteur : Ivan DUTKA-MALEN - EDF R&D * Mail : mailto:ivan.dutka-malen@der.edf.fr @@ -62,18 +62,21 @@ namespace Batch { virtual ~BatchManager_Local_SSH(); protected: - // Methode abstraite qui renvoie la commande de copie du fichier source en destination - virtual std::string copy_command( const std::string & host_source, - const std::string & source, - const std::string & host_destination, - const std::string & destination) const; + // Methode qui renvoie la commande de copie du fichier source en destination + virtual std::string copy_command( const std::string & user_source, + const std::string & host_source, + const std::string & source, + const std::string & user_destination, + const std::string & host_destination, + const std::string & destination) const; - // Methode abstraite qui renvoie la commande a executer + // Methode qui renvoie la commande a executer virtual std::string exec_command(Parametre & param) const; // Methode qui renvoie la commande d'effacement du fichier - virtual std::string remove_command( const std::string & host_destination, - const std::string & destination) const; + virtual std::string remove_command( const std::string & user_destination, + const std::string & host_destination, + const std::string & destination) const; }; diff --git a/src/Local/Test/CMakeLists.txt b/src/Local/Test/CMakeLists.txt index cc95e45..548a88e 100644 --- a/src/Local/Test/CMakeLists.txt +++ b/src/Local/Test/CMakeLists.txt @@ -21,8 +21,13 @@ # # Declare the configuration variables for the test scripts +SET (TEST_LOCAL_SH_WORK_DIR "/tmp" CACHE STRING + "Work directory for SH Batch test (only necessary for test target)") + SET (TEST_LOCAL_RSH_EXECUTION_HOST "localhost" CACHE STRING "Execution host for RSH Batch test (only necessary for test target)") +SET (TEST_LOCAL_RSH_USER $ENV{USER} CACHE STRING + "User name on the execution host for RSH Batch test (only necessary for test target)") SET (TEST_LOCAL_RSH_WORK_DIR "/tmp" CACHE STRING "Work directory for RSH Batch test (only necessary for test target)") diff --git a/src/Local/Test/Test_Local_RSH.cxx b/src/Local/Test/Test_Local_RSH.cxx index 5bd5c05..e5e2e4f 100644 --- a/src/Local/Test/Test_Local_RSH.cxx +++ b/src/Local/Test/Test_Local_RSH.cxx @@ -54,7 +54,7 @@ int main(int argc, char** argv) Job job; // ... and its parameters ... Parametre p; - p["EXECUTABLE"] = "./copied-test-script.sh"; + p["EXECUTABLE"] = "source copied-test-script.sh"; p["NAME"] = "Test_Local_RSH"; p["WORKDIR"] = TEST_LOCAL_RSH_WORK_DIR; p["INFILE"] = Couple("seta.sh", "copied-seta.sh"); @@ -62,6 +62,7 @@ int main(int argc, char** argv) p["INFILE"] += Couple("test-script.sh", "copied-test-script.sh"); p["OUTFILE"] = Couple("result.txt", "orig-result.txt"); p["EXECUTIONHOST"] = TEST_LOCAL_RSH_EXECUTION_HOST; + p["USER"] = TEST_LOCAL_RSH_USER; job.setParametre(p); // ... and its environment Environnement e; diff --git a/src/Local/Test/Test_Local_SH.cxx b/src/Local/Test/Test_Local_SH.cxx index 1df7923..2cdcea9 100644 --- a/src/Local/Test/Test_Local_SH.cxx +++ b/src/Local/Test/Test_Local_SH.cxx @@ -56,7 +56,7 @@ int main(int argc, char** argv) Parametre p; p["EXECUTABLE"] = "./copied-test-script.sh"; p["NAME"] = "Test_Local_SH"; - p["WORKDIR"] = "/tmp"; + p["WORKDIR"] = TEST_LOCAL_SH_WORK_DIR; p["INFILE"] = Couple("seta.sh", "copied-seta.sh"); p["INFILE"] += Couple("setb.sh", "copied-setb.sh"); p["INFILE"] += Couple("test-script.sh", "copied-test-script.sh"); @@ -80,7 +80,7 @@ int main(int argc, char** argv) // Wait for the end of the job string state = "Unknown"; - for (int i=0 ; i<10 && state != "Done" ; i++) { + for (int i=0 ; i<20 && state != "Done" ; i++) { usleep(100000); Versatile paramState = jobid.queryJob().getParametre()["STATE"]; state = (paramState.size() > 0) ? paramState.str() : "Unknown"; diff --git a/src/Local/Test/Test_Local_config.h.in b/src/Local/Test/Test_Local_config.h.in index 33da7f8..f584f72 100644 --- a/src/Local/Test/Test_Local_config.h.in +++ b/src/Local/Test/Test_Local_config.h.in @@ -20,7 +20,10 @@ // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // +#define TEST_LOCAL_SH_WORK_DIR "${TEST_LOCAL_SH_WORK_DIR}" + #define TEST_LOCAL_RSH_EXECUTION_HOST "${TEST_LOCAL_RSH_EXECUTION_HOST}" +#define TEST_LOCAL_RSH_USER "${TEST_LOCAL_RSH_USER}" #define TEST_LOCAL_RSH_WORK_DIR "${TEST_LOCAL_RSH_WORK_DIR}" #define TEST_LOCAL_SSH_EXECUTION_HOST "${TEST_LOCAL_SSH_EXECUTION_HOST}" diff --git a/src/Python/Test/Test_Python_Local_SH.py b/src/Python/Test/Test_Python_Local_SH.py index fddae1d..e5c2d0a 100644 --- a/src/Python/Test/Test_Python_Local_SH.py +++ b/src/Python/Test/Test_Python_Local_SH.py @@ -70,7 +70,7 @@ def work(): # Wait for the end of the job state = 'Unknown' i=0 - while state != 'Done' and i<10: + while state != 'Done' and i<20: time.sleep(0.1) i+=1 jinfo = jobid.queryJob() -- 2.39.2