     [file version.texi not included]

Copyright © 2003-2004 EDF R&D sous licence GPL

Introduction
************

Ceci est la documentation de la bibliotheque de classes Batch version VERSION.

Ce manuel est normalement disponible sous la forme de fichiers .info, PostScript .ps, PDF .pdf et HTML .html. Merci a Texinfo.

Description Generale
********************

Dans le domaine du batch, nombreux sont les gestionnaires qui sont apparus et se sont popularises en fonction des plates-formes et des constructeurs. On peut notamment citer NQS, le premier de tous, LSF, LoadLeveler, PBS (et ses derives OpenPBS et PBS Pro), etc. qui se prevalent tous d'une compatibilite avec NQS.

Si l'ensemble de ces produits offrent les fonctionnalites de base de NQS, a savoir soumission, controle, destruction, modification, etc. de travaux batch, ils se distinguent tous par leur incompatibilite mutuelle et par les syntaxes de fichiers et les appels de fonction specifiques qu'ils ont developpes.

Or il est interessant de pouvoir acceder d'une facon homogene et generique aux fonctionnalites de ces gestionnaires quitte a se restreindre a un sous-ensemble minimal mais essentiel de leurs possibilites.

La bibliotheque de classes Batch fournit ce moyen de soumettre et controler des travaux batch depuis une machine cliente sans s'occuper du type de gestionnaire present sur le serveur sur lequel se deroule l'execution du travail. Seul doit etre precise le nom du serveur sur lequel sera soumis le travail batch et le type de gestionnaire qui s'y trouve. Tout le reste est generique et ne depend plus de l'implementation.

Classes Internes
****************

Les classes de la bibliotheque reposent sur des concepts issus du monde de la gestion de batch, qui meritent d'etre reprecises pour ne pas introduire d'ambiguite semantique dans le discours.

Terminologie
============

Pour les non-inities aux mysteres de la gestion de batch, un petit glossaire des termes employes dans cette documentation, assaisonne a la sauce de la bibliotheque de classes Batch.

Batch
-----

Le traitement batch (batch processing en anglais), ou traitement par lot, fait reference au mode de sequencage et d'utilisation des ressources d'un calculateur tel qu'il a ete premierement employe dans les debuts de l'ere informatique. Mais il faut preciser que cette anteriorite ne condamne pas le traitement batch aux oubliettes au motif d'une quelconque obsolescence. Si le traitement par lot a vu le jour et existe encore aujourd'hui, c'est parce qu'il repond de maniere satisfaisante a une certaine utilisation des ressources d'un calculateur, et que cette utilisation est encore d'actualite. Present depuis plus de quarante ans, le batch est encore largement utilise sur les grands serveurs, et le sera vraisemblablement pour quelques annees encore.

Le traitement par lot se distingue de l'execution interactive par le fait que les travaux a effectuer sont places dans une file d'attente avec une indication pour chaque lot des ressources dont il doit disposer pour aboutir correctement. Une fois les travaux inscrits dans la file, c'est au systeme de traitement batch (see BatchManager.) de veiller a leur bonne execution en leur fournissant les ressources demandees. Tout travail qui ne disposerait pas des ressources adequates ne peut pas etre active.

Batch Manager
-------------

Le role du gestionnaire de batch, ou batch manager en anglais, est d'executer et eventuellement d'ordonner les travaux places en file d'attente en leur allouant exclusivement les ressources necessaires a leur execution. Son objectif est d'optimiser les ressources du systeme dont il a la charge de maniere a ecouler le maximum de travaux en un minimum de temps et un minimum de ressources materielles.

Job
---

Le travail, ou job en anglais, est l'unite elementaire de traitement qui peut etre soumis au gestionnaire de batch. Il peut s'agir d'une simple commande systeme, comme d'une application ou bien meme de l'enchainement complexe mais indivisible de plusieurs applications ou commandes.

Pour s'executer correctement, c'est-a-dire sans erreur, le job doit disposer de certaines ressources --- de la memoire, du temps, de l'espace disque ... --- pendant toute la duree de son execution. C'est au gestionnaire de batch (see BatchManager.) de garantir au job la presence et la persistence de ces ressources pendant l'execution du job.

Par contre c'est a l'utilisateur qui soumet le job d'informer le gestionnaire de batch des ressources necessaires au job. Pour des raisons evidentes de bonne gestion des ressources, le job ne peut consommer plus de ressources que celles qu'il a demande et obtenu du gestionnaire de batch sans etre arrete ou reclasse.

Parametre
---------

Le premier type de ressource necessaire a un job concerne les elements materiels ou temporels, en un mot, physiques. Parmi ces ressources, on trouve le temps de calcul, le temps de presence en machine, l'espace disque, la quantite de memoire vive, l'architecture du calculateur, etc.

Dans la terminologie de la bibliotheque de classes Batch, tous ces elements ont ete regroupes sous le terme de Parametre.

Environnement
-------------

Le second type de ressource necessaire a un job concerne les elements logiciels. Cela se traduit le plus souvent, et particulierement, dans les systemes Unix par la notion de variable d'environnement. Lorsque le job s'execute, il doit pouvoir trouver l'ensemble des commandes et des applications auquel il souhaite faire appel. Les variables d'environnement decrivent donc les localisations des ces programmes. Elles peuvent egalement contenir des informations influant sur le comportement des programmes.

Dans la terminologie de la bibliotheque de classes Batch, tous ces elements on ete regroupes sous le terme de Environnement.

JobId
-----

Si un job (see Job.) decrit les actions qui doivent etre effectues par le systeme sous le controle du gestionnaire de batch, il est clair qu'il est possible de soumettre plusieurs fois de suite le meme job, et par la-meme d'executer plusieurs fois (et parfois simultanement) ces memes actions. On a donc plusieurs instances du meme job qui sont presentes en machine. Chaque instance peut etre distinguee des autres par un identifiant unique qui lui est propre : c'est le jobId.

Le JobId est determine par le gestionnaire de batch au moment de la soumission.

JobInfo
-------

Des qu'un job (see Job.) est soumis donc des qu'il dispose d'un JobId (see JobId.), il est possible d'interroger le gestionnaire de batch pour etre informe de son comportement, de son evolution au sein du systeme pendant son execution.

On peut ainsi connaitre les parametres reellement consommes par rapport aux parametres alloues, ainsi que l'environnement d'execution du job.

Le JobInfo est une structure qui collecte ses informations sur l'etat du job.

Classes generiques
==================

Schematiquement, les classes composant la bibliotheque sont regroupees en trois categories. Celles appartenant au groupe Types de base ne servent que de support au fonctionnement des classes de plus haut niveau, egalement appellees Classes utilisateur. Seules ces dernieres sont vraiment interessantes pour l'utilisateur de la bibliotheque. Les exceptions sont regroupees dans une categorie qui leur est propre.

Namespace
---------

Toutes les classes de la bibliotheque sont regroupees dans un unique namespace nomme Batch afin de ne pas introduire de conflit avec d'autres classes de meme nom.

Ainsi lorsque par exemple on cite la classe BatchManager, il faudra declarer un objet Batch::BatchManager ou bien faire appel au namespace Batch en C++. En Python, les objets sont regroupes dans un module nomme libBatch_Swig.

Types de base
-------------

Les classes decrites ici sont toutes utilisees ou utilisables par les classes utilisateur de la bibliotheque, et en particulier par la classe Versatile. See Classe Versatile.

Ces classes implementent sous forme d'objet les types de base du langage C++. Ainsi la classe Booltype implemente le type de base bool. Certains types de base n'existant pas dans le langage ont ete crees et encapsules dans une classe : c'est le cas notamment du type de base Date et de la classe DateType, et du type de base Couple et de la classe CoupleType.

Tous les classes heritent de la classe generique GenericType.

Couple
......

La classe Couple implemente le comportement d'un couple de deux chaines de type string qui sont respectivement nommees local et remote.

Cette classe est utilisee essentiellement pour la designation des fichiers a transferer lors des soumissions de travaux, d'ou les noms employes.

Il faut toutefois faire attention a designer correctement ce qui est local ou distant. Ainsi dans la bibliotheque de classes Batch, on a adopte la convention qu'un fichier dit local est celui present sur la machine qui execute la bibliotheque de classes Batch, alors qu'un fichier dit remote (ou distant) est celui present sur le serveur du gestionnaire de batch. L'approche est donc clairement orientee utilisateur plutot que serveur.

  * Entete

          class Couple
          {
            public:
              // Constructeur standard
              Couple(const string & local, const string & remote);

              // Constructeur par recopie
              Couple(const Couple & C);

              // Operateur pour l'affichage sur un stream
              friend ostream & operator << (ostream & os, const Couple & cp);

              // Operateur d'affectation
              virtual Couple & operator =(const Couple &);

              // Conversion en chaine
              virtual string str() const;

              // Accesseurs
              virtual string getLocal() const;
              virtual string getRemote() const;

            protected:
              string _local;  // chemin d'acces au fichier local
              string _remote; // chemin d'acees au fichier distant

            private:

          };

Date
....

La classe Date sert a stocker n'importe quelle information de temps et peut la representer sous une forme plus lisible a l'utilisateur que le traditionnel appel a la fonction ctime. See (*manpages*)ctime.

  * Entete

          class Date
          {
            public:
              // Constructeur standard (a partir d'une valeur epoch)
              Date(const long l=0);

              // Constructeur a partir d'une chaine hh:mm:ss
              Date(const string s);

              // Operateurs portant sur les Dates
              virtual Date & operator =(long l);
              virtual Date & operator +(long l);
              virtual Date & operator -(long l);
              virtual Date & operator +=(long l);
              virtual Date & operator -=(long l);
              virtual Date & operator =(const string & s);

              // Conversions en types standards
              virtual string str() const;
              virtual long epoch() const;

            protected:
              int _day, _month, _year;
              int _hour, _min, _sec;

            private:

          };

GenericType
...........

La classe GenericType est la classe-mere de toutes les classes utilisees par la classe Versatile. See Classe Versatile.

Elle definit une interface que Versatile utilise pour controler les objets : constructeur simple et destructeur, operateur sur ostream, conversion en chaine et surtout methode clone.

La methode clone permet de recuperer un nouvel objet identique au premier qui sera automatiquement alloue sur le tas par un appel a new. Il est important de noter ici que le nouvel objet DEVRA etre desalloue par un appel a delete. Cette desallocation est a la charge de l'utilisateur de l'objet sans quoi une fuite memoire en resultera.

  * Entete

          class GenericType
          {
            public:
              // Constructeur et destructeur
              GenericType();
              virtual ~GenericType();

              // Operateur pour l'affichage sur un stream
              friend ostream & operator << (ostream & os,
                                            const GenericType & obj);

              // Conversion en chaine
              virtual string affiche() const;

              // Clone duplique l'objet et en fabrique un nouveau a l'aide de new
              // qu'il faudra detruire ensuite manuellement
              virtual GenericType * clone() const;

              // Retourne le nombre d'objets GenericType et al.
              static int getNb();

              protected:

              private:
                static int _nb; // nombre total d'objets GenericType et al.

          };

BoolType
........

Cette classe encapsule le type C++ bool dans un objet herite de GenericType de maniere a pouvoir le stocker aisement dans un objet de classe Versatile.

  * Entete

          class BoolType : public GenericType
          {
            public:
              // Constructeur
              BoolType(const bool b=false);

              // Conversion en chaine
              virtual string affiche() const;

              // Operateur d'affectation
              virtual BoolType & operator =(bool);

              // Conversion en bool
              virtual operator bool() const;

              // Clone duplique l'objet et en fabrique un nouveau a l'aide de new
              // qu'il faudra detruire ensuite manuellement
              virtual GenericType * clone() const;

            protected:
              bool _data;

            private:

          };

CharType
........

Cette classe encapsule le type C++ char dans un objet herite de GenericType de maniere a pouvoir le stocker aisement dans un objet de classe Versatile.

  * Entete

          class CharType : public GenericType
          {
            public:
              // Constructeur
              CharType(const char c=0);

              // Conversion en chaine
              virtual string affiche() const;

              // Operateur d'affectation
              virtual CharType & operator =(char);

              // Conversion en char
              virtual operator char() const;

              // Clone duplique l'objet et en fabrique un nouveau a l'aide de new
              // qu'il faudra detruire ensuite manuellement
              virtual GenericType * clone() const;

            protected:
              char _data;

            private:

          };

CoupleType
..........

Cette classe encapsule le type interne Couple dans un objet herite de GenericType de maniere a pouvoir le stocker aisement dans un objet de classe Versatile.

  * Entete

          class CoupleType : public GenericType
          {
            public:
              // Constructeur
              CoupleType(const Couple & C);

              // Conversion en chaine
              virtual string affiche() const;
              virtual operator string() const;

              // Operateur d'affectation
              virtual CoupleType & operator =(const Couple & C);

              // Conversion en char
              virtual operator Couple() const;

              // Clone duplique l'objet et en fabrique un nouveau a l'aide de new
              // qu'il faudra detruire ensuite manuellement
              virtual GenericType * clone() const;

            protected:
              Couple _data;

            private:

          };

DateType
........

Cette classe encapsule le type interne Date dans un objet herite de GenericType de maniere a pouvoir le stocker aisement dans un objet de classe Versatile.

  * Entete

          class DateType : public GenericType
          {
            public:
              // Constructeur
              DateType(const Date & d);

              // Conversion en chaine
              virtual string affiche() const;

              // Operateur d'affectation
              virtual DateType & operator =(const Date &);

              // Conversion en Date
              virtual operator Date() const;

              // Conversion en long
              virtual operator long() const;

              // Clone duplique l'objet et en fabrique un nouveau a l'aide de new
              // qu'il faudra detruire ensuite manuellement
              virtual GenericType * clone() const;

            protected:
              Date _data;

            private:
          };

IntType
.......

