Salome HOME
Base implementation of Notebook
[modules/kernel.git] / src / Launcher / Launcher.cxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 //  This library is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU Lesser General Public
8 //  License as published by the Free Software Foundation; either
9 //  version 2.1 of the License.
10 //
11 //  This library is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 //  Lesser General Public License for more details.
15 //
16 //  You should have received a copy of the GNU Lesser General Public
17 //  License along with this library; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 #ifdef WITH_LIBBATCH
24 #include <Batch/Batch_Date.hxx>
25 #include <Batch/Batch_FactBatchManager_eLSF.hxx>
26 #include <Batch/Batch_FactBatchManager_ePBS.hxx>
27 #include <Batch/Batch_BatchManager_eClient.hxx>
28 #include <Batch/Batch_FactBatchManager_eSGE.hxx>
29 #endif
30
31 #include "SALOME_Launcher_Handler.hxx"
32 #include "Launcher.hxx"
33 #include <iostream>
34 #include <sstream>
35 #include <sys/stat.h>
36 #include <time.h>
37
38 using namespace std;
39
40 //=============================================================================
41 /*! 
42  *  Constructor
43  *  \param orb
44  *  Define a CORBA single thread policy for the server, which avoid to deal
45  *  with non thread-safe usage like Change_Directory in SALOME naming service
46  */
47 //=============================================================================
48
49 Launcher_cpp::Launcher_cpp()
50 {
51 #if defined(_DEBUG_) || defined(_DEBUG)
52   cerr << "Launcher_cpp constructor" << endl;
53 #endif
54 }
55
56 //=============================================================================
57 /*! 
58  * destructor
59  */
60 //=============================================================================
61
62 Launcher_cpp::~Launcher_cpp()
63 {
64 #if defined(_DEBUG_) || defined(_DEBUG)
65   cerr << "Launcher_cpp destructor" << endl;
66 #endif
67
68 #ifdef WITH_LIBBATCH
69   std::map < string, Batch::BatchManager_eClient * >::const_iterator it1;
70   for(it1=_batchmap.begin();it1!=_batchmap.end();it1++)
71     delete it1->second;
72   std::map < std::pair<std::string,long> , Batch::Job* >::const_iterator it2;
73   for(it2=_jobmap.begin();it2!=_jobmap.end();it2++)
74     delete it2->second;
75 #endif
76 }
77
78 //=============================================================================
79 /*! CORBA Method:
80  *  Submit a batch job on a cluster and returns the JobId
81  *  \param xmlExecuteFile     : to define the execution on the batch cluster
82  *  \param clusterName        : name of the batch cluster
83  */
84 //=============================================================================
85 long Launcher_cpp::submitJob( const std::string xmlExecuteFile,
86                   const std::string clusterName) throw(LauncherException)
87 {
88 #ifdef WITH_LIBBATCH
89 #if defined(_DEBUG_) || defined(_DEBUG)
90   cout << "BEGIN OF Launcher_cpp::submitJob" << endl;
91 #endif
92   long jobId;
93   vector<string> aMachineList;
94
95   if(!_ResManager)
96     throw LauncherException("You must set Resources Manager to Launcher!!");
97
98   // verify if cluster is in resources catalog
99   machineParams params;
100   params.hostname = clusterName;
101   try{
102     aMachineList = _ResManager->GetFittingResources(params);
103   }
104   catch(const ResourcesException &ex){
105     throw LauncherException(ex.msg.c_str());
106   }
107   if (aMachineList.size() == 0)
108     throw LauncherException("This cluster is not in resources catalog");
109
110   // Parsing xml file
111   ParseXmlFile(xmlExecuteFile);
112
113   // verify if clustername is in xml file
114   map<std::string,MachineParameters>::const_iterator it1 = _launch.MachinesList.find(clusterName);
115   if(it1 == _launch.MachinesList.end())
116     throw LauncherException("This cluster is not in xml file");
117
118   ParserResourcesType p = _ResManager->GetResourcesList(aMachineList[0]);
119   string cname(p.Alias);
120 #if defined(_DEBUG_) || defined(_DEBUG)
121   cout << "Choose cluster: " <<  cname << endl;
122 #endif
123
124   // search batch manager for that cluster in map or instanciate one
125   map < string, Batch::BatchManager_eClient * >::const_iterator it2 = _batchmap.find(cname);
126   if(it2 == _batchmap.end())
127     {
128       _batchmap[cname] = FactoryBatchManager(p);
129       // TODO: Add a test for the cluster !
130     }
131     
132   try{
133
134     // directory on cluster to put files to execute
135     string remotedir = _launch.MachinesList[clusterName].WorkDirectory;
136     // local directory to get files to execute and to put results
137     string localdir = _launch.RefDirectory;
138
139     int idx1 = xmlExecuteFile.find_last_of("/");
140     if(idx1 == string::npos) idx1 = -1;
141     int idx2 = xmlExecuteFile.find(".xml");
142     string logfile = xmlExecuteFile.substr(idx1+1,idx2-idx1-1);
143     string ologfile = logfile + ".output.log";
144     string elogfile = logfile + ".error.log";
145
146     // create and submit job on cluster
147     Batch::Parametre param;
148     param[USER] = p.UserName;
149     param[EXECUTABLE] = "";
150     for(int i=0; i<_launch.InputFile.size();i++)
151       param[INFILE] += Batch::Couple( localdir + "/" + _launch.InputFile[i], remotedir + "/" + _launch.InputFile[i] );
152     for(int i=0; i<_launch.OutputFile.size();i++)
153       param[OUTFILE] += Batch::Couple( localdir + "/" + _launch.OutputFile[i], remotedir + "/" + _launch.OutputFile[i] );
154     param[OUTFILE] += Batch::Couple( localdir + "/" + ologfile, remotedir + "/" + ologfile );
155     param[OUTFILE] += Batch::Couple( localdir + "/" + elogfile, remotedir + "/" + elogfile );
156     param[NBPROC] = _launch.NbOfProcesses;
157     param[WORKDIR] = remotedir;
158     param[TMPDIR] = remotedir;
159     param[MAXWALLTIME] = getWallTime("");
160     param[MAXRAMSIZE] = getRamSize("");
161     param[HOMEDIR] = "";
162
163     Batch::Environnement env;
164     env["COMMAND"] = _launch.Command;
165     env["SOURCEFILE"] = _launch.MachinesList[clusterName].EnvFile;
166     env["LOGFILE"] = logfile;
167
168     Batch::Job* job = new Batch::Job(param,env);
169
170     // submit job on cluster
171     Batch::JobId jid = _batchmap[cname]->submitJob(*job);
172
173     // get job id in long
174     istringstream iss(jid.getReference());
175     iss >> jobId;
176
177     _jobmap[ pair<string,long>(cname,jobId) ] = job;
178   }
179   catch(const Batch::EmulationException &ex){
180     throw LauncherException(ex.message.c_str());
181   }
182
183   return jobId;
184 #else
185   throw LauncherException("Method Launcher_cpp::submitJob is not available "
186                           "(libBatch was not present at compilation time)");
187 #endif
188 }
189
190 //=============================================================================
191 /*! CORBA Method:
192  *  Submit a batch job on a cluster and returns the JobId
193  *  \param fileToExecute      : .py/.exe/.sh/... to execute on the batch cluster
194  *  \param filesToExport      : to export on the batch cluster
195  *  \param NumberOfProcessors : Number of processors needed on the batch cluster
196  *  \param params             : Constraints for the choice of the batch cluster
197  */
198 //=============================================================================
199 long Launcher_cpp::submitSalomeJob( const string fileToExecute ,
200                                     const vector<string>& filesToExport ,
201                                     const vector<string>& filesToImport ,
202                                     const batchParams& batch_params,
203                                     const machineParams& params) throw(LauncherException)
204 {
205 #ifdef WITH_LIBBATCH
206 #if defined(_DEBUG_) || defined(_DEBUG)
207   cerr << "BEGIN OF Launcher_cpp::submitSalomeJob" << endl;
208 #endif
209   long jobId;
210   vector<string> aMachineList;
211
212   if(!_ResManager)
213     throw LauncherException("You must set Resources Manager to Launcher!!");
214
215   // check batch params
216   if ( !check(batch_params) )
217     throw LauncherException("Batch parameters are bad (see informations above)");
218
219   // find a cluster matching the structure params
220   try{
221     aMachineList = _ResManager->GetFittingResources(params);
222   }
223   catch(const ResourcesException &ex){
224     throw LauncherException(ex.msg.c_str());
225   }
226   if (aMachineList.size() == 0)
227     throw LauncherException("No resources have been found with your parameters");
228
229   ParserResourcesType p = _ResManager->GetResourcesList(aMachineList[0]);
230   string clustername(p.Alias);
231 #if defined(_DEBUG_) || defined(_DEBUG)
232   cerr << "Choose cluster: " <<  clustername << endl;
233 #endif
234   
235   // search batch manager for that cluster in map or instanciate one
236   map < string, Batch::BatchManager_eClient * >::const_iterator it = _batchmap.find(clustername);
237   if(it == _batchmap.end())
238     {
239       _batchmap[clustername] = FactoryBatchManager(p);
240       // TODO: Add a test for the cluster !
241     }
242     
243   try{
244     // tmp directory on cluster to put files to execute
245     string tmpdir = getTmpDirForBatchFiles();
246
247     // create and submit job on cluster
248     Batch::Parametre param;
249     param[USER] = p.UserName;
250     param[EXECUTABLE] = buildSalomeCouplingScript(fileToExecute,tmpdir,p);
251     param[INFILE] = Batch::Couple( fileToExecute, getRemoteFile(tmpdir,fileToExecute) );
252     for(int i=0;i<filesToExport.size();i++)
253       param[INFILE] += Batch::Couple( filesToExport[i], getRemoteFile(tmpdir,filesToExport[i]) );
254
255     param[OUTFILE] = Batch::Couple( "", "~/" + tmpdir + "/" + "output.log*" );
256     param[OUTFILE] += Batch::Couple( "", "~/" + tmpdir + "/" + "error.log*" );
257     param[OUTFILE] += Batch::Couple( "", "~/" + tmpdir + "/" + "YACS_Server*" );
258     for(int i=0;i<filesToImport.size();i++)
259       param[OUTFILE] += Batch::Couple( "", "~/" + tmpdir + "/" + filesToImport[i] );
260
261     param[NBPROC] = batch_params.nb_proc;
262     param[WORKDIR] = batch_params.batch_directory;
263     param[TMPDIR] = tmpdir;
264     param[MAXWALLTIME] = getWallTime(batch_params.expected_during_time);
265     param[MAXRAMSIZE] = getRamSize(batch_params.mem);
266     param[HOMEDIR] = getHomeDir(p, tmpdir);
267     param[QUEUE] = p.batchQueue;
268
269     Batch::Environnement env;
270
271     Batch::Job* job = new Batch::Job(param,env);
272
273     // submit job on cluster
274     Batch::JobId jid = _batchmap[clustername]->submitJob(*job);
275
276     // get job id in long
277     istringstream iss(jid.getReference());
278     iss >> jobId;
279
280     _jobmap[ pair<string,long>(clustername,jobId) ] = job;    
281   }
282   catch(const Batch::EmulationException &ex){
283     throw LauncherException(ex.message.c_str());
284   }
285
286   return jobId;
287 #else
288   throw LauncherException("Method Launcher_cpp::submitSalomeJob is not available "
289                           "(libBatch was not present at compilation time)");
290 #endif
291 }
292
293 //=============================================================================
294 /*! CORBA Method:
295  *  Query a batch job on a cluster and returns the status of job
296  *  \param jobId              : identification of Salome job
297  *  \param params             : Constraints for the choice of the batch cluster
298  */
299 //=============================================================================
300 string Launcher_cpp::queryJob( long id, 
301                                const machineParams& params) throw(LauncherException)
302 {
303 #ifdef WITH_LIBBATCH
304   if(!_ResManager)
305     throw LauncherException("You must set Resources Manager to Launcher!!");
306
307   // find a cluster matching params structure
308   vector<string> aMachineList = _ResManager->GetFittingResources( params ) ;
309   ParserResourcesType p = _ResManager->GetResourcesList(aMachineList[0]);
310   string clustername(p.Alias);
311     
312   // search batch manager for that cluster in map
313   std::map < string, Batch::BatchManager_eClient * >::const_iterator it = _batchmap.find(clustername);
314   if(it == _batchmap.end())
315     throw LauncherException("no batchmanager for that cluster");
316     
317   Batch::Parametre par;
318   try{
319     ostringstream oss;
320     oss << id;
321     Batch::JobId jobId( _batchmap[clustername], oss.str() );
322
323     Batch::JobInfo jinfo = jobId.queryJob();
324     par = jinfo.getParametre();
325   }
326   catch(const Batch::EmulationException &ex){
327     throw LauncherException(ex.message.c_str());
328   }
329
330   return par[STATE];
331 #else
332   throw LauncherException("Method Launcher_cpp::queryJob is not available "
333                           "(libBatch was not present at compilation time)");
334 #endif
335 }
336
337 string Launcher_cpp::queryJob( long id, 
338                                const std::string clusterName) throw (LauncherException)
339 {
340   machineParams params;
341   params.hostname = clusterName;
342   return queryJob(id,params);
343 }
344
345 //=============================================================================
346 /*! CORBA Method:
347  *  Delete a batch job on a cluster 
348  *  \param jobId              : identification of Salome job
349  *  \param params             : Constraints for the choice of the batch cluster
350  */
351 //=============================================================================
352 void Launcher_cpp::deleteJob( const long id, 
353                               const machineParams& params) throw(LauncherException)
354 {
355 #ifdef WITH_LIBBATCH
356   if(!_ResManager)
357     throw LauncherException("You must set Resources Manager to Launcher!!");
358
359   // find a cluster matching params structure
360   vector<string> aMachineList = _ResManager->GetFittingResources( params ) ;
361   ParserResourcesType p = _ResManager->GetResourcesList(aMachineList[0]);
362   string clustername(p.Alias);
363     
364   // search batch manager for that cluster in map
365   map < string, Batch::BatchManager_eClient * >::const_iterator it = _batchmap.find(clustername);
366   if(it == _batchmap.end())
367     throw LauncherException("no batchmanager for that cluster");
368   
369   ostringstream oss;
370   oss << id;
371   Batch::JobId jobId( _batchmap[clustername], oss.str() );
372
373   jobId.deleteJob();
374 #else
375   throw LauncherException("Method Launcher_cpp::deleteJob is not available "
376                           "(libBatch was not present at compilation time)");
377 #endif
378 }
379
380 void Launcher_cpp::deleteJob( long id, 
381                               const std::string clusterName) throw (LauncherException)
382 {
383   machineParams params;
384   params.hostname = clusterName;
385   deleteJob(id,params);
386 }
387
388 //=============================================================================
389 /*! CORBA Method:
390  *  Get result files of job on a cluster
391  *  \param jobId              : identification of Salome job
392  *  \param params             : Constraints for the choice of the batch cluster
393  */
394 //=============================================================================
395 void Launcher_cpp::getResultsJob( const string directory,
396                                   const long id, 
397                                   const machineParams& params) throw(LauncherException)
398 {
399 #ifdef WITH_LIBBATCH
400   if(!_ResManager)
401     throw LauncherException("You must set Resources Manager to Launcher!!");
402
403   vector<string> aMachineList = _ResManager->GetFittingResources( params ) ;
404   ParserResourcesType p = _ResManager->GetResourcesList(aMachineList[0]);
405   string clustername(p.Alias);
406     
407   // search batch manager for that cluster in map
408   map < string, Batch::BatchManager_eClient * >::const_iterator it = _batchmap.find(clustername);
409   if(it == _batchmap.end())
410     throw LauncherException("no batchmanager for that cluster");
411     
412   Batch::Job* job = _jobmap[ pair<string,long>(clustername,id) ];
413
414   _batchmap[clustername]->importOutputFiles( *job, directory );
415 #else
416   throw LauncherException("Method Launcher_cpp::getResultsJob is not available "
417                           "(libBatch was not present at compilation time)");
418 #endif
419 }
420
421 void Launcher_cpp::getResultsJob( const std::string directory, 
422                                   long id, 
423                                   const std::string clusterName) throw (LauncherException)
424 {
425   machineParams params;
426   params.hostname = clusterName;
427   getResultsJob(directory,id,params);
428 }
429
430 //=============================================================================
431 /*!
432  *  Factory to instanciate the good batch manager for choosen cluster.
433  */ 
434 //=============================================================================
435
436 Batch::BatchManager_eClient *Launcher_cpp::FactoryBatchManager( const ParserResourcesType& params ) throw(LauncherException)
437 {
438 #ifdef WITH_LIBBATCH
439   std::string hostname, mpi;
440   Batch::CommunicationProtocolType protocol;
441   Batch::FactBatchManager_eClient* fact;
442
443   hostname = params.Alias;
444   switch(params.Protocol){
445   case rsh:
446     protocol = Batch::RSH;
447     break;
448   case ssh:
449     protocol = Batch::SSH;
450     break;
451   default:
452     throw LauncherException("unknown protocol");
453     break;
454   }
455   switch(params.mpi){
456   case lam:
457     mpi = "lam";
458     break;
459   case mpich1:
460     mpi = "mpich1";
461     break;
462   case mpich2:
463     mpi = "mpich2";
464     break;
465   case openmpi:
466     mpi = "openmpi";
467     break;
468   case slurm:
469     mpi = "slurm";
470     break;
471   case prun:
472     mpi = "prun";
473     break;
474   case nompi:
475     throw LauncherException("you must specified an mpi implementation for batch manager");
476     break;
477   default:
478     throw LauncherException("unknown mpi implementation");
479     break;
480   }    
481 #if defined(_DEBUG_) || defined(_DEBUG)
482   cerr << "Instanciation of batch manager" << endl;
483 #endif
484   switch( params.Batch ){
485   case pbs:
486 #if defined(_DEBUG_) || defined(_DEBUG)
487     cerr << "Instantiation of PBS batch manager" << endl;
488 #endif
489     fact = new Batch::FactBatchManager_ePBS;
490     break;
491   case lsf:
492 #if defined(_DEBUG_) || defined(_DEBUG)
493     cerr << "Instantiation of LSF batch manager" << endl;
494 #endif
495     fact = new Batch::FactBatchManager_eLSF;
496     break;
497   case sge:
498 #if defined(_DEBUG_) || defined(_DEBUG)
499     cout << "Instantiation of SGE batch manager" << endl;
500 #endif
501     fact = new Batch::FactBatchManager_eSGE;
502     break;
503   default:
504 #if defined(_DEBUG_) || defined(_DEBUG)
505     cerr << "BATCH = " << params.Batch << endl;
506 #endif
507     throw LauncherException("no batchmanager for that cluster");
508   }
509   return (*fact)(hostname.c_str(), protocol, mpi.c_str());
510 #else
511   throw LauncherException("Method Launcher_cpp::FactoryBatchManager is not available "
512                           "(libBatch was not present at compilation time)");
513 #endif
514 }
515
516 string Launcher_cpp::buildSalomeCouplingScript(const string fileToExecute, const string dirForTmpFiles, const ParserResourcesType& params)
517 {
518 #ifdef WITH_LIBBATCH
519 #ifndef WIN32 //TODO: need for porting on Windows
520   int idx = dirForTmpFiles.find("Batch/");
521   std::string filelogtemp = dirForTmpFiles.substr(idx+6, dirForTmpFiles.length());
522   std::string dfilelogtemp = params.AppliPath + "/" + filelogtemp;
523
524   string::size_type p1 = fileToExecute.find_last_of("/");
525   string::size_type p2 = fileToExecute.find_last_of(".");
526   std::string fileNameToExecute = fileToExecute.substr(p1+1,p2-p1-1);
527   std::string TmpFileName = "/tmp/runSalome_" + fileNameToExecute + ".sh";
528
529   MpiImpl* mpiImpl = FactoryMpiImpl(params.mpi);
530
531   ofstream tempOutputFile;
532   tempOutputFile.open(TmpFileName.c_str(), ofstream::out );
533
534   // Begin
535   tempOutputFile << "#! /bin/sh -f" << endl ;
536   tempOutputFile << "cd ~/" ;
537   tempOutputFile << dirForTmpFiles << endl ;
538   tempOutputFile << "export SALOME_BATCH=1\n";
539   tempOutputFile << "export PYTHONPATH=~/" ;
540   tempOutputFile << dirForTmpFiles ;
541   tempOutputFile << ":$PYTHONPATH" << endl ;
542
543   // Adding user script
544   std::string script = params.userCommands;
545   if (script != "")
546     tempOutputFile << script << endl;
547   // Test node rank
548   tempOutputFile << "if test \"" ;
549   tempOutputFile << mpiImpl->rank() ;
550   tempOutputFile << "\" = \"0\"; then" << endl ;
551
552   // -----------------------------------------------
553   // Code for rank 0 : launch runAppli and a container
554   // RunAppli
555   if(params.ModulesList.size()>0)
556     tempOutputFile << "  " << params.AppliPath << "/runAppli --terminal --modules=" ;
557   else
558     tempOutputFile << "  " << params.AppliPath << "/runAppli --terminal ";
559   for ( int i = 0 ; i < params.ModulesList.size() ; i++ ) {
560     tempOutputFile << params.ModulesList[i] ;
561     if ( i != params.ModulesList.size()-1 )
562       tempOutputFile << "," ;
563   }
564   tempOutputFile << " --standalone=registry,study,moduleCatalog --ns-port-log="
565                  << filelogtemp 
566                  << " &\n";
567
568   // Wait NamingService
569   tempOutputFile << "  current=0\n"
570                  << "  stop=20\n" 
571                  << "  while ! test -f " << dfilelogtemp << "\n"
572                  << "  do\n"
573                  << "    sleep 2\n"
574                  << "    let current=current+1\n"
575                  << "    if [ \"$current\" -eq \"$stop\" ] ; then\n"
576                  << "      echo Error Naming Service failed ! >&2"
577                  << "      exit\n"
578                  << "    fi\n"
579                  << "  done\n"
580                  << "  port=`cat " << dfilelogtemp << "`\n";
581     
582   // Wait other containers
583   tempOutputFile << "  for ((ip=1; ip < ";
584   tempOutputFile << mpiImpl->size();
585   tempOutputFile << " ; ip++))" << endl;
586   tempOutputFile << "  do" << endl ;
587   tempOutputFile << "    arglist=\"$arglist YACS_Server_\"$ip" << endl ;
588   tempOutputFile << "  done" << endl ;
589   tempOutputFile << "  sleep 5" << endl ;
590   tempOutputFile << "  " << params.AppliPath << "/runSession waitContainers.py $arglist" << endl ;
591   
592   // Launch user script
593   tempOutputFile << "  " << params.AppliPath << "/runSession python ~/" << dirForTmpFiles << "/" << fileNameToExecute << ".py" << endl;
594
595   // Stop application
596   tempOutputFile << "  rm " << dfilelogtemp << "\n"
597                  << "  " << params.AppliPath << "/runSession shutdownSalome.py" << endl;
598
599   // -------------------------------------
600   // Other nodes launch a container
601   tempOutputFile << "else" << endl ;
602
603   // Wait NamingService
604   tempOutputFile << "  current=0\n"
605                  << "  stop=20\n" 
606                  << "  while ! test -f " << dfilelogtemp << "\n"
607                  << "  do\n"
608                  << "    sleep 2\n"
609                  << "    let current=current+1\n"
610                  << "    if [ \"$current\" -eq \"$stop\" ] ; then\n"
611                  << "      echo Error Naming Service failed ! >&2"
612                  << "      exit\n"
613                  << "    fi\n"
614                  << "  done\n"
615                  << "  port=`cat " << dfilelogtemp << "`\n";
616
617   // Launching container
618   tempOutputFile << "  " << params.AppliPath << "/runSession SALOME_Container YACS_Server_";
619   tempOutputFile << mpiImpl->rank()
620                  << " > ~/" << dirForTmpFiles << "/YACS_Server_" 
621                  << mpiImpl->rank() << "_container_log." << filelogtemp
622                  << " 2>&1\n";
623   tempOutputFile << "fi" << endl ;
624   tempOutputFile.flush();
625   tempOutputFile.close();
626   chmod(TmpFileName.c_str(), 0x1ED);
627 #if defined(_DEBUG_) || defined(_DEBUG)
628   cerr << TmpFileName.c_str() << endl;
629 #endif
630
631   delete mpiImpl;
632
633   return TmpFileName;
634 #else
635   return "";
636 #endif
637     
638 #else
639   throw LauncherException("Method Launcher_cpp::buildSalomeCouplingScript is not available "
640                           "(libBatch was not present at compilation time)");
641 #endif
642 }
643
644 MpiImpl *Launcher_cpp::FactoryMpiImpl(MpiImplType mpi) throw(LauncherException)
645 {
646 #ifdef WITH_LIBBATCH
647   switch(mpi){
648   case lam:
649     return new MpiImpl_LAM();
650   case mpich1:
651     return new MpiImpl_MPICH1();
652   case mpich2:
653     return new MpiImpl_MPICH2();
654   case openmpi:
655     return new MpiImpl_OPENMPI();
656   case slurm:
657     return new MpiImpl_SLURM();
658   case prun:
659     return new MpiImpl_PRUN();
660   case nompi:
661     throw LauncherException("you must specify an mpi implementation for batch manager");
662   default:
663     ostringstream oss;
664     oss << mpi << " : not yet implemented";
665     throw LauncherException(oss.str().c_str());
666   }
667 #else
668   throw LauncherException("Method Launcher_cpp::FactoryMpiImpl is not available "
669                           "(libBatch was not present at compilation time)");
670 #endif
671 }
672
673 string Launcher_cpp::getTmpDirForBatchFiles()
674 {
675 #ifdef WITH_LIBBATCH
676   string ret;
677   string thedate;
678
679   // Adding date to the directory name
680   Batch::Date date = Batch::Date(time(0));
681   thedate = date.str();
682   int lend = thedate.size() ;
683   int i = 0 ;
684   while ( i < lend ) {
685     if ( thedate[i] == '/' || thedate[i] == '-' || thedate[i] == ':' ) {
686       thedate[i] = '_' ;
687     }
688     i++ ;
689   }
690
691   ret = string("Batch/");
692   ret += thedate;
693   return ret;
694 #else
695   throw LauncherException("Method Launcher_cpp::getTmpDirForBatchFiles is not available "
696                           "(libBatch was not present at compilation time)");
697 #endif
698 }
699
700 string Launcher_cpp::getRemoteFile( std::string remoteDir, std::string localFile )
701 {
702   string::size_type pos = localFile.find_last_of("/") + 1;
703   int ln = localFile.length() - pos;
704   string remoteFile = remoteDir + "/" + localFile.substr(pos,ln);
705   return remoteFile;
706 }
707
708 bool Launcher_cpp::check(const batchParams& batch_params)
709 {
710   bool rtn = true;
711 #if defined(_DEBUG_) || defined(_DEBUG)
712   cerr << "Job parameters are :" << endl;
713   cerr << "Directory : $HOME/Batch/$date" << endl;
714 #endif
715
716   // check expected_during_time (check the format)
717   std::string edt_info = batch_params.expected_during_time;
718   std::string edt_value = batch_params.expected_during_time;
719   if (edt_value != "") {
720     std::string begin_edt_value = edt_value.substr(0, 2);
721     std::string mid_edt_value = edt_value.substr(2, 1);
722     std::string end_edt_value = edt_value.substr(3);
723   
724     long value;
725     std::istringstream iss(begin_edt_value);
726     if (!(iss >> value)) {
727       edt_info = "Error on definition ! : " + edt_value;
728       rtn = false;
729     }
730     else if (value < 0) {
731       edt_info = "Error on definition time is negative ! : " + value;
732       rtn = false;
733     }
734     std::istringstream iss_2(end_edt_value);
735     if (!(iss_2 >> value)) {
736       edt_info = "Error on definition ! : " + edt_value;
737       rtn = false;
738     }
739     else if (value < 0) {
740       edt_info = "Error on definition time is negative ! : " + value;
741       rtn = false;
742     }
743     if (mid_edt_value != ":") {
744       edt_info = "Error on definition ! :" + edt_value;
745       rtn = false;
746     }
747   }
748   else {
749     edt_info = "No value given";
750   }
751 #if defined(_DEBUG_) || defined(_DEBUG)
752   cerr << "Expected during time : " << edt_info << endl;;
753 #endif
754
755   // check memory (check the format)
756   std::string mem_info;
757   std::string mem_value = batch_params.mem;
758   if (mem_value != "") {
759     std::string begin_mem_value = mem_value.substr(0, mem_value.length()-2);
760     long re_mem_value;
761     std::istringstream iss(begin_mem_value);
762     if (!(iss >> re_mem_value)) {
763       mem_info = "Error on definition ! : " + mem_value;
764       rtn = false;
765     }
766     else if (re_mem_value <= 0) {
767       mem_info = "Error on definition memory is negative ! : " + mem_value;
768       rtn = false;
769     }
770     std::string end_mem_value = mem_value.substr(mem_value.length()-2);
771     if (end_mem_value != "gb" && end_mem_value != "mb") {
772       mem_info = "Error on definition, type is bad ! " + mem_value;
773       rtn = false;
774     }
775   }
776   else {
777     mem_info = "No value given";
778   }
779 #if defined(_DEBUG_) || defined(_DEBUG)
780   cerr << "Memory : " << mem_info << endl;
781 #endif
782
783   // check nb_proc
784   std::string nb_proc_info;
785   ostringstream nb_proc_value;
786   nb_proc_value << batch_params.nb_proc;
787   if(batch_params.nb_proc <= 0) {
788     nb_proc_info = "Bad value ! nb_proc = ";
789     nb_proc_info += nb_proc_value.str();
790     rtn = false;
791   }
792   else {
793     nb_proc_info = nb_proc_value.str();
794   }
795 #if defined(_DEBUG_) || defined(_DEBUG)
796   cerr << "Nb of processors : " << nb_proc_info << endl;
797 #endif
798
799   return rtn;
800 }
801
802 long Launcher_cpp::getWallTime(std::string edt)
803 {
804   long hh, mm, ret;
805
806   if( edt.size() == 0 )
807     return 0;
808
809   string::size_type pos = edt.find(":");
810   string h = edt.substr(0,pos);
811   string m = edt.substr(pos+1,edt.size()-pos+1);
812   istringstream issh(h);
813   issh >> hh;
814   istringstream issm(m);
815   issm >> mm;
816   ret = hh*60 + mm;
817   return  ret;
818 }
819
820 long Launcher_cpp::getRamSize(std::string mem)
821 {
822   long mv;
823
824   if( mem.size() == 0 )
825     return 0;
826
827   string ram = mem.substr(0,mem.size()-2);
828   istringstream iss(ram);
829   iss >> mv;
830   string unity = mem.substr(mem.size()-2,2);
831   if( (unity.find("gb") != string::npos) || (unity.find("GB") != string::npos) )
832     return mv*1024;
833   else if( (unity.find("mb") != string::npos) || (unity.find("MB") != string::npos) )
834     return mv;
835   else if( (unity.find("kb") != string::npos) || (unity.find("KB") != string::npos) )
836     return mv/1024;
837   else if( (unity.find("b") != string::npos) || (unity.find("B") != string::npos) )
838     return mv/(1024*1024);
839   else
840     return 0;
841 }
842
843 void Launcher_cpp::ParseXmlFile(string xmlExecuteFile)
844 {
845   SALOME_Launcher_Handler* handler = new SALOME_Launcher_Handler(_launch);
846
847   const char* aFilePath = xmlExecuteFile.c_str();
848   FILE* aFile = fopen(aFilePath, "r");
849   
850   if (aFile != NULL)
851     {
852       xmlDocPtr aDoc = xmlReadFile(aFilePath, NULL, 0);
853       
854       if (aDoc != NULL)
855         handler->ProcessXmlDocument(aDoc);
856       else{
857 #if defined(_DEBUG_) || defined(_DEBUG)
858         cout << "ResourcesManager_cpp: could not parse file "<< aFilePath << endl;
859 #endif
860       }
861       
862       // Free the document
863       xmlFreeDoc(aDoc);
864
865       fclose(aFile);
866     }
867   else{
868 #if defined(_DEBUG_) || defined(_DEBUG)
869     cout << "Launcher_cpp: file "<<aFilePath<<" is not readable." << endl;
870 #endif
871   }
872   
873   delete handler;
874
875 }
876
877 std::string Launcher_cpp::getHomeDir(const ParserResourcesType& p, const std::string& tmpdir)
878 {
879   std::string home;
880   std::string command;
881   int idx = tmpdir.find("Batch/");
882   std::string filelogtemp = tmpdir.substr(idx+6, tmpdir.length());
883   filelogtemp = "/tmp/logs" + filelogtemp + "_home";
884   
885   if( p.Protocol == rsh )
886     command = "rsh ";
887   else if( p.Protocol == ssh )
888     command = "ssh ";
889   else
890     throw LauncherException("Unknown protocol");
891   if (p.UserName != ""){
892     command += p.UserName;
893     command += "@";
894   }
895   command += p.Alias;
896   command += " 'echo $HOME' > ";
897   command += filelogtemp;
898 #if defined(_DEBUG_) || defined(_DEBUG)
899   std::cerr << command.c_str() << std::endl;
900 #endif
901   int status = system(command.c_str());
902   if(status)
903     throw LauncherException("Error of launching home command on remote host");
904   
905   std::ifstream file_home(filelogtemp.c_str());
906   std::getline(file_home, home);
907   file_home.close();
908   return home;
909 }