From: barate Date: Tue, 11 Oct 2011 13:38:11 +0000 (+0000) Subject: Merge from trunk X-Git-Tag: V1_4_0_VISHNU~2 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=1ce00029435ed7091ce9eb914bacd761c140c35b;p=tools%2Flibbatch.git Merge from trunk --- diff --git a/CMakeLists.txt b/CMakeLists.txt index ab678ea..84797ca 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -56,7 +56,7 @@ SET(CPACK_GENERATOR TGZ) SET(CPACK_SOURCE_GENERATOR TGZ ZIP) SET(CPACK_PACKAGE_VERSION_MAJOR 1) SET(CPACK_PACKAGE_VERSION_MINOR 3) -SET(CPACK_PACKAGE_VERSION_PATCH 0) +SET(CPACK_PACKAGE_VERSION_PATCH 1) SET(CPACK_SOURCE_IGNORE_FILES /\\\\.;/CVS/;~) SET(CPACK_SOURCE_PACKAGE_FILE_NAME ${PROJECT_NAME}-${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}) diff --git a/CMakeModules/FindPThread.cmake b/CMakeModules/FindPThread.cmake index 4315044..690fdfc 100644 --- a/CMakeModules/FindPThread.cmake +++ b/CMakeModules/FindPThread.cmake @@ -24,8 +24,25 @@ IF (NOT PThread_FIND_QUIETLY) MESSAGE(STATUS "Looking for PThread...") ENDIF (NOT PThread_FIND_QUIETLY) -FIND_PATH(PTHREAD_INCLUDE_DIR pthread.h) -FIND_LIBRARY(PTHREAD_LIBRARY NAMES pthread pthreadVC2) +IF(WIN32) + SET(PTHREADS_ROOT_USER $ENV{PTHREADS_ROOT}) + SET(PTHREADS_FIND_PATHS_OPTION NO_DEFAULT_PATH) + SET(PTHREADS_INCLUDE_TO_FIND pthread.h) + SET(PTHREADS_INCLUDE_PATHS ${PTHREADS_ROOT_USER}/include) + FIND_PATH(PTHREAD_INCLUDE_DIR ${PTHREADS_INCLUDE_TO_FIND} + PATHS ${PTHREADS_INCLUDE_PATHS} ${PTHREADS_FIND_PATHS_OPTION}) + SET(PTHREADS_LIB_PATHS ${PTHREADS_ROOT_USER}/lib) + IF(CMAKE_BUILD_TYPE STREQUAL Release) + FIND_LIBRARY(PTHREAD_LIBRARY pthreadVSE2 pthreadVC2 + PATHS ${PTHREADS_LIB_PATHS} ${PTHREADS_FIND_PATHS_OPTION}) + ELSE(CMAKE_BUILD_TYPE STREQUAL Release) + FIND_LIBRARY(PTHREAD_LIBRARY pthreadVSE2d pthreadVC2d + PATHS ${PTHREADS_LIB_PATHS} ${PTHREADS_FIND_PATHS_OPTION}) + ENDIF(CMAKE_BUILD_TYPE STREQUAL Release) +ELSE(WIN32) + FIND_PATH(PTHREAD_INCLUDE_DIR pthread.h) + FIND_LIBRARY(PTHREAD_LIBRARY NAMES pthread) +ENDIF(WIN32) IF (PTHREAD_INCLUDE_DIR AND PTHREAD_LIBRARY) SET(PThread_FOUND True) diff --git a/src/CCC/Batch_BatchManager_eCCC.cxx b/src/CCC/Batch_BatchManager_eCCC.cxx index 45c1668..a52ee88 100644 --- a/src/CCC/Batch_BatchManager_eCCC.cxx +++ b/src/CCC/Batch_BatchManager_eCCC.cxx @@ -243,7 +243,7 @@ namespace Batch { if (params.find(NBPROC) != params.end()) nbproc = params[NBPROC]; if (params.find(MAXWALLTIME) != params.end()) - edt = params[MAXWALLTIME] * 60; + edt = (long)params[MAXWALLTIME] * 60; if (params.find(MAXRAMSIZE) != params.end()) mem = params[MAXRAMSIZE]; if (params.find(QUEUE) != params.end()) @@ -290,14 +290,17 @@ namespace Batch { tempOutputFile << " bool=1" << endl; tempOutputFile << " else" << endl; tempOutputFile << " for ((j=0;j<$i;j++)); do" << endl; - tempOutputFile << " echo $n >> nodesFile" << endl; + tempOutputFile << " echo $n >> nodesFile." << rootNameToExecute << endl; tempOutputFile << " done" << endl; tempOutputFile << " bool=0" << endl; tempOutputFile << " fi" << endl; tempOutputFile << "done" << endl; // Abstraction of PBS_NODEFILE - TODO - tempOutputFile << "export LIBBATCH_NODEFILE=nodesFile" << endl; + tempOutputFile << "export LIBBATCH_NODEFILE=nodesFile." << rootNameToExecute << endl; + + // Allow resource sharing in CCRT nodes + tempOutputFile << "export OMPI_MCA_orte_process_binding=none" << endl; // Launch the executable tempOutputFile << "./" + fileNameToExecute << endl; diff --git a/src/Core/Batch_BatchManager_eClient.cxx b/src/Core/Batch_BatchManager_eClient.cxx index 67c7725..c19c926 100644 --- a/src/Core/Batch_BatchManager_eClient.cxx +++ b/src/Core/Batch_BatchManager_eClient.cxx @@ -82,8 +82,8 @@ namespace Batch { { int status; Parametre params = job.getParametre(); - Versatile V = params[INFILE]; - Versatile::iterator Vit; + const Versatile & V = params[INFILE]; + Versatile::const_iterator Vit; status = _protocol.makeDirectory(string(params[TMPDIR]) + "/logs", _hostname, _username); if(status) { @@ -147,8 +147,8 @@ namespace Batch { void BatchManager_eClient::importOutputFiles( const Job & job, const string directory ) { Parametre params = job.getParametre(); - Versatile V = params[OUTFILE]; - Versatile::iterator Vit; + const Versatile & V = params[OUTFILE]; + Versatile::const_iterator Vit; // Create local result directory int status = CommunicationProtocol::getInstance(SH).makeDirectory(directory, "", ""); diff --git a/src/Core/Batch_Constants.cxx b/src/Core/Batch_Constants.cxx index 95b97f2..c5cb22d 100644 --- a/src/Core/Batch_Constants.cxx +++ b/src/Core/Batch_Constants.cxx @@ -71,6 +71,7 @@ namespace Batch { def_Constant(USER); def_Constant(WORKDIR); def_Constant(HOMEDIR); + def_Constant(EXCLUSIVE); // These constants define the status of a job (parameter STATE); def_Constant(CREATED); diff --git a/src/Core/Batch_Constants.hxx b/src/Core/Batch_Constants.hxx index d022fa5..5e948b1 100644 --- a/src/Core/Batch_Constants.hxx +++ b/src/Core/Batch_Constants.hxx @@ -82,6 +82,7 @@ namespace Batch { decl_extern_Constant(USER); decl_extern_Constant(WORKDIR); decl_extern_Constant(HOMEDIR); + decl_extern_Constant(EXCLUSIVE); // These constants define the status of a job (parameter STATE) decl_extern_Constant(CREATED); diff --git a/src/Core/Batch_IntType.cxx b/src/Core/Batch_IntType.cxx deleted file mode 100644 index 01d1c18..0000000 --- a/src/Core/Batch_IntType.cxx +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE -// -// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, -// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// -/* - * IntType.cxx : - * - * Auteur : Ivan DUTKA-MALEN - EDF R&D - * Date : Septembre 2003 - * Projet : SALOME 2 - * - */ - -#include -#include -#include -//#include "MEDMEM_STRING.hxx" -#include "Batch_IntType.hxx" -using namespace std; - - -namespace Batch { - - // Conversion en chaine - string IntType::affiche() const - { - //MEDMEM::STRING sst; - ostringstream sst; - sst << _data; - return sst.str(); - } - - // Operateur d'affectation - IntType & IntType::operator =(int i) - { - _data = i; - return *this; - } - - // Conversion en int - IntType::operator int() const - { - return this->_data; - } - - // Clone duplique l'objet et en fabrique un nouveau a l'aide de new - // qu'il faudra detruire ensuite manuellement - GenericType * IntType::clone() const - { - IntType * pI = new IntType(this->_data); - assert(pI != 0); - return pI; - } - -} diff --git a/src/Core/Batch_IntType.hxx b/src/Core/Batch_IntType.hxx deleted file mode 100644 index c3c8ee7..0000000 --- a/src/Core/Batch_IntType.hxx +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE -// -// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, -// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// -/* - * IntType.hxx : - * - * Auteur : Ivan DUTKA-MALEN - EDF R&D - * Date : Septembre 2003 - * Projet : SALOME 2 - * - */ - -#ifndef _INTTYPE_H_ -#define _INTTYPE_H_ - -#include "Batch_Defines.hxx" - -#include -#include "Batch_GenericType.hxx" - -namespace Batch { - - class BATCH_EXPORT IntType : public GenericType - { - public: - // Constructeur - IntType(const int i=0) : _data(i) {} - - // Conversion en chaine - virtual std::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: - - }; - -} - -#endif diff --git a/src/Core/Batch_ParameterTypeMap.cxx b/src/Core/Batch_ParameterTypeMap.cxx index 89279b1..8acb4f8 100644 --- a/src/Core/Batch_ParameterTypeMap.cxx +++ b/src/Core/Batch_ParameterTypeMap.cxx @@ -84,6 +84,7 @@ namespace Batch { addParameter("USER", STRING, 1); addParameter("WORKDIR", STRING, 1); addParameter("HOMEDIR", STRING, 1); + addParameter("EXCLUSIVE", BOOL, 1); } ParameterTypeMap::~ParameterTypeMap() @@ -106,13 +107,6 @@ namespace Batch { return (_map.find(key) != _map.end()); } - const ParameterType & ParameterTypeMap::operator[](const string & key) const - { - map::const_iterator it = _map.find(key); - if (it == _map.end()) throw InvalidKeyException(key); - return it->second; - } - void ParameterTypeMap::addParameter(const std::string & key, DiscriminatorType type, int maxelem) { if (hasKey(key)) throw InvalidKeyException(key + " is already present in type map"); @@ -120,4 +114,11 @@ namespace Batch { _map[key].maxelem = maxelem; } + Versatile ParameterTypeMap::createVersatile(const std::string & parameterName) + { + map::const_iterator it = _map.find(parameterName); + if (it == _map.end()) throw InvalidKeyException(parameterName); + return Versatile(it->second.type, it->second.maxelem, parameterName); + } + } diff --git a/src/Core/Batch_ParameterTypeMap.hxx b/src/Core/Batch_ParameterTypeMap.hxx index 277e281..bebeeea 100644 --- a/src/Core/Batch_ParameterTypeMap.hxx +++ b/src/Core/Batch_ParameterTypeMap.hxx @@ -54,9 +54,8 @@ namespace Batch { static ParameterTypeMap& getInstance(); bool hasKey(const std::string & key) const; - const ParameterType & operator[](const std::string & key) const; - void addParameter(const std::string & key, DiscriminatorType type, int maxelem); + Versatile createVersatile(const std::string & parameterName); protected: diff --git a/src/Core/Batch_Parametre.cxx b/src/Core/Batch_Parametre.cxx index 9a50e53..d38a3fe 100644 --- a/src/Core/Batch_Parametre.cxx +++ b/src/Core/Batch_Parametre.cxx @@ -44,24 +44,20 @@ namespace Batch { // Operateur de recherche dans la map // Cet operateur agit sur les objets NON CONSTANTS, il autorise la modification de - // la valeur associ�e � la clef car il retourne une reference non constante + // la valeur associée à la clef car il retourne une reference non constante Versatile & Parametre::operator [] (const string & mk) { // On controle que la clef est valide if (!ParameterTypeMap::getInstance().hasKey(mk)) throw InvalidKeyException(mk); - // On recherche la valeur associee... - Versatile & V = map< string, Versatile >::operator [] (mk); - - // ... et on l'initialise systematiquement - // ATTENTION : si un probleme de type survient (ie, on stocke une valeur d'un type - // different de celui inscrit dans TypeMap) une exception TypeMismatchException est - // levee - V.setName(mk); - V.setType(ParameterTypeMap::getInstance()[mk].type); - V.setMaxSize(ParameterTypeMap::getInstance()[mk].maxelem); - - return V; + Parametre::iterator it = find(mk); + if (it != end()) { + return it->second; + } else { + Versatile V = ParameterTypeMap::getInstance().createVersatile(mk); + pair result = insert(make_pair(mk, V)); + return result.first->second; + } } // Operateur de recherche dans la map diff --git a/src/Core/Batch_Versatile.cxx b/src/Core/Batch_Versatile.cxx index 73b4221..790e071 100644 --- a/src/Core/Batch_Versatile.cxx +++ b/src/Core/Batch_Versatile.cxx @@ -22,9 +22,8 @@ /* * Versatile.cxx : * - * Auteur : Ivan DUTKA-MALEN - EDF R&D - * Date : Septembre 2003 - * Projet : SALOME 2 + * Author : Ivan DUTKA-MALEN - EDF R&D + * Date : September 2003 * */ @@ -32,10 +31,8 @@ #include #include #include -#include -//#include "MEDMEM_STRING.hxx" + #include "Batch_GenericType.hxx" -#include "Batch_IntType.hxx" #include "Batch_BoolType.hxx" #include "Batch_CharType.hxx" #include "Batch_LongType.hxx" @@ -43,140 +40,107 @@ #include "Batch_Versatile.hxx" #include "Batch_TypeMismatchException.hxx" #include "Batch_ListIsFullException.hxx" + using namespace std; namespace Batch { - // Constructeur par recopie - Versatile::Versatile(const Versatile & V) : _discriminator(V._discriminator), _maxsize(V._maxsize), _name(V._name) // , _str_value(0) + Versatile::Versatile(DiscriminatorType discriminator, size_type maxsize, std::string name) + : _discriminator(discriminator), + _maxsize(maxsize), + _name(name) { - Versatile::const_iterator it; - - // On prend un a un les elements de l'objet passe en argument qu'on duplique - for(it=V.begin(); it!=V.end(); it++) - push_back( (*it)->clone() ); // Attention, la methode clone fait un new implicite } - // Destructeur - Versatile::~Versatile() + Versatile::Versatile(const Versatile & V) + : _discriminator(V._discriminator), + _maxsize(V._maxsize), + _name(V._name) { - eraseAll(); + Versatile::const_iterator it; + for(it=V.begin(); it!=V.end(); it++) + push_back( (*it)->clone() ); } - // Operateur d'affectation entre objets - Versatile & Versatile::operator = (const Versatile & Vrhs) throw(TypeMismatchException) + Versatile::~Versatile() { - // ATTENTION : le forçage de type leve une exception TypeMismatchException entre cas de conflit - setType(Vrhs._discriminator); - setMaxSize(Vrhs._maxsize); - _name = Vrhs._name; - - // On efface les donnees precedentes eraseAll(); - - // On copie les donnees de Vrhs - Versatile::const_iterator it; - - for(it=Vrhs.begin(); it!=Vrhs.end(); it++) - push_back( (*it)->clone() ); // Attention, la methode clone fait un new implicite - - return *this; } - // Operateur d'affectation a partir d'un long - Versatile & Versatile::operator = (const long l) throw(TypeMismatchException) + Versatile & Versatile::operator = (const long l) throw(TypeMismatchException) { - // ATTENTION : le forçage de type leve une exception TypeMismatchException entre cas de conflit - setType(LONG); - - // On efface les donnees precedentes + checkType(LONG); eraseAll(); - - // On ajoute un element interne de type long a l'objet - LongType * pL = new LongType(l); - assert(pL != 0); - push_back(pL); + push_back(new LongType(l)); return *this; } - // Operateur d'affectation a partir d'une string Versatile & Versatile::operator = (const string & ch) throw(TypeMismatchException) { - // ATTENTION : le forçage de type leve une exception TypeMismatchException entre cas de conflit - setType(STRING); - - // On efface les donnees precedentes + checkType(STRING); eraseAll(); - - // On ajoute un element interne de type string a l'objet - StringType * pS = new StringType(ch); - assert(pS != 0); - push_back(pS); - + push_back(new StringType(ch)); return *this; } - // Operateur de concatenation a partir d'une string Versatile & Versatile::operator +=(const string & ch) throw(TypeMismatchException,ListIsFullException) { - // ATTENTION : le forçage de type leve une exception TypeMismatchException entre cas de conflit - setType(STRING); + checkType(STRING); - // Si la taille maximale est atteinte, on leve une exception ListIsFullException - if (_maxsize == 0) push_back(new StringType(ch)); - else if ((_maxsize > 0) && (size() < _maxsize)) push_back(new StringType(ch)); + // If max size is reached, throw a ListIsFullException + if (_maxsize == 0 || size() < _maxsize) + push_back(new StringType(ch)); else { - //MEDMEM::STRING msg; ostringstream msg; - msg << "Taille maximum : " << _maxsize; + msg << "Maximum size for \"" << _name << "\" is reached: " << _maxsize; throw(ListIsFullException(msg.str())); } return *this; } - // Operateur de concatenation a partir d'une string Versatile & Versatile::operator , (const string & ch) throw(TypeMismatchException,ListIsFullException) { *this += ch; return *this; } - // Operateur d'affectation a partir d'un Couple - Versatile & Versatile::operator = (const Couple & cp) throw(TypeMismatchException) + Versatile & Versatile::operator = (const char * ch) throw(TypeMismatchException) + { + return operator=(string(ch)); + } + + Versatile & Versatile::operator +=(const char * ch) throw(TypeMismatchException,ListIsFullException) { - // ATTENTION : le forçage de type leve une exception TypeMismatchException entre cas de conflit - setType(COUPLE); + return operator+=(string(ch)); + } - // On efface les donnees precedentes - eraseAll(); - - // On ajoute un element interne de type Couple a l'objet - CoupleType * pC = new CoupleType(cp); - assert(pC != 0); - push_back(pC); + Versatile & Versatile::operator , (const char * ch) throw(TypeMismatchException,ListIsFullException) + { + return operator,(string(ch)); + } + Versatile & Versatile::operator = (const Couple & cp) throw(TypeMismatchException) + { + checkType(COUPLE); + eraseAll(); + push_back(new CoupleType(cp)); return *this; } - // Operateur de concatenation a partir d'un Couple Versatile & Versatile::operator +=(const Couple & cp) throw(TypeMismatchException,ListIsFullException) { - // ATTENTION : le forçage de type leve une exception TypeMismatchException entre cas de conflit - setType(COUPLE); - - // Si la taille maximale est atteinte, on leve une exception ListIsFullException - if (_maxsize == 0) push_back(new CoupleType(cp)); - else if ((_maxsize > 0) && (size() < _maxsize)) push_back(new CoupleType(cp)); + checkType(COUPLE); + // If max size is reached, throw a ListIsFullException + if (_maxsize == 0 || size() < _maxsize) + push_back(new CoupleType(cp)); else { - //MEDMEM::STRING msg; ostringstream msg; - msg << "Taille maximum : " << _maxsize; + msg << "Maximum size for \"" << _name << "\" is reached: " << _maxsize; throw(ListIsFullException(msg.str())); } return *this; } - // Operateur de concatenation a partir d'un Couple Versatile & Versatile::operator , (const Couple & cp) throw(TypeMismatchException,ListIsFullException) { *this += cp; @@ -195,88 +159,79 @@ namespace Batch { return os; } - // Positionnement du type de l'element interne - void Versatile::setType(DiscriminatorType t) throw(TypeMismatchException) + Versatile & Versatile::operator = (const int i) throw(TypeMismatchException) { - // Si le type est deja defini et ne correspond pas au type en argument - // une exception TypeMismatchException est levee - if ( (_discriminator == UNDEFINED) || (_discriminator == t) ) - _discriminator = t; - else { - //MEDMEM::STRING sst; - ostringstream sst; - sst << "Trying to change type of Versatile object \"" - << _name << "\""; - throw(TypeMismatchException(sst.str())); - } + checkType(LONG); + eraseAll(); + push_back(new LongType((long)i)); + return *this; } - - // Positionnement du nombre d'elements internes - void Versatile::setMaxSize(int i) + + Versatile & Versatile::operator = (const bool b) throw(TypeMismatchException) { - _maxsize = i; - if (i <= 0) return; - // Si la nouvelle taille est inferieure au nombre d'elements deja - // presents, les elements en surplus sont effaces (troncature) - if (size() > _maxsize) - { - int reste = size() - _maxsize; - Versatile::iterator it; - for(it=end(); (it!=begin()) && reste; it--, reste--) - { - delete back(); - pop_back(); - } - } + checkType(BOOL); + eraseAll(); + push_back(new BoolType(b)); + return *this; } + void Versatile::checkType(DiscriminatorType t) const throw(TypeMismatchException) + { + if (_discriminator != t) + throw (TypeMismatchException("Trying to change type of Versatile object \"" + _name + "\"")); + } - // Conversion de type vers un long Versatile::operator long() const throw(TypeMismatchException) { - // Si le type ne correspond pas ou si la liste contient plus d'un element, - // la conversion est impossible et une exception TypeMismatchException - // est levee - if ( (_maxsize != 1) || (_discriminator != LONG) || (size() == 0) ) { - //MEDMEM::STRING sst; + // If the type does not correspond or if the list has more than one element, + // throw a TypeMismatchException + if ( _maxsize != 1 || _discriminator != LONG || size() == 0 ) { ostringstream sst; - sst << "Cannot cast Versatile object \"" - << _name << "\" to long"; + sst << "Cannot cast Versatile object \"" << _name << "\" to long"; + throw (TypeMismatchException(sst.str())); + } + return *( static_cast(this->front()) ); + } + + Versatile::operator bool() const throw(TypeMismatchException) + { + // If the type does not correspond or if the list has more than one element, + // throw a TypeMismatchException + if ( _maxsize != 1 || _discriminator != BOOL || size() == 0 ) { + ostringstream sst; + sst << "Cannot cast Versatile object \"" << _name << "\" to bool"; throw(TypeMismatchException(sst.str())); } - return *( static_cast(this->front()) ); + return *( static_cast(this->front()) ); + } + + Versatile::operator int() const throw(TypeMismatchException) + { + return operator long(); } - // Conversion de type vers un Couple Versatile::operator Couple() const throw(TypeMismatchException) { - // Si le type ne correspond pas ou si la liste contient plus d'un element, - // la conversion est impossible et une exception TypeMismatchException - // est levee - if ( (_maxsize != 1) || (_discriminator != COUPLE) || (size() == 0) ) { - //MEDMEM::STRING sst; + // If the type does not correspond or if the list has more than one element, + // throw a TypeMismatchException + if ( _maxsize != 1 || _discriminator != COUPLE || size() == 0 ) { ostringstream sst; - sst << "Cannot cast Versatile object \"" - << _name << "\" to Couple"; + sst << "Cannot cast Versatile object \"" << _name << "\" to Couple"; throw(TypeMismatchException(sst.str())); } - return *( static_cast(this->front()) ); + return *( static_cast(this->front()) ); } - // Conversion de type vers une string string Versatile::str() const throw(TypeMismatchException) { - // Si le type ne correspond pas, la conversion est impossible et - // une exception TypeMismatchException est levee - if ( (_discriminator != STRING) || (size() == 0) ) { - //MEDMEM::STRING sst; + // If the type does not correspond, throw a TypeMismatchException + if ( _discriminator != STRING || size() == 0 ) { ostringstream sst; - sst << "Cannot cast Versatile object \"" - << _name << "\" to string"; + sst << "Cannot cast Versatile object \"" << _name << "\" to string"; throw(TypeMismatchException(sst.str())); } - // La chaine renvoyee est la concatenation des chaines internes + // The returned string is the concatenation of internal strings string s; Versatile::const_iterator it; const char * sep = ""; @@ -286,38 +241,32 @@ namespace Batch { return s; } - // Conversion de type vers une string Versatile::operator string () const throw(TypeMismatchException) { return str(); } - // Efface tous les elements internes de l'objet void Versatile::eraseAll() { - while(!empty()) - { - delete back(); - pop_back(); - } + while(!empty()) { + delete back(); + pop_back(); + } } - - // Recuperation du type de l'element interne DiscriminatorType Versatile::getType() const { return _discriminator; } - // Recuperation du nom de l'objet - string Versatile::getName() const + Versatile::size_type Versatile::getMaxSize() const { - return _name; + return _maxsize; } - // Positionnement du nom de l'objet - void Versatile::setName(const string & name) + const string & Versatile::getName() const { - _name = name; + return _name; } + } diff --git a/src/Core/Batch_Versatile.hxx b/src/Core/Batch_Versatile.hxx index ee8eb2a..96b4b60 100644 --- a/src/Core/Batch_Versatile.hxx +++ b/src/Core/Batch_Versatile.hxx @@ -22,9 +22,8 @@ /* * Versatile.hxx : * - * Auteur : Ivan DUTKA-MALEN - EDF R&D - * Date : Septembre 2003 - * Projet : SALOME 2 + * Author : Ivan DUTKA-MALEN - EDF R&D + * Date : September 2003 * */ @@ -37,7 +36,6 @@ #include #include #include "Batch_GenericType.hxx" -#include "Batch_IntType.hxx" #include "Batch_BoolType.hxx" #include "Batch_CharType.hxx" #include "Batch_LongType.hxx" @@ -48,68 +46,68 @@ namespace Batch { - // Les types autorises - // enum DiscriminatorType { UNDEFINED, BOOL, CHAR, INT, LONG, STRING}; - enum DiscriminatorType { UNDEFINED, LONG, STRING, COUPLE }; + // Authorized types + enum DiscriminatorType { BOOL, LONG, STRING, COUPLE }; class BATCH_EXPORT Versatile : public std::list< GenericType * > { public: - // Constructeur standard et destructeur - Versatile() : _discriminator(UNDEFINED), _maxsize(1), _name("undefined") {} - virtual ~Versatile(); - // Constructeur par recopie + // Constructors + Versatile(DiscriminatorType discriminator, size_type maxsize, std::string name); Versatile(const Versatile & V); - // Constructeur depuis le type de "base" - Versatile(long l) : _discriminator(LONG), _maxsize(1), _name("long") { push_back(new LongType(l)); } - Versatile(const std::string & s) : _discriminator(STRING), _maxsize(1), _name("string") { push_back(new StringType(s)); } - Versatile(const Couple & c) : _discriminator(COUPLE), _maxsize(1), _name("couple") { push_back(new CoupleType(c)); } + // Destructor + virtual ~Versatile(); - // Operateur d'affectation et de concatenation a partir d'un type de "base" + // Affectation and concatenation operators from base types Versatile & operator = (const long l) throw(TypeMismatchException); Versatile & operator = (const std::string & ch) throw(TypeMismatchException); Versatile & operator +=(const std::string & ch) throw(TypeMismatchException,ListIsFullException); Versatile & operator , (const std::string & ch) throw(TypeMismatchException,ListIsFullException); + Versatile & operator = (const char * ch) throw(TypeMismatchException); + Versatile & operator +=(const char * ch) throw(TypeMismatchException,ListIsFullException); + Versatile & operator , (const char * 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); + Versatile & operator = (const int i) throw(TypeMismatchException); + Versatile & operator = (const bool b) throw(TypeMismatchException); - // Operateur d'affectation entre objets - Versatile & operator = (const Versatile & V) throw(TypeMismatchException); - - // Conversion de type vers un type de "base" + // Type conversion to base types operator long() const throw(TypeMismatchException); operator std::string() const throw(TypeMismatchException); operator Couple() const throw(TypeMismatchException); std::string str() const throw(TypeMismatchException); + operator bool() const throw(TypeMismatchException); + operator int() const throw(TypeMismatchException); - // Operateur pour l'affichage sur un stream + // Display on a stream BATCH_EXPORT friend std::ostream & operator << (std::ostream & os, const Versatile & ); - // Positionnement et recuperation du type de l'element interne - void setType(DiscriminatorType) throw(TypeMismatchException); - DiscriminatorType getType() const; + // Check the type + void checkType(DiscriminatorType t) const throw (TypeMismatchException); - // Positionnement et recuperation du nombre d'elements internes - void setMaxSize(int i); - int getMaxSize() const { return _maxsize; } + // Getter methods + DiscriminatorType getType() const; + size_type getMaxSize() const; + const std::string & getName() const; - // Positionnement et recuperation du nom de l'objet - std::string getName() const; - void setName(const std::string & name); + // Erase all internal elements + void eraseAll(); - // Efface tous les elements internes de l'objet - virtual void eraseAll(); protected: - DiscriminatorType _discriminator; // type de l'element interne - size_type _maxsize; // nombre max d'elements internes - std::string _name; // nom de l'objet (sert pour les exceptions) + DiscriminatorType _discriminator; // Internal element type + size_type _maxsize; // Maximum number of internal elements + std::string _name; // Object name (used for exceptions) private: + // Forbid the use of default constructor and affectation operator + Versatile() {} + void operator= (const Versatile & V) {} + }; } diff --git a/src/Core/CMakeLists.txt b/src/Core/CMakeLists.txt index c53d1bb..1e4f5c2 100644 --- a/src/Core/CMakeLists.txt +++ b/src/Core/CMakeLists.txt @@ -39,7 +39,6 @@ SET(CLASS_LIST Core/Batch_APIInternalFailureException Core/Batch_FactBatchManager Core/Batch_GenericException Core/Batch_GenericType - Core/Batch_IntType Core/Batch_InvalidArgumentException Core/Batch_InvalidKeyException Core/Batch_Job diff --git a/src/LSF/Batch_BatchManager_eLSF.cxx b/src/LSF/Batch_BatchManager_eLSF.cxx index fe3cfc7..1da7a92 100644 --- a/src/LSF/Batch_BatchManager_eLSF.cxx +++ b/src/LSF/Batch_BatchManager_eLSF.cxx @@ -267,6 +267,11 @@ namespace Batch { if( mem > 0 ) tempOutputFile << "#BSUB -M " << mem*1024 << endl ; tempOutputFile << "#BSUB -n " << nbproc << endl ; + + if (params.find(EXCLUSIVE) != params.end() && params[EXCLUSIVE]) { + tempOutputFile << "#BSUB -x" << endl ; + } + size_t pos = workDir.find("$HOME"); string baseDir; if( pos != string::npos ) @@ -281,10 +286,16 @@ namespace Batch { tempOutputFile << "#BSUB -o " << baseDir << "/logs/output.log." << rootNameToExecute << endl ; tempOutputFile << "#BSUB -e " << baseDir << "/logs/error.log." << rootNameToExecute << endl ; + // Define environment for the job + Environnement env = job.getEnvironnement(); + for (Environnement::const_iterator iter = env.begin() ; iter != env.end() ; ++iter) { + tempOutputFile << "export " << iter->first << "=" << iter->second << endl; + } + tempOutputFile << "cd " << workDir << endl ; // generate nodes file - tempOutputFile << "NODEFILE=`mktemp nodefile-XXXXXXXXXX` || exit 1" << endl; + tempOutputFile << "LIBBATCH_NODEFILE=`mktemp nodefile-XXXXXXXXXX` || exit 1" << endl; tempOutputFile << "bool=0" << endl; tempOutputFile << "for i in $LSB_MCPU_HOSTS; do" << endl; tempOutputFile << " if test $bool = 0; then" << endl; @@ -292,20 +303,18 @@ namespace Batch { tempOutputFile << " bool=1" << endl; tempOutputFile << " else" << endl; tempOutputFile << " for ((j=0;j<$i;j++)); do" << endl; - tempOutputFile << " echo $n >> $NODEFILE" << endl; + tempOutputFile << " echo $n >> $LIBBATCH_NODEFILE" << endl; tempOutputFile << " done" << endl; tempOutputFile << " bool=0" << endl; tempOutputFile << " fi" << endl; tempOutputFile << "done" << endl; - - // Abstraction of PBS_NODEFILE - TODO - tempOutputFile << "export LIBBATCH_NODEFILE=$NODEFILE" << endl; + tempOutputFile << "export LIBBATCH_NODEFILE" << endl; // Launch the executable tempOutputFile << "./" + fileNameToExecute << endl; // Remove the node file - tempOutputFile << "rm $NODEFILE" << endl; + tempOutputFile << "rm $LIBBATCH_NODEFILE" << endl; tempOutputFile.flush(); tempOutputFile.close(); diff --git a/src/LSF/Batch_JobInfo_eLSF.cxx b/src/LSF/Batch_JobInfo_eLSF.cxx index e210564..349c575 100644 --- a/src/LSF/Batch_JobInfo_eLSF.cxx +++ b/src/LSF/Batch_JobInfo_eLSF.cxx @@ -56,40 +56,46 @@ namespace Batch { _param[ID] = oss.str(); // read status of job in log file - char line[128]; - ifstream fp(logFile.c_str(),ios::in); - fp.getline(line,80,'\n'); - - string sjobid, username, status; - fp >> sjobid; - fp >> username; - fp >> status; - - if (status == "PEND") { // Pending - _param[STATE] = QUEUED; - } else if (status == "PSUSP") { // Suspended while pending - _param[STATE] = PAUSED; - } else if (status == "RUN") { // Running - _param[STATE] = RUNNING; - } else if (status == "USUSP") { // Suspended while running - _param[STATE] = PAUSED; - } else if (status == "SSUSP") { // Suspended by LSF - _param[STATE] = PAUSED; - } else if (status == "DONE") { // Finished successfully + string line; + ifstream fp(logFile.c_str()); + getline(fp, line); + + // On some batch managers, the job is deleted soon after it is finished, + // so we have to consider that an unknown job (empty file) is a finished + // one, even if it is not always true. + if (fp.eof()) { _param[STATE] = FINISHED; - } else if (status == "EXIT") { // Finished in error - _param[STATE] = FAILED; - } else if (status == "UNKWN") { // Lost contact - _param[STATE] = FAILED; - } else if (status == "ZOMBI") { // Zombie - _param[STATE] = FAILED; } else { - cerr << "Unknown job state code: " << status << endl; + string sjobid, username, status; + fp >> sjobid; + fp >> username; + fp >> status; + + if (status == "PEND") { // Pending + _param[STATE] = QUEUED; + } else if (status == "PSUSP") { // Suspended while pending + _param[STATE] = PAUSED; + } else if (status == "RUN") { // Running + _param[STATE] = RUNNING; + } else if (status == "USUSP") { // Suspended while running + _param[STATE] = PAUSED; + } else if (status == "SSUSP") { // Suspended by LSF + _param[STATE] = PAUSED; + } else if (status == "DONE") { // Finished successfully + _param[STATE] = FINISHED; + } else if (status == "EXIT") { // Finished in error + _param[STATE] = FAILED; + } else if (status == "UNKWN") { // Lost contact + _param[STATE] = FAILED; + } else if (status == "ZOMBI") { // Zombie + _param[STATE] = FAILED; + } else { + cerr << "Unknown job state code: " << status << endl; + } + + if( status.find("RUN") != string::npos) + _running = true; } - - if( status.find("RUN") != string::npos) - _running = true; - } // Teste si un job est present en machine diff --git a/src/LSF/CMakeLists.txt b/src/LSF/CMakeLists.txt index 764d224..434003f 100644 --- a/src/LSF/CMakeLists.txt +++ b/src/LSF/CMakeLists.txt @@ -35,3 +35,7 @@ IF (BUILD_LSF_INTERFACE AND LSF_FOUND) ENDIF (BUILD_LSF_INTERFACE AND LSF_FOUND) APPEND_CLASSES_TO_SRC_FILES(${CLASS_LIST}) + +IF (TEST_ENABLED) + add_subdirectory(Test) +ENDIF (TEST_ENABLED) diff --git a/src/LSF/Test/CMakeLists.txt b/src/LSF/Test/CMakeLists.txt new file mode 100644 index 0000000..47e0512 --- /dev/null +++ b/src/LSF/Test/CMakeLists.txt @@ -0,0 +1,44 @@ +# Copyright (C) 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE +# +# Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +# CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# + +# Just copy the test scripts to the binary dir +CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/seta.sh ${CMAKE_CURRENT_BINARY_DIR}/seta.sh COPYONLY) +CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/setb.sh ${CMAKE_CURRENT_BINARY_DIR}/setb.sh COPYONLY) +CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/test-script.sh ${CMAKE_CURRENT_BINARY_DIR}/test-script.sh COPYONLY) + +# set the include directories +include_directories(${CMAKE_SOURCE_DIR}/src/Core) +include_directories(${CMAKE_SOURCE_DIR}/src/Core/Test) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..) +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +# Build the test programs and add the tests +add_executable(Test_eLSF Test_eLSF.cxx) +target_link_libraries(Test_eLSF Batch SimpleParser) + +IF (HAS_SSH) + ADD_TEST(eLSF_SSH Test_eLSF SSH) +ENDIF (HAS_SSH) + +#IF (HAS_RSH) +# ADD_TEST(eLSF_RSH Test_eLSF RSH) +#ENDIF (HAS_RSH) diff --git a/src/LSF/Test/Test_eLSF.cxx b/src/LSF/Test/Test_eLSF.cxx new file mode 100644 index 0000000..b3962a9 --- /dev/null +++ b/src/LSF/Test/Test_eLSF.cxx @@ -0,0 +1,163 @@ +// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +/* + * Test_eLSF.cxx : + * + * Author : Renaud BARATE - EDF R&D + * Date : September 2011 + * + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace std; +using namespace Batch; + +void print_usage() +{ + cout << "usage: Test_eLSF PROTOCOL" << endl; + cout << " PROTOCOL \"SSH\" or \"RSH\"" << endl; +} + +int main(int argc, char** argv) +{ + // Parse argument + if (argc != 2) { + print_usage(); + return 1; + } + CommunicationProtocolType protocol; + if (strcmp(argv[1], "SSH") == 0) + protocol = SSH; + else if (strcmp(argv[1], "RSH") == 0) + protocol = RSH; + else { + print_usage(); + return 1; + } + + cout << "*******************************************************************************************" << endl; + cout << "This program tests the batch submission based on LSF emulation. Passwordless" << endl; + cout << "authentication must be used for this test to pass. For SSH, this can be configured with" << endl; + cout << "ssh-agent for instance. For RSH, this can be configured with the .rhosts file." << endl; + cout << "*******************************************************************************************" << endl; + + // eventually remove any previous result + remove("result.txt"); + + try { + // Parse the test configuration file + SimpleParser parser; + parser.parseTestConfigFile(); + const string & homedir = parser.getValue("TEST_ELSF_HOMEDIR"); + const string & host = parser.getValue("TEST_ELSF_HOST"); + const string & user = parser.getValue("TEST_ELSF_USER"); + int timeout = parser.getValueAsInt("TEST_ELSF_TIMEOUT"); + + // Define the job... + Job job; + // ... and its parameters ... + Parametre p; + p[EXECUTABLE] = "./test-script.sh"; + p[NAME] = string("Test eLSF ") + argv[1]; + p[WORKDIR] = homedir + "/tmp/Batch"; + p[INFILE] = Couple("seta.sh", "tmp/Batch/seta.sh"); + p[INFILE] += Couple("setb.sh", "tmp/Batch/setb.sh"); + p[OUTFILE] = Couple("result.txt", "tmp/Batch/result.txt"); + p[TMPDIR] = "tmp/Batch/"; + p[NBPROC] = 1; + p[MAXWALLTIME] = 1; + p[MAXRAMSIZE] = 50; + p[HOMEDIR] = homedir; + p[EXCLUSIVE] = true; + job.setParametre(p); + // ... and its environment + Environnement e; + e["MYENVVAR"] = "MYVALUE"; + job.setEnvironnement(e); + cout << job << endl; + + // Get the catalog + BatchManagerCatalog& c = BatchManagerCatalog::getInstance(); + + // Create a BatchManager of type ePBS on localhost + FactBatchManager_eClient * fbm = (FactBatchManager_eClient *)(c("eLSF")); + BatchManager_eClient * bm = (*fbm)(host.c_str(), user.c_str(), protocol); + + // Submit the job to the BatchManager + JobId jobid = bm->submitJob(job); + cout << jobid.__repr__() << endl; + + // Wait for the end of the job + string state = bm->waitForJobEnd(jobid, timeout); + + if (state == FINISHED) { + cout << "Job " << jobid.__repr__() << " is done" << endl; + bm->importOutputFiles(job, "resultdir/seconddirname"); + } else if (state == FAILED) { + cerr << "Job " << jobid.__repr__() << " finished in error" << endl; + bm->importOutputFiles(job, "resultdir/seconddirname"); + return 1; + } else { + cerr << "Timeout while executing job" << endl; + return 1; + } + + } catch (GenericException e) { + cerr << "Error: " << e << endl; + return 1; + } catch (ParserException e) { + cerr << "Parser error: " << e.what() << endl; + return 1; + } + + // test the result file + try { + SimpleParser resultParser; + resultParser.parse("resultdir/seconddirname/result.txt"); + cout << "Result:" << endl << resultParser; + const string & envvar = resultParser.getValue("MYENVVAR"); + int result = resultParser.getValueAsInt("c"); + if (envvar == "MYVALUE" && result == 12) { + cout << "OK, Expected result found." << endl; + return 0; + } else { + cerr << "Error, result is not the expected one (MYENVVAR = MYVALUE, c = 12)." << endl; + return 1; + } + } catch (ParserException e) { + cerr << "Parser error on result file: " << e.what() << endl; + return 1; + } +} diff --git a/src/LSF/Test/seta.sh b/src/LSF/Test/seta.sh new file mode 100644 index 0000000..42d1e38 --- /dev/null +++ b/src/LSF/Test/seta.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +a=4 diff --git a/src/LSF/Test/setb.sh b/src/LSF/Test/setb.sh new file mode 100644 index 0000000..8969060 --- /dev/null +++ b/src/LSF/Test/setb.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +b=3 diff --git a/src/LSF/Test/test-script.sh b/src/LSF/Test/test-script.sh new file mode 100755 index 0000000..1d56247 --- /dev/null +++ b/src/LSF/Test/test-script.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +. ./seta.sh +. ./setb.sh + +c=`expr $a "*" $b` + +echo "MYENVVAR = $MYENVVAR" > result.txt +echo "c = $c" >> result.txt diff --git a/src/LoadLeveler/Batch_BatchManager_eLL.cxx b/src/LoadLeveler/Batch_BatchManager_eLL.cxx index 85a387c..aa3562a 100644 --- a/src/LoadLeveler/Batch_BatchManager_eLL.cxx +++ b/src/LoadLeveler/Batch_BatchManager_eLL.cxx @@ -147,7 +147,6 @@ namespace Batch { tempOutputFile << "#!/bin/bash" << endl; tempOutputFile << "# @ output = " << workDir << "/logs/output.log." << rootNameToExecute << endl; tempOutputFile << "# @ error = " << workDir << "/logs/error.log." << rootNameToExecute << endl; - tempOutputFile << "# @ node_usage = not_shared" << endl; if (params.find(NAME) != params.end()) tempOutputFile << "# @ job_name = " << params[NAME] << endl; @@ -157,6 +156,13 @@ namespace Batch { if (params.find(NBPROC) != params.end()) nbproc = params[NBPROC]; + if (params.find(EXCLUSIVE) != params.end()) { + if (params[EXCLUSIVE]) + tempOutputFile << "# @ node_usage = not_shared" << endl; + else + tempOutputFile << "# @ node_usage = shared" << endl; + } + // If job type is not specified, try to guess it from number of procs string job_type; if (params.find(LL_JOBTYPE) != params.end()) @@ -168,10 +174,10 @@ namespace Batch { tempOutputFile << "# @ job_type = " << job_type << endl; - if (job_type != "serial") { + if (job_type == "mpich") { int nodes_requested = (nbproc + _nb_proc_per_node -1) / _nb_proc_per_node; tempOutputFile << "# @ node = " << nodes_requested << endl; - tempOutputFile << "# @ tasks_per_node = " << _nb_proc_per_node << endl; + tempOutputFile << "# @ total_tasks = " << nbproc << endl; } if (params.find(MAXWALLTIME) != params.end()) diff --git a/src/LoadLeveler/Test/Test_eLL.cxx b/src/LoadLeveler/Test/Test_eLL.cxx index a3e70d6..8064386 100644 --- a/src/LoadLeveler/Test/Test_eLL.cxx +++ b/src/LoadLeveler/Test/Test_eLL.cxx @@ -104,7 +104,8 @@ int main(int argc, char** argv) p[MAXRAMSIZE] = 50; p[HOMEDIR] = homedir; p[QUEUE] = queue; - p[LL_JOBTYPE] = jobType; + p[LL_JOBTYPE] = jobType; + p[EXCLUSIVE] = false; job.setParametre(p); // ... and its environment Environnement e; diff --git a/src/PBS/Batch_BatchManager_ePBS.cxx b/src/PBS/Batch_BatchManager_ePBS.cxx index 7232f7e..c92a121 100644 --- a/src/PBS/Batch_BatchManager_ePBS.cxx +++ b/src/PBS/Batch_BatchManager_ePBS.cxx @@ -256,9 +256,31 @@ namespace Batch { tempOutputFile << "#! /bin/sh -f" << endl; if (nbproc > 0) { - // Division - arrondi supérieur - int nodes_requested = (nbproc + _nb_proc_per_node -1) / _nb_proc_per_node; - tempOutputFile << "#PBS -l nodes=" << nodes_requested << ":ppn=" << _nb_proc_per_node << endl; + int nb_full_nodes = nbproc / _nb_proc_per_node; + int nb_proc_on_last_node = nbproc % _nb_proc_per_node; + + // In exclusive mode, we reserve all procs on the nodes + if (params.find(EXCLUSIVE) != params.end() && params[EXCLUSIVE] && nb_proc_on_last_node > 0) { + nb_full_nodes += 1; + nb_proc_on_last_node = 0; + } + + tempOutputFile << "#PBS -l nodes="; + + // Full nodes + if (nb_full_nodes > 0) { + tempOutputFile << nb_full_nodes << ":ppn=" << _nb_proc_per_node; + if (nb_proc_on_last_node > 0) { + tempOutputFile << "+"; + } + } + + // Partly reserved node + if (nb_proc_on_last_node > 0) { + tempOutputFile << "1:ppn=" << nb_proc_on_last_node; + } + + tempOutputFile << endl; } if (queue != "") tempOutputFile << "#PBS -q " << queue << endl; diff --git a/src/PBS/Test/Test_ePBS.cxx b/src/PBS/Test/Test_ePBS.cxx index 0e57d3c..1040faa 100644 --- a/src/PBS/Test/Test_ePBS.cxx +++ b/src/PBS/Test/Test_ePBS.cxx @@ -114,7 +114,7 @@ int main(int argc, char** argv) // Create a BatchManager of type ePBS on localhost FactBatchManager_eClient * fbm = (FactBatchManager_eClient *)(c("ePBS")); - BatchManager_eClient * bm = (*fbm)(host.c_str(), user.c_str(), protocol, "lam"); + BatchManager_eClient * bm = (*fbm)(host.c_str(), user.c_str(), protocol, "nompi", 8); // Submit the job to the BatchManager JobId jobid = bm->submitJob(job); diff --git a/src/Python/Batch_PyVersatile.cxx b/src/Python/Batch_PyVersatile.cxx deleted file mode 100644 index 3584724..0000000 --- a/src/Python/Batch_PyVersatile.cxx +++ /dev/null @@ -1,202 +0,0 @@ -// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE -// -// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, -// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// -/* - * PyVersatile.cxx : - * - * Auteur : Ivan DUTKA-MALEN - EDF R&D - * Mail : mailto:ivan.dutka-malen@der.edf.fr - * Date : Mon Oct 13 12:01:12 2003 - * Projet : Salome 2 - * - */ - -#include -#include "Batch_TypeMismatchException.hxx" -#include "Batch_ListIsFullException.hxx" -#include "Batch_InvalidArgumentException.hxx" -#include "Batch_PyVersatile.hxx" -#include - -using namespace std; - -namespace Batch { - - // Constructeur a partir d'un objet Versatile - PyVersatile::PyVersatile(const Versatile & V) : Versatile(V) - { - // Nothing to do - } - - - // Constructeur a partir d'un PyObject - // Les objets autorises sont les strings et les ints, - // ainsi que les listes de strings - PyVersatile::PyVersatile(const PyObject * PyO) throw(TypeMismatchException, ListIsFullException, InvalidArgumentException) : Versatile() - { - PyObject * _PyO = const_cast(PyO); - - if (PyList_Check(_PyO)) { // c'est une liste - _maxsize = PyList_Size(_PyO); - for (size_type i=0; i<_maxsize; i++) { - PyObject * val = PyList_GetItem(_PyO, i); - if (PyString_Check(val)) { - *this += PyString_AsString(val); - - } else if (PyTuple_Check(val) && - (PyTuple_Size(val) == 2) && - PyString_Check( PyTuple_GetItem(val,0) ) && - PyString_Check( PyTuple_GetItem(val,1) ) ) { - *this += Couple( PyString_AsString( PyTuple_GetItem(val,0) ), - PyString_AsString( PyTuple_GetItem(val,1) ) - ); - - } else { - PyErr_SetString(PyExc_RuntimeWarning, "PyVersatile::PyVersatile(const PyObject * PyO) : invalid PyObject"); - } - } - - } else if (PyString_Check(_PyO)) { // c'est une string - const char * s = PyString_AsString(_PyO); - Versatile V = string(s); - *this = V; - - } else if (PyInt_Check(_PyO)) { // c'est un int - *this = PyInt_AsLong(_PyO); - - } else { // erreur - PyErr_SetString(PyExc_RuntimeWarning, "PyVersatile::PyVersatile(const PyObject * PyO) : invalid PyObject"); - } - } - - - - // Conversion de type vers un PyObject - PyVersatile::operator PyObject *() const - { - PyObject * obj; - - if (_maxsize != 1) { // une liste - obj = PyList_New(0); - for(Versatile::const_iterator it=begin(); it!=end(); it++) { - // char ch[2] = {0, 0}; - string st; - Couple cp; - // PyObject * tuple; - switch (_discriminator) { - // case BOOL: - // PyList_Append(obj, PyInt_FromLong(* static_cast(*it))); - // break; - - // case CHAR: - // *ch = * static_cast(*it); - // PyList_Append(obj, PyString_FromString(ch)); - // break; - - // case INT: - // PyList_Append(obj, PyInt_FromLong(* static_cast(*it))); - // break; - - case LONG: - PyList_Append(obj, PyInt_FromLong(* static_cast(*it))); - break; - - case STRING: - st = * static_cast(*it); - PyList_Append(obj, PyString_FromString(st.c_str())); - break; - - case COUPLE: - cp = * static_cast(*it); - // tuple = PyTuple_New(2); - // PyTuple_SetItem(tuple, 0, PyString_FromString( cp.getLocal().c_str() ) ); - // PyTuple_SetItem(tuple, 1, PyString_FromString( cp.getRemote().c_str() ) ); - // PyList_Append(obj, tuple); - PyList_Append(obj, Py_BuildValue("(ss)", cp.getLocal().c_str(), cp.getRemote().c_str() )); - break; - - case UNDEFINED: - PyList_Append(obj, Py_None); - break; - } - - } - - } else { // un scalaire - // char ch[2] = {0, 0}; - string st; - Couple cp; - // PyObject * tuple; - switch (_discriminator) { - // case BOOL: - // obj = PyInt_FromLong(* static_cast(front())); - // break; - - // case CHAR: - // *ch = * static_cast(front()); - // obj = PyString_FromString(ch); - // break; - - // case INT: - // obj = PyInt_FromLong(* static_cast(front())); - // break; - - case LONG: - obj = PyInt_FromLong(* static_cast(front())); - break; - - case STRING: - st = * static_cast(front()); - obj = PyString_FromString(st.c_str()); - break; - - case COUPLE: - cp = * static_cast(front()); - // tuple = PyTuple_New(2); - // PyTuple_SetItem(tuple, 0, PyString_FromString( cp.getLocal().c_str() ) ); - // PyTuple_SetItem(tuple, 1, PyString_FromString( cp.getRemote().c_str() ) ); - // obj = PyList_New(0); - // PyList_Append(obj, tuple); - obj = Py_BuildValue("[(ss)]", cp.getLocal().c_str(), cp.getRemote().c_str() ); - break; - - case UNDEFINED: - obj = Py_None; - break; - } - } - - return obj; - } - - - // Operateur d'affectation a partir d'un objet Versatile - PyVersatile & PyVersatile::operator =(const Versatile & V) - { - Versatile * me = this; - *me = V; - return *this; - } - -} - - -// COMMENTS diff --git a/src/Python/Batch_PyVersatile.hxx b/src/Python/Batch_PyVersatile.hxx deleted file mode 100644 index 1e33af0..0000000 --- a/src/Python/Batch_PyVersatile.hxx +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE -// -// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, -// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// -/* - * PyVersatile.hxx : - * - * Auteur : Ivan DUTKA-MALEN - EDF R&D - * Mail : mailto:ivan.dutka-malen@der.edf.fr - * Date : Mon Oct 13 12:01:12 2003 - * Projet : Salome 2 - * - */ - -#ifndef _PYVERSATILE_H_ -#define _PYVERSATILE_H_ - - -#include "Batch_Defines.hxx" - -#include -#include "Batch_Versatile.hxx" -#include "Batch_TypeMismatchException.hxx" -#include "Batch_ListIsFullException.hxx" -#include "Batch_InvalidArgumentException.hxx" - -#ifdef WIN32 -# if defined _libBatch_Swig_EXPORTS -# define BATCH_SWIG_EXPORT __declspec( dllexport ) -# else -# define BATCH_SWIG_EXPORT __declspec( dllimport ) -# endif -#else -# define BATCH_SWIG_EXPORT -#endif - -namespace Batch { - - class BATCH_SWIG_EXPORT 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: - - }; - -} - -#endif diff --git a/src/Python/CMakeLists.txt b/src/Python/CMakeLists.txt index a24051e..08febb7 100644 --- a/src/Python/CMakeLists.txt +++ b/src/Python/CMakeLists.txt @@ -28,13 +28,12 @@ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) SET(SWIG_SRC_FILE libBatch_Swig.i) SET_SOURCE_FILES_PROPERTIES(${SWIG_SRC_FILE} PROPERTIES CPLUSPLUS ON SWIG_FLAGS "-shadow") -SWIG_ADD_MODULE(libBatch_Swig python ${SWIG_SRC_FILE} Batch_PyVersatile.cxx) +SWIG_ADD_MODULE(libBatch_Swig python ${SWIG_SRC_FILE}) SWIG_LINK_LIBRARIES(libBatch_Swig Batch ${PYTHON_LIBRARIES}) INSTALL(TARGETS ${SWIG_MODULE_libBatch_Swig_REAL_NAME} DESTINATION lib/python${PYTHON_VERSION}/site-packages) INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/libBatch_Swig.py DESTINATION lib/python${PYTHON_VERSION}/site-packages) -INSTALL(FILES Batch_PyVersatile.hxx DESTINATION include/Batch) SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES libBatch_Swig.py) diff --git a/src/Python/libBatch_Swig_typemap.i b/src/Python/libBatch_Swig_typemap.i index e4fea7d..d6a9575 100644 --- a/src/Python/libBatch_Swig_typemap.i +++ b/src/Python/libBatch_Swig_typemap.i @@ -32,20 +32,167 @@ #include #include #include +#include "Batch_ParameterTypeMap.hxx" #include "Batch_Parametre.hxx" -#include "Batch_PyVersatile.hxx" #include "Batch_JobId.hxx" #include "Batch_FactBatchManager.hxx" -#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN) -typedef int Py_ssize_t; -#define PY_SSIZE_T_MAX INT_MAX -#define PY_SSIZE_T_MIN INT_MIN -#endif +#include "Batch_RunTimeException.hxx" %} # // supprime toutes les definitions par defaut => sert au debug # %typemap(in) SWIGTYPE ; +%{ +// Helper function to initialize a Batch::Versatile from a PyObj +static bool initVersatile(Batch::Versatile & newVersatile, PyObject * input) +{ + if (PyList_Check(input)) { // c'est une liste + for (Py_ssize_t i=0; i(*it))); + break; + + case Batch::STRING: + st = * static_cast(*it); + PyList_Append(obj, PyString_FromString(st.c_str())); + break; + + case Batch::COUPLE: + cp = * static_cast(*it); + PyList_Append(obj, Py_BuildValue("(ss)", cp.getLocal().c_str(), cp.getRemote().c_str() )); + break; + + default: + throw Batch::RunTimeException("Versatile object cannot be converted to Python object"); + } + + } + + } else { + bool b; + std::string st; + Batch::Couple cp; + switch (vers.getType()) { + case Batch::BOOL: + b = (* static_cast(vers.front())); + obj = PyBool_FromLong(b); + break; + + case Batch::LONG: + obj = PyInt_FromLong(* static_cast(vers.front())); + break; + + case Batch::STRING: + st = * static_cast(vers.front()); + obj = PyString_FromString(st.c_str()); + break; + + case Batch::COUPLE: + cp = * static_cast(vers.front()); + obj = Py_BuildValue("[(ss)]", cp.getLocal().c_str(), cp.getRemote().c_str() ); + break; + + default: + throw Batch::RunTimeException("Versatile object cannot be converted to Python object"); + } + } + + return obj; +} + +// Helper function to initialize a Batch::Parametre from a PyObj +static bool initParameter(Batch::Parametre & newParam, PyObject * input) +{ + if (!PyDict_Check(input)) { + PyErr_SetString(PyExc_ValueError, "Expected a dictionnary"); + return false; + } + + try { + // on itere sur toutes les clefs du dictionnaire, et on passe par la classe PyVersatile + // qui convertit un Versatile en PyObject et vice versa + PyObject *key, *value; + Py_ssize_t pos = 0; + while (PyDict_Next(input, &pos, &key, &value)) { + std::string mk = PyString_AsString(key); + bool res = initVersatile(newParam[mk], value); + if (!res) + return false; + } + } + catch (Batch::GenericException & ex) { + std::string msg = ex.type + " : " + ex.message; + PyErr_SetString(PyExc_RuntimeWarning, msg.c_str()); + return false; + } + catch (...) { + PyErr_SetString(PyExc_RuntimeWarning, "unknown exception"); + return false; + } + return true; +} + +// Helper function to initialize a Batch::Environnement from a PyObj +static bool initEnvironment(Batch::Environnement & newEnv, PyObject * input) +{ + if (!PyDict_Check(input)) { + PyErr_SetString(PyExc_ValueError, "Expected a dictionnary"); + return false; + } + + // on itere sur toutes les clefs du dictionnaire + PyObject *key, *value; + Py_ssize_t pos = 0; + while (PyDict_Next(input, &pos, &key, &value)) { + std::string mk = PyString_AsString(key); + std::string val = PyString_AsString(value); + newEnv[mk] = val; + } + return true; +} +%} # // construction d'un dictionnaire Python a partir d'un objet BatchManagerCatalog C++ %typemap(out) std::map * @@ -73,78 +220,26 @@ typedef int Py_ssize_t; // on itere sur toutes les clefs de la map, et on passe par la classe PyVersatile // qui convertit un Versatile en PyObject et vice versa for(Batch::Parametre::const_iterator it=$1.begin(); it!=$1.end(); it++) { - std::string key = (*it).first; - Batch::PyVersatile PyV = (*it).second; - PyDict_SetItem($result, PyString_FromString(key.c_str()), PyV); + const std::string & key = (*it).first; + const Batch::Versatile & vers = (*it).second; + PyDict_SetItem($result, PyString_FromString(key.c_str()), versatileToPyObj(vers)); } } - -# // construction d'un objet Parametre C++ a partir d'un dictionnaire Python -%typemap(in) Batch::Parametre & (Batch::Parametre PM) +// Build a C++ object Batch::Parametre from a Python dictionary +%typemap(in) const Batch::Parametre & (Batch::Parametre PM) { - if (!PyDict_Check($input)) { - PyErr_SetString(PyExc_ValueError,"Expected a dictionnary"); + bool res = initParameter(PM, $input); + if (res) + $1 = &PM; + else return NULL; - } - - try { - // on itere sur toutes les clefs du dictionnaire, et on passe par la classe PyVersatile - // qui convertit un Versatile en PyObject et vice versa - PyObject *key, *value; - Py_ssize_t pos = 0; - while (PyDict_Next($input, &pos, &key, &value)) { - std::string mk = PyString_AsString(key); - Batch::PyVersatile PyV = value; - PyV.setName(mk); - PM[mk] = PyV; - } - - $1 = &PM; // $1 est une reference donc on lui passe une adresse - } - catch (Batch::GenericException & ex) { - std::string msg = ex.type + " : " + ex.message; - PyErr_SetString(PyExc_RuntimeWarning, msg.c_str()); - return NULL; - } - catch (...) { - PyErr_SetString(PyExc_RuntimeWarning, "unknown exception"); - return NULL; - } } - -# // construction d'un objet Parametre C++ a partir d'un dictionnaire Python -%typemap(in) Batch::Parametre (Batch::Parametre PM) +%typemap(in) Batch::Parametre { - if (!PyDict_Check($input)) { - PyErr_SetString(PyExc_ValueError,"Expected a dictionnary"); - return NULL; - } - - try { - // on itere sur toutes les clefs du dictionnaire, et on passe par la classe PyVersatile - // qui convertit un Versatile en PyObject et vice versa - PyObject *key, *value; - Py_ssize_t pos = 0; - while (PyDict_Next($input, &pos, &key, &value)) { - std::string mk = PyString_AsString(key); - Batch::PyVersatile PyV = value; - PyV.setName(mk); - PM[mk] = PyV; - } - - $1 = PM; - } - catch (Batch::GenericException & ex) { - std::string msg = ex.type + " : " + ex.message; - PyErr_SetString(PyExc_RuntimeWarning, msg.c_str()); - return NULL; - } - catch (...) { - PyErr_SetString(PyExc_RuntimeWarning, "unknown exception"); - return NULL; - } + bool res = initParameter($1, $input); + if (!res) return NULL; } %typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER) Batch::Environnement @@ -167,47 +262,20 @@ typedef int Py_ssize_t; } } - -# // construction d'un objet Environnement C++ a partir d'un dictionnaire Python -%typemap(in) Batch::Environnement & (Batch::Environnement E) +// Build a C++ object Batch::Environnement from a Python dictionary +%typemap(in) const Batch::Environnement & (Batch::Environnement E) { - if (!PyDict_Check($input)) { - PyErr_SetString(PyExc_ValueError,"Expected a dictionnary"); + bool res = initEnvironment(E, $input); + if (res) + $1 = &E; + else return NULL; - } - - // on itere sur toutes les clefs du dictionnaire - PyObject *key, *value; - Py_ssize_t pos = 0; - while (PyDict_Next($input, &pos, &key, &value)) { - std::string mk = PyString_AsString(key); - std::string val = PyString_AsString(value); - E[mk] = val; - } - - $1 = &E; // $1 est une reference donc on lui passe une adresse } - - -# // construction d'un objet Environnement C++ a partir d'un dictionnaire Python -%typemap(in) Batch::Environnement (Batch::Environnement E) +%typemap(in) Batch::Environnement { - if (!PyDict_Check($input)) { - PyErr_SetString(PyExc_ValueError,"Expected a dictionnary"); - return NULL; - } - - // on itere sur toutes les clefs du dictionnaire - PyObject *key, *value; - Py_ssize_t pos = 0; - while (PyDict_Next($input, &pos, &key, &value)) { - std::string mk = PyString_AsString(key); - std::string val = PyString_AsString(value); - E[mk] = val; - } - - $1 = E; + bool res = initEnvironment($1, $input); + if (!res) return NULL; } // Dynamic cast to FactBatchManager_eClient if necessary diff --git a/src/Slurm/Batch_BatchManager_eSlurm.cxx b/src/Slurm/Batch_BatchManager_eSlurm.cxx index e20775b..e677509 100644 --- a/src/Slurm/Batch_BatchManager_eSlurm.cxx +++ b/src/Slurm/Batch_BatchManager_eSlurm.cxx @@ -150,10 +150,14 @@ namespace Batch { int nbproc = 1; if (params.find(NBPROC) != params.end()) nbproc = params[NBPROC]; + tempOutputFile << "#SBATCH --ntasks=" << nbproc << endl; - int nodes_requested = (nbproc + _nb_proc_per_node -1) / _nb_proc_per_node; - tempOutputFile << "#SBATCH --nodes=" << nodes_requested << endl; - tempOutputFile << "#SBATCH --ntasks-per-node=" << _nb_proc_per_node << endl; + if (params.find(EXCLUSIVE) != params.end()) { + if (params[EXCLUSIVE]) + tempOutputFile << "#SBATCH --exclusive" << endl; + else + tempOutputFile << "#SBATCH --share" << endl; + } if (params.find(MAXWALLTIME) != params.end()) tempOutputFile << "#SBATCH --time=" << params[MAXWALLTIME] << endl; @@ -177,6 +181,9 @@ namespace Batch { tempOutputFile << "cd " << workDir << endl; tempOutputFile << "./" + fileNameToExecute << endl; + // Remove the node file + tempOutputFile << "rm $LIBBATCH_NODEFILE" << endl; + tempOutputFile.flush(); tempOutputFile.close(); @@ -242,9 +249,10 @@ namespace Batch { command += " > "; command += logFile; cerr << command.c_str() << endl; - int status = system(command.c_str()); - if (status != 0) - throw EmulationException("Can't query job " + jobid.getReference()); + system(command.c_str()); + // We don't test the return code here because with jobs finished since a long time Slurm + // returns an error and a message like "slurm_load_jobs error: Invalid job id specified". + // So we consider that the job is finished when we get an error. JobInfo_eSlurm jobinfo = JobInfo_eSlurm(jobid.getReference(), logFile); return jobinfo; diff --git a/src/Slurm/Test/Test_eSlurm.cxx b/src/Slurm/Test/Test_eSlurm.cxx index 1726db7..09ff90c 100644 --- a/src/Slurm/Test/Test_eSlurm.cxx +++ b/src/Slurm/Test/Test_eSlurm.cxx @@ -100,6 +100,7 @@ int main(int argc, char** argv) p[MAXWALLTIME] = 1; p[MAXRAMSIZE] = 50; p[HOMEDIR] = homedir; + p[EXCLUSIVE] = true; job.setParametre(p); // ... and its environment Environnement e;