Cette classe encapsule le type C++ int dans un objet herite de GenericType de maniere a pouvoir le stocker aisement dans un objet de classe Versatile.

  * Entete

          class IntType : public GenericType
          {
            public:
              // Constructeur
              IntType(const int i=0);

              // Conversion en chaine
              virtual string affiche() const;

              // Operateur d'affectation
              virtual IntType & operator =(int);

              // Conversion en int
              virtual operator int() const;

              // Clone duplique l'objet et en fabrique un nouveau a l'aide de new
              // qu'il faudra detruire ensuite manuellement
              virtual GenericType * clone() const;

            protected:
              int _data;

            private:

          };

LongType
........

Cette classe encapsule le type C++ long dans un objet herite de GenericType de maniere a pouvoir le stocker aisement dans un objet de classe Versatile.

  * Entete

          class LongType : public GenericType
          {
            public:
              // Constructeur
              LongType(const long l=0L);

              // Conversion en chaine
              virtual string affiche() const;

              // Operateur d'affectation
              virtual LongType & operator =(long);

              // Conversion en long
              virtual operator long() const;

              // Clone duplique l'objet et en fabrique un nouveau a l'aide de new
              // qu'il faudra detruire ensuite manuellement
              virtual GenericType * clone() const;

            protected:
              long _data;

            private:

          };

StringType
..........

Cette classe encapsule le type C++ string de la STL dans un objet herite de GenericType de maniere a pouvoir le stocker aisement dans un objet de classe Versatile.

  * Entete

          class StringType : public GenericType
          {
            public:
              // Constructeur
              StringType(const string & s="");

              // Conversion en chaine
              virtual string affiche() const;
              virtual operator string() const;

              // Operateur d'affectation
              virtual StringType & operator =(string);

              // Clone duplique l'objet et en fabrique un nouveau a l'aide de new
              // qu'il faudra detruire ensuite manuellement
              virtual GenericType * clone() const;

            protected:
              string _data;

            private:

          };

Classes utilisateur
-------------------

Les classes dites classes utilisateur sont en realite les classes de plus haut niveau de la biliotheque de classes Batch. Ces classes remplissent les unes avec les autres l'ensemble des fonctionnalites proposees par la bibliotheque. L'utilisateur trouvera donc dans cette section la description des possibilites de la bibliotheque et le moyen de les mettre en oeuvre.

La premiere section montre un exemple complet de soumission et de controle d'un job soumis a travers les classes de la biliotheque. Les sections suivantes reprennent les elements de l'exemple pour le detailler et le completer.

Exemple
.......

Cet exemple decrit le processus type de creation et de soumission d'un job a travers les classes de la bibliotheque.

Il faut toutefois penser que les appels aux methodes peuvent lever des exceptions qu'il faudra intercepter et gerer. See Exceptions.

       ...

       // On recupere l'instance du catalogue de gestionnaires de batch
       Batch::BatchManagerCatalog cata = Batch::BatchManagerCatalog::getInstance();

       // On cree un BatchManager qui se connecte au veritable gestionnaire
       // de batch
       Batch::BatchManager & bm = (* cata("PBS"))("monserver.mondomaine.fr");

       // Pour fabriquer un Job, on doit d'abord creer un objet Parametre et
       // un objet Environnement qui contiennent respectivement la liste des
       // parametres du job au sein du gestionnaire de batch et la liste des
       // variables d'environnement necessaires au fonctionnement du job
       Batch::Parametre param;

       param[EXECUTABLE]  = "/home/user/mon_application/executable";
       param[NAME]        = "MonJob";
       param[ACCOUNT]     = "MonProjet"; // code d'imputation/facturation
       param[MAXCPUTIME]  = 360L;        // 6min
       param[MAXWALLTIME] = 480L;        // 8min
       param[INFILE]      = Batch::Couple("/tmp/infich1",  rempath+"/infich1");
       param[OUTFILE]     = Batch::Couple("/tmp/outfich1", rempath+"/outfich1");
       param[OUTFILE]    += Batch::Couple("stderr", path + "/STDERR");
       param[OUTFILE]    += Batch::Couple("stdout", path + "/STDOUT");
       param[MAIL]        = "user@domaine.fr";
       param[USER]        = "user";

       Batch::Environnement env;
       env["DEBUG"]       = "3"; // un niveau de debug exige par l'application
       env["MYAPP_FILE"]  = "/home/user/mon_application/data/mydatafile";

       // Creation du job
       Batch::Job job(param, env);

       // On soumet le Job au BatchManager qui le relaie jusqu'au veritable
       // gestionnaire de batch sur le serveur. En retour on obtient un
       // identifiant unique de notre job (JobId).
       const Batch::JobId jobid = bm.submitJob(job);

       // On interroge le BatchManager pour connaitre l'etat du Job
       const Batch::JobInfo jinfo = jobid.queryJob();
       cout << jinfo << endl;

       // On detruit l'objet BatchManager
       delete &bm;

       ...

BatchManagerCatalog
...................

La classe BatchManagerCatalog definit une interface d'acces au catalogue de fabriques de BatchManager. See Classe FactBatchManager.

Pourquoi utiliser une fabrique et ne pas instancier directement un objet BatchManager en fonction de sa classe ? C'est l'option qui avait ete choisie dans la premiere version de la bibliotheque de classes Batch. Cette facon de proceder est simple, aussi bien pour le developpeur de la classe que pour l'utilisateur, mais elle se revele a terme penalisante dans la souplesse d'utilisation des classes. Elle permet aussi moins facilement de mettre en place une strategie de singleton pour les objets BatchManager, ce qui peut se reveler utile non pas en termes de performance mais plutot en termes de genericite et toujours de souplesse.

En resume, l'utilisation de fabiques permet d'acceder a la genericite, qui rappelons-le est l'objet de cette biliotheque, a la souplesse et a la performance au prix d'une legere complication pour le developpeur mais pas pour l'utilisateur.

Le catalogue de fabriques est une map, ou tableau associatif, auquel on passe le nom d'une fabrique et qui retourne un pointeur sur une instance de cette fabrique.

Le catalogue est renseigne statiquement par les fabriques declarees elles-memes statiquement dans la biliotheque. Il est donc precharge avec les fabriques correspondant a chacune des API disponibles. Comme le catalogue n'est pas declare constant, il est possible de rajouter ou de supprimer des fabriques dans le catalogue dynamiquement.

  * Entete

          class BatchManagerCatalog
          {
          public:
            // Methode permettant de recuperer l'instance unique de catalogue
            static BatchManagerCatalog& getInstance();

            // Accesseurs
            void addFactBatchManager(const char * type, Batch::FactBatchManager * pFBM);
            Batch::FactBatchManager * operator() (const char * type);

            // Wrapping Python
            virtual std::map<std::string, FactBatchManager *> * dict();
            virtual std::string __repr__() const;

          protected:
            // Constructeur
            BatchManagerCatalog();
            // Destructeur
            virtual ~BatchManagerCatalog();

            // Le catalogue proprement dit
            std::map<std::string, FactBatchManager *> _catalog;
            // Mutex permettant d'assurer des acces "thread-safe" au catalogue
            pthread_mutex_t _mutex;

          private:
            // On interdit la copie de l'instance unique du catalogue (singleton)
            BatchManagerCatalog(const BatchManagerCatalog & orig);
            BatchManagerCatalog& operator=(const BatchManagerCatalog & orig);

          };

  * Exemple

          ...

          // On recupere l'instance du catalogue de gestionnaires de batch
          Batch::BatchManagerCatalog cata = Batch::BatchManagerCatalog::getInstance();

          ...

  * Methodes

       - static BatchManagerCatalog& getInstance()

          Cette methode retourne l'instance unique du catalogue qui peut ensuite etre utilisee pour ajouter ou recuperer des fabriques.

       - void addFactBatchManager(const char * type, FactBatchManager * pFBM)

          Cet accesseur enregistre dans le catalogue un pointeur sur un objet de type FactBatchManager sous le nom (le type) passe en argument.

       - FactBatchManager * operator() (const char * type)

          Cet accesseur retourne un pointeur sur un objet de type FactBatchManager en fonction du nom (le type) sous lequel il s'est enregistre dans le catalogue.

       - map<string, FactBatchManager *> * dict()

          Cette methode utilisable depuis Python permet de recuperer un dictionnaire decrivant le contenu du catalogue.

       - string __repr__() const

          Cette methode utilisable depuis Python retourne une description de l'objet BatchManagerCatalog.

       - BatchManagerCatalog()

          Le constructeur par defaut est declare "protected" et ne peut donc pas etre utilise pour creer une nouvelle instance de BatchManagerCatalog. En effet, le catalogue est un singleton, ce qui signifie qu'une seule instance du catalogue existe. Pour recuperer cette instance, il faut utiliser la methode BatchManagerCatalog::getInstance().

       - ~BatchManagerCatalog()

          De la meme maniere, le destructeur est declare "protected" et ne peut pas etre utilise pour detruire l'instance de catalogue. Le singleton est detruit automatiquement a la fin du programme.

FactBatchManager
................

La classe FactBatchManager est abstraite. Elle definit une interface qui doit etre implementee par des classes specialisees en fonction du gestionnaire de batch et de son API de communication. See Classes specifiques.

Les objets repondant a l'interface de FactBatchManager sont automatiquement inseres dans le catalogue des fabriques de BatchManager a la construction de l'objet. Il est ainsi possible de definir statiquement des objets de ce type qui enrichiront le catalogue des la compilation. See Classe BatchManagerCatalog. See Classe BatchManager.

Les objets de la classe FactBatchManager ou de ses derivees sont des functors et renvoient au moment de l'appel un pointeur sur un objet gestionnaire de batch BatchManager associe a un serveur. L'allocation de l'objet est faite sur le tas et celui-ci doit donc etre desalloue manuellement par l'utilisateur de la bibliotheque au moment opportun.

  * Entete

          class FactBatchManager
          {
          public:
            // Constructeur
            FactBatchManager(const string & type);

            // Destructeur
            virtual ~FactBatchManager();

            // Functor
            virtual BatchManager * operator() (const char * hostname) const = 0;

            // Accesseur au type interne
            string getType() const;

            // Wrapping Python
            string __repr__() const;

          protected:
            string type; // Le type interne

          private:

          };

  * Exemple

          ...

          // On recupere l'instance du catalogue de gestionnaires de batch
          Batch::BatchManagerCatalog cata = Batch::BatchManagerCatalog::getInstance();

          // On cree une fabrique de BatchManager de type PBS
          Batch::FactBatchManager & fbm = * cata("PBS");

          ...

  * Methodes

       - FactBatchManager(const string & type)

          Le constructeur de la classe prend un type qui doit identifer de maniere unique la fabrique au sein du catalogue de fabrique. Ce type sert de cle au catalogue. See Classe BatchManagerCatalog.

       - ~FactBatchManager()

          Le destructeur de la classe n'a pas d'action particuliere.

       - BatchManager * operator() (const char * hostname) const

          Cette methode est virtuelle pure. Elle doit etre surchargee dans les classes derivees et doit retourner un pointeur sur un objet de type BatchManager correpondant au type de la classe et oeuvrant sur la machine passee en argument. Le hostname est soit alphabetique soit numerique et doit etre soit un nom de machine valide soit une adresse IP valide. Aucun controle n'est a priori realise et cet argument est passe tel quel a l'API du gestionnaire de batch.

          Cet objet agit comme parent vis-a-vis de l'objet BatchManager qu'il retourne.

       - string getType() const

          Cette methode renvoie le type interne de l'objet, c'est-a-dire la cle sous lequel il est enregistre dans le catalogue.

       - string __repr__() const

          Cette methode utilisable depuis Python retourne une description de l'objet FactBatchManager.

BatchManager
............

La classe BatchManager est abstraite. Elle definit une interface qui doit etre implementee par des classes specialisees en fonction du gestionnaire de batch et de son API de communication. See Classes specifiques.

Toute action a destination du gestionnaire de batch doit etre precedee de l'instanciation d'un objet derivant de la classe BatchManager puisque c'est a travers cet objet que l'on aura acces a l'interface du gestionnaire.

