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
14 #include "Batch_Job_PBS.hxx"
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)
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);
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;
31 } else { // la liste est completement vide
32 ptr = *attr_list = new struct attropl;
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;
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;
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;
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;
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)
62 // On parcoure la liste chainee pour trouver l'element dont les champs name et resource coincident
63 struct attropl * ptr = attr_list;
65 if (!strcmp(ptr->name, attr_name) && !strcmp(ptr->resource, attr_resource)) break;
72 // Recherche le dernier element de la liste chainee d'attributs + operateur
73 struct attropl * Job_PBS::lastAttributeOP(struct attropl * attr_list)
75 struct attropl * ptr = attr_list;
76 while (ptr && ptr->next) {
83 // Convertit un objet Parametre en liste chainee d'attributs + operateur
84 struct attropl * Job_PBS::ParametreToAttributeOPList(struct attropl ** _p_attr_list, Parametre & P)
86 Parametre::iterator it;
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());
94 } else if ( (*it).first == CHECKPOINT ) {
95 setResourceAttributeOP(_p_attr_list, ATTR_c, "", "u");
98 } else if ( (*it).first == CKPTINTERVAL ) {
101 } else if ( (*it).first == EXECUTABLE ) {
104 } else if ( (*it).first == HOLD ) {
105 if (static_cast< long >((*it).second))
106 setResourceAttributeOP(_p_attr_list, ATTR_h, "", USER_HOLD);
108 setResourceAttributeOP(_p_attr_list, ATTR_h, "", NO_HOLD);
110 } else if ( (*it).first == INFILE ) {
111 Versatile V = (*it).second;
112 Versatile::iterator Vit;
117 for(Vit=V.begin(); Vit!=V.end(); Vit++, sep=",") {
118 CoupleType cpt = *static_cast< CoupleType * >(*Vit);
120 string local = cp.getLocal();
121 string remote = cp.getRemote();
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;
128 setResourceAttributeOP(_p_attr_list, ATTR_stagein, "", stagein.c_str());
131 } else if ( (*it).first == MAIL ) {
132 st_second = (*it).second.str();
133 setResourceAttributeOP(_p_attr_list, ATTR_M, "", st_second.c_str());
135 } else if ( (*it).first == MAXCPUTIME ) {
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);
143 setResourceAttributeOP(_p_attr_list, ATTR_l, "cput", attr_value);
146 } else if ( (*it).first == MAXDISKSIZE ) {
148 } else if ( (*it).first == MAXRAMSIZE ) {
150 } else if ( (*it).first == MAXWALLTIME ) {
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);
158 setResourceAttributeOP(_p_attr_list, ATTR_l, "walltime", attr_value);
161 } else if ( (*it).first == NAME ) {
162 st_second = (*it).second.str();
163 setResourceAttributeOP(_p_attr_list, ATTR_N, "", st_second.c_str());
166 } else if ( (*it).first == OUTFILE ) {
167 Versatile V = (*it).second;
168 Versatile::iterator Vit;
173 for(Vit=V.begin(); Vit!=V.end(); Vit++, sep=",") {
174 CoupleType cpt = *static_cast< CoupleType * >(*Vit);
176 string local = cp.getLocal();
177 string remote = cp.getRemote();
179 if (remote == "stdout")
180 setResourceAttributeOP(_p_attr_list, ATTR_o, "", local.c_str());
182 else if (remote == "stderr")
183 setResourceAttributeOP(_p_attr_list, ATTR_e, "", local.c_str());
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;
191 setResourceAttributeOP(_p_attr_list, ATTR_stageout, "", stageout.c_str());
193 } else if ( (*it).first == QUEUE ) {
196 } else if ( (*it).first == STARTDATE ) {
198 } else if ( (*it).first == TMPDIR ) {
200 } else if ( (*it).first == USER ) {
201 st_second = (*it).second.str();
202 setResourceAttributeOP(_p_attr_list, ATTR_u, "", st_second.c_str());
206 return *_p_attr_list;
210 // Convertit un objet Environnement en liste chainee d'attributs + operateur
211 struct attropl * Job_PBS::EnvironnementToAttributeOPList(struct attropl ** _p_attr_list, Environnement & E)
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());
217 return *_p_attr_list;
221 // Ajoute les variables d'environnement presentes dans tout job PBS
222 void Job_PBS::addPBSEnvironnement(Environnement & E)
227 if (c) E["PBS_O_HOME"] = c;
230 if (c) E["PBS_O_LANG"] = c;
232 c = getenv("LOGNAME");
233 if (c) E["PBS_O_LOGNAME"] = c;
236 if (c) E["PBS_O_PATH"] = c;
238 c = getenv("LD_LIBRARY_PATH");
239 if (c) E["PBS_O_LD_LIBRARY_PATH"] = c;
242 if (c) E["PBS_O_MAIL"] = c;
245 if (c) E["PBS_O_SHELL"] = c;
248 if (c) E["PBS_O_TZ"] = c;
250 /* Recuperation du working directory */
255 if (buf) delete[] buf;
256 buf = new char[size];
257 rc = getcwd(buf, size);
260 E["PBS_O_WORKDIR"] = buf;
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)
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);
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;
277 } else { // la liste est completement vide
278 ptr = *attr_list = new struct attrl;
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;
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;
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;
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;
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)
307 // On parcoure la liste chainee pour trouver l'element dont les champs name et resource coincident
308 struct attrl * ptr = attr_list;
310 if (!strcmp(ptr->name, attr_name) && !strcmp(ptr->resource, attr_resource)) break;
317 // Recherche le dernier element de la liste chainee d'attributs
318 struct attrl * Job_PBS::lastAttribute(struct attrl * attr_list)
320 struct attrl * ptr = attr_list;
321 while (ptr && ptr->next) {
329 Job_PBS::Job_PBS(const Job & job) : _p_attropl(0), _p_attrl(0), _script(0), _destination(0)
331 Parametre P = job.getParametre();
332 Parametre::iterator it;
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);
346 _script = new char[1];
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];
357 strcat(_destination, dest);
358 _destination[strlen(dest)] = 0;
360 _destination = new char[1];
364 // On convertit les objets Parametre et Environnement en liste chainee d'attributs + operateur
365 Environnement E = job.getEnvironnement();
366 addPBSEnvironnement(E);
368 _p_attropl = ParametreToAttributeOPList(&_p_attropl, P);
369 _p_attropl = EnvironnementToAttributeOPList(&_p_attropl, E);
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;
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;
399 // On detruit les champs alloues
401 delete[] _destination;
406 struct attropl * Job_PBS::getAttributesOP()
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()
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
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);
431 current_p_attropl = current_p_attropl->next;
440 char * Job_PBS::getScript()
446 char * Job_PBS::getDestination()