Salome HOME
untabify
[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 #include <Batch/Batch_FactBatchManager_eSSH.hxx>
30 #endif
31
32 #include "SALOME_Launcher_Handler.hxx"
33 #include "Launcher.hxx"
34 #include "Launcher_Job_Command.hxx"
35 #include <iostream>
36 #include <sstream>
37 #include <sys/stat.h>
38 #include <time.h>
39
40 using namespace std;
41
42 //=============================================================================
43 /*! 
44  *  Constructor
45  *  \param orb
46  *  Define a CORBA single thread policy for the server, which avoid to deal
47  *  with non thread-safe usage like Change_Directory in SALOME naming service
48  */
49 //=============================================================================
50 Launcher_cpp::Launcher_cpp()
51 {
52   LAUNCHER_MESSAGE("Launcher_cpp constructor");
53   _job_cpt = 0;
54   _job_cpt_mutex = new pthread_mutex_t();
55   pthread_mutex_init(_job_cpt_mutex, NULL);
56 }
57
58 //=============================================================================
59 /*! 
60  * destructor
61  */
62 //=============================================================================
63 Launcher_cpp::~Launcher_cpp()
64 {
65   LAUNCHER_MESSAGE("Launcher_cpp destructor");
66 #ifdef WITH_LIBBATCH
67   std::map < string, Batch::BatchManager_eClient * >::const_iterator it1;
68   for(it1=_batchmap.begin();it1!=_batchmap.end();it1++)
69     delete it1->second;
70   std::map<int, Launcher::Job *>::const_iterator it_job;
71   for(it_job = _launcher_job_map.begin(); it_job != _launcher_job_map.end(); it_job++)
72     delete it_job->second;
73 #endif
74
75   pthread_mutex_destroy(_job_cpt_mutex);
76   delete _job_cpt_mutex;
77 }
78
79 #ifdef WITH_LIBBATCH
80
81 //=============================================================================
82 /*!
83  * Add a job into the launcher - check resource and choose one 
84  */ 
85 //=============================================================================
86 void 
87 Launcher_cpp::createJob(Launcher::Job * new_job)
88 {
89   LAUNCHER_MESSAGE("Creating a new job");
90   
91   // First step take a resource
92   std::vector<std::string> ResourceList;
93   resourceParams params = new_job->getResourceRequiredParams();
94   try{
95     ResourceList = _ResManager->GetFittingResources(params);
96   }
97   catch(const ResourcesException &ex){
98     throw LauncherException(ex.msg.c_str());
99   }
100   if (ResourceList.size() == 0)
101   {
102     LAUNCHER_INFOS("No adequate resource found for the job, number " << new_job->getNumber() << " - deleting it");
103     delete new_job;
104     throw LauncherException("No resource found the job");
105   }
106
107   // Second step configure the job with the resource selected - the first of the list
108   ParserResourcesType resource_definition = _ResManager->GetResourcesDescr(ResourceList[0]);
109
110   // Set resource definition to the job
111   // The job will check if the definitions needed
112   try 
113   {
114     new_job->setResourceDefinition(resource_definition);
115   }
116   catch(const LauncherException &ex)
117   {
118     LAUNCHER_INFOS("Error in the definition of the resource, mess: " << ex.msg);
119     delete new_job;
120     throw ex;
121   }
122
123   // Third step search batch manager for the resource into the map -> instanciate one if does not exist
124   std::string resource_name = resource_definition.Name;
125   std::map<std::string, Batch::BatchManager_eClient *>::const_iterator it = _batchmap.find(resource_name);
126   if(it == _batchmap.end())
127   {
128     try 
129     {
130       _batchmap[resource_name] = FactoryBatchManager(resource_definition);
131     }
132     catch(const LauncherException &ex)
133     {
134       LAUNCHER_INFOS("Error during creation of the batch manager of the resource, mess: " << ex.msg);
135       delete new_job;
136       throw ex;
137     }
138     catch(const Batch::EmulationException &ex)
139     {
140       LAUNCHER_INFOS("Error during creation of the batch manager of the resource, mess: " << ex.message);
141       delete new_job;
142       throw LauncherException(ex.message);
143     }
144   }
145
146
147   // Final step - add job to the jobs map
148   pthread_mutex_lock(_job_cpt_mutex);
149   new_job->setNumber(_job_cpt);
150   _job_cpt++;
151   pthread_mutex_unlock(_job_cpt_mutex);
152   std::map<int, Launcher::Job *>::const_iterator it_job = _launcher_job_map.find(new_job->getNumber());
153   if (it_job == _launcher_job_map.end())
154     _launcher_job_map[new_job->getNumber()] = new_job;
155   else
156   {
157     LAUNCHER_INFOS("A job as already the same id: " << new_job->getNumber());
158     delete new_job;
159     throw LauncherException("A job as already the same id - job is not created !");
160   }
161   LAUNCHER_MESSAGE("New Job created");
162 }
163
164 //=============================================================================
165 /*!
166  * Launch a job 
167  */ 
168 //=============================================================================
169 void 
170 Launcher_cpp::launchJob(int job_id)
171 {
172   LAUNCHER_MESSAGE("Launch a job");
173
174   // Check if job exist
175   std::map<int, Launcher::Job *>::const_iterator it_job = _launcher_job_map.find(job_id);
176   if (it_job == _launcher_job_map.end())
177   {
178     LAUNCHER_INFOS("Cannot find the job, is it created ? job number: " << job_id);
179     throw LauncherException("Cannot find the job, is it created ?");
180   }
181
182   Launcher::Job * job = it_job->second;
183
184   // Check job state (cannot launch a job already launched...)
185   if (job->getState() != "CREATED")
186   {
187     LAUNCHER_INFOS("Bad state of the job: " << job->getState());
188     throw LauncherException("Bad state of the job: " + job->getState());
189   }
190
191   std::string resource_name = job->getResourceDefinition().Name;
192   try {
193     Batch::JobId batch_manager_job_id = _batchmap[resource_name]->submitJob(*(job->getBatchJob()));
194     job->setBatchManagerJobId(batch_manager_job_id);
195     job->setState("QUEUED");
196   }
197   catch(const Batch::EmulationException &ex)
198   {
199     LAUNCHER_INFOS("Job is not launched, exception in submitJob: " << ex.message);
200     throw LauncherException(ex.message.c_str());
201   }
202   LAUNCHER_MESSAGE("Job launched");
203 }
204
205 //=============================================================================
206 /*!
207  * Get job state
208  */ 
209 //=============================================================================
210 const char *
211 Launcher_cpp::getJobState(int job_id)
212 {
213   LAUNCHER_MESSAGE("Get job state");
214
215   // Check if job exist
216   std::map<int, Launcher::Job *>::const_iterator it_job = _launcher_job_map.find(job_id);
217   if (it_job == _launcher_job_map.end())
218   {
219     LAUNCHER_INFOS("Cannot find the job, is it created ? job number: " << job_id);
220     throw LauncherException("Cannot find the job, is it created ?");
221   }
222
223   Launcher::Job * job = it_job->second;
224   std::string state = job->updateJobState();
225
226   return state.c_str();
227 }
228
229 //=============================================================================
230 /*!
231  * Get Job result - the result directory could be changed
232  */ 
233 //=============================================================================
234 void
235 Launcher_cpp::getJobResults(int job_id, std::string directory)
236 {
237   LAUNCHER_MESSAGE("Get Job results");
238
239   // Check if job exist
240   std::map<int, Launcher::Job *>::const_iterator it_job = _launcher_job_map.find(job_id);
241   if (it_job == _launcher_job_map.end())
242   {
243     LAUNCHER_INFOS("Cannot find the job, is it created ? job number: " << job_id);
244     throw LauncherException("Cannot find the job, is it created ?");
245   }
246
247   Launcher::Job * job = it_job->second;
248   std::string resource_name = job->getResourceDefinition().Name;
249   try 
250   {
251     if (directory != "")
252       _batchmap[resource_name]->importOutputFiles(*(job->getBatchJob()), directory);
253     else
254       _batchmap[resource_name]->importOutputFiles(*(job->getBatchJob()), job->getResultDirectory());
255   }
256   catch(const Batch::EmulationException &ex)
257   {
258     LAUNCHER_INFOS("getJobResult is maybe incomplete, exception: " << ex.message);
259     throw LauncherException(ex.message.c_str());
260   }
261   LAUNCHER_MESSAGE("getJobResult ended");
262 }
263
264 //=============================================================================
265 /*!
266  * Remove the job - into the Launcher and its batch manager
267  */ 
268 //=============================================================================
269 void
270 Launcher_cpp::removeJob(int job_id)
271 {
272   LAUNCHER_MESSAGE("Remove Job");
273
274   // Check if job exist
275   std::map<int, Launcher::Job *>::iterator it_job = _launcher_job_map.find(job_id);
276   if (it_job == _launcher_job_map.end())
277   {
278     LAUNCHER_INFOS("Cannot find the job, is it created ? job number: " << job_id);
279     throw LauncherException("Cannot find the job, is it created ?");
280   }
281
282   delete it_job->second;
283   _launcher_job_map.erase(it_job);
284 }
285
286 //=============================================================================
287 /*! 
288  *  create a launcher job based on a file
289  *  \param xmlExecuteFile     : to define the execution on the batch cluster
290  */
291 //=============================================================================
292 long 
293 Launcher_cpp::createJobWithFile(const std::string xmlExecuteFile, 
294                                 const std::string clusterName)
295 {
296   LAUNCHER_MESSAGE("Begin of Launcher_cpp::createJobWithFile");
297
298   // Parsing xml file
299   ParserLauncherType job_params = ParseXmlFile(xmlExecuteFile);
300
301   // Creating a new job
302   Launcher::Job_Command * new_job = new Launcher::Job_Command();
303   new_job->setJobFile(job_params.Command);
304   new_job->setLocalDirectory(job_params.RefDirectory);
305   new_job->setWorkDirectory(job_params.MachinesList[clusterName].WorkDirectory);
306   new_job->setEnvFile(job_params.MachinesList[clusterName].EnvFile);
307
308   for(int i=0; i < job_params.InputFile.size(); i++)
309     new_job->add_in_file(job_params.InputFile[i]);
310   for(int i=0; i < job_params.OutputFile.size();i++)
311     new_job->add_out_file(job_params.OutputFile[i]);
312
313   resourceParams p;
314   p.hostname = clusterName;
315   p.nb_proc = job_params.NbOfProcesses;
316   new_job->setResourceRequiredParams(p);
317
318   createJob(new_job);
319   return new_job->getNumber();
320 }
321
322 //=============================================================================
323 /*!
324  *  Factory to instanciate the good batch manager for choosen cluster.
325  */ 
326 //=============================================================================
327 Batch::BatchManager_eClient *
328 Launcher_cpp::FactoryBatchManager(ParserResourcesType& params)
329 {
330   std::string mpi;
331   Batch::CommunicationProtocolType protocol;
332   Batch::FactBatchManager_eClient* fact;
333
334   int nb_proc_per_node = params.DataForSort._nbOfProcPerNode;
335   std::string hostname = params.HostName;
336
337   switch(params.Protocol)
338   {
339     case rsh:
340       protocol = Batch::RSH;
341       break;
342     case ssh:
343       protocol = Batch::SSH;
344       break;
345     default:
346       throw LauncherException("Unknown protocol for this resource");
347       break;
348   }
349
350   switch(params.mpi)
351   {
352     case lam:
353       mpi = "lam";
354       break;
355     case mpich1:
356       mpi = "mpich1";
357       break;
358     case mpich2:
359       mpi = "mpich2";
360       break;
361     case openmpi:
362       mpi = "openmpi";
363       break;
364     case slurm:
365       mpi = "slurm";
366       break;
367     case prun:
368       mpi = "prun";
369       break;
370     default:
371       mpi = "nompi";
372   }
373
374   std::string message = "Instanciation of batch manager of type: ";
375   switch( params.Batch )
376   {
377     case pbs:
378       message += "ePBS";
379       fact = new Batch::FactBatchManager_ePBS;
380       break;
381     case lsf:
382       message += "eLSF";
383       fact = new Batch::FactBatchManager_eLSF;
384       break;
385     case sge:
386       message += "eSGE";
387       fact = new Batch::FactBatchManager_eSGE;
388       break;
389     case ssh_batch:
390       message += "eSSH";
391       fact = new Batch::FactBatchManager_eSSH;
392       break;
393     default:
394       LAUNCHER_MESSAGE("Bad batch description of the resource: Batch = " << params.Batch);
395       throw LauncherException("No batchmanager for that cluster - Bad batch description of the resource");
396   }
397   LAUNCHER_MESSAGE(message);
398   return (*fact)(hostname.c_str(), protocol, mpi.c_str(), nb_proc_per_node);
399 }
400
401 //----------------------------------------------------------
402 // Without LIBBATCH - Launcher_cpp do nothing...
403 //----------------------------------------------------------
404 #else
405
406 void 
407 Launcher_cpp::createJob(Launcher::Job * new_job)
408 {
409   LAUNCHER_INFOS("Launcher compiled without LIBBATCH - cannot create a job !!!");
410   delete new_job;
411   throw LauncherException("Method Launcher_cpp::createJob is not available "
412                           "(libBatch was not present at compilation time)");
413 }
414
415 void 
416 Launcher_cpp::launchJob(int job_id)
417 {
418   LAUNCHER_INFOS("Launcher compiled without LIBBATCH - cannot launch a job !!!");
419   throw LauncherException("Method Launcher_cpp::launchJob is not available "
420                           "(libBatch was not present at compilation time)");
421 }
422
423 const char *
424 Launcher_cpp::getJobState(int job_id)
425 {
426   LAUNCHER_INFOS("Launcher compiled without LIBBATCH - cannot get job state!!!");
427   throw LauncherException("Method Launcher_cpp::getJobState is not available "
428                           "(libBatch was not present at compilation time)");
429 }
430
431 void
432 Launcher_cpp::getJobResults(int job_id, std::string directory)
433 {
434   LAUNCHER_INFOS("Launcher compiled without LIBBATCH - cannot get job results!!!");
435   throw LauncherException("Method Launcher_cpp::getJobResults is not available "
436                           "(libBatch was not present at compilation time)");
437 }
438
439 void
440 Launcher_cpp::removeJob(int job_id)
441 {
442   LAUNCHER_INFOS("Launcher compiled without LIBBATCH - cannot remove job!!!");
443   throw LauncherException("Method Launcher_cpp::removeJob is not available "
444                           "(libBatch was not present at compilation time)");
445 }
446
447 long 
448 Launcher_cpp::createJobWithFile( const std::string xmlExecuteFile, std::string clusterName)
449 {
450   throw LauncherException("Method Launcher_cpp::createJobWithFile is not available "
451                           "(libBatch was not present at compilation time)");
452   return 0;
453 }
454
455 #endif
456
457 ParserLauncherType 
458 Launcher_cpp::ParseXmlFile(string xmlExecuteFile)
459 {
460   ParserLauncherType job_params;
461   SALOME_Launcher_Handler * handler = new SALOME_Launcher_Handler(job_params);
462
463   const char* aFilePath = xmlExecuteFile.c_str();
464   FILE* aFile = fopen(aFilePath, "r");
465   if (aFile != NULL)
466   {
467     xmlDocPtr aDoc = xmlReadFile(aFilePath, NULL, 0);
468     if (aDoc != NULL)
469       handler->ProcessXmlDocument(aDoc);
470     else
471     {
472       std::string message = "ResourcesManager_cpp: could not parse file: " + xmlExecuteFile;
473       LAUNCHER_MESSAGE(message);
474       delete handler;
475       throw LauncherException(message);
476     }
477     // Free the document
478     xmlFreeDoc(aDoc);
479     fclose(aFile);
480   }
481   else
482   {
483     std::string message = "ResourcesManager_cpp: file is not readable: " + xmlExecuteFile;
484     LAUNCHER_MESSAGE(message);
485     delete handler;
486     throw LauncherException(message);
487   }
488
489   // Return
490   delete handler;
491   return job_params;
492 }
493