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