Cette instanciation est realisee par une fabrique de gestionnaire de batch, instance elle-meme derivee de la classe abstraite FactBatchManager. See Classe FactBatchManager.

  * Entete

          class BatchManager
          {
            public:
              // Constructeur et destructeur
              BatchManager(const FactBatchManager * parent,
                           const char * host="localhost")
                throw(InvalidArgumentException);
              virtual ~BatchManager();

              // Recupere l'identifiant d'un job deja soumis au BatchManager
              virtual const JobId getJobIdByReference(const string & ref);

              // Methodes pour le controle des jobs : virtuelles pures
              // soumet un job au gestionnaire
              virtual const JobId submitJob(const Job & job) = 0;

              // retire un job du gestionnaire
              virtual void deleteJob(const JobId & jobid) = 0;

              // suspend un job en file d'attente
              virtual void holdJob(const JobId & jobid) = 0;

              // relache un job suspendu
              virtual void releaseJob(const JobId & jobid) = 0;

              // modifie un job en file d'attente
              virtual void alterJob(const JobId & jobid,
                                    const Parametre & param,
                                    const Environnement & env) = 0;
              virtual void alterJob(const JobId & jobid,
                                    const Parametre & param) = 0;
              virtual void alterJob(const JobId & jobid,
                                    const Environnement & env) = 0;

              // renvoie l'etat du job
              virtual JobInfo queryJob(const JobId & jobid) = 0;

              // wrapping Python
              virtual string __repr__() const;

            protected:
              string _hostname; // serveur ou tourne le BatchManager
              const FactBatchManager * _parent; // fabrique qui a produit l'instance

            private:

          };

  * Exemple

          ...

          // On recupere l'instance du catalogue de gestionnaires de batch
          Batch::BatchManagerCatalog cata = Batch::BatchManagerCatalog::getInstance();

          // On cree un BatchManager qui se connecte au veritable gestionnaire
          // de batch
          Batch::BatchManager & bm = (* cata("PBS"))("monserver.mondomaine.fr");

          // Maintenant, on peut utiliser toutes les fonctionnalites du
          // gestionnaire de batch a travers le variable myBM

          // On detruit l'objet BatchManager
          delete &bm;

          ...

  * Methodes

       - BatchManager(const FactBatchManager * parent,$* const char * host="localhost") throw(InvalidArgumentException)

          Excepte un pointeur sur la fabrique qui a produit l'objet, see Classe FactBatchManager, le constructeur accepte zero ou un argument de type string decrivant soit le nom de domaine completement qualifie (FQDN, fully qualified domain name) du serveur de batch, soit son adresse IP dans un format decimal "aaa.bbb.ccc.ddd".

          Une resolution du nom ou de l'adresse peut etre realisee en fonction des capacites de la plate-forme pour s'assurer que le serveur est connu et joignable. En cas d'echec, une exception InvalidArgumentException est levee. See Classe InvalidArgumentException. A priori, aucune verification n'est faite par defaut.

          Ceci fait, une connexion est etablie avec le gestionnaire de batch qui est maintenue jusqu'a destruction de l'objet, si le gestionnaire le permet.

       - ~BatchManager()

          Le destructeur supprime la connexion precedemment etablie par le constructeur lorsque celle-ci a reussi.

       - const JobId submitJob(const Job & job)

          Cette methode soumet le job passe en argument au gestionnaire de batch. Etant donne que le job ne peut pas etre envoye tel quel puisqu'il a un format generique au sein de la bibliotheque de classes Batch, cette methode est chargee de le convertir dans un format adapte au gestionnaire de batch sous-jacent.

          Ce n'est que lorsque cette conversion est realisee que le job est soumis au gestionnaire a travers son API. L'identifiant propose par le gestionnaire est alors renvoye a l'appelant. Si la soumission echoue pour une raison ou une autre, une exception APIInternalFailureException est levee. See Classe APIInternalFailureException.

       - void deleteJob(const JobId & jobid)

          Cette methode retire le job dont l'identifiant est passe en argument de la file d'attente du gestionnaire, ou bien l'arrete s'il est en cours d'execution. Cette methode est inoperante sur des travaux deja termines, auquel cas une exception APIInternalFailureException est levee. See Classe APIInternalFailureException.

       - void holdJob(const JobId & jobid)

          Cette methode suspend le job dont l'identifiant est passe en argument au sein de la file d'attente du gestionnaire. Cette methode est inoperante sur des travaux en cours d'execution ou deja termines, ainsi que sur des travaux deja suspendus. En cas de probleme, une exception APIInternalFailureException est levee. See Classe APIInternalFailureException.

       - void releaseJob(const JobId & jobid)

          Cette methode relache un job precedemment suspendu en file d'attente dont l'identifiant est passe en argument. Elle est inoperante sur des travaux deja relaches, en cours d'execution ou termines. En cas de probleme, une exception APIInternalFailureException est levee. See Classe APIInternalFailureException.

       - void alterJob(const JobId & jobid, const Parametre & param, const Environnement & env)

          void alterJob(const JobId & jobid, const Parametre & param)

          void alterJob(const JobId & jobid, const Environnement & env)

          Ces methodes permettent de modifier les parametres d'execution et d'environnement d'un job dont l'identifiant est passe en argument. See Classe Parametre. See Classe Environnement. Il est important de noter que le job doit etre encore place en file d'attente sinon la methode est inoperante. En cas de probleme, une exception APIInternalFailureException est levee. See Classe APIInternalFailureException.

       - JobInfo queryJob(const JobId & jobid)

          Cette methode permet de recuperer les informations concernant le job dont l'identifiant est passe en argument dans un objet de classe JobInfo. See Classe JobInfo. On y retrouve les parametres d'execution et d'environnement du job tels qu'ils ont ete passes au gestionnaire au moment de la soumission, ainsi que des informations concernant l'execution du job comme par exemple la machine d'execution, le temps consomme, la memoire consommee, etc.

          Il n'est pas toujours possible d'interroger un job deja termine. En cas de probleme, une exception APIInternalFailureException est levee. See Classe APIInternalFailureException.

       - const JobId getJobIdByReference(const string & ref)

          Cette methode permet de recuperer au sein de la classe un identifiant de job a partir d'une chaine de caracteres obtenue par un biais externe. Cet identifiant pourra etre utilise par la suite au sein de la biliotheque de classes pour controler le job comme s'il avait ete cree et soumis depuis la biliotheque-meme.

Environnement
.............

La classe Environnement permet de definir les variables d'environnement necessaires a l'execution d'un job. Ces variables seront creees automatiquement dans l'environnement du job lorsque celui-ci debutera son execution sur la machine.

Une variable d'environnement est traditionnellement composee d'un nom et d'une valeur qui peut etre vide ou absente. L'ensemble des variables d'environnement peut ainsi etre represente sous la forme d'une table associative dans laquelle le nom de la variable correspond a la clef de la table, et la valeur de la variable correspond a la valeur de la table pour la clef donnee.

Chaque objet de la classe Environnement se comporte comme une table associative telle que decrite auparavant.

  * Entete

          typedef map < string, string > Environnement;

  * Exemple

          ...

          Environnement env;
          env["MYAPP_ROOTDIR"]     = "/home/user/myapplication";
          env["MYAPP_LICENSEFILE"] = env["MYAPP_ROOTDIR"] + "/license.dat";
          env["CXX"]               = "g++";
          env["CXXFLAGS"]          = "-g -O2";

          ...

  * Methodes

     Compte tenu de la definition actuelle de la classe Environnement en tant que map STL, elle beneficie de toutes les fonctionnalites classiques des maps STL.

Job
...

La classe Job represente la notion de travail, ou job, dans la bibliotheque de classes Batch. Elle se comporte essentiellement comme une collection de parametres et de variables necessaires a la description des actions qui doivent etre realisees dans des conditions precisees.

Elle se repose sur deux autres classes qui distinguent la notion de parametre d'execution et celle de variable d'environnement : les classes Parametre et Environnement. See Classe Parametre. See Classe Environnement.

Son role est de preparer la soumission qui aura lieu et qui concretisera l'incarnation du job dans le gestionnaire de batch. Tant que le job n'a pas ete soumis, on ne peut pas vraiment considerer son existence et de fait les interactions qu'on peut avoir avec l'objet sont tres limitees.

  * Entete

          class Job
          {
            public:
              // Constructeurs et destructeur
              Job();
              Job(Parametre param);
              Job(Environnement env);
              Job(Parametre param, Environnement env);
              virtual ~Job();

              // Operateur pour l'affichage sur un stream
              friend ostream & operator <<(ostream & os, const Job & job);

              // Accesseurs
              Parametre getParametre() const;
              void setParametre(const Parametre &);

              // Accesseurs
              Environnement getEnvironnement() const;
              void setEnvironnement(const Environnement &);

              // Methodes pour l'interfacage avec Python (SWIG)
              string  __repr__() const;

            protected:
              Parametre _param;   // table des parametres batch du job
              Environnement _env; // table des variables d'environnement

            private:

          };

  * Exemple

          ...

          ... (ici on cree un BatchManager bm)
          Parametre param;
          Environnement env;

          ... (ici on cree les parametres du job)

          Job job(param, env);
          JobId jobid = bm.sumbitJob(job);

          ...

  * Methodes

       - Job()$* Job(Parametre param)$* Job(Environnement env)$* Job(Parametre param, Environnement env)

          Le constructeur, en plus de creer l'objet, peut faire des verifications sur la coherence des objets passes en argument s'il y en a.

       - ~Job()

          Le destructeur libere simplement les espaces alloues.

       - ostream & operator <<(ostream & os, const Job & job)

          Cette methode permet a l'utilisateur d'afficher sur un stream le contenu d'un objet de classe Job.

       - Parametre getParametre() const

          Un accesseur pour recuperer l'objet Parametre passe en argument du constructeur.

       - void setParametre(const Parametre &)

          Cette methode permet de positionner a posteriori l'objet Parametre. Des tests complementaires peuvent etre faits pour verifier la coherence de l'objet.

       - Environnement getEnvironnement() const

          Un accesseur pour recuperer l'objet Environnement passe en argument du constructeur.

       - void setEnvironnement(const Environnement &)

          Cette methode permet de positionner a posteriori l'objet Environnement. Des tests complementaires peuvent etre faits pour verifier la coherence de l'objet.

       - string  __repr__() const

          Cette methode sert dans l'interfacage Python de l'objet et permet d'en realiser l'affichage a travers l'interpreteur Python.

JobId
.....

La classe JobId represente l'incarnation d'un objet de classe Job une fois soumis au travers du gestionnaire de batch. A chaque objet JobId correspond une et une seule soumission d'un objet Job. Ainsi un meme objet Job peut etre soumis plusieurs fois de suite a un ou plusieurs gestionnaires de batch et produira autant d'objets JobId.

L'objet JobId assure le controle et la gestion du job au travers du gestionnaire de batch. Chaque objet JobId est associe a un gestionnaire particulier aupres duquel il relaie les actions qu'on lui soumet.

  * Entete

          class JobId
          {
              friend class BatchManager;

            public:
              // Constructeur standard et destructeur
              JobId();
              virtual ~JobId();

              // Constructeur avec le pointeur sur le BatchManager associe
              // et avec une reference
              JobId(BatchManager *, string ref);

              // Operateur d'affectation entre objets
              virtual JobId & operator =(const JobId &);

              // Constructeur par recopie
              JobId(const JobId &);

              // Accesseur pour la reference interne
              virtual string getReference() const;

              // Methodes pour le controle du job
              // retire un job du gestionnaire
              virtual void deleteJob() const;

              // suspend un job en file d'attente
              virtual void holdJob() const;

              // relache un job suspendu
              virtual void releaseJob() const;

              // modifie un job en file d'attente
              virtual void alterJob(const Parametre & param,
                                    const Environnement & env) const;
              virtual void alterJob(const Parametre & param) const;
              virtual void alterJob(const Environnement & env) const;

              // modifie un job en file d'attente
              virtual void setParametre(const Parametre & param);
              virtual void setEnvironnement(const Environnement & env);

              // renvoie l'etat du job
              virtual Batch::JobInfo queryJob() const;

              // Methodes pour l'interfacage avec Python (SWIG)
              string  __str__() const;  // SWIG : affichage en Python
              string  __repr__() const; // SWIG : affichage en Python

            protected:
              BatchManager * _p_batchmanager; // pointeur sur le BatchManager
                                              // qui controle le job
              string _reference; // reference du job au sein du BatchManager

            private:

          };

  * Exemple

          ... (ici on cree un BatchManager bm et un Job job)

          // On soumet le job et on recupere un identifiant
          JobId   jobid = bm.submitJob(job);

          // Ce qui permet d'interroger l'etat du job en cours
          JobInfo jinfo = jobid.queryJob();

          ...

  * Methodes

       - JobId()

          JobId(BatchManager *, string ref)

          Le constructeur par defaut cree un JobId qui devra etre complete par la suite. Ceci n'est pas directement realisable par l'utilisateur mais sert pour certaines classes amies de la classe JobId.

          D'un point de vue utilisateur la construction d'un objet JobId necessite un pointeur sur un gestionnaire de batch existant et une chaine de caractere representant une reference au sein de ce gestionnaire de batch.

          Ces parametres sont en general issus de la communication avec l'API du gestionnaire de batch et ne peuvent etre aisement deduits. C'est pourquoi il est recommande de passer par une classe d'implementation pour fabriquer un objet JobId.

       - ~JobId()

          Le destructeur libere l'espace occupe par l'objet.

       - JobId & operator =(const JobId &)

          L'affectation d'un objet JobId duplique les donnees internes de l'objet passe en argument. Les deux objets sont totalement independants a l'issue de l'affectation et designent chacun la meme instance du job dans le meme gestionnaire de batch. Le controle du job peut etre realise avec l'un ou l'autre des objets.

       - JobId(const JobId &)

          De meme que l'affectation le constructeur par recopie produit un objet JobId totalement independant de l'objet passe en argument et qui designe le meme job dans le meme gestionnaire de batch. Le controle du job peut etre realise avec l'un ou l'autre des objets.

       - string getReference() const

          Cet accesseur retourne la reference du job pour le gestionnaire de batch qui a produit l'objet.

       - void deleteJob() const

          Cette methode relaie aupres au gestionnaire de batch qui a produit l'objet la demande d'arret du job.

       - void holdJob() const

          Cette methode relaie aupres au gestionnaire de batch qui a produit l'objet la demande de suspension du job.

       - void releaseJob() const

          Cette methode relaie aupres au gestionnaire de batch qui a produit l'objet la demande de liberation du job.

       - void alterJob(const Parametre & param, const Environnement & env) const

          void alterJob(const Parametre & param) const

          void alterJob(const Environnement & env) const

          Ces methodes relaient aupres du gestionnaire de batch qui a produit l'objet la demande de modification des parametres et/ou des variables d'environnement du job.

       - void setParametre(const Parametre & param)

          Cette methode n'est utile que pour l'interfacage avec Python, car Python ne sait pas gerer la surcharge de methode, et de fait leve des exceptions lors d'appels a de telles methodes.

          Elle est equivalente a la methode void alterJob(const Parametre & param) const.

       - void setEnvironnement(const Environnement & env)

          Cette methode n'est utile que pour l'interfacage avec Python, car Python ne sait pas gerer la surcharge de methode, et de fait leve des exceptions lors d'appels a de telles methodes.

          Elle est equivalente a la methode void alterJob(const Environnement & env) const.

       - Batch::JobInfo queryJob() const

          Cette methode relaie aupres du gestionnaire de batch qui a produit l'objet la demande d'interrogation de l'etat du job.

       - string  __str__() const

          Cette methode n'est utile que pour l'interfacage avec Python. Elle permet d'afficher l'etat de l'objet JobId.

       - string  __repr__() const

          Cette methode n'est utile que pour l'interfacage avec Python. Elle permet d'afficher l'etat de l'objet JobId.

JobInfo
.......

