From: admin Date: Thu, 17 Jul 2008 11:09:28 +0000 (+0000) Subject: This commit was generated by cvs2git to create tag 'V4_1_0rc1'. X-Git-Tag: V4_1_0rc1 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=ba295c1247ebf303c50d73a8cad00ad86348459c;p=modules%2Fkernel.git This commit was generated by cvs2git to create tag 'V4_1_0rc1'. Sprout from BR_Dev_For_4_0 2007-11-08 11:20:28 UTC mkr 'IMP NPAL13547: Checkbox to kill SALOME completely.' Cherrypick from V4_1_0_maintainance 2008-07-17 11:09:26 UTC jfa 'Bug 0019869: Compile KERNEL in Werror mode. Integrating KERNEL_SRC_20080710.patch.': bin/salome_utilities.py doc/salome/salome_application.dox src/Batch/Batch_BatchManager_eClient.cxx src/Batch/Batch_BatchManager_eClient.hxx src/Batch/Batch_BatchManager_eLSF.cxx src/Batch/Batch_BatchManager_eLSF.hxx src/Batch/Batch_BatchManager_ePBS.cxx src/Batch/Batch_BatchManager_ePBS.hxx src/Batch/Batch_FactBatchManager_eClient.cxx src/Batch/Batch_FactBatchManager_eClient.hxx src/Batch/Batch_FactBatchManager_eLSF.cxx src/Batch/Batch_FactBatchManager_eLSF.hxx src/Batch/Batch_FactBatchManager_ePBS.cxx src/Batch/Batch_FactBatchManager_ePBS.hxx src/Batch/Batch_JobInfo_eLSF.cxx src/Batch/Batch_JobInfo_eLSF.hxx src/Batch/Batch_JobInfo_ePBS.cxx src/Batch/Batch_JobInfo_ePBS.hxx src/DSC/DSC_User/Datastream/Calcium/CalciumCxxInterface.hxx src/DSC/DSC_User/Datastream/Calcium/calciumE.h src/Launcher/BatchTest.cxx src/Launcher/BatchTest.hxx src/Launcher/Launcher.cxx src/Launcher/Launcher.hxx src/ResourcesManager/ResourcesManager.cxx src/ResourcesManager/ResourcesManager.hxx Cherrypick from master 2008-03-07 07:43:41 UTC jfa 'Join modifications from BR_Dev_For_4_0 tag V4_1_1.': bin/appliskel/getAppliPath.py bin/waitNS.sh doc/salome/batch.dox doc/salome/install.dox doc/salome/kernel_resources.dox doc/salome/kernel_services.dox doc/salome/main.dox doc/salome/salome_file.dox doc/salome/tui/KERNEL/sources/kernel_about_4.png doc/salome/unittests.dox src/DSC/DSC.dox src/ParallelContainer/SALOME_ParallelContainerProxy_i.cxx src/ParallelContainer/SALOME_ParallelContainerProxy_i.hxx --- diff --git a/bin/appliskel/getAppliPath.py b/bin/appliskel/getAppliPath.py new file mode 100755 index 000000000..bac311da7 --- /dev/null +++ b/bin/appliskel/getAppliPath.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python + +import os + +def relpath(target, base): + """ Find relative path from base to target + if target== "/local/chris/appli" and base== "/local/chris" the result is appli + if target== /tmp/appli and base /local/chris the result is ../../tmp/appli + """ + target=target.split(os.path.sep) + base=base.split(os.path.sep) + for i in xrange(len(base)): + if base[i] != target[i]: + i=i-1 + #not in base + break + p=['..']*(len(base)-i-1)+target[i+1:] + if p == []: + return '.' + return os.path.join( *p ) + +def set_var(VAR, strpath): + """Set VAR environment variable """ + value = "%r" % strpath + shell = os.getenv('SHELL') + if shell and shell.endswith('csh'): + return "setenv %s %s" % (VAR, value) + else: + return "export %s=%s" % (VAR, value) + + +applipath=relpath(os.path.abspath(os.path.dirname(__file__)),os.path.abspath(os.getenv('HOME'))) + +#print set_var('APPLI', applipath) +print applipath diff --git a/bin/salome_utilities.py b/bin/salome_utilities.py new file mode 100644 index 000000000..b4349cd20 --- /dev/null +++ b/bin/salome_utilities.py @@ -0,0 +1,346 @@ +# Copyright (C) 2005 OPEN CASCADE, CEA, EDF R&D, LEG +# PRINCIPIA R&D, EADS CCR, Lip6, BV, CEDRAT +# 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 +# +# --- +# +# File : salome_utilities.py +# Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com) +# +# --- + +""" +Set of utility functions used by SALOME python scripts. +""" + +# +# Exported functions +# +__all__ = [ + 'getORBcfgInfo', + 'getHostFromORBcfg', + 'getPortFromORBcfg', + 'getUserName', + 'getHostName', + 'getShortHostName', + 'getAppName', + 'getPortNumber', + 'getTmpDir', + 'generateFileName', + ] + +# --- + +def _try_bool( arg ): + """ + Check if specified parameter represents boolean value and returns its value. + String values like 'True', 'TRUE', 'YES', 'Yes', 'y', 'NO', 'false', 'n', etc + are supported. + If does not represent a boolean, an exception is raised. + """ + import types + if type( arg ) == types.BooleanType : + return arg + elif type( arg ) == types.StringType : + v = str( arg ).lower() + if v in [ "yes", "y", "true" ]: return True + elif v in [ "no", "n", "false" ]: return False + pass + raise Exception("Not boolean value") + +# --- + +def getORBcfgInfo(): + """ + Get omniORB current configuration. + Returns a list of three values: [ orb_version, host_name, port_number ]. + + The information is retrieved from the omniORB configuration file defined + by the OMNIORB_CONFIG environment variable. + If omniORB configuration file can not be accessed, a list of three empty + strings is returned. + """ + import os, re + ret = [ "", "", "" ] + try: + f = open( os.getenv( "OMNIORB_CONFIG" ) ) + lines = f.readlines() + f.close() + regvar = re.compile( "(ORB)?InitRef.*corbaname::(.*):(\d+)\s*$" ) + for l in lines: + try: + m = regvar.match( l ) + if m: + if m.group(1) is None: + ret[0] = "4" + else: + ret[0] = "3" + pass + ret[1] = m.group(2) + ret[2] = m.group(3) + break + pass + except: + pass + pass + pass + except: + pass + return ret + +# --- + +def getHostFromORBcfg(): + """ + Get current omniORB host. + """ + return getORBcfgInfo()[1] +# --- + +def getPortFromORBcfg(): + """ + Get current omniORB port. + """ + return getORBcfgInfo()[2] + +# --- + +def getUserName(): + """ + Get user name: + 1. try USER environment variable + 2. if fails, return 'unknown' as default user name + """ + import os + return os.getenv( "USER", "unknown" ) # 'unknown' is default user name + +# --- + +def getHostName(): + """ + Get host name: + 1. try socket python module gethostname() function + 2. if fails, try HOSTNAME environment variable + 3. if fails, try HOST environment variable + 4. if fails, return 'unknown' as default host name + """ + import os + try: + import socket + host = socket.gethostname() + except: + host = None + pass + if not host: host = os.getenv("HOSTNAME") + if not host: host = os.getenv("HOST") + if not host: host = "unknown" # 'unknown' is default host name + return host + +# --- + +def getShortHostName(): + """ + Get short host name: + 1. try socket python module gethostname() function + 2. if fails, try HOSTNAME environment variable + 3. if fails, try HOST environment variable + 4. if fails, return 'unknown' as default host name + """ + try: + return getHostName().split('.')[0] + except: + pass + return "unknown" # 'unknown' is default host name + +# --- + +def getAppName(): + """ + Get application name: + 1. try APPNAME environment variable + 2. if fails, return 'SALOME' as default application name + """ + import os + return os.getenv( "APPNAME", "SALOME" ) # 'SALOME' is default user name + +# --- + +def getPortNumber(): + """ + Get current naming server port number: + 1. try NSPORT environment variable + 1. if fails, try to parse config file defined by OMNIORB_CONFIG environment variable + 2. if fails, return 2809 as default port number + """ + import os + try: + return int( os.getenv( "NSPORT" ) ) + except: + pass + port = getPortFromORBcfg() + if port is not None: return port + return 2809 # '2809' is default port number + +# --- + +def getTmpDir(): + """ + Get directory to be used for the temporary files. + """ + import os, sys + if sys.platform == "win32": + # for Windows: temporarily using home directory for tmp files; + # to be replaced with TEMP environment variable later... + dir = os.getenv("HOME") + else: + # for Linux: use /tmp/logs/{user} folder + dir = os.path.join( '/tmp', 'logs', getUserName() ) + pass + return dir + +# --- + +def generateFileName( dir, prefix = None, suffix = None, extension = None, + unique = False, separator = "_", hidden = False, **kwargs ): + """ + Generate file name by sepecified parameters. If necessary, file name + can be generated to be unique. + + Parameters: + - dir : directory path + - prefix : file prefix (not added by default) + - suffix : file suffix (not added by default) + - extension : file extension (not added by default) + - unique : if this parameter is True, the unique file name is generated: + in this case, if the file with the generated name already exists + in the directory, an integer suffix is added to the end of the + file name. This parameter is False by default. + - separator : separator of the words ('_' by default) + - hidden : if this parameter is True, the file name is prepended by . (dot) + symbol. This parameter is False by default. + + Other keyword parameters are: + - with_username : 'add user name' flag/option: + * boolean value can be passed to determine user name automatically + * string value to be used as user name + - with_hostname : 'add host name' flag/option: + * boolean value can be passed to determine host name automatically + * string value to be used as host name + - with_port : 'add port number' flag/option: + * boolean value can be passed to determine port number automatically + * string value to be used as port number + - with_app : 'add application name' flag/option: + * boolean value can be passed to determine application name automatically + * string value to be used as application name + All parameters are optional. + """ + supported = [ 'with_username', 'with_hostname', 'with_port', 'with_app' ] + from launchConfigureParser import verbose + filename = [] + # separator + if separator is None: + separator = "" + pass + else: + separator = str( separator ) + pass + # prefix (if specified) + if prefix is not None: + filename.append( str( prefix ) ) + pass + # additional keywords + ### check unsupported parameters + for kw in kwargs: + if kw not in supported and verbose(): + print 'Warning! salome_utilitie.py: generateFileName(): parameter %s is not supported' % kw + pass + pass + ### process supported keywords + for kw in supported: + if kw not in kwargs: continue + ### user name + if kw == 'with_username': + try: + # auto user name ? + if _try_bool( kwargs[kw] ): filename.append( getUserName() ) + pass + except: + # user name given as parameter + filename.append( kwargs[kw] ) + pass + pass + ### host name + elif kw == 'with_hostname': + try: + # auto host name ? + if _try_bool( kwargs[kw] ): filename.append( getShortHostName() ) + pass + except: + # host name given as parameter + filename.append( kwargs[kw] ) + pass + pass + ### port number + elif kw == 'with_port': + try: + # auto port number ? + if _try_bool( kwargs[kw] ): filename.append( str( getPortNumber() ) ) + pass + except: + # port number given as parameter + filename.append( str( kwargs[kw] ) ) + pass + pass + ### application name + elif kw == 'with_app': + try: + # auto application name ? + if _try_bool( kwargs[kw] ): filename.append( getAppName() ) + pass + except: + # application name given as parameter + filename.append( kwargs[kw] ) + pass + pass + pass + # suffix (if specified) + if suffix is not None: + filename.append( str( suffix ) ) + pass + # raise an exception if file name is empty + if not filename: + raise Exception("Empty file name") + # + if extension is not None and extension.startswith("."): extension = extension[1:] + # + import os + name = separator.join( filename ) + if hidden: name = "." + name # add dot for hidden files + if extension: name = name + "." + str( extension ) # add extension if defined + name = os.path.join( dir, name ) + if unique: + # create unique file name + index = 0 + while os.path.exists( name ): + index = index + 1 + name = separator.join( filename ) + separator + str( index ) + if hidden: name = "." + name # add dot for hidden files + if extension: name = name + "." + str( extension ) # add extension if defined + name = os.path.join( dir, name ) + pass + pass + return name diff --git a/bin/waitNS.sh b/bin/waitNS.sh new file mode 100755 index 000000000..3d875f992 --- /dev/null +++ b/bin/waitNS.sh @@ -0,0 +1,9 @@ +#! /bin/sh +status=1 +while [ $status -ne 0 ]; do + ls $HOME/$APPLI/.omniORB_last.cfg >& /dev/null + status=$? + sleep 1 + echo -n "#" +done +./runSession waitNS.py \ No newline at end of file diff --git a/doc/salome/batch.dox b/doc/salome/batch.dox new file mode 100644 index 000000000..7e0e4e29b --- /dev/null +++ b/doc/salome/batch.dox @@ -0,0 +1,10 @@ +/*! + +\page batch_page Batch + + Batch documentation + +*/ + + + diff --git a/doc/salome/install.dox b/doc/salome/install.dox new file mode 100644 index 000000000..8090ff92f --- /dev/null +++ b/doc/salome/install.dox @@ -0,0 +1,378 @@ +/*! + \page INSTALL Installation instructions + +NOT UP TO DATE %SALOME 4 +WORK in PROGRESS, INCOMPLETE DOCUMENT + +You'll find here generic instructions for installing the SALOME2 platform. + +\section Summary + +
    +
  1. \ref S1_install
  2. +
  3. \ref S2_install
  4. +
  5. \ref S3_install
  6. +
  7. \ref S4_install
  8. +
  9. \ref S5_install
  10. +
  11. \ref S6_install
  12. +
  13. \ref S7_install
  14. +
  15. \ref S8_install
  16. +
