]> SALOME platform Git repositories - modules/kernel.git/blob - src/Batch/Batch_BatchManager_ePBS.cxx
Salome HOME
Merging from V4_1_0_maintainance for porting on Win32 Platform
[modules/kernel.git] / src / Batch / Batch_BatchManager_ePBS.cxx
1 // Copyright (C) 2005  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
3 // 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either 
7 // version 2.1 of the License.
8 // 
9 // This library is distributed in the hope that it will be useful 
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
12 // Lesser General Public License for more details.
13 //
14 // You should have received a copy of the GNU Lesser General Public  
15 // License along with this library; if not, write to the Free Software 
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 //
18 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 //
20 /*
21  * BatchManager_ePBS.cxx : emulation of PBS client
22  *
23  * Auteur : Bernard SECHER - CEA DEN
24  * Mail   : mailto:bernard.secher@cea.fr
25  * Date   : Thu Apr 24 10:17:22 2008
26  * Projet : PAL Salome 
27  *
28  */
29
30 #include <iostream>
31 #include <fstream>
32 #include <sstream>
33 #include <sys/stat.h>
34 #include "Batch_BatchManager_ePBS.hxx"
35 #ifdef WIN32
36 # include <time.h>
37 # include <io.h>
38 #endif
39
40 using namespace std;
41
42 namespace Batch {
43
44   BatchManager_ePBS::BatchManager_ePBS(const FactBatchManager * parent, const char * host, const char * protocol, const char * mpiImpl) throw(InvalidArgumentException,ConnexionFailureException) : BatchManager_eClient(parent,host,protocol,mpiImpl)
45   {
46     // Nothing to do
47   }
48
49   // Destructeur
50   BatchManager_ePBS::~BatchManager_ePBS()
51   {
52     // Nothing to do
53   }
54
55   // Methode pour le controle des jobs : soumet un job au gestionnaire
56   const JobId BatchManager_ePBS::submitJob(const Job & job)
57   {
58     int status;
59     Parametre params = job.getParametre();
60     const std::string dirForTmpFiles = params[TMPDIR];
61     const string fileToExecute = params[EXECUTABLE];
62     string::size_type p1 = fileToExecute.find_last_of("/");
63     string::size_type p2 = fileToExecute.find_last_of(".");
64     std::string fileNameToExecute = fileToExecute.substr(p1+1,p2-p1-1);
65
66     // export input files on cluster
67     exportInputFiles(job);
68
69     // build batch script for job
70     buildBatchScript(job);
71
72     // define name of log file
73     string logFile="/tmp/logs/";
74     logFile += getenv("USER");
75     logFile += "/batchSalome_";
76     srand ( time(NULL) );
77     int ir = rand();
78     ostringstream oss;
79     oss << ir;
80     logFile += oss.str();
81     logFile += ".log";
82
83     string command;
84
85     // define command to submit batch
86     command = _protocol;
87     command += " ";
88
89     if(_username != ""){
90       command += _username;
91       command += "@";
92     }
93
94     command += _hostname;
95     command += " \"cd " ;
96     command += dirForTmpFiles ;
97     command += "; qsub " ;
98     command += fileNameToExecute ;
99     command += "_Batch.sh\" > ";
100     command += logFile;
101     cerr << command.c_str() << endl;
102     status = system(command.c_str());
103     if(status)
104       throw EmulationException("Error of connection on remote host");
105
106     // read id of submitted job in log file
107     char line[128];
108     FILE *fp = fopen(logFile.c_str(),"r");
109     fgets( line, 128, fp);
110     fclose(fp);
111     
112     string sline(line);
113     int pos = sline.find(".");
114     string strjob;
115     if(pos == string::npos)
116       strjob = sline;
117     else
118       strjob = sline.substr(0,pos);
119
120     JobId id(this, strjob);
121     return id;
122   }
123
124   // Methode pour le controle des jobs : retire un job du gestionnaire
125   void BatchManager_ePBS::deleteJob(const JobId & jobid)
126   {
127     int status;
128     int ref;
129     istringstream iss(jobid.getReference());
130     iss >> ref;
131     
132     // define command to submit batch
133     string command;
134     command = _protocol;
135     command += " ";
136
137     if (_username != ""){
138       command += _username;
139       command += "@";
140     }
141
142     command += _hostname;
143     command += " \"qdel " ;
144     command += iss.str();
145     command += "\"";
146     cerr << command.c_str() << endl;
147     status = system(command.c_str());
148     if(status)
149       throw EmulationException("Error of connection on remote host");
150
151     cerr << "jobId = " << ref << "killed" << endl;
152   }
153    
154   // Methode pour le controle des jobs : suspend un job en file d'attente
155   void BatchManager_ePBS::holdJob(const JobId & jobid)
156   {
157     throw EmulationException("Not yet implemented");
158   }
159
160   // Methode pour le controle des jobs : relache un job suspendu
161   void BatchManager_ePBS::releaseJob(const JobId & jobid)
162   {
163     throw EmulationException("Not yet implemented");
164   }
165
166
167   // Methode pour le controle des jobs : modifie un job en file d'attente
168   void BatchManager_ePBS::alterJob(const JobId & jobid, const Parametre & param, const Environnement & env)
169   {
170     throw EmulationException("Not yet implemented");
171   }
172
173   // Methode pour le controle des jobs : modifie un job en file d'attente
174   void BatchManager_ePBS::alterJob(const JobId & jobid, const Parametre & param)
175   {
176     alterJob(jobid, param, Environnement());
177   }
178
179   // Methode pour le controle des jobs : modifie un job en file d'attente
180   void BatchManager_ePBS::alterJob(const JobId & jobid, const Environnement & env)
181   {
182     alterJob(jobid, Parametre(), env);
183   }
184
185   // Methode pour le controle des jobs : renvoie l'etat du job
186   JobInfo BatchManager_ePBS::queryJob(const JobId & jobid)
187   {
188     int id;
189     istringstream iss(jobid.getReference());
190     iss >> id;
191
192     // define name of log file
193     string logFile="/tmp/logs/";
194     logFile += getenv("USER");
195     logFile += "/batchSalome_";
196
197     ostringstream oss;
198     oss << this << "_" << id;
199     logFile += oss.str();
200     logFile += ".log";
201
202     string command;
203     int status;
204
205     // define command to submit batch
206     command = _protocol;
207     command += " ";
208
209     if (_username != ""){
210       command += _username;
211       command += "@";
212     }
213
214     command += _hostname;
215     command += " \"qstat -f " ;
216     command += iss.str();
217     command += "\" > ";
218     command += logFile;
219     cerr << command.c_str() << endl;
220     status = system(command.c_str());
221     if(status && status != 153 && status != 256*153)
222       throw EmulationException("Error of connection on remote host");
223
224     JobInfo_ePBS ji = JobInfo_ePBS(id,logFile);
225     return ji;
226   }
227
228   // Methode pour le controle des jobs : teste si un job est present en machine
229   bool BatchManager_ePBS::isRunning(const JobId & jobid)
230   {
231     throw EmulationException("Not yet implemented");
232   }
233
234   void BatchManager_ePBS::buildBatchScript(const Job & job) throw(EmulationException)
235   {
236 #ifndef WIN32 //TODO: need for porting on Windows
237     int status;
238     Parametre params = job.getParametre();
239     const long nbproc = params[NBPROC];
240     const long edt = params[MAXWALLTIME];
241     const long mem = params[MAXRAMSIZE];
242     const string workDir = params[WORKDIR];
243     const std::string dirForTmpFiles = params[TMPDIR];
244     const string fileToExecute = params[EXECUTABLE];
245     const string home = params[HOMEDIR];
246     string::size_type p1 = fileToExecute.find_last_of("/");
247     string::size_type p2 = fileToExecute.find_last_of(".");
248     std::string rootNameToExecute = fileToExecute.substr(p1+1,p2-p1-1);
249     std::string fileNameToExecute = "~/" + dirForTmpFiles + "/" + string(basename(fileToExecute.c_str()));
250
251     int idx = dirForTmpFiles.find("Batch/");
252     std::string filelogtemp = dirForTmpFiles.substr(idx+6, dirForTmpFiles.length());
253
254     std::string TmpFileName = BuildTemporaryFileName();
255     ofstream tempOutputFile;
256     tempOutputFile.open(TmpFileName.c_str(), ofstream::out );
257
258     tempOutputFile << "#! /bin/sh -f" << endl;
259     if( edt > 0 )
260       tempOutputFile << "#PBS -l walltime=" << edt*60 << endl ;
261     if( mem > 0 )
262       tempOutputFile << "#PBS -l mem=" << mem << "mb" << endl ;
263     tempOutputFile << "#PBS -o " << home << "/" << dirForTmpFiles << "/runSalome.output.log." << filelogtemp << endl ;
264     tempOutputFile << "#PBS -e " << home << "/" << dirForTmpFiles << "/runSalome.error.log." << filelogtemp << endl ;
265     if( workDir.size() > 0 )
266       tempOutputFile << "cd " << workDir << endl ;
267     tempOutputFile << _mpiImpl->boot("${PBS_NODEFILE}",nbproc);
268     tempOutputFile << _mpiImpl->run("${PBS_NODEFILE}",nbproc,fileNameToExecute);
269     tempOutputFile << _mpiImpl->halt();
270     tempOutputFile.flush();
271     tempOutputFile.close();
272 #ifdef WIN32
273     _chmod(
274 #else
275     chmod(
276 #endif
277       TmpFileName.c_str(), 0x1ED);
278     cerr << TmpFileName.c_str() << endl;
279
280     string command;
281     if( _protocol == "rsh" )
282       command = "rcp ";
283     else if( _protocol == "ssh" )
284       command = "scp ";
285     else
286       throw EmulationException("Unknown protocol");
287     command += TmpFileName;
288     command += " ";
289     if(_username != ""){
290       command +=  _username;
291       command += "@";
292     }
293     command += _hostname;
294     command += ":";
295     command += dirForTmpFiles ;
296     command += "/" ;
297     command += rootNameToExecute ;
298     command += "_Batch.sh" ;
299     cerr << command.c_str() << endl;
300     status = system(command.c_str());
301     if(status)
302       throw EmulationException("Error of connection on remote host");    
303
304     RmTmpFile(TmpFileName);
305 #endif    
306   }
307
308 }