Un objet de classe JobInfo represente l'ensemble des informations disponibles sur un travail actif, c'est-a-dire soumis au gestionnaire de batch, a un instant donne.

Cet objet reprend des informations issues du job tel qu'il a ete soumis, see Classe Job, mais aussi des informations produites par le gestionnaire de batch a partir de la soumission et du transit du job en son sein : nom de la queue dans laquelle le job est inscrit, duree d'execution, date de soumission, etc.

Ces informations sont disponibles aupres de l'utilisateur de la classe a travers les objets Parametre et Environnement que l'objet JobInfo peut fournir.

  * Entete

          class JobInfo
          {
            public:
              // Constructeur standard et destructeur
              JobInfo();
              virtual ~JobInfo();

              // Constructeur par recopie
              JobInfo(const JobInfo & jinfo);

              // Operateur pour l'affichage sur un stream
              friend ostream & operator <<(ostream & os, const JobInfo & ji);

              // Accesseurs
              virtual Parametre getParametre() const;
              virtual Environnement getEnvironnement() const;

              // Methodes pour l'interfacage avec Python (SWIG)
              string  __str__() const;  // SWIG : affichage en Python
              string  __repr__() const; // SWIG : affichage en Python

            protected:
              Parametre _param; // parametres du job
              Environnement _env; // variables d'environnement du job

            private:
          };

  * Exemple

          ... (ici on cree un BatchManager bm et un Job job)

          // On soumet le job et on recupere un identifiant
          JobId   jobid = bm.submitJob(job);

          // Ce qui permet d'interroger l'etat du job en cours
          JobInfo jinfo = jobid.queryJob();

          // On recupere l'objet Parametre interne modifie
          // par le gestionnaire de batch
          Parametre param = jinfo.getParametre();

          // On recupere l'objet Environnement interne modifie
          // par le gestionnaire de batch
          Environnement env = jinfo.getEnvironnement();

          ...

  * Methodes

       - JobInfo()

          Ce constructeur cree un objet JobInfo vide.

       - ~JobInfo()

          Le destructeur libere l'espace memoire alloue par l'objet.

       - JobInfo(const JobInfo & jinfo)

          Le constructeur par recopie produit un objet identique a celui passe en argument. Les deux objets sont totalement independants l'un de l'autre.

       - ostream & operator <<(ostream & os, const JobInfo & ji)

          Cet operateur permet de voir le contenu de l'objet sur un flot de sortie.

       - Parametre getParametre() const

          Cet accesseur retourne l'objet interne Parametre modifie par le gestionnaire de batch. En particulier on y retrouve toutes les clefs et les valeurs correspondant aux informations produites dynamiquement par le gestionnaire (duree d'execution, machine d'execution, etc.). Il n'est pas garanti que les valeurs passees au moment de la soumission soient inchangees car des modifications ont pu etre apportees a ces valeurs pendant le traitement du job par le gestionnaire.

       - Environnement getEnvironnement() const

          Cet accesseur retourne l'objet interne Environnement modifie par le gestionnaire de batch. En particulier on y retrouve toutes les clefs et les valeurs correspondant aux informations produites dynamiquement par le gestionnaire (chemin d'acces, variables d'environnement specifiques a la machine d'execution, etc.). Il n'est pas garanti que les valeurs passees au moment de la soumission soient inchangees car des modifications ont pu etre apportees a ces valeurs pendant le traitement du job par le gestionnaire.

       - string  __str__() const

          Cette methode n'est utile que pour l'interfacage avec Python. Elle permet d'afficher l'etat de l'objet JobInfo.

       - string  __repr__() const

          Cette methode n'est utile que pour l'interfacage avec Python. Elle permet d'afficher l'etat de l'objet JobInfo.

Parametre
.........

Les objets de la classe Parametre se comportent comme des maps STL, dont ils ont les fonctionnalites, decrivant les parametres d'execution du job.

Contrairement aux variables d'environnement qui sont decrites par les objets de la classe Environnement, les parametres d'execution servent a preciser les contraintes qui pesent sur le job, comme par exemple la duree maximale d'execution autorisee, la quantite maximale de memoire utilisable ou la queue de soumission, ou bien a renseigner le job avec des informations specifiques a l'utilisateur, comme son username, son adresse email, le code d'imputation du job, etc.

En raison du caractere tres specifique et precis des informations qui doivent etre fournies au gestionnaire de batch, une nomenclature est proposee par la classe Parametre qu'il est vivement conseille de suivre. De plus tout a ete fait pour rendre cette ecriture naturelle et facile, donc il ne devrait pas y avoir de probleme pour l'utiliser.

Ainsi, a titre d'exemple, pour preciser le temps maximal autorise pour un job, il faut creer une clef de nom MAXCPUTIME dans un objet de classe Parametre qui sera ensuite passe au job. Et pour preciser le code d'imputation du job, il faut creer une clef de nom ACCOUNT.

Mais cet exemple simple montre que la valeur associee a la clef MAXCPUTIME est semantiquement une duree, et que la valeur associee a la clef ACCOUNT est semantiquement un nom. On a donc un probleme de type puisque dans la definition d'une map STL le type de la valeur doit etre le meme, et ce meme si les valeurs doivent par la suite avoir des types semantiques differents. C'est pourquoi on a definit une classe Versatile qui encapsule des types differents. See Classe Versatile.

Quoiqu'il en soit toute la mecanique est cachee et seul importe pour l'utilisateur de savoir que les valeurs associees aux clefs sont typees et que ces types sont definis dans l'enumeration DiscriminatorType. See Classe Versatile.

  * Entete

          class Parametre : public map< string, Versatile >
          {
            public:
              // Constructeur standard
              Parametre();

              // Constructeur par recopie
              Parametre(const Parametre & PM);

              // Operateur de recherche dans la map
              Versatile & operator [] (const string &);
              const Versatile & operator [] (const string &) const;

              // Operateur d'affectation
              Parametre & operator =(const Parametre & PM);

              // Declarations statique des clefs de la map
              static const string ACCOUNT;
              static const string CHECKPOINT;
              static const string CKPTINTERVAL;
              static const string CREATIONTIME;
              static const string EGROUP;
              static const string ELIGIBLETIME;
              static const string EUSER;
              static const string EXECUTABLE;
              static const string EXECUTIONHOST;
              static const string HOLD;
              static const string ID;
              static const string INFILE;
              static const string MAIL;
              static const string MAXCPUTIME;
              static const string MAXDISKSIZE;
              static const string MAXRAMSIZE;
              static const string MAXWALLTIME;
              static const string MODIFICATIONTIME;
              static const string NAME;
              static const string OUTFILE;
              static const string PID;
              static const string QUEUE;
              static const string QUEUEDTIME;
              static const string SERVER;
              static const string STARTDATE;
              static const string STATE;
              static const string TEXT;
              static const string TMPDIR;
              static const string USEDCPUTIME;
              static const string USEDDISKSIZE;
              static const string USEDRAMSIZE;
              static const string USEDWALLTIME;
              static const string USER;

            protected:
              // map interne servant a controler le type
              // de la valeur associee a chaque clef
              map< string, TypeParam > TypeMap;

            private:

          };

  * Exemple

          ...

          Parametre param;

          param[EXECUTABLE]  = "/home/user/mon_application/executable";
          param[NAME]        = "MonJob";
          param[ACCOUNT]     = "MonProjet"; // code d'imputation/facturation
          param[MAXCPUTIME]  = 360L;        // 6min
          param[MAXWALLTIME] = 480L;        // 8min
          param[INFILE]      = Couple("/tmp/infich1",  rempath + "/infich1");
          param[OUTFILE]     = Couple("/tmp/outfich1", rempath + "/outfich1");
          param[OUTFILE]    += Couple("stderr", path + "/STDERR");
          param[OUTFILE]    += Couple("stdout", path + "/STDOUT");
          param[MAIL]        = "user@domaine.fr";
          param[USER]        = "user";

          ...

  * Methodes

       - Parametre()

          Le constructeur par defaut initialise l'objet Parametre et cree la table des types internes. Par contre l'objet ne contient aucune valeur.

       - Parametre(const Parametre & PM)

          Le constructeur par recopie cree un objet Parametre a l'image de celui qui lui est passe en argument. La table des types internes est dupliquee ainsi que tous les objets correspondant a chacune des clefs.

       - Versatile & operator [] (const string &)

          Cet operateur permet de recuperer la valeur designee par la clef passee en argument. Cette valeur est de classe Versatile qui encapsule tous les types de base utilisables dans la bibliotheque en tant que parametre. See Classe Versatile.

       - const Versatile & operator [] (const string &) const

          A l'image de l'operateur precedent, cet operateur permet de recuperer la valeur designee par la clef passee en argument mais uniquement pour des objets constants.

       - Parametre & operator =(const Parametre & PM)

          L'operateur d'affectation remplace l'ensemble du contenu de l'objet Parametre par le contenu de l'objet passe en argument. Les valeurs sont dupliquees par rapport a l'objet PM.

  * Description des clefs

     Selon les gestionnaires de batch utilises, certaines clefs sont actives ou inactives. Une definition superflue ne pose pas de probleme et se trouve ignoree au moment de la soumission. Par contre l'absence d'un clef peut empecher la soumission d'aboutir et lever une exception.

       - ACCOUNT : type STRING

          Le code de facturation sur lequel le job doit s'imputer.

       - CHECKPOINT : type LONG

          Une valeur non nulle indique au gestionnaire de batch que le job est checkpointable, c'est-a-dire interruptible pour une reprise ulterieure.

       - CKPTINTERVAL : type LONG

          En liaison avec la clef CHECKPOINT, la clef CKPTINTERVAL indique l'intervalle en secondes entre deux interruptions du code (checkpoint).

       - CREATIONTIME : type LONG

          La date a laquelle le job a ete cree (soumis) dans le gestionnaire de batch.

       - EGROUP : type STRING

          Le groupe effectif au sens Unix du terme dans lequel le job s'execute.

       - ELIGIBLETIME : type LONG

          La date a laquelle le job a pu disposer des ressources necessaires a son execution.

       - EUSER : type STRING

          L'utilisateur effectif au sens Unix du terme pour lequel le job s'execute.

       - EXECUTABLE : type STRING

          Le chemin d'acces absolu a l'executable sur la machine qui soumet le job.

       - EXECUTIONHOST : type STRING

          Le nom de la machine qui execute le job.

       - HOLD : type LONG

          Une valeur non nulle indique au gestionnaire de batch que le job doit etre place dans l'etat suspendu. Une valeur nulle libere le job.

       - ID : type STRING

          L'identifiant unique du job pour le gestionnaire de batch.

       - INFILE : type liste de COUPLE

          La clef INFILE liste les fichiers qui seront envoyes au job avant son execution. Chaque fichier peut avoir un nom different sur la machine cliente --- qui soumet le job --- et sur le serveur. C'est pourquoi chaque fichier a envoyer est represente par un couple dont le nom LOCAL est le chemin absolu du fichier sur la machine cliente et le nom REMOTE est le chemin absolu du fichier sur le serveur. See Classe Couple.

          Si le nom REMOTE vaut stdin, alors le contenu du fichier designe par le nom LOCAL est envoye sur l'entree standard du job au moment de son execution.

       - MAIL : type STRING

          L'adresse email de l'utilisateur ou lui seront envoyes les eventuels messages d'information et d'alerte du gestionnaire de batch.

       - MAXCPUTIME : type LONG

          Le temps de calcul (CPU time) en secondes que ne devra pas depasser le job.

       - MAXDISKSIZE : type LONG

          L'espace disque en octets que ne devra pas depasser le job.

       - MAXRAMSIZE : type LONG

          La quantite de memoire vive en octets que ne devra pas depasser le job.

       - MAXWALLTIME : type LONG

          Le temps reel (elapsed time) en secondes que ne devra pas depasser le job.

       - MODIFICATIONTIME : type LONG

          La date a laquelle le job a ete modifie pour la derniere fois dans le gestionnaire de batch. Cette date correspond le plus souvent a la derniere operation realisee par le gestionnaire dans la gestion du job : routage au sein des files, suspension ou reprise, etc.

       - NAME : type STRING

          Le nom du job tel qu'il apparait a l'utilisateur dans son dialogue avec le gestionnaire de batch. Ce nom n'a pas besoin d'etre unique et ne remplace pas l'identifiant (ID). Il n'est la que pour informer l'utilisateur de la nature de son job.

       - OUTFILE : type liste de COUPLE

          La clef OUTFILE liste les fichiers qui sont produits par le job et qui seront recuperes sur la machine locale de l'utilisateur apres son execution. Chaque fichier peut avoir un nom different sur la machine cliente --- qui soumet le job --- et sur le serveur. C'est pourquoi chaque fichier a recuperer est represente par un couple dont le nom LOCAL est le chemin absolu du fichier sur la machine cliente et le nom REMOTE est le chemin absolu du fichier sur le serveur. See Classe Couple.

          Si le nom LOCAL vaut stdout, alors le contenu du fichier designe par le nom LOCAL contient la sortie standard du job au moment de son execution.

          Si le nom LOCAL vaut stderr, alors le contenu du fichier designe par le nom LOCAL contient la sortie d'erreur du job au moment de son execution.

       - PID : type LONG

          La valeur du PID (process identifier) du job sur la machine sur lqsuelle il s'execute.

       - QUEUE : type STRING

          Le nom de la queue, aussi appelee classe ou file suivant les terminologies, qui accueille le job.

       - QUEUEDTIME : type LONG

          La date depuis laquelle le job a ete place en queue dans le gestionnaire de batch.

       - SERVER : type STRING

          Le nom complet du serveur qui recoit les soumissions de job.

       - STARTDATE : type LONG

          La date a partir de laquelle l'utilisateur desire que le job soit execute. L'execution ne demarrera qu'au dela de cette date et a condition que toutes les conditions de ressources soient remplies.

       - STATE : type STRING

          L'etat actuel du job.

          ATTENTION : Ces valeurs ne sont pas encore normalisees.

       - TEXT : type STRING

          Un texte d'information que le gestionnaire peut emettre a destination de l'utilisateur lorsque l'ensemble des parametres n'est pas suffisant pour traduire l'etat reel du job. Par exemple, ce message peut informer l'utilisateur de la raison qui maintient un job dans un etat suspendu ou qui l'empeche de s'executer.

       - TMPDIR : type STRING

          Un chemin d'acces absolu a un repertoire qui sera cree au demarrage du job et qui isolera le job des autres travaux en cours d'execution sur la meme machine.

       - USEDCPUTIME : type LONG

          Le temps de calcul (CPU time) en secondes reellement consomme par le job.

       - USEDDISKSIZE : type LONG

          L'espace disque en octets reellement consomme par le job.

       - USEDRAMSIZE : type LONG

          L'espace disque en octets reellement consommee par le job.

       - USEDWALLTIME : type LONG

          Le temps reel (elapsed time) en secondes reellement consomme par le job.

       - USER : type STRING

          Le nom de l'utilisateur (username) sous lequel le job devra tourner sur la machine d'execution. Ce parametre est utile lorsque l'utilisateur possede des comptes differents sur les machines sur lequel il soumet et calcule.

