]> SALOME platform Git repositories - modules/kernel.git/blob - src/Launcher/Launcher_Job.cxx
Salome HOME
Try to kill Salome application when a YACS Launcher job is killed
[modules/kernel.git] / src / Launcher / Launcher_Job.cxx
1 // Copyright (C) 2009-2011  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 // Author: André RIBES - EDF R&D
21 //
22 #include "Launcher_Job.hxx"
23 #include "Launcher.hxx"
24
25 #ifdef WITH_LIBBATCH
26 #include <Batch/Batch_Constants.hxx>
27 #endif
28
29 Launcher::Job::Job()
30 {
31   _number = -1;
32   _state = "CREATED";
33   _launch_date = getLaunchDate();
34
35   _env_file = "";
36   _job_name = "";
37   _job_file = "";
38   _job_file_name = "";
39   _job_file_name_complete = "";
40   _work_directory = "";
41   _local_directory = "";
42   _result_directory = "";
43   _maximum_duration = "";
44   _maximum_duration_in_second = -1;
45   _resource_required_params.name = "";
46   _resource_required_params.hostname = "";
47   _resource_required_params.OS = "";
48   _resource_required_params.nb_proc = -1;
49   _resource_required_params.nb_node = -1;
50   _resource_required_params.nb_proc_per_node = -1;
51   _resource_required_params.cpu_clock = -1;
52   _resource_required_params.mem_mb = -1;
53   _queue = "";
54   _job_type = "";
55
56 #ifdef WITH_LIBBATCH
57   _batch_job = new Batch::Job();
58 #endif
59 }
60
61 Launcher::Job::~Job() 
62 {
63   LAUNCHER_MESSAGE("Deleting job number: " << _number);
64 #ifdef WITH_LIBBATCH
65   if (_batch_job)
66     delete _batch_job;
67 #endif
68 }
69
70 void
71 Launcher::Job::stopJob()
72 {
73   LAUNCHER_MESSAGE("Stop resquested for job number: " << _number);
74   setState("FAILED");
75 #ifdef WITH_LIBBATCH
76   if (_batch_job_id.getReference() != "undefined")
77   {
78     try 
79     {
80       _batch_job_id.deleteJob();
81     }
82     catch (const Batch::EmulationException &ex)
83     {
84       LAUNCHER_INFOS("WARNING: exception when stopping the job: " << ex.message);
85     }
86   }
87 #endif
88 }
89
90
91 void
92 Launcher::Job::removeJob()
93 {
94   LAUNCHER_MESSAGE("Removing job number: " << _number);
95 #ifdef WITH_LIBBATCH
96   if (_batch_job_id.getReference() != "undefined")
97   {
98     try 
99     {
100       _batch_job_id.deleteJob();
101     }
102     catch (const Batch::EmulationException &ex)
103     {
104       LAUNCHER_INFOS("WARNING: exception when removing the job: " << ex.message);
105     }
106   }
107 #endif
108 }
109
110 std::string
111 Launcher::Job::getJobType()
112 {
113   return _job_type;
114 }
115
116 void
117 Launcher::Job::setJobName(const std::string & job_name)
118 {
119   _job_name = job_name;
120 }
121
122 std::string
123 Launcher::Job::getJobName()
124 {
125   return _job_name;
126 }
127
128 void 
129 Launcher::Job::setState(const std::string & state)
130 {
131   // State of a Job: CREATED, QUEUED, RUNNING, FINISHED, FAILED
132   if (state != "CREATED" &&
133       state != "IN_PROCESS" &&
134       state != "QUEUED" &&
135       state != "RUNNING" &&
136       state != "PAUSED" &&
137       state != "FINISHED" &&
138       state != "FAILED" &&
139       state != "ERROR")
140   {
141     throw LauncherException("Bad state, this state does not exist: " + state);
142   }
143   _state = state;
144 }
145
146 std::string 
147 Launcher::Job::getState()
148 {
149   return _state;
150 }
151
152 void 
153 Launcher::Job::setNumber(const int & number)
154 {
155   if (_number != -1)
156     std::cerr << "Launcher::Job::setNumber -- Job number was already defined, before: " << _number << " now: " << number << std::endl;
157   _number = number;
158 }
159
160 int
161 Launcher::Job::getNumber()
162 {
163   return _number;
164 }
165
166 void 
167 Launcher::Job::setResourceDefinition(const ParserResourcesType & resource_definition)
168 {
169   // Check machine_definition
170   std::string user_name = "";
171   if (resource_definition.UserName == "")
172   {
173     user_name = getenv("USER");
174     if (user_name == "")
175     {
176       std::string mess = "You must define a user name: into your resource description or with env variable USER";
177       throw LauncherException(mess);
178     }
179   }
180   else
181     user_name = resource_definition.UserName;
182
183   _resource_definition = resource_definition;
184   _resource_definition.UserName = user_name;
185 }
186
187 ParserResourcesType 
188 Launcher::Job::getResourceDefinition()
189 {
190   return _resource_definition;
191 }
192
193 void 
194 Launcher::Job::setJobFile(const std::string & job_file)
195 {
196   // Check job file
197   if (job_file == "")
198   {
199     std::string mess = "Empty Job File is forbidden !";
200     throw LauncherException(mess);
201   }
202
203   _job_file = job_file;
204   std::string::size_type p1 = _job_file.find_last_of("/");
205   std::string::size_type p2 = _job_file.find_last_of(".");
206   _job_file_name_complete = _job_file.substr(p1+1);
207   _job_file_name = _job_file.substr(p1+1,p2-p1-1);
208
209   if (_job_file != "")
210     add_in_file(_job_file);
211 }
212
213 std::string
214 Launcher::Job::getJobFile()
215 {
216   return _job_file;
217 }
218 void 
219 Launcher::Job::setEnvFile(const std::string & env_file)
220 {
221   _env_file = env_file;
222   if (_env_file != "")
223     add_in_file(_env_file);
224 }
225
226 std::string
227 Launcher::Job::getEnvFile()
228 {
229   return _env_file;
230 }
231
232 void 
233 Launcher::Job::setWorkDirectory(const std::string & work_directory)
234 {
235   _work_directory = work_directory;
236 }
237
238 void 
239 Launcher::Job::setLocalDirectory(const std::string & local_directory)
240 {
241   _local_directory = local_directory;
242 }
243
244 void 
245 Launcher::Job::setResultDirectory(const std::string & result_directory)
246 {
247   _result_directory = result_directory;
248 }
249
250 void 
251 Launcher::Job::add_in_file(const std::string & file)
252 {
253   std::list<std::string>::iterator it = std::find(_in_files.begin(), _in_files.end(), file);
254   if (it == _in_files.end())
255     _in_files.push_back(file);
256   else
257     std::cerr << "Launcher::Job::add_in_file -- Warning file was already entered in in_files: " << file << std::endl;
258 }
259
260 void 
261 Launcher::Job::add_out_file(const std::string & file)
262 {
263   std::list<std::string>::iterator it = std::find(_out_files.begin(), _out_files.end(), file);
264   if (it == _out_files.end())
265     _out_files.push_back(file);
266   else
267     std::cerr << "Launcher::Job::add_out_file -- Warning file was already entered in out_files: " << file << std::endl;
268 }
269
270 void 
271 Launcher::Job::setMaximumDuration(const std::string & maximum_duration)
272 {
273   checkMaximumDuration(maximum_duration);
274   _maximum_duration_in_second = convertMaximumDuration(maximum_duration);
275   _maximum_duration = maximum_duration;
276 }
277
278 void 
279 Launcher::Job::setResourceRequiredParams(const resourceParams & resource_required_params)
280 {
281   checkResourceRequiredParams(resource_required_params);
282   _resource_required_params = resource_required_params;
283 }
284
285 void 
286 Launcher::Job::setQueue(const std::string & queue)
287 {
288   _queue = queue;
289 }
290
291 std::string 
292 Launcher::Job::getWorkDirectory()
293 {
294   return _work_directory;
295 }
296
297 std::string 
298 Launcher::Job::getLocalDirectory()
299 {
300   return _local_directory;
301 }
302
303 std::string
304 Launcher::Job::getResultDirectory()
305 {
306   return _result_directory;
307 }
308
309 const std::list<std::string> & 
310 Launcher::Job::get_in_files()
311 {
312   return _in_files;
313 }
314
315 const std::list<std::string> & 
316 Launcher::Job::get_out_files()
317 {
318   return _out_files;
319 }
320
321 std::string 
322 Launcher::Job::getMaximumDuration()
323 {
324   return _maximum_duration;
325 }
326
327 resourceParams 
328 Launcher::Job::getResourceRequiredParams()
329 {
330   return _resource_required_params;
331 }
332
333 std::string 
334 Launcher::Job::getQueue()
335 {
336   return _queue;
337 }
338
339 void 
340 Launcher::Job::checkMaximumDuration(const std::string & maximum_duration)
341 {
342   std::string result("");
343   std::string edt_value = maximum_duration;
344   std::size_t pos = edt_value.find(":");
345
346   if (edt_value != "") {
347     std::string begin_edt_value = edt_value.substr(0, pos);
348     std::string mid_edt_value = edt_value.substr(pos, 1);
349     std::string end_edt_value = edt_value.substr(pos + 1, edt_value.npos);
350   
351     long value;
352     std::istringstream iss(begin_edt_value);
353     if (!(iss >> value)) {
354       result = "[Launcher::Job::checkExpectedDuration] Error on definition ! : " + edt_value;
355     }
356     else if (value < 0) {
357       result = "[Launcher::Job::checkExpectedDuration] Error on definition time is negative ! : " + value;
358     }
359     std::istringstream iss_2(end_edt_value);
360     if (!(iss_2 >> value)) {
361       result = "[Launcher::Job::checkExpectedDuration] Error on definition ! : " + edt_value;
362     }
363     else if (value < 0) {
364       result = "[Launcher::Job::checkExpectedDuration] Error on definition time is negative ! : " + value;
365     }
366     if (mid_edt_value != ":") {
367       result = "[Launcher::Job::checkExpectedDuration] Error on definition ! :" + edt_value;
368     }
369   }
370   if (result != "")
371     throw LauncherException(result);
372 }
373
374 void 
375 Launcher::Job::checkResourceRequiredParams(const resourceParams & resource_required_params)
376 {
377   // nb_proc has be to > 0
378   if (resource_required_params.nb_proc <= 0)
379   {
380     std::string message("[Launcher::Job::checkResourceRequiredParams] proc number is not > 0 ! ");
381     throw LauncherException(message);
382   }
383 }
384
385 long 
386 Launcher::Job::convertMaximumDuration(const std::string & edt)
387 {
388   long hh, mm, ret;
389
390   if( edt.size() == 0 )
391     return -1;
392
393   std::string::size_type pos = edt.find(":");
394   std::string h = edt.substr(0,pos);
395   std::string m = edt.substr(pos+1,edt.size()-pos+1);
396   std::istringstream issh(h);
397   issh >> hh;
398   std::istringstream issm(m);
399   issm >> mm;
400   ret = hh*60 + mm;
401   ret = ret * 60;
402
403   return ret;
404 }
405
406 std::string 
407 Launcher::Job::getLaunchDate()
408 {
409   time_t rawtime;
410   time(&rawtime);
411   std::string launch_date = ctime(&rawtime);
412   int i = 0 ;
413   for (;i < launch_date.size(); i++) 
414     if (launch_date[i] == '/' ||
415         launch_date[i] == '-' ||
416         launch_date[i] == ':' ||
417         launch_date[i] == ' ') 
418       launch_date[i] = '_';
419   launch_date.erase(--launch_date.end()); // Last caracter is a \n
420
421   return launch_date;
422 }
423
424 std::string
425 Launcher::Job::updateJobState()
426 {
427
428   if (_state != "FINISHED" &&
429       _state != "ERROR"    &&
430       _state != "FAILED")
431   {
432 #ifdef WITH_LIBBATCH
433     if (_batch_job_id.getReference() != "undefined")
434     {
435       // A batch manager has been affected to the job
436       Batch::JobInfo job_info = _batch_job_id.queryJob();
437       Batch::Parametre par = job_info.getParametre();
438       _state = par[Batch::STATE].str();
439       LAUNCHER_MESSAGE("State received is: " << par[Batch::STATE].str());
440     }
441 #endif
442   }
443   return _state;
444 }
445
446 #ifdef WITH_LIBBATCH
447 Batch::Job * 
448 Launcher::Job::getBatchJob()
449 {
450   update_job();
451   return _batch_job;
452 }
453
454 Batch::Parametre
455 Launcher::Job::common_job_params()
456 {
457   Batch::Parametre params;
458
459   params[Batch::NAME] = getJobName();
460   params[Batch::USER] = _resource_definition.UserName;
461   params[Batch::NBPROC] = _resource_required_params.nb_proc;
462
463   // Memory in megabytes
464   if (_resource_required_params.mem_mb > 0)
465   {
466     params[Batch::MAXRAMSIZE] = _resource_required_params.mem_mb;
467   }
468
469   // We define a default directory based on user time
470   if (_work_directory == "")
471   {
472     std::string thedate;
473     Batch::Date date = Batch::Date(time(0));
474     thedate = date.str();
475     int lend = thedate.size() ;
476     int i = 0 ;
477     while ( i < lend ) {
478       if ( thedate[i] == '/' || thedate[i] == '-' || thedate[i] == ':' ) {
479         thedate[i] = '_' ;
480       }
481       i++ ;
482     }
483     _work_directory = std::string("$HOME/Batch/");
484     _work_directory += thedate;
485   }
486   params[Batch::WORKDIR] = _work_directory;
487   params[Batch::TMPDIR] = _work_directory; // To Compatibility -- remove ??? TODO
488
489   // If result_directory is not defined, we use HOME environnement
490   if (_result_directory == "")
491     _result_directory = getenv("HOME");
492
493   // _in_files
494   for(std::list<std::string>::iterator it = _in_files.begin(); it != _in_files.end(); it++)
495   {
496     std::string file = *it;
497
498     // local file -> If file is not an absolute path, we apply _local_directory
499     std::string local_file;
500     if (file.substr(0, 1) == std::string("/"))
501       local_file = file;
502     else
503       local_file = _local_directory + "/" + file;
504     
505     // remote file -> get only file name from _in_files
506     size_t found = file.find_last_of("/");
507     std::string remote_file = _work_directory + "/" + file.substr(found+1);
508
509     params[Batch::INFILE] += Batch::Couple(local_file, remote_file);
510   }
511    
512   // _out_files
513   for(std::list<std::string>::iterator it = _out_files.begin(); it != _out_files.end(); it++)
514   {
515     std::string file = *it;
516
517     // local file 
518     size_t found = file.find_last_of("/");
519     std::string local_file = _result_directory +  "/" + file.substr(found+1);
520
521     // remote file -> If file is not an absolute path, we apply _work_directory
522     std::string remote_file;
523     if (file.substr(0, 1) == std::string("/"))
524       remote_file = file;
525     else
526       remote_file = _work_directory + "/" + file;
527
528     params[Batch::OUTFILE] += Batch::Couple(local_file, remote_file);
529   }
530
531   // Time
532   if (_maximum_duration_in_second != -1)
533     params[Batch::MAXWALLTIME] = _maximum_duration_in_second / 60;
534
535   // Queue
536   if (_queue != "")
537     params[Batch::QUEUE] = _queue;
538
539   // Specific parameters
540   std::map<std::string, std::string>::iterator it = _specific_parameters.find("LoalLevelerJobType");
541   if (it != _specific_parameters.end())
542     params["LL_JOBTYPE"] = it->second;
543   return params;
544 }
545
546 void 
547 Launcher::Job::setBatchManagerJobId(Batch::JobId batch_manager_job_id)
548 {
549   _batch_job_id = batch_manager_job_id;
550 }
551
552 Batch::JobId 
553 Launcher::Job::getBatchManagerJobId()
554 {
555   return _batch_job_id;
556 }
557 #endif
558
559 void
560 Launcher::Job::addToXmlDocument(xmlNodePtr root_node)
561 {
562   // Begin job
563   xmlNodePtr job_node = xmlNewChild(root_node, NULL, xmlCharStrdup("job"), NULL);
564   xmlNewProp(job_node, xmlCharStrdup("type"), xmlCharStrdup(getJobType().c_str()));
565   xmlNewProp(job_node, xmlCharStrdup("name"), xmlCharStrdup(getJobName().c_str()));
566
567   // Add user part
568   xmlNodePtr node = xmlNewChild(job_node, NULL, xmlCharStrdup("user_part"), NULL);
569
570   xmlNewChild(node, NULL, xmlCharStrdup("job_file"),         xmlCharStrdup(getJobFile().c_str()));
571   xmlNewChild(node, NULL, xmlCharStrdup("env_file"),         xmlCharStrdup(getEnvFile().c_str()));
572   xmlNewChild(node, NULL, xmlCharStrdup("work_directory"),   xmlCharStrdup(getWorkDirectory().c_str()));
573   xmlNewChild(node, NULL, xmlCharStrdup("local_directory"),  xmlCharStrdup(getLocalDirectory().c_str()));
574   xmlNewChild(node, NULL, xmlCharStrdup("result_directory"), xmlCharStrdup(getResultDirectory().c_str()));
575
576   // Files
577   xmlNodePtr files_node = xmlNewChild(node, NULL, xmlCharStrdup("files"), NULL);
578   std::list<std::string> in_files  = get_in_files();
579   std::list<std::string> out_files = get_out_files();
580   for(std::list<std::string>::iterator it = in_files.begin(); it != in_files.end(); it++)
581     xmlNewChild(files_node, NULL, xmlCharStrdup("in_file"), xmlCharStrdup((*it).c_str()));
582   for(std::list<std::string>::iterator it = out_files.begin(); it != out_files.end(); it++)
583     xmlNewChild(files_node, NULL, xmlCharStrdup("out_file"), xmlCharStrdup((*it).c_str()));
584
585   // Resource part
586   resourceParams resource_params = getResourceRequiredParams();
587   xmlNodePtr res_node = xmlNewChild(node, NULL, xmlCharStrdup("resource_params"), NULL);
588   xmlNewChild(res_node, NULL, xmlCharStrdup("name"),   xmlCharStrdup(resource_params.name.c_str()));
589   xmlNewChild(res_node, NULL, xmlCharStrdup("hostname"),   xmlCharStrdup(resource_params.hostname.c_str()));
590   xmlNewChild(res_node, NULL, xmlCharStrdup("OS"),   xmlCharStrdup(resource_params.OS.c_str()));
591   std::ostringstream nb_proc_stream;
592   std::ostringstream nb_node_stream;
593   std::ostringstream nb_proc_per_node_stream;
594   std::ostringstream cpu_clock_stream;
595   std::ostringstream mem_mb_stream;
596   nb_proc_stream << resource_params.nb_proc;
597   nb_node_stream << resource_params.nb_node;
598   nb_proc_per_node_stream << resource_params.nb_proc_per_node;
599   cpu_clock_stream << resource_params.cpu_clock;
600   mem_mb_stream << resource_params.mem_mb;
601   xmlNewChild(res_node, NULL, xmlCharStrdup("nb_proc"),            xmlCharStrdup(nb_proc_stream.str().c_str()));
602   xmlNewChild(res_node, NULL, xmlCharStrdup("nb_node"),            xmlCharStrdup(nb_node_stream.str().c_str()));
603   xmlNewChild(res_node, NULL, xmlCharStrdup("nb_proc_per_node"),   xmlCharStrdup(nb_proc_per_node_stream.str().c_str()));
604   xmlNewChild(res_node, NULL, xmlCharStrdup("cpu_clock"),          xmlCharStrdup(cpu_clock_stream.str().c_str()));
605   xmlNewChild(res_node, NULL, xmlCharStrdup("mem_mb"),             xmlCharStrdup(mem_mb_stream.str().c_str()));
606
607   xmlNewChild(node, NULL, xmlCharStrdup("maximum_duration"), xmlCharStrdup(getMaximumDuration().c_str()));
608   xmlNewChild(node, NULL, xmlCharStrdup("queue"),            xmlCharStrdup(getQueue().c_str()));
609
610   // Specific parameters part
611   xmlNodePtr specific_parameters_node = xmlNewChild(node, NULL, xmlCharStrdup("specific_parameters"), NULL);
612   std::map<std::string, std::string> specific_parameters = getSpecificParameters();
613   for(std::map<std::string, std::string>::iterator it = specific_parameters.begin(); it != specific_parameters.end(); it++)
614   {
615     xmlNodePtr specific_parameter_node = xmlNewChild(specific_parameters_node, NULL, xmlCharStrdup("specific_parameter"), NULL);
616     xmlNewChild(specific_parameter_node, NULL, xmlCharStrdup("name"), xmlCharStrdup((it->first).c_str()));
617     xmlNewChild(specific_parameter_node, NULL, xmlCharStrdup("value"), xmlCharStrdup((it->second).c_str()));
618   }
619
620   // Run part
621   xmlNodePtr run_node = xmlNewChild(job_node, NULL, xmlCharStrdup("run_part"), NULL);
622   xmlNewChild(run_node, NULL, xmlCharStrdup("job_state"), xmlCharStrdup(getState().c_str()));
623   ParserResourcesType resource_definition = getResourceDefinition();
624   xmlNewChild(run_node, NULL, xmlCharStrdup("resource_choosed_name"), xmlCharStrdup(resource_definition.Name.c_str()));
625
626 #ifdef WITH_LIBBATCH
627   Batch::JobId job_id = getBatchManagerJobId();
628   xmlNewChild(run_node, NULL, xmlCharStrdup("job_reference"), xmlCharStrdup(job_id.getReference().c_str()));
629 #endif
630 }
631
632 void 
633 Launcher::Job::addSpecificParameter(const std::string & name,
634                                       const std::string & value)
635 {
636   _specific_parameters[name] = value;
637 }
638
639 const std::map<std::string, std::string> &
640 Launcher::Job::getSpecificParameters()
641 {
642   return _specific_parameters;
643 }
644
645 void
646 Launcher::Job::checkSpecificParameters()
647 {
648 }