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