Versatile
.........

Cette classe est normalement invisible en tant que telle a l'utilsateur de la bibliotheque de classes Batch. Mais il est tout de meme utile de la presenter car son action est visible, notamment dans son interaction fine avec la classe Parametre. See Classe Parametre.

Comme il a ete precise dans la descrption de la classe Parametre, la classe Versatile a ete concue pour encapsuler les valeurs de la map Parametre qui peuvent etre de types effectifs differents.

Ces types, decrits par l'enumeration DiscriminatorType, sont actuellement au nombre de trois : LONG, STRING et COUPLE. Ces types correpondent au types de base du langage C++ ou de la biliotheque de classes Batch. See Types de base.

Le type special UNDEFINED ne sert que pour l'objet Versatile juste cree mais non encore affecte d'une valeur et donc d'un type. La premiere affection d'une valeur a un objet Versatile non encore affecte lui donne automatiquement le type de la valeur.

Les objets de classe Versatile peuvent se comporter soit comme des variables scalaires, c'est-a-dire ne contenant qu'une valeur unique, soit comme des listes, auquel cas elles utilisent l'interface des list de la STL. Toutefois afin de faciliter l'ecriture pour l'utilisateur basique de la classe Versatile --- et de la classe Parametre ---, des operateurs de concatenation += et , ont ete ajoutes.

  * Entete

          // Les types autorises
          enum DiscriminatorType { UNDEFINED, LONG, STRING, COUPLE };

          typedef struct {
              DiscriminatorType type; // le type de l'element interne
              int maxelem;            // le nombre d'elements autorises
          } TypeParam;

          class Versatile : public list< GenericType * >
          {
            public:
              // Constructeur standard et destructeur
              Versatile();
              virtual ~Versatile();

              // Constructeur par recopie
              Versatile(const Versatile & V);

              // Constructeur depuis le type de "base"
              Versatile(long   l);
              Versatile(const string & s);
              Versatile(const Couple & c);

              // Operateur d'affectation et de concatenation
              // a partir d'un type de "base"
              Versatile & operator = (const long     l)
                throw(TypeMismatchException);
              Versatile & operator = (const string & ch)
                throw(TypeMismatchException);
              Versatile & operator +=(const string & ch)
                throw(TypeMismatchException,ListIsFullException);
              Versatile & operator , (const string & ch)
                throw(TypeMismatchException,ListIsFullException);
              Versatile & operator = (const Couple & cp)
                throw(TypeMismatchException);
              Versatile & operator +=(const Couple & cp)
                throw(TypeMismatchException,ListIsFullException);
              Versatile & operator , (const Couple & cp)
                throw(TypeMismatchException,ListIsFullException);

              // Operateur d'affectation entre objets
              Versatile & operator = (const Versatile & V)
                throw(TypeMismatchException);

              // Conversion de type vers un type de "base"
              operator long() const throw(TypeMismatchException);
              operator string() const throw(TypeMismatchException);
              operator Couple() const throw(TypeMismatchException);
              string str() const throw(TypeMismatchException);

              // Operateur pour l'affichage sur un stream
              friend ostream & operator << (ostream & os, const Versatile & );

              // Positionnement et recuperation du type de l'element interne
              void setType(DiscriminatorType) throw(TypeMismatchException);
              DiscriminatorType getType() const;

              // Positionnement et recuperation du nombre d'elements internes
              void setMaxSize(int i);
              int getMaxSize() const;

              // Positionnement et recuperation du nom de l'objet
              string getName() const;
              void setName(const string & name);

            protected:
              // Efface tous les elements internes de l'objet
              virtual void eraseAll();

              DiscriminatorType _discriminator; // type de l'element interne
              int _maxsize; // nombre max d'elements internes
              string _name; // nom de l'objet (sert pour les exceptions)

            private:

          };

  * Exemple

          ...

          // On cree un objet Versatile non encore affecte (scalaire)
          Versatile Vlong;

          // L'affectation d'un long lui donne le type LONG
          Vlong = 1024L * 1024L * 1024L;
          cout << "Versatile long  (must be 1073741824) : " << Vlong   << endl;

          // On cree un objet Versatile non encore affecte (scalaire)
          Versatile Vstring;

          // L'affectation d'une string (const char * promu en string)
          // lui donne le type STRING
          Vstring = "UneChaine";
          cout << "Versatile string (must be UneChaine) : " << Vstring << endl;

          try
            {
              // L'affectation d'un autre type leve une exception.
              // Il n'y a pas de retypage dynamique.
              Vlong = "";
              cout << "ERR : No TypeMismatchException catched for Versatile long"
                   << endl;
            }
          catch (TypeMismatchException & ex)
            {
              cout << "OK : TypeMismatchException catched for Versatile long"
                   << endl;
            }

          // Reaffectation avec le meme type
          Vlong = 1024L * 1024L;
          cout << "Versatile long  (must be 1048576) : " << Vlong   << endl;

          // On cree un objet Versatile non encore affecte (scalaire) ...
          Versatile Vcat1;

          // ... que l'on transforme en liste (non limitee)
          Vcat1.setMaxSize(0);

          // On affecte la premiere valeur ...
          Vcat1  = "A";

          // ... puis les suivantes par concatenation
          Vcat1 += "B";
          Vcat1 += "C";
          Vcat1 += "D";
          Vcat1 += "E";
          cout << "Versatile string concatenation (must be A B C D E) : "
               << Vcat1 << endl;

          // Idem que pour Vcat1, mais avec une limite a 5 elements dans la liste
          Versatile Vcat2;
          Vcat2.setMaxSize(5);
          Vcat2 = "a", "b", "c", "d", "e";
          cout << "Versatile string concatenation (must be a b c d e) : "
               << Vcat2 << endl;

          // On tronque les 2 derniers elements de la liste (il en reste 3)
          Vcat2.setMaxSize(3);
          cout << "Versatile string concatenation (must be a b c) : "
               << Vcat2 << endl;

          Versatile Vcopy2(Vcat2);
          cout << "Versatile copy  (must be a b c) : " << Vcopy2  << endl;

          Versatile Vaffect;
          Vaffect = Vcat1;
          cout << "Versatile affect (must be A B C D E) : " << Vaffect  << endl;
          Vaffect = Vcat2;
          cout << "Versatile affect (must be a b c) : " << Vaffect  << endl;

          try
            {
              // Retypage dynamique interdit
              Vaffect = Vlong;
              cout << "ERR : No TypeMismatchException catched for Versatile"
                   << endl;
            }
          catch (TypeMismatchException & ex)
            {
              cout << "OK : TypeMismatchException catched for Versatile string"
                   << endl;
            }

          try
            {
              // Concatenation au dela de la limite interdit
              Vcat2 += "En trop";
              cout << "ERR : No ListIsFullException catched for Versatile string"
                   << endl;
            }
          catch (ListIsFullException & ex)
            {
              cout << "OK : ListIsFullException catched for Versatile string"
                   << endl;
            }

          // Les objets Versatile se comportent (presque) comme des objets
          // standards du langage
          long L = Vlong;
          cout << "Long value of Versatile long   (must be 1048576) : "
               << L << endl;

          string S = Vstring;
          cout << "String value of Versatile (must be EncoreUneAutreChaine):"
               << S << endl;

          ...

  * Methodes

       - Versatile()

          Le constructeur par defaut fabrique un objet scalaire de type UNDEFINED et de nom undefined.

       - ~Versatile()

          Le destructeur efface tout le contenu de l'objet si celui-ci avait ete affecte.

       - Versatile(const Versatile & V)

          Le constructeur par recopie duplique l'objet passe en argument ainsi que les valeurs qu'il contient. Le nouvel objet est totalement independant de son geniteur.

       - Versatile(long l)

          Versatile(const string & s)

          Versatile(const Couple & c)

          Ces constructeurs fabriquent des objets scalaires Versatile a partir des types de base passes en argument. Chaque objet acquerera definitivement le type correspondant au type de base : LONG pour long, STRING pour string et COUPLE pour Couple.

       - Versatile & operator = (const long l) throw(TypeMismatchException)

          Versatile & operator = (const string & ch) throw(TypeMismatchException)

          Versatile & operator = (const Couple & cp) throw(TypeMismatchException)

          Ces operateurs affectent ou reaffectent la valeur passee en argument a l'objet. Le type de la valeur doit correspondre au type de l'objet si celui-ci a deja ete affecte, sinon une exception TypeMismatchException est levee. See Classe TypeMismatchException.

          L'ancienne valeur de l'objet est perdue.

       - Versatile & operator += (const string & ch)
          throw(TypeMismatchException, ListIsFullException)

          Versatile & operator ,  (const string & ch)
          throw(TypeMismatchException, ListIsFullException)

          Versatile & operator += (const Couple & cp)
          throw(TypeMismatchException, ListIsFullException)

          Versatile & operator ,  (const Couple & cp)
          throw(TypeMismatchException, ListIsFullException)

          Ces operateurs concatenent la valeur passee en argument a l'objet. Le type de la valeur doit correspondre au type interne de l'objet si celui-ci a deja ete affecte, sinon une exception TypeMismatchException est levee. See Classe TypeMismatchException.

          Si la taille maximale de la liste est depasse, une exception ListIsFullException est levee. See Classe ListIsFullException.

       - Versatile & operator = (const Versatile & V) throw(TypeMismatchException)

          L'operateur d'affectation duplique l'objet passe en argument dans l'objet. Toutes les valeurs internes sont dupliquees de maniere a avoir une independance totale entre les deux objets a l'issue de l'affectation.

          Il est a noter qu'il est possible d'affecter a un objet un objet possedant un type different, auquel cas l'objet courant change de type pour acquerir celui de l'objet passe en argument. C'est le seul cas de changement de type autorise pour un objet.

       - operator long() const throw(TypeMismatchException)

          operator string() const throw(TypeMismatchException)

          operator Couple() const throw(TypeMismatchException)

          string str() const throw(TypeMismatchException)

          Ces operateur de conversion dans les types de base permettent de recuperer la valeur interne de l'objet. Lorsque le type interne est incompatible avec la conversion une exception TypeMismatchException est levee. See Classe TypeMismatchException.

       - ostream & operator << (ostream & os, const Versatile & )

          Cet operateur permet de voir le contenu de l'objet sur un flot de sortie.

       - void setType(DiscriminatorType) throw(TypeMismatchException)

          Cette methode change le type interne de l'objet en celui passe en argument. Ceci n'est possible que pour un objet non encore affecte. Si le nouveau type est different du type actuel une exception TypeMismatchException est levee. See Classe TypeMismatchException.

       - DiscriminatorType getType() const

          Cet accesseur renvoie le type interne de l'objet.

       - void setMaxSize(int i)

          Cette methode permet de changer le nombre d'elements que l'objet est capable de stocker. Par defaut ce nombre est 1 a la construction de l'objet, signifiant qu'il ne peut contenir qu'une seule valeur a la fois (scalaire).

          Si ce nombre est superieur a 1 alors il represente une limite qui ne pourra etre depassee par l'objet sans lever d'exception ListIsFullException. See Classe ListIsFullException.

          Si ce nombre vaut 0 (zero) alors il n'y a aucune limite superieure au nombre d'element dans l'objet.

       - int getMaxSize() const

          Cet accesseur renvoie la taille maximale admise par l'objet.

       - void setName(const string & name)

          Cette methode permet de positionner le nom de l'objet. Par defaut ce nom vaut undefined a la construction de l'objet.

          Il est interessant de positionner le nom a une valeur significative comme par exemple le nom de la variable contenant l'objet car lorsqu'une exception est levee ce nom apparait en clair et aide au debugging.

       - string getName() const

          Cet accesseur renvoie le nom interne de l'objet.

Exceptions
----------

La bibliotheque de classes Batch definit un certain nombre d'exceptions qui sont levees par les classes lors d'evenements qui traduisent un comportement anormal de la bibliotheque.

APIInternalFailureException
...........................

Cette exception est levee par les classes d'implementation de la bibliotheque lorsqu'une erreur est detectee au moment de la communication avec l'API du gestionnaire de batch. En general l'erreur renvoyee par l'API est incluse dans le message de l'exception.

Cette exception herite de la classe GenericException qui definit uniquement un constructeur et deux membres publics constants : type et message. See Classe GenericException.

  * Entete

          class APIInternalFailureException : public GenericException
          {
            public:
              // Constructeur
              APIInternalFailureException(string msg = "undefined");
          };

  * Methodes

       - APIInternalFailureException(string msg = "undefined")

          Ce contructeur prend la chaine msg comme message d'erreur a renvoyer au gestionnaire d'exception. Cette valeur est stockee dans le membre public constant message.

          Le membre public constant type est initialise avec le nom de la classe, soit APIInternalFailureException.

ConnexionFailureException
.........................

