]> SALOME platform Git repositories - modules/kernel.git/blob - src/Launcher/Launcher_XML_Persistence.cxx
Salome HOME
b60b14fd5214cbb03568f9cbedfb4b4294a13394
[modules/kernel.git] / src / Launcher / Launcher_XML_Persistence.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 <libxml/parser.h>
24
25 #include "Launcher_XML_Persistence.hxx"
26 #include "Launcher_Job_Command.hxx"
27 #include "Launcher_Job_YACSFile.hxx"
28 #include "Launcher_Job_PythonSALOME.hxx"
29 #include "Launcher_Job_Writer.hxx"
30
31 using namespace std;
32
33 namespace Launcher
34 {
35
36 list<Job *>
37 XML_Persistence::loadJobs(const char* jobs_file)
38 {
39   // Step 1: check jobs_file read access
40   FILE* xml_file = fopen(jobs_file, "r");
41   if (xml_file == NULL)
42   {
43     std::string error = "Error opening jobs_file in SALOME_Launcher::loadJobs: " + std::string(jobs_file);
44     LAUNCHER_INFOS(error);
45     throw LauncherException(error);
46   }
47
48   // Step 2: read xml file
49   xmlDocPtr doc = xmlReadFile(jobs_file, NULL, 0);
50   if (doc == NULL)
51   {
52     std::string error = "Error in xmlReadFile in SALOME_Launcher::loadJobs, could not parse file: " + std::string(jobs_file);
53     LAUNCHER_INFOS(error);
54     fclose(xml_file);
55     throw LauncherException(error);
56   }
57
58   // Step 3: Find jobs
59   list<Job *> jobs_list;
60   xmlNodePtr root_node = xmlDocGetRootElement(doc);
61   xmlNodePtr xmlCurrentNode = root_node->xmlChildrenNode;
62   if (!xmlStrcmp(root_node->name, xmlCharStrdup("jobs")))
63   {
64     while(xmlCurrentNode != NULL)
65     {
66       if (!xmlStrcmp(xmlCurrentNode->name, xmlCharStrdup("job")))
67       {
68         LAUNCHER_INFOS("A job is found");
69         Launcher::Job * new_job; // It is Launcher_cpp that is going to destroy it
70         xmlNodePtr job_node = xmlCurrentNode;
71
72         // Begin Job
73         if (!xmlHasProp(job_node, xmlCharStrdup("type"))  ||
74             !xmlHasProp(job_node, xmlCharStrdup("name")))
75         {
76           LAUNCHER_INFOS("A bad job is found, type or name not found");
77           break;
78         }
79         xmlChar* type = xmlGetProp(job_node, xmlCharStrdup("type"));
80         xmlChar* name = xmlGetProp(job_node, xmlCharStrdup("name"));
81         std::string job_type((const char*) type);
82         if (job_type == "command")
83           new_job = new Launcher::Job_Command();
84         else if (job_type == "yacs_file")
85           new_job = new Launcher::Job_YACSFile();
86         else if (job_type == "python_salome")
87           new_job = new Launcher::Job_PythonSALOME();
88         new_job->setJobName(std::string((const char *)name));
89         xmlFree(type);
90         xmlFree(name);
91
92         xmlNodePtr user_node = xmlFirstElementChild(job_node);
93         xmlNodePtr run_node = xmlNextElementSibling(user_node);
94         if (user_node == NULL || run_node == NULL)
95         {
96           LAUNCHER_INFOS("A bad job is found, user_part or run_part not found");
97           delete new_job;
98           break;
99         }
100         if (xmlStrcmp(user_node->name, xmlCharStrdup("user_part")) ||
101             xmlStrcmp(run_node->name, xmlCharStrdup("run_part")))
102         {
103           LAUNCHER_INFOS("A bad job is found, cannot get a correct user_part or run_part node");
104           delete new_job;
105           break;
106         }
107
108         // Add user part
109
110         // Get job_file env_file work_directory local_directory result_directory
111         xmlNodePtr job_file_node         = xmlFirstElementChild(user_node);
112         xmlNodePtr env_file_node         = xmlNextElementSibling(job_file_node);
113         xmlNodePtr work_directory_node   = xmlNextElementSibling(env_file_node);
114         xmlNodePtr local_directory_node  = xmlNextElementSibling(work_directory_node);
115         xmlNodePtr result_directory_node = xmlNextElementSibling(local_directory_node);
116
117                 // Parameters for COORM
118         xmlNodePtr launcher_file_node = xmlNextElementSibling(result_directory_node);
119
120         if (job_file_node         == NULL ||
121             env_file_node         == NULL ||
122             work_directory_node   == NULL ||
123             local_directory_node  == NULL ||
124             result_directory_node == NULL ||
125                         // For COORM
126             launcher_file_node    == NULL
127            )
128         {
129           LAUNCHER_INFOS("A bad job is found, some user_part are not found");
130           delete new_job;
131           break;
132         }
133         if (xmlStrcmp(job_file_node->name,         xmlCharStrdup("job_file"))         ||
134             xmlStrcmp(env_file_node->name,         xmlCharStrdup("env_file"))         ||
135             xmlStrcmp(work_directory_node->name,   xmlCharStrdup("work_directory"))   ||
136             xmlStrcmp(local_directory_node->name,  xmlCharStrdup("local_directory"))  ||
137             xmlStrcmp(result_directory_node->name, xmlCharStrdup("result_directory")) ||
138                         // For COORM
139             xmlStrcmp(launcher_file_node->name, xmlCharStrdup("launcher_file"))
140            )
141         {
142           LAUNCHER_INFOS("A bad job is found, some user part node are not in the rigth or does not have a correct name");
143           delete new_job;
144           break;
145         }
146         xmlChar* job_file         = xmlNodeGetContent(job_file_node);
147         try
148         {
149           new_job->setJobFile(std::string((const char *)job_file));
150         }
151         catch(const LauncherException &ex)
152         {
153           LAUNCHER_INFOS("Exception receice for job_file, cannot add the job" << ex.msg.c_str());
154           delete new_job;
155           xmlFree(job_file);
156           break;
157         }
158         xmlChar* env_file         = xmlNodeGetContent(env_file_node);
159         xmlChar* work_directory   = xmlNodeGetContent(work_directory_node);
160         xmlChar* local_directory  = xmlNodeGetContent(local_directory_node);
161         xmlChar* result_directory = xmlNodeGetContent(result_directory_node);
162
163                 // Parameters for COORM
164         xmlChar* launcher_file = xmlNodeGetContent(launcher_file_node);
165
166         new_job->setEnvFile(std::string((const char *)env_file));
167         new_job->setWorkDirectory(std::string((const char *)work_directory));
168         new_job->setLocalDirectory(std::string((const char *)local_directory));
169         new_job->setResultDirectory(std::string((const char *)result_directory));
170
171                 // Parameters for COORM
172         new_job->setLauncherFile(std::string((const char *)launcher_file));
173
174         xmlFree(job_file);
175         xmlFree(env_file);
176         xmlFree(work_directory);
177         xmlFree(local_directory);
178         xmlFree(result_directory);
179
180                 // Parameters for COORM
181                 xmlFree(launcher_file);
182
183         // Get in and out files
184         xmlNodePtr files_node = xmlNextElementSibling(launcher_file_node);
185         if (files_node == NULL)
186         {
187           LAUNCHER_INFOS("A bad job is found, user_part files is not found");
188           delete new_job;
189           break;
190         }
191         if (xmlStrcmp(files_node->name, xmlCharStrdup("files")))
192         {
193           LAUNCHER_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");
194           delete new_job;
195           break;
196         }
197         xmlNodePtr file_node = xmlFirstElementChild(files_node);
198         while (file_node != NULL)
199         {
200           if (!xmlStrcmp(file_node->name, xmlCharStrdup("in_file")))
201           {
202             xmlChar* in_file = xmlNodeGetContent(file_node);
203             new_job->add_in_file(std::string((const char *)in_file));
204             xmlFree(in_file);
205           }
206           else if (!xmlStrcmp(file_node->name, xmlCharStrdup("out_file")))
207           {
208             xmlChar* out_file = xmlNodeGetContent(file_node);
209             new_job->add_out_file(std::string((const char *)out_file));
210             xmlFree(out_file);
211           }
212           file_node = xmlNextElementSibling(file_node);
213         }
214
215         // Get resource part
216         xmlNodePtr res_node = xmlNextElementSibling(files_node);
217         xmlNodePtr maximum_duration_node = xmlNextElementSibling(res_node);
218         xmlNodePtr queue_node = xmlNextElementSibling(maximum_duration_node);
219         xmlNodePtr exclusive_node = xmlNextElementSibling(queue_node);
220         xmlNodePtr mem_per_cpu_node = xmlNextElementSibling(exclusive_node);
221         xmlNodePtr launcher_args_node = xmlNextElementSibling(mem_per_cpu_node);
222         if (res_node              == NULL ||
223             maximum_duration_node == NULL ||
224             queue_node            == NULL ||
225             exclusive_node        == NULL ||
226             mem_per_cpu_node      == NULL ||
227                         // For COORM
228             launcher_args_node    == NULL
229            )
230         {
231           LAUNCHER_INFOS("A bad job is found, some user_part are not found");
232           delete new_job;
233           break;
234         }
235         if (xmlStrcmp(res_node->name,              xmlCharStrdup("resource_params"))  ||
236             xmlStrcmp(maximum_duration_node->name, xmlCharStrdup("maximum_duration")) ||
237             xmlStrcmp(queue_node->name,            xmlCharStrdup("queue")) ||
238             xmlStrcmp(exclusive_node->name,        xmlCharStrdup("exclusive")) ||
239             xmlStrcmp(mem_per_cpu_node->name,      xmlCharStrdup("mem_per_cpu")) ||
240                         // For COORM
241             xmlStrcmp(launcher_args_node->name,    xmlCharStrdup("launcher_args"))
242            )
243         {
244           LAUNCHER_INFOS("A bad job is found, some user part node are not in the rigth or does not have a correct name");
245           delete new_job;
246           break;
247         }
248         xmlChar* maximum_duration = xmlNodeGetContent(maximum_duration_node);
249         try
250         {
251           new_job->setMaximumDuration(std::string((const char *)maximum_duration));
252         }
253         catch(const LauncherException &ex)
254         {
255           LAUNCHER_INFOS("Exception receice for maximum_duration, cannot add the job" << ex.msg.c_str());
256           delete new_job;
257           xmlFree(maximum_duration);
258           break;
259         }
260         xmlChar* queue            = xmlNodeGetContent(queue_node);
261         new_job->setQueue(std::string((const char *)queue));
262         xmlFree(maximum_duration);
263         xmlFree(queue);
264
265         xmlChar* exclusive = xmlNodeGetContent(exclusive_node);
266         try
267         {
268           new_job->setExclusiveStr(std::string((const char *)exclusive));
269         }
270         catch(const LauncherException &ex)
271         {
272           LAUNCHER_INFOS("Exception received for exclusive, cannot add the job. " << ex.msg.c_str());
273           delete new_job;
274           xmlFree(exclusive);
275           break;
276         }
277         xmlFree(exclusive);
278
279         xmlChar* mem_per_cpu_str = xmlNodeGetContent(mem_per_cpu_node);
280         std::istringstream mem_per_cpu_stream((const char *)mem_per_cpu_str);
281         unsigned long mem_per_cpu = 0;
282         if (!(mem_per_cpu_stream >> mem_per_cpu))
283         {
284           LAUNCHER_INFOS("A bad job is found, mem_per_cpu parameter is not correct");
285           delete new_job;
286           break;
287         }
288         else
289           new_job->setMemPerCpu(mem_per_cpu);
290
291                 // For COORM
292         xmlChar* launcher_args           = xmlNodeGetContent(launcher_args_node);
293         new_job->setLauncherArgs(std::string((const char *)launcher_args));
294         xmlFree(launcher_args);
295
296         xmlNodePtr specific_node = xmlNextElementSibling(launcher_args_node);
297         if (specific_node == NULL)
298         {
299           LAUNCHER_INFOS("A bad job is found, specific_parameters part is not found");
300           delete new_job;
301           break;
302         }
303         xmlNodePtr parameter_node = xmlFirstElementChild(specific_node);
304         while (parameter_node != NULL)
305         {
306           if (!xmlStrcmp(parameter_node->name, xmlCharStrdup("specific_parameter")))
307           {
308             xmlNodePtr name_node = xmlFirstElementChild(parameter_node);
309             xmlNodePtr value_node = xmlNextElementSibling(name_node);
310             if (name_node == NULL ||
311                 value_node == NULL)
312             {
313               LAUNCHER_INFOS("A bad job is found, specific_parameter parts are not found");
314               delete new_job;
315               break;
316             }
317             if (xmlStrcmp(name_node->name, xmlCharStrdup("name")) ||
318                 xmlStrcmp(value_node->name, xmlCharStrdup("value")))
319             {
320               LAUNCHER_INFOS("A bad job is found, specific_parameter bad parts are found");
321               delete new_job;
322               break;
323             }
324
325             xmlChar* name  = xmlNodeGetContent(name_node);
326             xmlChar* value = xmlNodeGetContent(value_node);
327             try
328             {
329               new_job->addSpecificParameter(std::string((const char*)name), std::string((const char*)value));
330               xmlFree(name);
331               xmlFree(value);
332             }
333             catch(const LauncherException &ex)
334             {
335               LAUNCHER_INFOS("Exception receice for a specific parameter, cannot add the job" << ex.msg.c_str());
336               delete new_job;
337               xmlFree(name);
338               xmlFree(value);
339               break;
340             }
341           }
342           else
343           {
344             LAUNCHER_INFOS("A bad job is found, specific_parameters part is bad, a node that is not a specific parameter is found");
345             delete new_job;
346             break;
347           }
348           parameter_node = xmlNextElementSibling(parameter_node);
349         }
350
351         xmlNodePtr res_name_node             = xmlFirstElementChild(res_node);
352         xmlNodePtr res_hostname_node         = xmlNextElementSibling(res_name_node);
353         xmlNodePtr res_os_node               = xmlNextElementSibling(res_hostname_node);
354         xmlNodePtr res_nb_proc_node          = xmlNextElementSibling(res_os_node);
355         xmlNodePtr res_nb_node_node          = xmlNextElementSibling(res_nb_proc_node);
356         xmlNodePtr res_nb_proc_per_node_node = xmlNextElementSibling(res_nb_node_node);
357         xmlNodePtr res_cpu_clock_node        = xmlNextElementSibling(res_nb_proc_per_node_node);
358         xmlNodePtr res_mem_mb_node           = xmlNextElementSibling(res_cpu_clock_node);
359         if (res_name_node             == NULL ||
360             res_hostname_node         == NULL ||
361             res_os_node               == NULL ||
362             res_nb_proc_node          == NULL ||
363             res_nb_node_node          == NULL ||
364             res_nb_proc_per_node_node == NULL ||
365             res_cpu_clock_node        == NULL ||
366             res_mem_mb_node           == NULL
367            )
368         {
369           LAUNCHER_INFOS("A bad job is found, some resource_params user_part are not found");
370           delete new_job;
371           break;
372         }
373         if (xmlStrcmp(res_name_node->name,             xmlCharStrdup("name"))             ||
374             xmlStrcmp(res_hostname_node->name,         xmlCharStrdup("hostname"))         ||
375             xmlStrcmp(res_os_node->name,               xmlCharStrdup("OS"))               ||
376             xmlStrcmp(res_nb_proc_node->name,          xmlCharStrdup("nb_proc"))          ||
377             xmlStrcmp(res_nb_node_node->name,          xmlCharStrdup("nb_node"))          ||
378             xmlStrcmp(res_nb_proc_per_node_node->name, xmlCharStrdup("nb_proc_per_node")) ||
379             xmlStrcmp(res_cpu_clock_node->name,        xmlCharStrdup("cpu_clock"))        ||
380             xmlStrcmp(res_mem_mb_node->name,           xmlCharStrdup("mem_mb"))
381            )
382         {
383           LAUNCHER_INFOS("A bad job is found, some resource_params user_part node are not in the rigth or does not have a correct name");
384           delete new_job;
385           break;
386         }
387         xmlChar* res_name     = xmlNodeGetContent(res_name_node);
388         xmlChar* res_hostname = xmlNodeGetContent(res_hostname_node);
389         xmlChar* res_os       = xmlNodeGetContent(res_os_node);
390         resourceParams p;
391         p.name     = std::string((const char*) res_name);
392         p.hostname = std::string((const char*) res_hostname);
393         p.OS       = std::string((const char*) res_os);
394         xmlFree(res_name);
395         xmlFree(res_hostname);
396         xmlFree(res_os);
397         xmlChar* res_nb_proc          = xmlNodeGetContent(res_nb_proc_node);
398         xmlChar* res_nb_node          = xmlNodeGetContent(res_nb_node_node);
399         xmlChar* res_nb_proc_per_node = xmlNodeGetContent(res_nb_proc_per_node_node);
400         xmlChar* res_cpu_clock        = xmlNodeGetContent(res_cpu_clock_node);
401         xmlChar* res_mem_mb           = xmlNodeGetContent(res_mem_mb_node);
402         bool import_value = true;
403         std::istringstream nb_proc_stream((const char *) res_nb_proc);
404         if (!(nb_proc_stream >> p.nb_proc))
405           import_value = false;
406         std::istringstream nb_node_stream((const char *) res_nb_node);
407         if (!(nb_node_stream >> p.nb_node))
408           import_value = false;
409         std::istringstream nb_proc_per_node_stream((const char *) res_nb_proc_per_node);
410         if (!(nb_proc_per_node_stream >> p.nb_proc_per_node))
411           import_value = false;
412         std::istringstream cpu_clock_stream((const char *) res_cpu_clock);
413         if (!(cpu_clock_stream >> p.cpu_clock))
414           import_value = false;
415         std::istringstream mem_mb_stream((const char *) res_mem_mb);
416         if (!(mem_mb_stream >> p.mem_mb))
417           import_value = false;
418         xmlFree(res_nb_proc);
419         xmlFree(res_nb_node);
420         xmlFree(res_nb_proc_per_node);
421         xmlFree(res_cpu_clock);
422         xmlFree(res_mem_mb);
423         if (!import_value)
424         {
425           LAUNCHER_INFOS("A bad job is found, some resource_params value are not correct");
426           delete new_job;
427           break;
428         }
429         try
430         {
431           new_job->setResourceRequiredParams(p);
432         }
433         catch(const LauncherException &ex)
434         {
435           LAUNCHER_INFOS("A bad job is found, an error when inserting resource_params:" << ex.msg.c_str());
436           delete new_job;
437           break;
438         }
439
440         // We finally get run part to figure out what to do
441         xmlNodePtr job_state_node             = xmlFirstElementChild(run_node);
442         xmlNodePtr resource_choosed_name_node = xmlNextElementSibling(job_state_node);
443         xmlNodePtr job_reference_node         = xmlNextElementSibling(resource_choosed_name_node);
444         if (job_state_node             == NULL ||
445             resource_choosed_name_node == NULL ||
446             job_reference_node         == NULL
447            )
448         {
449           LAUNCHER_INFOS("A bad job is found, some run_part are not found");
450           delete new_job;
451           break;
452         }
453         if (xmlStrcmp(job_state_node->name,             xmlCharStrdup("job_state"))             ||
454             xmlStrcmp(resource_choosed_name_node->name, xmlCharStrdup("resource_choosed_name")) ||
455             xmlStrcmp(job_reference_node->name,         xmlCharStrdup("job_reference"))
456            )
457         {
458           LAUNCHER_INFOS("A bad job is found, some run_part nodes are not in the rigth or does not have a correct name");
459           delete new_job;
460           break;
461         }
462         xmlChar* job_state_xml             = xmlNodeGetContent(job_state_node);
463         xmlChar* resource_choosed_name_xml = xmlNodeGetContent(resource_choosed_name_node);
464         xmlChar* job_reference_xml         = xmlNodeGetContent(job_reference_node);
465         std::string job_state((const char *) job_state_xml);
466         std::string resource_choosed_name((const char *) resource_choosed_name_xml);
467         std::string job_reference((const char *) job_reference_xml);
468         xmlFree(job_state_xml);
469         xmlFree(resource_choosed_name_xml);
470         xmlFree(job_reference_xml);
471         new_job->setState(job_state);
472         new_job->setReference(job_reference);
473
474         jobs_list.push_back(new_job);
475       }
476       xmlCurrentNode = xmlCurrentNode->next;
477     }
478   }
479   else
480   {
481     xmlFreeDoc(doc);
482     fclose(xml_file);
483     std::string error = "Error in xml file, could not find root_node named jobs: " + std::string(jobs_file);
484     LAUNCHER_INFOS(error);
485     throw LauncherException(error);
486   }
487
488   // Clean
489   xmlFreeDoc(doc);
490   fclose(xml_file);
491
492   return jobs_list;
493 }
494
495 void
496 XML_Persistence::saveJobs(const char* jobs_file, const list<const Job *> & jobs_list)
497 {
498   // Step 1: check jobs_file write access
499   FILE* xml_file = fopen(jobs_file, "w");
500   if (xml_file == NULL)
501   {
502     std::string error = "Error opening jobs_file in SALOME_Launcher::saveJobs: " + std::string(jobs_file);
503     LAUNCHER_INFOS(error);
504     throw LauncherException(error);
505   }
506
507   // Step 2: First lines
508   xmlKeepBlanksDefault(0);
509   xmlDocPtr doc = xmlNewDoc(xmlCharStrdup("1.0"));
510   xmlNodePtr root_node = xmlNewNode(NULL, xmlCharStrdup("jobs"));
511   xmlDocSetRootElement(doc, root_node);
512   xmlNodePtr doc_comment = xmlNewDocComment(doc, xmlCharStrdup("SALOME Launcher save jobs file"));
513   xmlAddPrevSibling(root_node, doc_comment);
514
515   // Step 3: For each job write it on the xml document
516   // We could put a mutex but are not foing to do that currently
517   list<const Job *>::const_iterator it_job;
518   for (it_job = jobs_list.begin(); it_job != jobs_list.end(); it_job++)
519   {
520     addToXmlDocument(root_node, *it_job);
521   }
522
523   // Final step: write file
524   int isOk = xmlSaveFormatFile(jobs_file, doc, 1);
525   if (!isOk)
526   {
527     std::string error = "Error during xml file saving in SALOME_Launcher::saveJobs: " + std::string(jobs_file);
528     LAUNCHER_INFOS(error);
529     xmlFreeDoc(doc);
530     fclose(xml_file);
531     throw LauncherException(error);
532   }
533
534   // Clean
535   xmlFreeDoc(doc);
536   fclose(xml_file);
537   LAUNCHER_MESSAGE("SALOME_Launcher::saveJobs : WRITING DONE!");
538 }
539
540 }