Salome HOME
Added possibility to add specific parameters in the client classes. Added parameter...
[tools/libbatch.git] / src / PBS / Batch_Job_PBS.cxx
1 //  Copyright (C) 2007-2010  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  * Job_PBS.cxx :
24  *
25  * Auteur : Ivan DUTKA-MALEN - EDF R&D
26  * Mail   : mailto:ivan.dutka-malen@der.edf.fr
27  * Date   : Fri Nov 14 11:00:39 2003
28  * Projet : Salome 2
29  *
30  */
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <cstring>
36
37 #include "Batch_Constants.hxx"
38 #include "Batch_Job_PBS.hxx"
39 using namespace std;
40
41 namespace Batch {
42
43   // Ajoute un element (name,resource,value) a la liste chainee d'attributs + operateur
44   void Job_PBS::setResourceAttributeOP(struct attropl ** attr_list, const char * attr_name, const char * attr_resource, const char * attr_value)
45   {
46     // L'element (name,resource,value) existe-t-il deja ? si oui ptr != 0
47     struct attropl * ptr = findResourceAttributeOP(*attr_list, attr_name, attr_resource);
48
49     if (!ptr) { // L'element n'existe pas, il faut le creer
50       if ((ptr = lastAttributeOP(*attr_list))) { // la liste n'est pas vide
51         ptr->next = new struct attropl;
52         ptr = ptr->next;
53         ptr->next = 0;
54
55       } else { // la liste est completement vide
56         ptr = *attr_list = new struct attropl;
57         ptr->next = 0;
58       }
59
60       // On remplit les champs (name,resource,value)
61       ptr->name = new char[strlen(attr_name) + 1];
62       strncpy(ptr->name, attr_name, strlen(attr_name));
63       ptr->name[strlen(attr_name)] = 0;
64
65       ptr->resource = new char[strlen(attr_resource) + 1];
66       strncpy(ptr->resource, attr_resource, strlen(attr_resource));
67       ptr->resource[strlen(attr_resource)] = 0;
68
69       ptr->value = new char[strlen(attr_value) + 1];
70       strncpy(ptr->value, attr_value, strlen(attr_value));
71       ptr->value[strlen(attr_value)] = 0;
72
73     } else { // L'attribut existe, on change sa valeur
74       delete[] ptr->value; // On efface la valeur precedente
75       ptr->value = new char[strlen(attr_value) + 1];
76       strncpy(ptr->value, attr_value, strlen(attr_value));
77       ptr->value[strlen(attr_value)] = 0;
78
79     }
80   }
81
82
83   // Recherche un element (name,resource,value) dans la liste chainee d'attributs + operateur
84   struct attropl * Job_PBS::findResourceAttributeOP(struct attropl * attr_list, const char * attr_name, const char * attr_resource)
85   {
86     // On parcoure la liste chainee pour trouver l'element dont les champs name et resource coincident
87     struct attropl * ptr = attr_list;
88     while (ptr) {
89       if (!strcmp(ptr->name, attr_name) && !strcmp(ptr->resource, attr_resource)) break;
90       ptr = ptr->next;
91     }
92     return ptr;
93   }
94
95
96   // Recherche le dernier element de la liste chainee d'attributs + operateur
97   struct attropl * Job_PBS::lastAttributeOP(struct attropl * attr_list)
98   {
99     struct attropl * ptr = attr_list;
100     while (ptr && ptr->next) {
101       ptr = ptr->next;
102     }
103     return ptr;
104   }
105
106
107   // Convertit un objet Parametre en liste chainee d'attributs + operateur
108   struct attropl * Job_PBS::ParametreToAttributeOPList(struct attropl ** _p_attr_list, Parametre & P)
109   {
110     Parametre::iterator it;
111     string st_second;
112     for(it=P.begin(); it!=P.end(); it++) {
113       if ( (*it).first == ACCOUNT ) {
114         st_second = (*it).second.str();
115         setResourceAttributeOP(_p_attr_list, ATTR_A, "", st_second.c_str());
116
117
118       } else if ( (*it).first == CHECKPOINT ) {
119         setResourceAttributeOP(_p_attr_list, ATTR_c, "", "u");
120
121
122       } else if ( (*it).first == CKPTINTERVAL ) {
123         // Not significant
124
125       } else if ( (*it).first == EXECUTABLE ) {
126         // Already done
127
128       } else if ( (*it).first == HOLD ) {
129         if (static_cast< long >((*it).second))
130           setResourceAttributeOP(_p_attr_list, ATTR_h, "", USER_HOLD);
131         else
132           setResourceAttributeOP(_p_attr_list, ATTR_h, "", NO_HOLD);
133
134       } else if ( (*it).first == INFILE ) {
135         Versatile V = (*it).second;
136         Versatile::iterator Vit;
137
138         string sep = "";
139         string stagein;
140
141         for(Vit=V.begin(); Vit!=V.end(); Vit++, sep=",") {
142           CoupleType cpt  = *static_cast< CoupleType * >(*Vit);
143           Couple cp       = cpt;
144           string local    = cp.getLocal();
145           string remote   = cp.getRemote();
146
147           // ATTENTION : les notions de fichier "local" ou "remote" sont inverses de celle de PBS qui a un point de vue serveur et non pas utilisateur
148           stagein        += sep + remote + "@" + local;
149         }
150
151         if (stagein.size())
152           setResourceAttributeOP(_p_attr_list, ATTR_stagein, "", stagein.c_str());
153
154
155       } else if ( (*it).first == MAIL ) {
156         st_second = (*it).second.str();
157         setResourceAttributeOP(_p_attr_list, ATTR_M, "", st_second.c_str());
158
159       } else if ( (*it).first == MAXCPUTIME ) {
160         char attr_value[32];
161         long secondes = (*it).second;
162         long heures = secondes / 3600L;
163         long minutes = (secondes - 3600L * heures) / 60L;
164         secondes = secondes % 60L;
165         sprintf(attr_value, "%02ld:%02ld:%02ld", heures, minutes, secondes);
166
167         setResourceAttributeOP(_p_attr_list, ATTR_l, "cput", attr_value);
168
169
170       } else if ( (*it).first == MAXDISKSIZE ) {
171
172       } else if ( (*it).first == MAXRAMSIZE ) {
173
174       } else if ( (*it).first == MAXWALLTIME ) {
175         char attr_value[32];
176         long minutes = (*it).second;
177         long heures = minutes / 60L;
178         minutes -= 60L * heures;
179         sprintf(attr_value, "%02ld:%02ld:00", heures, minutes);
180
181         setResourceAttributeOP(_p_attr_list, ATTR_l, "walltime", attr_value);
182
183
184       } else if ( (*it).first == NAME ) {
185         st_second = (*it).second.str();
186         setResourceAttributeOP(_p_attr_list, ATTR_N, "", st_second.c_str());
187
188
189       } else if ( (*it).first == OUTFILE ) {
190         Versatile V = (*it).second;
191         Versatile::iterator Vit;
192
193         string sep = "";
194         string stageout;
195
196         for(Vit=V.begin(); Vit!=V.end(); Vit++, sep=",") {
197           CoupleType cpt  = *static_cast< CoupleType * >(*Vit);
198           Couple cp       = cpt;
199           string local    = cp.getLocal();
200           string remote   = cp.getRemote();
201
202           if (remote == "stdout")
203             setResourceAttributeOP(_p_attr_list, ATTR_o, "", local.c_str());
204
205           else if (remote == "stderr")
206             setResourceAttributeOP(_p_attr_list, ATTR_e, "", local.c_str());
207
208           else
209             // ATTENTION : les notions de fichier "local" ou "remote" sont inverses de celle de PBS qui a un point de vue serveur et non pas utilisateur
210             stageout       += sep + remote + "@" + local;
211         }
212
213         if (stageout.size())
214           setResourceAttributeOP(_p_attr_list, ATTR_stageout, "", stageout.c_str());
215
216       } else if ( (*it).first == QUEUE ) {
217         // Already done
218
219       } else if ( (*it).first == STARTTIME ) {
220
221       } else if ( (*it).first == TMPDIR ) {
222
223       } else if ( (*it).first == USER ) {
224         st_second = (*it).second.str();
225         setResourceAttributeOP(_p_attr_list, ATTR_u, "", st_second.c_str());
226
227       }
228     }
229     return *_p_attr_list;
230   }
231
232
233   // Convertit un objet Environnement en liste chainee d'attributs + operateur
234   struct attropl * Job_PBS::EnvironnementToAttributeOPList(struct attropl ** _p_attr_list, Environnement & E)
235   {
236     Environnement::iterator it;
237     for(it=E.begin(); it!=E.end(); it++) {
238       setResourceAttributeOP(_p_attr_list, ATTR_v, (*it).first.c_str(), ( (*it).first + "=" + (*it).second ).c_str());
239     }
240     return *_p_attr_list;
241   }
242
243
244   // Ajoute les variables d'environnement presentes dans tout job PBS
245   void Job_PBS::addPBSEnvironnement(Environnement & E)
246   {
247     char * c;
248
249     c = getenv("HOME");
250     if (c) E["PBS_O_HOME"] = c;
251
252     c = getenv("LANG");
253     if (c) E["PBS_O_LANG"] = c;
254
255     c = getenv("LOGNAME");
256     if (c) E["PBS_O_LOGNAME"] = c;
257
258     c = getenv("PATH");
259     if (c) E["PBS_O_PATH"] = c;
260
261     c = getenv("LD_LIBRARY_PATH");
262     if (c) E["PBS_O_LD_LIBRARY_PATH"] = c;
263
264     c = getenv("MAIL");
265     if (c) E["PBS_O_MAIL"] = c;
266
267     c = getenv("SHELL");
268     if (c) E["PBS_O_SHELL"] = c;
269
270     c = getenv("TZ");
271     if (c) E["PBS_O_TZ"] = c;
272
273     /* Recuperation du working directory */
274     size_t size = 256;
275     char * buf = 0;
276     char * rc = 0;
277     do {
278       if (buf) delete[] buf;
279       buf = new char[size];
280       rc = getcwd(buf, size);
281       size += size;
282     } while (!rc);
283     E["PBS_O_WORKDIR"] = buf;
284     delete[] buf;
285   }
286
287
288   // Ajoute un element (name,resource,value) a la liste chainee d'attributs
289   void Job_PBS::setResourceAttribute(struct attrl ** attr_list, const char * attr_name, const char * attr_resource, const char * attr_value)
290   {
291     // L'element (name,resource,value) existe-t-il deja ? si oui ptr != 0
292     struct attrl * ptr = findResourceAttribute(*attr_list, attr_name, attr_resource);
293
294     if (!ptr) { // L'attribut n'existe pas, il faut le creer
295       if ((ptr = lastAttribute(*attr_list))) { // la liste n'est pas vide
296         ptr->next = new struct attrl;
297         ptr = ptr->next;
298         ptr->next = 0;
299
300       } else { // la liste est completement vide
301         ptr = *attr_list = new struct attrl;
302         ptr->next = 0;
303       }
304
305       // On remplit les champs (name,resource,value)
306       ptr->name = new char[strlen(attr_name) + 1];
307       strncpy(ptr->name, attr_name, strlen(attr_name));
308       ptr->name[strlen(attr_name)] = 0;
309
310       ptr->resource = new char[strlen(attr_resource) + 1];
311       strncpy(ptr->resource, attr_resource, strlen(attr_resource));
312       ptr->resource[strlen(attr_resource)] = 0;
313
314       ptr->value = new char[strlen(attr_value) + 1];
315       strncpy(ptr->value, attr_value, strlen(attr_value));
316       ptr->value[strlen(attr_value)] = 0;
317
318     } else { // L'attribut existe, on change sa valeur
319       delete[] ptr->value; // On efface la valeur precedente
320       ptr->value = new char[strlen(attr_value) + 1];
321       strncpy(ptr->value, attr_value, strlen(attr_value));
322       ptr->value[strlen(attr_value)] = 0;
323
324     }
325   }
326
327   // Recherche un element (name,resource,value) dans la liste chainee d'attributs
328   struct attrl * Job_PBS::findResourceAttribute(struct attrl * attr_list, const char * attr_name, const char * attr_resource)
329   {
330     // On parcoure la liste chainee pour trouver l'element dont les champs name et resource coincident
331     struct attrl * ptr = attr_list;
332     while (ptr) {
333       if (!strcmp(ptr->name, attr_name) && !strcmp(ptr->resource, attr_resource)) break;
334       ptr = ptr->next;
335     }
336     return ptr;
337   }
338
339
340   // Recherche le dernier element de la liste chainee d'attributs
341   struct attrl * Job_PBS::lastAttribute(struct attrl * attr_list)
342   {
343     struct attrl * ptr = attr_list;
344     while (ptr && ptr->next) {
345       ptr = ptr->next;
346     }
347     return ptr;
348   }
349
350
351   // Constructeur
352   Job_PBS::Job_PBS(const Job & job) : _p_attropl(0), _p_attrl(0), _script(0), _destination(0)
353   {
354     Parametre P = job.getParametre();
355     Parametre::iterator it;
356
357     // On extrait de l'objet Parametre le champ EXECUTABLE qui deviendra le script PBS
358     if ( (it=P.find(EXECUTABLE)) != P.end()) {
359       Versatile V = (*it).second;
360       string st_exe = V.str();
361       const char * exe = st_exe.c_str();
362       int lg = strlen(exe);
363       _script = new char[lg + 1];
364       for (int ii=0; ii<lg+1; ii++) _script[ii] = 0;
365       strcpy(_script, exe);
366       _script[lg] = 0;
367
368     } else {
369       _script = new char[1];
370       _script[0] = 0;
371     }
372
373     // On extrait de l'objet Parametre le champ QUEUE qui deviendra la destination
374     if ( (it=P.find(QUEUE)) != P.end()) {
375       Versatile V = (*it).second;
376       string st_dest = V.str();
377       const char * dest = st_dest.c_str();
378       _destination = new char[strlen(dest) + 2 + 1];
379       _destination[0] = 0;
380       strcat(_destination, dest);
381       _destination[strlen(dest)] = 0;
382     } else {
383       _destination = new char[1];
384       _destination[0] = 0;
385     }
386
387     // On convertit les objets Parametre et Environnement en liste chainee d'attributs + operateur
388     Environnement E = job.getEnvironnement();
389     addPBSEnvironnement(E);
390
391     _p_attropl = ParametreToAttributeOPList(&_p_attropl, P);
392     _p_attropl = EnvironnementToAttributeOPList(&_p_attropl, E);
393
394   }
395
396
397   // Destructeur
398   Job_PBS::~Job_PBS()
399   {
400     // On detruit la liste chainee d'attributs + operateur
401     struct attropl * current_p_attropl = _p_attropl;
402     while (current_p_attropl) {
403       struct attropl * next = current_p_attropl->next;
404       delete[] current_p_attropl->name;
405       delete[] current_p_attropl->resource;
406       delete[] current_p_attropl->value;
407       delete current_p_attropl;
408       current_p_attropl = next;
409     }
410
411     // On detruit la liste chainee d'attributs
412     struct attrl * current_p_attrl = _p_attrl;
413     while (current_p_attrl) {
414       struct attrl * next = current_p_attrl->next;
415       delete[] current_p_attrl->name;
416       delete[] current_p_attrl->resource;
417       delete[] current_p_attrl->value;
418       delete current_p_attrl;
419       current_p_attrl = next;
420     }
421
422     // On detruit les champs alloues
423     delete[] _script;
424     delete[] _destination;
425   }
426
427
428   // Accesseur
429   struct attropl * Job_PBS::getAttributesOP()
430   {
431     return _p_attropl;
432   }
433
434   // Accesseur
435   // Cette methode sert pour les pbs_alter de PBS
436   // Pbs_alter est bugg� par rapport a la specification ers_all.ps car les
437   // variables d'environnement ne sont pas supportees (ATTR_v)
438   struct attrl * Job_PBS::getAttributes()
439   {
440     if (_p_attrl == 0) {
441
442       // On remplit la structure attrl a partir de la strucuture attropl
443       // (elles ne different que par le parametre op, mais elles ne sont pas interchangeables
444       // dans les appels)
445
446       struct attropl * current_p_attropl = _p_attropl;
447       while (current_p_attropl) {
448         if (strcmp(current_p_attropl->name, ATTR_v))  // Bug fix for ATTR_v
449           setResourceAttribute(&_p_attrl,
450                                current_p_attropl->name,
451                                current_p_attropl->resource,
452                                current_p_attropl->value);
453
454         current_p_attropl = current_p_attropl->next;
455       }
456
457     }
458
459     return _p_attrl;
460   }
461
462   // Accesseur
463   char * Job_PBS::getScript()
464   {
465     return _script;
466   }
467
468   // Accesseur
469   char * Job_PBS::getDestination()
470   {
471     return _destination;
472   }
473
474 }