Salome HOME
Move XML persistence functions from SALOME_Launcher class to a dedicated class Launch...
[modules/yacs.git] / src / Launcher / Launcher.cxx
1 // Copyright (C) 2007-2013  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 #include <list>
24 #include <iostream>
25 #include <sstream>
26 #include <sys/stat.h>
27 #include <time.h>
28
29 #ifdef WITH_LIBBATCH
30 #include <libbatch/BatchManagerCatalog.hxx>
31 #include <libbatch/FactBatchManager.hxx>
32 #include <libbatch/BatchManager.hxx>
33 #endif
34
35 #include "Basics_Utils.hxx"
36 #include "Basics_DirUtils.hxx"
37 #include "SALOME_Launcher_Handler.hxx"
38 #include "Launcher.hxx"
39 #include "Launcher_Job_Command.hxx"
40 #include "Launcher_XML_Persistence.hxx"
41
42 using namespace std;
43
44 //=============================================================================
45 /*! 
46  *  Constructor
47  *  \param orb
48  *  Define a CORBA single thread policy for the server, which avoid to deal
49  *  with non thread-safe usage like Change_Directory in SALOME naming service
50  */
51 //=============================================================================
52 Launcher_cpp::Launcher_cpp()
53 {
54   LAUNCHER_MESSAGE("Launcher_cpp constructor");
55   _job_cpt = 0;
56   _job_cpt_mutex = new pthread_mutex_t();
57   pthread_mutex_init(_job_cpt_mutex, NULL);
58 }
59
60 //=============================================================================
61 /*! 
62  * destructor
63  */
64 //=============================================================================
65 Launcher_cpp::~Launcher_cpp()
66 {
67   LAUNCHER_MESSAGE("Launcher_cpp destructor");
68 #ifdef WITH_LIBBATCH
69   std::map<int, Launcher::Job *>::const_iterator it_job;
70   for(it_job = _launcher_job_map.begin(); it_job != _launcher_job_map.end(); it_job++)
71     delete it_job->second;
72   std::map <int, Batch::BatchManager * >::const_iterator it1;
73   for(it1=_batchmap.begin();it1!=_batchmap.end();it1++)
74     delete it1->second;
75 #endif
76
77   pthread_mutex_destroy(_job_cpt_mutex);
78   delete _job_cpt_mutex;
79 }
80
81 #ifdef WITH_LIBBATCH
82
83 //=============================================================================
84 /*!
85  * Add a job into the launcher - check resource and choose one 
86  */ 
87 //=============================================================================
88 void 
89 Launcher_cpp::createJob(Launcher::Job * new_job)
90 {
91   LAUNCHER_MESSAGE("Creating a new job");
92   // Add job to the jobs map
93   pthread_mutex_lock(_job_cpt_mutex);
94   new_job->setNumber(_job_cpt);
95   _job_cpt++;
96   pthread_mutex_unlock(_job_cpt_mutex);
97   std::map<int, Launcher::Job *>::const_iterator it_job = _launcher_job_map.find(new_job->getNumber());
98   if (it_job == _launcher_job_map.end())
99     _launcher_job_map[new_job->getNumber()] = new_job;
100   else
101   {
102     LAUNCHER_INFOS("A job as already the same id: " << new_job->getNumber());
103     delete new_job;
104     throw LauncherException("A job as already the same id - job is not created !");
105   }
106   LAUNCHER_MESSAGE("New Job created");
107 }
108
109 //=============================================================================
110 /*!
111  * Launch a job 
112  */ 
113 //=============================================================================
114 void 
115 Launcher_cpp::launchJob(int job_id)
116 {
117   LAUNCHER_MESSAGE("Launch a job");
118
119   // Check if job exist
120   std::map<int, Launcher::Job *>::const_iterator it_job = _launcher_job_map.find(job_id);
121   if (it_job == _launcher_job_map.end())
122   {
123     LAUNCHER_INFOS("Cannot find the job, is it created ? job number: " << job_id);
124     throw LauncherException("Cannot find the job, is it created ?");
125   }
126
127   Launcher::Job * job = it_job->second;
128
129   // Check job state (cannot launch a job already launched...)
130   if (job->getState() != "CREATED")
131   {
132     LAUNCHER_INFOS("Bad state of the job: " << job->getState());
133     throw LauncherException("Bad state of the job: " + job->getState());
134   }
135
136   // Third step search batch manager for the job into the map -> instanciate one if does not exist
137 #ifdef WITH_LIBBATCH
138   std::map<int, Batch::BatchManager *>::const_iterator it = _batchmap.find(job_id);
139   if(it == _batchmap.end())
140   {
141     createBatchManagerForJob(job);
142   }
143 #endif
144
145   try {
146     Batch::JobId batch_manager_job_id = _batchmap[job_id]->submitJob(*(job->getBatchJob()));
147     job->setBatchManagerJobId(batch_manager_job_id);
148     job->setState("QUEUED");
149   }
150   catch(const Batch::GenericException &ex)
151   {
152     LAUNCHER_INFOS("Job is not launched, exception in submitJob: " << ex.message);
153     throw LauncherException(ex.message.c_str());
154   }
155   LAUNCHER_MESSAGE("Job launched");
156 }
157
158 //=============================================================================
159 /*!
160  * Get job state
161  */ 
162 //=============================================================================
163 const char *
164 Launcher_cpp::getJobState(int job_id)
165 {
166   LAUNCHER_MESSAGE("Get job state");
167
168   // Check if job exist
169   std::map<int, Launcher::Job *>::const_iterator it_job = _launcher_job_map.find(job_id);
170   if (it_job == _launcher_job_map.end())
171   {
172     LAUNCHER_INFOS("Cannot find the job, is it created ? job number: " << job_id);
173     throw LauncherException("Cannot find the job, is it created ?");
174   }
175
176   Launcher::Job * job = it_job->second;
177
178   std::string state;
179   try
180   {
181     state = job->updateJobState();
182   }
183   catch(const Batch::GenericException &ex)
184   {
185     LAUNCHER_INFOS("getJobState failed, exception: " << ex.message);
186     throw LauncherException(ex.message.c_str());
187   }
188
189   return state.c_str();
190 }
191
192 //=============================================================================
193 /*!
194  * Get job assigned hostnames
195  */
196 //=============================================================================
197 const char *
198 Launcher_cpp::getAssignedHostnames(int job_id)
199 {
200   LAUNCHER_MESSAGE("Get job assigned hostnames");
201
202   // Check if job exist
203   std::map<int, Launcher::Job *>::const_iterator it_job = _launcher_job_map.find(job_id);
204   if (it_job == _launcher_job_map.end())
205   {
206     LAUNCHER_INFOS("Cannot find the job, is it created ? job number: " << job_id);
207     throw LauncherException("Cannot find the job, is it created ?");
208   }
209
210   Launcher::Job * job = it_job->second;
211   std::string assigned_hostnames = job->getAssignedHostnames();
212
213   return assigned_hostnames.c_str();
214 }
215
216 //=============================================================================
217 /*!
218  * Get Job result - the result directory could be changed
219  */ 
220 //=============================================================================
221 void
222 Launcher_cpp::getJobResults(int job_id, std::string directory)
223 {
224   LAUNCHER_MESSAGE("Get Job results");
225
226   // Check if job exist
227   std::map<int, Launcher::Job *>::const_iterator it_job = _launcher_job_map.find(job_id);
228   if (it_job == _launcher_job_map.end())
229   {
230     LAUNCHER_INFOS("Cannot find the job, is it created ? job number: " << job_id);
231     throw LauncherException("Cannot find the job, is it created ?");
232   }
233
234   Launcher::Job * job = it_job->second;
235   std::string resource_name = job->getResourceDefinition().Name;
236   try 
237   {
238     if (directory != "")
239       _batchmap[job_id]->importOutputFiles(*(job->getBatchJob()), directory);
240     else
241       _batchmap[job_id]->importOutputFiles(*(job->getBatchJob()), job->getResultDirectory());
242   }
243   catch(const Batch::GenericException &ex)
244   {
245     LAUNCHER_INFOS("getJobResult is maybe incomplete, exception: " << ex.message);
246     throw LauncherException(ex.message.c_str());
247   }
248   LAUNCHER_MESSAGE("getJobResult ended");
249 }
250
251 //=============================================================================
252 /*!
253  * Get Job dump state - the result directory could be changed
254  */ 
255 //=============================================================================
256 bool
257 Launcher_cpp::getJobDumpState(int job_id, std::string directory)
258 {
259   bool rtn;
260   LAUNCHER_MESSAGE("Get Job dump state");
261
262   // Check if job exist
263   std::map<int, Launcher::Job *>::const_iterator it_job = _launcher_job_map.find(job_id);
264   if (it_job == _launcher_job_map.end())
265   {
266     LAUNCHER_INFOS("Cannot find the job, is it created ? job number: " << job_id);
267     throw LauncherException("Cannot find the job, is it created ?");
268   }
269
270   Launcher::Job * job = it_job->second;
271   std::string resource_name = job->getResourceDefinition().Name;
272   try 
273   {
274     if (directory != "")
275       rtn = _batchmap[job_id]->importDumpStateFile(*(job->getBatchJob()), directory);
276     else
277       rtn = _batchmap[job_id]->importDumpStateFile(*(job->getBatchJob()), job->getResultDirectory());
278   }
279   catch(const Batch::GenericException &ex)
280   {
281     LAUNCHER_INFOS("getJobResult is maybe incomplete, exception: " << ex.message);
282     throw LauncherException(ex.message.c_str());
283   }
284   LAUNCHER_MESSAGE("getJobResult ended");
285   return rtn;
286 }
287
288 //=============================================================================
289 /*!
290  * Remove the job - into the Launcher and its batch manager
291  */ 
292 //=============================================================================
293 void
294 Launcher_cpp::removeJob(int job_id)
295 {
296   LAUNCHER_MESSAGE("Remove Job");
297
298   // Check if job exist
299   std::map<int, Launcher::Job *>::iterator it_job = _launcher_job_map.find(job_id);
300   if (it_job == _launcher_job_map.end())
301   {
302     LAUNCHER_INFOS("Cannot find the job, is it created ? job number: " << job_id);
303     throw LauncherException("Cannot find the job, is it created ?");
304   }
305
306   it_job->second->removeJob();
307   delete it_job->second;
308   _launcher_job_map.erase(it_job);
309 }
310
311 //=============================================================================
312 /*!
313  * stop the job
314  */ 
315 //=============================================================================
316 void
317 Launcher_cpp::stopJob(int job_id)
318 {
319   LAUNCHER_MESSAGE("Stop Job");
320
321   // Check if job exist
322   std::map<int, Launcher::Job *>::iterator it_job = _launcher_job_map.find(job_id);
323   if (it_job == _launcher_job_map.end())
324   {
325     LAUNCHER_INFOS("Cannot find the job, is it created ? job number: " << job_id);
326     throw LauncherException("Cannot find the job, is it created ?");
327   }
328
329   it_job->second->stopJob();
330 }
331
332 //=============================================================================
333 /*! 
334  *  create a launcher job based on a file
335  *  \param xmlExecuteFile     : to define the execution on the batch cluster
336  */
337 //=============================================================================
338 long 
339 Launcher_cpp::createJobWithFile(const std::string xmlExecuteFile, 
340                                 const std::string clusterName)
341 {
342   LAUNCHER_MESSAGE("Begin of Launcher_cpp::createJobWithFile");
343
344   // Parsing xml file
345   ParserLauncherType job_params = ParseXmlFile(xmlExecuteFile);
346
347   // Creating a new job
348   Launcher::Job_Command * new_job = new Launcher::Job_Command();
349
350   std::string cmdFile = Kernel_Utils::GetTmpFileName();  
351 #ifndef WIN32
352   cmdFile += ".sh";
353 #else
354   cmdFile += ".bat";
355 #endif
356   std::ofstream os;
357   os.open(cmdFile.c_str(), std::ofstream::out );
358   os << "#! /bin/sh" << std::endl;
359   os << job_params.Command;
360   os.close();
361
362   new_job->setJobFile(cmdFile);
363   new_job->setLocalDirectory(job_params.RefDirectory);
364   new_job->setWorkDirectory(job_params.MachinesList[clusterName].WorkDirectory);
365   new_job->setEnvFile(job_params.MachinesList[clusterName].EnvFile);
366
367   for(int i=0; i < job_params.InputFile.size(); i++)
368     new_job->add_in_file(job_params.InputFile[i]);
369   for(int i=0; i < job_params.OutputFile.size();i++)
370     new_job->add_out_file(job_params.OutputFile[i]);
371
372   resourceParams p;
373   p.hostname = clusterName;
374   p.name = "";
375   p.OS = "";
376   p.nb_proc = job_params.NbOfProcesses;
377   p.nb_node = 0;
378   p.nb_proc_per_node = 0;
379   p.cpu_clock = 0;
380   p.mem_mb = 0;
381   new_job->setResourceRequiredParams(p);
382
383   createJob(new_job);
384   return new_job->getNumber();
385 }
386
387 //=============================================================================
388 /*!
389  *  Factory to instanciate the good batch manager for choosen cluster.
390  */ 
391 //=============================================================================
392 Batch::BatchManager *
393 Launcher_cpp::FactoryBatchManager(ParserResourcesType& params)
394 {
395   std::string mpi;
396   Batch::CommunicationProtocolType protocol;
397   Batch::FactBatchManager * fact;
398
399   std::string hostname = params.HostName;
400
401   switch(params.Protocol)
402   {
403     case sh:
404       protocol = Batch::SH;
405       break;
406     case rsh:
407       protocol = Batch::RSH;
408       break;
409     case ssh:
410       protocol = Batch::SSH;
411       break;
412     default:
413       throw LauncherException("Unknown protocol for this resource");
414       break;
415   }
416
417   switch(params.mpi)
418   {
419     case lam:
420       mpi = "lam";
421       break;
422     case mpich1:
423       mpi = "mpich1";
424       break;
425     case mpich2:
426       mpi = "mpich2";
427       break;
428     case openmpi:
429       mpi = "openmpi";
430       break;
431     case ompi:
432       mpi = "ompi";
433       break;
434     case slurmmpi:
435       mpi = "slurmmpi";
436       break;
437     case prun:
438       mpi = "prun";
439       break;
440     default:
441       mpi = "nompi";
442   }
443
444   const char * bmType;
445   switch( params.Batch )
446   {
447     case pbs:
448       bmType = "PBS";
449       break;
450     case lsf:
451       bmType = "LSF";
452       break;
453     case sge:
454       bmType = "SGE";
455       break;
456     case ccc:
457       bmType = "CCC";
458       break;
459     case slurm:
460       bmType = "SLURM";
461       break;
462     case none:
463       bmType = "LOCAL";
464       break;
465     case ll:
466       bmType = "LL";
467       break;
468     case vishnu:
469       bmType = "VISHNU";
470       break;
471     case oar:
472       bmType = "OAR";
473       break;
474     case coorm:
475       bmType = "COORM";
476       break;
477     default:
478       LAUNCHER_MESSAGE("Bad batch description of the resource: Batch = " << params.Batch);
479       throw LauncherException("No batchmanager for that cluster - Bad batch description of the resource");
480   }
481   Batch::BatchManagerCatalog & cata = Batch::BatchManagerCatalog::getInstance();
482   fact = dynamic_cast<Batch::FactBatchManager*>(cata(bmType));
483   if (fact == NULL) {
484     LAUNCHER_MESSAGE("Cannot find batch manager factory for " << bmType << ". Check your version of libBatch.");
485     throw LauncherException("Cannot find batch manager factory");
486   }
487   LAUNCHER_MESSAGE("Instanciation of batch manager of type: " << bmType);
488   Batch::BatchManager * batch_client = (*fact)(hostname.c_str(), params.UserName.c_str(),
489                                                protocol, mpi.c_str());
490   return batch_client;
491 }
492
493 //----------------------------------------------------------
494 // Without LIBBATCH - Launcher_cpp do nothing...
495 //----------------------------------------------------------
496 #else
497
498 void 
499 Launcher_cpp::createJob(Launcher::Job * new_job)
500 {
501   LAUNCHER_INFOS("Launcher compiled without LIBBATCH - cannot create a job !!!");
502   delete new_job;
503   throw LauncherException("Method Launcher_cpp::createJob is not available "
504                           "(libBatch was not present at compilation time)");
505 }
506
507 void 
508 Launcher_cpp::launchJob(int job_id)
509 {
510   LAUNCHER_INFOS("Launcher compiled without LIBBATCH - cannot launch a job !!!");
511   throw LauncherException("Method Launcher_cpp::launchJob is not available "
512                           "(libBatch was not present at compilation time)");
513 }
514
515 const char *
516 Launcher_cpp::getJobState(int job_id)
517 {
518   LAUNCHER_INFOS("Launcher compiled without LIBBATCH - cannot get job state!!!");
519   throw LauncherException("Method Launcher_cpp::getJobState is not available "
520                           "(libBatch was not present at compilation time)");
521 }
522
523 const char *
524 Launcher_cpp::getAssignedHostnames(int job_id)
525 {
526   LAUNCHER_INFOS("Launcher compiled without LIBBATCH - cannot get job assigned hostnames!!!");
527   throw LauncherException("Method Launcher_cpp::getAssignedHostnames is not available "
528                           "(libBatch was not present at compilation time)");
529 }
530
531 void
532 Launcher_cpp::getJobResults(int job_id, std::string directory)
533 {
534   LAUNCHER_INFOS("Launcher compiled without LIBBATCH - cannot get job results!!!");
535   throw LauncherException("Method Launcher_cpp::getJobResults is not available "
536                           "(libBatch was not present at compilation time)");
537 }
538
539 bool
540 Launcher_cpp::getJobDumpState(int job_id, std::string directory)
541 {
542   LAUNCHER_INFOS("Launcher compiled without LIBBATCH - cannot get job dump state!!!");
543   throw LauncherException("Method Launcher_cpp::getJobDumpState is not available "
544                           "(libBatch was not present at compilation time)");
545 }
546
547 void
548 Launcher_cpp::removeJob(int job_id)
549 {
550   LAUNCHER_INFOS("Launcher compiled without LIBBATCH - cannot remove job!!!");
551   throw LauncherException("Method Launcher_cpp::removeJob is not available "
552                           "(libBatch was not present at compilation time)");
553 }
554
555 void
556 Launcher_cpp::stopJob(int job_id)
557 {
558   throw LauncherException("Method Launcher_cpp::stopJob is not available "
559                           "(libBatch was not present at compilation time)");
560 }
561
562 long 
563 Launcher_cpp::createJobWithFile( const std::string xmlExecuteFile, std::string clusterName)
564 {
565   throw LauncherException("Method Launcher_cpp::createJobWithFile is not available "
566                           "(libBatch was not present at compilation time)");
567   return 0;
568 }
569
570 #endif
571
572 ParserLauncherType 
573 Launcher_cpp::ParseXmlFile(std::string xmlExecuteFile)
574 {
575   ParserLauncherType job_params;
576   SALOME_Launcher_Handler * handler = new SALOME_Launcher_Handler(job_params);
577
578   const char* aFilePath = xmlExecuteFile.c_str();
579   FILE* aFile = fopen(aFilePath, "r");
580   if (aFile != NULL)
581   {
582     xmlDocPtr aDoc = xmlReadFile(aFilePath, NULL, 0);
583     if (aDoc != NULL)
584       handler->ProcessXmlDocument(aDoc);
585     else
586     {
587       std::string message = "ResourcesManager_cpp: could not parse file: " + xmlExecuteFile;
588       LAUNCHER_MESSAGE(message);
589       delete handler;
590       throw LauncherException(message);
591     }
592     // Free the document
593     xmlFreeDoc(aDoc);
594     fclose(aFile);
595   }
596   else
597   {
598     std::string message = "ResourcesManager_cpp: file is not readable: " + xmlExecuteFile;
599     LAUNCHER_MESSAGE(message);
600     delete handler;
601     throw LauncherException(message);
602   }
603
604   // Return
605   delete handler;
606   return job_params;
607 }
608
609 std::map<int, Launcher::Job *>
610 Launcher_cpp::getJobs()
611 {
612   return _launcher_job_map;
613 }
614
615 void 
616 Launcher_cpp::createBatchManagerForJob(Launcher::Job * job)
617 {
618   int job_id = job->getNumber();
619
620   // Select a ressource for the job
621   std::vector<std::string> ResourceList;
622   resourceParams params = job->getResourceRequiredParams();
623   // Consider only resources that can launch batch jobs
624   params.can_launch_batch_jobs = true;
625   try
626   {
627     ResourceList = _ResManager->GetFittingResources(params);
628   }
629   catch(const ResourcesException &ex)
630   {
631     throw LauncherException(ex.msg.c_str());
632   }
633   if (ResourceList.size() == 0)
634   {
635     LAUNCHER_INFOS("No adequate resource found for the job, number " << job->getNumber());
636     job->setState("ERROR");
637     throw LauncherException("No resource found the job");
638   }
639
640   // Configure the job with the resource selected - the first of the list
641   ParserResourcesType resource_definition = _ResManager->GetResourcesDescr(ResourceList[0]);
642
643   // Set resource definition to the job
644   // The job will check if the definitions needed
645   try
646   {
647     job->setResourceDefinition(resource_definition);
648   }
649   catch(const LauncherException &ex)
650   {
651     LAUNCHER_INFOS("Error in the definition of the resource, mess: " << ex.msg);
652     job->setState("ERROR");
653     throw ex;
654   }
655
656   // Step 2: We can now add a Factory if the resource is correctly define
657 #ifdef WITH_LIBBATCH
658   std::map<int, Batch::BatchManager *>::const_iterator it = _batchmap.find(job_id);
659   if(it == _batchmap.end())
660   {
661     try
662     {
663       // Warning cannot write on one line like this, because map object is constructed before
664       // the method is called...
665       //_batchmap[job_id] = FactoryBatchManager(resource_definition);
666       Batch::BatchManager * batch_client = FactoryBatchManager(resource_definition);
667       _batchmap[job_id] = batch_client;
668     }
669     catch(const LauncherException &ex)
670     {
671       LAUNCHER_INFOS("Error during creation of the batch manager of the job, mess: " << ex.msg);
672       throw ex;
673     }
674     catch(const Batch::GenericException &ex)
675     {
676       LAUNCHER_INFOS("Error during creation of the batch manager of the job, mess: " << ex.message);
677       throw LauncherException(ex.message);
678     }
679   }
680 #endif
681 }
682
683 void 
684 Launcher_cpp::addJobDirectlyToMap(Launcher::Job * new_job)
685 {
686   // Step 0: Calculated job_id
687   pthread_mutex_lock(_job_cpt_mutex);
688   int job_id = _job_cpt;
689   _job_cpt++;
690   new_job->setNumber(job_id);
691   pthread_mutex_unlock(_job_cpt_mutex);
692
693   // Step 1: check if resource is already in the map
694   createBatchManagerForJob(new_job);
695
696   // Step 2: add the job to the batch manager
697 #ifdef WITH_LIBBATCH
698   try
699   {
700     Batch::JobId batch_manager_job_id = _batchmap[job_id]->addJob(*(new_job->getBatchJob()),
701                                                                   new_job->getReference());
702     new_job->setBatchManagerJobId(batch_manager_job_id);
703   }
704   catch(const Batch::GenericException &ex)
705   {
706     LAUNCHER_INFOS("Job cannot be added, exception in addJob: " << ex.message);
707     throw LauncherException(ex.message.c_str());
708   }
709
710   // Step 3: add job to launcher map
711   std::map<int, Launcher::Job *>::const_iterator it_job = _launcher_job_map.find(new_job->getNumber());
712   if (it_job == _launcher_job_map.end())
713     _launcher_job_map[new_job->getNumber()] = new_job;
714   else
715   {
716     LAUNCHER_INFOS("A job as already the same id: " << new_job->getNumber());
717     delete new_job;
718     throw LauncherException("A job as already the same id - job is not created !");
719   }
720   LAUNCHER_MESSAGE("New job added");
721 #endif
722 }
723
724 list<int>
725 Launcher_cpp::loadJobs(const char* jobs_file)
726 {
727   list<int> new_jobs_id_list;
728
729   // Load the jobs from XML file
730   list<Launcher::Job *> jobs_list = Launcher::XML_Persistence::loadJobs(jobs_file);
731
732   // Create each job in the launcher
733   list<Launcher::Job *>::const_iterator it_job;
734   for (it_job = jobs_list.begin(); it_job != jobs_list.end(); it_job++)
735   {
736     Launcher::Job * new_job = *it_job;
737     string job_state = new_job->getState();
738
739     try
740     {
741       if (job_state == "CREATED")
742       {
743         // In this case, we ignore run_part informations
744         createJob(new_job);
745         new_jobs_id_list.push_back(new_job->getNumber());
746       }
747       else if (job_state == "QUEUED"     ||
748                job_state == "RUNNING"    ||
749                job_state == "IN_PROCESS" ||
750                job_state == "PAUSED")
751       {
752         addJobDirectlyToMap(new_job);
753         new_jobs_id_list.push_back(new_job->getNumber());
754
755         // Step 4: We check that the BatchManager could resume
756         // the job
757 #ifdef WITH_LIBBATCH
758         if (new_job->getBatchManagerJobId().getReference() != new_job->getReference())
759         {
760           LAUNCHER_INFOS("BatchManager type cannot resume a job - job state is set to ERROR");
761           new_job->setState("ERROR");
762         }
763 #endif
764       }
765       else if (job_state == "FINISHED" ||
766                job_state == "FAILED"   ||
767                job_state == "ERROR")
768       {
769         // Step 2: We add run_part informations
770         addJobDirectlyToMap(new_job);
771         new_jobs_id_list.push_back(new_job->getNumber());
772       }
773       else
774       {
775         LAUNCHER_INFOS("A bad job is found, state unknown " << job_state);
776         delete new_job;
777       }
778     }
779     catch(const LauncherException &ex)
780     {
781       LAUNCHER_INFOS("Cannot load the job. Exception: " << ex.msg.c_str());
782       delete new_job;
783     }
784   }
785
786   return new_jobs_id_list;
787 }
788
789 void
790 Launcher_cpp::saveJobs(const char* jobs_file)
791 {
792   // Create a sorted list from the internal job map
793   list<const Launcher::Job *> jobs_list;
794   for (int i=0; i<_job_cpt; i++)
795   {
796     map<int, Launcher::Job *>::const_iterator it_job = _launcher_job_map.find(i);
797     if (it_job != _launcher_job_map.end())
798       jobs_list.push_back(it_job->second);
799   }
800
801   // Save the jobs in XML file
802   Launcher::XML_Persistence::saveJobs(jobs_file, jobs_list);
803 }