+ +\section S1_install Quick Overview + +First of all, you have to check (or install if needed) the dependant +software programs on your system. These programs are: + +- common development tools as gcc, automake, autoconf and libtools. +- third party softwares used in SALOME building or runtime process + (python, OCC, VTK, ...) + +Further details can be found in sections [2] and [3]. + +If the dependencies are installed on your system, then you have to set +your shell environment to get access to the software components +(cf. [4]. "Preparing the shell environment"). + +The next step is to install the KERNEL (cf. [5] "Installing KERNEL"): + +\code +$ mkdir +$ mkdir +$ cd +$ ./build_configure +$ cd +$ /configure --prefix= +$ make +$ make install +\endcode + +Then, the %SALOME components GEOM, MED, VISU, ... can be installed +with a similar procedure (cf. [6]). + +Eventually, the platform ccodean be run by executing the shell script +runSalome (cf. [7]). Here, somme additionnal variables have to be set +to describe the %SALOME runtime configuration (_ROOT_DIR, +OMNIORB_CONFIG) + +The following provides you with specific instructions for each step. + + +\section S2_install System configuration + +%SALOME is compiled and tested on differents platforms with native packages: +- Debian sarge +- Mandrake 10.1 +- ... + +If you have another platform, we suggest the following configuration +for building process: + +- gcc-3.3.x or 3.4.x +- automake-1.7 or more (only aclocal is used) +- autoconf-2.59 +- libtool-1.5.6 + +remarks: + +- This is the minimum level of automake, autoconf and libtool, if you need + to compile all the third party softwares (included OpenCascade 5.2.x). + +\section S3_install Third-party dependencies + +The %SALOME platform relies on a set of third-party softwares. The +current version depends on the following list +(versions given here are from Debian Sarge, except OpenCascade, VTK and MED, +which are not Debian packages): + +- CAS-5.2.4 OpenCascade (try binaries,a source patch is needed) +- VTK-4.2.6 VTK 3D-viewer +- PyQt-3.13 Python-Qt Wrapper +- Python-2.3.5 Python interpreter +- SWIG-1.3.24 SWIG library +- boost-1_32_0 C++ library (only include templates are used) +- hdf5-1.6.2 Files Database library +- med-2.2.2 MED Data Format support for file records +- omniORB-4.0.5 ORB used in %SALOME +- qt-x11-free-3.3.3 Qt library +- qwt-4.2 Graph components for Qt +- sip4-4.1.1 langage binding software + +And, in order to build the documentation: + +- doxygen-1.4.2 +- graphviz-2.2.1 + + +Additionnal software may be installed for optional features: + +- netgen4.3 + patch +- tix8.1.4 +- openpbs-2.3.16 +- lsf-??? + +To Do + +- Instructions for installing these software programs can be found in a + special note doc/configuration_examples/install-prerequis. +- Installation shell scripts are also provided. + These scripts have to be adapted to your own configuration. + +- See doc/configuration_examples/* + +In the following, we assume that all the third-party softwares are +installed in the same root directory, named /prerequis. +Then, your file system should probably look like:: + +\code +/prerequis/Python-2.2.2 +/prerequis/omniORB-3.0.5 +/prerequis/qt-x11-free-3.0.5 +... +\endcode + +\section S4_install Preparing the shell environment + +Some variables have to be set to get acces to third-party software +components (include files, executable, library, ...) during building +process and runtime. + +The shell file prerequis.sh, embedded in the KERNEL source package, +provides a template for setting those variables. In this example, all the +softwares are supposed to be installed in the same root directory, +named here INSTALLROOT. + +Copy the prerequis.sh in a working directory and adjust the settings +to your own configuration. To get the shell prepared, just +execute the following command in the building shell: + +\code +$ source prerequis.sh +\endcode + +(we assume here a ksh or bash mode) + + +\section S5_install Installing the KERNEL component + +We use here the notation to specify the source directory +of the KERNEL component. The shell environment is supposed to have +been set (cf. 4). + +Installing the KERNEL from a source package needs three directories: + +- the source directory, denoted here by . + +- the build directory, denoted by in the following. This + directory can't be the same directory as . + +- the install directory, denoted by in the following. This + directory can't be the same directory as or + . + +The installing process is: + +STEP 1: + preparing directories + + create the and the directories: + + \code +$ mkdir +$ mkdir +\endcode + +STEP 2: + build configure script + + go to directory and generate the "configure" script: + + \code +$ cd +$ ./build_configure + \endcode + + If it doesn't work, check your system automake tools as specified in + section [2]. + +STEP 3: + configure the building process + go to the build directory and execute the configuration process:: + + \code +$ cd +$ /configure --prefix= + \endcode + + Note that must be an absolute path. + + When the configure process is complete, check the status of + third-party softwares detection. You should have a status like:: + + \code + --------------------------------------------- + Summary + --------------------------------------------- + Configure + cc : yes + boost : yes + lex_yacc : yes + python : yes + swig : yes + threads : yes + OpenGL : yes + qt : yes + vtk : yes + hdf5 : yes + med2 : yes + omniORB : yes + occ : yes + sip : yes + pyqt : yes + qwt : yes + doxygen : yes + graphviz : no + openpbs : no + lsf : no + Default ORB : omniORB + ---------------------------------------------- + \endcode + +If a software get a status "no", then it's not "seen" in the system: + +- the software is not installed, or +- the shell environment is not set correctly. + +In this example, the software programs graphviz, openpbs and lsf are not +installed (optional for most usages). + + +STEP 4 : + Building the binary files + + Execute make in the directory:: + + \code +$ make + \endcode + +STEP 5: + Installing binary files, scripts and documentation + + Execute install target in the directory:: + + \code +$ make install + \endcode + +\section S6_install Installing the SALOME components + +TInstalling a component is done by following the same +instructions as given for the KERNEL, replacing KERNEL by + (build_configure, configure, make, make install). + +You just have to be aware of the dependencies between components: + +- MED depends on KERNEL +- GEOM depends on KERNEL +- SMESH depends on KERNEL, MED, GEOM +- VISU depends on KERNEL, MED +- SUPERV depends on KERNEL + +For example, installing the component SMESH needs the previous +installation of the KERNEL component, and then the GEOM and MED components. + +The building process uses the variables _ROOT_DIR to +localize the dependant components. The variables must be set to the +install path directory of the components (ex: +KERNEL_ROOT_DIR=). + +In the above example, the three variables KERNEL_ROOT_DIR, +GEOM_ROOT_DIR and MED_ROOT_DIR have to be set before configuring the +building process of the SMESH component (STEP 3). + + +\section S7_install Runtime + +See SALOME_Application to define your own configuration of %SALOME and run it +on one or several computers. This is the recommended way of configuration. + +The following explains the general principles. + +To run the %SALOME platform, the procedure is: + +- set the shell environment to get acces to third-party softwares: + +\code +$ source prerequis.sh +\endcode + +- define the %SALOME configuration by setting the whole set of + variables _ROOT_DIR. Here, you just have to set the + kernel and the components you need:: + + \code +$ export KERNEL_ROOT_DIR= +$ export MED_ROOT_DIR= +$ ... + \endcode + +- define the CORBA configuration file by setting the variable + OMNIORB_CONFIG. This variable must be set to a writable file + path. The file may be arbitrary chosen and doesn't need to exist + before running. We suggest:: + + \code +$ export OMNIORB_CONFIG=$HOME/.omniORB.cfg + \endcode + +- run the %SALOME platform by executing the script runSalome: + + \code +$KERNEL_ROOT_DIR/bin/salome/runSalome + \endcode + +\section S8_install Suggestions and advices + +For convenience or customization, we suggest the following organisation: + +- chose and create a root directory for the %SALOME platform, say + . + +- install the third-party softwares in a sub-directory "prerequis" + +- install the %SALOME components in a sub-directory "SALOME2" + +- make personnal copies of the files prerequis.sh and runSalome in + : + + \code +$ cp /prerequis.sh /. +$ cp /bin/salome/runSalome /. + \endcode + + Edit the file prerequis.sh and adjust it to your own configuration. + +- define the SALOME2 configuration + + This step consists in setting the KERNEL_ROOT_DIR, the whole set of + variables _ROOT_DIR you need, and the OMNIORB_CONFIG + variable. + + We suggest to create a shell file envSalome.sh containing those + settings. Then the configuration consists in loading envSalome.sh in + the runtime shell: + +\code +$ source envSalome.sh +\endcode + +- When installed with this file organisation, running %SALOME is done + with the following shell commands:: + + \code + $ source /prerequis.sh + $ source /envSalome.sh + $ ./runSalome + \endcode +*/ diff --git a/doc/salome/kernel_resources.dox b/doc/salome/kernel_resources.dox new file mode 100644 index 000000000..6401e942b --- /dev/null +++ b/doc/salome/kernel_resources.dox @@ -0,0 +1,559 @@ +/*! + +\page kernel_resources SALOME Kernel resources for developer + +WORK in PROGRESS, INCOMPLETE DOCUMENT + + +\section S1_kernel_res Abstract + +This document describes the development environment for +C++ and Python. Makefiles generation and usage are +introduced in another document: "using the %SALOME +configuration and building system environment". +Development environment is intended here as: trace and +debug macros usage; %SALOME exceptions usage, in C++ and +Python; user CORBA exceptions usage, in C++ and Python, +with and without Graphical User Interface; some general +purpose services such as singleton, used for CORBA +connection and disconnection. + +\section S2_kernel_res Trace and debug Utilities + +During the development process, an execution log is +useful to identify problems. This log contains +messages, variables values, source files names and line +numbers. It is recommended to verify assertions on +variables values and if necessary, to stop the +execution at debug time, in order to validate all parts +of code. + +
    +
  1. +Two modes: debug and release + +The goal of debug mode is to check as many features as +possible during the early stages of the development +process. The purpose of the utilities provided in +%SALOME is to help the developer to add detailed traces +and check variables values, without writing a lot of code. + +When the code is assumed to be valid, the release mode +optimizes execution, in terms of speed, memory, and +display only user level messages. + +But, some informations must always be displayed in both +modes: especially messages concerning environment or +internal errors, with version identification. When an +end user is confronted to such a message, he may refer +to a configuration documentation or send the message to +the people in charge of %SALOME installation, or to the +development team, following the kind of error. +
  2. +
  3. +C++ Macros for trace and debug + +%SALOME provides C++ macros for trace and debug. These +macros are in: + +\code +KERNEL_SRC/src/SALOMELocalTrace/utilities.h +\endcode + +This file must be included in C++ source. Some +macros are activated only in debug mode, others are +always activated. To activate the debug mode, ``_DEBUG_`` +must be defined, which is the case when %SALOME +Makefiles are generated from configure, without +options. When ``_DEBUG_`` is undefined (release mode: +``configure --disable-debug --enable-production``), the +debug mode macros are defined empty (they do nothing). +So, when switching from debug to release, it is +possible (and recommended) to let the macro calls +unchanged in the source. + +All the macros generate trace messages, stored in a +circular buffer pool. %A separate %thread reads the +messages in the buffer pool, and, depending on options +given at %SALOME start, writes the messages on the +standard output, a file, or send them via CORBA, in +case of a multi machine configuration. + +Three informations are systematically added in front of +the information displayed: + +- the %thread number from which the message come from; + +- the name of the source file in which the macros is set; + +- the line number of the source file at which the macro + is set. + +
      +
    1. +Macros defined in debug and release modes +\n +INFOS_COMPILATION + + The C++ macro INFOS_COMPILATION writes on the trace + buffer pool informations about the compiling process: + + - the name of the compiler : g++, KCC, CC, pgCC; + + - the date and the time of the compiling processing process. + + This macro INFOS_COMPILATION does not have any + argument. Moreover, it is defined in both compiling + mode : _DEBUG_ and _RELEASE_. + + Example: + + \code +#include "utilities.h" +int main(int argc , char **argv) +{ + INFOS_COMPILATION; + ... +} +INFOS(str) + \endcode +\n +INFOS + + In both compiling mode _DEBUG_ and _RELEASE_, The C++ + macro INFOS writes on the trace buffer pool %the string + which has been passed in argument by the user. + + Example: + + \code +#include "utilities.h" +int main(int argc , char **argv) +{ + ... + INFOS("NORMAL END OF THE PROCESS"); + return 0; +} + \endcode + + Displays: + + \code +main.cxx [5] : NORMAL END OF THE PROCESS + \endcode +\n +INTERRUPTION(str) + + In both compiling mode _DEBUG_ and _RELEASE_, The C++ + macro INTERRUPTION writes on the trace buffer pool the + %string, with a special ABORT type. When the %thread in + charge of collecting messages finds this message, it + terminates the application, after message treatment. + +IMMEDIATE_ABORT(str) + + In both compiling mode _DEBUG_ and _RELEASE_, The C++ + macro IMMEDIATE_ABORT writes the message str immediately on + standard error and exits the application. Remaining + messages not treated by the message collector %thread + are lost. + +
    2. +
    3. +Macros defined only in debug mode +\n +MESSAGE(str) + + In _DEBUG_ compiling mode only, the C++ macro MESSAGE + writes on the trace buffer pool the %string which has + been passed in argument by the user. In _RELEASE_ + compiling mode, this macro is blank. + + Example: + + \code +#include "utilities.h" +#include + +using namespace std; + +int main(int argc , char **argv) +{ + ... + const char *str = "Salome"; + MESSAGE(str); + ... const string st; + st = "Aster"; + MESSAGE(c_str(st+" and CASTEM")); + return 0; +} + + \endcode + + Displays: + + \code +- Trace main.cxx [8] : Salome +- Trace main.cxx [12] : Aster and CASTEM + \endcode + +\n +BEGIN_OF(func_name) + + In _DEBUG_ compiling mode, The C++ macro BEGIN_OF + appends the %string "Begin of " to the one passed in + argument by the user and displays the result on the + trace buffer pool. In _RELEASE_ compiling mode, this + macro is blank. + + Example: + + \code +#include "utilities.h" +int main(int argc , char **argv) +{ + BEGIN_OF(argv[0]); + return 0; +} + \endcode + + Displays: + + \code + - Trace main.cxx [3] : Begin of a.out + \endcode +\n +END_OF(func_name) + + In _DEBUG_ compiling mode, The C++ macro END_OF appends + the %string "Normal end of " to the one passed in + argument by the user and displays the result on the + trace buffer pool. In _RELEASE_ compiling mode, this + macro is blank. + + Example: + + \code +#include "utilities.h" +int main(int argc , char **argv) +{ + END_OF(argv[0]); + return 0; +} + \endcode + + Displays: + + \code +- Trace main.cxx [4] : Normal end of a.out + \endcode +\n +SCRUTE(var) + + In _DEBUG_ compiling mode, The C++ macro SCRUTE + displays its argument which is an application variable + followed by the value of the variable. In _RELEASE_ + compiling mode, this macro is blank. + + Example: + + \code +#include "utilities.h" +int main(int argc , char **argv) +{ + const int i=999; + if( i > 0 ) SCRUTE(i) ; i=i+1; + return 0; +} + \endcode + + Displays: + + \code +- Trace main.cxx [5] : i=999 + \endcode +\n +ASSERT(condition) + + In _DEBUG_ compiling mode only, The C++ macro ASSERT + checks the expression passed in argument to be not + NULL. If it is NULL the condition is written with the + macro INTERRUPTION (see above). The process exits after + trace of this last message. In _RELEASE_ compiling + mode, this macro is blank. N.B. : if ASSERT is already + defined, this macro is ignored. + + Example: + + \code +#include "utilities.h" +... +const char *ptrS = fonc(); +ASSERT(ptrS!=NULL); +cout << strlen(ptrS); +float table[10]; +int k; +... +ASSERT(k<10); +cout << table[k]; + \endcode + +
    4. +
    +
  4. +
+ +\section S3_kernel_res Exceptions + +
    +
  1. +C++ exceptions: class SALOME_Exception + +
      +
    1. +definition + +The class SALOME_Exception provides a generic method to +send a message, with optional source file name and line +number. This class is intended to serve as a base class +for all kinds of exceptions %SALOME code. All the +exceptions derived from SALOME_Exception could be +handled in a single catch, in which the message +associated to the exception is displayed, or sent to a +log file. + +The class SALOME_Exception inherits its behavior from +the STL class exception. +
    2. +
    3. +usage + +The header %SALOME/src/utils/utils_SALOME_Exception.hxx +must be included in the C++ source, when raised or trapped: + +\code +#include "utils_SALOME_Exception.hxx" +\endcode + +The SALOME_Exception constructor is: + +\code +SALOME_Exception( const char *text, + const char *fileName=0, + const unsigned int lineNumber=0 ); +\endcode + +The exception is raised like this: + +\code +throw SALOME_Exception("my pertinent message"); +\endcode + +or like this: + +\code +throw SALOME_Exception(LOCALIZED("my pertinent message")); +\endcode + +where LOCALIZED is a macro provided with +``utils_SALOME_Exception.hxx`` which gives file name and +line number. + +The exception is handled like this: + +\code + try +{ + ... +} +catch (const SALOME_Exception &ex) +{ + cerr << ex.what() < +
    +
  2. +
  3. +CORBA exceptions + +
      +
    1. +definition + +The idl SALOME_Exception provides a generic CORBA +exception for %SALOME, with an attribute that gives an +exception type,a message, plus optional source file +name and line number. + +This idl is intended to serve for all user CORBA +exceptions raised in %SALOME code, as IDL specification +does not support exception inheritance. So, all the +user CORBA exceptions from %SALOME could be handled in a +single catch. + +The exception types defined in idl are: + + - COMM CORBA communication problem, + + - BAD_PARAM Bad User parameters, + + - INTERNAL_ERROR application level problem (often irrecoverable). + +CORBA system and user exceptions already defined in the +packages used within %SALOME, such as OmniORB +exceptions, must be handled separately. + +
    2. +
    3. +usage +
        +
      1. +CORBA servant, C++ + + The CORBA Server header for SALOME_Exception and a + macro to throw the exception are provided with the + header ``KERNEL_SRC/src/Utils/Utils_CorbaException.hxx``: + + \code +#include "Utils_CorbaException.hxx" + \endcode + + The exception is raised with a macro which appends file + name and line number: + + \code +if (myStudyName.size() == 0) + THROW_SALOME_CORBA_EXCEPTION("No Study Name given", + SALOME::BAD_PARAM); + \endcode + +
      2. +
      3. +CORBA Client, GUI Qt C++ + + NO MORE AVAILABLE in %SALOME 3.x + + The CORBA Client header for SALOME_Exception and a Qt + function header that displays a message box are + provided in: + + ``KERNEL_SRC/src/SALOMEGUI/SALOMEGUI_QtCatchCorbaException.hxx`` + + \code +#include "SALOMEGUI_QtCatchCorbaException.hxx" + \endcode + + %A typical exchange with a CORBA Servant will be: + + \code +try +{ + ... // one ore more CORBA calls +} + +catch (const SALOME::SALOME_Exception & S_ex) +{ + QtCatchCorbaException(S_ex); +} + \endcode + +
      4. +
      5. +CORBA Client, C++, without GUI + + Nothing specific has been provided to the developer + yet. See the idl or the Qt function + SALOMEGUI_QtCatchCorbaException.hxx to see how to get + the information given by the exception %object. + +
      6. +
      +
    4. +
    +
+ +\section S4_kernel_res Miscellaneous tools + +
    +
  1. +Singleton +
      +
    1. +Definition + +%A singleton is an application data which is created and +deleted only once at the end of the application +process. The C++ compiler allows the user to create a +static singleton data before the first executable +statement. They are deleted after the last statement execution. + +The ``SINGLETON_`` template class deals with dynamic +singleton. It is useful for functor objects. For +example, an %object that connects the application to a +system at creation and disconnects the application at deletion. + +
    2. +
    3. +Usage + +To create a single instance of a POINT %object: + +\code +# include "Utils_SINGLETON.hxx" +... +POINT *ptrPoint=SINGLETON_::Instance() ; +assert(ptrPoint!=NULL) ; +\endcode + +No need to delete ptrPoint. Deletion is achieved +automatically at exit. If the user tries to create more +than one singleton by using the class method +SINGLETON_::Instance(), the pointer is returned +with the same value even if this is done in different +functions (threads ?): + +\code +POINT *p1=SINGLETON_::Instance() ; +... +POINT *p2=SINGLETON_::Instance() ; + +assert(p1==p2) +\endcode + +
    4. +
    5. +Design description + +Here are the principles features of the singleton +design: + +- the user creates an %object of class TYPE by using the + class method ``SINGLETON_::Instance()`` which + returns a pointer to the single %object ; + +- to create an %object, ``SINGLETON_::Instance()`` + uses the default constructor of class TYPE ; + +- at the same time, this class method creates a + destructor %object which is added to the generic list + of destructor objects to be executed at the end of + the application (atexit) ; + +- at the end of the application process all the + deletions are performed by the ``Nettoyage()`` C function + which executes the destruction objects end then + deletes the destructions objects themselves ; + +- the ``Nettoyage()`` C function using ``atexit()`` C function + is embedded in a static single %object ``ATEXIT_()``. + +
    6. +
    +
  2. +
+ +*/ diff --git a/doc/salome/kernel_services.dox b/doc/salome/kernel_services.dox new file mode 100644 index 000000000..d363c84cf --- /dev/null +++ b/doc/salome/kernel_services.dox @@ -0,0 +1,236 @@ +/*! + \page KERNEL_Services KERNEL Services for end user (Python interface) + +WORK in PROGRESS, INCOMPLETE DOCUMENT + +In a %SALOME application, distributed components, servers and clients use +the CORBA middleware for comunication. CORBA interfaces are defined via idl +files. All the different CORBA interfaces are available for users in Python, +see CORBA interfaces below. + +For some general purpose services, CORBA interfaces have been encapsulated +in order to provide a simple interface (encapsulation is generally done in +C++ classes, and a Python SWIG interface is also generated from C++, to +ensure a consistent behavior between C++ modules and Python modules or user +script). + +\section S1_kernel_ser General purpose services + +
    +
  1. +%SALOME services access from a Python shell + +See \ref SALOME_Application for detailed instructions to launch a Python +interpreter with full acces to the %SALOME environment and services. + +You can use the embedded Python interpreter in Grahic User Interface, or an +external interpreter, with: + +\code +./runSession +python +\endcode + +In either cases, %SALOME services access is done with: + +\code +import salome +salome.salome_init() +\endcode + +In the embedded interpreter, it is already done, but there is no problem to +do it several times, so it is preferable to add these instructions +systematically in your scripts, to allow them to work in all configurations. + +
  2. +
  3. +Container and component instanciation + +See LifeCycleCORBA for the C++ interface (Python interface obtained with SWIG +is very similar). + +In the following example, a test component provided in KERNEL is launched +in the local container, "FactoryServer", created when %SALOME starts: + +\code +import salome +salome.salome_init() + +import LifeCycleCORBA +lcc = LifeCycleCORBA.LifeCycleCORBA() +obj=lcc.FindOrLoad_Component("FactoryServer","SalomeTestComponent") + +import Engines +comp=obj._narrow(Engines.TestComponent) + +comp.Coucou(1) +\endcode + +The answer is something like: + +\code +'TestComponent_i : L = 1' +\endcode + +The _narrow() instruction is not always mandatory in Python, but sometimes +useful to be sure you have got the right type of %object. Here, Testcomponent +interface is defined in CORBA module Engines. With this example, it works also +without the _narrow() instruction: + +\code + obj.Coucou(1) +\endcode + +In the next example, a component instance is created in a specific Container +defined by it's computer hostname and it's name. Here we use the local +computer. Note that in Utils_Identity, getShortHostName() gives the short +hostname of the computer, without domain suffixes, which is used in %SALOME. +The container process is created here if it does not exists, and a new +component instance is created: + +\code +import salome +salome.salome_init() +import LifeCycleCORBA +lcc = LifeCycleCORBA.LifeCycleCORBA() + +import Utils_Identity +host = Utils_Identity.getShortHostName() + +import Engines +params={} +params['hostname']=host +params['container_name']='myContainer' +comp=lcc.LoadComponent(params,'SalomeTestComponent') +comp.Coucou(1) +\endcode + +If you want to get a list of containers and component instances, client %object +from orbmodule provides a list: + +\code +import orbmodule +clt=orbmodule.client() +clt.showNS() +\endcode + +The list looks like: + +\code +Logger. +ContainerManager.object +Containers.dir + cli70ac.dir + FactoryServerPy.object + SuperVisionContainer.object + FactoryServer.object + FactoryServer.dir + SalomeTestComponent_inst_1.object + myContainer.object + myContainer.dir + SalomeTestComponent_inst_1.object + SalomeTestComponent_inst_2.object +Registry.object +Kernel.dir + ModulCatalog.object + Session.object +Study.dir + Study2.object + extStudy_1.object + extStudy_2.object + extStudy_3.object +myStudyManager.object +SalomeAppEngine.object +\endcode + +
  4. +
  5. +File transfer service + +See SALOME_FileTransferCORBA for the C++ interface (Python interface obtained with +SWIG is very similar). + +The following example shows how to tranfer a file from a remote host to the +client computer. Remote hostname is 'cli76cc', we would like to copy +'tkcvs_8_0_3.tar.gz' from remote to local computer. %A full pathname is +required. %A container is created on remote computer if it does not exist, +to handle the file transfer: + +\code +import salome +salome.salome_init() + +import LifeCycleCORBA +remotefile="/home/prascle/tkcvs_8_0_3.tar.gz" +aFileTransfer=LifeCycleCORBA.SALOME_FileTransferCORBA('cli76cc',remotefile) +localFile=aFileTransfer.getLocalFile() +\endcode + +
  6. +
  7. +CORBA Naming service access + +See SALOME_NamingService for the C++ interface. The Python interface +SALOME_NamingServicePy is not yet derived from the C++ interface and offers +only the most useful functions. + +
  8. +
  9. +Batch services + +See \ref batch_page documentation (in french only). + +
  10. +
+ +\section S2_kernel_ser All IDL Interfaces + +
    +
  1. +Containers and component life cycle, File transfer service + +- Engines : engines CORBA module. +- Engines::Component : generic component interface. All %SALOME components inherit this interface. +- Engines::Container : host for C++ and Python components components instances +- Engines::fileTransfer : agent for file transfer created by a container copy a local file to a distent client +- Engines::fileRef : reference to a file, used by a container for file transfers +- Engines::ContainerManager : unique instance, in charge of container creation on remote computers +- Engines::MPIContainer : an exemple of parallel implementation for containers and components +- Engines::MPIObject + +
  2. +
  3. +Study management + +- SALOMEDS : SALOMEDS CORBA module +- SALOMEDS.idl +- SALOMEDS_Attributes.idl + +
  4. +
  5. +High speed transfer, object life cycle, exceptions, GUI interface... + +- SALOME : %SALOME CORBA module +- SALOME_Comm.idl +- SALOME_GenericObj.idl +- SALOME_Exception +- SALOME_Session.idl + +
  6. +
  7. +Miscelleanous + +- SALOME_ModuleCatalog +- SALOME_RessourcesCatalog +- SALOME_Registry.idl +- Logger.idl + +Other idl for test purposes +\n +- nstest.idl +- SALOME_TestComponent.idl +- SALOME_TestModuleCatalog.idl +- SALOME_TestMPIComponent.idl +- TestNotif.idl + +*/ diff --git a/doc/salome/main.dox b/doc/salome/main.dox new file mode 100644 index 000000000..7515c353c --- /dev/null +++ b/doc/salome/main.dox @@ -0,0 +1,82 @@ +/*! \mainpage SALOME KERNEL Reference Documentation + \image html kernel_about_4.png + + \section S1_main Introduction + + Welcome to the %SALOME KERNEL documentation ! + + Following your kind of usage of %SALOME, you will find some specific + introductory documentation, listed below. + + \section S2_main End user + +
      +
    1. + How to configure a %SALOME application + \n The end user may have to configure his own %SALOME application by selection of a + subset of availables %SALOME modules. He also may want to install his + application on several computers. + See \subpage SALOME_Application to define your own configuration of %SALOME and run it + on one or several computers. This is the recommended way of configuration. +
    2. +
    3. + How to launch %SALOME in a %SALOME application + \n See \ref SALOME_Application. +
    4. +
    5. + How to use KERNEL services in Python scripts + \n The %SALOME KERNEL offers a list of services available in Python. See \subpage KERNEL_Services. +
    6. +
    + + \section S3_main Application Integrator + + Applications integrators are in charge of configuration and installation of + specific %SALOME applications over a local network. Application Integrators + built %SALOME modules binaries from sources tarballs. + +
      +
    1. + How to install %SALOME + \n See \subpage INSTALL for general information on required configuration and + prerequisites, compilation procedure, setting environment principles. +
    2. +
    3. + How to configure a %SALOME application + \n See \ref SALOME_Application to define your own configuration of %SALOME and run it + on one or several computers. This is the recommended way of configuration. +
    4. +
    + + \section S4_main Module maintainer + + Module maintainers are in charge of the development and debug of the %SALOME + modules. Each %SALOME module is stored in a CVS base. CVS bases are organised + in separate branches for developments and debug. All official or development + releases are identified by a CVS tag. + +
      +
    1. + Source code structuration and Unit Tests + \n See \subpage UnitTests for general information on code directories structure, + unit tests associated to the different kind of classes, and how to run + the unit tests. +
    2. +
    3. + Some development utilities + \n See \subpage kernel_resources for information on basic utilities for C++ and Python + development, like trace and debug, exceptions, singleton. +
    4. +
    + + \section S5_main SALOME programming model + + You will find in the next pages informations about + specific points of %SALOME Kernel : + + - \subpage dsc_page : DSC documentation page. + - \subpage salome_file_page : Salome_file documentation page. + - \subpage batch_page : BATCH documentation page. + +*/ + diff --git a/doc/salome/salome_application.dox b/doc/salome/salome_application.dox new file mode 100644 index 000000000..d970338a3 --- /dev/null +++ b/doc/salome/salome_application.dox @@ -0,0 +1,377 @@ +/*! + \page SALOME_Application SALOME Application Concept + + Configuration for one or more computers + + + **WORK in PROGRESS, INCOMPLETE DOCUMENT** + +The following explains how to configure your own application with your list of +modules, how to define and run this application on one or more computers. + +\section S1_sal_appl General principles + +%A %SALOME application is defined by a set of modules (GEOM, SMESH, ASTER...). + +%A %SALOME User can define several %SALOME Applications. These applications are +runnable from the same user account. These applications may share the same +KERNEL and modules. Thus, the application configuration is independant of +KERNEL and must not be put in KERNEL_ROOT_DIR. + +Furthermore, prerequisites may not be the same on all the applications. + +%A %SALOME Session can run on a several computers. + +Binary modules and prerequisites are installed on the different computers. +There is no need to have all the modules on each computer (the minimum is +KERNEL). + +There is no need of standardization or centralised information on the details +of configuration on each computer (PATH, LD_LIBRARY_PATH, environment +variables) provided the application modules are version - compatible. Details +of configuration stay private to the computer, and are held by scripts on each +computer. + +There is no hierarchy between the computers (for example only one master +computer used to launch application). + +The %SALOME user has an account on all the computers. Access between +account@computer is via rsh or ssh and must be configured for use without +password (key exchange for ssh). Account may be different on each +computer. + +\section S2_sal_appl Application Directory + +There are two ways for creation of an application directory, the recommended way is +the second, easier to configure. + +
      +
    1. + First way - references to different module directories + +The script createAppli.sh in ${KERNEL_ROOT_DIR}/bin/salome creates an +application directory with the given path in parameter. The path given, ${APPLI}, is +relative to ${HOME}. + +The directory is only a skeleton, the user has to edit several files to +configure his own application. These files are described after, the list is: + +- env.d/atFirst.sh +- env.d/envProducts.sh +- env.d/envSALOME.sh +- CatalogResources.xml +- SALOMEApp.xml + +
    2. +
    3. + Second and easiest way - one single virtual install directory + +The user must create a %SALOME application configuration file by modifying a +copy of ${KERNEL_ROOT_DIR}/bin/salome/config_appli.xml. +The file describes the list of %SALOME modules used in the application, with +their respective installation path. The configuration file also defines the +path of an existing script which sets the %SALOME prerequisites, +and optionnaly, the path of samples directory (SAMPLES_SRC). +The following command:: + +\code +python /bin/salome/appli_gen.py --prefix= --config= +\endcode + +creates a virtual installation of %SALOME in the application directory ${APPLI} +(bin, lib, doc, share...), with, for each file (executable, script, data, +library, resources...), symbolic links to the actual file. +Note: it is recommended to set the environment for %SALOME prerequisites +before invoking the above command, in order to use the same python as SALOME, +otherwise installation may be wrong + +Providing an existing script for %SALOME prerequisites (the same one +used for modules compilation, or given with the modules installation), the +installation works without further modification for a single computer (unless +some modules needs a special environment not defined in the above script). +For a distributed application (several computers), one must copy and adapt +CatalogResources.xml from ${KERNEL_ROOT_DIR}/bin/salome/appliskel (see below). +
    4. +
    + +\section S3_sal_appl General rules + +Directory ${APPLI} must be created on each computer of the application. +The easiest way is to use the same relative path (to ${HOME}) on each computer. +(Sometimes it is not possible to use the same path everywhere, for instance +when ${HOME} is shared with NFS, so it is possible to define different path +following the computers). + +The ${APPLI} directory contains scripts for environment and runs. Environment +scripts must be configured (by the user) on each computer. All the environment +scripts are in the ${APPLI}/env.d directory. + +The script ${APPLI}/envd sources **all** the files (\*.sh) in ${APPLI}/env.d +in alphanumeric order (after edition, think to remove backup files). the envd +script is used by run scripts. + +
      +
    1. +env.d scripts + +With the first way of installation, each user **must define** his own +configuration for these scripts, following the above rules. +With the virtual installation (second way, above), env.d +scripts are built automatically. + + **The following is only an example proposed by createAppli.sh, (first way of installation) not working as it is**. + +- atFirst.sh + Sets the computer configuration not directly related to %SALOME, + like useful tools, default PATH. + +- envProducts.sh + Sets the %SALOME prerequisites. + +- envSALOME.sh + Sets all the MODULE_ROOT_DIR that can be used in the %SALOME application. + + SALOMEAppConfig is also defined by: + +\code +export SALOMEAppConfig=${HOME}/${APPLI} +\endcode + + where SALOMEAppConfig designates the directory containing SALOMEApp.xml. + Note that ${APPLI} is already defined by the calling scripts when + env.d/envSALOME.sh is sourced. +
    2. +
    3. +User run scripts + +The %SALOME user can use 4 scripts: + +- runAppli + Launches a %SALOME Session + (similar to ${KERNEL_ROOT_DIR}/bin/salome/runSalome but with a different + name to avoid confusions). See parameters below. + +- runSession + Launches a shell script in the %SALOME application environment, with access + to the current (last launched) %SALOME session (naming service), if any. + Without arguments, the script is interactive. With arguments, the script + executes the command in the %SALOME application environment. + +- runConsole + Gives a python console connected to the current %SALOME Session. + It is also possible to use runSession, then python. + +- runTests + Similar to runSession, used for unit testing, but runSession tries to use an + already existing naming service definition from a running session (hostname + and port number), and runTests defines a new configuration for naming service + (new port number). +
    4. +
    5. +%SALOME internal run scripts + +- envd + Sets %SALOME application environment, envd is sourced by other scripts. + +For remote calls, %SALOME uses one script. + +- runRemote.sh + This script is mainly used to launch containers. The first 3 arguments + define the hostname and port userd for naming service, plus a working directory, the remaining + arguments define the command to execute. +
    6. +
    7. +Other configuration files + +- SALOMEApp.xml + This file is similar to the default given + in ${GUI_ROOT_DIR}/share/SALOME/resources/gui + + +- CatalogRessources.xml + This files describes all the computers the application can use. The given + example is minimal and suppose ${APPLI} is the same relative path + to ${HOME}, on all the computers. %A different directory can be set on a + particular computer with a line: + +\code +appliPath="my/specific/path/on/this/computer" +\endcode + +
    8. +
    + +\section S4_sal_appl Examples of use + +
      +
    1. +Launch a %SALOME session with a GUI interface + +Launch is done with a command like:: + +\code +./runAppli --logger +\endcode + +The --logger option means here : collect all the traces from the all the +distributed process, via CORBA, in a single file : logger.log. + +There are a lot of options, a complete list is given by:: + +\code +./runAppli --help +\endcode + +Note that, without argument, runAppli is a non interactive Python application, +and, with arguments, runAppli is an interactive Python interpreter. + +Several options are already defined by default in SALOMEApp.xml files. Optional +arguments given in the command override the SALOMEApp.xml configuration. + +Several sessions can run simultaneously, each session use a different port for +CORBA naming service, so the sessions are totally separated from each other. + +When the GUI is closed, the different %SALOME servers are still running. +
    2. +
    3. +Close a %SALOME session, kill all the servers + +Inside the interactive python interpreter you get when you use runAppli +with arguments, you can kill all the servers of your session with:: + +\code +>>> killLocalPort() +\endcode + +or the servers of all the sessions with:: + +\code +>>> killAllPorts() +\endcode + +If you have no active Python interpreter connected to your session, you can +kill all the %SALOME servers of **all the sessions** on a given computer:: + +\code +./runSession killSalome.py +\endcode + +Remember! it's the same idea in Windows (R) operating system (Microsoft and Windows are either registered trademarks or trademarks of + Microsoft Corporation in the United States and/or other countries) : +use the start menu to stop... + +When you use only one session at a time, you don't need more. + +To kill a given session (when several session are running), one needs +the naming service port number:: + +\code +./runSession killSalomeWithPort 2810 +\endcode + +Note that the port number of the last launched session can be found on Linux, +in the prompt, within a runSession shell (see below). + +It is also possible to get the Naming Service host and port number of +the last launched session with:: + +\code +./runSession NSparam.py +\endcode + +
    4. +
    5. +Launch a %SALOME session without GUI interface + +This is used to launch a %SALOME Python script without GUI +(no GUI %server = SALOME_session_server) + +Example of script (test_session_geom.py): + +\code +import salome_session +salome_session.startSession(modules=["GEOM"]) +import GEOM_usinggeom +raw_input("Press a key and the servers will be killed ...") +\endcode + +This script is run in a non interactive way with:: + +\code +./runSession python test_session_geom.py +\endcode + +All the process are automatically killed when Python is closed +(with SALOME_session delete). +
    6. +
    7. +Add an external Python interpretor to a running session + +It's often easier to develop and try Python scripts outside the GUI embedded +Python interpreter. Imagine, for instance, you are writing a script involving +geometry and mesh modules. +first, launch a %SALOME session with gui, then, on another terminal:: + +\code +./runSession +python +\endcode + +Import %SALOME module. salome_init() without arguments creates a new study +in the running session (note: SALOME_init(n) attachs to a running session whose +studyId is n):: + +\code +import salome +salome.salome_init() +\endcode + +An example of script given with SMESH:: + +\code +import ex01_cube2build +\endcode + +It is possible to connect the GUI interface to the study created in the above +script with the file/connect menu, then browse study and display objects. +Further modifications on study can be done either with GUI or external script +(use refresh popup in GUI %object browser to see study modifications generated +by the external script). **AVOID modifications with GUI when a Python script +is running**. Not all the modules are protected against concurrent actions... +
    8. +
    9. +Different uses of the runSession shell interpreter + +runSession invoked without arguments gives an interactive shell with the full +environment of %SALOME (PATH, LD_LIBRARY_PATH, PYTHONPATH, other variables). +If there are running sessions of the same %SALOME application, runSession +connects to the last launched session (i.e. gets the naming service references +of the session: hostname and port) + +On Linux, the shell prompt (bash) gives information on naming service +references, hostname and port:: + +\code +[NS=cli76cc:2811]prascle@cli76cc:~/SALOME2/Run/Virtual$ +\endcode + +If there is no running session, prompt looks like:: + +\code +[NS=:]prascle@cli76cc:~/SALOME2/Run/Virtual$ +\endcode + +runSession is useful to launch any script or program which needs the complete +%SALOME environment, with or without a session already running. +For instance, to launch the ddd debugger interface on the gui %server, first +launch a %SALOME session with gui, then, on another terminal:: + +\code +./runSession ddd +\endcode + +Then attach to the running SALOME_Session_Server process. +
    10. +
    + +*/ diff --git a/doc/salome/salome_file.dox b/doc/salome/salome_file.dox new file mode 100644 index 000000000..dffb378b9 --- /dev/null +++ b/doc/salome/salome_file.dox @@ -0,0 +1,123 @@ +/*! + +\page salome_file_page Salome_file + +This page introduces the Salome_file feature. Salome_file is based on the +SALOME_FileTransfer. It extends it to enable a higher model for managing files into +%SALOME applications. + +\section S1_Salome_file Principles + +Salome_file is a CORBA %object. It's role is to managed many system files. When a Salome_file +is created, no files are managed. Then, files are added using Salome_file interface. %A file is represented +by a name and a path. + +There is two different cases when a file is added : + +- Local file : the file added exists or it will be created by the user with the path and the name used in +its registration. +- Distributed file : the file added exists into a distributed localization. + +To be able to get a distributed file, the Salome_file has to be connected with an another Salome_file that +managed this file. This distributed Salome_file could be located into a distributed resource. + +\section S2_Salome_file Simple example + +This section shows a simple example of the use of Salome_file. The objective is to create +two Salome_file; one is managing a local file, the other is managing a distributed file. +Then, these Salome_files are connected to enable the copy of the real file gbetween the two Salome_files. + +Firstly, two Salome_files are created : + +\code +#include "Salome_file_i.hxx" + +int main (int argc, char * argv[]) +{ + Salome_file_i file_source; + Salome_file_i file_dest; + +\endcode + +Secondly, the real files are registered into the Salome_files. + +\code + file_source.setLocalFile("/bin/cat"); + file_dest.setDistributedFile("/tmp/cat_copy"); +\endcode + +Thirdly, we connect the destination file with the source file : + +\code + file_dest.connect(file_source); +\endcode + +Finally, the file is sended using Salome_file interface. + +\code + file_dest.recvFiles(); + // Status check + state = file_dest.getSalome_fileState(); + print_state(state); // You have to implement this function. +}; +\endcode + +\section S3_Salome_file Advanced example + +This advanced example illustrates a part of the Salome_file API dedicated +for situations where multiple files are managed. + +This is the situation : + +\code + +#include "Salome_file_i.hxx" + +int main (int argc, char * argv[]) +{ + Salome_file_i file_source_a; + Salome_file_i file_source_b; + Salome_file_i file_dest; + + file_source_a.setLocalFile("/bin/cat"); + file_source_a.setLocalFile("/bin/ls"); + + file_source_b.setLocalFile("/bin/echo"); + file_source_b.setLocalFile("/bin/cp"); + + file_dest.setDistributedFile("/tmp/cat_copy"); + file_dest.setDistributedFile("/tmp/echo_copy"); +\endcode + +There is two problems in this case. + +The first problem is in the file_dest Salome_file, there is two files. If +the method connect is used, the Salome_file cannot know if the reference is for cat_copy or +echo_copy. Indeed echo_copy could be provided by another Salome_file that for cat_copy. + +The second problem comes from the two files of file_source_a Salome_file. Indeed when connect is used, +there is no information about the choice of the source file into the source Salome_file. For +cat_copy, did the used want cat or echo ? + +To avoid these cases, Salome_file API provides advanced methods : + +\code + file_dest.connectDistributedFile("cat_copy", file_source_a); + file_dest.setDistributedSourceFile("cat_copy", "cat"); + + file_dest.connectDistributedFile("cat_echo", file_source_b); + file_dest.setDistributedSourceFile("cat_echo", "echo"); + + file_dest.recvFiles(); + // Status check + state = file_dest.getSalome_fileState(); + print_state(state); // You have to implement this function. +}; +\endcode + +\section S3_Salome_file Using Salome_file into %SALOME services + +Currently you can't use Salome_file into YACS schema. In the next version of %SALOME, +files ports will be available to connect output files to input files. + +*/ diff --git a/doc/salome/tui/KERNEL/sources/kernel_about_4.png b/doc/salome/tui/KERNEL/sources/kernel_about_4.png new file mode 100644 index 000000000..5c9c09a79 Binary files /dev/null and b/doc/salome/tui/KERNEL/sources/kernel_about_4.png differ diff --git a/doc/salome/unittests.dox b/doc/salome/unittests.dox new file mode 100644 index 000000000..fc5ebdd47 --- /dev/null +++ b/doc/salome/unittests.dox @@ -0,0 +1,207 @@ +/*! + +\page UnitTests Source code structuration and Unit Tests + +WORK in PROGRESS, INCOMPLETE DOCUMENT + +You will find here general information on code directories structure, +unit tests associated to the different kind of classes, and how to run +the unit tests. + +\section S1_unit SALOME KERNEL source code structuration + +
      +
    1. General structure of KERNEL_SRC + +- KERNEL_SRC : + Some README files and configuration tools for build + +- KERNEL_SRC/adm_local : + Part of the configuration files, other modules have a directory with the + same name. Not used in KERNEL. + +- KERNEL_SRC/bin : + Python and shell scripts used at run time. + Kit to install a %SALOME Application. + +- KERNEL_SRC/doc : + Kit for KERNEL end user documentation production: + public interfaces, Python, CORBA. + Integrator and Developper documentation. + +- KERNEL_SRC/idl : + All CORBA interfaces from KERNEL are regrouped here. + +- KERNEL_SRC/resources : + Configuration files for servers (examples). + Interfaces definitions for KERNEL test components. + +- KERNEL_SRC/salome_adm : + Configuration files used by autotools (M4 macros & co.) + +- KERNEL_SRC/src : + The source code (C++ and Python) + +
    2. +
    3. +Directory src: C++ and Python source code + +
        +
      1. +Basic services non related to CORBA + +- Basics + %A set of general purpose C++ services, not related to CORBA. + Some general purpose services that are in Utils directory (CORBA related), + are progressivley moved here, as they are not related to CORBA. + + +- SALOMELocalTrace + %A multithread trace system that allows message tracing on standard error + or a file. + +- CASCatch + Exceptions and signal handler. + +- HDFPersist + %A C++ interface to HDF. + +
      2. + +
      3. +Basic CORBA services + +- Logger : + %A CORBA %server that collects the trace messages from differents CORBA + process. + +- SALOMETraceCollector : + %A multithread trace system derived from SALOMELocalTrace, that sends messages + to Logger %server via CORBA. + +- Utils : + %A set of general purpose services related to CORBA, such as basic CORBA + exception system. See also Basics directory above. + +- NamingService : + C++ and Python interfaces to name, store and retrieve CORBA objects + +- GenericObj : + %A generic CORBA interface for CORBA objects, to count distributed references, + and to allow destruction by client. + +
      4. +
      5. +Miscellaneous CORBA servers + +- %Registry : + Implements SALOME_registry.idl. + Provides a CORBA %server library and a separate %server program. + +- ModuleCatalog : + Implements SALOME_moduleCatalog.idl. + Provide a CORBA %server library and separate %server and client programs. + +- ModuleGenerator : + Tool to generate a module catalog from CORBA idl + +- ResourcesManager : + library included in container %server + +- Notification : + library included in differents servers (container) + +- NOTIFICATION_SWIG + +
      6. + +
      7. +CORBA Containers for %SALOME Modules + +- Container + +- TestContainer + +- LifeCycleCORBA + +- LifeCycleCORBA_SWIG + +
      8. + +
      9. +STUDY %server and related interfaces and tools + +- SALOMEDSClient + +- TOOLSDS + +- SALOMEDSImpl + +- SALOMEDS + +
      10. +
      11. +Python interface to %SALOME + +- KERNEL_PY + +
      12. +
      13. +Efficient CORBA transfer services + +- Communication + +- Communication_SWIG + +
      14. +
      15. +%A Parallel container with MPI + +- MPIContainer + +- TestMPIContainer + +
      16. +
      17. +Batch interface library + +- Batch + +- Batch_SWIG + +
      18. +
      19. +Unit tests + +- UnitTests + +
      20. +
      +
    4. +
    + +\section S2_unit Tools and principles used for Unit testing + +**TO BE COMPLETED** + +Unit Testing rely on cppunit package for C++ testing, and on unittest module +for Python. See these products for general principles of unit testing. + +The cppunit package is optional. When the prerequisite is detected, the unit +tests are compiled. + +Unit Tests sources are in directories Test under the src/directories +containing the classes to test. + +Test are ordered following the order of directories given above. + +Tests can be run as a whole, or for a particular directory. In this case, only +a partial test is run (the classes to test, and the classes used, i.e. the +preceding test directories). + + +Today, only some tests are written as an example. There are not yet python +scripts in KERNEL_SRC, but it's a matter of days, there are working scripts +to test LifeCycleCORBA_SWIG interface. + +*/ diff --git a/src/Batch/Batch_BatchManager_eClient.cxx b/src/Batch/Batch_BatchManager_eClient.cxx new file mode 100644 index 000000000..41ce47c2e --- /dev/null +++ b/src/Batch/Batch_BatchManager_eClient.cxx @@ -0,0 +1,235 @@ +// Copyright (C) 2005 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 +// +/* + * BatchManager_eLSF.cxx : emulation of LSF client + * + * Auteur : Bernard SECHER - CEA DEN + * Mail : mailto:bernard.secher@cea.fr + * Date : Thu Apr 24 10:17:22 2008 + * Projet : PAL Salome + * + */ + +#include +#include +#include +#include +#include "Batch_BatchManager_eClient.hxx" + +namespace Batch { + + BatchManager_eClient::BatchManager_eClient(const Batch::FactBatchManager * parent, const char* host, const char* protocol, const char* mpiImpl) : BatchManager(parent, host), _protocol(protocol), _username("") + { + // instanciation of mpi implementation needed to launch executable in batch script + _mpiImpl = FactoryMpiImpl(mpiImpl); + } + + // Destructeur + BatchManager_eClient::~BatchManager_eClient() + { + // Nothing to do + delete _mpiImpl; + } + + void BatchManager_eClient::exportInputFiles(const Job& job) throw(EmulationException) + { + int status; + Parametre params = job.getParametre(); + Versatile V = params[INFILE]; + Versatile::iterator Vit; + string command; + string copy_command; + _username = string(params[USER]); + + // Test protocol + if( _protocol == "rsh" ) + copy_command = "rcp "; + else if( _protocol == "ssh" ) + copy_command = "scp "; + else + throw EmulationException("Unknown protocol : only rsh and ssh are known !"); + + // First step : creating batch tmp files directory + command = _protocol; + command += " "; + if(_username != ""){ + command += _username; + command += "@"; + } + command += _hostname; + command += " \"mkdir -p "; + command += string(params[TMPDIR]); + command += "\"" ; + cerr << command.c_str() << endl; + status = system(command.c_str()); + if(status) { + std::ostringstream oss; + oss << status; + std::string ex_mess("Error of connection on remote host ! status = "); + ex_mess += oss.str(); + throw EmulationException(ex_mess.c_str()); + } + + // Second step : copy fileToExecute into + // batch tmp files directory + command = copy_command; + command += string(params[EXECUTABLE]); + command += " "; + if(_username != ""){ + command += _username; + command += "@"; + } + command += _hostname; + command += ":"; + command += string(params[TMPDIR]); + cerr << command.c_str() << endl; + status = system(command.c_str()); + if(status) { + std::ostringstream oss; + oss << status; + std::string ex_mess("Error of connection on remote host ! status = "); + ex_mess += oss.str(); + throw EmulationException(ex_mess.c_str()); + } + + // Third step : copy filesToExportList into + // batch tmp files directory + for(Vit=V.begin(); Vit!=V.end(); Vit++) { + CoupleType cpt = *static_cast< CoupleType * >(*Vit); + Couple inputFile = cpt; + command = copy_command; + command += inputFile.getLocal(); + command += " "; + if(_username != ""){ + command += _username; + command += "@"; + } + command += _hostname; + command += ":"; + command += inputFile.getRemote(); + cerr << command.c_str() << endl; + status = system(command.c_str()); + if(status) { + std::ostringstream oss; + oss << status; + std::string ex_mess("Error of connection on remote host ! status = "); + ex_mess += oss.str(); + throw EmulationException(ex_mess.c_str()); + } + } + + } + + void BatchManager_eClient::importOutputFiles( const Job & job, const string directory ) throw(EmulationException) + { + string command; + int status; + + Parametre params = job.getParametre(); + Versatile V = params[OUTFILE]; + Versatile::iterator Vit; + + for(Vit=V.begin(); Vit!=V.end(); Vit++) { + CoupleType cpt = *static_cast< CoupleType * >(*Vit); + Couple outputFile = cpt; + if( _protocol == "rsh" ) + command = "rcp "; + else if( _protocol == "ssh" ) + command = "scp "; + else + throw EmulationException("Unknown protocol"); + + if (_username != ""){ + command += _username; + command += "@"; + } + command += _hostname; + command += ":"; + command += outputFile.getRemote(); + command += " "; + command += directory; + cerr << command.c_str() << endl; + status = system(command.c_str()); + if(status) + { + // Try to get what we can (logs files) + // throw BatchException("Error of connection on remote host"); + std::string mess("Copy command failed ! status is :"); + ostringstream status_str; + status_str << status; + mess += status_str.str(); + cerr << mess << endl; + } + } + + } + + MpiImpl *BatchManager_eClient::FactoryMpiImpl(string mpiImpl) throw(EmulationException) + { + if(mpiImpl == "lam") + return new MpiImpl_LAM(); + else if(mpiImpl == "mpich1") + return new MpiImpl_MPICH1(); + else if(mpiImpl == "mpich2") + return new MpiImpl_MPICH2(); + else if(mpiImpl == "openmpi") + return new MpiImpl_OPENMPI(); + else if(mpiImpl == "slurm") + return new MpiImpl_SLURM(); + else{ + ostringstream oss; + oss << mpiImpl << " : not yet implemented"; + throw EmulationException(oss.str().c_str()); + } + } + + string BatchManager_eClient::BuildTemporaryFileName() const + { + //build more complex file name to support multiple salome session + char *temp = new char[19]; + strcpy(temp, "/tmp/command"); + strcat(temp, "XXXXXX"); +#ifndef WNT + mkstemp(temp); +#else + char aPID[80]; + itoa(getpid(), aPID, 10); + strcat(temp, aPID); +#endif + + string command(temp); + delete [] temp; + command += ".sh"; + return command; + } + + void BatchManager_eClient::RmTmpFile(std::string & TemporaryFileName) + { + string command = "rm "; + command += TemporaryFileName; + char *temp = strdup(command.c_str()); + int lgthTemp = strlen(temp); + temp[lgthTemp - 3] = '*'; + temp[lgthTemp - 2] = '\0'; + system(temp); + free(temp); + } + +} diff --git a/src/Batch/Batch_BatchManager_eClient.hxx b/src/Batch/Batch_BatchManager_eClient.hxx new file mode 100644 index 000000000..717eae6a3 --- /dev/null +++ b/src/Batch/Batch_BatchManager_eClient.hxx @@ -0,0 +1,73 @@ +// Copyright (C) 2005 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 +// +/* + * BatchManager_eLSF.hxx : emulation of client + * + * Auteur : Bernard SECHER - CEA DEN + * Mail : mailto:bernard.secher@cea.fr + * Date : Thu Apr 24 10:17:22 2008 + * Projet : PAL Salome + * + */ + +#ifndef _BATCHMANAGER_eClient_H_ +#define _BATCHMANAGER_eClient_H_ + + +#include "MpiImpl.hxx" +#include "Batch_BatchManager.hxx" + +namespace Batch { + + class Job; + + class EmulationException + { + public: + const std::string msg; + + EmulationException(const std::string m) : msg(m) {} + }; + + class BatchManager_eClient : public BatchManager + { + public: + // Constructeur et destructeur + BatchManager_eClient(const Batch::FactBatchManager * parent, const char* host="localhost", const char* protocol="ssh", const char* mpiImpl="indif"); + virtual ~BatchManager_eClient(); + void importOutputFiles( const Job & job, const std::string directory ) throw(EmulationException); + + protected: + std::string _protocol; // protocol to access _hostname + std::string _username; // username to access _hostname + MpiImpl *_mpiImpl; // Mpi implementation to launch executable in batch script + + std::string BuildTemporaryFileName() const; + void RmTmpFile(std::string & TemporaryFileName); + MpiImpl* FactoryMpiImpl(string mpiImpl) throw(EmulationException); + void exportInputFiles(const Job & job) throw(EmulationException); + + private: + + }; + +} + +#endif diff --git a/src/Batch/Batch_BatchManager_eLSF.cxx b/src/Batch/Batch_BatchManager_eLSF.cxx new file mode 100644 index 000000000..d1c44e60d --- /dev/null +++ b/src/Batch/Batch_BatchManager_eLSF.cxx @@ -0,0 +1,310 @@ +// Copyright (C) 2005 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 +// +/* + * BatchManager_eLSF.cxx : emulation of LSF client + * + * Auteur : Bernard SECHER - CEA DEN + * Mail : mailto:bernard.secher@cea.fr + * Date : Thu Apr 24 10:17:22 2008 + * Projet : PAL Salome + * + */ + +#include +#include +#include +#include +#include "Batch_BatchManager_eLSF.hxx" + +namespace Batch { + + BatchManager_eLSF::BatchManager_eLSF(const FactBatchManager * parent, const char * host, const char * protocol, const char * mpiImpl) throw(InvalidArgumentException,ConnexionFailureException) : BatchManager_eClient(parent,host,protocol,mpiImpl) + { + // Nothing to do + } + + // Destructeur + BatchManager_eLSF::~BatchManager_eLSF() + { + // Nothing to do + } + + // Methode pour le controle des jobs : soumet un job au gestionnaire + const JobId BatchManager_eLSF::submitJob(const Job & job) + { + int status; + Parametre params = job.getParametre(); + const std::string dirForTmpFiles = params[TMPDIR]; + const string fileToExecute = params[EXECUTABLE]; + string::size_type p1 = fileToExecute.find_last_of("/"); + string::size_type p2 = fileToExecute.find_last_of("."); + std::string fileNameToExecute = fileToExecute.substr(p1+1,p2-p1-1); + + // export input files on cluster + exportInputFiles(job); + + // build batch script for job + buildBatchScript(job); + + // define name of log file + string logFile="/tmp/logs/"; + logFile += getenv("USER"); + logFile += "/batchSalome_"; + srand ( time(NULL) ); + int ir = rand(); + ostringstream oss; + oss << ir; + logFile += oss.str(); + logFile += ".log"; + + string command; + + // define command to submit batch + command = _protocol; + command += " "; + + if(_username != ""){ + command += _username; + command += "@"; + } + + command += _hostname; + command += " \"cd " ; + command += dirForTmpFiles ; + command += "; bsub < " ; + command += fileNameToExecute ; + command += "_Batch.sh\" > "; + command += logFile; + cerr << command.c_str() << endl; + status = system(command.c_str()); + if(status) + throw EmulationException("Error of connection on remote host"); + + // read id of submitted job in log file + char line[128]; + FILE *fp = fopen(logFile.c_str(),"r"); + fgets( line, 128, fp); + fclose(fp); + + string sline(line); + int p10 = sline.find("<"); + int p20 = sline.find(">"); + string strjob = sline.substr(p10+1,p20-p10-1); + + JobId id(this, strjob); + return id; + } + + // Methode pour le controle des jobs : retire un job du gestionnaire + void BatchManager_eLSF::deleteJob(const JobId & jobid) + { + int status; + int ref; + istringstream iss(jobid.getReference()); + iss >> ref; + + // define command to submit batch + string command; + command = _protocol; + command += " "; + + if (_username != ""){ + command += _username; + command += "@"; + } + + command += _hostname; + command += " \"bkill " ; + command += iss.str(); + command += "\""; + cerr << command.c_str() << endl; + status = system(command.c_str()); + if(status) + throw EmulationException("Error of connection on remote host"); + + cerr << "jobId = " << ref << "killed" << endl; + } + + // Methode pour le controle des jobs : suspend un job en file d'attente + void BatchManager_eLSF::holdJob(const JobId & jobid) + { + throw EmulationException("Not yet implemented"); + } + + // Methode pour le controle des jobs : relache un job suspendu + void BatchManager_eLSF::releaseJob(const JobId & jobid) + { + throw EmulationException("Not yet implemented"); + } + + + // Methode pour le controle des jobs : modifie un job en file d'attente + void BatchManager_eLSF::alterJob(const JobId & jobid, const Parametre & param, const Environnement & env) + { + throw EmulationException("Not yet implemented"); + } + + // Methode pour le controle des jobs : modifie un job en file d'attente + void BatchManager_eLSF::alterJob(const JobId & jobid, const Parametre & param) + { + alterJob(jobid, param, Environnement()); + } + + // Methode pour le controle des jobs : modifie un job en file d'attente + void BatchManager_eLSF::alterJob(const JobId & jobid, const Environnement & env) + { + alterJob(jobid, Parametre(), env); + } + + // Methode pour le controle des jobs : renvoie l'etat du job + JobInfo BatchManager_eLSF::queryJob(const JobId & jobid) + { + int id; + istringstream iss(jobid.getReference()); + iss >> id; + + // define name of log file + string logFile="/tmp/logs/"; + logFile += getenv("USER"); + logFile += "/batchSalome_"; + + srand ( time(NULL) ); + int ir = rand(); + ostringstream oss; + oss << ir; + logFile += oss.str(); + logFile += ".log"; + + string command; + int status; + + // define command to submit batch + command = _protocol; + command += " "; + + if (_username != ""){ + command += _username; + command += "@"; + } + + command += _hostname; + command += " \"bjobs " ; + command += iss.str(); + command += "\" > "; + command += logFile; + cerr << command.c_str() << endl; + status = system(command.c_str()); + if(status) + throw EmulationException("Error of connection on remote host"); + + JobInfo_eLSF ji = JobInfo_eLSF(id,logFile); + return ji; + } + + + + // Methode pour le controle des jobs : teste si un job est present en machine + bool BatchManager_eLSF::isRunning(const JobId & jobid) + { + throw EmulationException("Not yet implemented"); + } + + void BatchManager_eLSF::buildBatchScript(const Job & job) throw(EmulationException) + { + int status; + Parametre params = job.getParametre(); + const int nbproc = params[NBPROC]; + const long edt = params[MAXWALLTIME]; + const long mem = params[MAXRAMSIZE]; + const string workDir = params[WORKDIR]; + const std::string dirForTmpFiles = params[TMPDIR]; + const string fileToExecute = params[EXECUTABLE]; + string::size_type p1 = fileToExecute.find_last_of("/"); + string::size_type p2 = fileToExecute.find_last_of("."); + std::string rootNameToExecute = fileToExecute.substr(p1+1,p2-p1-1); + std::string fileNameToExecute = "~/" + dirForTmpFiles + "/" + string(basename(fileToExecute.c_str())); + + int idx = dirForTmpFiles.find("Batch/"); + std::string filelogtemp = dirForTmpFiles.substr(idx+6, dirForTmpFiles.length()); + + std::string TmpFileName = BuildTemporaryFileName(); + ofstream tempOutputFile; + tempOutputFile.open(TmpFileName.c_str(), ofstream::out ); + + tempOutputFile << "#! /bin/sh -f" << endl ; + if( edt > 0 ) + tempOutputFile << "#BSUB -W " << getWallTime(edt) << endl ; + if( mem > 0 ) + tempOutputFile << "#BSUB -M " << mem*1024 << endl ; + tempOutputFile << "#BSUB -n " << nbproc << endl ; + tempOutputFile << "#BSUB -o runSalome.output.log." << filelogtemp << endl ; + tempOutputFile << "#BSUB -e runSalome.error.log." << filelogtemp << endl ; + if( workDir.size() > 0 ) + tempOutputFile << "cd " << workDir << endl ; + tempOutputFile << _mpiImpl->boot("",nbproc); + tempOutputFile << _mpiImpl->run("",nbproc,fileNameToExecute); + tempOutputFile << _mpiImpl->halt(); + tempOutputFile.flush(); + tempOutputFile.close(); + chmod(TmpFileName.c_str(), 0x1ED); + cerr << TmpFileName.c_str() << endl; + + string command; + if( _protocol == "rsh" ) + command = "rcp "; + else if( _protocol == "ssh" ) + command = "scp "; + else + throw EmulationException("Unknown protocol"); + command += TmpFileName; + command += " "; + if(_username != ""){ + command += _username; + command += "@"; + } + command += _hostname; + command += ":"; + command += dirForTmpFiles ; + command += "/" ; + command += rootNameToExecute ; + command += "_Batch.sh" ; + cerr << command.c_str() << endl; + status = system(command.c_str()); + if(status) + throw EmulationException("Error of connection on remote host"); + + RmTmpFile(TmpFileName); + + } + + std::string BatchManager_eLSF::getWallTime(const long edt) + { + long h, m; + h = edt / 60; + m = edt - h*60; + ostringstream oss; + if( m >= 10 ) + oss << h << ":" << m; + else + oss << h << ":0" << m; + return oss.str(); + } + +} diff --git a/src/Batch/Batch_BatchManager_eLSF.hxx b/src/Batch/Batch_BatchManager_eLSF.hxx new file mode 100644 index 000000000..00d79a4fa --- /dev/null +++ b/src/Batch/Batch_BatchManager_eLSF.hxx @@ -0,0 +1,93 @@ +// Copyright (C) 2005 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 +// +/* + * BatchManager_eLSF.hxx : emulation of LSF client + * + * Auteur : Bernard SECHER - CEA DEN + * Mail : mailto:bernard.secher@cea.fr + * Date : Thu Apr 24 10:17:22 2008 + * Projet : PAL Salome + * + */ + +#ifndef _BATCHMANAGER_eLSF_H_ +#define _BATCHMANAGER_eLSF_H_ + + +#include "Batch_JobId.hxx" +#include "Batch_JobInfo.hxx" +#include "Batch_JobInfo_eLSF.hxx" +#include "Batch_InvalidArgumentException.hxx" +#include "Batch_ConnexionFailureException.hxx" +#include "Batch_APIInternalFailureException.hxx" +#include "Batch_NotYetImplementedException.hxx" +#include "Batch_BatchManager.hxx" +#include "Batch_BatchManager_eClient.hxx" + +namespace Batch { + + class Job; + class JobId; + class JobInfo; + class FactBatchManager; + + class BatchManager_eLSF : public BatchManager_eClient + { + public: + // Constructeur et destructeur + BatchManager_eLSF(const FactBatchManager * parent, const char * host="localhost", const char * protocol="ssh", const char * mpiImpl="indif") throw(InvalidArgumentException,ConnexionFailureException); // connexion a la machine host + virtual ~BatchManager_eLSF(); + + // Recupere le nom du serveur par defaut + // static string BatchManager_LSF::getDefaultServer(); + + // Methodes pour le controle des jobs + virtual const JobId submitJob(const Job & job); // soumet un job au gestionnaire + virtual void deleteJob(const JobId & jobid); // retire un job du gestionnaire + virtual void holdJob(const JobId & jobid); // suspend un job en file d'attente + virtual void releaseJob(const JobId & jobid); // relache un job suspendu + virtual void alterJob(const JobId & jobid, const Parametre & param, const Environnement & env); // modifie un job en file d'attente + virtual void alterJob(const JobId & jobid, const Parametre & param); // modifie un job en file d'attente + virtual void alterJob(const JobId & jobid, const Environnement & env); // modifie un job en file d'attente + virtual JobInfo queryJob(const JobId & jobid); // renvoie l'etat du job + virtual bool isRunning(const JobId & jobid); // teste si un job est present en machine + + virtual void setParametre(const JobId & jobid, const Parametre & param) { return alterJob(jobid, param); } // modifie un job en file d'attente + virtual void setEnvironnement(const JobId & jobid, const Environnement & env) { return alterJob(jobid, env); } // modifie un job en file d'attente + + + protected: + void buildBatchScript(const Job & job) throw(EmulationException); + std::string getWallTime(const long edt); + + private: + +#ifdef SWIG + public: + // Recupere le l'identifiant d'un job deja soumis au BatchManager + //virtual const JobId getJobIdByReference(const string & ref) { return BatchManager::getJobIdByReference(ref); } + virtual const JobId getJobIdByReference(const char * ref) { return BatchManager::getJobIdByReference(ref); } +#endif + + }; + +} + +#endif diff --git a/src/Batch/Batch_BatchManager_ePBS.cxx b/src/Batch/Batch_BatchManager_ePBS.cxx new file mode 100644 index 000000000..999025cfb --- /dev/null +++ b/src/Batch/Batch_BatchManager_ePBS.cxx @@ -0,0 +1,296 @@ +// Copyright (C) 2005 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 +// +/* + * BatchManager_ePBS.cxx : emulation of PBS client + * + * Auteur : Bernard SECHER - CEA DEN + * Mail : mailto:bernard.secher@cea.fr + * Date : Thu Apr 24 10:17:22 2008 + * Projet : PAL Salome + * + */ + +#include +#include +#include +#include +#include "Batch_BatchManager_ePBS.hxx" + +namespace Batch { + + BatchManager_ePBS::BatchManager_ePBS(const FactBatchManager * parent, const char * host, const char * protocol, const char * mpiImpl) throw(InvalidArgumentException,ConnexionFailureException) : BatchManager_eClient(parent,host,protocol,mpiImpl) + { + // Nothing to do + } + + // Destructeur + BatchManager_ePBS::~BatchManager_ePBS() + { + // Nothing to do + } + + // Methode pour le controle des jobs : soumet un job au gestionnaire + const JobId BatchManager_ePBS::submitJob(const Job & job) + { + int status; + Parametre params = job.getParametre(); + const std::string dirForTmpFiles = params[TMPDIR]; + const string fileToExecute = params[EXECUTABLE]; + string::size_type p1 = fileToExecute.find_last_of("/"); + string::size_type p2 = fileToExecute.find_last_of("."); + std::string fileNameToExecute = fileToExecute.substr(p1+1,p2-p1-1); + + // export input files on cluster + exportInputFiles(job); + + // build batch script for job + buildBatchScript(job); + + // define name of log file + string logFile="/tmp/logs/"; + logFile += getenv("USER"); + logFile += "/batchSalome_"; + srand ( time(NULL) ); + int ir = rand(); + ostringstream oss; + oss << ir; + logFile += oss.str(); + logFile += ".log"; + + string command; + + // define command to submit batch + command = _protocol; + command += " "; + + if(_username != ""){ + command += _username; + command += "@"; + } + + command += _hostname; + command += " \"cd " ; + command += dirForTmpFiles ; + command += "; qsub " ; + command += fileNameToExecute ; + command += "_Batch.sh\" > "; + command += logFile; + cerr << command.c_str() << endl; + status = system(command.c_str()); + if(status) + throw EmulationException("Error of connection on remote host"); + + // read id of submitted job in log file + char line[128]; + FILE *fp = fopen(logFile.c_str(),"r"); + fgets( line, 128, fp); + fclose(fp); + + string sline(line); + int pos = sline.find("."); + string strjob; + if(pos == string::npos) + strjob = sline; + else + strjob = sline.substr(0,pos); + + JobId id(this, strjob); + return id; + } + + // Methode pour le controle des jobs : retire un job du gestionnaire + void BatchManager_ePBS::deleteJob(const JobId & jobid) + { + int status; + int ref; + istringstream iss(jobid.getReference()); + iss >> ref; + + // define command to submit batch + string command; + command = _protocol; + command += " "; + + if (_username != ""){ + command += _username; + command += "@"; + } + + command += _hostname; + command += " \"qdel " ; + command += iss.str(); + command += "\""; + cerr << command.c_str() << endl; + status = system(command.c_str()); + if(status) + throw EmulationException("Error of connection on remote host"); + + cerr << "jobId = " << ref << "killed" << endl; + } + + // Methode pour le controle des jobs : suspend un job en file d'attente + void BatchManager_ePBS::holdJob(const JobId & jobid) + { + throw EmulationException("Not yet implemented"); + } + + // Methode pour le controle des jobs : relache un job suspendu + void BatchManager_ePBS::releaseJob(const JobId & jobid) + { + throw EmulationException("Not yet implemented"); + } + + + // Methode pour le controle des jobs : modifie un job en file d'attente + void BatchManager_ePBS::alterJob(const JobId & jobid, const Parametre & param, const Environnement & env) + { + throw EmulationException("Not yet implemented"); + } + + // Methode pour le controle des jobs : modifie un job en file d'attente + void BatchManager_ePBS::alterJob(const JobId & jobid, const Parametre & param) + { + alterJob(jobid, param, Environnement()); + } + + // Methode pour le controle des jobs : modifie un job en file d'attente + void BatchManager_ePBS::alterJob(const JobId & jobid, const Environnement & env) + { + alterJob(jobid, Parametre(), env); + } + + // Methode pour le controle des jobs : renvoie l'etat du job + JobInfo BatchManager_ePBS::queryJob(const JobId & jobid) + { + int id; + istringstream iss(jobid.getReference()); + iss >> id; + + // define name of log file + string logFile="/tmp/logs/"; + logFile += getenv("USER"); + logFile += "/batchSalome_"; + + ostringstream oss; + oss << this << "_" << id; + logFile += oss.str(); + logFile += ".log"; + + string command; + int status; + + // define command to submit batch + command = _protocol; + command += " "; + + if (_username != ""){ + command += _username; + command += "@"; + } + + command += _hostname; + command += " \"qstat -f " ; + command += iss.str(); + command += "\" > "; + command += logFile; + cerr << command.c_str() << endl; + status = system(command.c_str()); + if(status && status != 153 && status != 256*153) + throw EmulationException("Error of connection on remote host"); + + JobInfo_ePBS ji = JobInfo_ePBS(id,logFile); + return ji; + } + + // Methode pour le controle des jobs : teste si un job est present en machine + bool BatchManager_ePBS::isRunning(const JobId & jobid) + { + throw EmulationException("Not yet implemented"); + } + + void BatchManager_ePBS::buildBatchScript(const Job & job) throw(EmulationException) + { + int status; + Parametre params = job.getParametre(); + const long nbproc = params[NBPROC]; + const long edt = params[MAXWALLTIME]; + const long mem = params[MAXRAMSIZE]; + const string workDir = params[WORKDIR]; + const std::string dirForTmpFiles = params[TMPDIR]; + const string fileToExecute = params[EXECUTABLE]; + const string home = params[HOMEDIR]; + string::size_type p1 = fileToExecute.find_last_of("/"); + string::size_type p2 = fileToExecute.find_last_of("."); + std::string rootNameToExecute = fileToExecute.substr(p1+1,p2-p1-1); + std::string fileNameToExecute = "~/" + dirForTmpFiles + "/" + string(basename(fileToExecute.c_str())); + + int idx = dirForTmpFiles.find("Batch/"); + std::string filelogtemp = dirForTmpFiles.substr(idx+6, dirForTmpFiles.length()); + + std::string TmpFileName = BuildTemporaryFileName(); + ofstream tempOutputFile; + tempOutputFile.open(TmpFileName.c_str(), ofstream::out ); + + tempOutputFile << "#! /bin/sh -f" << endl; + if( edt > 0 ) + tempOutputFile << "#PBS -l walltime=" << edt*60 << endl ; + if( mem > 0 ) + tempOutputFile << "#PBS -l mem=" << mem << "mb" << endl ; + tempOutputFile << "#PBS -o " << home << "/" << dirForTmpFiles << "/runSalome.output.log." << filelogtemp << endl ; + tempOutputFile << "#PBS -e " << home << "/" << dirForTmpFiles << "/runSalome.error.log." << filelogtemp << endl ; + if( workDir.size() > 0 ) + tempOutputFile << "cd " << workDir << endl ; + tempOutputFile << _mpiImpl->boot("${PBS_NODEFILE}",nbproc); + tempOutputFile << _mpiImpl->run("${PBS_NODEFILE}",nbproc,fileNameToExecute); + tempOutputFile << _mpiImpl->halt(); + tempOutputFile.flush(); + tempOutputFile.close(); + chmod(TmpFileName.c_str(), 0x1ED); + cerr << TmpFileName.c_str() << endl; + + string command; + if( _protocol == "rsh" ) + command = "rcp "; + else if( _protocol == "ssh" ) + command = "scp "; + else + throw EmulationException("Unknown protocol"); + command += TmpFileName; + command += " "; + if(_username != ""){ + command += _username; + command += "@"; + } + command += _hostname; + command += ":"; + command += dirForTmpFiles ; + command += "/" ; + command += rootNameToExecute ; + command += "_Batch.sh" ; + cerr << command.c_str() << endl; + status = system(command.c_str()); + if(status) + throw EmulationException("Error of connection on remote host"); + + RmTmpFile(TmpFileName); + + } + +} diff --git a/src/Batch/Batch_BatchManager_ePBS.hxx b/src/Batch/Batch_BatchManager_ePBS.hxx new file mode 100644 index 000000000..42f4b1b69 --- /dev/null +++ b/src/Batch/Batch_BatchManager_ePBS.hxx @@ -0,0 +1,91 @@ +// Copyright (C) 2005 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 +// +/* + * BatchManager_ePBS.hxx : emulation of PBS client + * + * Auteur : Bernard SECHER - CEA DEN + * Mail : mailto:bernard.secher@cea.fr + * Date : Thu Apr 24 10:17:22 2008 + * Projet : PAL Salome + * + */ + +#ifndef _BATCHMANAGER_eLSF_H_ +#define _BATCHMANAGER_eLSF_H_ + +#include "Batch_JobId.hxx" +#include "Batch_JobInfo.hxx" +#include "Batch_JobInfo_ePBS.hxx" +#include "Batch_InvalidArgumentException.hxx" +#include "Batch_ConnexionFailureException.hxx" +#include "Batch_APIInternalFailureException.hxx" +#include "Batch_NotYetImplementedException.hxx" +#include "Batch_BatchManager.hxx" +#include "Batch_BatchManager_eClient.hxx" + +namespace Batch { + + class Job; + class JobId; + class JobInfo; + class FactBatchManager; + + class BatchManager_ePBS : public BatchManager_eClient + { + public: + // Constructeur et destructeur + BatchManager_ePBS(const FactBatchManager * parent, const char * host="localhost", const char * protocol="ssh", const char * mpiImpl="indif") throw(InvalidArgumentException,ConnexionFailureException); // connexion a la machine host + virtual ~BatchManager_ePBS(); + + // Recupere le nom du serveur par defaut + // static string BatchManager_LSF::getDefaultServer(); + + // Methodes pour le controle des jobs + virtual const JobId submitJob(const Job & job); // soumet un job au gestionnaire + virtual void deleteJob(const JobId & jobid); // retire un job du gestionnaire + virtual void holdJob(const JobId & jobid); // suspend un job en file d'attente + virtual void releaseJob(const JobId & jobid); // relache un job suspendu + virtual void alterJob(const JobId & jobid, const Parametre & param, const Environnement & env); // modifie un job en file d'attente + virtual void alterJob(const JobId & jobid, const Parametre & param); // modifie un job en file d'attente + virtual void alterJob(const JobId & jobid, const Environnement & env); // modifie un job en file d'attente + virtual JobInfo queryJob(const JobId & jobid); // renvoie l'etat du job + virtual bool isRunning(const JobId & jobid); // teste si un job est present en machine + + virtual void setParametre(const JobId & jobid, const Parametre & param) { return alterJob(jobid, param); } // modifie un job en file d'attente + virtual void setEnvironnement(const JobId & jobid, const Environnement & env) { return alterJob(jobid, env); } // modifie un job en file d'attente + + + protected: + void buildBatchScript(const Job & job) throw(EmulationException); + + private: + +#ifdef SWIG + public: + // Recupere le l'identifiant d'un job deja soumis au BatchManager + //virtual const JobId getJobIdByReference(const string & ref) { return BatchManager::getJobIdByReference(ref); } + virtual const JobId getJobIdByReference(const char * ref) { return BatchManager::getJobIdByReference(ref); } +#endif + + }; + +} + +#endif diff --git a/src/Batch/Batch_FactBatchManager_eClient.cxx b/src/Batch/Batch_FactBatchManager_eClient.cxx new file mode 100644 index 000000000..6673879de --- /dev/null +++ b/src/Batch/Batch_FactBatchManager_eClient.cxx @@ -0,0 +1,48 @@ +// Copyright (C) 2005 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 +// +/* + * FactBatchManager_eClient.cxx : emulation of client + * + * Auteur : Bernard SECHER - CEA DEN + * Mail : mailto:bernard.secher@cea.fr + * Date : Thu Apr 24 10:17:22 2008 + * Projet : PAL Salome + * + */ + +#include +#include +#include "Batch_FactBatchManager_eClient.hxx" +using namespace std; + +namespace Batch { + + // Constructeur + FactBatchManager_eClient::FactBatchManager_eClient(const string & _t) : FactBatchManager(_t) + { + } + + // Destructeur + FactBatchManager_eClient::~FactBatchManager_eClient() + { + // Nothing to do + } + +} diff --git a/src/Batch/Batch_FactBatchManager_eClient.hxx b/src/Batch/Batch_FactBatchManager_eClient.hxx new file mode 100644 index 000000000..616a6626d --- /dev/null +++ b/src/Batch/Batch_FactBatchManager_eClient.hxx @@ -0,0 +1,58 @@ +// Copyright (C) 2005 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 +// +/* + * FactBatchManager_eClient.hxx : emulation of client + * + * Auteur : Bernard SECHER - CEA DEN + * Mail : mailto:bernard.secher@cea.fr + * Date : Thu Apr 24 10:17:22 2008 + * Projet : PAL Salome + * + */ + +#ifndef _FACTBATCHMANAGER_eClient_H_ +#define _FACTBATCHMANAGER_eClient_H_ + +#include +#include +#include "Batch_FactBatchManager.hxx" + +namespace Batch { + + class BatchManager_eClient; + + class FactBatchManager_eClient : public FactBatchManager + { + public: + // Constructeur et destructeur + FactBatchManager_eClient(const std::string & type); + virtual ~FactBatchManager_eClient(); + + virtual Batch::BatchManager_eClient * operator() (const char * hostname,const char * protocol, const char * mpi) const = 0; + + protected: + + private: + + }; + +} + +#endif diff --git a/src/Batch/Batch_FactBatchManager_eLSF.cxx b/src/Batch/Batch_FactBatchManager_eLSF.cxx new file mode 100644 index 000000000..227bffa32 --- /dev/null +++ b/src/Batch/Batch_FactBatchManager_eLSF.cxx @@ -0,0 +1,63 @@ +// Copyright (C) 2005 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 +// +/* + * FactBatchManager_eLSF.cxx : + * + * Auteur : Bernard SECHER - CEA DEN + * Date : Avril 2008 + * Projet : PAL Salome + * + */ + +#include +#include "Batch_BatchManager_eLSF.hxx" +#include "Batch_FactBatchManager_eLSF.hxx" +//#include "utilities.h" + +namespace Batch { + + static FactBatchManager_eLSF sFBM_eLSF; + + // Constructeur + FactBatchManager_eLSF::FactBatchManager_eLSF() : FactBatchManager_eClient("eLSF") + { + // Nothing to do + } + + // Destructeur + FactBatchManager_eLSF::~FactBatchManager_eLSF() + { + // Nothing to do + } + + // Functor + BatchManager * FactBatchManager_eLSF::operator() (const char * hostname) const + { + // MESSAGE("Building new BatchManager_LSF on host '" << hostname << "'"); + return new BatchManager_eLSF(this, hostname); + } + + BatchManager_eClient * FactBatchManager_eLSF::operator() (const char * hostname, const char * protocol, const char * mpiImpl) const + { + // MESSAGE("Building new BatchManager_LSF on host '" << hostname << "'"); + return new BatchManager_eLSF(this, hostname, protocol, mpiImpl); + } + +} diff --git a/src/Batch/Batch_FactBatchManager_eLSF.hxx b/src/Batch/Batch_FactBatchManager_eLSF.hxx new file mode 100644 index 000000000..e1660aaaa --- /dev/null +++ b/src/Batch/Batch_FactBatchManager_eLSF.hxx @@ -0,0 +1,60 @@ +// Copyright (C) 2005 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 +// +/* + * FactBatchManager_eLSF.hxx : + * + * Auteur : Bernard SECHER : CEA DEN + * Date : Avril 2008 + * Projet : PAL Salome + * + */ + +#ifndef _FACTBATCHMANAGER_eLSF_H_ +#define _FACTBATCHMANAGER_eLSF_H_ + +using namespace std; +#include +#include +#include "Batch_BatchManager_eClient.hxx" +#include "Batch_FactBatchManager_eClient.hxx" + +namespace Batch { + + class BatchManager_eLSF; + + class FactBatchManager_eLSF : public FactBatchManager_eClient + { + public: + // Constructeur et destructeur + FactBatchManager_eLSF(); + virtual ~FactBatchManager_eLSF(); + + virtual BatchManager * operator() (const char * hostname) const; + virtual BatchManager_eClient * operator() (const char * hostname, const char * protocol, const char * mpiImpl) const; + + protected: + + private: + + }; + +} + +#endif diff --git a/src/Batch/Batch_FactBatchManager_ePBS.cxx b/src/Batch/Batch_FactBatchManager_ePBS.cxx new file mode 100644 index 000000000..3bcbda530 --- /dev/null +++ b/src/Batch/Batch_FactBatchManager_ePBS.cxx @@ -0,0 +1,64 @@ +// Copyright (C) 2005 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 +// +/* + * FactBatchManager_ePBS.cxx : + * + * Auteur : Bernard SECHER - CEA DEN + * Date : Avril 2008 + * Projet : PAL Salome + * + */ + +#include +#include "Batch_BatchManager_ePBS.hxx" +#include "Batch_FactBatchManager_ePBS.hxx" +//#include "utilities.h" + +namespace Batch { + + static FactBatchManager_ePBS sFBM_ePBS; + + // Constructeur + FactBatchManager_ePBS::FactBatchManager_ePBS() : FactBatchManager_eClient("ePBS") + { + // Nothing to do + } + + // Destructeur + FactBatchManager_ePBS::~FactBatchManager_ePBS() + { + // Nothing to do + } + + // Functor + BatchManager * FactBatchManager_ePBS::operator() (const char * hostname) const + { + // MESSAGE("Building new BatchManager_PBS on host '" << hostname << "'"); + return new BatchManager_ePBS(this, hostname); + } + + BatchManager_eClient * FactBatchManager_ePBS::operator() (const char * hostname, const char * protocol, const char * mpiImpl) const + { + // MESSAGE("Building new BatchManager_PBS on host '" << hostname << "'"); + return new BatchManager_ePBS(this, hostname, protocol, mpiImpl); + } + + +} diff --git a/src/Batch/Batch_FactBatchManager_ePBS.hxx b/src/Batch/Batch_FactBatchManager_ePBS.hxx new file mode 100644 index 000000000..69fdf322a --- /dev/null +++ b/src/Batch/Batch_FactBatchManager_ePBS.hxx @@ -0,0 +1,60 @@ +// Copyright (C) 2005 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 +// +/* + * FactBatchManager_ePBS.hxx : + * + * Auteur : Bernard SECHER : CEA DEN + * Date : Avril 2008 + * Projet : PAL Salome + * + */ + +#ifndef _FACTBATCHMANAGER_ePBS_H_ +#define _FACTBATCHMANAGER_ePBS_H_ + +using namespace std; +#include +#include +#include "Batch_BatchManager_eClient.hxx" +#include "Batch_FactBatchManager_eClient.hxx" + +namespace Batch { + + class BatchManager_ePBS; + + class FactBatchManager_ePBS : public FactBatchManager_eClient + { + public: + // Constructeur et destructeur + FactBatchManager_ePBS(); + virtual ~FactBatchManager_ePBS(); + + virtual BatchManager * operator() (const char * hostname) const; + virtual BatchManager_eClient * operator() (const char * hostname, const char * protocol, const char * mpiImpl) const; + + protected: + + private: + + }; + +} + +#endif diff --git a/src/Batch/Batch_JobInfo_eLSF.cxx b/src/Batch/Batch_JobInfo_eLSF.cxx new file mode 100644 index 000000000..177f2eb06 --- /dev/null +++ b/src/Batch/Batch_JobInfo_eLSF.cxx @@ -0,0 +1,103 @@ +// Copyright (C) 2005 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 +// +/* + * JobInfo_eLSF.cxx : emulation of LSF client + * + * Auteur : Bernard SECHER - CEA DEN + * Mail : mailto:bernard.secher@cea.fr + * Date : Thu Apr 24 10:17:22 2008 + * Projet : PAL Salome + * + */ + +#include +#include +#include +#include +#include "Batch_Parametre.hxx" +#include "Batch_Environnement.hxx" +#include "Batch_RunTimeException.hxx" +#include "Batch_APIInternalFailureException.hxx" +#include "Batch_JobInfo_eLSF.hxx" + +namespace Batch { + + + + // Constructeurs + JobInfo_eLSF::JobInfo_eLSF(int id, string logFile) : JobInfo() + { + // On remplit les membres _param et _env + ostringstream oss; + oss << id; + _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; + + _param[STATE] = status; + + if( status.find("RUN") != string::npos) + _running = true; + + } + + // Teste si un job est present en machine + bool JobInfo_eLSF::isRunning() const + { + return _running; + } + + + // Destructeur + JobInfo_eLSF::~JobInfo_eLSF() + { + // Nothing to do + } + + // Convertit une date HH:MM:SS en secondes + long JobInfo_eLSF::HMStoLong(const string & s) + { + long hour, min, sec; + + sscanf( s.c_str(), "%ld:%ld:%ld", &hour, &min, &sec); + return ( ( ( hour * 60L ) + min ) * 60L ) + sec; + } + + // Methode pour l'interfacage avec Python (SWIG) : affichage en Python + string JobInfo_eLSF::__str__() const + { + ostringstream sst; + sst << " +#include +#include +#include +#include "Batch_Parametre.hxx" +#include "Batch_Environnement.hxx" +#include "Batch_RunTimeException.hxx" +#include "Batch_APIInternalFailureException.hxx" +#include "Batch_JobInfo_ePBS.hxx" + +namespace Batch { + + + + // Constructeurs + JobInfo_ePBS::JobInfo_ePBS(int id, string logFile) : JobInfo() + { + // On remplit les membres _param et _env + ostringstream oss; + oss << id; + _param[ID] = oss.str(); + + // read of log file + char line[128]; + ifstream fp(logFile.c_str(),ios::in); + + string status; + string sline; + int pos = string::npos; + while( (pos == string::npos) && fp.getline(line,80,'\n') ){ + sline = string(line); + pos = sline.find("job_state"); + }; + + if(pos!=string::npos){ + istringstream iss(sline); + iss >> status; + iss >> status; + iss >> status; + } + else + status = "U"; + + _param[STATE] = status; + + if( status.find("R") != string::npos) + _running = true; + + } + + // Teste si un job est present en machine + bool JobInfo_ePBS::isRunning() const + { + return _running; + } + + + // Destructeur + JobInfo_ePBS::~JobInfo_ePBS() + { + // Nothing to do + } + + // Convertit une date HH:MM:SS en secondes + long JobInfo_ePBS::HMStoLong(const string & s) + { + long hour, min, sec; + + sscanf( s.c_str(), "%ld:%ld:%ld", &hour, &min, &sec); + return ( ( ( hour * 60L ) + min ) * 60L ) + sec; + } + + // Methode pour l'interfacage avec Python (SWIG) : affichage en Python + string JobInfo_ePBS::__str__() const + { + ostringstream sst; + sst << " + +
  8. +BASIC datastream ports + + + +
    Port name Data type Idl Name Idl File
    BASIC_short short Data_Short_Port SALOME_Ports.idl
    +
  9. + +
  10. +CALCIUM datastream ports + + + + + + + + +
    Port name Data type Idl Name Idl File
    CALCIUM_integer sequence of long Calcium_Integer_Port Calcium_Ports.idl
    CALCIUM_real sequence of float Calcium_Real_Port Calcium_Ports.idl
    CALCIUM_double sequence of double Calcium_Double_Port Calcium_Ports.idl
    CALCIUM_string sequence of %string Calcium_String_Port Calcium_Ports.idl
    CALCIUM_logical sequence of boolean Calcium_Logical_Port Calcium_Ports.idl
    CALCIUM_complex sequence of float Calcium_Complex_Port Calcium_Ports.idl
    +
  11. + +
  12. +PALM datastream ports + + + + +
    Port name Data type Idl Name Idl File
    PALM_short short Palm_Data_Short_Port Palm_Ports.idl
    PALM_seq_short sequence of short Palm_Data_Seq_Short_Port Palm_Ports.idl
    +
  13. + +
