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