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