+ +*/ + + diff --git a/src/DSC/DSC_User/Datastream/Calcium/CalciumCxxInterface.hxx b/src/DSC/DSC_User/Datastream/Calcium/CalciumCxxInterface.hxx new file mode 100644 index 000000000..969b510e8 --- /dev/null +++ b/src/DSC/DSC_User/Datastream/Calcium/CalciumCxxInterface.hxx @@ -0,0 +1,532 @@ +// Copyright (C) 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 +// +// +// +// File : CalciumCxxInterface.hxx +// Author : Eric Fayolle (EDF) +// Module : KERNEL +// Modified by : $LastChangedBy$ +// Date : $LastChangedDate: 2007-03-01 13:27:58 +0100 (jeu, 01 mar 2007) $ +// Id : $Id$ + +#ifndef _CALCIUM_CXXINTERFACE_HXX_ +#define _CALCIUM_CXXINTERFACE_HXX_ + +#include +#include +#include +#include "Superv_Component_i.hxx" +#include "CalciumException.hxx" +#include "CalciumTypes.hxx" +#include "CalciumGenericUsesPort.hxx" +#include "Copy2UserSpace.hxx" +#include "Copy2CorbaSpace.hxx" +#include "CalciumPortTraits.hxx" + +#include + +//#define _DEBUG_ + +template +struct IsSameType { + static const bool value = false; +}; +template +struct IsSameType { + static const bool value = true; +}; + + +#include + +namespace CalciumInterface { + + /********************* INTERFACE DE DECONNEXION *****************/ + + static inline void + ecp_cd (Superv_Component_i & component, std::string & instanceName) + { + /* TODO : Trouver le nom de l'instance SALOME*/ + if (instanceName.empty()) instanceName="UNDEFINED"; + + } + + static void + ecp_fin (Superv_Component_i & component, bool provideLastGivenValue) + { + std::vector usesPortNames; + std::vector::const_iterator it; + component.get_uses_port_names(usesPortNames); + + //Récupérer le type de réel du port est un peu difficile + //car l'interface ne donne aucune indication + + // uses_port *myUsesPort; + calcium_uses_port* myCalciumUsesPort; + + for (it=usesPortNames.begin(); it != usesPortNames.end(); ++it) { + try { + + myCalciumUsesPort= + component.Superv_Component_i::get_port< calcium_uses_port >((*it).c_str()); + +// component.Superv_Component_i::get_port(myUsesPort,(*it).c_str()); +// calcium_uses_port* myCalciumUsesPort= +// dynamic_cast(myUsesPort); + +#ifdef _DEBUG_ + std::cerr << "-------- CalciumInterface(ecp_fin) MARK 1 -|"<< *it <<"|----"<< + // typeid(myUsesPort).name() <<"-------------" << + typeid(myCalciumUsesPort).name() <<"-------------" << std::endl; +#endif + +// if ( !myCalciumUsesPort ) +// throw Superv_Component_i::BadCast(LOC(OSS()<<"Impossible de convertir le port " +// << *it << " en port de type calcium_uses_port." )); + + myCalciumUsesPort->disconnect(provideLastGivenValue); + + } catch ( const Superv_Component_i::BadCast & ex) { +#ifdef _DEBUG_ + std::cerr << ex.what() << std::endl; +#endif + throw (CalciumException(CalciumTypes::CPTPVR,ex)); + } catch ( const DSC_Exception & ex) { +#ifdef _DEBUG_ + std::cerr << ex.what() << std::endl; +#endif + // Exception venant de SupervComponent : + // PortNotDefined(CPNMVR), PortNotConnected(CPLIEN) + // ou du port uses : Dsc_Exception + // On continue à traiter la deconnexion des autres ports uses + } catch (...) { + throw (CalciumException(CalciumTypes::CPATAL,"Exception innatendue")); + // En fonction du mode de gestion des erreurs throw; + } + } + } + + + /********************* INTERFACES DE DESALLOCATION *****************/ + + // Uniquement appelé par l'utilisateur s'il utilise la 0 copie + // ( pointeur de données data==NULL à l'appel de ecp_lecture ) + // Une désallocation aura lieu uniquement si un buffer intermédiaire + // était necessaire (type utilisateur et corba diffférent) + // La propriété du buffer est rendue à CORBA sinon + template static void + ecp_free ( T1 * dataPtr ) + { + typedef typename ProvidesPortTraits::PortType PortType; + typedef typename PortType::DataManipulator DataManipulator; + typedef typename DataManipulator::Type DataType; // Attention != T1 + typedef typename DataManipulator::InnerType InnerType; + + DeleteTraits::value, DataManipulator >::apply(dataPtr); + } + + template static void + ecp_free ( T1 * dataPtr ) + { + ecp_free ( dataPtr ); + } + + + /********************* INTERFACES DE LECTURE *****************/ + + + // T1 est le type de données + // T2 est un de type Calcium permettant de sélectionner le port CORBA correspondant + // T1 et T2 sont dissociés pour discriminer le cas des nombres complexes + // -> Les données des nombres complexes sont de type float mais + // le port à utiliser est le port cplx + template static void + ecp_lecture ( Superv_Component_i & component, + int const & dependencyType, + double & ti, + double const & tf, + long & i, + const string & nomVar, + size_t bufferLength, + size_t & nRead, + T1 * &data ) + { + + assert(&component); + + typedef typename ProvidesPortTraits::PortType PortType; + typedef typename PortType::DataManipulator DataManipulator; + typedef typename DataManipulator::Type CorbaDataType; // Attention != T1 + typedef typename DataManipulator::InnerType InnerType; + CalciumTypes::DependencyType _dependencyType= + static_cast(dependencyType); + + CorbaDataType corbaData; + +#ifdef _DEBUG_ + std::cerr << "-------- CalciumInterface(ecp_lecture) MARK 1 ------------------" << std::endl; +#endif + + if (nomVar.empty()) + throw CalciumException(CalciumTypes::CPNMVR, + LOC("Le nom de la variable est ")); + PortType * port; +#ifdef _DEBUG_ + std::cout << "-------- CalciumInterface(ecp_lecture) MARK 2 ------------------" << std::endl; +#endif + + try { + port = component.Superv_Component_i::get_port< PortType > (nomVar.c_str()); +#ifdef _DEBUG_ + std::cout << "-------- CalciumInterface(ecp_lecture) MARK 3 ------------------" << std::endl; +#endif + } catch ( const Superv_Component_i::PortNotDefined & ex) { +#ifdef _DEBUG_ + std::cerr << ex.what() << std::endl; +#endif + throw (CalciumException(CalciumTypes::CPNMVR,ex)); + } catch ( const Superv_Component_i::PortNotConnected & ex) { +#ifdef _DEBUG_ + std::cerr << ex.what() << std::endl;; +#endif + throw (CalciumException(CalciumTypes::CPLIEN,ex)); + // VERIFIER LES CAS DES CODES : CPINARRET, CPSTOPSEQ, CPCTVR, CPLIEN + } catch ( const Superv_Component_i::BadCast & ex) { +#ifdef _DEBUG_ + std::cerr << ex.what() << std::endl; +#endif + throw (CalciumException(CalciumTypes::CPTPVR,ex)); + } + + // mode == mode du port + CalciumTypes::DependencyType portDependencyType = port->getDependencyType(); + + if ( portDependencyType == CalciumTypes::UNDEFINED_DEPENDENCY ) + throw CalciumException(CalciumTypes::CPIT, + LOC(OSS()<<"Le mode de dépendance de la variable " + << nomVar << " est indéfini.")); + + if ( ( portDependencyType != _dependencyType ) && + ( _dependencyType != CalciumTypes::SEQUENCE_DEPENDENCY ) ) + throw CalciumException(CalciumTypes::CPITVR, + LOC(OSS()<<"Le mode de dépendance de la variable " + << nomVar << ": " << portDependencyType + << " ne correspond pas au mode demandé.")); + + + if ( _dependencyType == CalciumTypes::TIME_DEPENDENCY ) { + corbaData = port->get(ti,tf, 0); +#ifdef _DEBUG_ + std::cout << "-------- CalciumInterface(ecp_lecture) MARK 5 ------------------" << std::endl; +#endif + } + else if ( _dependencyType == CalciumTypes::ITERATION_DEPENDENCY ) { + corbaData = port->get(0, i); +#ifdef _DEBUG_ + std::cout << "-------- CalciumInterface(ecp_lecture) MARK 6 ------------------" << std::endl; +#endif + } else { + // Lecture en séquence +#ifdef _DEBUG_ + std::cout << "-------- CalciumInterface(ecp_lecture) MARK 7 ------------------" << std::endl; +#endif + corbaData = port->next(ti,i); + } + +#ifdef _DEBUG_ + std::cout << "-------- CalciumInterface(ecp_lecture) MARK 8 ------------------" << std::endl; +#endif + size_t corbaDataSize = DataManipulator::size(corbaData); +#ifdef _DEBUG_ + std::cout << "-------- CalciumInterface(ecp_lecture) corbaDataSize : " << corbaDataSize << std::endl; +#endif + + // Vérifie si l'utilisateur demande du 0 copie + if ( data == NULL ) { + if ( bufferLength != 0 ) { + MESSAGE("bufferLength devrait valoir 0 pour l'utilisation du mode sans copie (data==NULL)"); + } + nRead = corbaDataSize; + // Si les types T1 et InnerType sont différents, il faudra effectuer tout de même une recopie + if (!IsSameType::value) data = new T1[nRead]; +#ifdef _DEBUG_ + std::cout << "-------- CalciumInterface(ecp_lecture) MARK 9 ------------------" << std::endl; +#endif + // On essaye de faire du 0 copy si les types T1 et InnerType sont les mêmes. + // Copy2UserSpace : + // La raison d'être du foncteur Copy2UserSpace est que le compilateur n'acceptera + // pas une expresion d'affectation sur des types incompatibles même + // si cette expression se trouve dans une branche non exécuté d'un test + // sur la compatibilité des types. + // En utilisant le foncteur Copy2UserSpace, seul la spécialisation en adéquation + // avec la compatibilité des types sera compilée + Copy2UserSpace< IsSameType::value, DataManipulator >::apply(data,corbaData,nRead); +#ifdef _DEBUG_ + std::cout << "-------- CalciumInterface(ecp_lecture) MARK 10 ------------------" << std::endl; +#endif + // Attention : Seul CalciumCouplingPolicy via eraseDataId doit décider de supprimer ou non + // la donnée corba associée à un DataId ! Ne pas effectuer la desallocation suivante : + // DataManipulator::delete_data(corbaData); + // ni DataManipulator::getPointer(corbaData,true); qui détruit la sequence lorsque l'on + // prend la propriété du buffer + // old : Dans les deux cas la structure CORBA n'est plus utile + // old : Si !IsSameType::value l'objet CORBA est détruit avec son contenu + // old : Dans l'autre cas seul la coquille CORBA est détruite + // L'utilisateur devra appeler ecp_free qui déterminera s'il est necessaire + // de désallouer un buffer intermédiaire ( types différents) ou de rendre la propriété + } else { + nRead = std::min < size_t > (corbaDataSize,bufferLength); +#ifdef _DEBUG_ + std::cout << "-------- CalciumInterface(ecp_lecture) MARK 11 ------------------" << std::endl; +#endif + Copy2UserSpace::apply(data,corbaData,nRead); + DataManipulator::copy(corbaData,data,nRead); + +#ifdef _DEBUG_ + std::cout << "-------- CalciumInterface(ecp_lecture) MARK 12 ------------------" << std::endl; +#endif + // Attention : Seul CalciumCouplingPolicy via eraseDataId doit décider de supprimer ou non + // la donnée corba associée à un DataId ! Ne pas effectuer la desallocation suivante : + // DataManipulator::delete_data(corbaData); + } +#ifdef _DEBUG_ + std::cout << "-------- CalciumInterface(ecp_lecture), Valeur de data : " << std::endl; + std::copy(data,data+nRead,std::ostream_iterator(std::cout," ")); + std::cout << "Ptr :" << data << std::endl; + + std::cout << "-------- CalciumInterface(ecp_lecture) MARK 13 ------------------" << std::endl; +#endif + + + return; + } + + // T1 est le type de données + template static void + ecp_lecture ( Superv_Component_i & component, + int const & dependencyType, + double & ti, + double const & tf, + long & i, + const string & nomVar, + size_t bufferLength, + size_t & nRead, + T1 * &data ) + { + ecp_lecture (component,dependencyType,ti,tf, + i,nomVar,bufferLength,nRead,data); + + } + + /********************* INTERFACES D'ECRITURE *****************/ + + // T1 : DataType + // T2 : PortType + template static void + ecp_ecriture ( Superv_Component_i & component, + int const & dependencyType, + double const & t, + long const & i, + const string & nomVar, + size_t bufferLength, + T1 const & data ) + { + + assert(&component); + + //typedef typename StarTrait::NonStarType T; + typedef typename boost::remove_all_extents< T2 >::type T2_without_extent; + typedef typename boost::remove_all_extents< T1 >::type T1_without_extent; + + typedef typename UsesPortTraits ::PortType UsesPortType; + typedef typename ProvidesPortTraits::PortType ProvidesPortType;// pour obtenir un manipulateur de données + typedef typename ProvidesPortType::DataManipulator DataManipulator; + // Verifier que l'on peut définir UsesPortType::DataManipulator + // typedef typename PortType::DataManipulator DataManipulator; + typedef typename DataManipulator::Type CorbaDataType; // Attention != T1 + typedef typename DataManipulator::InnerType InnerType; + + T1_without_extent const & _data = data; + + CalciumTypes::DependencyType _dependencyType= + static_cast(dependencyType); + +#ifdef _DEBUG_ + std::cerr << "-------- CalciumInterface(ecriture) MARK 1 ------------------" << std::endl; +#endif + if ( nomVar.empty() ) throw CalciumException(CalciumTypes::CPNMVR, + LOC("Le nom de la variable est ")); + UsesPortType * port; +#ifdef _DEBUG_ + std::cout << "-------- CalciumInterface(ecriture) MARK 2 ------------------" << std::endl; +#endif + + try { + port = component.Superv_Component_i::get_port< UsesPortType > (nomVar.c_str()); +#ifdef _DEBUG_ + std::cout << "-------- CalciumInterface(ecriture) MARK 3 ------------------" << std::endl; +#endif + } catch ( const Superv_Component_i::PortNotDefined & ex) { +#ifdef _DEBUG_ + std::cerr << ex.what() << std::endl; +#endif + throw (CalciumException(CalciumTypes::CPNMVR,ex)); + } catch ( const Superv_Component_i::PortNotConnected & ex) { +#ifdef _DEBUG_ + std::cerr << ex.what() << std::endl;; +#endif + throw (CalciumException(CalciumTypes::CPLIEN,ex)); + // VERIFIER LES CAS DES CODES : CPINARRET, CPSTOPSEQ, CPCTVR, CPLIEN + } catch ( const Superv_Component_i::BadCast & ex) { +#ifdef _DEBUG_ + std::cerr << ex.what() << std::endl; +#endif + throw (CalciumException(CalciumTypes::CPTPVR,ex)); + } + + // mode == mode du port + // On pourrait créer la méthode CORBA dans le mode de Couplage CALCIUM. + // et donc ajouter cette cette méthode uniquement dans l'IDL calcium ! + +// CalciumTypes::DependencyType portDependencyType; +// try { +// portDependencyType = port->getDependencyType(); +// std::cout << "-------- CalciumInterface(ecriture) MARK 4 ------------------" << std::endl; +// } catch ( const DSC_Exception & ex ) { +// std::cerr << ex.what() << std::endl;; +// throw (CalciumException(CalciumTypes::CPIT,ex)); +// } + + if ( _dependencyType == CalciumTypes::UNDEFINED_DEPENDENCY ) + throw CalciumException(CalciumTypes::CPIT, + LOC(OSS()<<"Le mode de dépendance demandé pour la variable " + << nomVar << " est indéfini.")); + + if ( _dependencyType == CalciumTypes::SEQUENCE_DEPENDENCY ) + throw CalciumException(CalciumTypes::CPIT, + LOC(OSS()<<"Le mode de dépendance SEQUENCE_DEPENDENCY pour la variable " + << nomVar << " est impossible en écriture.")); + + // Il faudrait que le port provides génère une exception si le mode donnée n'est pas + // le bon. La seule façon de le faire est d'envoyer -1 en temps si on n'est en itération + // et vice-versa pour informer les provides port du mode dans lequel on est. Sinon il faut + // modifier l'interface IDL pour y ajouter un mode de dépendance ! + // ----> +// if ( portDependencyType != _dependencyType ) +// throw CalciumException(CalciumTypes::CPITVR, +// LOC(OSS()<<"Le mode de dépendance de la variable " +// << nomVar << " ne correspond pas au mode demandé.")); + + + if ( bufferLength < 1 ) + throw CalciumException(CalciumTypes::CPNTNULL, + LOC(OSS()<<"Le buffer a envoyer est de taille nulle ")); + + +#ifdef _DEBUG_ + std::cout << "-------- CalciumInterface(ecriture) MARK 4 ------------------" << std::endl; +#endif + CorbaDataType corbaData; + + + // Si les types Utilisateurs et CORBA sont différents + // il faut effectuer une recopie sinon on utilise directement le + // buffer data pour constituer la séquence + // TODO : + // - Attention en mode asynchrone il faudra eventuellement + // faire une copie des données même si elles sont de même type. + // - OLD : En cas de collocalisation (du port provide et du port uses) + // OLD : il est necessaire d'effectuer une recopie du buffer car la + // OLD : séquence est envoyée au port provide par une référence sur + // OLD : la séquence locale. Or la méthode put récupère le buffer directement + // OLD : qui est alors le buffer utilisateur. Il pourrait alors arriver que : + // OLD : * Le recepteur efface le buffer emetteur + // OLD : * Le port lui-même efface le buffer de l'utilisateur ! + // OLD : Cette copie est effectuée dans GenericPortUses::put + // OLD : en fonction de la collocalisation ou non. + // - OLD :En cas de connection multiples d'un port uses distant vers plusieurs port provides + // OLD : collocalisés les ports provides partagent la même copie de la donnée ! + // OLD : Il faut effectuer une copie dans le port provides. + // OLD : Cette copie est effectuée dans GenericPortUses::put + // OLD : en fonction de la collocalisation ou non. + Copy2CorbaSpace::value, DataManipulator >::apply(corbaData,_data,bufferLength); + + //TODO : GERER LES EXCEPTIONS ICI : ex le port n'est pas connecté + if ( _dependencyType == CalciumTypes::TIME_DEPENDENCY ) { + try + { + port->put(*corbaData,t, -1); + } + catch ( const DSC_Exception & ex) + { + throw (CalciumException(CalciumTypes::CPATAL,ex.what())); + } + //Le -1 peut être traité par le cst DataIdContainer et transformé en 0 + //Etre obligé de mettre une étoile ds (*corbadata) va poser des pb pour les types <> seq +#ifdef _DEBUG_ + std::cout << "-------- CalciumInterface(ecriture) MARK 5 ------------------" << std::endl; +#endif + } + else if ( _dependencyType == CalciumTypes::ITERATION_DEPENDENCY ) { + try + { + port->put(*corbaData,-1, i); + } + catch ( const DSC_Exception & ex) + { + throw (CalciumException(CalciumTypes::CPATAL,ex.what())); + } +#ifdef _DEBUG_ + std::cout << "-------- CalciumInterface(ecriture) MARK 6 ------------------" << std::endl; +#endif + } + + +#ifdef _DEBUG_ + std::cout << "-------- CalciumInterface(ecriture), Valeur de corbaData : " << std::endl; + for (int i = 0; i < corbaData->length(); ++i) + cout << "-------- CalciumInterface(ecriture), corbaData[" << i << "] = " << (*corbaData)[i] << endl; +#endif + + // if ( !IsSameType::value ) delete corbaData; + // Supprime l'objet CORBA avec eventuellement les données qu'il contient (cas de la recopie) + delete corbaData; + +#ifdef _DEBUG_ + std::cout << "-------- CalciumInterface(ecriture) MARK 7 ------------------" << std::endl; +#endif + + return; + }; + + template static void + ecp_ecriture ( Superv_Component_i & component, + int const & dependencyType, + double const & t, + long const & i, + const string & nomVar, + size_t bufferLength, + T1 const & data ) { + ecp_ecriture (component,dependencyType,t,i,nomVar,bufferLength,data); + }; + +}; + +#endif diff --git a/src/DSC/DSC_User/Datastream/Calcium/calciumE.h b/src/DSC/DSC_User/Datastream/Calcium/calciumE.h new file mode 100644 index 000000000..49c9e57d8 --- /dev/null +++ b/src/DSC/DSC_User/Datastream/Calcium/calciumE.h @@ -0,0 +1,401 @@ +/* Copyright (C) 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 + * + * + * + * File : calcium.h + * Author : Eric Fayolle (EDF) + * Module : KERNEL + */ + +/* Outils d'Aide au Couplage de Code de Calcul : $Id$ */ + +#ifndef __CALCIUM_E_H +#define __CALCIUM_E_H + +#include + +#if defined(__STDC__) || defined(__cplusplus) || defined(c_plusplus) +#define CPNeedPrototype 1 +#else +#define CPNeedPrototype 0 +#endif + + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + +/* */ +/* */ +/* Fonctions de connexion */ +/* */ +/* */ +extern int ecp_cd( +/* ----- */ +#if CPNeedPrototype + void * component /* Pointeur de type Superv_Component_i* sur le */ + /* composant SALOME Supervisable */, + char * /* S Nom de l instance appelante*/ +#endif +); + + +/* */ +/* */ +/* Fonction de deconnexion */ +/* */ +/* */ +extern int ecp_fin( +/* ------ */ +#if CPNeedPrototype + void * component /* Pointeur de type Superv_Component_i* sur le */ + /* composant SALOME Supervisable */, + int /* E Directive de continuation */ + /* CP_CONT ou CP_ARRET */ +#endif +); + +/* */ +/* */ +/* Fonctions de libération du buffer 0 copy */ +/* */ + + extern void ecp_len_free( +#if CPNeedPrototype + int * +#endif + ); + extern void ecp_lre_free( +#if CPNeedPrototype + float * +#endif + ); + extern void ecp_ldb_free( +#if CPNeedPrototype + double * +#endif + ); + extern void ecp_llo_free( +#if CPNeedPrototype + int * +#endif + ); + extern void ecp_lcp_free( +#if CPNeedPrototype + float * +#endif + ); + extern void ecp_lch_free( +#if CPNeedPrototype + char ** +#endif + ); + + + +/* */ +/* */ +/* Fonctions de lecture bloquante 0 copy */ +/* */ +/* */ +extern int ecp_len( +/* ------ */ +#if CPNeedPrototype + void * component /* Pointeur de type Superv_Component_i* sur le */ + /* composant SALOME Supervisable */, + int /* E Type de dependance ou de lecture */ + /* CP_TEMPS, CP_ITERATION, CP_SEQUENTIEL */, + float * /* E/S Borne inf de l'intervalle de lecture */ + /* Retourne le pas lu dans le cas de */ + /* lecture sequentielle */, + float * /* E Borne Sup de l'intervalle de lecture */, + int * /* E/S Pas d'iteration a lire */ + /* Retourne le pas lu dans le cas de */ + /* lecture sequentielle */, + char * /* E Nom de la variable a lire */, + int /* E Nombre max de valeurs a lire */, + int * /* S Nombre de valeurs rellement lues */, + int ** /* E/S Tableau d'entiers pour stocker les */ + /* valeurs lues */ +#endif +); + +extern int ecp_lre( +/* ------ */ +#if CPNeedPrototype + void * component /* Pointeur de type Superv_Component_i* sur le */ + /* composant SALOME Supervisable */, + int /* E Type de dependance ou de lecture */ + /* CP_TEMPS, CP_ITERATION, CP_SEQUENTIEL */, + float * /* E/S Borne inf de l'intervalle de lecture */ + /* Retourne le pas lu dans le cas de */ + /* lecture sequentielle */, + float * /* E Borne Sup de l'intervalle de lecture */, + int * /* E/S Pas d'iteration a lire */ + /* Retourne le pas lu dans le cas de */ + /* lecture sequentielle */, + char * /* E Nom de la variable a lire */, + int /* E Nombre max de valeurs a lire */, + int * /* S Nombre de valeurs rellement lues */, + float **/* E/S Tableau de flottants pour stocker les */ + /* valeurs lues */ +#endif +); + +extern int ecp_ldb( +/* ------ */ +#if CPNeedPrototype + void * component /* Pointeur de type Superv_Component_i* sur le */ + /* composant SALOME Supervisable */, + int /* E Type de dependance ou de lecture */ + /* CP_TEMPS, CP_ITERATION, CP_SEQUENTIEL */, + double* /* E/S Borne inf de l'intervalle de lecture */ + /* Retourne le pas lu dans le cas de */ + /* lecture sequentielle */, + double* /* E Borne Sup de l'intervalle de lecture */, + int * /* E/S Pas d'iteration a lire */ + /* Retourne le pas lu dans le cas de */ + /* lecture sequentielle */, + char * /* E Nom de la variable a lire */, + int /* E Nombre max de valeurs a lire */, + int * /* S Nombre de valeurs rellement lues */, + double**/* E/S Tableau de doubles pour stocker les */ + /* valeurs lues */ +#endif +); + +extern int ecp_lcp( +/* ------ */ +#if CPNeedPrototype + void * component /* Pointeur de type Superv_Component_i* sur le */ + /* composant SALOME Supervisable */, + int /* E Type de dependance ou de lecture */ + /* CP_TEMPS, CP_ITERATION, CP_SEQUENTIEL */, + float * /* E/S Borne inf de l'intervalle de lecture */ + /* Retourne le pas lu dans le cas de */ + /* lecture sequentielle */, + float * /* E Borne Sup de l'intervalle de lecture */, + int * /* E/S Pas d'iteration lire */ + /* Retourne le pas lu dans le cas de */ + /* lecture sequentielle */, + char * /* E Nom de la variable a lire */, + int /* E Nombre max de valeurs a lire */, + int * /* S Nombre de valeurs rellement lues */, + float **/* E/S Tableau de flottants pour stocker les */ + /* valeurs lues (dimension = 2 * le nombre */ + /* de valeurs lues) */ +#endif +); + +extern int ecp_llo( +/* ------ */ +#if CPNeedPrototype + void * component /* Pointeur de type Superv_Component_i* sur le */ + /* composant SALOME Supervisable */, + int /* E Type de dependance ou de lecture */ + /* CP_TEMPS, CP_ITERATION, CP_SEQUENTIEL */, + float * /* E/S Borne inf de l'intervalle de lecture */ + /* Retourne le pas lu dans le cas de */ + /* lecture sequentielle */, + float * /* E Borne Sup de l'intervalle de lecture */, + int * /* E/S Pas d'iteration a lire */ + /* Retourne le pas lu dans le cas de */ + /* lecture sequentielle */, + char * /* E Nom de la variable a lire */, + int /* E Nombre max de valeurs a lire */, + int * /* S Nombre de valeurs rellement lues */, + int ** /* E/S Tableau d 'entier pour stocker les */ + /* valeurs lues (remplace le logiques) */ +#endif +); + +extern int ecp_lch( +/* ------ */ +#if CPNeedPrototype + void * component /* Pointeur de type Superv_Component_i* sur le */ + /* composant SALOME Supervisable */, + int /* E Type de dependance ou de lecture */ + /* CP_TEMPS, CP_ITERATION, CP_SEQUENTIEL */, + float * /* E/S Borne inf de l'intervalle de lecture */ + /* Retourne le pas lu dans le cas de */ + /* lecture sequentielle */, + float * /* E Borne Sup de l'intervalle de lecture */, + int * /* E/S Pas d'iteration a lire */ + /* Retourne le pas lu dans le cas de */ + /* lecture sequentielle */, + char * /* E Nom de la variable a lire */, + int /* E Nombre max de valeurs a lire */, + int * /* S Nombre de valeurs rellement lues */, + char **[]/*E/S Tableau de chaines pour stocker les */ + /* valeurs lues (remplace le logiques) */, + int /* E Taille des chaines du tablaeu */ +#endif +); + + + +/* */ +/* */ +/* Fonctions de lecture non bloquantes */ +/* */ +/* */ +extern int ecp_nlen( +/* ------- */ +#if CPNeedPrototype + void * component /* Pointeur de type Superv_Component_i* sur le */ + /* composant SALOME Supervisable */, + int /* E Type de dependance ou de lecture */ + /* CP_TEMPS, CP_ITERATION, CP_SEQUENTIEL */, + float * /* E/S Borne inf de l'intervalle de lecture */ + /* Retourne le pas lu dans le cas de */ + /* lecture sequentielle */, + float * /* E Borne Sup de l'intervalle de lecture */, + int * /* E/S Pas d'iteration a lire */ + /* Retourne le pas lu dans le cas de */ + /* lecture sequentielle */, + char * /* E Nom de la variable a lire */, + int /* E Nombre max de valeurs a lire */, + int * /* S Nombre de valeurs rellement lues */, + int ** /* E/S Tableau d'entiers pour stocker les */ + /* valeurs lues */ +#endif +); + +extern int ecp_nlre( +/* ------- */ +#if CPNeedPrototype + void * component /* Pointeur de type Superv_Component_i* sur le */ + /* composant SALOME Supervisable */, + int /* E Type de dependance ou de lecture */ + /* CP_TEMPS, CP_ITERATION, CP_SEQUENTIEL */, + float * /* E/S Borne inf de l'intervalle de lecture */ + /* Retourne le pas lu dans le cas de */ + /* lecture sequentielle */, + float * /* E Borne Sup de l'intervalle de lecture */, + int * /* E/S Pas d'iteration a lire */ + /* Retourne le pas lu dans le cas de */ + /* lecture sequentielle */, + char * /* E Nom de la variable a lire */, + int /* E Nombre max de valeurs a lire */, + int * /* S Nombre de valeurs rellement lues */, + float **/* E/S Tableau de flottants pour stocker les */ + /* valeurs lues */ +#endif +); + +extern int ecp_nldb( +/* ------- */ + +#if CPNeedPrototype + void * component /* Pointeur de type Superv_Component_i* sur le */ + /* composant SALOME Supervisable */, + int /* E Type de dependance ou de lecture */ + /* CP_TEMPS, CP_ITERATION, CP_SEQUENTIEL */, + double */* E/S Borne inf de l'intervalle de lecture */ + /* Retourne le pas lu dans le cas de */ + /* lecture sequentielle */, + double */* E Borne Sup de l'intervalle de lecture */, + int * /* E/S Pas d'iteration a lire */ + /* Retourne le pas lu dans le cas de */ + /* lecture sequentielle */, + char * /* E Nom de la variable a lire */, + int /* E Nombre max de valeurs a lire */, + int * /* S Nombre de valeurs rellement lues */, + double**/* E/S Tableau de doubles pour stocker les */ + /* valeurs lues */ +#endif +); + +extern int ecp_nlcp( +/* ------- */ +#if CPNeedPrototype + void * component /* Pointeur de type Superv_Component_i* sur le */ + /* composant SALOME Supervisable */, + int /* E Type de dependance ou de lecture */ + /* CP_TEMPS, CP_ITERATION, CP_SEQUENTIEL */, + float * /* E/S Borne inf de l'intervalle de lecture */ + /* Retourne le pas lu dans le cas de */ + /* lecture sequentielle */, + float * /* E Borne Sup de l'intervalle de lecture */, + int * /* E/S Pas d'iteration lire */ + /* Retourne le pas lu dans le cas de */ + /* lecture sequentielle */, + char * /* E Nom de la variable a lire */, + int /* E Nombre max de valeurs a lire */, + int * /* S Nombre de valeurs rellement lues */, + float **/* E/S Tableau de flottants pour stocker les */ + /* valeurs lues (dimension = 2 * le nombre */ + /* de valeurs lues) */ +#endif +); + +extern int ecp_nllo( +/* ------- */ +#if CPNeedPrototype + void * component /* Pointeur de type Superv_Component_i* sur le */ + /* composant SALOME Supervisable */, + int /* E Type de dependance ou de lecture */ + /* CP_TEMPS, CP_ITERATION, CP_SEQUENTIEL */, + float * /* E/S Borne inf de l'intervalle de lecture */ + /* Retourne le pas lu dans le cas de */ + /* lecture sequentielle */, + float * /* E Borne Sup de l'intervalle de lecture */, + int * /* E/S Pas d'iteration a lire */ + /* Retourne le pas lu dans le cas de */ + /* lecture sequentielle */, + char * /* E Nom de la variable a lire */, + int /* E Nombre max de valeurs a lire */, + int * /* S Nombre de valeurs rellement lues */, + int **/* E/S Tableau d 'entier pour stocker les */ + /* valeurs lues (remplace le logiques) */ +#endif +); + +extern int ecp_nlch( +/* ------- */ +#if CPNeedPrototype + void * component /* Pointeur de type Superv_Component_i* sur le */ + /* composant SALOME Supervisable */, + int /* E Type de dependance ou de lecture */ + /* CP_TEMPS, CP_ITERATION, CP_SEQUENTIEL */, + float * /* E/S Borne inf de l'intervalle de lecture */ + /* Retourne le pas lu dans le cas de */ + /* lecture sequentielle */, + float * /* E Borne Sup de l'intervalle de lecture */, + int * /* E/S Pas d'iteration a lire */ + /* Retourne le pas lu dans le cas de */ + /* lecture sequentielle */, + char * /* E Nom de la variable a lire */, + int /* E Nombre max de valeurs a lire */, + int * /* S Nombre de valeurs rellement lues */, + char **[]/* E/S Tableau de chaines pour stocker les */ + /* valeurs lues (remplace le logiques) */, + int /* E Taille des chaines du tablaeu */ +#endif +); + + + +#if defined(__cplusplus) || defined(c_plusplus) +} +#endif + + +#endif diff --git a/src/Launcher/BatchTest.cxx b/src/Launcher/BatchTest.cxx new file mode 100644 index 000000000..bb44166f4 --- /dev/null +++ b/src/Launcher/BatchTest.cxx @@ -0,0 +1,689 @@ +#include "BatchTest.hxx" + +BatchTest::BatchTest(const Engines::MachineParameters& batch_descr) +{ + _batch_descr = batch_descr; + + // Getting date + Batch::Date date = Batch::Date(time(0)); + _date = date.str(); + int lend = _date.size() ; + int i = 0 ; + while (i < lend) + { + if (_date[i] == '/' || _date[i] == '-' || _date[i] == ':' ) + { + _date[i] = '_' ; + } + i++ ; + } + + // Creating test temporary file + _test_filename = "/tmp/"; + _test_filename += _date + "_test_cluster_file_"; + _test_filename += _batch_descr.alias.in(); + _base_filename = _date + "_test_cluster_file_" + _batch_descr.alias.in(); +} + +BatchTest::~BatchTest() {} + +bool +BatchTest::test() +{ + bool rtn = false; + INFOS(std::endl + << "--- Testing batch Machine :" << std::endl + << "--- Name : " << _batch_descr.hostname << std::endl + << "--- Alias : " << _batch_descr.alias << std::endl + << "--- Protocol : " << _batch_descr.protocol << std::endl + << "--- User Name : " << _batch_descr.username << std::endl + << "--- Batch Type : " << _batch_descr.batch << std::endl + << "--- MPI Impl : " << _batch_descr.mpiImpl << std::endl + << "--- Appli Path : " << _batch_descr.applipath << std::endl + ); + + std::string result_connection("Not Tested"); + std::string result_filecopy("Not Tested"); + std::string result_getresult("Not Tested"); + std::string result_jobsubmit_simple("Not Tested"); + std::string result_jobsubmit_mpi("Not Tested"); + std::string result_appli("Not Tested"); + + result_connection = test_connection(); + result_filecopy = test_filecopy(); + result_getresult = test_getresult(); + result_jobsubmit_simple = test_jobsubmit_simple(); + result_jobsubmit_mpi = test_jobsubmit_mpi(); + result_appli = test_appli(); + + INFOS(std::endl + << "--- Test results" << std::endl + << "--- Connection : " << result_connection << std::endl + << "--- File copy : " << result_filecopy << std::endl + << "--- Get results : " << result_getresult << std::endl + << "--- Submit simple job : " << result_jobsubmit_simple << std::endl + << "--- Submit mpi job : " << result_jobsubmit_mpi << std::endl + << "--- Application : " << result_appli << std::endl + ); + + if (result_connection == "OK" and + result_filecopy == "OK" and + result_getresult == "OK" and + result_jobsubmit_simple == "OK" and + result_jobsubmit_mpi == "OK" and + result_appli == "OK") + rtn = true; + + return rtn; +} + +// For this test we use : alias, protocol, username +std::string +BatchTest::test_connection() +{ + int status; + std::string command; + std::string result("Failed : "); + std::string alias = _batch_descr.alias.in(); + std::string username = _batch_descr.username.in(); + std::string protocol = _batch_descr.protocol.in(); + + // Basic tests + if(alias == "") + { + result += "alias is empty !"; + return result; + } + if(username == "") + { + result += "username is empty !"; + return result; + } + if( protocol != "rsh" and protocol != "ssh") + { + result += "protocol unknown ! (" + protocol + ")"; + return result; + } + + // Build command + command += protocol + + " " + + username + "@" + alias; + + // Test + status = system(command.c_str()); + if(status) { + std::ostringstream oss; + oss << status; + result += "Error of connection on remote host ! status = "; + result += oss.str(); + return result; + } + + result = "OK"; + return result; +} + +// For this test we use : alias, protocol, username +std::string +BatchTest::test_filecopy() +{ + int status; + std::string home; + std::string command; + std::string result("Failed : "); + std::string alias = _batch_descr.alias.in(); + std::string username = _batch_descr.username.in(); + std::string protocol = _batch_descr.protocol.in(); + + // Getting home directory + std::string rst = get_home(&home); + if(rst != "") { + result += rst; + return result; + } + + // Writing into the tempory file + command = "echo Hello > " + _test_filename; + status = system(command.c_str()); + if(status) { + std::ostringstream oss; + oss << status; + result += "Error in creating tempory file ! status = "; + result += oss.str(); + return result; + } + + // Build command + command = "scp"; + if(protocol == "rsh") + command = "rcp"; + command += " " + _test_filename + " " + + username + "@" + alias + ":" + home; + + // Test + status = system(command.c_str()); + if(status) { + std::ostringstream oss; + oss << status; + result += "Error in copy file on remote host ! status = "; + result += oss.str(); + return result; + } + + result = "OK"; + return result; +} + +// For this test we use : alias, protocol, username +std::string +BatchTest::test_getresult() +{ + int status; + std::string home; + std::string command; + std::string result("Failed : "); + std::string alias = _batch_descr.alias.in(); + std::string username = _batch_descr.username.in(); + std::string protocol = _batch_descr.protocol.in(); + + // Getting home directory + std::string rst = get_home(&home); + if(rst != "") { + result += rst; + return result; + } + + // Build command + command = "scp"; + if(protocol == "rsh") + command = "rcp"; + command += " " + username + "@" + alias + ":" + home + + "/" + _base_filename + " " + _test_filename + "_copy"; + + // Test + status = system(command.c_str()); + if(status) { + std::ostringstream oss; + oss << status; + result += "Error in copy file from remote host ! status = "; + result += oss.str(); + return result; + } + + // Compare files + std::ifstream src_file(_test_filename.c_str()); + if (!src_file) + { + result += "Error in reading temporary file ! filename = " + _test_filename; + return result; + } + std::string cp_filename = _test_filename + "_copy"; + std::ifstream cp_file(cp_filename.c_str()); + if (!cp_file) + { + result += "Error in reading temporary copy file ! filename = " + cp_filename; + return result; + } + std::string src_firstline; + std::string cp_firstline; + std::getline(src_file, src_firstline); + std::getline(cp_file, cp_firstline); + src_file.close(); + cp_file.close(); + if (src_firstline != cp_firstline) + { + result += "Error source file and copy file are not equa ! source = " + src_firstline + " copy = " + cp_firstline; + return result; + } + + result = "OK"; + return result; +} + +std::string +BatchTest::test_jobsubmit_simple() +{ + int status; + std::string home; + std::string command; + std::string result("Failed : "); + std::string alias = _batch_descr.alias.in(); + std::string username = _batch_descr.username.in(); + std::string protocol = _batch_descr.protocol.in(); + std::string batch_type = _batch_descr.batch.in(); + + // Basic test + if (batch_type == "slurm") + { + INFOS("test_jobsubmit_simple not yet implemented for slurm... return OK"); + result = "OK"; + return result; + } + if (batch_type != "pbs") + { + result += "Batch type unknown ! : " + batch_type; + return result; + } + + // Getting home directory + std::string rst = get_home(&home); + if(rst != "") { + result += rst; + return result; + } + + // PBS test + std::string _test_file_simple = _test_filename + "_simple"; + std::ofstream file; + file.open(_test_file_simple.c_str(), std::ofstream::out); + file << "#!/bin/bash\n" + << "#PBS -l nodes=1\n" + << "#PBS -l walltime=00:01:00\n" + << "#PBS -o " + home + "/" + _date + "_simple_output.log\n" + << "#PBS -e " + home + "/" + _date + "_simple_error.log\n" + << "echo Bonjour\n" + << "echo Error >&2\n"; + file.flush(); + file.close(); + + + // Build command for copy + command = "scp"; + if(protocol == "rsh") + command = "rcp"; + command += " " + _test_file_simple + " " + + username + "@" + alias + ":" + home; + status = system(command.c_str()); + if(status) { + std::ostringstream oss; + oss << status; + result += "Error in copy job file to remote host ! status = "; + result += oss.str(); + return result; + } + + // Build command for submit job + std::string file_job_name = _test_filename + "_jobid"; + command = protocol + " " + username + "@" + alias + " qsub " + _base_filename + "_simple > " + file_job_name; + status = system(command.c_str()); + if(status) { + std::ostringstream oss; + oss << status; + result += "Error in sending qsub to remote host ! status = "; + result += oss.str(); + return result; + } + std::string jobid; + std::ifstream file_job(file_job_name.c_str()); + if (!file_job) + { + result += "Error in reading temporary file ! filename = " + file_job_name; + return result; + } + std::getline(file_job, jobid); + file_job.close(); + + // Wait the end of the job + command = protocol + " " + username + "@" + alias + " qstat -f " + jobid + " > " + file_job_name; + bool stop = false; + while (!stop) + { + status = system(command.c_str()); + if(status && status != 153 && status != 256*153) + { + std::ostringstream oss; + oss << status; + result += "Error in sending qstat to remote host ! status = "; + result += oss.str(); + return result; + } + + if(status == 153 || status == 256*153 ) + stop = true; + sleep(1); + } + + // Build command for getting results + command = "scp"; + if(protocol == "rsh") + command = "rcp"; + command += " " + + username + "@" + alias + ":" + home + "/" + _date + "_simple* /tmp"; + status = system(command.c_str()); + if(status) { + std::ostringstream oss; + oss << status; + result += "error in getting file result of qsub simple to remote host ! status = "; + result += oss.str(); + return result; + } + + // Test results + std::string normal_input; + std::string file_normal_name = "/tmp/" + _date + "_simple_output.log"; + std::ifstream file_normal(file_normal_name.c_str()); + if (!file_normal) + { + result += "Error in reading temporary file ! filename = " + file_normal_name; + return result; + } + std::getline(file_normal, normal_input); + file_normal.close(); + if (normal_input != "Bonjour") + { + result += "error from simple ouput file ! waiting for Bonjour and get : " + normal_input; + return result; + } + std::string error_input; + std::string file_error_name = "/tmp/" + _date + "_simple_error.log"; + std::ifstream file_error(file_error_name.c_str()); + if (!file_error) + { + result += "Error in reading temporary file ! filename = " + file_error_name; + return result; + } + std::getline(file_error, error_input); + file_error.close(); + if (error_input != "Error") + { + result += "error from simple error file ! waiting for Error and get : " + error_input; + return result; + } + result = "OK"; + return result; +} + +std::string +BatchTest::test_jobsubmit_mpi() +{ + int status; + std::string home; + std::string command; + MpiImpl * mpiImpl; + std::string result("Failed : "); + std::string alias = _batch_descr.alias.in(); + std::string username = _batch_descr.username.in(); + std::string protocol = _batch_descr.protocol.in(); + std::string batch_type = _batch_descr.batch.in(); + std::string mpi_type = _batch_descr.mpiImpl.in(); + + // Basic test + if(mpi_type == "lam") + mpiImpl = new MpiImpl_LAM(); + else if(mpi_type == "mpich1") + mpiImpl = new MpiImpl_MPICH1(); + else if(mpi_type == "mpich2") + mpiImpl = new MpiImpl_MPICH2(); + else if(mpi_type == "openmpi") + mpiImpl = new MpiImpl_OPENMPI(); + else + { + result += "Error MPI impl not supported : " + mpi_type; + return result; + } + + // SLURM not yet implemented... + if (batch_type == "slurm") + { + INFOS("test_jobsubmit_simple not yet implemented for slurm... return OK"); + result = "OK"; + return result; + } + + // Getting home directory + std::string rst = get_home(&home); + if(rst != "") { + result += rst; + return result; + } + + // MPI test + std::string _test_file_script = _test_filename + "_script"; + std::ofstream file_script; + file_script.open(_test_file_script.c_str(), std::ofstream::out); + file_script << "#!/bin/bash\n" + << "echo HELLO MPI\n"; + file_script.flush(); + file_script.close(); + chmod(_test_file_script.c_str(), 0x1ED); + + std::string _test_file_mpi = _test_filename + "_mpi"; + std::ofstream file_mpi; + file_mpi.open(_test_file_mpi.c_str(), std::ofstream::out); + file_mpi << "#!/bin/bash\n" + << "#PBS -l nodes=1\n" + << "#PBS -l walltime=00:01:00\n" + << "#PBS -o " << home << "/" << _date << "_mpi_output.log\n" + << "#PBS -e " << home << "/" << _date << "_mpi_error.log\n" + << mpiImpl->boot("${PBS_NODEFILE}", 1) + << mpiImpl->run("${PBS_NODEFILE}", 1, _base_filename + "_script") + << mpiImpl->halt(); + file_mpi.flush(); + file_mpi.close(); + + + // Build command for copy + command = "scp"; + if(protocol == "rsh") + command = "rcp"; + command += " " + _test_file_script + " " + + username + "@" + alias + ":" + home; + status = system(command.c_str()); + if(status) { + std::ostringstream oss; + oss << status; + result += "Error in copy job file to remote host ! status = "; + result += oss.str(); + return result; + } + command = "scp"; + if(protocol == "rsh") + command = "rcp"; + command += " " + _test_file_mpi + " " + + username + "@" + alias + ":" + home; + status = system(command.c_str()); + if(status) { + std::ostringstream oss; + oss << status; + result += "Error in copy job file to remote host ! status = "; + result += oss.str(); + return result; + } + + // Build command for submit job + std::string file_job_name = _test_filename + "_jobid"; + command = protocol + " " + username + "@" + alias + " qsub " + _base_filename + "_mpi > " + file_job_name; + status = system(command.c_str()); + if(status) { + std::ostringstream oss; + oss << status; + result += "Error in sending qsub to remote host ! status = "; + result += oss.str(); + return result; + } + std::string jobid; + std::ifstream file_job(file_job_name.c_str()); + if (!file_job) + { + result += "Error in reading temporary file ! filename = " + file_job_name; + return result; + } + std::getline(file_job, jobid); + file_job.close(); + + // Wait the end of the job + command = protocol + " " + username + "@" + alias + " qstat -f " + jobid + " > " + file_job_name; + bool stop = false; + while (!stop) + { + status = system(command.c_str()); + if(status && status != 153 && status != 256*153) + { + std::ostringstream oss; + oss << status; + result += "Error in sending qstat to remote host ! status = "; + result += oss.str(); + return result; + } + + if(status == 153 || status == 256*153 ) + stop = true; + sleep(1); + } + + // Build command for getting results + command = "scp"; + if(protocol == "rsh") + command = "rcp"; + command += " " + + username + "@" + alias + ":" + home + "/" + _date + "_mpi* /tmp"; + status = system(command.c_str()); + if(status) { + std::ostringstream oss; + oss << status; + result += "error in getting file result of qsub mpi from remote host ! status = "; + result += oss.str(); + return result; + } + + // Test results + std::string normal_input; + std::string file_normal_name = "/tmp/" + _date + "_mpi_output.log"; + std::ifstream file_normal(file_normal_name.c_str()); + if (!file_normal) + { + result += "Error in reading temporary file ! filename = " + file_normal_name; + return result; + } + bool test_ok = false; + while (std::getline(file_normal, normal_input)) + { + if (normal_input == "HELLO MPI") + test_ok = true; + } + file_normal.close(); + if (!test_ok) + { + result += "error from mpi ouput file ! waiting for HELLO MPI please watch /tmp/" + _date + "_mpi_output.log file"; + return result; + } + result = "OK"; + return result; +} + +std::string +BatchTest::test_appli() +{ + int status; + std::string home; + std::string command; + std::string result("Failed : "); + std::string alias = _batch_descr.alias.in(); + std::string username = _batch_descr.username.in(); + std::string protocol = _batch_descr.protocol.in(); + std::string applipath = _batch_descr.applipath.in(); + + // Getting home directory + std::string rst = get_home(&home); + if(rst != "") { + result += rst; + return result; + } + + std::string _test_file_appli = _test_filename + "_appli_test"; + std::ofstream file_appli; + file_appli.open(_test_file_appli.c_str(), std::ofstream::out); + file_appli << "#!/bin/bash\n" + << "if [ -f " << applipath << "/runAppli ]\n" + << "then\n" + << " echo OK\n" + << "else\n" + << " echo NOK\n" + << "fi\n"; + file_appli.flush(); + file_appli.close(); + + // Build command for copy + command = "scp"; + if(protocol == "rsh") + command = "rcp"; + command += " " + _test_file_appli + " " + + username + "@" + alias + ":" + home; + status = system(command.c_str()); + if(status) { + std::ostringstream oss; + oss << status; + result += "Error in copy appli test file to remote host ! status = "; + result += oss.str(); + return result; + } + + // Launch test + command = protocol + " " + username + "@" + alias + + " sh " + home + "/" + _base_filename + "_appli_test > " + + _test_filename + "_appli_test_result"; + + status = system(command.c_str()); + if(status) { + std::ostringstream oss; + oss << status; + result += "Error in launching appli test on remote host ! status = "; + result += oss.str(); + return result; + } + + // Read test result + std::string rst_appli; + std::string file_appli_result_name = _test_filename + "_appli_test_result"; + std::ifstream file_appli_result(file_appli_result_name.c_str()); + if (!file_appli_result) + { + result += "Error in reading temporary file ! filename = " + file_appli_result_name; + return result; + } + std::getline(file_appli_result, rst_appli); + file_appli_result.close(); + + if (rst_appli != "OK") + { + result += "Error checking application on remote host ! result = " + rst; + return result; + } + + result = "OK"; + return result; +} + +// Useful methods +std::string +BatchTest::get_home(std::string * home) +{ + int status; + std::string result = ""; + std::string command; + std::string alias = _batch_descr.alias.in(); + std::string username = _batch_descr.username.in(); + std::string protocol = _batch_descr.protocol.in(); + std::string file_home_name = _test_filename + "_home"; + + command = protocol + " " + username + "@" + alias + " 'echo $HOME' > " + file_home_name; + status = system(command.c_str()); + if(status) { + std::ostringstream oss; + oss << status; + result += "Error in getting home directory ! status = "; + result += oss.str(); + return result; + } + + std::ifstream file_home(file_home_name.c_str()); + if (!file_home) + { + result += "Error in reading temporary file ! filename = " + file_home_name; + return result; + } + std::getline(file_home, *home); + file_home.close(); + return result; +} diff --git a/src/Launcher/BatchTest.hxx b/src/Launcher/BatchTest.hxx new file mode 100644 index 000000000..600b71bee --- /dev/null +++ b/src/Launcher/BatchTest.hxx @@ -0,0 +1,60 @@ +// Copyright (C) 2008 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 +// + +#ifndef __BatchTest_HXX__ +#define __BatchTest_HXX__ + +#include +#include +#include + +#include +#include "utilities.h" +#include CORBA_CLIENT_HEADER(SALOME_ContainerManager) + +#include "Batch_Date.hxx" +#include "MpiImpl.hxx" + +class BatchTest +{ + public: + BatchTest(const Engines::MachineParameters& batch_descr); + virtual ~BatchTest(); + + bool test(); + + std::string test_connection(); + std::string test_filecopy(); + std::string test_getresult(); + std::string test_jobsubmit_simple(); + std::string test_jobsubmit_mpi(); + std::string test_appli(); + + protected: + std::string get_home(std::string * home); + + private: + Engines::MachineParameters _batch_descr; + std::string _test_filename; + std::string _base_filename; + std::string _date; +}; + +#endif diff --git a/src/Launcher/Launcher.cxx b/src/Launcher/Launcher.cxx new file mode 100644 index 000000000..8a92e1d87 --- /dev/null +++ b/src/Launcher/Launcher.cxx @@ -0,0 +1,628 @@ +// Copyright (C) 2005 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 +// +#include "Batch_Date.hxx" +#include "Batch_FactBatchManager_eLSF.hxx" +#include "Batch_FactBatchManager_ePBS.hxx" +#include "Launcher.hxx" +#include +#include +#include + +using namespace std; + +//============================================================================= +/*! + * Constructor + * \param orb + * Define a CORBA single thread policy for the server, which avoid to deal + * with non thread-safe usage like Change_Directory in SALOME naming service + */ +//============================================================================= + +Launcher_cpp::Launcher_cpp() +{ + cerr << "Launcher_cpp constructor" << endl; +} + +//============================================================================= +/*! + * destructor + */ +//============================================================================= + +Launcher_cpp::~Launcher_cpp() +{ + cerr << "Launcher_cpp destructor" << endl; + std::map < string, Batch::BatchManager_eClient * >::const_iterator it1; + for(it1=_batchmap.begin();it1!=_batchmap.end();it1++) + delete it1->second; + std::map < std::pair , Batch::Job* >::const_iterator it2; + for(it2=_jobmap.begin();it2!=_jobmap.end();it2++) + delete it2->second; +} + +//============================================================================= +/*! CORBA Method: + * Submit a batch job on a cluster and returns the JobId + * \param fileToExecute : .py/.exe/.sh/... to execute on the batch cluster + * \param filesToExport : to export on the batch cluster + * \param NumberOfProcessors : Number of processors needed on the batch cluster + * \param params : Constraints for the choice of the batch cluster + */ +//============================================================================= +long Launcher_cpp::submitSalomeJob( const string fileToExecute , + const vector& filesToExport , + const vector& filesToImport , + const batchParams& batch_params, + const machineParams& params) throw(LauncherException) +{ + cerr << "BEGIN OF Launcher_cpp::submitSalomeJob" << endl; + long jobId; + vector aMachineList; + + // check batch params + if ( !check(batch_params) ) + throw LauncherException("Batch parameters are bad (see informations above)"); + + // find a cluster matching the structure params + vector aCompoList ; + try{ + aMachineList = _ResManager->GetFittingResources(params, aCompoList); + } + catch(const ResourcesException &ex){ + throw LauncherException(ex.msg.c_str()); + } + if (aMachineList.size() == 0) + throw LauncherException("No resources have been found with your parameters"); + + ParserResourcesType p = _ResManager->GetResourcesList(aMachineList[0]); + string clustername(p.Alias); + cerr << "Choose cluster: " << clustername << endl; + + // search batch manager for that cluster in map or instanciate one + map < string, Batch::BatchManager_eClient * >::const_iterator it = _batchmap.find(clustername); + if(it == _batchmap.end()) + { + _batchmap[clustername] = FactoryBatchManager(p); + // TODO: Add a test for the cluster ! + } + + try{ + // tmp directory on cluster to put files to execute + string tmpdir = getTmpDirForBatchFiles(); + + // create and submit job on cluster + Batch::Parametre param; + param[USER] = p.UserName; + param[EXECUTABLE] = buildSalomeCouplingScript(fileToExecute,tmpdir,p); + param[INFILE] = Batch::Couple( fileToExecute, getRemoteFile(tmpdir,fileToExecute) ); + for(int i=0;isubmitJob(*job); + + // get job id in long + istringstream iss(jid.getReference()); + iss >> jobId; + + _jobmap[ pair(clustername,jobId) ] = job; + } + catch(const Batch::EmulationException &ex){ + throw LauncherException(ex.msg.c_str()); + } + + return jobId; +} + +//============================================================================= +/*! CORBA Method: + * Query a batch job on a cluster and returns the status of job + * \param jobId : identification of Salome job + * \param params : Constraints for the choice of the batch cluster + */ +//============================================================================= +string Launcher_cpp::querySalomeJob( long id, + const machineParams& params) throw(LauncherException) +{ + // find a cluster matching params structure + vector aCompoList ; + vector aMachineList = _ResManager->GetFittingResources( params , aCompoList ) ; + ParserResourcesType p = _ResManager->GetResourcesList(aMachineList[0]); + string clustername(p.Alias); + + // search batch manager for that cluster in map + std::map < string, Batch::BatchManager_eClient * >::const_iterator it = _batchmap.find(clustername); + if(it == _batchmap.end()) + throw LauncherException("no batchmanager for that cluster"); + + ostringstream oss; + oss << id; + Batch::JobId jobId( _batchmap[clustername], oss.str() ); + + Batch::JobInfo jinfo = jobId.queryJob(); + Batch::Parametre par = jinfo.getParametre(); + return par[STATE]; +} + +//============================================================================= +/*! CORBA Method: + * Delete a batch job on a cluster + * \param jobId : identification of Salome job + * \param params : Constraints for the choice of the batch cluster + */ +//============================================================================= +void Launcher_cpp::deleteSalomeJob( const long id, + const machineParams& params) throw(LauncherException) +{ + // find a cluster matching params structure + vector aCompoList ; + vector aMachineList = _ResManager->GetFittingResources( params , aCompoList ) ; + ParserResourcesType p = _ResManager->GetResourcesList(aMachineList[0]); + string clustername(p.Alias); + + // search batch manager for that cluster in map + map < string, Batch::BatchManager_eClient * >::const_iterator it = _batchmap.find(clustername); + if(it == _batchmap.end()) + throw LauncherException("no batchmanager for that cluster"); + + ostringstream oss; + oss << id; + Batch::JobId jobId( _batchmap[clustername], oss.str() ); + + jobId.deleteJob(); +} + +//============================================================================= +/*! CORBA Method: + * Get result files of job on a cluster + * \param jobId : identification of Salome job + * \param params : Constraints for the choice of the batch cluster + */ +//============================================================================= +void Launcher_cpp::getResultSalomeJob( const string directory, + const long id, + const machineParams& params) throw(LauncherException) +{ + vector aCompoList ; + vector aMachineList = _ResManager->GetFittingResources( params , aCompoList ) ; + ParserResourcesType p = _ResManager->GetResourcesList(aMachineList[0]); + string clustername(p.Alias); + + // search batch manager for that cluster in map + map < string, Batch::BatchManager_eClient * >::const_iterator it = _batchmap.find(clustername); + if(it == _batchmap.end()) + throw LauncherException("no batchmanager for that cluster"); + + Batch::Job* job = _jobmap[ pair(clustername,id) ]; + + _batchmap[clustername]->importOutputFiles( *job, directory ); +} + +//============================================================================= +/*! + * Factory to instanciate the good batch manager for choosen cluster. + */ +//============================================================================= + +Batch::BatchManager_eClient *Launcher_cpp::FactoryBatchManager( const ParserResourcesType& params ) throw(LauncherException) +{ + + std::string hostname, protocol, mpi; + Batch::FactBatchManager_eClient* fact; + + hostname = params.Alias; + switch(params.Protocol){ + case rsh: + protocol = "rsh"; + break; + case ssh: + protocol = "ssh"; + break; + default: + throw LauncherException("unknown protocol"); + break; + } + switch(params.mpi){ + case lam: + mpi = "lam"; + break; + case mpich1: + mpi = "mpich1"; + break; + case mpich2: + mpi = "mpich2"; + break; + case openmpi: + mpi = "openmpi"; + break; + case slurm: + mpi = "slurm"; + break; + default: + mpi = "indif"; + break; + } + cerr << "Instanciation of batch manager" << endl; + switch( params.Batch ){ + case pbs: + cerr << "Instantiation of PBS batch manager" << endl; + fact = new Batch::FactBatchManager_ePBS; + break; + case lsf: + cerr << "Instantiation of LSF batch manager" << endl; + fact = new Batch::FactBatchManager_eLSF; + break; + default: + cerr << "BATCH = " << params.Batch << endl; + throw LauncherException("no batchmanager for that cluster"); + } + return (*fact)(hostname.c_str(),protocol.c_str(),mpi.c_str()); +} + +string Launcher_cpp::buildSalomeCouplingScript(const string fileToExecute, const string dirForTmpFiles, const ParserResourcesType& params) +{ + int idx = dirForTmpFiles.find("Batch/"); + std::string filelogtemp = dirForTmpFiles.substr(idx+6, dirForTmpFiles.length()); + + string::size_type p1 = fileToExecute.find_last_of("/"); + string::size_type p2 = fileToExecute.find_last_of("."); + std::string fileNameToExecute = fileToExecute.substr(p1+1,p2-p1-1); + std::string TmpFileName = "/tmp/runSalome_" + fileNameToExecute + ".sh"; + + MpiImpl* mpiImpl = FactoryMpiImpl(params.mpi); + + ofstream tempOutputFile; + tempOutputFile.open(TmpFileName.c_str(), ofstream::out ); + + // Begin + tempOutputFile << "#! /bin/sh -f" << endl ; + tempOutputFile << "cd " ; + tempOutputFile << params.AppliPath << endl ; + tempOutputFile << "export SALOME_BATCH=1\n"; + tempOutputFile << "export PYTHONPATH=~/" ; + tempOutputFile << dirForTmpFiles ; + tempOutputFile << ":$PYTHONPATH" << endl ; + + // Test node rank + tempOutputFile << "if test " ; + tempOutputFile << mpiImpl->rank() ; + tempOutputFile << " = 0; then" << endl ; + + // ----------------------------------------------- + // Code for rank 0 : launch runAppli and a container + // RunAppli + if(params.ModulesList.size()>0) + tempOutputFile << " ./runAppli --terminal --modules=" ; + else + tempOutputFile << " ./runAppli --terminal "; + for ( int i = 0 ; i < params.ModulesList.size() ; i++ ) { + tempOutputFile << params.ModulesList[i] ; + if ( i != params.ModulesList.size()-1 ) + tempOutputFile << "," ; + } + tempOutputFile << " --standalone=registry,study,moduleCatalog --ns-port-log=" + << filelogtemp + << " &\n"; + + // Wait NamingService + tempOutputFile << " current=0\n" + << " stop=20\n" + << " while ! test -f " << filelogtemp << "\n" + << " do\n" + << " sleep 2\n" + << " let current=current+1\n" + << " if [ \"$current\" -eq \"$stop\" ] ; then\n" + << " echo Error Naming Service failed ! >&2" + << " exit\n" + << " fi\n" + << " done\n" + << " port=`cat " << filelogtemp << "`\n"; + + // Wait other containers + tempOutputFile << " for ((ip=1; ip < "; + tempOutputFile << mpiImpl->size(); + tempOutputFile << " ; ip++))" << endl; + tempOutputFile << " do" << endl ; + tempOutputFile << " arglist=\"$arglist YACS_Server_\"$ip" << endl ; + tempOutputFile << " done" << endl ; + tempOutputFile << " sleep 5" << endl ; + tempOutputFile << " ./runSession waitContainers.py $arglist" << endl ; + + // Launch user script + tempOutputFile << " ./runSession python ~/" << dirForTmpFiles << "/" << fileNameToExecute << ".py" << endl; + + // Stop application + tempOutputFile << " rm " << filelogtemp << "\n" + << " ./runSession shutdownSalome.py" << endl; + + // ------------------------------------- + // Other nodes launch a container + tempOutputFile << "else" << endl ; + + // Wait NamingService + tempOutputFile << " current=0\n" + << " stop=20\n" + << " while ! test -f " << filelogtemp << "\n" + << " do\n" + << " sleep 2\n" + << " let current=current+1\n" + << " if [ \"$current\" -eq \"$stop\" ] ; then\n" + << " echo Error Naming Service failed ! >&2" + << " exit\n" + << " fi\n" + << " done\n" + << " port=`cat " << filelogtemp << "`\n"; + + // Launching container + tempOutputFile << " ./runSession SALOME_Container YACS_Server_"; + tempOutputFile << mpiImpl->rank() + << " > ~/" << dirForTmpFiles << "/YACS_Server_" + << mpiImpl->rank() << "_container_log." << filelogtemp + << " 2>&1\n"; + tempOutputFile << "fi" << endl ; + tempOutputFile.flush(); + tempOutputFile.close(); + chmod(TmpFileName.c_str(), 0x1ED); + cerr << TmpFileName.c_str() << endl; + + delete mpiImpl; + + return TmpFileName; + +} + +MpiImpl *Launcher_cpp::FactoryMpiImpl(MpiImplType mpi) throw(LauncherException) +{ + switch(mpi){ + case lam: + return new MpiImpl_LAM(); + case mpich1: + return new MpiImpl_MPICH1(); + case mpich2: + return new MpiImpl_MPICH2(); + case openmpi: + return new MpiImpl_OPENMPI(); + case slurm: + return new MpiImpl_SLURM(); + case indif: + throw LauncherException("you must specify a mpi implementation in CatalogResources.xml file"); + default: + ostringstream oss; + oss << mpi << " : not yet implemented"; + throw LauncherException(oss.str().c_str()); + } + +} + +string Launcher_cpp::getTmpDirForBatchFiles() +{ + string ret; + string thedate; + + // Adding date to the directory name + Batch::Date date = Batch::Date(time(0)); + thedate = date.str(); + int lend = thedate.size() ; + int i = 0 ; + while ( i < lend ) { + if ( thedate[i] == '/' || thedate[i] == '-' || thedate[i] == ':' ) { + thedate[i] = '_' ; + } + i++ ; + } + + ret = string("Batch/"); + ret += thedate; + return ret; +} + +string Launcher_cpp::getRemoteFile( std::string remoteDir, std::string localFile ) +{ + string::size_type pos = localFile.find_last_of("/") + 1; + int ln = localFile.length() - pos; + string remoteFile = remoteDir + "/" + localFile.substr(pos,ln); + return remoteFile; +} + +bool Launcher_cpp::check(const batchParams& batch_params) +{ + bool rtn = true; + cerr << "Job parameters are :" << endl; + cerr << "Directory : $HOME/Batch/$date" << endl; + + // check expected_during_time (check the format) + std::string edt_info = batch_params.expected_during_time; + std::string edt_value = batch_params.expected_during_time; + if (edt_value != "") { + std::string begin_edt_value = edt_value.substr(0, 2); + std::string mid_edt_value = edt_value.substr(2, 1); + std::string end_edt_value = edt_value.substr(3); + + long value; + std::istringstream iss(begin_edt_value); + if (!(iss >> value)) { + edt_info = "Error on definition ! : " + edt_value; + rtn = false; + } + else if (value < 0) { + edt_info = "Error on definition time is negative ! : " + value; + rtn = false; + } + std::istringstream iss_2(end_edt_value); + if (!(iss_2 >> value)) { + edt_info = "Error on definition ! : " + edt_value; + rtn = false; + } + else if (value < 0) { + edt_info = "Error on definition time is negative ! : " + value; + rtn = false; + } + if (mid_edt_value != ":") { + edt_info = "Error on definition ! :" + edt_value; + rtn = false; + } + } + else { + edt_info = "No value given"; + } + cerr << "Expected during time : " << edt_info << endl;; + + // check memory (check the format) + std::string mem_info; + std::string mem_value = batch_params.mem; + if (mem_value != "") { + std::string begin_mem_value = mem_value.substr(0, mem_value.length()-2); + long re_mem_value; + std::istringstream iss(begin_mem_value); + if (!(iss >> re_mem_value)) { + mem_info = "Error on definition ! : " + mem_value; + rtn = false; + } + else if (re_mem_value <= 0) { + mem_info = "Error on definition memory is negative ! : " + mem_value; + rtn = false; + } + std::string end_mem_value = mem_value.substr(mem_value.length()-2); + if (end_mem_value != "gb" and end_mem_value != "mb") { + mem_info = "Error on definition, type is bad ! " + mem_value; + rtn = false; + } + } + else { + mem_info = "No value given"; + } + cerr << "Memory : " << mem_info << endl; + + // check nb_proc + std::string nb_proc_info; + ostringstream nb_proc_value; + nb_proc_value << batch_params.nb_proc; + if(batch_params.nb_proc <= 0) { + nb_proc_info = "Bad value ! nb_proc = "; + nb_proc_info += nb_proc_value.str(); + rtn = false; + } + else { + nb_proc_info = nb_proc_value.str(); + } + cerr << "Nb of processors : " << nb_proc_info << endl; + + return rtn; +} + +long Launcher_cpp::getWallTime(std::string edt) +{ + long hh, mm, ret; + + if( edt.size() == 0 ) + return 0; + + string::size_type pos = edt.find(":"); + string h = edt.substr(0,pos); + string m = edt.substr(pos+1,edt.size()-pos+1); + istringstream issh(h); + issh >> hh; + istringstream issm(m); + issm >> mm; + ret = hh*60 + mm; + return ret; +} + +long Launcher_cpp::getRamSize(std::string mem) +{ + long mv; + + if( mem.size() == 0 ) + return 0; + + string ram = mem.substr(0,mem.size()-2); + istringstream iss(ram); + iss >> mv; + string unity = mem.substr(mem.size()-2,2); + if( (unity.find("gb") != string::npos) || (unity.find("GB") != string::npos) ) + return mv*1024; + else if( (unity.find("mb") != string::npos) || (unity.find("MB") != string::npos) ) + return mv; + else if( (unity.find("kb") != string::npos) || (unity.find("KB") != string::npos) ) + return mv/1024; + else if( (unity.find("b") != string::npos) || (unity.find("B") != string::npos) ) + return mv/(1024*1024); + else + return 0; +} + +std::string +Launcher_cpp::getHomeDir(const ParserResourcesType& p, const std::string& tmpdir) +{ + std::string home; + std::string command; + int idx = tmpdir.find("Batch/"); + std::string filelogtemp = tmpdir.substr(idx+6, tmpdir.length()); + filelogtemp = "/tmp/logs" + filelogtemp + "_home"; + + if( p.Protocol == rsh ) + command = "rsh "; + else if( p.Protocol == ssh ) + command = "ssh "; + else + throw LauncherException("Unknown protocol"); + if (p.UserName != ""){ + command += p.UserName; + command += "@"; + } + command += p.Alias; + command += " 'echo $HOME' > "; + command += filelogtemp; + std::cerr << command.c_str() << std::endl; + int status = system(command.c_str()); + if(status) + throw LauncherException("Error of launching home command on remote host"); + + std::ifstream file_home(filelogtemp.c_str()); + std::getline(file_home, home); + file_home.close(); + return home; +} diff --git a/src/Launcher/Launcher.hxx b/src/Launcher/Launcher.hxx new file mode 100644 index 000000000..84dd59dd5 --- /dev/null +++ b/src/Launcher/Launcher.hxx @@ -0,0 +1,79 @@ +// Copyright (C) 2005 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 +// +#ifndef __LAUNCHER_HXX__ +#define __LAUNCHER_HXX__ + +#include "Batch_BatchManager_eClient.hxx" +#include "ResourcesManager.hxx" + +#include + +struct batchParams{ + std::string batch_directory; + std::string expected_during_time; + std::string mem; + unsigned long nb_proc; +}; + +class LauncherException +{ +public: + const std::string msg; + + LauncherException(const std::string m) : msg(m) {} +}; + +class Launcher_cpp +{ + +public: + Launcher_cpp(); + ~Launcher_cpp(); + + long submitSalomeJob(const std::string fileToExecute , + const std::vector& filesToExport , + const std::vector& filesToImport , + const batchParams& batch_params, + const machineParams& params) throw(LauncherException); + + std::string querySalomeJob( const long jobId, const machineParams& params) throw(LauncherException); + void deleteSalomeJob( const long jobId, const machineParams& params) throw(LauncherException); + void getResultSalomeJob( const std::string directory, const long jobId, const machineParams& params ) throw(LauncherException); + + void SetResourcesManager( ResourcesManager_cpp* rm ) { _ResManager = rm; } + +protected: + + std::string buildSalomeCouplingScript(const string fileToExecute, const string dirForTmpFiles, const ParserResourcesType& params); + MpiImpl *FactoryMpiImpl(MpiImplType mpiImpl) throw(LauncherException); + Batch::BatchManager_eClient *FactoryBatchManager( const ParserResourcesType& params ) throw(LauncherException); + std::string getTmpDirForBatchFiles(); + std::string getRemoteFile( std::string remoteDir, std::string localFile ); + std::string getHomeDir(const ParserResourcesType& p, const std::string & tmpdir); + + std::map _batchmap; + std::map < std::pair , Batch::Job* > _jobmap; + ResourcesManager_cpp *_ResManager; + bool check(const batchParams& batch_params); + long getWallTime(std::string edt); + long getRamSize(std::string mem); +}; + +#endif diff --git a/src/ParallelContainer/SALOME_ParallelContainerProxy_i.cxx b/src/ParallelContainer/SALOME_ParallelContainerProxy_i.cxx new file mode 100644 index 000000000..c88588c00 --- /dev/null +++ b/src/ParallelContainer/SALOME_ParallelContainerProxy_i.cxx @@ -0,0 +1,43 @@ +// SALOME_ParallelContainerProxy : implementation of container and engine for Parallel Kernel +// +// Copyright (C) 2008 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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org +// +// File : SALOME_ParallelContainerProxy_i.cxx +// Author : André RIBES, EDF + +#include "SALOME_ParallelContainerProxy_i.hxx" + +Container_proxy_impl_final::Container_proxy_impl_final(CORBA::ORB_ptr orb, + paco_fabrique_thread * fab_thread, + bool is_a_return_proxy) : + Engines::Container_proxy_impl(orb, fab_thread, is_a_return_proxy), + InterfaceManager_impl(orb, fab_thread, is_a_return_proxy) +{} + +Container_proxy_impl_final:: ~Container_proxy_impl_final() {} + +void +Container_proxy_impl_final::Shutdown() +{ + INFOS("Shutdown Parallel Proxy"); + if(!CORBA::is_nil(_orb)) + _orb->shutdown(0); +} + diff --git a/src/ParallelContainer/SALOME_ParallelContainerProxy_i.hxx b/src/ParallelContainer/SALOME_ParallelContainerProxy_i.hxx new file mode 100644 index 000000000..77d59144f --- /dev/null +++ b/src/ParallelContainer/SALOME_ParallelContainerProxy_i.hxx @@ -0,0 +1,44 @@ +// SALOME_ParallelContainerProxy : implementation of container and engine for Parallel Kernel +// +// Copyright (C) 2008 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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org +// +// File : SALOME_ParallelContainerProxy_i.hxx +// Author : André RIBES, EDF + +#ifndef _SALOME_PARALLEL_CONTAINER_PROXY_I_HXX_ +#define _SALOME_PARALLEL_CONTAINER_PROXY_I_HXX_ + +#include "utilities.h" +#include "SALOME_ComponentPaCO_Engines_Container_server.h" + +class Container_proxy_impl_final : + public Engines::Container_proxy_impl +{ + public: + Container_proxy_impl_final(CORBA::ORB_ptr orb, + paco_fabrique_thread * fab_thread, + bool is_a_return_proxy = false); + + virtual ~Container_proxy_impl_final(); + + virtual void Shutdown(); +}; + +#endif diff --git a/src/ResourcesManager/ResourcesManager.cxx b/src/ResourcesManager/ResourcesManager.cxx new file mode 100644 index 000000000..ddf3712ff --- /dev/null +++ b/src/ResourcesManager/ResourcesManager.cxx @@ -0,0 +1,488 @@ +// Copyright (C) 2005 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 +// +#include "ResourcesManager.hxx" +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "utilities.h" + +#define MAX_SIZE_FOR_HOSTNAME 256; + +using namespace std; + +//============================================================================= +/*! + * just for test + */ +//============================================================================= + +ResourcesManager_cpp:: +ResourcesManager_cpp(const char *xmlFilePath) : + _path_resources(xmlFilePath) +{ + MESSAGE ( "ResourcesManager_cpp constructor" ); +} + +//============================================================================= +/*! + * Standard constructor, parse resource file. + * - if ${APPLI} exists in environment, + * look for ${HOME}/${APPLI}/CatalogResources.xml + * - else look for default: + * ${KERNEL_ROOT_DIR}/share/salome/resources/kernel/CatalogResources.xml + * - parse XML resource file. + */ +//============================================================================= + +ResourcesManager_cpp::ResourcesManager_cpp() +{ + MESSAGE ( "ResourcesManager_cpp constructor" ); + _isAppliSalomeDefined = (getenv("APPLI") != 0); + + if (_isAppliSalomeDefined) + { + _path_resources = getenv("HOME"); + _path_resources += "/"; + _path_resources += getenv("APPLI"); + _path_resources += "/CatalogResources.xml"; + } + + else + { + _path_resources = getenv("KERNEL_ROOT_DIR"); + _path_resources += "/share/salome/resources/kernel/CatalogResources.xml"; + } + + ParseXmlFile(); + MESSAGE ( "ResourcesManager_cpp constructor end" ); +} + +//============================================================================= +/*! + * Standard Destructor + */ +//============================================================================= + +ResourcesManager_cpp::~ResourcesManager_cpp() +{ + MESSAGE ( "ResourcesManager_cpp destructor" ); +} + +//============================================================================= +/*! + * get the list of name of ressources fitting for the specified module. + * If hostname specified, check it is local or known in resources catalog. + * + * Else + * - select first machines with corresponding OS (all machines if + * parameter OS empty), + * - then select the sublist of machines on witch the module is known + * (if the result is empty, that probably means that the inventory of + * modules is probably not done, so give complete list from previous step) + */ +//============================================================================= + +std::vector +ResourcesManager_cpp::GetFittingResources(const machineParams& params, + const std::vector& componentList) throw(ResourcesException) +{ +// cerr << "ResourcesManager_cpp::GetFittingResources" << endl; + vector vec; + + ParseXmlFile(); + + const char *hostname = params.hostname.c_str(); + INFOS ( "GetFittingResources " << hostname << " " << GetHostname().c_str() ); + + if (hostname[0] != '\0'){ + // cerr << "ResourcesManager_cpp::GetFittingResources : hostname specified" << endl; + + if ( strcmp(hostname, "localhost") == 0 || + strcmp(hostname, GetHostname().c_str()) == 0 ) + { + // cerr << "ResourcesManager_cpp::GetFittingResources : localhost" << endl; + vec.push_back(GetHostname().c_str()); + // cerr << "ResourcesManager_cpp::GetFittingResources : " << vec.size() << endl; + } + + else if (_resourcesList.find(hostname) != _resourcesList.end()) + { + // --- params.hostname is in the list of resources so return it. + vec.push_back(hostname); + } + else if (_resourcesBatchList.find(hostname) != _resourcesBatchList.end()) + { + // --- params.hostname is in the list of resources so return it. + vec.push_back(hostname); + } + else + { + // Cas d'un cluster: nombre de noeuds > 1 + int cpt=0; + for (map::const_iterator iter = _resourcesList.begin(); iter != _resourcesList.end(); iter++){ + if( (*iter).second.DataForSort._nbOfNodes > 1 ){ + if( strncmp(hostname,(*iter).first.c_str(),strlen(hostname)) == 0 ){ + vec.push_back((*iter).first.c_str()); + //cerr << "SALOME_ResourcesManager_cpp::GetFittingResources vector[" + // << cpt << "] = " << (*iter).first.c_str() << endl ; + cpt++; + } + } + } + if(cpt==0){ + // --- user specified an unknown hostame so notify him. + MESSAGE ( "ResourcesManager_cpp::GetFittingResources : SALOME_Exception" ); + throw ResourcesException("unknown host"); + } + } + } + + else{ + // --- Search for available resources sorted by priority + SelectOnlyResourcesWithOS(vec, params.OS.c_str()); + + KeepOnlyResourcesWithModule(vec, componentList); + + if (vec.size() == 0) + SelectOnlyResourcesWithOS(vec, params.OS.c_str()); + + // --- set wanted parameters + ResourceDataToSort::_nbOfNodesWanted = params.nb_node; + + ResourceDataToSort::_nbOfProcPerNodeWanted = params.nb_proc_per_node; + + ResourceDataToSort::_CPUFreqMHzWanted = params.cpu_clock; + + ResourceDataToSort::_memInMBWanted = params.mem_mb; + + // --- end of set + + list li; + + for (vector::iterator iter = vec.begin(); + iter != vec.end(); + iter++) + li.push_back(_resourcesList[(*iter)].DataForSort); + + li.sort(); + + unsigned int i = 0; + + for (list::iterator iter2 = li.begin(); + iter2 != li.end(); + iter2++) + vec[i++] = (*iter2)._hostName; + } + + return vec; + +} + +//============================================================================= +/*! + * add an entry in the ressources catalog xml file. + * Return 0 if OK (KERNEL found in new resources modules) else throw exception + */ +//============================================================================= + +int +ResourcesManager_cpp:: +AddResourceInCatalog(const machineParams& paramsOfNewResources, + const vector& modulesOnNewResources, + const char *alias, + const char *userName, + AccessModeType mode, + AccessProtocolType prot) +throw(ResourcesException) +{ + vector::const_iterator iter = find(modulesOnNewResources.begin(), + modulesOnNewResources.end(), + "KERNEL"); + + if (iter != modulesOnNewResources.end()) + { + ParserResourcesType newElt; + newElt.DataForSort._hostName = paramsOfNewResources.hostname; + newElt.Alias = alias; + newElt.Protocol = prot; + newElt.Mode = mode; + newElt.UserName = userName; + newElt.ModulesList = modulesOnNewResources; + newElt.OS = paramsOfNewResources.OS; + newElt.DataForSort._memInMB = paramsOfNewResources.mem_mb; + newElt.DataForSort._CPUFreqMHz = paramsOfNewResources.cpu_clock; + newElt.DataForSort._nbOfNodes = paramsOfNewResources.nb_node; + newElt.DataForSort._nbOfProcPerNode = + paramsOfNewResources.nb_proc_per_node; + _resourcesList[newElt.DataForSort._hostName] = newElt; + return 0; + } + + else + throw ResourcesException("KERNEL is not present in this resource"); +} + +//============================================================================= +/*! + * Deletes a resource from the catalog + */ +//============================================================================= + +void ResourcesManager_cpp::DeleteResourceInCatalog(const char *hostname) +{ + _resourcesList.erase(hostname); +} + +//============================================================================= +/*! + * write the current data in memory in file. + */ +//============================================================================= + +void ResourcesManager_cpp::WriteInXmlFile() +{ + const char* aFilePath = _path_resources.c_str(); + + FILE* aFile = fopen(aFilePath, "w"); + + if (aFile == NULL) + { + INFOS ( "Error opening file !" ); + return; + } + + xmlDocPtr aDoc = xmlNewDoc(BAD_CAST "1.0"); + xmlNewDocComment(aDoc, BAD_CAST "ResourcesCatalog"); + + SALOME_ResourcesCatalog_Handler* handler = + new SALOME_ResourcesCatalog_Handler(_resourcesList, _resourcesBatchList); + handler->PrepareDocToXmlFile(aDoc); + delete handler; + + int isOk = xmlSaveFile(aFilePath, aDoc); + + if (!isOk) + INFOS ( "Error while XML file saving." ); + + // Free the document + xmlFreeDoc(aDoc); + + fclose(aFile); + + INFOS ( "WRITING DONE!" ); +} + +//============================================================================= +/*! + * parse the data type catalog + */ +//============================================================================= + +const MapOfParserResourcesType& ResourcesManager_cpp::ParseXmlFile() +{ + SALOME_ResourcesCatalog_Handler* handler = + new SALOME_ResourcesCatalog_Handler(_resourcesList, _resourcesBatchList); + + const char* aFilePath = _path_resources.c_str(); + FILE* aFile = fopen(aFilePath, "r"); + + if (aFile != NULL) + { + xmlDocPtr aDoc = xmlReadFile(aFilePath, NULL, 0); + + if (aDoc != NULL) + handler->ProcessXmlDocument(aDoc); + else + INFOS ( "ResourcesManager_cpp: could not parse file "<< aFilePath ); + + // Free the document + xmlFreeDoc(aDoc); + + fclose(aFile); + } + else + INFOS ( "ResourcesManager_cpp: file "<& listOfMachines) +{ + return _dynamicResourcesSelecter.FindFirst(listOfMachines); +} + +//============================================================================= +/*! + * dynamically obtains the best machines + */ +//============================================================================= + +string ResourcesManager_cpp::FindNext(const std::vector& listOfMachines) +{ + return _dynamicResourcesSelecter.FindNext(listOfMachines,_resourcesList); +} +//============================================================================= +/*! + * dynamically obtains the best machines + */ +//============================================================================= + +string ResourcesManager_cpp::FindBest(const std::vector& listOfMachines) +{ + return _dynamicResourcesSelecter.FindBest(listOfMachines); +} + +//============================================================================= +/*! + * Gives a sublist of machines with matching OS. + * If parameter OS is empty, gives the complete list of machines + */ +//============================================================================= + +// Warning need an updated parsed list : _resourcesList +void ResourcesManager_cpp::SelectOnlyResourcesWithOS( vector& hosts, const char *OS) const +throw(ResourcesException) +{ + string base(OS); + + for (map::const_iterator iter = + _resourcesList.begin(); + iter != _resourcesList.end(); + iter++) + { + if ( (*iter).second.OS == base || base.size() == 0) + hosts.push_back((*iter).first); + } +} + + +//============================================================================= +/*! + * Gives a sublist of machines on which the module is known. + */ +//============================================================================= + +//Warning need an updated parsed list : _resourcesList +void ResourcesManager_cpp::KeepOnlyResourcesWithModule( vector& hosts, const vector& componentList) const +throw(ResourcesException) +{ + for (vector::iterator iter = hosts.begin(); iter != hosts.end();) + { + MapOfParserResourcesType::const_iterator it = _resourcesList.find(*iter); + const vector& mapOfModulesOfCurrentHost = (((*it).second).ModulesList); + + bool erasedHost = false; + if( mapOfModulesOfCurrentHost.size() > 0 ){ + for(int i=0;i::const_iterator itt = find(mapOfModulesOfCurrentHost.begin(), + mapOfModulesOfCurrentHost.end(), + compoi); +// componentList[i]); + if (itt == mapOfModulesOfCurrentHost.end()){ + erasedHost = true; + break; + } + } + } + if(erasedHost) + hosts.erase(iter); + else + iter++; + } +} + + +ParserResourcesType ResourcesManager_cpp::GetResourcesList(const std::string& machine) +{ + if (_resourcesList.find(machine) != _resourcesList.end()) + return _resourcesList[machine]; + else + return _resourcesBatchList[machine]; +} + +std::string ResourcesManager_cpp::GetHostname() +{ + int ls = 100, r = 1; + char *s; + + while (ls < 10000 && r) { + ls *= 2; + s = new char[ls]; + r = gethostname(s, ls-1); + switch (r) + { + case 0: + break; + default: +#ifdef EINVAL + case EINVAL: +#endif +#ifdef ENAMETOOLONG + case ENAMETOOLONG: +#endif + delete [] s; + continue; + } + } + + if (r != 0) { + s = new char[50]; + strcpy(s, "localhost"); + } + + // remove all after '.' + char *aDot = (strchr(s,'.')); + if (aDot) aDot[0] = '\0'; + + string p = s; + delete [] s; + return p; +} + diff --git a/src/ResourcesManager/ResourcesManager.hxx b/src/ResourcesManager/ResourcesManager.hxx new file mode 100644 index 000000000..951aba5da --- /dev/null +++ b/src/ResourcesManager/ResourcesManager.hxx @@ -0,0 +1,116 @@ +// Copyright (C) 2005 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 +// +#ifndef __RESOURCESMANAGER_HXX__ +#define __RESOURCESMANAGER_HXX__ + +#include +#include +#include +#include "SALOME_ResourcesCatalog_Parser.hxx" +#include "SALOME_ResourcesCatalog_Handler.hxx" +#include "SALOME_LoadRateManager.hxx" + +// --- WARNING --- +// The call of BuildTempFileToLaunchRemoteContainer and RmTmpFile must be done +// in a critical section to be sure to be clean. +// Only one thread should use the SALOME_ResourcesManager class in a SALOME +// session. + +struct machineParams{ + std::string hostname; + std::string OS; + unsigned int nb_node; + unsigned int nb_proc_per_node; + unsigned int cpu_clock; + unsigned int mem_mb; +}; + +class ResourcesException +{ +public: + const std::string msg; + + ResourcesException(const std::string m) : msg(m) {} +}; + +class ResourcesManager_cpp + { + + public: + + ResourcesManager_cpp(const char *xmlFilePath); + ResourcesManager_cpp(); + + ~ResourcesManager_cpp(); + + std::vector + GetFittingResources(const machineParams& params, + const std::vector& componentList) throw(ResourcesException); + + std::string FindFirst(const std::vector& listOfMachines); + std::string FindNext(const std::vector& listOfMachines); + std::string FindBest(const std::vector& listOfMachines); + + int AddResourceInCatalog + (const machineParams& paramsOfNewResources, + const std::vector& modulesOnNewResources, + const char *alias, + const char *userName, + AccessModeType mode, + AccessProtocolType prot) throw(ResourcesException); + + void DeleteResourceInCatalog(const char *hostname); + + void WriteInXmlFile(); + + const MapOfParserResourcesType& ParseXmlFile(); + + const MapOfParserResourcesType& GetList() const; + + ParserResourcesType GetResourcesList(const std::string& machine); + + protected: + + void SelectOnlyResourcesWithOS(std::vector& hosts, + const char *OS) const + throw(ResourcesException); + + void KeepOnlyResourcesWithModule(std::vector& hosts, + const std::vector& componentList) const + throw(ResourcesException); + + //! will contain the path to the ressources catalog + std::string _path_resources; + + //! will contain the informations on the data type catalog(after parsing) + MapOfParserResourcesType _resourcesList; + + //! will contain the informations on the data type catalog(after parsing) + MapOfParserResourcesType _resourcesBatchList; + + SALOME_LoadRateManager _dynamicResourcesSelecter; + + //! different behaviour if $APPLI exists (SALOME Application) + bool _isAppliSalomeDefined; + + std::string GetHostname(); + }; + +#endif // __RESOURCESMANAGER_HXX__