Salome HOME
Fix compilation with gcc 4.7
[tools/libbatch.git] / src / Core / Batch_BatchManager_eClient.cxx
index c0a8ae44c965b6102def2f81dfbf15c1e1fc9339..835b5956f8b27e910a4c4ef452fe1e6be60b6ca4 100644 (file)
@@ -1,4 +1,4 @@
-//  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
+//  Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
 //
 //  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
 *
 */
 
-#include "Batch_BatchManager_eClient.hxx"
-#include "Batch_RunTimeException.hxx"
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
 
+#include <ctime>
 #include <iostream>
 #include <fstream>
 #include <sstream>
 
+#include <stdlib.h>
+
 #ifdef WIN32
 #include <direct.h>
+#include <io.h>
 #endif
 
-#include "Batch_config.h"
+#include <Batch_config.h>
+
+#include "Batch_Constants.hxx"
+#include "Batch_BatchManager_eClient.hxx"
+#include "Batch_RunTimeException.hxx"
+
+#ifdef MSVC
+#define EXISTS(path) _access_s(path, 0) == 0
+#else
+#define EXISTS(path) access(path, F_OK) == 0
+#endif
 
 using namespace std;
 
@@ -48,8 +63,10 @@ using namespace std;
 namespace Batch {
 
   BatchManager_eClient::BatchManager_eClient(const Batch::FactBatchManager * parent, const char* host,
-                                             const char* protocol, const char* mpiImpl)
-    : BatchManager(parent, host), _protocol(protocol), _username("")
+                                             const char * username,
+                                             CommunicationProtocolType protocolType, const char* mpiImpl)
+    : BatchManager(parent, host), _protocol(CommunicationProtocol::getInstance(protocolType)),
+      _username(username)
   {
     // instanciation of mpi implementation needed to launch executable in batch script
     _mpiImpl = FactoryMpiImpl(mpiImpl);
@@ -58,43 +75,18 @@ namespace Batch {
   // Destructeur
   BatchManager_eClient::~BatchManager_eClient()
   {
-    // Nothing to do
-    delete _mpiImpl;
+    if (_mpiImpl)
+      delete _mpiImpl;
   }
 
   void BatchManager_eClient::exportInputFiles(const Job& job)
   {
     int status;
     Parametre params = job.getParametre();
-    Versatile V = params[INFILE];
-    Versatile::iterator Vit;
-    _username = string(params[USER]);
-
-    string command = "\"";
-    string copy_command = "\"";
-
-    // Test protocol
-    if( _protocol == "rsh" ) {
-      command += RSH;
-      copy_command += RCP;
-    } else if( _protocol == "ssh" ) {
-      command += SSH;
-      copy_command += SCP;
-    } else
-      throw EmulationException("Unknown protocol : only rsh and ssh are known !");
-
-    command += "\" ";
-    copy_command += "\" ";
-
-    // First step : creating batch tmp files directory
-    if(_username != ""){
-      command += _username + "@";
-    }
-    command += _hostname;
-    command += " mkdir -p ";
-    command += string(params[TMPDIR]);
-    cerr << command.c_str() << endl;
-    status = system(command.c_str());
+    const Versatile & V = params[INFILE];
+    Versatile::const_iterator Vit;
+
+    status = _protocol.makeDirectory(string(params[TMPDIR]) + "/logs", _hostname, _username);
     if(status) {
       std::ostringstream oss;
       oss << status;
@@ -106,19 +98,9 @@ namespace Batch {
     // Second step : copy fileToExecute into
     // batch tmp files directory
     string executeFile = params[EXECUTABLE];
-    if( executeFile.size() > 0 ){
-      command = copy_command;
-      command += string(params[EXECUTABLE]);
-      command += " ";
-      if(_username != ""){
-        command += _username;
-        command += "@";
-      }
-      command += _hostname;
-      command += ":";
-      command += string(params[TMPDIR]);
-      cerr << command.c_str() << endl;
-      status = system(command.c_str());
+    if (executeFile.size() != 0) {
+      status = _protocol.copyFile(executeFile, "", "",
+                                  params[TMPDIR], _hostname, _username);
       if(status) {
         std::ostringstream oss;
         oss << status;
@@ -128,23 +110,11 @@ namespace Batch {
       }
 
 #ifdef WIN32
-      // On Windows, we make the remote file executable afterward because pscp does not preserve
-      // access permissions on files
-      command = "\"";
-      if( _protocol == "rsh" ) {
-        command += RSH;
-      } else if( _protocol == "ssh" ) {
-        command += SSH;
-      } else
-        throw EmulationException("Unknown protocol : only rsh and ssh are known !");
-
-      command += "\" ";
-      if(_username != ""){
-        command += _username + "@";
-      }
-      command += _hostname;
-      command += " chmod u+x ";
-      command += string(params[TMPDIR]) + "/" + string(params[EXECUTABLE]);
+      // On Windows, we make the remote file executable afterward because
+      // pscp does not preserve access permissions on files
+      string subCommand = string("chmod u+x ") + string(params[TMPDIR]) + "/" +
+                          string(params[EXECUTABLE]);
+      string command = _protocol.getExecCommand(subCommand, _hostname, _username);
       cerr << command.c_str() << endl;
       status = system(command.c_str());
       if(status) {
@@ -162,18 +132,8 @@ namespace Batch {
     for(Vit=V.begin(); Vit!=V.end(); Vit++) {
       CoupleType cpt  = *static_cast< CoupleType * >(*Vit);
       Couple inputFile = cpt;
-      command = copy_command;
-      command += inputFile.getLocal();
-      command += " ";
-      if(_username != ""){
-        command += _username;
-        command += "@";
-      }
-      command += _hostname;
-      command += ":";
-      command += inputFile.getRemote();
-      cerr << command.c_str() << endl;
-      status = system(command.c_str());
+      status = _protocol.copyFile(inputFile.getLocal(), "", "",
+                                  inputFile.getRemote(), _hostname, _username);
       if(status) {
         std::ostringstream oss;
         oss << status;
@@ -185,43 +145,28 @@ namespace Batch {
 
   }
 
-  void BatchManager_eClient::importOutputFiles( const Job & job, const string directory ) throw(EmulationException)
+  void BatchManager_eClient::importOutputFiles( const Job & job, const string directory )
   {
-    int status;
-
     Parametre params = job.getParametre();
-    Versatile V = params[OUTFILE];
-    Versatile::iterator Vit;
+    const Versatile & V = params[OUTFILE];
+    Versatile::const_iterator Vit;
+
+    // Create local result directory
+    int status = CommunicationProtocol::getInstance(SH).makeDirectory(directory, "", "");
+    if (status) {
+      string mess("Directory creation failed. Status is :");
+      ostringstream status_str;
+      status_str << status;
+      mess += status_str.str();
+      cerr << mess << endl;
+    }
 
     for(Vit=V.begin(); Vit!=V.end(); Vit++) {
       CoupleType cpt  = *static_cast< CoupleType * >(*Vit);
       Couple outputFile = cpt;
-
-      string command = "\"";
-
-      // Test protocol
-      if( _protocol == "rsh" ) {
-        command += RCP;
-      } else if( _protocol == "ssh" ) {
-        command += SCP;
-      } else
-        throw EmulationException("Unknown protocol : only rsh and ssh are known !");
-
-      command += "\" ";
-
-      if (_username != ""){
-        command += _username;
-        command += "@";
-      }
-      command += _hostname;
-      command += ":";
-      command += outputFile.getRemote();
-      command += " ";
-      command += directory;
-      cerr << command.c_str() << endl;
-      status = system(command.c_str());
-      if(status)
-      {
+      status = _protocol.copyFile(outputFile.getRemote(), _hostname, _username,
+                                  directory, "", "");
+      if (status) {
         // Try to get what we can (logs files)
         // throw BatchException("Error of connection on remote host");
         std::string mess("Copy command failed ! status is :");
@@ -232,9 +177,50 @@ namespace Batch {
       }
     }
 
+    // Copy logs
+    status = _protocol.copyFile(string(params[TMPDIR]) + string("/logs"), _hostname, _username,
+                                directory, "", "");
+    if (status) {
+      std::string mess("Copy logs directory failed ! status is :");
+      ostringstream status_str;
+      status_str << status;
+      mess += status_str.str();
+      cerr << mess << endl;
+    }
+
+  }
+
+  bool BatchManager_eClient::importDumpStateFile( const Job & job, const string directory )
+  {
+    Parametre params = job.getParametre();
+
+    // Create local result directory
+    int status = CommunicationProtocol::getInstance(SH).makeDirectory(directory, "", "");
+    if (status) {
+      string mess("Directory creation failed. Status is :");
+      ostringstream status_str;
+      status_str << status;
+      mess += status_str.str();
+      cerr << mess << endl;
+    }
+
+    bool ret = true;
+    status = _protocol.copyFile(string(params[TMPDIR]) + string("/dumpState*.xml"), _hostname, _username,
+                                directory, "", "");
+    if (status) {
+      // Try to get what we can (logs files)
+      // throw BatchException("Error of connection on remote host");
+      std::string mess("Copy command failed ! status is :");
+      ostringstream status_str;
+      status_str << status;
+      mess += status_str.str();
+      cerr << mess << endl;
+      ret = false;
+    }
+    return ret;
   }
 
-  MpiImpl *BatchManager_eClient::FactoryMpiImpl(string mpiImpl) throw(EmulationException)
+  MpiImpl *BatchManager_eClient::FactoryMpiImpl(string mpiImpl)
   {
     if(mpiImpl == "lam")
       return new MpiImpl_LAM();
@@ -249,7 +235,7 @@ namespace Batch {
     else if(mpiImpl == "prun")
       return new MpiImpl_PRUN();
     else if(mpiImpl == "nompi")
-      throw EmulationException("you must specify an mpi implementation for batch manager");
+      return NULL;
     else{
       ostringstream oss;
       oss << mpiImpl << " : not yet implemented";
@@ -273,7 +259,7 @@ namespace Batch {
     do {
       sprintf(randstr, "%06d", rand() % 1000000);
       fileName.replace(fileName.size()-6, 6, randstr);
-    } while (access(fileName.c_str(), F_OK) == 0);
+    } while (EXISTS(fileName.c_str()));
 
     return fileName;
   }
@@ -296,19 +282,23 @@ namespace Batch {
 #ifdef WIN32
 
     string fileName = generateTemporaryFileName(prefix);
-    outputStream.open(fileName.c_str());
+    // Open the file as binary to avoid problems with Windows newlines
+    outputStream.open(fileName.c_str(), ios_base::binary | ios_base::out);
 
 #else
 
     string fileName = getTmpDir() + "/" + prefix + "-XXXXXX";
-    char buf[fileName.size()+1];
+    char * buf = new char[fileName.size()+1];
     fileName.copy(buf, fileName.size());
     buf[fileName.size()] = '\0';
 
     int fd = mkstemp(buf);
-    if (fd == -1)
+    if (fd == -1) {
+      delete[] buf;
       throw RunTimeException(string("Can't create temporary file ") + fileName);
+    }
     fileName = buf;
+    delete[] buf;
 
     outputStream.open(fileName.c_str());
     close(fd);  // Close the file descriptor so that the file is not opened twice
@@ -335,13 +325,13 @@ namespace Batch {
   const std::string & BatchManager_eClient::getTmpDir()
   {
     if (tmpDirName.empty()) {
-      char * baseDir = getenv("TEMP");
+      const char * baseDir = getenv("TEMP");
       if (baseDir == NULL) baseDir = getenv("TMP");
       if (baseDir == NULL) baseDir = getenv("TEMPDIR");
       if (baseDir == NULL) baseDir = getenv("TMPDIR");
       if (baseDir == NULL) baseDir = "/tmp";
 
-      char * userName = getenv("USER");
+      const char * userName = getenv("USER");
       if (userName == NULL) userName = getenv("USERNAME");
       if (userName == NULL) userName = "unknown";
 
@@ -354,19 +344,22 @@ namespace Batch {
       do {
         sprintf(randstr, "%06d", rand() % 1000000);
         baseName.replace(baseName.size()-6, 6, randstr);
-      } while (access(baseName.c_str(), F_OK) == 0);
+      } while (EXISTS(baseName.c_str()));
       if (_mkdir(baseName.c_str()) != 0)
         throw RunTimeException(string("Can't create temporary directory ") + baseName);
       tmpDirName = baseName;
 
 #else
 
-      char buf[baseName.size()+1];
+      char * buf = new char[baseName.size() + 1];
       baseName.copy(buf, baseName.size());
       buf[baseName.size()] = '\0';
-      if (mkdtemp(buf) == NULL)
+      if (mkdtemp(buf) == NULL) {
+        delete[] buf;
         throw RunTimeException(string("Can't create temporary directory ") + baseName);
+      }
       tmpDirName = buf;
+      delete[] buf;
 
 #endif