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