Cette exception est levee par les classes d'implementation de la bibliotheque lorsqu'une erreur est detectee au moment de la connexion au gestionnaire de batch. En general l'erreur renvoyee par l'API de connexion est incluse dans le message de l'exception.

Cette exception herite de la classe GenericException qui definit uniquement un constructeur et deux membres publics constants : type et message. See Classe GenericException.

  * Entete

          class ConnexionFailureException : public GenericException
          {
            public:
              // Constructeur
              ConnexionFailureException(string msg = "undefined");
          };

  * Methodes

       - ConnexionFailureException(string msg = "undefined")

          Ce contructeur prend la chaine msg comme message d'erreur a renvoyer au gestionnaire d'exception. Cette valeur est stockee dans le membre public constant message.

          Le membre public constant type est initialise avec le nom de la classe, soit ConnexionFailureException.

GenericException
................

Cette classe est generique comme son nom l'indique et definit une interface commune pour toutes les exceptions de la bibliotheque.

Cette exception definit uniquement un constructeur et deux membres publics constants : type et message. See Classe GenericException.

  * Entete

          class GenericException
          {
            public:
              const string type;    // la nature de l'exception
              const string message; // la raison de l'exception

              // Constructeur
              GenericException(const string tp = "GenericException",
                               const string msg = "undefined");
          };

  * Methodes

       - GenericException(const string tp = "GenericException", const string msg = "undefined")

          Ce contructeur prend la chaine msg comme message d'erreur a renvoyer au gestionnaire d'exception. Cette valeur est stockee dans le membre public constant message.

          Le membre public constant type est initialise avec le parametre tp qui contient generalement le nom de la classe.

InvalidArgumentException
........................

Cette exception est levee par les classes de la bibliotheque lorsqu'un parametre erronne est passe en argument a une methode. En general le nom de l'arguement erronne est inclus dans le message de l'exception.

Cette exception herite de la classe GenericException qui definit uniquement un constructeur et deux membres publics constants : type et message. See Classe GenericException.

  * Entete

          class InvalidArgumentException : public GenericException
          {
            public:
              // Constructeur
              InvalidArgumentException(string msg = "undefined");
          };

  * Methodes

       - InvalidArgumentException(string msg = "undefined")

          Ce contructeur prend la chaine msg comme message d'erreur a renvoyer au gestionnaire d'exception. Cette valeur est stockee dans le membre public constant message.

          Le membre public constant type est initialise avec le nom de la classe, soit InvalidArgumentException.

InvalidKeyException
...................

Cette exception est levee par les methodes de la classe Parametre lorsqu'une clef erronnee est utilisee. En general le nom de la clef erronnee est inclus dans le message de l'exception.

Cette exception herite de la classe GenericException qui definit uniquement un constructeur et deux membres publics constants : type et message. See Classe GenericException.

  * Entete

          class InvalidKeyException : public GenericException
          {
            public:
              // Constructeur
              InvalidKeyException(string msg = "undefined");
          };

  * Methodes

       - InvalidKeyException(string msg = "undefined")

          Ce contructeur prend la chaine msg comme message d'erreur a renvoyer au gestionnaire d'exception. Cette valeur est stockee dans le membre public constant message.

          Le membre public constant type est initialise avec le nom de la classe, soit InvalidKeyException.

ListIsFullException
...................

Cette exception est levee par les methodes de la classe Versatile lorsque la taille maximale de la liste interne est depasse. En general le nom de l'objet en erreur est inclus dans le message de l'exception.

Cette exception herite de la classe GenericException qui definit uniquement un constructeur et deux membres publics constants : type et message. See Classe GenericException.

  * Entete

          class ListIsFullException : public GenericException
          {
            public:
              // Constructeur
              ListIsFullException(string msg = "undefined");
          };

  * Methodes

       - ListIsFullException(string msg = "undefined")

          Ce contructeur prend la chaine msg comme message d'erreur a renvoyer au gestionnaire d'exception. Cette valeur est stockee dans le membre public constant message.

          Le membre public constant type est initialise avec le nom de la classe, soit ListIsFullException.

NotYetImplementedException
..........................

Cette exception est levee par les classes de la bibliotheque lorsqu'une methode declaree mais non encore implementee est utilisee. En general le nom de l'objet en erreur est inclus dans le message de l'exception.

Cette exception herite de la classe GenericException qui definit uniquement un constructeur et deux membres publics constants : type et message. See Classe GenericException.

  * Entete

          class NotYetImplementedException : public GenericException
          {
            public:
              // Constructeur
              NotYetImplementedException(string msg = "undefined");
          };

  * Methodes

       - NotYetImplementedException(string msg = "undefined")

          Ce contructeur prend la chaine msg comme message d'erreur a renvoyer au gestionnaire d'exception. Cette valeur est stockee dans le membre public constant message.

          Le membre public constant type est initialise avec le nom de la classe, soit NotYetImplementedException.

RunTimeException
................

Cette exception est levee par les classes de la bibliotheque lorsqu'une erreur inconnue et imprevue apparait. Cette exception est le comportement par defaut que doit gerer le gestionnaire d'exception en ce qui concerne les classes de la bibliotheque. En general le nom de l'objet en erreur est inclus dans le message de l'exception.

Cette exception herite de la classe GenericException qui definit uniquement un constructeur et deux membres publics constants : type et message. See Classe GenericException.

  * Entete

          class RunTimeException : public GenericException
          {
            public:
              // Constructeur
              RunTimeException(string msg = "undefined");
          };

  * Methodes

       - RunTimeException(string msg = "undefined")

          Ce contructeur prend la chaine msg comme message d'erreur a renvoyer au gestionnaire d'exception. Cette valeur est stockee dans le membre public constant message.

          Le membre public constant type est initialise avec le nom de la classe, soit RunTimeException.

TypeMismatchException
.....................

Cette exception est levee par les methodes de la classe Versatile lorsque qu'une erreur de type est rencontree dans un objet. Ce genre d'erreur survient lorsqu'on essaie d'affecter une valeur d'un type different du type interne de l'objet Versatile a ce meme objet, ou bien lorsqu'on ajoute une valeur d'un type different a une liste. En general le nom de l'objet en erreur est inclus dans le message de l'exception.

Cette exception herite de la classe GenericException qui definit uniquement un constructeur et deux membres publics constants : type et message. See Classe GenericException.

  * Entete

          class TypeMismatchException : public GenericException
          {
            public:
              // Constructeur
              TypeMismatchException(string msg = "undefined");
          };

  * Methodes

       - TypeMismatchException(string msg = "undefined")

          Ce contructeur prend la chaine msg comme message d'erreur a renvoyer au gestionnaire d'exception. Cette valeur est stockee dans le membre public constant message.

          Le membre public constant type est initialise avec le nom de la classe, soit TypeMismatchException.

Classes specifiques
===================

Afin de pouvoir se connecter aux gestionnaires de batch reels a travers leurs API, les classes generiques ont ete derivees pour offrir une implementation correspondant a l'interface qu'elles definissent.

Pour traduire a la fois le fait que les nouvelles classes derivent d'une classe generique et qu'elles sont une implementation d'une API particuliere, on adopte la convention de nom suivante : la classe se nomme comme sa classe generique mais est suffixee par le nom de l'API du gestionnaire de batch, les deux termes etant separes par un caractere _ (souligne).

Actuellement, seul le gestionnaire de batch OpenPBS, see Prerequis, est supporte. Mais ce catalogue devrait s'enrichir par la suite.

Les classes de la bibliotheque sont egalement accessibles a travers un interpreteur Python, ce qui a necessite la creation de certaines classes d'interface avec l'interpreteur.

Classes PBS
-----------

Actuellement seules les classes BatchManager, JobInfo et Job ont besoin d'etre derivees pour implementer la communication et l'interfacage avec l'API du gestionnaire de batch OpenPBS.

FactBatchManager_PBS
....................

Cette classe derive de la classe generique FactBatchManager, see Classe FactBatchManager.

Les objets de la classe BatchManager_PBS realisent l'interface de la bibliotheque avec l'API du gestionnaire de batch OpenPBS.

  * Entete

          class FactBatchManager_PBS : public FactBatchManager
          {
          public:
            // Constructeur et destructeur
            FactBatchManager_PBS();
            virtual ~FactBatchManager_PBS();

            virtual BatchManager_PBS * operator() (const char * hostname) const;

          protected:

          private:

          };

  * Exemple

          ...

          // On recupere l'instance du catalogue de gestionnaires de batch
          Batch::BatchManagerCatalog cata = Batch::BatchManagerCatalog::getInstance();

          // On cree une fabrique de BatchManager de type PBS
          Batch::FactBatchManager & fbm = * cata("PBS");

          ...

  * Methodes

       - FactBatchManager_PBS()

          Ce constructeur instancie un objet de la classe FactBatchManager_PBS et l'enregistre automatiquement aupres du catalogue de fabrique. See Classe BatchManagerCatalog.

          Le type est positionne a la valeur PBS.

       - ~FactBatchManager_PBS()

          Le destructeur ne fait rien de particulier.

       - BatchManager_PBS * operator() (const char * hostname) const

          Cet operateur renvoie un objet nouvellement cree de type BatchManager_PBS derivant de BatchManager et oeuvrant sur la machine hostname. La destruction de l'objet est a la charge de l'appelant.

BatchManager_PBS
................

Cette classe derive de la classe generique BatchManager, see Classe BatchManager.

Les objets de la classe BatchManager_PBS realisent l'interface de la bibliotheque avec l'API du gestionnaire de batch OpenPBS.

  * Entete

          class BatchManager_PBS : public BatchManager
          {
            public:
              // Constructeur et destructeur
              BatchManager_PBS(FactBatchManager * parent,
                               const char * host) throw(InvalidArgumentException);
              virtual ~BatchManager_PBS();

              // Recupere le nom du serveur par defaut
              static string getDefaultServer();

              // Recupere le l'identifiant d'un job deja soumis au BatchManager
              virtual const JobId getJobIdByReference(const string & ref);

              // Methodes pour le controle des jobs : virtuelles pures
              // soumet un job au gestionnaire
              virtual const JobId submitJob(const Job & job);

              // retire un job du gestionnaire
              virtual void deleteJob(const JobId & jobid);

              // suspend un job en file d'attente
              virtual void holdJob(const JobId & jobid);

              // relache un job suspendu
              virtual void releaseJob(const JobId & jobid);

              // modifie un job en file d'attente
              virtual void alterJob(const JobId & jobid,
                                    const Parametre & param,
                                    const Environnement & env);
              virtual void alterJob(const JobId & jobid,
                                    const Parametre & param);
              virtual void alterJob(const JobId & jobid,
                                    const Environnement & env);

              // renvoie l'etat du job
              virtual JobInfo queryJob(const JobId & jobid);

              // modifie un job en file d'attente
              virtual void setParametre(const JobId & jobid,
                                        const Parametre & param);
              virtual void setEnvironnement(const JobId & jobid,
                                            const Environnement & env);

            protected:
              string _hostname; // serveur ou tourne le BatchManager

            private:

          };

  * Exemple

          ...

          // On recupere l'instance du catalogue de gestionnaires de batch
          Batch::BatchManagerCatalog cata = Batch::BatchManagerCatalog::getInstance();

          // On cree une fabrique de BatchManager de type PBS
          Batch::BatchManager & myBM = (* cata("PBS"))("serveur.domaine.fr")

          // Maintenant, on peut utiliser toutes les fonctionnalites du
          // gestionnaire de batch a travers le variable myBM

          ...

  * Methodes

       - BatchManager_PBS(FactBatchManager * parent, const char * host) throw(InvalidArgumentException)

          Excepte un pointeur sur la fabrique qui a produit l'objet, le constructeur accepte zero ou un argument de type string decrivant soit le nom de domaine completement qualifie (FQDN, fully qualified domain name) du serveur de batch, soit son adresse IP dans un format decimal "aaa.bbb.ccc.ddd".

          Si aucun parametre n'est passe au constructeur, celui-ci prend le serveur par defaut tel que renvoye par la methode getDefaultServer.

          Une resolution du nom ou de l'adresse peut etre realisee en fonction des capacites de la plate-forme pour s'assurer que le serveur est connu et joignable. En cas d'echec, une exception InvalidArgumentException est levee. See Classe InvalidArgumentException.

          Ceci fait, une connexion est etablie avec le gestionnaire de batch qui est maintenue jusqu'a destruction de l'objet.

       - ~BatchManager()

          Le destructeur supprime la connexion precedemment etablie par le constructeur lorsque celle-ci a reussi.

       - const JobId submitJob(const Job & job)

          Cette methode soumet le job passe en argument au gestionnaire de batch. Etant donne que le job ne peut pas etre envoye tel quel puisqu'il a un format generique au sein de la bibliotheque de classes Batch, cette methode est chargee de le convertir dans un format adapte au gestionnaire de batch sous-jacent.

          La methode opere ici une conversion du job de la classe Job en Job_PBS.

          Ce n'est que lorsque cette conversion est realisee que le job est soumis au gestionnaire a travers son API. L'identifiant propose par le gestionnaire est alors renvoye a l'appelant. Si la soumission echoue pour une raison ou une autre, une exception APIInternalFailureException est levee. See Classe APIInternalFailureException.

       - void deleteJob(const JobId & jobid)

          Cette methode retire le job dont l'identifiant est passe en argument de la file d'attente du gestionnaire, ou bien l'arrete en cours d'execution. Cette methode est inoperante sur des travaux deja termines, auquel cas une exception APIInternalFailureException est levee. See Classe APIInternalFailureException.

       - void holdJob(const JobId & jobid)

          Cette methode suspend le job dont l'identifiant est passe en argument au sein de la file d'attente du gestionnaire. Cette methode est inoperante sur des travaux en cours d'execution ou deja termines, ainsi que sur des travaux deja suspendus. En cas de probleme, une exception APIInternalFailureException est levee. See Classe APIInternalFailureException.

       - void releaseJob(const JobId & jobid)

          Cette methode relache un job precedemment suspendu en file d'attente dont l'identifiant est passe en argument. Elle est inoperante sur des travaux deja reclaches, en cours d'execution ou termines. En cas de probleme, une exception APIInternalFailureException est levee. See Classe APIInternalFailureException.

       - void alterJob(const JobId & jobid, const Parametre & param, const Environnement & env)

          void alterJob(const JobId & jobid, const Parametre & param)

          void alterJob(const JobId & jobid, const Environnement & env)

          Ces methodes permettent de modifier les parametres d'execution et d'environnement d'un job dont l'identifiant est passe en argument. See Classe Parametre. See Classe Environnement. Il est important de noter que le job doit etre encore place en file d'attente sinon la methode est inoperante. En cas de probleme, une exception APIInternalFailureException est levee. See Classe APIInternalFailureException.

       - JobInfo queryJob(const JobId & jobid)

          Cette methode permet de recuperer les informations concernant le job dont l'identifiant est passe en argument dans un objet de classe JobInfo. See Classe JobInfo. On y retrouve les parametres d'execution et d'environnement du job tels qu'ils ont ete passes au gestionnaire au moment de la soumission, ainsi que des informations concernant l'execution du job comme par exemple la machine d'execution, le temps consomme, la memoire consommee, etc.

          Il n'est pas toujours possible d'interroger un job deja termine. En cas de probleme, une exception APIInternalFailureException est levee. See Classe APIInternalFailureException.

       - const JobId getJobIdByReference(const string & ref)

          Cette methode permet de recuperer au sein de la classe un identifiant de job a partir d'une chaine de caracteres obtenue par un biais externe. Cet identifiant pourra etre utilise par la suite au sein de la biliotheque de classes pour controler le job comme s'il avait ete cree et soumis depuis la biliotheque-meme.

       - void setParametre(const JobId & jobid, const Parametre & param)

          Cette methode n'est utile que pour l'interfacage avec Python, car Python ne sait pas gerer la surcharge de methode, et de fait leve des exceptions lors d'appels a de telles methodes.

          Elle est equivalente a la methode void alterJob(const JobId & jobid, const Parametre & param).

       - void setEnvironnement(const JobId & jobid, const Environnement & env)

          Cette methode n'est utile que pour l'interfacage avec Python, car Python ne sait pas gerer la surcharge de methode, et de fait leve des exceptions lors d'appels a de telles methodes.

          Elle est equivalente a la methode void alterJob(const JobId & jobid, const Environnement & env).

