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