From 622943a60b0033fccad737b98e90accc1d2d2fe3 Mon Sep 17 00:00:00 2001 From: Anthony Geay Date: Tue, 21 Apr 2015 18:43:15 +0200 Subject: [PATCH] First implementation of evalyfx. --- src/CMakeLists.txt | 26 +- src/engine/Bloc.cxx | 40 ++ src/engine/Bloc.hxx | 3 +- src/engine/DynParaLoop.cxx | 5 + src/engine/DynParaLoop.hxx | 1 + src/engine/ElementaryNode.hxx | 2 + src/engine/InlineNode.cxx | 7 +- src/engine/InlineNode.hxx | 5 +- src/engine/Loop.cxx | 7 + src/engine/Loop.hxx | 1 + src/engine/Node.hxx | 1 + src/engine/Proc.cxx | 58 ++- src/engine/Proc.hxx | 3 + src/engine/Switch.cxx | 8 + src/engine/Switch.hxx | 1 + src/engine/VisitorSaveSchema.cxx | 8 +- src/evalyfx/CMakeLists.txt | 86 ++++ src/evalyfx/YACSEvalAutoPtr.hxx | 85 ++++ src/evalyfx/YACSEvalPort.cxx | 311 ++++++++++++++ src/evalyfx/YACSEvalPort.hxx | 133 ++++++ src/evalyfx/YACSEvalResource.cxx | 623 +++++++++++++++++++++++++++++ src/evalyfx/YACSEvalResource.hxx | 157 ++++++++ src/evalyfx/YACSEvalSeqAny.cxx | 135 +++++++ src/evalyfx/YACSEvalSeqAny.hxx | 97 +++++ src/evalyfx/YACSEvalSession.cxx | 130 ++++++ src/evalyfx/YACSEvalSession.hxx | 54 +++ src/evalyfx/YACSEvalYFX.cxx | 180 +++++++++ src/evalyfx/YACSEvalYFX.hxx | 68 ++++ src/evalyfx/YACSEvalYFXExport.hxx | 34 ++ src/evalyfx/YACSEvalYFXPattern.cxx | 491 +++++++++++++++++++++++ src/evalyfx/YACSEvalYFXPattern.hxx | 113 ++++++ src/evalyfx_swig/CMakeLists.txt | 63 +++ src/evalyfx_swig/evalyfx.i | 431 ++++++++++++++++++++ src/evalyfx_swig/test.py | 97 +++++ src/evalyfx_swig/test0.xml | 54 +++ src/evalyfx_swig/testEvalYFX.py | 94 +++++ src/runtime/CORBAPorts.hxx | 2 + 37 files changed, 3584 insertions(+), 30 deletions(-) create mode 100644 src/evalyfx/CMakeLists.txt create mode 100644 src/evalyfx/YACSEvalAutoPtr.hxx create mode 100644 src/evalyfx/YACSEvalPort.cxx create mode 100644 src/evalyfx/YACSEvalPort.hxx create mode 100644 src/evalyfx/YACSEvalResource.cxx create mode 100644 src/evalyfx/YACSEvalResource.hxx create mode 100644 src/evalyfx/YACSEvalSeqAny.cxx create mode 100644 src/evalyfx/YACSEvalSeqAny.hxx create mode 100644 src/evalyfx/YACSEvalSession.cxx create mode 100644 src/evalyfx/YACSEvalSession.hxx create mode 100644 src/evalyfx/YACSEvalYFX.cxx create mode 100644 src/evalyfx/YACSEvalYFX.hxx create mode 100644 src/evalyfx/YACSEvalYFXExport.hxx create mode 100644 src/evalyfx/YACSEvalYFXPattern.cxx create mode 100644 src/evalyfx/YACSEvalYFXPattern.hxx create mode 100644 src/evalyfx_swig/CMakeLists.txt create mode 100644 src/evalyfx_swig/evalyfx.i create mode 100644 src/evalyfx_swig/test.py create mode 100644 src/evalyfx_swig/test0.xml create mode 100644 src/evalyfx_swig/testEvalYFX.py diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 621a019ce..ce9cc73c5 100755 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -29,36 +29,26 @@ SET(SUBDIRS_COMMON # KERNEL ## IF(SALOME_YACS_USE_KERNEL) - SET(SUBDIRS_KERNEL - runtime yacsloader - ) -ENDIF() + SET(SUBDIRS_KERNEL runtime yacsloader evalyfx) +ENDIF(SALOME_YACS_USE_KERNEL) ## # SWIG wrapping ## IF(SALOME_YACS_USE_SWIG) - SET(SUBDIRS_SWIG - engine_swig - ) + SET(SUBDIRS_SWIG engine_swig) IF(SALOME_YACS_USE_KERNEL) - LIST(APPEND SUBDIRS_SWIG - runtime_swig yacsloader_swig - ) - ENDIF() -ENDIF() + LIST(APPEND SUBDIRS_SWIG runtime_swig yacsloader_swig evalyfx_swig) + ENDIF(SALOME_YACS_USE_KERNEL) +ENDIF(SALOME_YACS_USE_SWIG) ## # GUI ## IF(SALOME_BUILD_GUI) - SET(SUBDIRS_GUI - pyqt hmi salomewrap genericgui salomegui - ) + SET(SUBDIRS_GUI pyqt hmi salomewrap genericgui salomegui) IF(SALOME_YACS_USE_SWIG) - LIST(APPEND SUBDIRS_GUI - salomegui_swig - ) + LIST(APPEND SUBDIRS_GUI salomegui_swig) ENDIF() ENDIF() diff --git a/src/engine/Bloc.cxx b/src/engine/Bloc.cxx index efe4dba10..d4822f5b5 100644 --- a/src/engine/Bloc.cxx +++ b/src/engine/Bloc.cxx @@ -27,6 +27,7 @@ #include "Visitor.hxx" #include +#include //#define _DEVDEBUG_ #include "YacsTrace.hxx" @@ -393,6 +394,45 @@ void Bloc::accept(Visitor* visitor) visitor->visitBloc(this); } +/*! + * Returns the max level of parallelism is this. The max of parallelism is equal to the sum of the max parallelism level + * for all concurrent branches in \a this. + */ +int Bloc::getMaxLevelOfParallelism() const +{ + std::set s(_setOfNode.begin(),_setOfNode.end()); + for(std::set::const_iterator it=s.begin();it!=s.end();it++) + (*it)->_colour=White; + std::vector levs; + while(!s.empty()) + { + Node *seed(*(s.begin())); + int myCurLev(0); + while(seed) + { + s.erase(seed); + std::set ingates(seed->getOutGate()->edSetInGate()); + int myCurLev2(1); + for(std::set::const_iterator it=ingates.begin();it!=ingates.end();it++) + { + Node *curNode((*it)->getNode()); + curNode->_colour=Grey; + myCurLev2=std::max(curNode->getMaxLevelOfParallelism(),myCurLev2); + } + myCurLev=std::max(myCurLev,myCurLev2); + seed=0; + for(std::set::const_iterator it=s.begin();it!=s.end();it++) + if((*it)->_colour==Grey) + { + seed=*it; + break; + } + } + levs.push_back(myCurLev); + } + return std::accumulate(levs.begin(),levs.end(),0); +} + /*! * Updates mutable structures _fwLinks and _bwLinks with the result of computation (CPU consuming method). * _fwLinks is a map with a Node* as key and a set as value. The set gives diff --git a/src/engine/Bloc.hxx b/src/engine/Bloc.hxx index 43d118b2c..0bd35120d 100644 --- a/src/engine/Bloc.hxx +++ b/src/engine/Bloc.hxx @@ -58,7 +58,8 @@ namespace YACS void findAllPathsStartingFrom(Node *start, std::list< std::vector >& vec, std::map >& accelStr) const; template void findAllNodesStartingFrom(Node *start, std::set& result, std::map >& accelStr, LinkInfo& info) const; - virtual std::string typeName() {return "YACS__ENGINE__Bloc";} + virtual std::string typeName() { return "YACS__ENGINE__Bloc"; } + int getMaxLevelOfParallelism() const; protected: bool areAllSubNodesFinished() const; bool areAllSubNodesDone() const; diff --git a/src/engine/DynParaLoop.cxx b/src/engine/DynParaLoop.cxx index 0564dabd0..ac42a27d2 100644 --- a/src/engine/DynParaLoop.cxx +++ b/src/engine/DynParaLoop.cxx @@ -805,6 +805,11 @@ Node * DynParaLoop::getFinalizeNode() return _finalizeNode; } +int DynParaLoop::getMaxLevelOfParallelism() const +{ + return _nbOfBranches.getIntValue(); +} + void DynParaLoop::shutdown(int level) { if(level==0)return; diff --git a/src/engine/DynParaLoop.hxx b/src/engine/DynParaLoop.hxx index 3a29a872d..14db8b2f9 100644 --- a/src/engine/DynParaLoop.hxx +++ b/src/engine/DynParaLoop.hxx @@ -104,6 +104,7 @@ namespace YACS Node * getInitNode(); Node * getExecNode(); Node * getFinalizeNode(); + int getMaxLevelOfParallelism() const; protected: void buildDelegateOf(InPort * & port, OutPort *initialStart, const std::list& pointsOfView); void buildDelegateOf(std::pair& port, InPort *finalTarget, const std::list& pointsOfView); diff --git a/src/engine/ElementaryNode.hxx b/src/engine/ElementaryNode.hxx index db82867dd..843de41e1 100644 --- a/src/engine/ElementaryNode.hxx +++ b/src/engine/ElementaryNode.hxx @@ -105,6 +105,8 @@ namespace YACS virtual void edUpdateState(); virtual void ensureLoading(); + int getMaxLevelOfParallelism() const { return 1; } + //run part void begin(); bool isReady(); diff --git a/src/engine/InlineNode.cxx b/src/engine/InlineNode.cxx index ac0c0c38f..2d2298645 100644 --- a/src/engine/InlineNode.cxx +++ b/src/engine/InlineNode.cxx @@ -28,6 +28,9 @@ using namespace YACS::ENGINE; using namespace std; +const char InlineNode::LOCAL_STR[]="local"; + +const char InlineNode::REMOTE_STR[]="remote"; InlineNode::~InlineNode() { @@ -82,7 +85,7 @@ void InlineFuncNode::checkBasicConsistency() const throw(YACS::Exception) void InlineNode::setExecutionMode(const std::string& mode) { if(mode == _mode)return; - if(mode == "local"||mode == "remote") + if(mode == LOCAL_STR || mode == REMOTE_STR) { _mode=mode; modified(); @@ -130,7 +133,7 @@ void InlineNode::performShallowDuplicationOfPlacement(const Node& other) bool InlineNode::isDeployable() const { - if(_mode=="remote") + if(_mode==REMOTE_STR) return true; else return false; diff --git a/src/engine/InlineNode.hxx b/src/engine/InlineNode.hxx index 891acb065..f6582d599 100644 --- a/src/engine/InlineNode.hxx +++ b/src/engine/InlineNode.hxx @@ -45,7 +45,7 @@ namespace YACS protected: InlineNode(const InlineNode& other, ComposedNode *father) :ElementaryNode(other,father),_script(other._script),_mode(other._mode),_container(0) { } - InlineNode(const std::string& name):ElementaryNode(name),_mode("local"),_container(0) { } + InlineNode(const std::string& name):ElementaryNode(name),_mode(LOCAL_STR),_container(0) { } public: virtual void setScript(const std::string& script); virtual std::string getScript(){return _script;} @@ -67,6 +67,9 @@ namespace YACS void performDuplicationOfPlacement(const Node& other); void performShallowDuplicationOfPlacement(const Node& other); bool isDeployable() const; + public: + static const char LOCAL_STR[]; + static const char REMOTE_STR[]; protected: std::string _script; std::string _mode; diff --git a/src/engine/Loop.cxx b/src/engine/Loop.cxx index ccf1375df..8ce0063e6 100644 --- a/src/engine/Loop.cxx +++ b/src/engine/Loop.cxx @@ -412,6 +412,13 @@ int Loop::getNumberOfInputPorts() const return StaticDefinedComposedNode::getNumberOfInputPorts()+1; } +int Loop::getMaxLevelOfParallelism() const +{ + if(!_node) + return 0; + return _node->getMaxLevelOfParallelism(); +} + Node *Loop::getChildByShortName(const std::string& name) const throw(YACS::Exception) { if (_node) diff --git a/src/engine/Loop.hxx b/src/engine/Loop.hxx index 8917570f4..e1e86f61b 100644 --- a/src/engine/Loop.hxx +++ b/src/engine/Loop.hxx @@ -172,6 +172,7 @@ namespace YACS std::list edGetDirectDescendants() const; std::list getSetOfInputPort() const; int getNumberOfInputPorts() const; + int getMaxLevelOfParallelism() const; Node *getChildByShortName(const std::string& name) const throw(Exception); static TypeCode* MappingDF2DS(TypeCode* type) throw(Exception); static TypeCode* MappingDS2DF(TypeCode* type) throw(Exception); diff --git a/src/engine/Node.hxx b/src/engine/Node.hxx index 98b8dfaa3..c724fb605 100644 --- a/src/engine/Node.hxx +++ b/src/engine/Node.hxx @@ -164,6 +164,7 @@ namespace YACS virtual Proc *getProc(); virtual const Proc *getProc() const; virtual void accept(Visitor *visitor) = 0; + virtual int getMaxLevelOfParallelism() const = 0; std::string getQualifiedName() const; int getNumId(); virtual void sendEvent(const std::string& event); diff --git a/src/engine/Proc.cxx b/src/engine/Proc.cxx index 3cc7eb291..5f83fe162 100644 --- a/src/engine/Proc.cxx +++ b/src/engine/Proc.cxx @@ -75,10 +75,7 @@ Proc::~Proc() for(pt=typeMap.begin();pt!=typeMap.end();pt++) ((*pt).second)->decrRef(); - //get rid of containers in container map - std::map::const_iterator it; - for(it=containerMap.begin();it!=containerMap.end();it++) - ((*it).second)->decrRef(); + removeContainers(); //get rid of loggers in logger map std::map::const_iterator lt; @@ -463,6 +460,15 @@ void Proc::saveState(const std::string& xmlStateFile) vst.closeFileDump(); } +void Proc::removeContainers() +{ + //get rid of containers in container map + std::map::const_iterator it; + for(it=containerMap.begin();it!=containerMap.end();it++) + ((*it).second)->decrRef(); + containerMap.clear(); +} + //! Create a new Container and store it in containerMap /*! * \param name: the container name and key in containerMap @@ -580,3 +586,47 @@ const Proc * Proc::getProc() const { return this; } + +/*! + * This method is useful if this has been modified recursively and an update is needed between all the + * containers and components refered by children and little children and maps. + */ +void Proc::updateContainersAndComponents() +{ + std::map myContainerMap; + std::map myComponentInstanceMap; + DeploymentTree treeToDup(getDeploymentTree()); + vector conts(treeToDup.getAllContainers()); + for(vector::const_iterator iterCt=conts.begin();iterCt!=conts.end();iterCt++) + { + Container *tmp(*iterCt); + if(tmp) + { + if(myContainerMap.find(tmp->getName())!=myContainerMap.end()) + { + std::ostringstream oss; oss << "Proc::updateContainersAndComponents : more than one container instance with name \"" << tmp->getName() << "\" !"; + throw YACS::Exception(oss.str()); + } + myContainerMap[tmp->getName()]=tmp; + tmp->incrRef(); + } + vector comps=treeToDup.getComponentsLinkedToContainer(*iterCt); + for(vector::iterator iterCp=comps.begin();iterCp!=comps.end();iterCp++) + { + ComponentInstance *tmp2(*iterCp); + if(tmp2) + { + if(myComponentInstanceMap.find(tmp2->getCompoName())!=myComponentInstanceMap.end()) + { + std::ostringstream oss; oss << "Proc::updateContainersAndComponents : more than one component instance with name \"" << tmp2->getCompoName() << "\" !"; + throw YACS::Exception(oss.str()); + } + } + myComponentInstanceMap[tmp2->getCompoName()]=tmp2; + tmp2->incrRef(); + } + } + removeContainers(); + containerMap=myContainerMap; + componentInstanceMap=myComponentInstanceMap; +} diff --git a/src/engine/Proc.hxx b/src/engine/Proc.hxx index 5f84545d4..e4b8329a3 100644 --- a/src/engine/Proc.hxx +++ b/src/engine/Proc.hxx @@ -63,6 +63,7 @@ namespace YACS virtual void accept(Visitor *visitor); virtual Proc *getProc(); virtual const Proc *getProc() const; + virtual void updateContainersAndComponents(); YACS::StatesForNode getNodeState(int numId); std::string getNodeProgress(int numId); @@ -97,6 +98,8 @@ namespace YACS virtual void modified(); virtual void saveSchema(const std::string& xmlSchemaFile); virtual void saveState(const std::string& xmlStateFile); + protected: + void removeContainers(); protected: bool _edition; int _compoinstctr; diff --git a/src/engine/Switch.cxx b/src/engine/Switch.cxx index 2c6fb6344..f06d6d86b 100644 --- a/src/engine/Switch.cxx +++ b/src/engine/Switch.cxx @@ -400,6 +400,14 @@ int Switch::getNumberOfInputPorts() const return StaticDefinedComposedNode::getNumberOfInputPorts()+1; } +int Switch::getMaxLevelOfParallelism() const +{ + int ret(0); + for(std::map< int , Node * >::const_iterator it=_mapOfNode.begin();it!=_mapOfNode.end();it++) + ret=std::max(ret,((*it).second)->getMaxLevelOfParallelism()); + return ret; +} + void Switch::edRemoveChild(Node *node) throw(YACS::Exception) { map< int , Node * >::iterator iter=_mapOfNode.begin(); diff --git a/src/engine/Switch.hxx b/src/engine/Switch.hxx index f8a7dc3a6..4d6670d13 100644 --- a/src/engine/Switch.hxx +++ b/src/engine/Switch.hxx @@ -115,6 +115,7 @@ namespace YACS InputPort *edGetConditionPort() { return &_condition; } void writeDot(std::ostream &os) const; int getNumberOfInputPorts() const; + int getMaxLevelOfParallelism() const; void edRemoveChild(Node *node) throw(Exception); std::list getSetOfInputPort() const; std::list getLocalInputPorts() const; diff --git a/src/engine/VisitorSaveSchema.cxx b/src/engine/VisitorSaveSchema.cxx index eed7e1b21..6563c0ed9 100644 --- a/src/engine/VisitorSaveSchema.cxx +++ b/src/engine/VisitorSaveSchema.cxx @@ -222,7 +222,7 @@ void VisitorSaveSchema::visitInlineNode(InlineNode *node) DEBTRACE("START visitInlineNode " << _root->getChildName(node)); beginCase(node); int depth = depthNode(node); - if(node->getExecutionMode()=="local") + if(node->getExecutionMode()==InlineNode::LOCAL_STR) _out << indent(depth) << "getName() << "\""; else _out << indent(depth) << "getName() << "\""; @@ -245,7 +245,7 @@ void VisitorSaveSchema::visitInlineNode(InlineNode *node) writeOutputPorts(node); writeOutputDataStreamPorts(node); - if(node->getExecutionMode()=="local") + if(node->getExecutionMode()==InlineNode::LOCAL_STR) _out << indent(depth) << "" << endl; else _out << indent(depth) << "" << endl; @@ -259,7 +259,7 @@ void VisitorSaveSchema::visitInlineFuncNode(InlineFuncNode *node) DEBTRACE("START visitInlineFuncNode " << _root->getChildName(node)); beginCase(node); int depth = depthNode(node); - if(node->getExecutionMode()=="local") + if(node->getExecutionMode()==InlineNode::LOCAL_STR) _out << indent(depth) << "getName() << "\""; else _out << indent(depth) << "getName() << "\""; @@ -284,7 +284,7 @@ void VisitorSaveSchema::visitInlineFuncNode(InlineFuncNode *node) writeOutputPorts(node); writeOutputDataStreamPorts(node); - if(node->getExecutionMode()=="local") + if(node->getExecutionMode()==InlineNode::LOCAL_STR) _out << indent(depth) << "" << endl; else _out << indent(depth) << "" << endl; diff --git a/src/evalyfx/CMakeLists.txt b/src/evalyfx/CMakeLists.txt new file mode 100644 index 000000000..8779522e4 --- /dev/null +++ b/src/evalyfx/CMakeLists.txt @@ -0,0 +1,86 @@ +# Copyright (C) 2012-2015 CEA/DEN, EDF R&D +# +# 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, or (at your option) any later version. +# +# 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 +# + +IF(SALOME_YACS_USE_KERNEL) + INCLUDE_DIRECTORIES(${KERNEL_INCLUDE_DIRS}) + ADD_DEFINITIONS(${KERNEL_DEFINITIONS}) + SET(SALOME_LIBS + ${KERNEL_SalomeLifeCycleCORBA} + ${KERNEL_SalomeIDLKernel} + ${KERNEL_SalomeNS} + ${KERNEL_SalomeContainer} + ${KERNEL_SALOMEBasics} + ${KERNEL_SalomeResourcesManager} + ${KERNEL_OpUtil} + ${KERNEL_SALOMELocalTrace} + ${KERNEL_Registry} + ${KERNEL_SalomeNotification} + ${KERNEL_ResourcesManager} + ${KERNEL_SalomeHDFPersist} + ${KERNEL_SalomeGenericObj} + ) +ENDIF(SALOME_YACS_USE_KERNEL) + +# additional include directories +INCLUDE_DIRECTORIES( + ${OMNIORB_INCLUDE_DIR} + ${PYTHON_INCLUDE_DIR} + ${PROJECT_SOURCE_DIR}/src/bases + ${PROJECT_SOURCE_DIR}/src/engine + ${PROJECT_SOURCE_DIR}/src/runtime + ${PROJECT_SOURCE_DIR}/src/yacsloader + ) + +ADD_DEFINITIONS( + ${PYTHON_DEFINITIONS} + ${OMNIORB_DEFINITIONS} + ) + +SET(YACSevalYFX_LIBRARIES + YACSloader + YACSRuntimeSALOME + ${SALOME_LIBS} + ${OMNIORB_LIBRARIES} + ${PYTHON_LIBRARIES} + ${LIBXML2_LIBRARIES} + ) + +# no more than 4 files should be installed +SET(YACSEvalYFX_HEADERS + YACSEvalYFXExport.hxx + YACSEvalYFX.hxx + YACSEvalPort.hxx + YACSEvalSeqAny.hxx + YACSEvalResource.hxx + YACSEvalSession.hxx + ) + +SET(YACSevalYFX_SOURCES + YACSEvalYFX.cxx + YACSEvalYFXPattern.cxx + YACSEvalPort.cxx + YACSEvalSeqAny.cxx + YACSEvalResource.cxx + YACSEvalSession.cxx + ) + +ADD_LIBRARY(YACSevalYFX ${YACSevalYFX_SOURCES}) +TARGET_LINK_LIBRARIES(YACSevalYFX ${YACSevalYFX_LIBRARIES}) +INSTALL(TARGETS YACSevalYFX EXPORT ${PROJECT_NAME}TargetGroup DESTINATION ${SALOME_INSTALL_LIBS}) +INSTALL(FILES ${YACSEvalYFX_HEADERS} DESTINATION ${SALOME_INSTALL_HEADERS}) diff --git a/src/evalyfx/YACSEvalAutoPtr.hxx b/src/evalyfx/YACSEvalAutoPtr.hxx new file mode 100644 index 000000000..4efdecb87 --- /dev/null +++ b/src/evalyfx/YACSEvalAutoPtr.hxx @@ -0,0 +1,85 @@ +// Copyright (C) 2012-2015 CEA/DEN, EDF R&D +// +// 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, or (at your option) any later version. +// +// 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 +// +// Author : Anthony Geay (EDF R&D) + +#ifndef __YACSEVALYFXAUTOPTR_HXX__ +#define __YACSEVALYFXAUTOPTR_HXX__ + +namespace YACS +{ + template + class AutoPtr + { + public: + AutoPtr(T *ptr=0):_ptr(ptr) { } + ~AutoPtr() { destroyPtr(); } + AutoPtr &operator=(T *ptr) { if(_ptr!=ptr) { destroyPtr(); _ptr=ptr; } return *this; } + T *operator->() { return _ptr ; } + const T *operator->() const { return _ptr; } + T& operator*() { return *_ptr; } + const T& operator*() const { return *_ptr; } + operator T *() { return _ptr; } + operator const T *() const { return _ptr; } + private: + void destroyPtr() { delete [] _ptr; } + private: + T *_ptr; + }; + + template + class AutoCppPtr + { + public: + AutoCppPtr(T *ptr=0):_ptr(ptr) { } + ~AutoCppPtr() { destroyPtr(); } + AutoCppPtr &operator=(T *ptr) { if(_ptr!=ptr) { destroyPtr(); _ptr=ptr; } return *this; } + T *operator->() { return _ptr ; } + const T *operator->() const { return _ptr; } + T& operator*() { return *_ptr; } + const T& operator*() const { return *_ptr; } + operator T *() { return _ptr; } + operator const T *() const { return _ptr; } + T *dettach() { T *ret(_ptr); _ptr=0; return ret; } + private: + void destroyPtr() { delete _ptr; } + private: + T *_ptr; + }; + + template + class AutoCPtr + { + public: + AutoCPtr(T *ptr=0):_ptr(ptr) { } + ~AutoCPtr() { destroyPtr(); } + AutoCPtr &operator=(T *ptr) { if(_ptr!=ptr) { destroyPtr(); _ptr=ptr; } return *this; } + T *operator->() { return _ptr ; } + const T *operator->() const { return _ptr; } + T& operator*() { return *_ptr; } + const T& operator*() const { return *_ptr; } + operator T *() { return _ptr; } + operator const T *() const { return _ptr; } + private: + void destroyPtr() { free(_ptr); } + private: + T *_ptr; + }; +} + +#endif diff --git a/src/evalyfx/YACSEvalPort.cxx b/src/evalyfx/YACSEvalPort.cxx new file mode 100644 index 000000000..61a06fb91 --- /dev/null +++ b/src/evalyfx/YACSEvalPort.cxx @@ -0,0 +1,311 @@ +// Copyright (C) 2012-2015 CEA/DEN, EDF R&D +// +// 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, or (at your option) any later version. +// +// 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 +// +// Author : Anthony Geay (EDF R&D) + +#include "YACSEvalPort.hxx" +#include "YACSEvalSeqAny.hxx" +#include "OutputPort.hxx" +#include "InputPort.hxx" +#include "TypeCode.hxx" + +#include "CORBAPorts.hxx" +#include "PythonPorts.hxx" +#include "AnyInputPort.hxx" + +#include +#include +#include + +const char YACSEvalAnyDouble::TYPE_REPR[]="double"; + +const char YACSEvalAnyInt::TYPE_REPR[]="int"; + +int YACSEvalAnyDouble::toInt() const +{ + throw YACS::Exception("YACSEvalAnyDouble::toInt : invalid type requested !"); +} + +double YACSEvalAnyDouble::toDouble() const +{ + return _v; +} + +YACSEvalAnyDouble *YACSEvalAnyDouble::deepCpy() const +{ + return new YACSEvalAnyDouble(*this); +} + +int YACSEvalAnyInt::toInt() const +{ + return _v; +} + +double YACSEvalAnyInt::toDouble() const +{ + throw YACS::Exception("YACSEvalAnyInt::toDouble : invalid type requested !"); +} + +YACSEvalAnyInt *YACSEvalAnyInt::deepCpy() const +{ + return new YACSEvalAnyInt(*this); +} + +std::string YACSEvalPort::GetTypeOfData(const YACS::ENGINE::DataPort *port) +{ + YACS::ENGINE::TypeCode *tc(port->edGetType()); + if(!tc) + throw YACS::Exception("YACSEvalPort::GetTypeOfData : null type code !"); + if(tc->kind()==YACS::ENGINE::Double) + return std::string(YACSEvalAnyDouble::TYPE_REPR); + if(tc->kind()==YACS::ENGINE::Int) + return std::string(YACSEvalAnyInt::TYPE_REPR); + throw YACS::Exception("YACSEvalPort::GetTypeOfData : Unrecognized type of data ! Must be int or double for the moment !"); +} + +YACSEvalInputPort::YACSEvalInputPort(YACS::ENGINE::InputPort *ptr):_ptr(ptr),_isLocked(false),_mySeq(0) +{ + GetTypeOfData(_ptr); +} + +std::string YACSEvalInputPort::getName() const +{ + return _ptr->getName(); +} + +std::string YACSEvalInputPort::getTypeOfData() const +{ + return GetTypeOfData(_ptr); +} + +bool YACSEvalInputPort::isOKForLock() const +{ + if(_isLocked) + return true; + return hasDefaultValueDefined(); +} + +bool YACSEvalInputPort::hasDefaultValueDefined() const +{ + return _ptr->edIsManuallyInitialized(); +} + +/*! + * The caller has the ownership of the returned instance. + */ +YACSEvalAny *YACSEvalInputPort::getDefaultValueDefined() const +{ + if(!hasDefaultValueDefined()) + throw YACS::Exception("YACSEvalInputPort::getDefaultValueDefined : no default value defined !"); + _ptr->exRestoreInit(); + YACS::ENGINE::InputPyPort *i0(dynamic_cast(_ptr)); + if(i0) + { + PyObject *data(i0->getPyObj()); + if(!data) + throw YACS::Exception("YACSEvalInputPort::getDefaultValueDefined : internal error !"); + if(PyFloat_Check(data)) + return new YACSEvalAnyDouble(PyFloat_AsDouble(data)); + if(PyInt_Check(data)) + return new YACSEvalAnyInt((int)PyInt_AsLong(data)); + throw YACS::Exception("YACSEvalInputPort::getDefaultValueDefined : unmanaged types different from int and double for py !"); + } + YACS::ENGINE::AnyInputPort *i1(dynamic_cast(_ptr)); + if(i1) + { + YACS::ENGINE::Any *data(i1->getValue()); + return convertFromInternalAnyToExternal(data); + } + YACS::ENGINE::InputCorbaPort *i2(dynamic_cast(_ptr)); + if(i2) + { + CORBA::Any *data(i2->getAny()); + if(!data) + throw YACS::Exception("YACSEvalInputPort::getDefaultValueDefined : internal error # 3 !"); + std::string td(getTypeOfData()); + if(td==YACSEvalAnyDouble::TYPE_REPR) + { + CORBA::Double v; + if((*data)>>=v) + return new YACSEvalAnyDouble(v); + else + throw YACS::Exception("YACSEvalInputPort::getDefaultValueDefined : internal error # 31 !"); + } + if(td==YACSEvalAnyInt::TYPE_REPR) + { + CORBA::Long v; + if((*data)>>=v) + return new YACSEvalAnyInt(v); + else + throw YACS::Exception("YACSEvalInputPort::getDefaultValueDefined : internal error # 32 !"); + } + } + std::ostringstream oss; + oss << "YACSEvalInputPort::getDefaultValueDefined : Please contact anthony.geay@edf.fr with -> \"" << typeid(*_ptr).name() << "\" !"; + throw YACS::Exception(oss.str()); +} + +/*! + * This method does not steal the ownership of \a parameter (a deep copy is performed). + */ +void YACSEvalInputPort::setDefaultValue(const YACSEvalAny *parameter) +{ + checkForNonConstMethod(); + if(parameter) + { + if(parameter->getTypeOfData()!=getTypeOfData()) + { + std::ostringstream oss; oss << "YACSEvalInputPort::setParameter : Type of data mismatch ! Expecting \"" << getTypeOfData() << "\" having \"" << parameter->getTypeOfData() << "\" !"; + throw YACS::Exception(oss.str()); + } + } + // + YACS::ENGINE::InputPyPort *i0(dynamic_cast(_ptr)); + YACS::ENGINE::AnyInputPort *i1(dynamic_cast(_ptr)); + YACS::ENGINE::InputCorbaPort *i2(dynamic_cast(_ptr)); + if(parameter) + { + const YACSEvalAnyDouble *par0(dynamic_cast(parameter)); + const YACSEvalAnyInt *par1(dynamic_cast(parameter)); + if(i0) + { + if(par0) + { + PyObject *obj(PyFloat_FromDouble(par0->toDouble())); + i0->put(obj); + Py_XDECREF(obj); + } + else if(par1) + { + PyObject *obj(PyInt_FromLong(par1->toInt())); + i0->put(obj); + Py_XDECREF(obj); + } + else + throw YACS::Exception("YACSEvalInputPort::setDefaultValueDefined : unmanaged types different from int and double for py !"); + } + else if(i1) + { + if(par0) + { + YACS::ENGINE::AtomAny *v(YACS::ENGINE::AtomAny::New(par0->toDouble())); + i1->put(v); + v->decrRef(); + } + else if(par1) + { + YACS::ENGINE::AtomAny *v(YACS::ENGINE::AtomAny::New(par1->toInt())); + i1->put(v); + v->decrRef(); + } + else + throw YACS::Exception("YACSEvalInputPort::setDefaultValueDefined : unmanaged types different from int and double for yacsport !"); + } + else if(i2) + { + CORBA::Any v; + if(par0) + v<<=par0->toDouble(); + else if(par1) + v<<=par1->toInt(); + else + throw YACS::Exception("YACSEvalInputPort::setDefaultValueDefined : unmanaged types different from int and double for corbaport !"); + i2->put(&v); + } + else + { + std::ostringstream oss; + oss << "YACSEvalInputPort::getDefaultValueDefined : Please contact anthony.geay@edf.fr with -> \"" << typeid(*_ptr).name() << "\" !"; + throw YACS::Exception(oss.str()); + } + _ptr->exSaveInit(); + } + else + _ptr->edRemoveManInit(); +} + +void YACSEvalInputPort::setSequenceOfValuesToEval(const YACSEvalSeqAny *vals) +{ + checkForNonConstMethod(); + if(!vals) + throw YACS::Exception("YACSEvalInputPort::setSequenceOfValuesToEval : input is NULL !"); + if(vals==_mySeq) + return ; + if(_mySeq) + delete _mySeq; + _mySeq=vals->copy(); +} + +bool YACSEvalInputPort::hasSequenceOfValuesToEval(std::size_t& sz) const +{ + sz=std::numeric_limits::max(); + bool ret(_mySeq!=0); + if(ret) + sz=_mySeq->size(); + return ret; +} + +void YACSEvalInputPort::initializeUndergroundWithSeq(YACS::ENGINE::InputPyPort *p) const +{ + if(!p) + throw YACS::Exception("YACSEvalInputPort::initializeUndergroundWithSeq : p is null !"); + if(!_mySeq) + throw YACS::Exception("YACSEvalInputPort::initializeUndergroundWithSeq : this is not set as a sequence !"); + _mySeq->initialize(p); +} + +YACSEvalInputPort::~YACSEvalInputPort() +{ + delete _mySeq; +} + +YACSEvalAny *YACSEvalInputPort::convertFromInternalAnyToExternal(YACS::ENGINE::Any *data) const +{ + if(!data) + throw YACS::Exception("YACSEvalInputPort::convertFromInternalAnyToExternal : internal error # 2 !"); + YACS::ENGINE::AtomAny *data2(dynamic_cast(data)); + if(!data2) + throw YACS::Exception("YACSEvalInputPort::convertFromInternalAnyToExternal : internal error # 21 !"); + std::string td(getTypeOfData()); + if(td==YACSEvalAnyDouble::TYPE_REPR) + return new YACSEvalAnyDouble(data2->getDoubleValue()); + if(td==YACSEvalAnyInt::TYPE_REPR) + return new YACSEvalAnyInt(data2->getIntValue()); + throw YACS::Exception("YACSEvalInputPort::convertFromInternalAnyToExternal : unmanaged types different from int and double for any !"); +} + +void YACSEvalInputPort::checkForNonConstMethod() const +{ + if(_isLocked) + throw YACS::Exception("YACSEvalInputPort::checkForNonConstMethod : trying to modify a locked input ! To release it call unlockAll on YACSEvalYFX instance owning this !"); +} + +YACSEvalOutputPort::YACSEvalOutputPort(YACS::ENGINE::OutputPort *ptr):_ptr(ptr) +{ + GetTypeOfData(_ptr); +} + +std::string YACSEvalOutputPort::getName() const +{ + return _ptr->getName(); +} + +std::string YACSEvalOutputPort::getTypeOfData() const +{ + return GetTypeOfData(_ptr); +} diff --git a/src/evalyfx/YACSEvalPort.hxx b/src/evalyfx/YACSEvalPort.hxx new file mode 100644 index 000000000..3044dcae7 --- /dev/null +++ b/src/evalyfx/YACSEvalPort.hxx @@ -0,0 +1,133 @@ +// Copyright (C) 2012-2015 CEA/DEN, EDF R&D +// +// 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, or (at your option) any later version. +// +// 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 +// +// Author : Anthony Geay (EDF R&D) + +#ifndef __YACSEVALPORT_HXX__ +#define __YACSEVALPORT_HXX__ + +#include "YACSEvalYFXExport.hxx" + +#include + +namespace YACS +{ + namespace ENGINE + { + class Any; + class DataPort; + class InputPort; + class OutputPort; + class InputPyPort; + } +} + +class YACSEvalSeqAny; + +class YACSEvalAny +{ +public: + YACSEVALYFX_EXPORT virtual ~YACSEvalAny() { } + YACSEVALYFX_EXPORT virtual std::string getTypeOfData() const = 0; + YACSEVALYFX_EXPORT virtual int toInt() const = 0; + YACSEVALYFX_EXPORT virtual double toDouble() const = 0; + YACSEVALYFX_EXPORT virtual YACSEvalAny *deepCpy() const = 0; +}; + +class YACSEvalAnyDouble : public YACSEvalAny +{ +public: + YACSEVALYFX_EXPORT YACSEvalAnyDouble(double val):_v(val) { } + YACSEVALYFX_EXPORT std::string getTypeOfData() const { return std::string(TYPE_REPR); } + YACSEVALYFX_EXPORT int toInt() const; + YACSEVALYFX_EXPORT double toDouble() const; + YACSEVALYFX_EXPORT YACSEvalAnyDouble *deepCpy() const; + YACSEVALYFX_EXPORT ~YACSEvalAnyDouble() { } +private: + double _v; +public: + static const char TYPE_REPR[]; +}; + +class YACSEvalAnyInt : public YACSEvalAny +{ +public: + YACSEVALYFX_EXPORT YACSEvalAnyInt(int val):_v(val) { } + YACSEVALYFX_EXPORT std::string getTypeOfData() const { return std::string(TYPE_REPR); } + YACSEVALYFX_EXPORT int toInt() const; + YACSEVALYFX_EXPORT double toDouble() const; + YACSEVALYFX_EXPORT YACSEvalAnyInt *deepCpy() const; + YACSEVALYFX_EXPORT ~YACSEvalAnyInt() { } +private: + int _v; +public: + static const char TYPE_REPR[]; +}; + +class YACSEvalPort +{ +public: + YACSEVALYFX_EXPORT virtual std::string getTypeOfData() const = 0; + YACSEVALYFX_EXPORT virtual ~YACSEvalPort() { } +protected: + YACSEVALYFX_EXPORT static std::string GetTypeOfData(const YACS::ENGINE::DataPort *port); +}; + +class YACSEvalInputPort : public YACSEvalPort +{ +public: + YACSEVALYFX_EXPORT YACSEvalInputPort(YACS::ENGINE::InputPort *ptr); + YACSEVALYFX_EXPORT std::string getName() const; + YACSEVALYFX_EXPORT std::string getTypeOfData() const; + YACSEVALYFX_EXPORT bool isOKForLock() const; + // + YACSEVALYFX_EXPORT bool hasDefaultValueDefined() const; + YACSEVALYFX_EXPORT YACSEvalAny *getDefaultValueDefined() const; + YACSEVALYFX_EXPORT void setDefaultValue(const YACSEvalAny *parameter); + YACSEVALYFX_EXPORT void setSequenceOfValuesToEval(const YACSEvalSeqAny* vals); + YACSEVALYFX_EXPORT bool hasSequenceOfValuesToEval(std::size_t& sz) const; + // + YACSEVALYFX_EXPORT YACS::ENGINE::InputPort *getUndergroundPtr() const { return _ptr; } + YACSEVALYFX_EXPORT void initializeUndergroundWithSeq(YACS::ENGINE::InputPyPort *p) const; + // + YACSEVALYFX_EXPORT virtual ~YACSEvalInputPort(); + void lock() const { _isLocked=true; } + void unlock() const { _isLocked=false; } +private: + YACSEvalAny *convertFromInternalAnyToExternal(YACS::ENGINE::Any *data) const; + void checkForNonConstMethod() const; +private: + YACS::ENGINE::InputPort * _ptr; + YACSEvalSeqAny *_mySeq; + mutable bool _isLocked; +}; + +class YACSEvalOutputPort : public YACSEvalPort +{ +public: + YACSEVALYFX_EXPORT YACSEvalOutputPort(YACS::ENGINE::OutputPort *ptr); + YACSEVALYFX_EXPORT std::string getName() const; + YACSEVALYFX_EXPORT std::string getTypeOfData() const; + // + YACSEVALYFX_EXPORT YACS::ENGINE::OutputPort *getUndergroundPtr() const { return _ptr; } + // +private: + YACS::ENGINE::OutputPort * _ptr; +}; + +#endif diff --git a/src/evalyfx/YACSEvalResource.cxx b/src/evalyfx/YACSEvalResource.cxx new file mode 100644 index 000000000..aa9df200a --- /dev/null +++ b/src/evalyfx/YACSEvalResource.cxx @@ -0,0 +1,623 @@ +// Copyright (C) 2012-2015 CEA/DEN, EDF R&D +// +// 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, or (at your option) any later version. +// +// 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 +// +// Author : Anthony Geay (EDF R&D) + +#include "YACSEvalResource.hxx" + +#include "DeploymentTree.hxx" +#include "Container.hxx" +#include "Exception.hxx" + +#include "SalomeContainer.hxx" +#include "SalomeHPContainer.hxx" +#include "ComponentInstance.hxx" + +#include "ResourcesManager.hxx" + +#include +#include +#include +#include +#include + +const char YACSEvalVirtualYACSContainer::CONTAINER_NAME_KEY[]="container_name"; + +const char YACSEvalVirtualYACSContainer::CPU_CLOCK_KEY[]="cpu_clock"; + +const char YACSEvalVirtualYACSContainer::HOSTNAME_KEY[]="hostname"; + +const char YACSEvalVirtualYACSContainer::MEM_KEY[]="mem_mb"; + +const char YACSEvalVirtualYACSContainer::NB_NODE_KEY[]="nb_node"; + +const char YACSEvalVirtualYACSContainer::NB_PROC_PER_NODE_KEY[]="nb_proc_per_node"; + +const char YACSEvalVirtualYACSContainer::NB_RESOURCE_PROCS_KEY[]="nb_resource_procs"; + +const char YACSEvalVirtualYACSContainer::POLICY_KEY[]="policy"; + +const char YACSEvalVirtualYACSContainer::OS_KEY[]="OS"; + +/*! + * This class is here only to avoid "friend class YACSEvalListOfResources". + */ +class YACSEvalResourceEff : public YACSEvalResource +{ +public: + YACSEvalResourceEff(YACSEvalListOfResources *gf, const std::vector< YACS::ENGINE::Container * >& conts); +}; + +YACSEvalResourceEff::YACSEvalResourceEff(YACSEvalListOfResources *gf, const std::vector< YACS::ENGINE::Container * >& conts):YACSEvalResource(gf,conts) +{ +} + +void YACSEvalNonConstLocker::checkNonLocked() const +{ + if(_isLocked) + throw YACS::Exception("YACSEvalNonConstLocker::checkNonLocked : this is locked and trying to invoke non-const method !"); +} + +YACSEvalVirtualYACSContainer::YACSEvalVirtualYACSContainer():_gf(0),_cont(0) +{ +} + +void YACSEvalVirtualYACSContainer::set(YACSEvalResource *gf, YACS::ENGINE::Container *cont) +{ + checkNonLocked(); + _gf=gf; + if(_cont==cont) + return ; + if(_cont) + _cont->decrRef(); + _cont=cont; + _propertyMap=listOfPropertiesInYACSContainer(); +} + +YACSEvalVirtualYACSContainer::YACSEvalVirtualYACSContainer(YACSEvalResource *gf, YACS::ENGINE::Container *cont):_gf(gf),_cont(cont) +{ + if(_cont) + _cont->incrRef(); + _propertyMap=listOfPropertiesInYACSContainer(); +} + +YACSEvalVirtualYACSContainer::~YACSEvalVirtualYACSContainer() +{ + if(_cont) + _cont->decrRef(); +} + +/*! + * \param [in,out] entry - Resource type instance to be updated with \a this. + */ +void YACSEvalVirtualYACSContainer::aggregate(ParserResourcesType& entry) const +{ + if(entry.HostName.empty()) + entry.HostName=getHostName(); + entry.DataForSort._memInMB=std::max(entry.DataForSort._memInMB,getMem()); + entry.DataForSort._nbOfProcPerNode=std::max(entry.DataForSort._nbOfProcPerNode,getNbProcPerNode()); + entry.DataForSort._nbOfNodes=std::max(entry.DataForSort._nbOfNodes,getNbNodes()); + entry.DataForSort._CPUFreqMHz=std::max(entry.DataForSort._CPUFreqMHz,getCPUFreq()); + std::vector comps(_gf->getGodFather()->getDeploymentTree()->getComponentsLinkedToContainer(_cont)); + std::set compNames; + for(std::vector::const_iterator it=comps.begin();it!=comps.end();it++) + { + YACS::ENGINE::ComponentInstance *elt(*it); + if(elt) + compNames.insert(elt->getCompoName()); + } + compNames.insert(entry.ComponentsList.begin(),entry.ComponentsList.end()); + compNames.erase(std::string()); + std::vector compNames2(compNames.begin(),compNames.end()); + entry.ComponentsList=compNames2; +} + +std::string YACSEvalVirtualYACSContainer::findDefault(bool isInteractive) const +{ + std::vector possibleHosts(_gf->getAllFittingMachines()); + for(std::vector::const_iterator it=possibleHosts.begin();it!=possibleHosts.end();it++) + { + if(_gf->getGodFather()->hasRightInteractiveStatus(*it,isInteractive)) + return *it; + } + throw YACS::Exception("YACSEvalVirtualYACSContainer::findDefault : impossible to find a right machine with requested interactive status !"); +} + +void YACSEvalVirtualYACSContainer::setWantedMachine(const std::string& machine) +{ + checkNonLocked(); + std::vector possibleHosts(_gf->getAllFittingMachines()); + if(std::find(possibleHosts.begin(),possibleHosts.end(),machine)==possibleHosts.end()) + throw YACS::Exception("YACSEvalVirtualYACSContainer::setWantedMachine : the specified machine is not in the list of available !"); + std::string oldMachine(getChosenMachine()); + setMachineNoCheck(machine); + try + { + _gf->notifyWantedMachine(this,oldMachine,machine); + } + catch(YACS::Exception& e) + { + setMachineNoCheck(oldMachine); + throw e; + } +} + +std::vector YACSEvalVirtualYACSContainer::listOfPropertyKeys() const +{ + std::set s; + std::map::const_iterator it; + for(it=_overloadedPropertyMap.begin();it!=_overloadedPropertyMap.end();it++) + s.insert((*it).first); + for(it=_propertyMap.begin();it!=_propertyMap.end();it++) + s.insert((*it).first); + std::vector ret(s.begin(),s.end()); + return ret; +} + +std::string YACSEvalVirtualYACSContainer::getValueOfKey(const char *key) const +{ + std::map::const_iterator it; + it=_overloadedPropertyMap.find(key); + if(it!=_overloadedPropertyMap.end()) + return (*it).second; + it=_propertyMap.find(key); + if(it!=_propertyMap.end()) + return (*it).second; + return std::string(); +} + +void YACSEvalVirtualYACSContainer::setProperty(const std::string& key, const std::string &value) +{ + checkNonLocked(); + _overloadedPropertyMap[key]=value; +} + +void YACSEvalVirtualYACSContainer::apply() +{ + YACS::ENGINE::SalomeContainer *cont0(dynamic_cast(_cont)); + YACS::ENGINE::SalomeHPContainer *cont1(dynamic_cast(_cont)); + if(cont0) + { + cont0->setProperty(HOSTNAME_KEY,getValueOfKey(HOSTNAME_KEY)); + return ; + } + else if(cont1) + { + cont1->setProperty(HOSTNAME_KEY,getValueOfKey(HOSTNAME_KEY)); + return ; + } + else + throw YACS::Exception("YACSEvalVirtualYACSContainer::apply : unrecognized container !"); +} + +unsigned int YACSEvalVirtualYACSContainer::getValueOfKeyUInt(const char *key) const +{ + std::string v(getValueOfKey(key)); + unsigned int ret(0); + if(v.empty()) + return ret; + std::istringstream iss(v); + iss >> ret; + return ret; +} + +std::map YACSEvalVirtualYACSContainer::listOfPropertiesInYACSContainer() const +{ + YACS::ENGINE::SalomeContainer *cont0(dynamic_cast(_cont)); + YACS::ENGINE::SalomeHPContainer *cont1(dynamic_cast(_cont)); + std::map props; + if(cont0) + props=cont0->getProperties(); + else if(cont1) + props=cont1->getProperties(); + return props; +} + +YACSEvalResource::~YACSEvalResource() +{ +} + +std::vector YACSEvalResource::getAllChosenMachines() const +{ + std::set s; + for(std::vector< YACSEvalVirtualYACSContainer >::const_iterator it=_containers.begin();it!=_containers.end();it++) + s.insert((*it).getChosenMachine()); + std::vector ret(s.begin(),s.end()); + return ret; +} + +std::vector YACSEvalResource::getAllFittingMachines() const +{ + ParserResourcesType ref; + aggregate(ref); + return _gf->getFittingResources(&ref); +} + +void YACSEvalResource::setWantedMachine(const std::string& machine) +{ + checkNonLocked(); + std::vector possibleHosts(getAllFittingMachines()); + if(std::find(possibleHosts.begin(),possibleHosts.end(),machine)==possibleHosts.end()) + throw YACS::Exception("YACSEvalResource::setWantedMachine : the specified machine is not in the list of available !"); + for(std::vector< YACSEvalVirtualYACSContainer >::iterator it=_containers.begin();it!=_containers.end();it++) + (*it).setMachineNoCheck(machine); +} + +YACSEvalVirtualYACSContainer *YACSEvalResource::at(std::size_t i) const +{ + if(i>=_containers.size()) + throw YACS::Exception("YACSEvalResource::at : invalid input ! must be < size !"); + return const_cast(&_containers[i]); +} + +void YACSEvalResource::apply() +{ + for(std::vector< YACSEvalVirtualYACSContainer >::iterator it=_containers.begin();it!=_containers.end();it++) + (*it).apply(); +} + +void YACSEvalResource::fitWithCurrentCatalogAbs() +{ + std::vector ress(getAllFittingMachines()); + if(ress.empty()) + throw YACS::Exception("YACSEvalResource::fitWithCurrentCatalogAbs : no suitable host in your catalog of resource !"); + setMachineNoCheck(ress.front()); +} + +void YACSEvalResource::aggregate(ParserResourcesType& entry) const +{ + for(std::vector< YACSEvalVirtualYACSContainer >::const_iterator it=_containers.begin();it!=_containers.end();it++) + (*it).aggregate(entry); +} + +void YACSEvalResource::notifyWantedMachine(YACSEvalVirtualYACSContainer *sender, const std::string& oldMachine, const std::string& newMachine) +{ + _gf->notifyWantedMachine(sender,oldMachine,newMachine); +} + +void YACSEvalResource::setMachineNoCheck(const std::string& machine) +{ + for(std::vector< YACSEvalVirtualYACSContainer >::iterator it=_containers.begin();it!=_containers.end();it++) + (*it).setMachineNoCheck(machine); +} + +YACSEvalResource::YACSEvalResource(YACSEvalListOfResources *gf, const std::vector< YACS::ENGINE::Container * >& conts):_gf(gf) +{ + std::size_t sz(conts.size()); + _containers.resize(sz); + for(std::size_t i=0;i conts(_dt->getAllContainers()); + std::map > listOfHosts; + for(std::vector::const_iterator it=conts.begin();it!=conts.end();it++) + { + std::vector cis(dt.getComponentsLinkedToContainer(*it)); + YACS::ENGINE::SalomeContainer *c1(dynamic_cast(*it)); + YACS::ENGINE::SalomeHPContainer *c2(dynamic_cast(*it)); + std::string zeHost; + if(c1) + zeHost=c1->getProperty(YACSEvalVirtualYACSContainer::HOSTNAME_KEY); + if(c2) + zeHost=c2->getProperty(YACSEvalVirtualYACSContainer::HOSTNAME_KEY); + listOfHosts[zeHost].push_back(*it); + } + for(std::map >::const_iterator it=listOfHosts.begin();it!=listOfHosts.end();it++) + _resources.push_back(new YACSEvalResourceEff(this,(*it).second)); + fitWithCurrentCatalog(); +} + +std::vector YACSEvalListOfResources::getAllChosenMachines() const +{ + std::set s; + for(std::vector::const_iterator it=_resources.begin();it!=_resources.end();it++) + { + std::vector tmp((*it)->getAllChosenMachines()); + s.insert(tmp.begin(),tmp.end()); + } + std::vector ret(s.begin(),s.end()); + return ret; +} + +std::vector YACSEvalListOfResources::getAllFittingMachines() const +{ + ParserResourcesType ref; + for(std::vector::const_iterator it=_resources.begin();it!=_resources.end();it++) + (*it)->aggregate(ref); + return getFittingResources(&ref); +} + +void YACSEvalListOfResources::setWantedMachine(const std::string& machine) +{ + checkNonLocked(); + std::vector possibleHosts(getAllFittingMachines()); + if(std::find(possibleHosts.begin(),possibleHosts.end(),machine)==possibleHosts.end()) + throw YACS::Exception("YACSEvalResource::setWantedMachine : the specified machine is not in the list of available !"); + for(std::vector::iterator it=_resources.begin();it!=_resources.end();it++) + (*it)->setMachineNoCheck(machine); +} + +YACSEvalResource *YACSEvalListOfResources::at(std::size_t i) const +{ + if(i>=size()) + throw YACS::Exception("YACSEvalListOfResources::at : invalid id !"); + return _resources[i]; +} + +bool YACSEvalListOfResources::isInteractive() const +{ + const MapOfParserResourcesType& zeList(_rm->GetList()); + std::vector allMachines(getAllChosenMachines()); + if(allMachines.empty()) + return true; + std::size_t ii(0),sz(allMachines.size()); + std::vector status(sz); + for(std::vector::const_iterator it=allMachines.begin();it!=allMachines.end();it++,ii++) + { + std::map::const_iterator it2(zeList.find(*it)); + if(it2==zeList.end()) + { + std::ostringstream oss; oss << "YACSEvalListOfResources::isInteractive : presence of non existing \"" << *it << "\" !"; + throw YACS::Exception(oss.str()); + } + const ParserResourcesType& elt((*it2).second); + status[ii]=(elt.ClusterInternalProtocol==sh || elt.ClusterInternalProtocol==rsh || elt.ClusterInternalProtocol==ssh); + } + std::size_t trueRet(std::count(status.begin(),status.end(),true)),falseRet(std::count(status.begin(),status.end(),false)); + if(trueRet==sz && falseRet==0) + return true; + else if(trueRet==0 && falseRet==sz) + return false; + throw YACS::Exception("YACSEvalListOfResources::isInteractive : mix of interactive and non interactive ! internal error !"); +} + +unsigned int YACSEvalListOfResources::getNumberOfProcsDeclared() const +{ + std::vector chosen(getAllChosenMachines()); + unsigned int ret(0); + for(std::vector::const_iterator it=chosen.begin();it!=chosen.end();it++) + ret+=getNumberOfProcOfResource(*it); + return ret; +} + +void YACSEvalListOfResources::apply() +{ + for(std::vector::iterator it=_resources.begin();it!=_resources.end();it++) + (*it)->apply(); +} + +YACSEvalListOfResources::~YACSEvalListOfResources() +{ + delete _dt; + for(std::vector::iterator it=_resources.begin();it!=_resources.end();it++) + delete *it; +} + +class EffectiveComparator +{ +public: + virtual ~EffectiveComparator() { } + virtual EffectiveComparator *copy() const = 0; + virtual bool compare(const ResourceDataToSort& elt1, const ResourceDataToSort& elt2) const = 0; +}; + +// comparator for a null request in scheme +class BasicComparator : public EffectiveComparator +{ +public: + EffectiveComparator *copy() const { return new BasicComparator; } + bool compare(const ResourceDataToSort& elt1, const ResourceDataToSort& elt2) const; +}; + +class MemAwareComparator : public EffectiveComparator +{ +public: + EffectiveComparator *copy() const { return new MemAwareComparator; } + bool compare(const ResourceDataToSort& elt1, const ResourceDataToSort& elt2) const; +}; + +class CompromiseComparator : public EffectiveComparator +{ +public: + CompromiseComparator(int memMB, int nbProcs):_memMB(memMB),_nbProcs(nbProcs) { } + EffectiveComparator *copy() const { return new CompromiseComparator(_memMB,_nbProcs); } + bool compare(const ResourceDataToSort& elt1, const ResourceDataToSort& elt2) const; +private: + int _memMB; + int _nbProcs; +}; + +class CompareRes +{ +public: + CompareRes(const ParserResourcesType *request, const MapOfParserResourcesType& zeCatalog); + CompareRes(const CompareRes& other); + bool operator()(const std::string& res1, const std::string& res2); + ~CompareRes() { delete _comp; } +private: + EffectiveComparator *_comp; + const ParserResourcesType *_request; + const MapOfParserResourcesType& _zeCatalog; +}; + +bool BasicComparator::compare(const ResourceDataToSort& elt1, const ResourceDataToSort& elt2) const +{ + int nbOfProcs1(elt1._nbOfNodes*elt1._nbOfProcPerNode),nbOfProcs2(elt2._nbOfNodes*elt2._nbOfProcPerNode); + return nbOfProcs1DataForSort); + // all request items are set to default -> Basic comparison on procs + if(request->DataForSort._nbOfNodes==1 && request->DataForSort._nbOfProcPerNode==1 && request->DataForSort._memInMB==0) + _comp=new BasicComparator; + // all items are set to default except memory -> Memory aware only + else if(request->DataForSort._memInMB!=0 && request->DataForSort._nbOfNodes==1 && request->DataForSort._nbOfProcPerNode==1) + _comp=new MemAwareComparator; + // memory and procs are set by the user -> do the best possible. + else if(request->DataForSort._memInMB!=0 && ( request->DataForSort._nbOfNodes!=1 || request->DataForSort._nbOfProcPerNode!=1 ) ) + _comp=new CompromiseComparator(request->DataForSort._memInMB,request->DataForSort._nbOfNodes*request->DataForSort._nbOfProcPerNode); + else + _comp=new BasicComparator; +} + +CompareRes::CompareRes(const CompareRes& other):_comp(other._comp->copy()),_request(other._request),_zeCatalog(other._zeCatalog) +{ +} + +bool CompareRes::operator()(const std::string& res1, const std::string& res2) +{ + std::map::const_iterator it1(_zeCatalog.find(res1)),it2(_zeCatalog.find(res2)); + if(it1==_zeCatalog.end() || it2==_zeCatalog.end()) + throw YACS::Exception("Internal error during comparison !"); + const ParserResourcesType& elt1((*it1).second); + const ParserResourcesType& elt2((*it2).second); + return _comp->compare(elt1.DataForSort,elt2.DataForSort); +} + +/*! + * Implements an another alg than those proposed by default in ResourcesManager_cpp in "ResourcesManager.hxx". + */ +std::vector YACSEvalListOfResources::getFittingResources(ParserResourcesType *request) const +{ + int mlop(getMaxLevelOfParallelism()); + request->DataForSort._memInMB*=mlop; + request->DataForSort._nbOfNodes*=mlop; + // + const MapOfParserResourcesType& zeListInCatalog(_rm->GetList()); + std::vector list0; + // first keep those having relevant components + const std::vector& listExpected(request->ComponentsList); + std::set listExpected2(listExpected.begin(),listExpected.end()); + for(std::map::const_iterator it=zeListInCatalog.begin();it!=zeListInCatalog.end();it++) + { + const std::vector& compoList((*it).second.ComponentsList); + std::set s1(compoList.begin(),compoList.end()); + std::vector diff; + std::set_difference(listExpected2.begin(),listExpected2.end(),s1.begin(),s1.end(),std::inserter(diff,diff.begin())); + if(diff.empty()) + list0.push_back((*it).first); + } + // sort list0 regarding request + std::sort(list0.begin(),list0.end(),CompareRes(request,zeListInCatalog)); + // if HostName in request is defined and in list0 put it first. + std::string tmp(request->HostName); + if(!tmp.empty()) + { + std::vector::iterator it1(std::find(list0.begin(),list0.end(),tmp)); + if(it1!=list0.end()) + {// HostName in list0 so put it in first place. + list0.erase(it1); + list0.insert(list0.begin(),tmp); + } + } + return list0; +} + +void YACSEvalListOfResources::notifyWantedMachine(YACSEvalVirtualYACSContainer *sender, const std::string& oldMachine, const std::string& newMachine) +{ + const MapOfParserResourcesType& zeList(_rm->GetList()); + std::map::const_iterator itOld(zeList.find(oldMachine)),itNew(zeList.find(newMachine)); + if(itOld==zeList.end() || itNew==zeList.end()) + throw YACS::Exception("YACSEvalListOfResources::notifyWantedMachine : internal error !"); + const ParserResourcesType& oldPRT((*itOld).second); + const ParserResourcesType& newPRT((*itNew).second); + if(oldPRT.ClusterInternalProtocol==newPRT.ClusterInternalProtocol) + return ; + // the batch/interactive mode has changed -> try to change for all. + std::queue sts; + try + { + for(std::vector::const_iterator it=_resources.begin();it!=_resources.end();it++) + { + std::size_t sz((*it)->size()); + for(std::size_t i=0;iat(i)); + if(cont==sender) + continue; + sts.push(cont->findDefault(newPRT.ClusterInternalProtocol==sh)); + } + } + } + catch(YACS::Exception& e) + { + std::ostringstream oss; oss << "YACSEvalListOfResources::notifyWantedMachine : switching from interactive/batch must be global ! " << e.what(); + throw YACS::Exception(oss.str()); + } + for(std::vector::const_iterator it=_resources.begin();it!=_resources.end();it++) + { + std::size_t sz((*it)->size()); + for(std::size_t i=0;iat(i)); + if(cont==sender) + continue; + cont->setMachineNoCheck(sts.front()); + sts.pop(); + } + } +} + +bool YACSEvalListOfResources::hasRightInteractiveStatus(const std::string& machineToTest, bool isInteractive) const +{ + const MapOfParserResourcesType& zeList(_rm->GetList()); + std::map::const_iterator it(zeList.find(machineToTest)); + if(it==zeList.end()) + throw YACS::Exception("YACSEvalListOfResources::hasRightInteractiveStatus : internal error !"); + const ParserResourcesType& elt((*it).second); + bool myStatus(elt.ClusterInternalProtocol==sh); + return myStatus==isInteractive; +} + +void YACSEvalListOfResources::fitWithCurrentCatalog() +{ + std::vector ress(getAllFittingMachines()); + if(ress.empty()) + throw YACS::Exception("YACSEvalListOfResources::fitWithCurrentCatalog : no available resource in your catalog !"); + for(std::vector::iterator it=_resources.begin();it!=_resources.end();it++) + (*it)->setMachineNoCheck(ress.front()); +} + +unsigned int YACSEvalListOfResources::getNumberOfProcOfResource(const std::string& machine) const +{ + const MapOfParserResourcesType& zeList(_rm->GetList()); + std::map::const_iterator it(zeList.find(machine)); + if(it==zeList.end()) + throw YACS::Exception("YACSEvalListOfResources::getNumberOfProcOfResource : internal error !"); + const ParserResourcesType& PRT((*it).second); + const ResourceDataToSort& RDT(PRT.DataForSort); + unsigned int ret(RDT._nbOfNodes*RDT._nbOfProcPerNode); + return ret; +} diff --git a/src/evalyfx/YACSEvalResource.hxx b/src/evalyfx/YACSEvalResource.hxx new file mode 100644 index 000000000..344d76488 --- /dev/null +++ b/src/evalyfx/YACSEvalResource.hxx @@ -0,0 +1,157 @@ +// Copyright (C) 2012-2015 CEA/DEN, EDF R&D +// +// 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, or (at your option) any later version. +// +// 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 +// +// Author : Anthony Geay (EDF R&D) + +#ifndef __YACSEVALRESOURCE_HXX__ +#define __YACSEVALRESOURCE_HXX__ + +#include "YACSEvalYFXExport.hxx" + +#include +#include +#include + +namespace YACS +{ + namespace ENGINE + { + class Container; + class DeploymentTree; + } +} + +class YACSEvalNonConstLocker +{ +public: + YACSEVALYFX_EXPORT YACSEvalNonConstLocker():_isLocked(false) { } + YACSEVALYFX_EXPORT YACSEvalNonConstLocker(const YACSEvalNonConstLocker& other):_isLocked(false) { } + YACSEVALYFX_EXPORT void lock() { _isLocked=true; } + YACSEVALYFX_EXPORT bool isLocked() const { return _isLocked; } + YACSEVALYFX_EXPORT void checkNonLocked() const; +private: + bool _isLocked; +}; + +class ParserResourcesType; +class YACSEvalResource; + +class YACSEvalVirtualYACSContainer : public YACSEvalNonConstLocker +{ +public: + YACSEvalVirtualYACSContainer(YACSEvalResource *gf, YACS::ENGINE::Container *cont); + YACSEVALYFX_EXPORT ~YACSEvalVirtualYACSContainer(); + YACSEVALYFX_EXPORT std::string getChosenMachine() const { return _chosenHost; } + YACSEVALYFX_EXPORT void setWantedMachine(const std::string& machine); + YACSEVALYFX_EXPORT std::vector listOfPropertyKeys() const; + YACSEVALYFX_EXPORT std::string getValueOfKey(const char *key) const; + YACSEVALYFX_EXPORT void setProperty(const std::string& key, const std::string &value); + YACSEVALYFX_EXPORT void resetOverloadedProps() { checkNonLocked(); _overloadedPropertyMap.clear(); } + void apply(); +public: + YACSEvalVirtualYACSContainer(); + void set(YACSEvalResource *gf, YACS::ENGINE::Container *cont); + void aggregate(ParserResourcesType& entry) const; + void setMachineNoCheck(const std::string& machine) { checkNonLocked(); _chosenHost=machine; } + std::string findDefault(bool isInteractive) const; +private: + std::string getHostName() const { return getValueOfKey(HOSTNAME_KEY); } + unsigned int getMem() const { return getValueOfKeyUInt(MEM_KEY); } + unsigned int getNbNodes() const { return getValueOfKeyUInt(NB_NODE_KEY); } + unsigned int getCPUFreq() const { return getValueOfKeyUInt(CPU_CLOCK_KEY); } + unsigned int getNbProcPerNode() const { return getValueOfKeyUInt(NB_PROC_PER_NODE_KEY); } + unsigned int getValueOfKeyUInt(const char *key) const; + std::map listOfPropertiesInYACSContainer() const; +public: + YACSEVALYFX_EXPORT static const char CONTAINER_NAME_KEY[]; + YACSEVALYFX_EXPORT static const char CPU_CLOCK_KEY[]; + YACSEVALYFX_EXPORT static const char HOSTNAME_KEY[]; + YACSEVALYFX_EXPORT static const char MEM_KEY[]; + YACSEVALYFX_EXPORT static const char NB_NODE_KEY[]; + YACSEVALYFX_EXPORT static const char NB_PROC_PER_NODE_KEY[]; + YACSEVALYFX_EXPORT static const char NB_RESOURCE_PROCS_KEY[]; + YACSEVALYFX_EXPORT static const char POLICY_KEY[]; + YACSEVALYFX_EXPORT static const char OS_KEY[]; +private: + std::string _chosenHost; + //! list of properties that overloads. + std::map _overloadedPropertyMap; + //! property map at the origin. + std::map _propertyMap; + YACSEvalResource *_gf; + YACS::ENGINE::Container *_cont; +}; + +class YACSEvalListOfResources; + +class YACSEvalResource : public YACSEvalNonConstLocker +{ +public: + YACSEVALYFX_EXPORT virtual ~YACSEvalResource(); + YACSEVALYFX_EXPORT std::vector getAllChosenMachines() const; + YACSEVALYFX_EXPORT std::vector getAllFittingMachines() const; + YACSEVALYFX_EXPORT void setWantedMachine(const std::string& machine); + YACSEVALYFX_EXPORT std::size_t size() const { return _containers.size(); } + YACSEVALYFX_EXPORT YACSEvalVirtualYACSContainer *at(std::size_t i) const; + YACSEVALYFX_EXPORT void apply(); +public: + void fitWithCurrentCatalogAbs(); + void aggregate(ParserResourcesType& entry) const; + YACSEvalListOfResources *getGodFather() const { return _gf; } + void notifyWantedMachine(YACSEvalVirtualYACSContainer *sender, const std::string& oldMachine, const std::string& newMachine); + void setMachineNoCheck(const std::string& machine); +protected: + YACSEvalResource(YACSEvalListOfResources *gf, const std::vector< YACS::ENGINE::Container * >& conts); +protected: + YACSEvalListOfResources *_gf; + std::vector< YACSEvalVirtualYACSContainer > _containers; +}; + +class ResourcesManager_cpp; + +class YACSEvalListOfResources : public YACSEvalNonConstLocker +{ +public: + YACSEvalListOfResources(int maxLevOfPara, ResourcesManager_cpp *rm, const YACS::ENGINE::DeploymentTree& dt); + YACSEVALYFX_EXPORT std::vector getAllChosenMachines() const; + YACSEVALYFX_EXPORT std::vector getAllFittingMachines() const; + YACSEVALYFX_EXPORT void setWantedMachine(const std::string& machine); + YACSEVALYFX_EXPORT std::size_t size() const { return _resources.size(); } + YACSEVALYFX_EXPORT YACSEvalResource *at(std::size_t i) const; + YACSEVALYFX_EXPORT bool isInteractive() const; + YACSEVALYFX_EXPORT unsigned int getNumberOfProcsDeclared() const; + void apply(); + YACSEVALYFX_EXPORT ~YACSEvalListOfResources(); +public: + ResourcesManager_cpp *getCatalogEntry() const { return _rm; } + YACS::ENGINE::DeploymentTree *getDeploymentTree() const { return _dt; } + int getMaxLevelOfParallelism() const { return _maxLevOfPara; } + std::vector getFittingResources(ParserResourcesType *request) const; + void notifyWantedMachine(YACSEvalVirtualYACSContainer *sender, const std::string& oldMachine, const std::string& newMachine); + bool hasRightInteractiveStatus(const std::string& machineToTest, bool isInteractive) const; +private: + void fitWithCurrentCatalog(); + unsigned int getNumberOfProcOfResource(const std::string& machine) const; +private: + ResourcesManager_cpp *_rm; + int _maxLevOfPara; + std::vector _resources; + YACS::ENGINE::DeploymentTree *_dt; +}; + +#endif diff --git a/src/evalyfx/YACSEvalSeqAny.cxx b/src/evalyfx/YACSEvalSeqAny.cxx new file mode 100644 index 000000000..43f3fad2d --- /dev/null +++ b/src/evalyfx/YACSEvalSeqAny.cxx @@ -0,0 +1,135 @@ +// Copyright (C) 2012-2015 CEA/DEN, EDF R&D +// +// 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, or (at your option) any later version. +// +// 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 +// +// Author : Anthony Geay (EDF R&D) + +#include "YACSEvalSeqAny.hxx" +#include "YACSEvalPort.hxx" +#include "Exception.hxx" + +#include "PythonPorts.hxx" + +YACSEvalSeqAny *YACSEvalSeqAny::BuildEmptyFromType(const std::string& dataType) +{ + if(dataType==YACSEvalAnyDouble::TYPE_REPR) + return new YACSEvalSeqAnyDouble; + else if(dataType==YACSEvalAnyInt::TYPE_REPR) + return new YACSEvalSeqAnyInt; + else + throw YACS::Exception("YACSEvalSeqAny::BuildEmptyFromType : Only int and double are actualy managed !"); +} + +template +std::size_t YACSEvalSeqAnyInternal::size() const +{ + if(!_arr) + throw YACS::Exception("YACSEvalSeqAnyDouble::size : empty array !"); + return _arr->size(); +} + +YACSEvalSeqAnyDouble::YACSEvalSeqAnyDouble(const std::vector& arr):_arr(0) +{ + std::vector *zeArr(new std::vector(arr)); + _arr=YACSEvalSeqAnyInternal::New(zeArr); +} + +YACSEvalSeqAnyDouble::YACSEvalSeqAnyDouble(const YACSEvalSeqAnyDouble& other):_arr(other._arr) +{ + if(_arr) + _arr->incrRef(); +} + +YACSEvalSeqAnyDouble::YACSEvalSeqAnyDouble():_arr(YACSEvalSeqAnyInternal::New(new std::vector(0))) +{ +} + +std::string YACSEvalSeqAnyDouble::getTypeOfConstitutingElements() const +{ + return std::string(YACSEvalAnyDouble::TYPE_REPR); +} + +YACSEvalSeqAnyDouble *YACSEvalSeqAnyDouble::copy() const +{ + return new YACSEvalSeqAnyDouble(*this); +} + +void YACSEvalSeqAnyDouble::initialize(YACS::ENGINE::InputPyPort *p) const +{ + std::size_t sz(size()); + PyObject *ob(PyList_New(sz)); + for(std::size_t i=0;iput(ob); + p->exSaveInit(); + Py_XDECREF(ob); +} + +std::vector *YACSEvalSeqAnyDouble::getInternal() const +{ + if(!_arr) + throw YACS::Exception("YACSEvalSeqAnyDouble::getInternal : null internal ref !"); + return _arr->getInternal(); +} + +YACSEvalSeqAnyInt::YACSEvalSeqAnyInt(const std::vector& arr):_arr(0) +{ + std::vector *zeArr(new std::vector(arr)); + _arr=YACSEvalSeqAnyInternal::New(zeArr); +} + +YACSEvalSeqAnyInt::YACSEvalSeqAnyInt(const YACSEvalSeqAnyInt& other):_arr(other._arr) +{ + if(_arr) + _arr->incrRef(); +} + +YACSEvalSeqAnyInt::YACSEvalSeqAnyInt():_arr(YACSEvalSeqAnyInternal::New(new std::vector(0))) +{ +} + +std::string YACSEvalSeqAnyInt::getTypeOfConstitutingElements() const +{ + return std::string(YACSEvalAnyInt::TYPE_REPR); +} + +YACSEvalSeqAnyInt *YACSEvalSeqAnyInt::copy() const +{ + return new YACSEvalSeqAnyInt(*this); +} + +void YACSEvalSeqAnyInt::initialize(YACS::ENGINE::InputPyPort *p) const +{ + std::size_t sz(size()); + PyObject *ob(PyList_New(sz)); + for(std::size_t i=0;iput(ob); + p->exSaveInit(); + Py_XDECREF(ob); +} + +std::vector *YACSEvalSeqAnyInt::getInternal() const +{ + if(!_arr) + throw YACS::Exception("YACSEvalSeqAnyInt::getInternal : null internal ref !"); + return _arr->getInternal(); +} diff --git a/src/evalyfx/YACSEvalSeqAny.hxx b/src/evalyfx/YACSEvalSeqAny.hxx new file mode 100644 index 000000000..d0edbf4d2 --- /dev/null +++ b/src/evalyfx/YACSEvalSeqAny.hxx @@ -0,0 +1,97 @@ +// Copyright (C) 2012-2015 CEA/DEN, EDF R&D +// +// 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, or (at your option) any later version. +// +// 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 +// +// Author : Anthony Geay (EDF R&D) + +#ifndef __YACSEVALSEQANY_HXX__ +#define __YACSEVALSEQANY_HXX__ + +#include "YACSEvalYFXExport.hxx" +#include "RefCounter.hxx" +#include "Exception.hxx" + +#include +#include + +namespace YACS +{ + namespace ENGINE + { + class InputPyPort; + } +} + +class YACSEvalSeqAny +{ +public: + YACSEVALYFX_EXPORT static YACSEvalSeqAny *BuildEmptyFromType(const std::string& dataType); + YACSEVALYFX_EXPORT virtual std::size_t size() const = 0; + YACSEVALYFX_EXPORT virtual std::string getTypeOfConstitutingElements() const = 0; + YACSEVALYFX_EXPORT virtual YACSEvalSeqAny *copy() const = 0; + YACSEVALYFX_EXPORT virtual void initialize(YACS::ENGINE::InputPyPort *p) const = 0; + YACSEVALYFX_EXPORT virtual ~YACSEvalSeqAny() { } +}; + +template +class YACSEvalSeqAnyInternal : public YACS::ENGINE::RefCounter +{ +public: + static YACSEvalSeqAnyInternal *New(std::vector *arr) { return new YACSEvalSeqAnyInternal(arr); } + std::size_t size() const; + T operator[](const std::size_t i) const { if(_arr) return (*_arr)[i]; else throw YACS::Exception("YACSEvalSeqAnyInternal[] : internal pointer is null !"); } + std::vector *getInternal() const { return _arr; } +private: + ~YACSEvalSeqAnyInternal() { delete _arr; } + YACSEvalSeqAnyInternal(std::vector *arr):_arr(arr) { } +private: + std::vector *_arr; +}; + +class YACSEvalSeqAnyDouble : public YACSEvalSeqAny +{ +public: + YACSEVALYFX_EXPORT std::size_t size() const { return _arr->size(); } + YACSEVALYFX_EXPORT ~YACSEvalSeqAnyDouble() { if(_arr) _arr->decrRef(); } + YACSEVALYFX_EXPORT YACSEvalSeqAnyDouble(const std::vector& arr); + YACSEVALYFX_EXPORT YACSEvalSeqAnyDouble(const YACSEvalSeqAnyDouble& other); + YACSEVALYFX_EXPORT YACSEvalSeqAnyDouble(); + YACSEVALYFX_EXPORT std::string getTypeOfConstitutingElements() const; + YACSEVALYFX_EXPORT YACSEvalSeqAnyDouble *copy() const; + YACSEVALYFX_EXPORT void initialize(YACS::ENGINE::InputPyPort *p) const; + YACSEVALYFX_EXPORT std::vector *getInternal() const; +private: + YACSEvalSeqAnyInternal *_arr; +}; + +class YACSEvalSeqAnyInt : public YACSEvalSeqAny +{ +public: + YACSEVALYFX_EXPORT std::size_t size() const { return _arr->size(); } + YACSEVALYFX_EXPORT ~YACSEvalSeqAnyInt() { if(_arr) _arr->decrRef(); } + YACSEVALYFX_EXPORT YACSEvalSeqAnyInt(const std::vector& arr); + YACSEVALYFX_EXPORT YACSEvalSeqAnyInt(const YACSEvalSeqAnyInt& other); + YACSEVALYFX_EXPORT YACSEvalSeqAnyInt(); + YACSEVALYFX_EXPORT std::string getTypeOfConstitutingElements() const; + YACSEVALYFX_EXPORT YACSEvalSeqAnyInt *copy() const; + YACSEVALYFX_EXPORT void initialize(YACS::ENGINE::InputPyPort *p) const; + YACSEVALYFX_EXPORT std::vector *getInternal() const; +private: + YACSEvalSeqAnyInternal *_arr; +}; + +#endif diff --git a/src/evalyfx/YACSEvalSession.cxx b/src/evalyfx/YACSEvalSession.cxx new file mode 100644 index 000000000..43b44787c --- /dev/null +++ b/src/evalyfx/YACSEvalSession.cxx @@ -0,0 +1,130 @@ +// Copyright (C) 2012-2015 CEA/DEN, EDF R&D +// +// 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, or (at your option) any later version. +// +// 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 +// +// Author : Anthony Geay (EDF R&D) + +#include "YACSEvalSession.hxx" +#include "Exception.hxx" + +#include + +const char YACSEvalSession::KERNEL_ROOT_DIR[]="KERNEL_ROOT_DIR"; + +const char YACSEvalSession::CORBA_CONFIG_ENV_VAR_NAME[]="OMNIORB_CONFIG"; + +YACSEvalSession::YACSEvalSession():_isLaunched(false),_port(-1),_salomeInstanceModule(0),_salomeInstance(0) +{ + if(!Py_IsInitialized()) + Py_Initialize(); + // + _salomeInstanceModule=PyImport_ImportModule(const_cast("salome_instance")); +} + +YACSEvalSession::~YACSEvalSession() +{ + if(isLaunched()) + { + PyObject *terminateSession(PyObject_GetAttrString(_salomeInstance,const_cast("stop")));//new + PyObject *res(PyObject_CallObject(terminateSession,0)); + Py_XDECREF(res); + Py_XDECREF(terminateSession); + } + Py_XDECREF(_salomeInstance); + Py_XDECREF(_salomeInstanceModule); +} + +void YACSEvalSession::launch() +{ + if(isLaunched()) + return ; + PyObject *salomeInstance(PyObject_GetAttrString(_salomeInstanceModule,const_cast("SalomeInstance")));//new + PyObject *startMeth(PyObject_GetAttrString(salomeInstance,const_cast("start"))); + Py_XDECREF(salomeInstance); + PyObject *myArgs(PyTuple_New(0));//new + PyObject *myKWArgs(PyDict_New());//new + PyDict_SetItemString(myKWArgs,"shutdown_servers",Py_True);//Py_True ref not stolen + _salomeInstance=PyObject_Call(startMeth,myArgs,myKWArgs);//new + PyObject *getPortMeth(PyObject_GetAttrString(_salomeInstance,const_cast("get_port")));//new + PyObject *portPy(PyObject_CallObject(getPortMeth,0));//new + _port=PyInt_AsLong(portPy); + Py_XDECREF(portPy); + Py_XDECREF(getPortMeth); + Py_XDECREF(myKWArgs); + Py_XDECREF(myArgs); + // + PyObject *osPy(PyImport_ImportModule(const_cast("os")));//new + PyObject *environPy(PyObject_GetAttrString(osPy,const_cast("environ")));//new + PyObject *corbaConfigStr(PyString_FromString(const_cast(CORBA_CONFIG_ENV_VAR_NAME)));//new + PyObject *corbaConfigFileNamePy(PyObject_GetItem(environPy,corbaConfigStr));//new + _corbaConfigFileName=PyString_AsString(corbaConfigFileNamePy); + Py_XDECREF(corbaConfigFileNamePy); + Py_XDECREF(corbaConfigStr); + Py_XDECREF(environPy); + Py_XDECREF(osPy); + _isLaunched=true; +} + +void YACSEvalSession::checkLaunched() const +{ + if(!isLaunched()) + throw YACS::Exception("YACSEvalSession::checkLaunched : not launched !"); +} + +int YACSEvalSession::getPort() const +{ + checkLaunched(); + return _port; +} + +std::string YACSEvalSession::getCorbaConfigFileName() const +{ + checkLaunched(); + return _corbaConfigFileName; +} + +std::string YACSEvalSession::GetPathToAdd() +{ + std::string ret; + PyObject *osPy(PyImport_ImportModule(const_cast("os")));//new + PyObject *kernelRootDir(0);// os.environ["KERNEL_ROOT_DIR"] + { + PyObject *environPy(PyObject_GetAttrString(osPy,const_cast("environ")));//new + PyObject *kernelRootDirStr(PyString_FromString(const_cast(KERNEL_ROOT_DIR)));//new + kernelRootDir=PyObject_GetItem(environPy,kernelRootDirStr);//new + Py_XDECREF(kernelRootDirStr); + Py_XDECREF(environPy); + } + { + PyObject *pathPy(PyObject_GetAttrString(osPy,const_cast("path")));//new + PyObject *joinPy(PyObject_GetAttrString(pathPy,const_cast("join")));//new + PyObject *myArgs(PyTuple_New(4)); + Py_XINCREF(kernelRootDir); PyTuple_SetItem(myArgs,0,kernelRootDir); + PyTuple_SetItem(myArgs,1,PyString_FromString(const_cast("bin"))); + PyTuple_SetItem(myArgs,2,PyString_FromString(const_cast("salome"))); + PyTuple_SetItem(myArgs,3,PyString_FromString(const_cast("appliskel"))); + PyObject *res(PyObject_CallObject(joinPy,myArgs)); + ret=PyString_AsString(res); + Py_XDECREF(res); + Py_XDECREF(myArgs); + Py_XDECREF(joinPy); + Py_XDECREF(pathPy); + } + Py_XDECREF(kernelRootDir); + Py_XDECREF(osPy); + return ret; +} diff --git a/src/evalyfx/YACSEvalSession.hxx b/src/evalyfx/YACSEvalSession.hxx new file mode 100644 index 000000000..ba62b76c7 --- /dev/null +++ b/src/evalyfx/YACSEvalSession.hxx @@ -0,0 +1,54 @@ +// Copyright (C) 2012-2015 CEA/DEN, EDF R&D +// +// 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, or (at your option) any later version. +// +// 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 +// +// Author : Anthony Geay (EDF R&D) + +#ifndef __YACSEVALSESSION_HXX__ +#define __YACSEVALSESSION_HXX__ + +#include "YACSEvalYFXExport.hxx" + +#include + +struct _object; +typedef _object PyObject; + +class YACSEvalSession +{ +public: + YACSEVALYFX_EXPORT YACSEvalSession(); + YACSEVALYFX_EXPORT ~YACSEvalSession(); + YACSEVALYFX_EXPORT void launch(); + YACSEVALYFX_EXPORT bool isLaunched() const { return _isLaunched; } + YACSEVALYFX_EXPORT void checkLaunched() const; + YACSEVALYFX_EXPORT int getPort() const; + YACSEVALYFX_EXPORT std::string getCorbaConfigFileName() const; +private: + static std::string GetPathToAdd(); +public: + YACSEVALYFX_EXPORT static const char KERNEL_ROOT_DIR[]; + YACSEVALYFX_EXPORT static const char CORBA_CONFIG_ENV_VAR_NAME[]; +private: + bool _isLaunched; + int _port; + std::string _corbaConfigFileName; + PyObject *_salomeInstanceModule; + PyObject *_salomeInstance; +}; + +#endif diff --git a/src/evalyfx/YACSEvalYFX.cxx b/src/evalyfx/YACSEvalYFX.cxx new file mode 100644 index 000000000..b3210bd5e --- /dev/null +++ b/src/evalyfx/YACSEvalYFX.cxx @@ -0,0 +1,180 @@ +// Copyright (C) 2012-2015 CEA/DEN, EDF R&D +// +// 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, or (at your option) any later version. +// +// 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 +// +// Author : Anthony Geay (EDF R&D) + +#include "YACSEvalYFX.hxx" +#include "YACSEvalYFXPattern.hxx" +#include "YACSEvalAutoPtr.hxx" +#include "YACSEvalResource.hxx" +#include "YACSEvalSession.hxx" +#include "YACSEvalPort.hxx" +#include "RuntimeSALOME.hxx" +#include "Executor.hxx" +#include "Proc.hxx" +#include "Exception.hxx" +#include "parsers.hxx" + +#include +#include +#include +#include + +#include + +class MyAutoThreadSaver +{ +public: + MyAutoThreadSaver():_save(PyEval_SaveThread()) { } + ~MyAutoThreadSaver() { PyEval_RestoreThread(_save); } +private: + PyThreadState *_save; +}; + + +YACSEvalYFX *YACSEvalYFX::BuildFromFile(const std::string& xmlOfScheme) +{ + YACS::ENGINE::RuntimeSALOME::setRuntime(); + YACS::YACSLoader l; + YACS::ENGINE::Proc *scheme(l.load(xmlOfScheme.c_str())); + return new YACSEvalYFX(scheme,true); +} + +YACSEvalYFX *YACSEvalYFX::BuildFromScheme(YACS::ENGINE::Proc *scheme) +{ + return new YACSEvalYFX(scheme,false); +} + +std::list< YACSEvalInputPort * > YACSEvalYFX::getFreeInputPorts() const +{ + return _pattern->getFreeInputPorts(); +} + +std::list< YACSEvalOutputPort * > YACSEvalYFX::getFreeOutputPorts() const +{ + return _pattern->getFreeOutputPorts(); +} + +void YACSEvalYFX::lockPortsForEvaluation(const std::list< YACSEvalOutputPort * >& outputsOfInterest) +{ + std::size_t sz(checkPortsForEvaluation(outputsOfInterest)); + _pattern->setOutPortsOfInterestForEvaluation(sz,outputsOfInterest); + _pattern->generateGraph(); +} + +void YACSEvalYFX::unlockAll() +{ + std::list< YACSEvalInputPort * > allInputs(getFreeInputPorts()); + for(std::list< YACSEvalInputPort * >::const_iterator it=allInputs.begin();it!=allInputs.end();it++) + (*it)->unlock(); + _pattern->resetOutputsOfInterest(); + _pattern->resetGeneratedGraph(); +} + +bool YACSEvalYFX::isLocked() const +{ + return _pattern->isLocked(); +} + +YACSEvalListOfResources *YACSEvalYFX::giveResources() +{ + return _pattern->giveResources(); +} + +bool YACSEvalYFX::run(YACSEvalSession *session, int& nbOfBranches) +{ + YACSEvalListOfResources *rss(giveResources()); + if(!rss->isInteractive()) + throw YACS::Exception("YACSEvalYFX::run : not implemented yet for non interactive !"); + YACSEvalSession *mySession(session); + YACS::AutoCppPtr loc; + if(!session) + { + throw YACS::Exception("YACSEvalYFX::run : input session in null !"); + /*loc=new YACSEvalSession; + mySession=loc;*/ + } + rss->apply(); + nbOfBranches=_pattern->assignNbOfBranches(); + mySession->launch(); + YACS::ENGINE::Executor exe; + // + { + MyAutoThreadSaver locker; + exe.RunW(getUndergroundGeneratedGraph()); + } + return getUndergroundGeneratedGraph()->getState()==YACS::DONE; +} + +std::vector YACSEvalYFX::getResults() const +{ + return _pattern->getResults(); +} + +YACS::ENGINE::Proc *YACSEvalYFX::getUndergroundGeneratedGraph() const +{ + return _pattern->getUndergroundGeneratedGraph(); +} + +YACSEvalYFX::YACSEvalYFX(YACS::ENGINE::Proc *scheme, bool ownScheme):_pattern(0) +{ + _pattern=YACSEvalYFXPattern::FindPatternFrom(scheme,ownScheme); +} + +std::size_t YACSEvalYFX::checkPortsForEvaluation(const std::list< YACSEvalOutputPort * >& outputs) const +{ + std::list< YACSEvalInputPort * > allInputs(getFreeInputPorts()); + std::list< YACSEvalOutputPort * > allOutputs(getFreeOutputPorts()); + std::size_t sz(std::numeric_limits::max()); + for(std::list< YACSEvalInputPort * >::const_iterator it=allInputs.begin();it!=allInputs.end();it++) + { + std::size_t mySz; + if(!(*it)->isOKForLock() && !(*it)->hasSequenceOfValuesToEval(mySz)) + { + std::ostringstream oss; oss << "YACSEvalYFX::checkPortsForEvaluation : input port with name \"" << (*it)->getName() << "\" is not set properly !"; + throw YACS::Exception(oss.str()); + } + if((*it)->hasSequenceOfValuesToEval(mySz)) + { + if(sz==std::numeric_limits::max()) + sz=mySz; + else + { + if(sz!=mySz) + { + std::ostringstream oss; oss << "YACSEvalYFX::checkPortsForEvaluation : input port with name \"" << (*it)->getName() << "\" is declared as to be evaluated on array ! But size of array is not the same than the others !"; + throw YACS::Exception(oss.str()); + } + } + } + } + for(std::list< YACSEvalOutputPort * >::const_iterator it=outputs.begin();it!=outputs.end();it++) + if(std::find(allOutputs.begin(),allOutputs.end(),*it)==allOutputs.end()) + throw YACS::Exception("YACSEvalYFX::lockPortsForEvaluation : one of output is not part of this !"); + std::set< YACSEvalOutputPort * > soutputs(outputs.begin(),outputs.end()); + if(soutputs.size()!=outputs.size()) + throw YACS::Exception("YACSEvalYFX::lockPortsForEvaluation : each elt in outputs must appear once !"); + for(std::list< YACSEvalInputPort * >::const_iterator it=allInputs.begin();it!=allInputs.end();it++) + (*it)->lock(); + return sz; +} + +YACSEvalYFX::~YACSEvalYFX() +{ + delete _pattern; +} diff --git a/src/evalyfx/YACSEvalYFX.hxx b/src/evalyfx/YACSEvalYFX.hxx new file mode 100644 index 000000000..f9ccdd5d9 --- /dev/null +++ b/src/evalyfx/YACSEvalYFX.hxx @@ -0,0 +1,68 @@ +// Copyright (C) 2012-2015 CEA/DEN, EDF R&D +// +// 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, or (at your option) any later version. +// +// 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 +// +// Author : Anthony Geay (EDF R&D) + +#ifndef __YACSEVALYFX_HXX__ +#define __YACSEVALYFX_HXX__ + +#include "YACSEvalYFXExport.hxx" + +#include +#include +#include + +namespace YACS +{ + namespace ENGINE + { + class Proc; + } +} + +class YACSEvalSeqAny; +class YACSEvalSession; +class YACSEvalYFXPattern; +class YACSEvalInputPort; +class YACSEvalOutputPort; +class YACSEvalListOfResources; + +class YACSEvalYFX +{ +public: + YACSEVALYFX_EXPORT static YACSEvalYFX *BuildFromFile(const std::string& xmlOfScheme); + YACSEVALYFX_EXPORT static YACSEvalYFX *BuildFromScheme(YACS::ENGINE::Proc *scheme); + YACSEVALYFX_EXPORT std::list< YACSEvalInputPort * > getFreeInputPorts() const; + YACSEVALYFX_EXPORT std::list< YACSEvalOutputPort * > getFreeOutputPorts() const; + YACSEVALYFX_EXPORT void lockPortsForEvaluation(const std::list< YACSEvalOutputPort * >& outputsOfInterest); + YACSEVALYFX_EXPORT void unlockAll(); + YACSEVALYFX_EXPORT bool isLocked() const; + YACSEVALYFX_EXPORT YACSEvalListOfResources *giveResources(); + YACSEVALYFX_EXPORT bool run(YACSEvalSession *session, int& nbOfBranches); + YACSEVALYFX_EXPORT std::vector getResults() const; + // + YACSEVALYFX_EXPORT YACS::ENGINE::Proc *getUndergroundGeneratedGraph() const; + YACSEVALYFX_EXPORT ~YACSEvalYFX(); +private: + YACSEvalYFX(YACS::ENGINE::Proc *scheme, bool ownScheme); + std::size_t checkPortsForEvaluation(const std::list< YACSEvalOutputPort * >& outputs) const; +private: + YACSEvalYFXPattern *_pattern; +}; + +#endif diff --git a/src/evalyfx/YACSEvalYFXExport.hxx b/src/evalyfx/YACSEvalYFXExport.hxx new file mode 100644 index 000000000..3ef78fd70 --- /dev/null +++ b/src/evalyfx/YACSEvalYFXExport.hxx @@ -0,0 +1,34 @@ +// Copyright (C) 2012-2015 CEA/DEN, EDF R&D +// +// 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, or (at your option) any later version. +// +// 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 +// +// Author : Anthony Geay (EDF R&D) + +#ifndef __YACSEVALYFXEXPORT_HXX__ +#define __YACSEVALYFXEXPORT_HXX__ + +#ifdef WIN32 +# if defined YACSEVALYFX_EXPORTS +# define YACSEVALYFX_EXPORT __declspec( dllexport ) +# else +# define YACSEVALYFX_EXPORT __declspec( dllimport ) +# endif +#else +# define YACSEVALYFX_EXPORT +#endif + +#endif diff --git a/src/evalyfx/YACSEvalYFXPattern.cxx b/src/evalyfx/YACSEvalYFXPattern.cxx new file mode 100644 index 000000000..9ac3852ee --- /dev/null +++ b/src/evalyfx/YACSEvalYFXPattern.cxx @@ -0,0 +1,491 @@ +// Copyright (C) 2012-2015 CEA/DEN, EDF R&D +// +// 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, or (at your option) any later version. +// +// 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 +// +// Author : Anthony Geay (EDF R&D) + +#include "YACSEvalYFXPattern.hxx" +#include "YACSEvalResource.hxx" +#include "YACSEvalSeqAny.hxx" +#include "YACSEvalAutoPtr.hxx" + +#include "ElementaryNode.hxx" +#include "RuntimeSALOME.hxx" +#include "InputPort.hxx" +#include "LinkInfo.hxx" +#include "TypeCode.hxx" +#include "Proc.hxx" + +#include "PythonPorts.hxx" +#include "ForEachLoop.hxx" +#include "PythonNode.hxx" +#include "InlineNode.hxx" +#include "ServiceNode.hxx" + +#include "ResourcesManager.hxx" + +#include +#include +#include + +const char YACSEvalYFXPattern::DFT_PROC_NAME[]="YFX"; + +const char YACSEvalYFXRunOnlyPattern::GATHER_NODE_NAME[]="__gather__"; + +std::list< YACSEvalInputPort *> YACSEvalYFXPattern::getFreeInputPorts() const +{ + std::size_t sz(_inputs.size()); + std::list< YACSEvalInputPort *> ret; + std::list< YACSEvalInputPort >::const_iterator it(_inputs.begin()); + for(std::size_t i=0;i(&(*it))); + return ret; +} + +std::list< YACSEvalOutputPort *> YACSEvalYFXPattern::getFreeOutputPorts() const +{ + std::size_t sz(_outputs.size()); + std::list< YACSEvalOutputPort *> ret; + std::list< YACSEvalOutputPort >::const_iterator it(_outputs.begin()); + for(std::size_t i=0;i(&(*it))); + return ret; +} + +YACSEvalYFXPattern *YACSEvalYFXPattern::FindPatternFrom(YACS::ENGINE::Proc *scheme, bool ownScheme) +{ + if(!scheme) + throw YACS::Exception("YACSEvalYFXPattern::FindPatternFrom : input scheme must be not null !"); + { + YACS::ENGINE::ComposedNode *zeRunNode(0); + bool isMatchingRunOnlyPattern(YACSEvalYFXRunOnlyPattern::IsMatching(scheme,zeRunNode)); + if(isMatchingRunOnlyPattern) + return new YACSEvalYFXRunOnlyPattern(scheme,ownScheme,zeRunNode); + } + throw YACS::Exception("YACSEvalYFXPattern::FindPatternFrom : no pattern found for the input scheme !"); +} + +bool YACSEvalYFXPattern::isAlreadyComputedResources() const +{ + return _res!=0; +} + +void YACSEvalYFXPattern::checkNonAlreadyComputedResources() const +{ + if(isAlreadyComputedResources()) + throw YACS::Exception("checkNonAlreadyComputedResources : instance of computed resources already computed !"); +} + +void YACSEvalYFXPattern::checkAlreadyComputedResources() const +{ + if(!isAlreadyComputedResources()) + throw YACS::Exception("checkAlreadyComputedResources : instance of computed resources not already computed !"); +} + +void YACSEvalYFXPattern::checkLocked() const +{ + if(!isLocked()) + throw YACS::Exception("YACSEvalYFXPattern::checkLocked : Pattern is not locked !"); +} + +void YACSEvalYFXPattern::checkNonLocked() const +{ + if(isLocked()) + throw YACS::Exception("YACSEvalYFXPattern::checkNonLocked : Pattern is locked !"); +} + +void YACSEvalYFXPattern::CheckNodeIsOK(YACS::ENGINE::ComposedNode *node) +{ + /*YACS::ENGINE::LinkInfo info(YACS::ENGINE::LinkInfo::WARN_ONLY_DONT_STOP); + try + { + node->checkConsistency(info); + } + catch(YACS::Exception& e) + { + } + if(info.getNumberOfErrLinks(YACS::ENGINE::E_ALL)!=0) + throw YACS::Exception("YACSEvalYFXPattern::CheckNodeIsOK : found node is not OK !"); + std::list allNodes(node->getRecursiveConstituents()); + for(std::list::const_iterator it=allNodes.begin();it!=allNodes.end();it++) + { + YACS::ENGINE::ServiceNode *node0(dynamic_cast(*it)); + YACS::ENGINE::InlineNode *node1(dynamic_cast(*it)); + if(node0) + { + YACS::ENGINE::Container *cont(node0->getContainer()); + YACS::ENGINE::ComponentInstance *comp(node0->getComponent()); + if(!cont || !comp) + { + std::ostringstream oss; oss << "YACSEvalYFXPattern::CheckNodeIsOK : ServiceNode called \"" << node0->getName() << "\" is not correctly defined !"; + throw YACS::Exception(oss.str()); + } + } + if(node1) + { + YACS::ENGINE::Container *cont(node1->getContainer()); + if(!cont && node1->getExecutionMode()==YACS::ENGINE::InlineNode::REMOTE_STR) + { + std::ostringstream oss; oss << "YACSEvalYFXPattern::CheckNodeIsOK : InlineNode called \"" << node1->getName() << "\" is not correctly defined !"; + throw YACS::Exception(oss.str()); + } + } + }*/ +} + +YACSEvalYFXPattern::YACSEvalYFXPattern(YACS::ENGINE::Proc *scheme, bool ownScheme):_scheme(scheme),_ownScheme(ownScheme),_rm(new ResourcesManager_cpp),_res(0) +{ +} + +YACS::ENGINE::TypeCode *YACSEvalYFXPattern::createSeqTypeCodeFrom(YACS::ENGINE::Proc *scheme, const std::string& zeType) +{ + std::ostringstream oss; oss << "list[" << zeType << "]"; + YACS::ENGINE::TypeCode *tc(scheme->getTypeCode(zeType)); + return scheme->createSequenceTc(oss.str(),oss.str(),tc); +} + +void YACSEvalYFXPattern::setResources(YACSEvalListOfResources *res) +{ + checkNonAlreadyComputedResources(); + if(res!=_res) + delete _res; + _res=res; +} + +void YACSEvalYFXPattern::resetResources() +{ + delete _res; + _res=0; +} + +YACSEvalSeqAny *YACSEvalYFXPattern::BuildValueInPort(YACS::ENGINE::InputPyPort *port) +{ + if(!port) + throw YACS::Exception("YACSEvalYFXPattern::GetValueInPort : null input port !"); + PyObject *obj(port->getPyObj()); + YACS::ENGINE::TypeCode *tc(port->edGetType()); + YACS::ENGINE::TypeCodeSeq *tcc(dynamic_cast(tc)); + if(!tcc) + { + std::ostringstream oss; oss << "YACSEvalYFXPattern::GetValueInPort : internal error for tc of input \"" << port->getName() << "\""; + throw YACS::Exception(oss.str()); + } + const YACS::ENGINE::TypeCode *tcct(tcc->contentType()); + if(!PyList_Check(obj)) + throw YACS::Exception("YACSEvalYFXPattern::GetValueInPort : internal error 2 !"); + std::size_t sz(PyList_Size(obj)); + if(tcct->kind()==YACS::ENGINE::Double) + { + std::vector eltCpp(sz); + for(std::size_t i=0;i elt(new YACSEvalSeqAnyDouble(eltCpp)); + return elt.dettach(); + } + else if(tcct->kind()==YACS::ENGINE::Int) + { + std::vector eltCpp(sz); + for(std::size_t i=0;i elt(new YACSEvalSeqAnyInt(eltCpp)); + return elt.dettach(); + } + else + throw YACS::Exception("YACSEvalYFXPattern::GetValueInPort : not implemented yet for other than Double and Int !"); +} + +void YACSEvalYFXPattern::cleanScheme() +{ + if(_ownScheme) + delete _scheme; + _scheme=0; +} + +YACSEvalYFXPattern::~YACSEvalYFXPattern() +{ + delete _rm; + delete _res; +} + +YACSEvalYFXRunOnlyPattern::YACSEvalYFXRunOnlyPattern(YACS::ENGINE::Proc *scheme, bool ownScheme, YACS::ENGINE::ComposedNode *runNode):YACSEvalYFXPattern(scheme,ownScheme),_runNode(runNode),_commonSz(0),_generatedGraph(0) +{ + if(!_runNode) + throw YACS::Exception("YACSEvalYFXRunOnlyPattern : internal run node must be not null !"); + buildInputPorts(); + buildOutputPorts(); +} + +void YACSEvalYFXRunOnlyPattern::setOutPortsOfInterestForEvaluation(std::size_t commonSize, const std::list& outputsOfInterest) +{ + checkNonLocked(); + _commonSz=commonSize; + _outputsOfInterest=outputsOfInterest; +} + +void YACSEvalYFXRunOnlyPattern::resetOutputsOfInterest() +{ + checkLocked(); + _commonSz=0; + _outputsOfInterest.clear(); +} + +void YACSEvalYFXRunOnlyPattern::generateGraph() +{ + static const char LISTPYOBJ_STR[]="list[pyobj]"; + if(_commonSz==0 || _outputsOfInterest.empty()) + return ; + YACS::ENGINE::RuntimeSALOME::setRuntime(); + YACS::ENGINE::RuntimeSALOME *r(YACS::ENGINE::getSALOMERuntime()); + _generatedGraph=r->createProc(DFT_PROC_NAME); + YACS::ENGINE::TypeCode *pyobjTC(_generatedGraph->createInterfaceTc("python:obj:1.0","pyobj",std::list())); + std::ostringstream oss; oss << "Loop_" << _runNode->getName(); + _generatedGraph->createType(YACSEvalAnyDouble::TYPE_REPR,"double"); + _generatedGraph->createType(YACSEvalAnyInt::TYPE_REPR,"int"); + // + YACS::ENGINE::InlineNode *n0(r->createScriptNode(YACS::ENGINE::PythonNode::KIND,"__initializer__")); + _generatedGraph->edAddChild(n0); + YACS::ENGINE::TypeCode *listPyobjTC(_generatedGraph->createSequenceTc(LISTPYOBJ_STR,LISTPYOBJ_STR,pyobjTC)); + YACS::ENGINE::OutputPort *sender(n0->edAddOutputPort("sender",listPyobjTC)); + std::ostringstream var0; + for(std::list< YACSEvalInputPort >::const_iterator it=_inputs.begin();it!=_inputs.end();it++) + { + std::size_t dummy; + if((*it).hasSequenceOfValuesToEval(dummy)) + { + var0 << (*it).getName() << ","; + YACS::ENGINE::TypeCode *tc(createSeqTypeCodeFrom(_generatedGraph,(*it).getTypeOfData())); + YACS::ENGINE::InputPort *inp(n0->edAddInputPort((*it).getName(),tc)); + YACS::ENGINE::InputPyPort *inpc(dynamic_cast(inp)); + if(!inpc) + throw YACS::Exception("YACSEvalYFXRunOnlyPattern::generateGraph : internal error 1 !"); + (*it).initializeUndergroundWithSeq(inpc); + } + } + std::ostringstream n0Script; n0Script << "sender=zip(" << var0.str() << ")\n"; + n0->setScript(n0Script.str()); + // + YACS::ENGINE::ForEachLoop *n1(r->createForEachLoop(oss.str(),pyobjTC)); + _generatedGraph->edAddChild(n1); + _generatedGraph->edAddCFLink(n0,n1); + _generatedGraph->edAddDFLink(sender,n1->edGetSeqOfSamplesPort()); + YACS::ENGINE::InlineNode *n2(r->createScriptNode(YACS::ENGINE::PythonNode::KIND,GATHER_NODE_NAME)); + _generatedGraph->edAddChild(n2); + _generatedGraph->edAddCFLink(n1,n2); + // + YACS::ENGINE::Bloc *n10(r->createBloc("Bloc")); + n1->edAddChild(n10); + YACS::ENGINE::InlineNode *n100(r->createScriptNode(YACS::ENGINE::PythonNode::KIND,"__dispatch__")); + YACS::ENGINE::Node *n101(_runNode->cloneWithoutCompAndContDeepCpy(0,true)); + n10->edAddChild(n100); + n10->edAddChild(n101); + YACS::ENGINE::InputPort *dispatchIn(n100->edAddInputPort("i0",pyobjTC)); + n10->edAddCFLink(n100,n101); + n1->edAddDFLink(n1->edGetSamplePort(),dispatchIn); + std::ostringstream var1; + for(std::list< YACSEvalInputPort >::const_iterator it=_inputs.begin();it!=_inputs.end();it++) + { + std::size_t dummy; + if((*it).hasSequenceOfValuesToEval(dummy)) + { + var1 << (*it).getName() << ","; + YACS::ENGINE::OutputPort *myOut(n100->edAddOutputPort((*it).getName(),_generatedGraph->getTypeCode((*it).getTypeOfData()))); + std::string tmpPortName(_runNode->getInPortName((*it).getUndergroundPtr())); + YACS::ENGINE::InputPort *myIn(n101->getInputPort(tmpPortName)); + n10->edAddDFLink(myOut,myIn); + } + } + std::ostringstream n100Script; n100Script << var1.str() << "=i0\n"; + n100->setScript(n100Script.str()); + for(std::list< YACSEvalOutputPort * >::const_iterator it=_outputsOfInterest.begin();it!=_outputsOfInterest.end();it++) + { + YACS::ENGINE::TypeCode *tc(createSeqTypeCodeFrom(_generatedGraph,(*it)->getTypeOfData())); + YACS::ENGINE::InputPort *myIn(n2->edAddInputPort((*it)->getName(),tc)); + std::string tmpPortName(_runNode->getOutPortName((*it)->getUndergroundPtr())); + YACS::ENGINE::OutputPort *myOut(n101->getOutputPort(tmpPortName)); + _generatedGraph->edAddDFLink(myOut,myIn); + } + _generatedGraph->updateContainersAndComponents(); +} + +void YACSEvalYFXRunOnlyPattern::resetGeneratedGraph() +{ + delete _generatedGraph; + _generatedGraph=0; + resetResources(); +} + +int YACSEvalYFXRunOnlyPattern::assignNbOfBranches() +{ + checkAlreadyComputedResources(); + if(!_generatedGraph) + throw YACS::Exception("YACSEvalYFXRunOnlyPattern::assignNbOfBranches : the generated graph has not been created !"); + std::list nodes(_generatedGraph->getChildren()); + YACS::ENGINE::ForEachLoop *zeMainNode(0); + for(std::list::const_iterator it=nodes.begin();it!=nodes.end();it++) + { + YACS::ENGINE::ForEachLoop *isZeMainNode(dynamic_cast(*it)); + if(isZeMainNode) + { + if(!zeMainNode) + zeMainNode=isZeMainNode; + else + throw YACS::Exception("YACSEvalYFXRunOnlyPattern::assignNbOfBranches : internal error 1 !"); + } + } + if(!zeMainNode) + throw YACS::Exception("YACSEvalYFXRunOnlyPattern::assignNbOfBranches : internal error 2 !"); + unsigned int nbProcsDeclared(getResourcesInternal()->getNumberOfProcsDeclared()); + nbProcsDeclared=std::max(nbProcsDeclared,4u); + int nbOfBranch(nbProcsDeclared/getResourcesInternal()->getMaxLevelOfParallelism()); + nbOfBranch=std::max(nbOfBranch,1); + YACS::ENGINE::InputPort *zeInputToSet(zeMainNode->edGetNbOfBranchesPort()); + YACS::ENGINE::AnyInputPort *zeInputToSetC(dynamic_cast(zeInputToSet)); + if(!zeInputToSetC) + throw YACS::Exception("YACSEvalYFXRunOnlyPattern::assignNbOfBranches : internal error 3 !"); + YACS::ENGINE::Any *a(YACS::ENGINE::AtomAny::New(nbOfBranch)); + zeInputToSetC->put(a); + zeInputToSetC->exSaveInit(); + a->decrRef(); + return nbOfBranch; +} + +bool YACSEvalYFXRunOnlyPattern::isLocked() const +{ + return _generatedGraph!=0; +} + +YACSEvalListOfResources *YACSEvalYFXRunOnlyPattern::giveResources() +{ + checkLocked(); + if(!isAlreadyComputedResources()) + { + YACS::ENGINE::DeploymentTree dt(_runNode->getDeploymentTree()); + YACSEvalListOfResources *res(new YACSEvalListOfResources(_runNode->getMaxLevelOfParallelism(),getCatalogInAppli(),dt)); + setResources(res); + } + return getResourcesInternal(); +} + +YACS::ENGINE::Proc *YACSEvalYFXRunOnlyPattern::getUndergroundGeneratedGraph() const +{ + return _generatedGraph; +} + +std::vector YACSEvalYFXRunOnlyPattern::getResults() const +{ + if(_generatedGraph->getState()!=YACS::DONE) + throw YACS::Exception("YACSEvalYFXRunOnlyPattern::getResults : the execution did not finished correctly ! getResults should not be called !"); + std::vector ret(_outputsOfInterest.size()); + YACS::ENGINE::Node *node(_generatedGraph->getChildByName(GATHER_NODE_NAME)); + YACS::ENGINE::PythonNode *nodeC(dynamic_cast(node)); + if(!nodeC) + throw YACS::Exception("YACSEvalYFXRunOnlyPattern::getResults : internal error !"); + std::size_t ii(0); + for(std::list< YACSEvalOutputPort * >::const_iterator it=_outputsOfInterest.begin();it!=_outputsOfInterest.end();it++,ii++) + { + YACS::ENGINE::InPort *input(nodeC->getInPort((*it)->getName())); + YACS::ENGINE::InputPyPort *inputC(dynamic_cast(input)); + if(!inputC) + { + std::ostringstream oss; oss << "YACSEvalYFXRunOnlyPattern::getResults : internal error for input \"" << (*it)->getName() << "\""; + throw YACS::Exception(oss.str()); + } + ret[ii]=BuildValueInPort(inputC); + } + return ret; +} + +bool YACSEvalYFXRunOnlyPattern::IsMatching(YACS::ENGINE::Proc *scheme, YACS::ENGINE::ComposedNode *& runNode) +{ + std::list nodes(scheme->getChildren()); + if(nodes.empty()) + return false; + bool areAllElementary(true); + for(std::list::const_iterator it=nodes.begin();it!=nodes.end() && areAllElementary;it++) + if(!dynamic_cast(*it)) + areAllElementary=false; + if(areAllElementary) + { + if(scheme) + CheckNodeIsOK(scheme); + runNode=scheme; + return true; + } + if(nodes.size()!=1) + return false; + YACS::ENGINE::ComposedNode *candidate(dynamic_cast(nodes.front())); + runNode=candidate; + if(candidate) + CheckNodeIsOK(candidate); + return candidate!=0; +} + +void YACSEvalYFXRunOnlyPattern::buildInputPorts() +{ + _inputs.clear(); + std::list< YACS::ENGINE::InputPort *> allInputPorts(_runNode->getSetOfInputPort()); + std::vector allNames; + for(std::list< YACS::ENGINE::InputPort *>::const_iterator it=allInputPorts.begin();it!=allInputPorts.end();it++) + { + YACS::ENGINE::InputPort *elt(*it); + if(!elt) + throw YACS::Exception("YACSEvalYFXRunOnlyPattern::buildInputPorts : presence of null input !"); + std::set bls(elt->edSetOutPort()); + if(bls.empty()) + { + std::string inpName(elt->getName()); + if(inpName.empty()) + throw YACS::Exception("YACSEvalYFXRunOnlyPattern::buildInputPorts : an input has empty name ! Should not !"); + _inputs.push_back(YACSEvalInputPort(elt)); + if(std::find(allNames.begin(),allNames.end(),inpName)!=allNames.end()) + { + std::ostringstream oss; oss << "YACSEvalYFXRunOnlyPattern::buildInputPorts : input name \"" << inpName << "\" appears more than once !"; + throw YACS::Exception(oss.str()); + } + allNames.push_back(inpName); + } + } +} + +void YACSEvalYFXRunOnlyPattern::buildOutputPorts() +{ + _outputs.clear(); + std::list< YACS::ENGINE::OutputPort *> allOutputPorts(_runNode->getSetOfOutputPort()); + std::vector allNames; + for(std::list< YACS::ENGINE::OutputPort *>::const_iterator it=allOutputPorts.begin();it!=allOutputPorts.end();it++) + { + YACS::ENGINE::OutputPort *elt(*it); + if(!elt) + throw YACS::Exception("YACSEvalYFXRunOnlyPattern::buildOutputPorts : presence of null output !"); + std::string outpName(elt->getName()); + if(outpName.empty()) + throw YACS::Exception("YACSEvalYFXRunOnlyPattern::buildOutputPorts : an output has empty name ! Should not !"); + if(std::find(allNames.begin(),allNames.end(),outpName)!=allNames.end()) + { + std::ostringstream oss; oss << "YACSEvalYFXRunOnlyPattern::buildOutputPorts : output name \"" << outpName << "\" appears more than once !"; + throw YACS::Exception(oss.str()); + } + _outputs.push_back(YACSEvalOutputPort(*it)); + } +} + diff --git a/src/evalyfx/YACSEvalYFXPattern.hxx b/src/evalyfx/YACSEvalYFXPattern.hxx new file mode 100644 index 000000000..063dae7cd --- /dev/null +++ b/src/evalyfx/YACSEvalYFXPattern.hxx @@ -0,0 +1,113 @@ +// Copyright (C) 2012-2015 CEA/DEN, EDF R&D +// +// 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, or (at your option) any later version. +// +// 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 +// +// Author : Anthony Geay (EDF R&D) + +#ifndef __YACSEVALYFXPATTERN_HXX__ +#define __YACSEVALYFXPATTERN_HXX__ + +#include "YACSEvalPort.hxx" + +#include +#include + +namespace YACS +{ + namespace ENGINE + { + class Proc; + class TypeCode; + class ComposedNode; + class InputPyPort; + } +} + +class YACSEvalListOfResources; +class ResourcesManager_cpp; + +class YACSEvalYFXPattern +{ +public: + virtual ~YACSEvalYFXPattern(); + std::list< YACSEvalInputPort *> getFreeInputPorts() const; + std::list< YACSEvalOutputPort *> getFreeOutputPorts() const; + static YACSEvalYFXPattern *FindPatternFrom(YACS::ENGINE::Proc *scheme, bool ownScheme); + bool isAlreadyComputedResources() const; + void checkNonAlreadyComputedResources() const; + void checkAlreadyComputedResources() const; + void checkLocked() const; + void checkNonLocked() const; + static void CheckNodeIsOK(YACS::ENGINE::ComposedNode *node); + virtual void setOutPortsOfInterestForEvaluation(std::size_t commonSize, const std::list& outputs) = 0; + virtual void resetOutputsOfInterest() = 0; + virtual void generateGraph() = 0; + virtual void resetGeneratedGraph() = 0; + virtual int assignNbOfBranches() = 0; + virtual bool isLocked() const = 0; + virtual YACSEvalListOfResources *giveResources() = 0; + virtual YACS::ENGINE::Proc *getUndergroundGeneratedGraph() const = 0; + virtual std::vector getResults() const = 0; +public: + static const char DFT_PROC_NAME[]; +protected: + YACSEvalYFXPattern(YACS::ENGINE::Proc *scheme, bool ownScheme); + YACS::ENGINE::TypeCode *createSeqTypeCodeFrom(YACS::ENGINE::Proc *scheme, const std::string& zeType); + void setResources(YACSEvalListOfResources *res); + void resetResources(); + YACSEvalListOfResources *getResourcesInternal() const { return _res; } + ResourcesManager_cpp *getCatalogInAppli() const { return _rm; } + static YACSEvalSeqAny *BuildValueInPort(YACS::ENGINE::InputPyPort *port); +private: + void cleanScheme(); +private: + bool _ownScheme; + YACS::ENGINE::Proc *_scheme; + ResourcesManager_cpp *_rm; + YACSEvalListOfResources *_res; +protected: + std::list< YACSEvalInputPort > _inputs; + std::list< YACSEvalOutputPort > _outputs; +}; + +class YACSEvalYFXRunOnlyPattern : public YACSEvalYFXPattern +{ +public: + YACSEvalYFXRunOnlyPattern(YACS::ENGINE::Proc *scheme, bool ownScheme, YACS::ENGINE::ComposedNode *runNode); + void setOutPortsOfInterestForEvaluation(std::size_t commonSize, const std::list& outputsOfInterest); + void resetOutputsOfInterest(); + void generateGraph(); + void resetGeneratedGraph(); + int assignNbOfBranches(); + bool isLocked() const; + YACSEvalListOfResources *giveResources(); + YACS::ENGINE::Proc *getUndergroundGeneratedGraph() const; + std::vector getResults() const; + static bool IsMatching(YACS::ENGINE::Proc *scheme, YACS::ENGINE::ComposedNode *& runNode); +public: + static const char GATHER_NODE_NAME[]; +private: + void buildInputPorts(); + void buildOutputPorts(); +private: + YACS::ENGINE::ComposedNode *_runNode; + std::size_t _commonSz; + std::list _outputsOfInterest; + YACS::ENGINE::Proc *_generatedGraph; +}; + +#endif diff --git a/src/evalyfx_swig/CMakeLists.txt b/src/evalyfx_swig/CMakeLists.txt new file mode 100644 index 000000000..79522c7ab --- /dev/null +++ b/src/evalyfx_swig/CMakeLists.txt @@ -0,0 +1,63 @@ +# Copyright (C) 2012-2015 CEA/DEN, EDF R&D +# +# 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, or (at your option) any later version. +# +# 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(${SWIG_USE_FILE}) + +# additional include directories +INCLUDE_DIRECTORIES( + ${PROJECT_SOURCE_DIR}/src/bases + ${PROJECT_SOURCE_DIR}/src/engine + ${PROJECT_SOURCE_DIR}/src/engine_swig + ${PROJECT_SOURCE_DIR}/src/yacsloader + ${PROJECT_SOURCE_DIR}/src/yacsloader_swig + ${PROJECT_SOURCE_DIR}/src/evalyfx + ${OMNIORB_INCLUDE_DIR} + ${PYTHON_INCLUDE_DIRS} +) + +# swig flags +SET_SOURCE_FILES_PROPERTIES(evalyfx.i PROPERTIES CPLUSPLUS ON SWIG_DEFINITIONS "-shadow") + +SET_PROPERTY(SOURCE evalyfx.i PROPERTY SWIG_FLAGS "-noexcept" "-DYACS_PTHREAD") + +# additional preprocessor / compiler flags +ADD_DEFINITIONS( + ${PYTHON_DEFINITIONS} + ${OMNIORB_DEFINITIONS} + ) + +# libraries to link to +SET(_link_LIBRARIES + YACSevalYFX + ${PYTHON_LIBRARIES} + ${OMNIORB_LIBRARIES} + ) + +SET(_swig_SCRIPTS ${CMAKE_CURRENT_BINARY_DIR}/evalyfx.py) + +SWIG_ADD_MODULE(evalyfx python evalyfx.i) + +SWIG_LINK_LIBRARIES(evalyfx ${_link_LIBRARIES}) +IF(WIN32) + SET_TARGET_PROPERTIES(_evalyfx PROPERTIES DEBUG_OUTPUT_NAME _evalyfx_d) +ENDIF(WIN32) + +INSTALL(TARGETS ${SWIG_MODULE_evalyfx_REAL_NAME} DESTINATION ${SALOME_INSTALL_PYTHON}) + +SALOME_INSTALL_SCRIPTS("${_swig_SCRIPTS}" ${SALOME_INSTALL_PYTHON}) diff --git a/src/evalyfx_swig/evalyfx.i b/src/evalyfx_swig/evalyfx.i new file mode 100644 index 000000000..6d9ee76e2 --- /dev/null +++ b/src/evalyfx_swig/evalyfx.i @@ -0,0 +1,431 @@ +// Copyright (C) 2012-2015 CEA/DEN, EDF R&D +// +// 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, or (at your option) any later version. +// +// 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 +// +// Author : Anthony Geay (EDF R&D) + +%define EVALYFXDOCSTRING +"Module to evaluate Y=f(X) easily." +%enddef + +%module(docstring=EVALYFXDOCSTRING) evalyfx + +%feature("autodoc", "1"); + +%include "engtypemaps.i" + +%{ +#include "YACSEvalYFX.hxx" +#include "YACSEvalPort.hxx" +#include "YACSEvalSeqAny.hxx" +#include "YACSEvalResource.hxx" +#include "YACSEvalSession.hxx" + +static void convertPyToIntArr(PyObject *pyLi, std::vector& arr) +{ + if(PyList_Check(pyLi)) + { + int size=PyList_Size(pyLi); + arr.resize(size); + for(int i=0;i& arr) +{ + if(PyList_Check(pyLi)) + { + int size=PyList_Size(pyLi); + arr.resize(size); + for(int i=0;i +{ + std::list::const_iterator it; + $result = PyList_New($1.size()); + int i = 0; + for (it = $1.begin(); it != $1.end(); ++it, ++i) + { + PyList_SetItem($result,i,SWIG_NewPointerObj(SWIG_as_voidptr(*it),SWIGTYPE_p_YACSEvalInputPort, 0 | 0 )); + } +} + +%typemap(out) std::list +{ + std::list::const_iterator it; + $result = PyList_New($1.size()); + int i = 0; + for (it = $1.begin(); it != $1.end(); ++it, ++i) + { + PyList_SetItem($result,i,SWIG_NewPointerObj(SWIG_as_voidptr(*it),SWIGTYPE_p_YACSEvalOutputPort, 0 | 0 )); + } +} + +%typemap(out) YACSEvalAny * +{ + $result = 0; + YACSEvalAnyDouble *val0(dynamic_cast($1)); + YACSEvalAnyInt *val1(dynamic_cast($1)); + if(val0) + { + $result = PyFloat_FromDouble(val0->toDouble()); + delete $1; + } + else if(val1) + { + $result = PyInt_FromLong(val1->toInt()); + delete $1; + } + else + { + delete $1; + throw YACS::Exception("PyWrap of YACSEvalInputPort::getDefaultValueDefined : unrecognized type !"); + } +} + +%typemap(in) const std::list< YACSEvalOutputPort * >& +{ + +} + +class YACSEvalPort +{ +public: + virtual std::string getTypeOfData() const; +private: + YACSEvalPort(); +}; + +class YACSEvalInputPort : public YACSEvalPort +{ +public: + std::string getName() const; + bool hasDefaultValueDefined() const; + YACSEvalAny *getDefaultValueDefined() const; + %extend + { + void setDefaultValue(PyObject *parameter) + { + if(parameter==Py_None) + self->setDefaultValue(0); + else if(PyFloat_Check(parameter)) + { + YACSEvalAnyDouble tmp(PyFloat_AsDouble(parameter)); + self->setDefaultValue(&tmp); + } + else if(PyInt_Check(parameter)) + { + YACSEvalAnyInt tmp((int)PyInt_AsLong(parameter)); + self->setDefaultValue(&tmp); + } + else + throw YACS::Exception("PyWrap of YACSEvalInputPort::setParameter : unrecognized type !"); + } + + void setSequenceOfValuesToEval(PyObject *vals) + { + if(!PyList_Check(vals)) + { + PyErr_SetString(PyExc_TypeError,"not a list"); + return ; + } + int size(PyList_Size(vals)); + YACSEvalSeqAny *valsCpp(0); + if(size>0) + { + PyObject *elt0(PyList_GetItem(vals,0)); + if(PyFloat_Check(elt0)) + { + std::vector zeVals; + convertPyToDblArr(vals,zeVals); + valsCpp=new YACSEvalSeqAnyDouble(zeVals); + } + else if(PyInt_Check(elt0)) + { + std::vector zeVals; + convertPyToIntArr(vals,zeVals); + valsCpp=new YACSEvalSeqAnyInt(zeVals); + } + else + throw YACS::Exception("YACSEvalInputPort::setSequenceOfValuesToEval : only list[float] and list[int] actualy supported !"); + } + else + valsCpp=YACSEvalSeqAny::BuildEmptyFromType(self->getTypeOfData()); + self->setSequenceOfValuesToEval(valsCpp); + delete valsCpp; + } + + PyObject *hasSequenceOfValuesToEval() const + { + std::size_t ret1; + bool ret0(self->hasSequenceOfValuesToEval(ret1)); + PyObject *ret(PyTuple_New(2)); + PyObject *ret0Py=ret0?Py_True:Py_False; + Py_XINCREF(ret0Py); + PyTuple_SetItem(ret,0,ret0Py); + PyTuple_SetItem(ret,1,PyInt_FromLong(ret1)); + return ret; + } + } +private: + YACSEvalInputPort(); +}; + +class YACSEvalOutputPort : public YACSEvalPort +{ +public: + std::string getName() const; +private: + YACSEvalOutputPort(); +}; + +class YACSEvalVirtualYACSContainer +{ +public: + std::string getChosenMachine() const; + void setWantedMachine(const std::string& machine); + std::vector listOfPropertyKeys() const; + std::string getValueOfKey(const char *key) const; + void setProperty(const std::string& key, const std::string &value); +private: + YACSEvalVirtualYACSContainer(); +}; + +class YACSEvalResource +{ +public: + std::vector getAllChosenMachines() const; + std::vector getAllFittingMachines() const; + void setWantedMachine(const std::string& machine); + std::size_t size() const; + YACSEvalVirtualYACSContainer *at(std::size_t i) const; + %extend + { + std::size_t __len__() const + { + return self->size(); + } + YACSEvalVirtualYACSContainer *__getitem__(std::size_t i) const + { + return self->at(i); + } + } +private: + YACSEvalResource(); +}; + +class YACSEvalListOfResources +{ +public: + std::vector getAllChosenMachines() const; + std::vector getAllFittingMachines() const; + void setWantedMachine(const std::string& machine); + std::size_t size() const; + bool isInteractive() const; + YACSEvalResource *at(std::size_t i) const; + unsigned int getNumberOfProcsDeclared() const; + %extend + { + std::size_t __len__() const + { + return self->size(); + } + YACSEvalResource *__getitem__(std::size_t i) const + { + return self->at(i); + } + } +private: + YACSEvalListOfResources(); +}; + +class YACSEvalSession +{ +public: + YACSEvalSession(); + ~YACSEvalSession(); + void launch(); + bool isLaunched() const; + void checkLaunched() const; + int getPort() const; + std::string getCorbaConfigFileName() const; +}; + +class YACSEvalYFX +{ +public: + static YACSEvalYFX *BuildFromFile(const std::string& xmlOfScheme); + static YACSEvalYFX *BuildFromScheme(YACS::ENGINE::Proc *schema); + std::list getFreeInputPorts() const; + std::list getFreeOutputPorts() const; + void unlockAll(); + bool isLocked() const; + YACS::ENGINE::Proc *getUndergroundGeneratedGraph() const; + YACSEvalListOfResources *giveResources(); + %extend + { + void lockPortsForEvaluation(PyObject *outputsOfInterest) + { + std::list outputsOfInterestCpp; + if(PyList_Check(outputsOfInterest)) + { + int size(PyList_Size(outputsOfInterest)); + for(int i=0;i(argp)); + } + } + else + { + PyErr_SetString(PyExc_TypeError,"not a list"); + return ; + } + self->lockPortsForEvaluation(outputsOfInterestCpp); + } + + PyObject *getResults() const + { + std::vector retCpp(self->getResults()); + std::size_t sz(retCpp.size()); + PyObject *ret(PyList_New(sz)); + for(std::size_t i=0;i(elt)); + YACSEvalSeqAnyInt *elt2(dynamic_cast(elt)); + if(elt1) + { + std::vector *zeArr(elt1->getInternal()); + std::size_t sz2(zeArr->size()); + PyObject *ret2(PyList_New(sz2)); + for(std::size_t i2=0;i2 *zeArr(elt2->getInternal()); + std::size_t sz2(zeArr->size()); + PyObject *ret2(PyList_New(sz2)); + for(std::size_t i2=0;i2run(session,ret1)); + PyObject *ret(PyTuple_New(2)); + PyObject *ret0Py(ret0?Py_True:Py_False); + Py_XINCREF(ret0Py); + PyTuple_SetItem(ret,0,ret0Py); + PyTuple_SetItem(ret,1,PyInt_FromLong(ret1)); + return ret; + } + } +private: + YACSEvalYFX(); +}; diff --git a/src/evalyfx_swig/test.py b/src/evalyfx_swig/test.py new file mode 100644 index 000000000..fc42faad5 --- /dev/null +++ b/src/evalyfx_swig/test.py @@ -0,0 +1,97 @@ +def buildScheme(fname): + import SALOMERuntime + import loader + SALOMERuntime.RuntimeSALOME.setRuntime() + r=SALOMERuntime.getSALOMERuntime() + p=r.createProc("run") + td=p.createType("double","double") + # + cont=p.createContainer("zeCont","Salome") + # + n0=r.createFuncNode("Salome","node0") + p.edAddChild(n0) + n0.setFname("func0") + n0.setContainer(cont) + n0.setScript("""def func0(a,b): + return a*b +""") + n0.setExecutionMode("remote") + a=n0.edAddInputPort("a",td) + b=n0.edAddInputPort("b",td) ; b.edInitPy(1.3) + c=n0.edAddOutputPort("c",td) + # + n1=r.createFuncNode("Salome","node1") + p.edAddChild(n1) + n1.setFname("func1") + n1.setContainer(cont) + n1.setScript("""def func1(a,b): + return a+b,3*(a+b) +""") + n1.setExecutionMode("remote") + d=n1.edAddInputPort("d",td) + e=n1.edAddInputPort("e",td) ; e.edInitPy(2.5) # agy : useless but for test + f=n1.edAddOutputPort("f",td) + g=n1.edAddOutputPort("g",td) + # + p.edAddCFLink(n0,n1) + p.edAddLink(c,d) + # + p.saveSchema(fname) + +fileName="test0.xml" +import evalyfx +session=evalyfx.YACSEvalSession() +session.launch() +buildScheme(fileName) +efx=evalyfx.YACSEvalYFX.BuildFromFile(fileName) +inps=efx.getFreeInputPorts() +# +inps[0].setDefaultValue(3.4) +# +inps[0].setDefaultValue(None) +inps[2].setDefaultValue(2.7) +inps[2].setDefaultValue(None) +# +outps=efx.getFreeOutputPorts() +# prepare for execution +inps[0].setDefaultValue(1.1) +inps[1].setSequenceOfValuesToEval([10.1,10.2,10.3]) +a,b=inps[2].hasSequenceOfValuesToEval() +inps[2].setSequenceOfValuesToEval([20.1,20.2,30.3,40.4]) +a,b=inps[2].hasSequenceOfValuesToEval() +inps[2].setSequenceOfValuesToEval([20.1,20.2,30.3]) +efx.lockPortsForEvaluation([outps[0],outps[2]]) +# +g=efx.getUndergroundGeneratedGraph() +g.saveSchema("toto.xml") +rss=efx.giveResources() +rss[0][0].setWantedMachine("localhost") +a,b=efx.run(session) +assert(a) +assert(b==4) +assert(efx.getResults()==[[11.110000000000001, 11.22, 11.330000000000002], [93.63, 94.26, 124.89000000000001]]) +#import loader +#import pilot +#l=loader.YACSLoader() +#p=l.load("/home/H87074/aaaaaaa.xml") +#ex=pilot.ExecutorSwig() +#ex.RunW(efx.getUndergroundGeneratedGraph()) +# +""" +import pilot +import SALOMERuntime +import loader +import os,sys +zePath=os.path.join(os.environ["KERNEL_ROOT_DIR"],"bin","salome","appliskel") +sys.path.append(zePath) +import salome_test_session +port=salome_test_session.startSession(shutdownAtExit=False) +omniorb_cfg=os.environ["OMNIORB_CONFIG"] +SALOMERuntime.RuntimeSALOME.setRuntime() +r=SALOMERuntime.getSALOMERuntime() +l=loader.YACSLoader() +p=l.load("/home/H87074/aaaaaaa.xml") +ex=pilot.ExecutorSwig() +ex.RunW(p) +salome_test_session.terminateSession(port) +""" diff --git a/src/evalyfx_swig/test0.xml b/src/evalyfx_swig/test0.xml new file mode 100644 index 000000000..e23ae1c98 --- /dev/null +++ b/src/evalyfx_swig/test0.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + node0 node1 + + node0 c + node1 d + + + node0b + 1.3 + + + node1e + 2.5 + + diff --git a/src/evalyfx_swig/testEvalYFX.py b/src/evalyfx_swig/testEvalYFX.py new file mode 100644 index 000000000..119065f3d --- /dev/null +++ b/src/evalyfx_swig/testEvalYFX.py @@ -0,0 +1,94 @@ +import unittest + +class TestEvalYFX(unittest.TestCase): + def test0(self): + fileName="test0.xml" + self.__buildScheme(fileName) + import evalyfx + efx=evalyfx.YACSEvalYFX.BuildFromFile(fileName) + inps=efx.getFreeInputPorts() + self.assertEqual([elt.getName() for elt in inps],['a','b','e']) + self.assertEqual([elt.hasDefaultValueDefined() for elt in inps],[False,True,True]) + self.assertAlmostEqual(inps[1].getDefaultValueDefined(),1.3,12) + self.assertAlmostEqual(inps[2].getDefaultValueDefined(),2.5,12) + # + inps[0].setDefaultValue(3.4) + self.assertEqual([elt.hasDefaultValueDefined() for elt in inps],[True,True,True]) + self.assertAlmostEqual(inps[0].getDefaultValueDefined(),3.4,12) + # + inps[0].setDefaultValue(None) + self.assertEqual([elt.hasDefaultValueDefined() for elt in inps],[False,True,True]) + inps[2].setDefaultValue(2.7) + self.assertAlmostEqual(inps[2].getDefaultValueDefined(),2.7,12) + inps[2].setDefaultValue(None) + self.assertEqual([elt.hasDefaultValueDefined() for elt in inps],[False,True,False]) + self.assertRaises(ValueError,inps[0].getDefaultValueDefined) + self.assertAlmostEqual(inps[1].getDefaultValueDefined(),1.3,12) + self.assertRaises(ValueError,inps[2].getDefaultValueDefined) + # + outps=efx.getFreeOutputPorts() + self.assertEqual([elt.getName() for elt in outps],['c','f','g']) + # prepare for execution + inps[0].setDefaultValue(1.1) + inps[1].setSequenceOfValuesToEval([10.1,10.2,10.3]) + self.assertRaises(ValueError,efx.lockPortsForEvaluation,[outps[0],outps[2]]) # because e is not set + a,b=inps[2].hasSequenceOfValuesToEval() + self.assertTrue(not a) + inps[2].setSequenceOfValuesToEval([20.1,20.2,30.3,40.4]) + a,b=inps[2].hasSequenceOfValuesToEval() + self.assertTrue(a) + self.assertEqual(b,4) + self.assertRaises(ValueError,efx.lockPortsForEvaluation,[outps[0],outps[2]]) # because size of vals of e is not equal to size of vals of a + inps[2].setSequenceOfValuesToEval([20.1,20.2,30.3]) + efx.lockPortsForEvaluation([outps[0],outps[2]]) + # + g=efx.getUndergroundGeneratedGraph() + g.saveSchema("toto.xml") + # + + pass + + def __buildScheme(self,fname): + import SALOMERuntime + import loader + SALOMERuntime.RuntimeSALOME.setRuntime() + r=SALOMERuntime.getSALOMERuntime() + p=r.createProc("run") + td=p.createType("double","double") + # + cont=p.createContainer("zeCont","Salome") + # + n0=r.createFuncNode("Salome","node0") + p.edAddChild(n0) + n0.setFname("func0") + n0.setContainer(cont) + n0.setScript("""def func0(a,b): + return a*b +""") + n0.setExecutionMode("remote") + a=n0.edAddInputPort("a",td) + b=n0.edAddInputPort("b",td) ; b.edInitPy(1.3) + c=n0.edAddOutputPort("c",td) + # + n1=r.createFuncNode("Salome","node1") + p.edAddChild(n1) + n1.setFname("func1") + n1.setContainer(cont) + n1.setScript("""def func1(a,b): + return a+b,3*(a+b) +""") + n1.setExecutionMode("remote") + d=n1.edAddInputPort("d",td) + e=n1.edAddInputPort("e",td) ; e.edInitPy(2.5) # agy : useless but for test + f=n1.edAddOutputPort("f",td) + g=n1.edAddOutputPort("g",td) + # + p.edAddCFLink(n0,n1) + p.edAddLink(c,d) + # + p.saveSchema(fname) + pass + pass + +if __name__ == '__main__': + unittest.main() diff --git a/src/runtime/CORBAPorts.hxx b/src/runtime/CORBAPorts.hxx index de5479026..162ec0a0b 100644 --- a/src/runtime/CORBAPorts.hxx +++ b/src/runtime/CORBAPorts.hxx @@ -27,6 +27,8 @@ #include "OutputPort.hxx" #include "Mutex.hxx" +#include + #include namespace YACS -- 2.30.2