JobInfo_PBS
...........

Un objet de classe JobInfo represente l'ensemble des informations disponibles sur un travail actif, c'est-a-dire soumis au gestionnaire de batch, a un instant donne.

Cet objet reprend des informations issues du job tel qu'il a ete soumis, see Classe Job, mais aussi des informations produites par le gestionnaire de batch a partir de la soumission et du transit du job en son sein : nom de la queue dans laquelle le job est inscrit, duree d'execution, date de soumission, etc.

Ces informations sont disponibles aupres de l'utilisateur de la classe a travers les objets Parametre et Environnement que l'objet JobInfo peut fournir.

  * Entete

          class JobInfo_PBS : public JobInfo
          {
            public:
              // Constructeur standard et destructeur
              JobInfo_PBS();
              JobInfo_PBS(struct batch_status * stat_list,
                          bool tobedeleted = false);
              virtual ~JobInfo_PBS();

              // Constructeur par recopie
              JobInfo_PBS(const JobInfo_PBS & jinfo);

              // Methodes pour l'interfacage avec Python (SWIG)
              string  __str__() const;  // SWIG : affichage en Python
              string  __repr__() const; // SWIG : affichage en Python

            protected:
              Parametre _param; // parametres du job
              Environnement _env; // variables d'environnement du job

            private:
          };

  * Exemple

          ... (ici on cree un BatchManager bm et un Job job)

          // On soumet le job et on recupere un identifiant
          JobId   jobid = bm.submitJob(job);

          // Ce qui permet d'interroger l'etat du job en cours
          // Nota : l'objet retourne est un JobInfo_PBS
          JobInfo jinfo = jobid.queryJob();

          ...

  * Methodes

       - JobInfo_PBS()

          Ce constructeur cree un objet JobInfo_PBS vide.

       - ~JobInfo_PBS()

          Le destructeur libere l'espace memoire alloue pour l'objet si la desollacation n'a pas eu deja lieu dans le constructeur.

       - JobInfo_PBS(const JobInfo_PBS & jinfo)

          Le constructeur par recopie produit un objet identique a celui passe en argument. Les deux objets sont totalement independants l'un de l'autre.

       - JobInfo_PBS(struct batch_status * stat_list, bool tobedeleted = false)

          Ce constructeur recupere une liste chainee du type interne OpenPBS struct batch_status *, la parcoure et l'analyse pour en extraire les informations utilisables par la bibliotheque de classes et les stocker dans deux objets internes Parametre et Environnement.

          Si le parametre tobedeleted vaut true alors la liste chainee stat_list sera desallouee a la fin du constructeur. Sinon elle sera desalloue dans le destructeur au plus tard.

       - string  __str__() const

          Cette methode n'est utile que pour l'interfacage avec Python. Elle permet d'afficher l'etat de l'objet JobInfo.

       - string  __repr__() const

          Cette methode n'est utile que pour l'interfacage avec Python. Elle permet d'afficher l'etat de l'objet JobInfo.

Job_PBS
.......

Un objet de classe Job possede une structure generique potentiellement utilisable par tout gestionnaire de batch mais pas en l'etat. Une conversion dans un format lisible par le gestionnaire doit etre realisee.

Ceci se fait en produisant a partir des donnees generiques de la classe Job des structures de donnees specifiques qui peuvent etre directement passees a l'API du gestionnaire.

La classe Job_PBS se distingue donc de la classe Job par son constructeur et par des accesseurs specifiques qui produisent des donnees lisibles par OpenPBS.

Etant donnee la specificite de cette classe, elle ne devrait concerner que les developpeurs de la bibliotheque de classes Batch.

  * Entete

          class Job_PBS
          {
            public:
              // Constructeurs et destructeur
              Job_PBS(const Job & job);
              virtual ~Job_PBS();

              // Accesseurs
              struct attropl * getAttributesOP();
              struct attrl   * getAttributes();
              char *           getScript();
              char *           getDestination();

            protected:
              struct attropl * _p_attropl; // liste d'attributs + operateur
              struct attrl   * _p_attrl; // liste d'attributs
              char * _script; // chemin d'acces au script du job
              char * _destination; // queue dans laquelle le job est soumis

            private:

          };

  * Exemple

          ...

          Parametre param;
          Environnement env;

          ... (ici on cree les parametres du job)

          Job job(param, env);

          // On fabrique un job specifique a OpenPBS a partir du job generique
          // Ceci ne concerne en general pas l'utilisateur de la bibliotheque
          Job_PBS jobpbs(job);

          ...

  * Methodes

       - Job_PBS(const Job & job)

          Le constructeur convertit les objets internes Parametre et Environnement de l'objet passe en argument en un ensemble de quatre structures C AttributesOP, Attributes, Script et Destination directement utilisable par l'API de OpenPBS.

       - ~Job_PBS()

          Le destructeur libere simplement les espaces alloues pour les structures AttributesOP, Attributes, Script et Destination.

       - struct attropl * getAttributesOP()

          Cet accesseur retourne un pointeur sur la structure interne AttributesOP de l'objet. Cette structure n'est pas protogee contre les modifications accidentelles de l'utilisateur. Par consequent il est recommande d'eviter d'y apporter toute alteration sous peine de dysfonctionnement.

          Pour la definition de la structure AttributesOP, voir la documentation OpenPBS.

       - struct attrl * getAttributes()

          Cet accesseur retourne un pointeur sur la structure interne Attributes de l'objet. Cette structure n'est pas protogee contre les modifications accidentelles de l'utilisateur. Par consequent il est recommande d'eviter d'y apporter toute alteration sous peine de dysfonctionnement.

          Pour la definition de la structure Attributes, voir la documentation OpenPBS.

       - char * getScript()

          Cet accesseur retourne un parametre Script qui est une chaine de caracteres C contenant le chemin absolu (sur la machine d'execution) du script a soumettre au gestionnaire de batch.

          Cette chaine n'est pas protegee contre les modifications accidentelles de l'utilisateur. Il est donc recommande de ne pas y apporter de modification.

       - char * getDestination()

          Cet accesseur retourne un parametre Destination qui est une chaine de caracteres C contenant le nom de la queue, ou classe ou file selon les terminologies, du gestionnaire de batch dans laquelle le job doit etre soumis.

          Cette chaine n'est pas protegee contre les modifications accidentelles de l'utilisateur. Il est donc recommande de ne pas y apporter de modification.

Classes Python
--------------

L'integration de la bibliotheque de classes Batch dans l'interpreteur Python a beaucoup progresse depuis la precedente version et se trouve etre quasiment iso-fonctionelle avec le C++.

Actuellement, l'interface avec Python s'appuie a la fois sur les fonctionnalites de l'utilitaire SWIG, et sur la definition d'une classe specifique qui permet de voir en Python la classe Versatile.

Certaines classes ont de plus des methodes specifiques pour le wrapping Python qui simplifient grandement le developpement des classes d'interface au detriment, il est vrai, d'une bonne independance entre les langages. Ce choix n'est pas definitif et pourra etre revu si l'occasion s'en presente.

Quoi qu'il en soit toutes les classes de haut niveau sont interfacees en Python sous le meme nom et proposent les memes methodes (sauf celles surchargees en C++ qui sot parfois renommees pour lever l'ambiguite). Pour ne pas refaire un expose detaille et fastidieux des fonctionnalites Python de la bibliotheque de classes, il est propose de retrouver les noms et la syntaxe de ces classe dans la partie Utilisation de ce document. See Utilisation.

PyVersatile
...........

La classe PyVersatile derive de la classe Versatile et offre la possibilite de convertir un tel objet en objet Python et vice versa.

  * Entete

          class PyVersatile : public Versatile
          {
            public:
              // Constructeur a partir d'un objet Versatile
              PyVersatile(const Versatile &);

              // Constructeur a partir d'un PyObject
              PyVersatile(const PyObject *) throw(TypeMismatchException,
                                                  ListIsFullException,
                                                  InvalidArgumentException);

              // Conversion de type vers un PyObject
              operator PyObject *() const;

              // Operateur d'affectation a partir d'un objet Versatile
              PyVersatile & operator =(const Versatile &);

            protected:

            private:

          };

  * Exemple

          ...

          // On cree un objet Versatile contenant
          // une liste de chaine de caracteres
          Versatile V;
          V = "a", "b", "c";

          // On convertit cet objet Versatile en PyVersatile
          PyVersatile PyV(V);

          // De la on produit un objet Python
          // qui est une liste de chaine de caracteres
          PyObject * PyO = PyV;

          ...

  * Methodes

       - PyVersatile(const Versatile &)

          Ce constructeur convertit un objet Versatile en objet PyVersatile.

       - PyVersatile(const PyObject *) throw(TypeMismatchException, ListIsFullException, InvalidArgumentException)

          Ce constructeur convertit un objet Python passe en argument en un objet PyVersatile.

          Seuls certains objets Python peuvent etre convertis : les string et les long, ainsi que les listes homogenes de ces types, ce qui est coherent avec la nature de l'objet Versatile. Si tel n'est pas le cas, une exception Python est renvoyee a l'interpreteur.

       - operator PyObject *() const

          Cet operateur convertit l'objet en objet Python. Selon le cas, l'objet retourne est soit un scalaire soit une liste. L'objet retourne est alloue dynamiquement et doit donc etre pris en charge par l'interpreteur.

       - PyVersatile & operator =(const Versatile &)

          L'affectation d'un objet Versatile passe en argument est similaire a l'affectation entre objets Versatile. Les structures de donnees internes initiales de l'objet sont effacees et remplacees par une copie des donnees internes de l'objet passe en argument. Les deux objets restent independants l'un de l'autre a l'issue de l'affectation.

Utilisation
***********

Ce chapitre presente les differentes actions qu'il est possible de realiser avec les classes de la bilbiotheque.

On presente un cas hypothetique ou un utilisateur voudrait soumettre et controler un job depuis un code C++. Les sections suivantes decrivent les operations a faire ainsi que leur action sur le travail soumis.

Connexion
=========

La premiere etape avant toute utilisation pratique des classes de la bibliotheque consiste a se connecter a un gestionnaire de batch.

Ce concept de connexion est purement interne a la bibliotheque car il est tout a fait possible d'imaginer le controle de jobs a travers l'API d'un gestionnaire sans jamais etablir ni maintenir une quelconque connexion avec celui-ci. D'autres par contre reclament l'etablissement d'une connexion.

Quoiqu'il en soit ceci n'est pas genant et l'etablissement et le maintien de la connexion avec le gestionnaire de batch se fait par la creation d'un objet de classe BatchManager ou d'une classe derivee.

En pratique, la classe BatchManager se comporte comme une interface et seules les classes d'implementation derivee doivent etre instanciees.

Si l'on prend le cas d'un serveur serveur.domaine.fr supportant un gestionnaire de batch OpenPBS, on peut s'y connecter de la maniere suivante :

  * Exemple C++ :

          BatchManagerCatalog cata = BatchManagerCatalog::getInstance();
          BatchManager_PBS & bm = * (* cata('PBS'))("serveur.domaine.fr");

  * Exemple Python:

          cata = BatchManagerCatalog.getInstance()
          bm   = cata('PBS')('serveur.domaine.fr')

Tant que l'objet bm sera present --- tant que son destructeur n'aura pas ete appele --- la connexion sera maintenue. La deconnexion aura lieu a la destruction de l'objet.

See Classe BatchManager. See Classe BatchManager_PBS.

Creation
========

La creation du job est l'etape qui precede toute soumission. Elle necessite de decrire d'un maniere ou d'un autre ce que l'on va demander a la machine d'executer.

