Salome HOME
Initial import: adding files
[tools/libbatch.git] / src / PBS / Batch_Job_PBS.cxx
diff --git a/src/PBS/Batch_Job_PBS.cxx b/src/PBS/Batch_Job_PBS.cxx
new file mode 100644 (file)
index 0000000..f55f05a
--- /dev/null
@@ -0,0 +1,472 @@
+//  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+//  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+//  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+/*
+ * Job_PBS.cxx :
+ *
+ * Auteur : Ivan DUTKA-MALEN - EDF R&D
+ * Mail   : mailto:ivan.dutka-malen@der.edf.fr
+ * Date   : Fri Nov 14 11:00:39 2003
+ * Projet : Salome 2
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "Batch_Job_PBS.hxx"
+using namespace std;
+
+namespace Batch {
+
+  // Ajoute un element (name,resource,value) a la liste chainee d'attributs + operateur
+  void Job_PBS::setResourceAttributeOP(struct attropl ** attr_list, const char * attr_name, const char * attr_resource, const char * attr_value)
+  {
+    // L'element (name,resource,value) existe-t-il deja ? si oui ptr != 0
+    struct attropl * ptr = findResourceAttributeOP(*attr_list, attr_name, attr_resource);
+
+    if (!ptr) { // L'element n'existe pas, il faut le creer
+      if ((ptr = lastAttributeOP(*attr_list))) { // la liste n'est pas vide
+        ptr->next = new struct attropl;
+        ptr = ptr->next;
+        ptr->next = 0;
+
+      } else { // la liste est completement vide
+        ptr = *attr_list = new struct attropl;
+        ptr->next = 0;
+      }
+
+      // On remplit les champs (name,resource,value)
+      ptr->name = new char[strlen(attr_name) + 1];
+      strncpy(ptr->name, attr_name, strlen(attr_name));
+      ptr->name[strlen(attr_name)] = 0;
+
+      ptr->resource = new char[strlen(attr_resource) + 1];
+      strncpy(ptr->resource, attr_resource, strlen(attr_resource));
+      ptr->resource[strlen(attr_resource)] = 0;
+
+      ptr->value = new char[strlen(attr_value) + 1];
+      strncpy(ptr->value, attr_value, strlen(attr_value));
+      ptr->value[strlen(attr_value)] = 0;
+
+    } else { // L'attribut existe, on change sa valeur
+      delete[] ptr->value; // On efface la valeur precedente
+      ptr->value = new char[strlen(attr_value) + 1];
+      strncpy(ptr->value, attr_value, strlen(attr_value));
+      ptr->value[strlen(attr_value)] = 0;
+
+    }
+  }
+
+
+  // Recherche un element (name,resource,value) dans la liste chainee d'attributs + operateur
+  struct attropl * Job_PBS::findResourceAttributeOP(struct attropl * attr_list, const char * attr_name, const char * attr_resource)
+  {
+    // On parcoure la liste chainee pour trouver l'element dont les champs name et resource coincident
+    struct attropl * ptr = attr_list;
+    while (ptr) {
+      if (!strcmp(ptr->name, attr_name) && !strcmp(ptr->resource, attr_resource)) break;
+      ptr = ptr->next;
+    }
+    return ptr;
+  }
+
+
+  // Recherche le dernier element de la liste chainee d'attributs + operateur
+  struct attropl * Job_PBS::lastAttributeOP(struct attropl * attr_list)
+  {
+    struct attropl * ptr = attr_list;
+    while (ptr && ptr->next) {
+      ptr = ptr->next;
+    }
+    return ptr;
+  }
+
+
+  // Convertit un objet Parametre en liste chainee d'attributs + operateur
+  struct attropl * Job_PBS::ParametreToAttributeOPList(struct attropl ** _p_attr_list, Parametre & P)
+  {
+    Parametre::iterator it;
+    string st_second;
+    for(it=P.begin(); it!=P.end(); it++) {
+      if ( (*it).first == ACCOUNT ) {
+       st_second = (*it).second.str();
+       setResourceAttributeOP(_p_attr_list, ATTR_A, "", st_second.c_str());
+
+
+      } else if ( (*it).first == CHECKPOINT ) {
+       setResourceAttributeOP(_p_attr_list, ATTR_c, "", "u");
+
+
+      } else if ( (*it).first == CKPTINTERVAL ) {
+       // Not significant
+
+      } else if ( (*it).first == EXECUTABLE ) {
+       // Already done
+
+      } else if ( (*it).first == HOLD ) {
+       if (static_cast< long >((*it).second))
+         setResourceAttributeOP(_p_attr_list, ATTR_h, "", USER_HOLD);
+       else
+         setResourceAttributeOP(_p_attr_list, ATTR_h, "", NO_HOLD);
+
+      } else if ( (*it).first == INFILE ) {
+       Versatile V = (*it).second;
+       Versatile::iterator Vit;
+
+       string sep = "";
+       string stagein;
+
+       for(Vit=V.begin(); Vit!=V.end(); Vit++, sep=",") {
+         CoupleType cpt  = *static_cast< CoupleType * >(*Vit);
+         Couple cp       = cpt;
+         string local    = cp.getLocal();
+         string remote   = cp.getRemote();
+
+         // 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
+         stagein        += sep + remote + "@" + local;
+       }
+
+       if (stagein.size())
+         setResourceAttributeOP(_p_attr_list, ATTR_stagein, "", stagein.c_str());
+
+
+      } else if ( (*it).first == MAIL ) {
+       st_second = (*it).second.str();
+       setResourceAttributeOP(_p_attr_list, ATTR_M, "", st_second.c_str());
+
+      } else if ( (*it).first == MAXCPUTIME ) {
+       char attr_value[32];
+       long secondes = (*it).second;
+       long heures = secondes / 3600L;
+       long minutes = (secondes - 3600L * heures) / 60L;
+       secondes = secondes % 60L;
+       sprintf(attr_value, "%02ld:%02ld:%02ld", heures, minutes, secondes);
+
+       setResourceAttributeOP(_p_attr_list, ATTR_l, "cput", attr_value);
+
+
+      } else if ( (*it).first == MAXDISKSIZE ) {
+
+      } else if ( (*it).first == MAXRAMSIZE ) {
+
+      } else if ( (*it).first == MAXWALLTIME ) {
+       char attr_value[32];
+       long secondes = (*it).second;
+       long heures = secondes / 3600L;
+       long minutes = (secondes - 3600L * heures) / 60L;
+       secondes = secondes % 60L;
+       sprintf(attr_value, "%02ld:%02ld:%02ld", heures, minutes, secondes);
+
+       setResourceAttributeOP(_p_attr_list, ATTR_l, "walltime", attr_value);
+
+
+      } else if ( (*it).first == NAME ) {
+       st_second = (*it).second.str();
+       setResourceAttributeOP(_p_attr_list, ATTR_N, "", st_second.c_str());
+
+
+      } else if ( (*it).first == OUTFILE ) {
+       Versatile V = (*it).second;
+       Versatile::iterator Vit;
+
+       string sep = "";
+       string stageout;
+
+       for(Vit=V.begin(); Vit!=V.end(); Vit++, sep=",") {
+         CoupleType cpt  = *static_cast< CoupleType * >(*Vit);
+         Couple cp       = cpt;
+         string local    = cp.getLocal();
+         string remote   = cp.getRemote();
+
+         if (remote == "stdout")
+           setResourceAttributeOP(_p_attr_list, ATTR_o, "", local.c_str());
+
+         else if (remote == "stderr")
+           setResourceAttributeOP(_p_attr_list, ATTR_e, "", local.c_str());
+
+         else
+           // 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
+           stageout       += sep + remote + "@" + local;
+       }
+
+       if (stageout.size())
+         setResourceAttributeOP(_p_attr_list, ATTR_stageout, "", stageout.c_str());
+
+      } else if ( (*it).first == QUEUE ) {
+       // Already done
+
+      } else if ( (*it).first == STARTTIME ) {
+
+      } else if ( (*it).first == TMPDIR ) {
+
+      } else if ( (*it).first == USER ) {
+       st_second = (*it).second.str();
+       setResourceAttributeOP(_p_attr_list, ATTR_u, "", st_second.c_str());
+
+      }
+    }
+    return *_p_attr_list;
+  }
+
+
+  // Convertit un objet Environnement en liste chainee d'attributs + operateur
+  struct attropl * Job_PBS::EnvironnementToAttributeOPList(struct attropl ** _p_attr_list, Environnement & E)
+  {
+    Environnement::iterator it;
+    for(it=E.begin(); it!=E.end(); it++) {
+      setResourceAttributeOP(_p_attr_list, ATTR_v, (*it).first.c_str(), ( (*it).first + "=" + (*it).second ).c_str());
+    }
+    return *_p_attr_list;
+  }
+
+
+  // Ajoute les variables d'environnement presentes dans tout job PBS
+  void Job_PBS::addPBSEnvironnement(Environnement & E)
+  {
+    char * c;
+
+    c = getenv("HOME");
+    if (c) E["PBS_O_HOME"] = c;
+
+    c = getenv("LANG");
+    if (c) E["PBS_O_LANG"] = c;
+
+    c = getenv("LOGNAME");
+    if (c) E["PBS_O_LOGNAME"] = c;
+
+    c = getenv("PATH");
+    if (c) E["PBS_O_PATH"] = c;
+
+    c = getenv("LD_LIBRARY_PATH");
+    if (c) E["PBS_O_LD_LIBRARY_PATH"] = c;
+
+    c = getenv("MAIL");
+    if (c) E["PBS_O_MAIL"] = c;
+
+    c = getenv("SHELL");
+    if (c) E["PBS_O_SHELL"] = c;
+
+    c = getenv("TZ");
+    if (c) E["PBS_O_TZ"] = c;
+
+    /* Recuperation du working directory */
+    size_t size = 256;
+    char * buf = 0;
+    char * rc = 0;
+    do {
+      if (buf) delete[] buf;
+      buf = new char[size];
+      rc = getcwd(buf, size);
+      size += size;
+    } while (!rc);
+    E["PBS_O_WORKDIR"] = buf;
+    delete[] buf;
+  }
+
+
+  // Ajoute un element (name,resource,value) a la liste chainee d'attributs
+  void Job_PBS::setResourceAttribute(struct attrl ** attr_list, const char * attr_name, const char * attr_resource, const char * attr_value)
+  {
+    // L'element (name,resource,value) existe-t-il deja ? si oui ptr != 0
+    struct attrl * ptr = findResourceAttribute(*attr_list, attr_name, attr_resource);
+
+    if (!ptr) { // L'attribut n'existe pas, il faut le creer
+      if ((ptr = lastAttribute(*attr_list))) { // la liste n'est pas vide
+        ptr->next = new struct attrl;
+        ptr = ptr->next;
+        ptr->next = 0;
+
+      } else { // la liste est completement vide
+        ptr = *attr_list = new struct attrl;
+        ptr->next = 0;
+      }
+
+      // On remplit les champs (name,resource,value)
+      ptr->name = new char[strlen(attr_name) + 1];
+      strncpy(ptr->name, attr_name, strlen(attr_name));
+      ptr->name[strlen(attr_name)] = 0;
+
+      ptr->resource = new char[strlen(attr_resource) + 1];
+      strncpy(ptr->resource, attr_resource, strlen(attr_resource));
+      ptr->resource[strlen(attr_resource)] = 0;
+
+      ptr->value = new char[strlen(attr_value) + 1];
+      strncpy(ptr->value, attr_value, strlen(attr_value));
+      ptr->value[strlen(attr_value)] = 0;
+
+    } else { // L'attribut existe, on change sa valeur
+      delete[] ptr->value; // On efface la valeur precedente
+      ptr->value = new char[strlen(attr_value) + 1];
+      strncpy(ptr->value, attr_value, strlen(attr_value));
+      ptr->value[strlen(attr_value)] = 0;
+
+    }
+  }
+
+  // Recherche un element (name,resource,value) dans la liste chainee d'attributs
+  struct attrl * Job_PBS::findResourceAttribute(struct attrl * attr_list, const char * attr_name, const char * attr_resource)
+  {
+    // On parcoure la liste chainee pour trouver l'element dont les champs name et resource coincident
+    struct attrl * ptr = attr_list;
+    while (ptr) {
+      if (!strcmp(ptr->name, attr_name) && !strcmp(ptr->resource, attr_resource)) break;
+      ptr = ptr->next;
+    }
+    return ptr;
+  }
+
+
+  // Recherche le dernier element de la liste chainee d'attributs
+  struct attrl * Job_PBS::lastAttribute(struct attrl * attr_list)
+  {
+    struct attrl * ptr = attr_list;
+    while (ptr && ptr->next) {
+      ptr = ptr->next;
+    }
+    return ptr;
+  }
+
+
+  // Constructeur
+  Job_PBS::Job_PBS(const Job & job) : _p_attropl(0), _p_attrl(0), _script(0), _destination(0)
+  {
+    Parametre P = job.getParametre();
+    Parametre::iterator it;
+
+    // On extrait de l'objet Parametre le champ EXECUTABLE qui deviendra le script PBS
+    if ( (it=P.find(EXECUTABLE)) != P.end()) {
+      Versatile V = (*it).second;
+      string st_exe = V.str();
+      const char * exe = st_exe.c_str();
+      int lg = strlen(exe);
+      _script = new char[lg + 1];
+      for (int ii=0; ii<lg+1; ii++) _script[ii] = 0;
+      strcpy(_script, exe);
+      _script[lg] = 0;
+
+    } else {
+      _script = new char[1];
+      _script[0] = 0;
+    }
+
+    // On extrait de l'objet Parametre le champ QUEUE qui deviendra la destination
+    if ( (it=P.find(QUEUE)) != P.end()) {
+      Versatile V = (*it).second;
+      string st_dest = V.str();
+      const char * dest = st_dest.c_str();
+      _destination = new char[strlen(dest) + 2 + 1];
+      _destination[0] = 0;
+      strcat(_destination, dest);
+      _destination[strlen(dest)] = 0;
+    } else {
+      _destination = new char[1];
+      _destination[0] = 0;
+    }
+
+    // On convertit les objets Parametre et Environnement en liste chainee d'attributs + operateur
+    Environnement E = job.getEnvironnement();
+    addPBSEnvironnement(E);
+
+    _p_attropl = ParametreToAttributeOPList(&_p_attropl, P);
+    _p_attropl = EnvironnementToAttributeOPList(&_p_attropl, E);
+
+  }
+
+
+  // Destructeur
+  Job_PBS::~Job_PBS()
+  {
+    // On detruit la liste chainee d'attributs + operateur
+    struct attropl * current_p_attropl = _p_attropl;
+    while (current_p_attropl) {
+      struct attropl * next = current_p_attropl->next;
+      delete[] current_p_attropl->name;
+      delete[] current_p_attropl->resource;
+      delete[] current_p_attropl->value;
+      delete current_p_attropl;
+      current_p_attropl = next;
+    }
+
+    // On detruit la liste chainee d'attributs
+    struct attrl * current_p_attrl = _p_attrl;
+    while (current_p_attrl) {
+      struct attrl * next = current_p_attrl->next;
+      delete[] current_p_attrl->name;
+      delete[] current_p_attrl->resource;
+      delete[] current_p_attrl->value;
+      delete current_p_attrl;
+      current_p_attrl = next;
+    }
+
+    // On detruit les champs alloues
+    delete[] _script;
+    delete[] _destination;
+  }
+
+
+  // Accesseur
+  struct attropl * Job_PBS::getAttributesOP()
+  {
+    return _p_attropl;
+  }
+
+  // Accesseur
+  // Cette methode sert pour les pbs_alter de PBS
+  // Pbs_alter est bugg� par rapport a la specification ers_all.ps car les
+  // variables d'environnement ne sont pas supportees (ATTR_v)
+  struct attrl * Job_PBS::getAttributes()
+  {
+    if (_p_attrl == 0) {
+
+      // On remplit la structure attrl a partir de la strucuture attropl
+      // (elles ne different que par le parametre op, mais elles ne sont pas interchangeables
+      // dans les appels)
+
+      struct attropl * current_p_attropl = _p_attropl;
+      while (current_p_attropl) {
+       if (strcmp(current_p_attropl->name, ATTR_v))  // Bug fix for ATTR_v
+         setResourceAttribute(&_p_attrl,
+                              current_p_attropl->name,
+                              current_p_attropl->resource,
+                              current_p_attropl->value);
+
+       current_p_attropl = current_p_attropl->next;
+      }
+
+    }
+
+    return _p_attrl;
+  }
+
+  // Accesseur
+  char * Job_PBS::getScript()
+  {
+    return _script;
+  }
+
+  // Accesseur
+  char * Job_PBS::getDestination()
+  {
+    return _destination;
+  }
+
+}