Salome HOME
Merge from V6_main 01/04/2013
[modules/yacs.git] / src / Launcher / SALOME_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 "SALOME_Launcher.hxx"
24 #include "BatchTest.hxx"
25 #include "OpUtil.hxx"
26 #include "SALOME_ContainerManager.hxx"
27 #include "Utils_CorbaException.hxx"
28
29
30 #include "Launcher_Job_Command.hxx"
31 #include "Launcher_Job_YACSFile.hxx"
32 #include "Launcher_Job_PythonSALOME.hxx"
33
34 #ifdef WIN32
35 # include <process.h>
36 #else
37 # include <unistd.h>
38 #endif
39 #include <sys/types.h>
40 #include <vector>
41
42 #include <libxml/parser.h>
43 #include <stdio.h>
44 #include <sstream>
45
46 const char *SALOME_Launcher::_LauncherNameInNS = "/SalomeLauncher";
47
48 //=============================================================================
49 /*! 
50  *  Constructor
51  *  \param orb
52  */
53 //=============================================================================
54 SALOME_Launcher::SALOME_Launcher(CORBA::ORB_ptr orb, PortableServer::POA_var poa) : _l()
55 {
56   MESSAGE("SALOME_Launcher constructor");
57   _NS = new SALOME_NamingService(orb);
58   _ResManager = new SALOME_ResourcesManager(orb,poa,_NS);
59   _l.SetResourcesManager(_ResManager->GetImpl());
60   _ContManager = new SALOME_ContainerManager(orb,poa,_ResManager,_NS);
61   _ResManager->_remove_ref();
62   _ContManager->_remove_ref();
63
64   _orb = CORBA::ORB::_duplicate(orb) ;
65   _poa = PortableServer::POA::_duplicate(poa) ;
66   PortableServer::ObjectId_var id = _poa->activate_object(this);
67   CORBA::Object_var obj = _poa->id_to_reference(id);
68   Engines::SalomeLauncher_var refContMan = Engines::SalomeLauncher::_narrow(obj);
69
70   _NS->Register(refContMan,_LauncherNameInNS);
71   MESSAGE("SALOME_Launcher constructor end");
72 }
73
74 //=============================================================================
75 /*! 
76  * destructor
77  */
78 //=============================================================================
79 SALOME_Launcher::~SALOME_Launcher()
80 {
81   MESSAGE("SALOME_Launcher destructor");
82   delete _NS;
83   MESSAGE("SALOME_Launcher destructor end");
84 }
85
86
87 CORBA::Long 
88 SALOME_Launcher::createJob(const Engines::JobParameters & job_parameters)
89 {
90   std::string job_type = job_parameters.job_type.in();
91
92   if (job_type != "command" && job_type != "yacs_file" && job_type != "python_salome")
93   {
94     std::string message("SALOME_Launcher::createJob: bad job type: ");
95     message += job_type;
96     THROW_SALOME_CORBA_EXCEPTION(message.c_str(), SALOME::INTERNAL_ERROR);
97   }
98
99   Launcher::Job * new_job; // It is Launcher_cpp that is going to destroy it
100
101   if (job_type == "command")
102     new_job = new Launcher::Job_Command();
103   else if (job_type == "yacs_file")
104     new_job = new Launcher::Job_YACSFile();
105   else if (job_type == "python_salome")
106     new_job = new Launcher::Job_PythonSALOME();
107
108   // Name
109   new_job->setJobName(job_parameters.job_name.in());
110
111   // Directories
112   std::string work_directory = job_parameters.work_directory.in();
113   std::string local_directory = job_parameters.local_directory.in();
114   std::string result_directory = job_parameters.result_directory.in();
115   new_job->setWorkDirectory(work_directory);
116   new_job->setLocalDirectory(local_directory);
117   new_job->setResultDirectory(result_directory);
118
119   // Job File
120   std::string job_file = job_parameters.job_file.in();
121   try
122   {
123     new_job->setJobFile(job_file);
124   }
125   catch(const LauncherException &ex)
126   {
127     INFOS(ex.msg.c_str());
128     THROW_SALOME_CORBA_EXCEPTION(ex.msg.c_str(),SALOME::INTERNAL_ERROR);
129   }
130
131   // Files
132   std::string env_file = job_parameters.env_file.in();
133   new_job->setEnvFile(env_file);
134   for (CORBA::ULong i = 0; i < job_parameters.in_files.length(); i++)
135     new_job->add_in_file(job_parameters.in_files[i].in());
136   for (CORBA::ULong i = 0; i < job_parameters.out_files.length(); i++)
137     new_job->add_out_file(job_parameters.out_files[i].in());
138
139   // Expected During Time
140   try
141   {
142     std::string maximum_duration = job_parameters.maximum_duration.in();
143     new_job->setMaximumDuration(maximum_duration);
144   }
145   catch(const LauncherException &ex){
146     INFOS(ex.msg.c_str());
147     THROW_SALOME_CORBA_EXCEPTION(ex.msg.c_str(),SALOME::INTERNAL_ERROR);
148   }
149
150   // Queue
151   std::string queue = job_parameters.queue.in();
152   new_job->setQueue(queue);
153
154   // Resources requirements
155   try
156   {
157     resourceParams p;
158     p.name = job_parameters.resource_required.name;
159     p.hostname = job_parameters.resource_required.hostname;
160     p.OS = job_parameters.resource_required.OS;
161     p.nb_proc = job_parameters.resource_required.nb_proc;
162     p.nb_node = job_parameters.resource_required.nb_node;
163     p.nb_proc_per_node = job_parameters.resource_required.nb_proc_per_node;
164     p.cpu_clock = job_parameters.resource_required.cpu_clock;
165     p.mem_mb = job_parameters.resource_required.mem_mb;
166     new_job->setResourceRequiredParams(p);
167   }
168   catch(const LauncherException &ex){
169     INFOS(ex.msg.c_str());
170     THROW_SALOME_CORBA_EXCEPTION(ex.msg.c_str(),SALOME::INTERNAL_ERROR);
171   }
172
173   // Adding specific parameters to the job
174   for (CORBA::ULong i = 0; i < job_parameters.specific_parameters.length(); i++)
175     new_job->addSpecificParameter(job_parameters.specific_parameters[i].name.in(),
176                                   job_parameters.specific_parameters[i].value.in());
177   try
178   {
179     new_job->checkSpecificParameters();
180   }
181   catch(const LauncherException &ex)
182   {
183     INFOS(ex.msg.c_str());
184     THROW_SALOME_CORBA_EXCEPTION(ex.msg.c_str(),SALOME::INTERNAL_ERROR);
185   }
186
187   try
188   {
189     _l.createJob(new_job);
190     std::ostringstream job_id;
191     job_id << new_job->getNumber();
192     notifyObservers("NEW_JOB", job_id.str());
193   }
194   catch(const LauncherException &ex)
195   {
196     INFOS(ex.msg.c_str());
197     THROW_SALOME_CORBA_EXCEPTION(ex.msg.c_str(),SALOME::BAD_PARAM);
198   }
199   return new_job->getNumber();
200 }
201
202 void 
203 SALOME_Launcher::launchJob(CORBA::Long job_id)
204 {
205   try
206   {
207     _l.launchJob(job_id);
208   }
209   catch(const LauncherException &ex)
210   {
211     INFOS(ex.msg.c_str());
212     THROW_SALOME_CORBA_EXCEPTION(ex.msg.c_str(),SALOME::BAD_PARAM);
213   }
214 }
215
216 char *
217 SALOME_Launcher::getJobState(CORBA::Long job_id)
218 {
219   std::string result;
220   try
221   {
222     result = _l.getJobState(job_id);
223   }
224   catch(const LauncherException &ex)
225   {
226     INFOS(ex.msg.c_str());
227     THROW_SALOME_CORBA_EXCEPTION(ex.msg.c_str(),SALOME::BAD_PARAM);
228   }
229   return CORBA::string_dup(result.c_str());
230 }
231
232 void
233 SALOME_Launcher::getJobResults(CORBA::Long job_id, const char * directory)
234 {
235   try
236   {
237     _l.getJobResults(job_id, directory);
238   }
239   catch(const LauncherException &ex)
240   {
241     INFOS(ex.msg.c_str());
242     THROW_SALOME_CORBA_EXCEPTION(ex.msg.c_str(),SALOME::BAD_PARAM);
243   }
244 }
245
246 CORBA::Boolean
247 SALOME_Launcher::getJobDumpState(CORBA::Long job_id, const char * directory)
248 {
249   CORBA::Boolean rtn = false;
250   try
251   {
252     rtn = _l.getJobDumpState(job_id, directory);
253   }
254   catch(const LauncherException &ex)
255   {
256     INFOS(ex.msg.c_str());
257     THROW_SALOME_CORBA_EXCEPTION(ex.msg.c_str(),SALOME::BAD_PARAM);
258   }
259   return rtn;
260 }
261
262 void 
263 SALOME_Launcher::removeJob(CORBA::Long job_id)
264 {
265   try
266   {
267     _l.removeJob(job_id);
268     std::ostringstream job_id_str;
269     job_id_str << job_id;
270     notifyObservers("REMOVE_JOB", job_id_str.str());
271   }
272   catch(const LauncherException &ex)
273   {
274     INFOS(ex.msg.c_str());
275     THROW_SALOME_CORBA_EXCEPTION(ex.msg.c_str(),SALOME::BAD_PARAM);
276   }
277 }
278
279 void 
280 SALOME_Launcher::stopJob(CORBA::Long job_id)
281 {
282   try
283   {
284     _l.stopJob(job_id);
285     std::ostringstream job_id_str;
286     job_id_str << job_id;
287     notifyObservers("UPDATE_JOB_STATE", job_id_str.str());
288   }
289   catch(const LauncherException &ex)
290   {
291     INFOS(ex.msg.c_str());
292     THROW_SALOME_CORBA_EXCEPTION(ex.msg.c_str(),SALOME::BAD_PARAM);
293   }
294 }
295
296 //=============================================================================
297 /*! CORBA Method:
298  *  Create a job in the launcher with a file
299  *  \param xmlExecuteFile     : .xml to parse that contains job description
300  *  \param clusterName        : machine choosed
301  */
302 //=============================================================================
303 CORBA::Long 
304 SALOME_Launcher::createJobWithFile(const char * xmlExecuteFile,
305                                    const char * clusterName)
306 {
307   CORBA::Long jobId;
308   try{
309     jobId = _l.createJobWithFile(xmlExecuteFile, clusterName);
310   }
311   catch(const LauncherException &ex){
312     INFOS(ex.msg.c_str());
313     THROW_SALOME_CORBA_EXCEPTION(ex.msg.c_str(),SALOME::INTERNAL_ERROR);
314   }
315
316   return jobId;
317 }
318
319 //=============================================================================
320 /*! CORBA Method:
321  *  the test batch configuration 
322  *  \param params             : The batch cluster
323  */
324 //=============================================================================
325 CORBA::Boolean 
326 SALOME_Launcher::testBatch(const Engines::ResourceParameters& params)
327 {
328   MESSAGE("BEGIN OF SALOME_Launcher::testBatch");
329   CORBA::Boolean rtn = false;
330   try
331   {
332     // Consider only resources that can run batch jobs
333     Engines::ResourceParameters new_params(params);
334     new_params.can_launch_batch_jobs = true;
335
336     // find a resource matching the required parameters
337     Engines::ResourceList *aMachineList = _ResManager->GetFittingResources(new_params);
338     if (aMachineList->length() == 0)
339       throw SALOME_Exception("No resources have been found with your parameters");
340
341     const Engines::ResourceDefinition* p = _ResManager->GetResourceDefinition((*aMachineList)[0]);
342         std::string resource_name(p->name);
343     INFOS("Choose resource for test: " <<  resource_name);
344     
345     BatchTest t(*p);
346     if (t.test()) 
347     {
348       rtn = true;
349     }
350   }
351   catch(const LauncherException &ex){
352     INFOS(ex.msg.c_str());
353     THROW_SALOME_CORBA_EXCEPTION(ex.msg.c_str(),SALOME::INTERNAL_ERROR);
354   }
355   return rtn;
356 }
357
358 //=============================================================================
359 /*! CORBA method:
360  *  shutdown all the containers, then the ContainerManager servant
361  */
362 //=============================================================================
363 void SALOME_Launcher::Shutdown()
364 {
365   MESSAGE("Shutdown");
366   _NS->Destroy_Name(_LauncherNameInNS);
367   _ContManager->Shutdown();
368   _ResManager->Shutdown();
369   PortableServer::ObjectId_var oid = _poa->servant_to_id(this);
370   _poa->deactivate_object(oid);
371   if(!CORBA::is_nil(_orb))
372     _orb->shutdown(0);
373 }
374
375 //=============================================================================
376 /*! CORBA Method:
377  *  Returns the PID of the process
378  */
379 //=============================================================================
380 CORBA::Long SALOME_Launcher::getPID()
381 {
382   return 
383 #ifndef WIN32
384     (CORBA::Long)getpid();
385 #else
386     (CORBA::Long)_getpid();
387 #endif
388 }
389
390 //=============================================================================
391 /*! CORBA Method:
392  *  Returns current launcher jobs list
393  */
394 //=============================================================================
395 Engines::JobsList *
396 SALOME_Launcher::getJobsList()
397 {
398   Engines::JobsList_var jobs_list = new Engines::JobsList();
399   std::map<int, Launcher::Job *> cpp_jobs = _l.getJobs();
400   std::map<int, Launcher::Job *>::const_iterator it_job;
401   int list_id = 0;
402   for(it_job = cpp_jobs.begin(); it_job != cpp_jobs.end(); it_job++)
403   {
404     int number          = it_job->first;
405     try
406     {
407       // Prepare CORBA job description
408       Engines::JobDescription_var job_descr = new Engines::JobDescription();
409       Engines::JobParameters_var job_parameters = getJobParameters(number);
410       job_descr->job_id = number;
411       job_descr->job_parameters = job_parameters;
412
413       // Add job description to the sequence
414       jobs_list->length(list_id + 1);
415       jobs_list[list_id] = job_descr;
416       list_id++;
417     }
418     catch (...) {}
419   }
420   return jobs_list._retn();
421 }
422
423 //=============================================================================
424 /*! CORBA Method:
425  * Returns the job description
426  */
427 //=============================================================================
428 Engines::JobParameters *
429 SALOME_Launcher::getJobParameters(CORBA::Long job_id)
430 {
431   std::map<int, Launcher::Job *> cpp_jobs = _l.getJobs();
432   std::map<int, Launcher::Job *>::const_iterator it_job = cpp_jobs.find(job_id);
433   if (it_job == cpp_jobs.end())
434   {
435     INFOS("Cannot find the job, is it created ? job number: " << job_id);
436     THROW_SALOME_CORBA_EXCEPTION("Job does not exist", SALOME::INTERNAL_ERROR);
437   }
438
439   Launcher::Job * job = it_job->second;
440   Engines::JobParameters_var job_parameters = new Engines::JobParameters;
441   job_parameters->job_name         = CORBA::string_dup(job->getJobName().c_str());
442   job_parameters->job_type         = CORBA::string_dup(job->getJobType().c_str());
443   job_parameters->job_file         = CORBA::string_dup(job->getJobFile().c_str());
444   job_parameters->env_file         = CORBA::string_dup(job->getEnvFile().c_str());
445   job_parameters->work_directory   = CORBA::string_dup(job->getWorkDirectory().c_str());
446   job_parameters->local_directory  = CORBA::string_dup(job->getLocalDirectory().c_str());
447   job_parameters->result_directory = CORBA::string_dup(job->getResultDirectory().c_str());
448
449   int i = 0;
450   int j = 0;
451   std::list<std::string> in_files  = job->get_in_files();
452   std::list<std::string> out_files = job->get_out_files();
453   job_parameters->in_files.length(in_files.size());
454   for(std::list<std::string>::iterator it = in_files.begin(); it != in_files.end(); it++)
455   {
456     job_parameters->in_files[i] = CORBA::string_dup((*it).c_str());
457     i++;
458   }
459   job_parameters->out_files.length(out_files.size());
460   for(std::list<std::string>::iterator it = out_files.begin(); it != out_files.end(); it++)
461   {
462     job_parameters->out_files[j] = CORBA::string_dup((*it).c_str());
463     j++;
464   }
465
466   job_parameters->maximum_duration = CORBA::string_dup(job->getMaximumDuration().c_str());
467   job_parameters->queue            = CORBA::string_dup(job->getQueue().c_str());
468
469   resourceParams resource_params = job->getResourceRequiredParams();
470   job_parameters->resource_required.name             = CORBA::string_dup(resource_params.name.c_str());
471   job_parameters->resource_required.hostname         = CORBA::string_dup(resource_params.hostname.c_str());
472   job_parameters->resource_required.OS               = CORBA::string_dup(resource_params.OS.c_str());
473   job_parameters->resource_required.nb_proc          = resource_params.nb_proc;
474   job_parameters->resource_required.nb_node          = resource_params.nb_node;
475   job_parameters->resource_required.nb_proc_per_node = resource_params.nb_proc_per_node;
476   job_parameters->resource_required.cpu_clock        = resource_params.cpu_clock;
477   job_parameters->resource_required.mem_mb           = resource_params.mem_mb;
478
479   std::map<std::string, std::string> specific_parameters = job->getSpecificParameters();
480   if (!specific_parameters.empty())
481   {
482     job_parameters->specific_parameters.length(specific_parameters.size());
483     std::map<std::string, std::string>::const_iterator it_specific;
484     CORBA::ULong i = 0;
485     for (it_specific = specific_parameters.begin() ; it_specific != specific_parameters.end(); it_specific++)
486     {
487       Engines::Parameter_var new_param = new Engines::Parameter;
488       new_param->name  = CORBA::string_dup((it_specific->first).c_str());
489       new_param->value = CORBA::string_dup((it_specific->second).c_str());
490       job_parameters->specific_parameters[i] = new_param;
491       i++;
492     }
493   }
494
495   return job_parameters._retn();
496 }
497
498 //=============================================================================
499 /*! CORBA Method:
500  *  Loads jobs saved in jobs_file
501  */
502 //=============================================================================
503 void
504 SALOME_Launcher::loadJobs(const char* jobs_file)
505 {
506   // Step 1: check jobs_file read access
507   FILE* xml_file = fopen(jobs_file, "r");
508   if (xml_file == NULL)
509   {
510     std::string error = "Error opening jobs_file in SALOME_Launcher::loadJobs: " + std::string(jobs_file);
511     INFOS(error);
512     THROW_SALOME_CORBA_EXCEPTION(error.c_str(), SALOME::INTERNAL_ERROR);
513   }
514
515   // Step 2: read xml file
516   xmlDocPtr doc = xmlReadFile(jobs_file, NULL, 0);
517   if (doc == NULL)
518   {
519     std::string error = "Error in xmlReadFile in SALOME_Launcher::loadJobs, could not parse file: " + std::string(jobs_file);
520     INFOS(error);
521     fclose(xml_file);
522     THROW_SALOME_CORBA_EXCEPTION(error.c_str(), SALOME::INTERNAL_ERROR);
523   }
524
525   // Step 3: Find jobs
526   xmlNodePtr root_node = xmlDocGetRootElement(doc);
527   xmlNodePtr xmlCurrentNode = root_node->xmlChildrenNode;
528   if (!xmlStrcmp(root_node->name, xmlCharStrdup("jobs")))
529   {
530     while(xmlCurrentNode != NULL)
531     {
532       if (!xmlStrcmp(xmlCurrentNode->name, xmlCharStrdup("job")))
533       {
534         INFOS("A job is found");
535         Launcher::Job * new_job; // It is Launcher_cpp that is going to destroy it
536         xmlNodePtr job_node = xmlCurrentNode;
537
538         // Begin Job
539         if (!xmlHasProp(job_node, xmlCharStrdup("type"))  ||
540             !xmlHasProp(job_node, xmlCharStrdup("name")))
541         {
542           INFOS("A bad job is found, type or name not found");
543           break;
544         }
545         xmlChar* type = xmlGetProp(job_node, xmlCharStrdup("type"));
546         xmlChar* name = xmlGetProp(job_node, xmlCharStrdup("name"));
547         std::string job_type((const char*) type);
548         if (job_type == "command")
549           new_job = new Launcher::Job_Command();
550         else if (job_type == "yacs_file")
551           new_job = new Launcher::Job_YACSFile();
552         else if (job_type == "python_salome")
553           new_job = new Launcher::Job_PythonSALOME();
554         new_job->setJobName(std::string((const char *)name));
555         xmlFree(type);
556         xmlFree(name);
557
558         xmlNodePtr user_node = xmlFirstElementChild(job_node);
559         xmlNodePtr run_node = xmlNextElementSibling(user_node);
560         if (user_node == NULL || run_node == NULL)
561         {
562           INFOS("A bad job is found, user_part or run_part not found");
563           delete new_job;
564           break;
565         }
566         if (xmlStrcmp(user_node->name, xmlCharStrdup("user_part")) ||
567             xmlStrcmp(run_node->name, xmlCharStrdup("run_part")))
568         {
569           INFOS("A bad job is found, cannot get a correct user_part or run_part node");
570           delete new_job;
571           break;
572         }
573
574         // Add user part
575
576         // Get job_file env_file work_directory local_directory result_directory
577         xmlNodePtr job_file_node         = xmlFirstElementChild(user_node);
578         xmlNodePtr env_file_node         = xmlNextElementSibling(job_file_node);
579         xmlNodePtr work_directory_node   = xmlNextElementSibling(env_file_node);
580         xmlNodePtr local_directory_node  = xmlNextElementSibling(work_directory_node);
581         xmlNodePtr result_directory_node = xmlNextElementSibling(local_directory_node);
582         if (job_file_node         == NULL ||
583             env_file_node         == NULL ||
584             work_directory_node   == NULL ||
585             local_directory_node  == NULL ||
586             result_directory_node == NULL
587            )
588         {
589           INFOS("A bad job is found, some user_part are not found");
590           delete new_job;
591           break;
592         }
593         if (xmlStrcmp(job_file_node->name,         xmlCharStrdup("job_file"))         ||
594             xmlStrcmp(env_file_node->name,         xmlCharStrdup("env_file"))         ||
595             xmlStrcmp(work_directory_node->name,   xmlCharStrdup("work_directory"))   ||
596             xmlStrcmp(local_directory_node->name,  xmlCharStrdup("local_directory"))  ||
597             xmlStrcmp(result_directory_node->name, xmlCharStrdup("result_directory"))
598            )
599         {
600           INFOS("A bad job is found, some user part node are not in the rigth or does not have a correct name");
601           delete new_job;
602           break;
603         }
604         xmlChar* job_file         = xmlNodeGetContent(job_file_node);
605         try
606         {
607           new_job->setJobFile(std::string((const char *)job_file));
608         }
609         catch(const LauncherException &ex)
610         {
611           INFOS("Exception receice for job_file, cannot add the job" << ex.msg.c_str());
612           delete new_job;
613           xmlFree(job_file);
614           break;
615         }
616         xmlChar* env_file         = xmlNodeGetContent(env_file_node);
617         xmlChar* work_directory   = xmlNodeGetContent(work_directory_node);
618         xmlChar* local_directory  = xmlNodeGetContent(local_directory_node);
619         xmlChar* result_directory = xmlNodeGetContent(result_directory_node);
620         new_job->setEnvFile(std::string((const char *)env_file));
621         new_job->setWorkDirectory(std::string((const char *)work_directory));
622         new_job->setLocalDirectory(std::string((const char *)local_directory));
623         new_job->setResultDirectory(std::string((const char *)result_directory));
624         xmlFree(job_file);
625         xmlFree(env_file);
626         xmlFree(work_directory);
627         xmlFree(local_directory);
628         xmlFree(result_directory);
629
630         // Get in and out files
631         xmlNodePtr files_node = xmlNextElementSibling(result_directory_node);
632         if (files_node == NULL)
633         {
634           INFOS("A bad job is found, user_part files is not found");
635           delete new_job;
636           break;
637         }
638         if (xmlStrcmp(files_node->name, xmlCharStrdup("files")))
639         {
640           INFOS("A bad job is found, files node are not in the rigth place or does not have a correct name or does not exist");
641           delete new_job;
642           break;
643         }
644         xmlNodePtr file_node = xmlFirstElementChild(files_node);
645         while (file_node != NULL)
646         {
647           if (!xmlStrcmp(file_node->name, xmlCharStrdup("in_file")))
648           {
649             xmlChar* in_file = xmlNodeGetContent(file_node);
650             new_job->add_in_file(std::string((const char *)in_file));
651             xmlFree(in_file);
652           }
653           else if (!xmlStrcmp(file_node->name, xmlCharStrdup("out_file")))
654           {
655             xmlChar* out_file = xmlNodeGetContent(file_node);
656             new_job->add_out_file(std::string((const char *)out_file));
657             xmlFree(out_file);
658           }
659           file_node = xmlNextElementSibling(file_node);
660         }
661
662         // Get resource part
663         xmlNodePtr res_node = xmlNextElementSibling(files_node);
664         xmlNodePtr maximum_duration_node = xmlNextElementSibling(res_node);
665         xmlNodePtr queue_node = xmlNextElementSibling(maximum_duration_node);
666         if (res_node              == NULL ||
667             maximum_duration_node == NULL ||
668             queue_node            == NULL
669            )
670         {
671           INFOS("A bad job is found, some user_part are not found");
672           delete new_job;
673           break;
674         }
675         if (xmlStrcmp(res_node->name,              xmlCharStrdup("resource_params"))  ||
676             xmlStrcmp(maximum_duration_node->name, xmlCharStrdup("maximum_duration")) ||
677             xmlStrcmp(queue_node->name,            xmlCharStrdup("queue"))
678            )
679         {
680           INFOS("A bad job is found, some user part node are not in the rigth or does not have a correct name");
681           delete new_job;
682           break;
683         }
684         xmlChar* maximum_duration = xmlNodeGetContent(maximum_duration_node);
685         try
686         {
687           new_job->setMaximumDuration(std::string((const char *)maximum_duration));
688         }
689         catch(const LauncherException &ex)
690         {
691           INFOS("Exception receice for maximum_duration, cannot add the job" << ex.msg.c_str());
692           delete new_job;
693           xmlFree(maximum_duration);
694           break;
695         }
696         xmlChar* queue            = xmlNodeGetContent(queue_node);
697         new_job->setQueue(std::string((const char *)queue));
698         xmlFree(maximum_duration);
699         xmlFree(queue);
700
701         xmlNodePtr specific_node = xmlNextElementSibling(queue_node);
702         if (specific_node == NULL)
703         {
704           INFOS("A bad job is found, specific_parameters part is not found");
705           delete new_job;
706           break;
707         }
708         xmlNodePtr parameter_node = xmlFirstElementChild(specific_node);
709         while (parameter_node != NULL)
710         {
711           if (!xmlStrcmp(parameter_node->name, xmlCharStrdup("specific_parameter")))
712           {
713             xmlNodePtr name_node = xmlFirstElementChild(parameter_node);
714             xmlNodePtr value_node = xmlNextElementSibling(name_node);
715             if (name_node == NULL ||
716                 value_node == NULL)
717             {
718               INFOS("A bad job is found, specific_parameter parts are not found");
719               delete new_job;
720               break;
721             }
722             if (xmlStrcmp(name_node->name, xmlCharStrdup("name")) ||
723                 xmlStrcmp(value_node->name, xmlCharStrdup("value")))
724             {
725               INFOS("A bad job is found, specific_parameter bad parts are found");
726               delete new_job;
727               break;
728             }
729
730             xmlChar* name  = xmlNodeGetContent(name_node);
731             xmlChar* value = xmlNodeGetContent(value_node);
732             try
733             {
734               new_job->addSpecificParameter(std::string((const char*)name), std::string((const char*)value));
735               xmlFree(name);
736               xmlFree(value);
737             }
738             catch(const LauncherException &ex)
739             {
740               INFOS("Exception receice for a specific parameter, cannot add the job" << ex.msg.c_str());
741               delete new_job;
742               xmlFree(name);
743               xmlFree(value);
744               break;
745             }
746           }
747           else
748           {
749             INFOS("A bad job is found, specific_parameters part is bad, a node that is not a specific parameter is found");
750             delete new_job;
751             break;
752           }
753           parameter_node = xmlNextElementSibling(parameter_node);
754         }
755
756         xmlNodePtr res_name_node             = xmlFirstElementChild(res_node);
757         xmlNodePtr res_hostname_node         = xmlNextElementSibling(res_name_node);
758         xmlNodePtr res_os_node               = xmlNextElementSibling(res_hostname_node);
759         xmlNodePtr res_nb_proc_node          = xmlNextElementSibling(res_os_node);
760         xmlNodePtr res_nb_node_node          = xmlNextElementSibling(res_nb_proc_node);
761         xmlNodePtr res_nb_proc_per_node_node = xmlNextElementSibling(res_nb_node_node);
762         xmlNodePtr res_cpu_clock_node        = xmlNextElementSibling(res_nb_proc_per_node_node);
763         xmlNodePtr res_mem_mb_node           = xmlNextElementSibling(res_cpu_clock_node);
764         if (res_name_node             == NULL ||
765             res_hostname_node         == NULL ||
766             res_os_node               == NULL ||
767             res_nb_proc_node          == NULL ||
768             res_nb_node_node          == NULL ||
769             res_nb_proc_per_node_node == NULL ||
770             res_cpu_clock_node        == NULL ||
771             res_mem_mb_node           == NULL
772            )
773         {
774           INFOS("A bad job is found, some resource_params user_part are not found");
775           delete new_job;
776           break;
777         }
778         if (xmlStrcmp(res_name_node->name,             xmlCharStrdup("name"))             ||
779             xmlStrcmp(res_hostname_node->name,         xmlCharStrdup("hostname"))         ||
780             xmlStrcmp(res_os_node->name,               xmlCharStrdup("OS"))               ||
781             xmlStrcmp(res_nb_proc_node->name,          xmlCharStrdup("nb_proc"))          ||
782             xmlStrcmp(res_nb_node_node->name,          xmlCharStrdup("nb_node"))          ||
783             xmlStrcmp(res_nb_proc_per_node_node->name, xmlCharStrdup("nb_proc_per_node")) ||
784             xmlStrcmp(res_cpu_clock_node->name,        xmlCharStrdup("cpu_clock"))        ||
785             xmlStrcmp(res_mem_mb_node->name,           xmlCharStrdup("mem_mb"))
786            )
787         {
788           INFOS("A bad job is found, some resource_params user_part node are not in the rigth or does not have a correct name");
789           delete new_job;
790           break;
791         }
792         xmlChar* res_name     = xmlNodeGetContent(res_name_node);
793         xmlChar* res_hostname = xmlNodeGetContent(res_hostname_node);
794         xmlChar* res_os       = xmlNodeGetContent(res_os_node);
795         resourceParams p;
796         p.name     = std::string((const char*) res_name);
797         p.hostname = std::string((const char*) res_hostname);
798         p.OS       = std::string((const char*) res_os);
799         xmlFree(res_name);
800         xmlFree(res_hostname);
801         xmlFree(res_os);
802         xmlChar* res_nb_proc          = xmlNodeGetContent(res_nb_proc_node);
803         xmlChar* res_nb_node          = xmlNodeGetContent(res_nb_node_node);
804         xmlChar* res_nb_proc_per_node = xmlNodeGetContent(res_nb_proc_per_node_node);
805         xmlChar* res_cpu_clock        = xmlNodeGetContent(res_cpu_clock_node);
806         xmlChar* res_mem_mb           = xmlNodeGetContent(res_mem_mb_node);
807         bool import_value = true;
808         std::istringstream nb_proc_stream((const char *) res_nb_proc);
809         if (!(nb_proc_stream >> p.nb_proc))
810           import_value = false;
811         std::istringstream nb_node_stream((const char *) res_nb_node);
812         if (!(nb_node_stream >> p.nb_node))
813           import_value = false;
814         std::istringstream nb_proc_per_node_stream((const char *) res_nb_proc_per_node);
815         if (!(nb_proc_per_node_stream >> p.nb_proc_per_node))
816           import_value = false;
817         std::istringstream cpu_clock_stream((const char *) res_cpu_clock);
818         if (!(cpu_clock_stream >> p.cpu_clock))
819           import_value = false;
820         std::istringstream mem_mb_stream((const char *) res_mem_mb);
821         if (!(mem_mb_stream >> p.mem_mb))
822           import_value = false;
823         xmlFree(res_nb_proc);
824         xmlFree(res_nb_node);
825         xmlFree(res_nb_proc_per_node);
826         xmlFree(res_cpu_clock);
827         xmlFree(res_mem_mb);
828         if (!import_value)
829         {
830           INFOS("A bad job is found, some resource_params value are not correct");
831           delete new_job;
832           break;
833         }
834         try
835         {
836           new_job->setResourceRequiredParams(p);
837         }
838         catch(const LauncherException &ex)
839         {
840           INFOS("A bad job is found, an error when inserting resource_params:" << ex.msg.c_str());
841           delete new_job;
842           break;
843         }
844
845         // We finally get run part to figure out what to do
846         xmlNodePtr job_state_node             = xmlFirstElementChild(run_node);
847         xmlNodePtr resource_choosed_name_node = xmlNextElementSibling(job_state_node);
848         xmlNodePtr job_reference_node         = xmlNextElementSibling(resource_choosed_name_node);
849         if (job_state_node             == NULL ||
850             resource_choosed_name_node == NULL ||
851             job_reference_node         == NULL
852            )
853         {
854           INFOS("A bad job is found, some run_part are not found");
855           delete new_job;
856           break;
857         }
858         if (xmlStrcmp(job_state_node->name,             xmlCharStrdup("job_state"))             ||
859             xmlStrcmp(resource_choosed_name_node->name, xmlCharStrdup("resource_choosed_name")) ||
860             xmlStrcmp(job_reference_node->name,         xmlCharStrdup("job_reference"))
861            )
862         {
863           INFOS("A bad job is found, some run_part nodes are not in the rigth or does not have a correct name");
864           delete new_job;
865           break;
866         }
867         xmlChar* job_state_xml             = xmlNodeGetContent(job_state_node);
868         xmlChar* resource_choosed_name_xml = xmlNodeGetContent(resource_choosed_name_node);
869         xmlChar* job_reference_xml         = xmlNodeGetContent(job_reference_node);
870         std::string job_state((const char *) job_state_xml);
871         std::string resource_choosed_name((const char *) resource_choosed_name_xml);
872         std::string job_reference((const char *) job_reference_xml);
873         xmlFree(job_state_xml);
874         xmlFree(resource_choosed_name_xml);
875         xmlFree(job_reference_xml);
876
877         if (job_state == "CREATED")
878         {
879           // In this case, we ignore run_part informations
880           try
881           {
882             _l.createJob(new_job);
883             std::ostringstream job_id;
884             job_id << new_job->getNumber();
885             notifyObservers("NEW_JOB", job_id.str());
886           }
887           catch(const LauncherException &ex)
888           {
889             INFOS("Load failed: " << ex.msg.c_str());
890           }
891         }
892         else if (job_state == "QUEUED"     ||
893                  job_state == "RUNNING"    ||
894                  job_state == "IN_PROCESS" ||
895                  job_state == "PAUSED")
896         {
897           try
898           {
899             new_job->setState(job_state);
900             _l.addJobDirectlyToMap(new_job, job_reference);
901
902             // Step 4: We check that the BatchManager could resume
903             // the job
904 #ifdef WITH_LIBBATCH
905             if (new_job->getBatchManagerJobId().getReference() != job_reference)
906             {
907               INFOS("BatchManager type cannot resume a job - job state is set to ERROR");
908               new_job->setState("ERROR");
909             }
910 #endif
911             std::ostringstream job_id;
912             job_id << new_job->getNumber();
913             notifyObservers("NEW_JOB", job_id.str());
914           }
915           catch(const LauncherException &ex)
916           {
917             INFOS("Cannot load the job! Exception: " << ex.msg.c_str());
918             delete new_job;
919           }
920         }
921         else if (job_state == "FINISHED" ||
922                  job_state == "FAILED"   ||
923                  job_state == "ERROR")
924         {
925           try
926           {
927             // Step 2: We add run_part informations
928             new_job->setState(job_state);
929             _l.addJobDirectlyToMap(new_job, job_reference);
930             std::ostringstream job_id;
931             job_id << new_job->getNumber();
932             notifyObservers("NEW_JOB", job_id.str());
933           }
934           catch(const LauncherException &ex)
935           {
936             INFOS("Cannot load the job! Exception: " << ex.msg.c_str());
937             delete new_job;
938           }
939         }
940         else
941         {
942           INFOS("A bad job is found, state unknown " << job_state);
943           delete new_job;
944         }
945
946       }
947       xmlCurrentNode = xmlCurrentNode->next;
948     }
949   }
950   else
951   {
952     xmlFreeDoc(doc);
953     fclose(xml_file);
954     std::string error = "Error in xml file, could not find root_node named jobs: " + std::string(jobs_file);
955     INFOS(error);
956     THROW_SALOME_CORBA_EXCEPTION(error.c_str(), SALOME::INTERNAL_ERROR);
957   }
958
959   // Clean
960   xmlFreeDoc(doc);
961   fclose(xml_file);
962   notifyObservers("LOAD_JOBS", jobs_file);
963 }
964
965 //=============================================================================
966 /*! CORBA Method:
967  *  Save jobs of Launcher (in any steps) in file jobs_file
968  */
969 //=============================================================================
970 void
971 SALOME_Launcher::saveJobs(const char* jobs_file)
972 {
973
974   // Step 1: check jobs_file write access
975   FILE* xml_file = fopen(jobs_file, "w");
976   if (xml_file == NULL)
977   {
978     std::string error = "Error opening jobs_file in SALOME_Launcher::saveJobs: " + std::string(jobs_file);
979     INFOS(error);
980     THROW_SALOME_CORBA_EXCEPTION(error.c_str(), SALOME::INTERNAL_ERROR);
981   }
982
983   // Step 2: First lines
984   xmlKeepBlanksDefault(0);
985   xmlDocPtr doc = xmlNewDoc(xmlCharStrdup("1.0"));
986   xmlNodePtr root_node = xmlNewNode(NULL, xmlCharStrdup("jobs"));
987   xmlDocSetRootElement(doc, root_node);
988   xmlNodePtr doc_comment = xmlNewDocComment(doc, xmlCharStrdup("SALOME Launcher save jobs file"));
989   xmlAddPrevSibling(root_node, doc_comment);
990
991   // Step 3: For each job write it on the xml document
992   // We could put a mutex but are not foing to do that currently
993   std::map<int, Launcher::Job *> jobs_list = _l.getJobs();
994   std::map<int, Launcher::Job *>::const_iterator it_job;
995   for(it_job = jobs_list.begin(); it_job != jobs_list.end(); it_job++)
996   {
997     it_job->second->addToXmlDocument(root_node);
998   }
999
1000   // Final step: write file
1001   int isOk = xmlSaveFormatFile(jobs_file, doc, 1);
1002   if (!isOk)
1003   {
1004     std::string error = "Error during xml file saving in SALOME_Launcher::saveJobs: " + std::string(jobs_file);
1005     INFOS(error);
1006     xmlFreeDoc(doc);
1007     fclose(xml_file);
1008     THROW_SALOME_CORBA_EXCEPTION(error.c_str(), SALOME::INTERNAL_ERROR);
1009   }
1010
1011   // Clean
1012   xmlFreeDoc(doc);
1013   fclose(xml_file);
1014   MESSAGE("SALOME_Launcher::saveJobs : WRITING DONE!");
1015   notifyObservers("SAVE_JOBS", jobs_file);
1016 }
1017
1018 //=============================================================================
1019 /*! CORBA Method:
1020  *  Add a new observer to the launcher
1021  */
1022 //=============================================================================
1023 void
1024 SALOME_Launcher::addObserver(Engines::SalomeLauncherObserver_ptr observer)
1025 {
1026   bool new_observer = true;
1027   std::list<Engines::SalomeLauncherObserver_var>::iterator iter = _observers.begin();
1028   while(iter != _observers.end())
1029   {
1030     if (std::string(_orb->object_to_string(*iter)) ==
1031         std::string(_orb->object_to_string(observer)))
1032     {
1033       new_observer = false;
1034       break;
1035     }
1036     iter++;
1037   }
1038   if (new_observer)
1039     _observers.push_back(Engines::SalomeLauncherObserver::_duplicate(observer));
1040
1041   // We notify the new observer with all jobs that are currently in the Launcher
1042   std::map<int, Launcher::Job *> cpp_jobs = _l.getJobs();
1043   std::map<int, Launcher::Job *>::const_iterator it_job;
1044   for(it_job = cpp_jobs.begin(); it_job != cpp_jobs.end(); it_job++)
1045   {
1046     int number = it_job->first;
1047     std::ostringstream job_id;
1048     job_id << number;
1049     try
1050     {
1051       observer->notify("NEW_JOB", job_id.str().c_str());
1052     }
1053     catch (...) 
1054     {
1055        MESSAGE("Notify Observer, exception catch");
1056     }
1057
1058   }
1059 }
1060
1061 //=============================================================================
1062 /*! CORBA Method:
1063  *  Add a new observer to the launcher
1064  */
1065 //=============================================================================
1066 void
1067 SALOME_Launcher::removeObserver(Engines::SalomeLauncherObserver_ptr observer)
1068 {
1069   std::list<Engines::SalomeLauncherObserver_var>::iterator iter = _observers.begin();
1070   while(iter != _observers.end())
1071   {
1072     if (std::string(_orb->object_to_string(*iter)) ==
1073         std::string(_orb->object_to_string(observer)))
1074     {
1075       // Observer found
1076       iter =_observers.erase(iter++);
1077     }
1078     else
1079     {
1080       iter++;
1081     }
1082   }
1083 }
1084
1085 //=============================================================================
1086 /*! Internal Method:
1087  *  Notify observers on a new event
1088  */
1089 //=============================================================================
1090 void
1091 SALOME_Launcher::notifyObservers(const std::string & event_name,
1092                                  const std::string & event_data)
1093 {
1094   std::list<Engines::SalomeLauncherObserver_var>::iterator iter = _observers.begin();
1095   while(iter != _observers.end())
1096   {
1097     try
1098     {
1099       (*iter)->notify(CORBA::string_dup(event_name.c_str()),
1100                       CORBA::string_dup(event_data.c_str()));
1101     }
1102     catch (...) 
1103     {
1104        MESSAGE("Notify Observer, exception catch");
1105     }
1106     iter++;
1107   }
1108
1109 }