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