Pour cela on passe par deux objets intermediaires qui sont l'objet Parametre et l'objet Environnement.

Le minimum a preciser est en general le chemin absolu d'acces a l'executable, quoique ceci depende fortement de la configuration du gestionnaire auquel on se connecte. Celui-ci peut reclamer des parametres supplementaires.

Pour connaitre l'ensemble des parametres disponibles : see Classe Parametre.

On supposera dans cet exemple que l'application en question sait reconnaitre une variable d'environnement MYAPP_LOGLEVEL qui prend une valeur numerique correspondant au niveau d'information affiche en sortie.

Cette application imaginaire utilise egalement trois fichiers :

  * un fichier d'entree nomme Cas1.data sur la machine locale qu'il faudra renommer fort.9 pour que l'application puisse le lire (notre application imaginaire est ecrite en FORTRAN et attend un fichier d'entree sur son descripteur 9);

  * un fichier de sortie standard que l'on voudra recuperer sous le nom Cas1.out;

  * un fichier d'erreur standard que l'on voudra recuperer sous le nom Cas1.err.

Le job est ensuite cree simplement a l'aide des deux objets precedents.

  * Exemple C++ :

          Parametre param;
          param[EXECUTABLE] = "/home/user/my_app/bin/exec_app.sh";
          param[INFILE]     = Couple("/home/user/my_app/data/Cas1.data","fort.9");
          param[OUTFILE]    = Couple("/home/user/my_app/data/Cas1.out", "stdout"),
                              Couple("/home/user/my_app/data/Cas1.err", "stderr");

          Environnement env;
          env["MYAPP_LOGLEVEL"] = "3";

          Job job(param, env);

  * Exemple Python:

          param = {}
          param["EXECUTABLE"] = "/home/user/my_app/bin/exec_app.sh"
          param["INFILE"]     = [ ("/home/user/my_app/data/Cas1.data","fort.9") ]
          param["OUTFILE"]    = [ ("/home/user/my_app/data/Cas1.out", "stdout"),
                                  ("/home/user/my_app/data/Cas1.err", "stderr") ]

          env = {}
          env["MYAPP_LOGLEVEL"] = "3"

          job = Job()
          job.setParametre(param)
          job.setEnvironnement(env)

See Classe Parametre. See Classe Environnement. See Classe Job.

Soumission
==========

Une fois le job cree, il est alors tres simple de le soumettre au gestionnaire de batch en passant par l'intermediaire de l'objet BatchManager cree precedemment.

Cette soumission produira un objet JobId qui servira a controler le job par la suite.

Cependant des exceptions peuvent etre levees au moment de la soumission et il convient de fournir un gestionnaire d'exception pour gerer proprement ces incidents.

  * Exemple C++ :

          try {
            const JobId jobid = bm.submitJob(job);

          } catch (GenericException & ex) {
            ...
          }

  * Exemple Python:

          try :
            jobid = bm.submitJob(job)
          except :
            ...

See Classe Job. See Classe JobId. See Exceptions.

Interrogation
=============

La fourniture d'un objet JobId permet d'avoir tout controle sur le job en cours. En particulier il est possible de l'interroger : ceci generera un objet JobInfo qui donnera l'ensemble des informations disponibles sur l'etat du job aupres du gestionnaire de batch.

Ces informations sont disponibles a travers deux objets internes de classes Parametre et Environnement, les memes que pour la classe Job, mais modifies et completes avec les donnees les plus a jour du gestionnaire de batch.

  * Exemple C++ :

          try {
            const JobInfo jinfo = jobid.queryJob();

            Parametre newparam   = jinfo.getParametre();
            Environnement newenv = jinfo.getEnvironnement();

          } catch (GenericException & ex) {
            ...
          }

  * Exemple Python:

          try :
            jobinfo = jobid.queryJob()

            newparam   = jinfo.getParametre()
            newenv = jinfo.getEnvironnement()
          except :
            ...

See Classe JobId. See Classe JobInfo. See Exceptions.

Destruction
===========

Il est possible de detruire un job que celui-ci soit encore en file d'attente ou bien que son execution ait deja commence, auquel cas elle serait immediatement interrompue.

  * Exemple C++ :

          try {
            jobid.deleteJob();

          } catch (GenericException & ex) {
            ...
          }

  * Exemple Python:

          try :
            jobid.deleteJob()

          except :
            ...

See Classe JobId. See Exceptions.

Suspension
==========

La suspension consiste a figer en file d'attente un job qui n'aurait pas encore commence son execution. Il n'est pas possible de suspendre un job qui s'execute.

Il y a deux manieres de suspendre un job en file d'attente :

  * en utilisant la methode holdJob;

  * en modifiant les parametres du job a l'aide de la methode alterJob.

Exemple 1 :

  * Exemple C++ :

          try {
            jobid.holdJob();

          } catch (GenericException & ex) {
            ...
          }

  * Exemple Python:

          try :
            jobid.holdJob()

          except :
            ...

Exemple 2 :

  * Exemple C++ :

          try {
            Parametre altparam;
            altparam[HOLD] = 1;
            jobid.alterJob(altparam);

          } catch (GenericException & ex) {
            ...
          }

  * Exemple Python:

          // Compte tenu de la surcharge d'operateur, cet exemple peut ne pas
          // fonctionner encore
          try :
            altparam = {}
            altparam["HOLD"] = 1
            jobid.alterJob(altparam)

          except :
            ...

See Classe JobId. See Exceptions. See Reprise.

Reprise
=======

La reprise est l'operation inverse de la suspension en ceci qu'elle libere un job precedemment suspendu en file d'attente. Le job continuera alors son cheminement normal au sein du gestionnaire de batch.

Il y a deux manieres de suspendre un job en file d'attente :

  * en utilisant la methode releaseJob;

  * en modifiant les parametres du job a l'aide de la methode alterJob.

Exemple 1 :

  * Exemple C++ :

          try {
            jobid.releaseJob();

          } catch (GenericException & ex) {
            ...
          }

  * Exemple Python:

          try :
            jobid.releaseJob()

          except :
            ...

Exemple 2 :

  * Exemple C++ :

          try {
            Parametre altparam;
            altparam[HOLD] = 0;
            jobid.alterJob(altparam);

          } catch (GenericException & ex) {
            ...
          }

  * Exemple Python:

          // Compte tenu de la surcharge d'operateur, cet exemple peut ne pas
          // fonctionner encore
          try :
            altparam = {}
            altparam["HOLD"] = 0
            jobid.alterJob(altparam)

          except :
            ...

See Classe JobId. See Exceptions. See Suspension.

Modification
============

Il est possible de modifier tout ou partie des parametres et des variables d'un job a condition que celui-ci soit encore en file d'attente. Un job dont l'execution a deja debute devient inalterable, sauf a l'arreter definitvement.

La modification se fait en declarant un objet Parametre et/ou un objet Environnement contenant l'ensemble des alterations a apporter a la description du job. Ces alterations peuvent porter sur des parametres ou des variables deja definies ou non.

En reprenant le cas du job imaginaire utilise jusqu'ici, on peut souhaiter changer le script qui tient lieu d'executable car le precedent etait incomplet, modifier le niveau d'affichage de la log et ajouter une variable nommee MYAPP_DEBUG qui indique au code de passer en mode debug. Ceci pourrait se faire de la maniere suivante :

  * Exemple C++ :

          try {
            Parametre altparam;
            altparam[EXECUTABLE] = "/home/user/my_app/bin/exec_app.sh";

            Environnement altenv;
            altenv["MYAPP_LOGLEVEL"] = "4";
            altenv["MYAPP_DEBUG"]    = "1";
            jobid.alterJob(altparam, altenv);

          } catch (GenericException & ex) {
            ...
          }

  * Exemple Python:

          // Compte tenu de la surcharge d'operateur, cet exemple peut ne pas
          // fonctionner encore
          try :
            altparam = {}
            altparam["EXECUTABLE"] = "/home/user/my_app/bin/exec_app.sh"

            altenv = {}
            altenv["MYAPP_LOGLEVEL"] = "4";
            altenv["MYAPP_DEBUG"]    = "1";

            jobid.alterJob(altparam, altenv)

          except :
            ...

See Classe JobId. See Exceptions.

Installation
************

Cette section montre comment installer l'ensemble de la bibliotheque de classes Batch sur une machine Unix.

Prerequis
=========

CMake
.....

La bibliotheque de classes Batch utilise CMake pour la configuration et la generation des Makefiles (voir le site officiel http://www.cmake.org/). La version minimum requise est la 2.4.

GCC/G++
-------

A l'heure actuelle, la bibliotheque de classes Batch est developpee en C++ et necessite de fait un compilateur pour ce langage. GCC/G++ version 2.95.3 ou une version ulterieure est un choix judicieux.

Gestionnaires de batch
----------------------

Comme la bibliotheque utilise les fonctionnalites de certains gestionnaires de batch, il est indispensable de pouvoir acceder aux bibliotheques et aux fichiers d'entete de ces produits, ou du moins des produits dont on se servira par la suite, ceci pour pouvoir communiquer a travers l'API qu'ils ont developpe.

Le cas le plus simple est d'avoir le produit directement installe sur la machine sur laquelle sera compilee la bibliotheque de classes Batch.

OpenPBS
.......

A ce jour, seul le gestionnaire de batch PBS (OpenPBS et PBS Pro) est supporte (voir le site officiel http://www.openpbs.org). Il doit avoir une version au moins egale a 2.3.16.

LSF
...

Il est prevu d'avoir un support de LSF dans les mois qui viennent.

LoadLeveler
...........

Il est prevu d'avoir un support de LoadLeveler mais dans un futur plus lointain en fonction de la disponibilite du produit mais surtout d'une machine sur lequel il serait installe.

Sun Grid Engine
...............

Ce choix-la est beaucoup plus hypothetique, et risque bien de ne jamais etre mene a bien.

Rsh/Ssh
.......

Il est prevu de simuler le fonctionnement d'un gestionnaire de batch a l'aide de commandes Unix Rsh et Ssh dans la mesure de leurs capacites lorsque qu'il n'est pas possible d'avoir un gestionnaire de batch sur certaines machines ou de s'y connecter (par exemple lorsqu'on traverse un coupe-feu).

Python
------

Les classes de haut-niveau de la bibliotheque de classes Batch disposent d'une interface en Python qui leur permet d'etre utilisables dans ce langage. L'usage de cette fonctionnalite necessite d'avoir a disposition une version de Python (voir le site officiel http://www.python.org) au moins egale a 2.2.

SWIG
----

De plus l'interfacage avec Python est automatise a l'aide de l'utilitaire SWIG (voir le site officiel http://www.swig.org) qui transcrit les definitions des classes C++ en classes Python. Il faut pour cela disposer de la version 1.3.17 ou ulterieure.

Installation rapide
===================

Il faut commencer par decompresser le fichier .tar.gz ou .tgz et descendre dans le repertoire qu'il a cree :

     $ tar -xzvf libBatch-VERSION.tar.gz
     $ cd libBatch-VERSION

Pour ceux qui sont vraiment presses, le minimum requis est :

     $ cmake
     $ make
     $ make install

Pour ceux qui ont le temps de lire la suite, les sections suivantes decrivent plus en detail ces etapes et les differents tests que l'on peut mener.

Configuration
=============

La phase de configuration, tres classique dans le domaine des logiciels libres, est basee sur CMake (voir http://www.cmake.org/).

La configuration est faite en appelant cmake avec en parametre le repertoire racine de la bibliotheque de classes Batch. Ce programme analyse l'ensemble des elements du systeme sur lequel se deroulera la compilation pour determiner les parametres optimaux et la presence de tous les produits necessaires a la compilation.

On n'oubliera pas de se referer a la documentation de cmake notamment pour determiner l'emplacement definitif de l'installation. Le fichier INSTALL situe a la racine de la bibliotheque de classes Batch pourra egalement donner des indications d'utilisation.

C'est aussi au cours de cette phase de configuration qu'il est indispensable de preciser avec quelles options la bibliotheque doit etre generee. En particulier il est necessaire d'indiquer avec quel(s) gestionnaire(s) de batch doit se faire la compilation de maniere a avoir acces a l'API. L'utilitaire ccmake, qui prend en parametre le repertoire racine de la bibliotheque de classes Batch, permet de preciser cette configuration.

Compilation
===========

La compilation proprement dite n'appelle pas de remarque particuliere :

     $ make

On n'oubliera pas d'utiliser les fonctionnalites de chaque make, comme par exemple la compilation parallele pour reduire les temps de compilation (voir make).

Compilation de la documentation
===============================

Normalement la documentation est automatiquement compilee lors de la compilation de la bibliotheque, mais uniquement sous forme HTML. Il est egalement possible d'obtenir un fichier .info ou un fichier .dvi qui permettra de generer d'autres formats comme le PostScript (fichier .ps) ou le PDF (fichier .pdf). Cependant les cibles permettant de generer ces autres formats n'ont pas ete creees a l'heure actuelle.

Tests
=====

Tests de pre-installation
-------------------------

La bibliotheque de classes Batch dispose d'un ensemble de tests permettant de verifier le fonctionnement des differents systemes de batch. Les tests sont executes de la maniere suivante :

     $ make test

A la fin des tests, un compte rendu est fait qui avertit l'utilisateur des tests reussis et des echecs rencontres. Chaque test peut etre rejoue individuellement grace a l'utilitaire ctest et en precisant le nom du test. Par exemple :

     $ ctest -R Local_SSH

Tests de post-installation
--------------------------

Aucun test de post-installation n'est actuellement possible sur la bibliotheque de classes Batch.

Installation
============

L'installation est la mise a disposition definitive dans le systeme de la bibliotheque de classes Batch. C'est la derniere etape de la procedure apres la configuration et la compilation.

On l'execute de la maniere suivante :

     $ make install

La bibliotheque, les fichiers d'entete, la documentation et eventuellement le module Python sont installes dans le repertoire definitif.

Divers
******

Index
*****