]> SALOME platform Git repositories - modules/yacs.git/commitdiff
Salome HOME
Merge multi-study removal branch.
authorrnv <rnv@opencascade.com>
Tue, 13 Jun 2017 10:01:34 +0000 (13:01 +0300)
committerrnv <rnv@opencascade.com>
Tue, 13 Jun 2017 10:01:34 +0000 (13:01 +0300)
126 files changed:
CMakeLists.txt
SalomeYACSConfig.cmake.in [changed mode: 0644->0755]
doc/conf.py.in
doc/exemples/exemple10/FreeFemComponent.py
doc/salome.rst
doc/sources/footer.html
src/CMakeLists.txt
src/CTestTestfileInstall.cmake
src/bases/AutoRefCnt.hxx
src/bases/DynLibLoaderGNU.cxx
src/bases/chrono.cxx
src/bases/chrono.hxx
src/engine/AbstractPoint.hxx
src/engine/BagPoint.cxx
src/engine/BagPoint.hxx
src/engine/Bloc.cxx
src/engine/Bloc.hxx
src/engine/BlocPoint.cxx
src/engine/BlocPoint.hxx
src/engine/Bloc_impl.cxx [new file with mode: 0644]
src/engine/CMakeLists.txt
src/engine/ComposedNode.cxx
src/engine/Container.hxx
src/engine/Dispatcher.cxx
src/engine/Dispatcher.hxx
src/engine/DynParaLoop.cxx
src/engine/DynParaLoop.hxx
src/engine/ElementaryNode.hxx
src/engine/ElementaryPoint.cxx
src/engine/ElementaryPoint.hxx
src/engine/Executor.cxx
src/engine/ForEachLoop.cxx
src/engine/ForEachLoop.hxx
src/engine/ForkBlocPoint.cxx
src/engine/ForkBlocPoint.hxx
src/engine/HomogeneousPoolContainer.hxx
src/engine/InlineNode.cxx
src/engine/InlineNode.hxx
src/engine/LinkedBlocPoint.cxx
src/engine/LinkedBlocPoint.hxx
src/engine/Loop.cxx
src/engine/Loop.hxx
src/engine/Node.cxx
src/engine/Node.hxx
src/engine/OutPort.hxx
src/engine/OutputDataStreamPort.hxx
src/engine/OutputPort.hxx
src/engine/PlayGround.cxx [new file with mode: 0644]
src/engine/PlayGround.hxx [new file with mode: 0644]
src/engine/Proc.hxx
src/engine/RefCounter.cxx
src/engine/RefCounter.hxx
src/engine/Runtime.hxx
src/engine/SetOfPoints.cxx
src/engine/SetOfPoints.hxx
src/engine/Switch.cxx
src/engine/Switch.hxx
src/engine/Test/RuntimeForEngineIntegrationTest.cxx
src/engine/Test/RuntimeForEngineIntegrationTest.hxx
src/engine/Test/RuntimeForEngineTest.cxx
src/engine/Test/RuntimeForEngineTest.hxx
src/engine/TypeCode.cxx
src/engine/TypeCode.hxx
src/engine/VisitorSaveSchema.cxx
src/engine_swig/CMakeLists.txt
src/engine_swig/CTestTestfileInstall.cmake [new file with mode: 0644]
src/engine_swig/PlayGround.i [new file with mode: 0644]
src/engine_swig/pilot.i
src/engine_swig/testPlayGround0.py [new file with mode: 0644]
src/evalyfx/YACSEvalSeqAny.cxx
src/evalyfx/YACSEvalSeqAny.hxx
src/evalyfx/YACSEvalSession.cxx
src/evalyfx/YACSEvalYFXPattern.cxx
src/evalyfx_swig/CMakeLists.txt
src/pmml/Test/BasicMainTest.hxx
src/pmml/doc/doxygen/static/footer.html
src/pmml/pmml_swig/CMakeLists.txt
src/py2yacs/CMakeLists.txt [new file with mode: 0644]
src/py2yacs/Test/CMakeLists.txt [new file with mode: 0644]
src/py2yacs/Test/CTestTestfileInstall.cmake [new file with mode: 0644]
src/py2yacs/Test/Py2yacsTest.cxx [new file with mode: 0644]
src/py2yacs/Test/Py2yacsTest.hxx [new file with mode: 0644]
src/py2yacs/Test/TestPy2yacs.cxx [new file with mode: 0644]
src/py2yacs/Test/bad_parsers.py [new file with mode: 0644]
src/py2yacs/Test/err_py2yacs_invalid.py [new file with mode: 0644]
src/py2yacs/Test/test_py2yacs.cxx [new file with mode: 0644]
src/py2yacs/py2yacs.cxx [new file with mode: 0644]
src/py2yacs/py2yacs.hxx [new file with mode: 0644]
src/py2yacs/py2yacs.py [new file with mode: 0644]
src/runtime/CMakeLists.txt
src/runtime/CppContainer.cxx
src/runtime/DistributedPythonNode.cxx
src/runtime/PythonNode.cxx
src/runtime/RuntimeSALOME.cxx
src/runtime/RuntimeSALOME.hxx
src/runtime/SalomeContainerHelper.cxx
src/runtime/SalomeContainerHelper.hxx
src/runtime/SalomeContainerTools.cxx
src/runtime/SalomeContainerTools.hxx
src/runtime/SalomeHPContainer.cxx
src/runtime/SalomeHPContainer.hxx
src/runtime/SalomeHPContainerTools.cxx
src/runtime/SalomeHPContainerTools.hxx
src/runtime/TypeConversions.hxx
src/runtime/VisitorSalomeSaveState.cxx [new file with mode: 0644]
src/runtime/VisitorSalomeSaveState.hxx [new file with mode: 0644]
src/runtime/XMLNode.cxx
src/runtime_swig/CMakeLists.txt
src/runtime_swig/SALOMERuntime.i
src/salomegui_swig/CMakeLists.txt
src/yacsloader/CMakeLists.txt
src/yacsloader/ExampleOfObserversPluginForDriver.cxx [new file with mode: 0644]
src/yacsloader/LoadState.cxx
src/yacsloader/LoadState.hxx
src/yacsloader/driver.cxx
src/yacsloader/loopParsers.hxx
src/yacsloader/pmml/BasicMainTest.hxx
src/yacsloader_swig/CMakeLists.txt
src/yacsloader_swig/Test/CMakeLists.txt
src/yacsloader_swig/Test/CTestTestfileInstall.cmake
src/yacsloader_swig/Test/StdAloneYacsLoaderTest1.py
src/yacsloader_swig/Test/YacsLoaderInSessionTest.sh.in
src/yacsloader_swig/Test/testHPDecorator.py [new file with mode: 0644]
src/yacsloader_swig/Test/testResume.py
src/yacsloader_swig/Test/testSaveLoadRun.py
src/yacsorb/YACS.py

index 71d5eee0be72765693674e946f43000e16522f3d..f23f76faf749d12fa1e8a571e4da5a800d5b41b1 100644 (file)
@@ -33,7 +33,7 @@ ENDIF(WIN32)
 STRING(TOUPPER ${PROJECT_NAME} PROJECT_NAME_UC)
 
 SET(${PROJECT_NAME_UC}_MAJOR_VERSION 8)
-SET(${PROJECT_NAME_UC}_MINOR_VERSION 1)
+SET(${PROJECT_NAME_UC}_MINOR_VERSION 3)
 SET(${PROJECT_NAME_UC}_PATCH_VERSION 0)
 SET(${PROJECT_NAME_UC}_VERSION
   ${${PROJECT_NAME_UC}_MAJOR_VERSION}.${${PROJECT_NAME_UC}_MINOR_VERSION}.${${PROJECT_NAME_UC}_PATCH_VERSION})
old mode 100644 (file)
new mode 100755 (executable)
index b615d5e..49f232c
@@ -78,7 +78,7 @@ ELSE()
   ENDIF()
 ENDIF()
 IF(SALOME_YACS_BUILD_GUI)
-  SET_AND_CHECK(GUI_ROOT_DIR_EXP "@PACKAGE_GUI_ROOT_DIR@")
+  SET_AND_CHECK(GUI_ROOT_DIR "@PACKAGE_GUI_ROOT_DIR@")
   LIST(APPEND YACS_DEFINITIONS "@GUI_DEFINITIONS@")
 ENDIF()
 
@@ -132,14 +132,15 @@ SET(SALOME_INSTALL_AMCONFIG_LOCAL "@SALOME_INSTALL_AMCONFIG_LOCAL@")
 
 IF(SALOME_YACS_BUILD_GUI)
   # Include GUI targets if they were not already loaded:
+  FIND_PACKAGE(SalomeGUI)
   IF(NOT (TARGET Event)) 
-    INCLUDE("${GUI_ROOT_DIR_EXP}/${SALOME_INSTALL_CMAKE_LOCAL}/SalomeGUITargets.cmake")
+    INCLUDE("${GUI_ROOT_DIR}/adm_local/cmake_files/SalomeGUITargets.cmake")
   ENDIF()
 ELSE(SALOME_YACS_BUILD_GUI) 
   IF(SALOME_YACS_USE_KERNEL) 
     # Include KERNEL targets if they were not already loaded:
     IF(NOT (TARGET SALOMEBasics)) 
-      INCLUDE("${KERNEL_ROOT_DIR_EXP}/${SALOME_INSTALL_CMAKE}/SalomeKERNELTargets.cmake")
+      INCLUDE("${KERNEL_ROOT_DIR_EXP}/salome_adm/cmake_files/SalomeKERNELTargets.cmake")
     ENDIF()
   ENDIF(SALOME_YACS_USE_KERNEL)
 ENDIF(SALOME_YACS_BUILD_GUI)
index 9373fc139dd17642049c1c6ec6dfd7b83405648c..c0d7d0f0b267983621b58040ddddcdd5316c3e1e 100644 (file)
@@ -41,7 +41,7 @@ master_doc = 'index'
 
 # General information about the project.
 project = 'yacs'
-copyright = '2007-2016 CEA/DEN, EDF R&D.'
+copyright = '2007-2017 CEA/DEN, EDF R&D.'
 
 # The version info for the project you're documenting, acts as replacement for
 # |version| and |release|, also used in various other places throughout the
index d1b13d05faeac80b90ba489d02abdd40712a6e73..e11882ca54f45584a484432500fb30f2a3fac289 100755 (executable)
@@ -8,7 +8,7 @@ class FreeFemComponent(Engines__POA.FreeFemComponent,
     def __init__(self, orb, poa, this, containerName,
                  instanceName, interfaceName):
         SALOME_ComponentPy_i.__init__(self, orb, poa, this, containerName,
-                                      instanceName, interfaceName, 0)
+                                      instanceName, interfaceName, False)
         self.F = FreeFem.FreeFem();
 
     def Bords(self, b):
index 478153eaf509ee919572343319c1f913ff5817f2..e456ea8cee8390d656f92189c61620a35357503e 100644 (file)
@@ -268,7 +268,7 @@ Making conforming with the component IDL
                        instanceName, interfaceName):
               SALOME_ComponentPy_i.__init__(self, orb, poa, this, 
                                             containerName, instanceName, 
-                                            interfaceName, 0)
+                                            interfaceName, False)
 
 Enable supervision of the component
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -295,7 +295,7 @@ The implementation class constructor should be modified as follows to signal use
                     instanceName, interfaceName):
            SALOME_ComponentPy_i.__init__(self, orb, poa, this, 
                                          containerName, instanceName, 
-                                         interfaceName, 1)
+                                         interfaceName, True)
 
 in which the parameter “1” is added to the end of the call to the ``SALOME_ComponentPy_i`` of the constructor.  
 The component can then use the following instruction::
index c3274d1943ff8cfe6402224f7ec6cb9892a885c5..124c1f41416219185c42a457b18f515e574a0e40 100755 (executable)
@@ -4,7 +4,7 @@
   <ul>
     $navpath
     <li class="footer">
-      Copyright &copy; 2006-2016  CEA/DEN, EDF R&amp;D<br>
+      Copyright &copy; 2006-2017  CEA/DEN, EDF R&amp;D<br>
     </li>
   </ul>
 </div>
index 064805212e5407d8cdda0c71837a46bb570d7331..af8928c9fb58d7e84be992132b89f0f2406d45e5 100755 (executable)
@@ -29,7 +29,7 @@ SET(SUBDIRS_COMMON
 # KERNEL
 ##
 IF(SALOME_YACS_USE_KERNEL)
-  SET(SUBDIRS_KERNEL runtime yacsloader evalyfx)
+  SET(SUBDIRS_KERNEL runtime yacsloader evalyfx py2yacs)
 ENDIF(SALOME_YACS_USE_KERNEL)
 
 ##
index 71e7e4c8b7f725bde7362914c06d57ef24fc277d..6f6927794391dc500c0e1ef42b54e637fd838697 100644 (file)
@@ -29,8 +29,10 @@ SET(YACS_TEST_LIB "../lib")
 SUBDIRS(
     bases
     engine
+    engine_swig
     runtime
     pmml
     yacsloader
     yacsloader_swig
+    py2yacs
     )
index 003a73e82a6d4726ee43dbbe95e55cf5eb123d9d..346f0406b4df2747aa8ef5a04467733e72531407 100644 (file)
@@ -33,6 +33,9 @@ namespace YACS
       AutoRefCnt(const AutoRefCnt& other):_ptr(0) { referPtr(other._ptr); }
       AutoRefCnt(T *ptr=0):_ptr(ptr) { }
       ~AutoRefCnt() { destroyPtr(); }
+      bool isNull() const { return _ptr==0; }
+      bool isNotNull() const { return !isNull(); }
+      void nullify() { destroyPtr(); _ptr=0; }
       bool operator==(const AutoRefCnt& other) const { return _ptr==other._ptr; }
       bool operator==(const T *other) const { return _ptr==other; }
       AutoRefCnt &operator=(const AutoRefCnt& other) { if(_ptr!=other._ptr) { destroyPtr(); referPtr(other._ptr); } return *this; }
@@ -44,6 +47,7 @@ namespace YACS
       operator T *() { return _ptr; }
       operator const T *() const { return _ptr; }
       T *retn() { if(_ptr) _ptr->incrRef(); return _ptr; }
+      void takeRef(T *ptr) { if(_ptr!=ptr) { destroyPtr(); _ptr=ptr; if(_ptr) _ptr->incrRef(); } }
     private:
       void referPtr(T *ptr) { _ptr=ptr; if(_ptr) _ptr->incrRef(); }
       void destroyPtr() { if(_ptr) _ptr->decrRef(); }
@@ -51,6 +55,32 @@ namespace YACS
       T *_ptr;
     };
 
+    template<class T>
+    class AutoConstRefCnt
+    {
+    public:
+      AutoConstRefCnt(const AutoConstRefCnt& other):_ptr(0) { referPtr(other._ptr); }
+      AutoConstRefCnt(const T *ptr=0):_ptr(ptr) { }
+      ~AutoConstRefCnt() { destroyPtr(); }
+      bool isNull() const { return _ptr==0; }
+      bool isNotNull() const { return !isNull(); }
+      void nullify() { destroyPtr(); _ptr=0; }
+      bool operator==(const AutoConstRefCnt& other) const { return _ptr==other._ptr; }
+      bool operator==(const T *other) const { return _ptr==other; }
+      AutoConstRefCnt &operator=(const AutoConstRefCnt& other) { if(_ptr!=other._ptr) { destroyPtr(); referPtr(other._ptr); } return *this; }
+      AutoConstRefCnt &operator=(const T *ptr) { if(_ptr!=ptr) { destroyPtr(); _ptr=ptr; } return *this; }
+      const T *operator->() const { return _ptr; }
+      const T& operator*() const { return *_ptr; }
+      operator const T *() const { return _ptr; }
+      const T *retn() { if(_ptr) _ptr->incrRef(); return _ptr; }
+      void takeRef(const T *ptr) { if(_ptr!=ptr) { destroyPtr(); _ptr=ptr; if(_ptr) _ptr->incrRef(); } }
+    private:
+      void referPtr(const T *ptr) { _ptr=ptr; if(_ptr) _ptr->incrRef(); }
+      void destroyPtr() { if(_ptr) _ptr->decrRef(); }
+    private:
+      const T *_ptr;
+    };
+
     template<class T, class U>
     typename YACS::BASES::AutoRefCnt<U> DynamicCast(typename YACS::BASES::AutoRefCnt<T>& autoSubPtr) throw()
     {
index e622138868a0b8a44fc32fd191e7e9e53313963b..b3e6072093f23bfe4038ffd0f0baf58c54c8f993 100644 (file)
 
 using namespace YACS::BASES;
 
+#if defined(__APPLE__)
+const char DynLibLoaderGNU::_extForDynLib[]=".dylib";
+#else
 const char DynLibLoaderGNU::_extForDynLib[]=".so";
+#endif
 
 DynLibLoaderGNU::DynLibLoaderGNU(const std::string& libNameWithoutExtension):_libName(libNameWithoutExtension),
                                                                              _handleOnLoadedLib(0)
index 5bceee79c3a338e4f19c23d225e2b1816e639f17..7182b35b930bac4d89048a3b8a119747b97fbafd 100644 (file)
@@ -62,20 +62,20 @@ void counters::stats()
 
 
 
-chrono::chrono(int i) : _ctr(i), _run(true)
+salome_chrono::salome_chrono(int i) : _ctr(i), _run(true)
 {
-  //DEBTRACE("chrono::chrono " << _ctr << " " << _run);
+  //DEBTRACE("salome_chrono::salome_chrono " << _ctr << " " << _run);
   _start = clock();    
 }
 
-chrono::~chrono()
+salome_chrono::~salome_chrono()
 {
   if (_run) stop();
 }
 
-void chrono::stop()
+void salome_chrono::stop()
 {
-  //DEBTRACE("chrono::stop " << _ctr << " " << _run);
+  //DEBTRACE("salome_chrono::stop " << _ctr << " " << _run);
   if (_run)
     {
       _run = false;
index e16fb3ec37027ed0e34804e2a2502a3b50c1da40..9f6e8f4da6e45e9e5752d61d696c3bf0cb572a51 100644 (file)
@@ -50,11 +50,11 @@ protected:
   int _nbChrono;
 };
 
-class YACSBASES_EXPORT chrono
+class YACSBASES_EXPORT salome_chrono
 {
 public:
-  chrono(int i);
-  ~chrono();
+  salome_chrono(int i);
+  ~salome_chrono();
   void stop();
 protected:
   bool _run;
@@ -79,7 +79,7 @@ static timeval tv;
 #ifdef CHRONODEF
 #define CHRONO(i) counters::_ctrs[i]._ctrNames = (char *)__FILE__; \
   counters::_ctrs[i]._ctrLines = __LINE__; \
-  chrono aChrono##i(i);
+  salome_chrono aChrono##i(i);
 
 #define CHRONOSTOP(i) aChrono##i.stop();
 
index 9a8d35afa9a783a4e040ef0ae55068c59f8b315a..3b4f5dc6409d388c7cb4d819a343a58f9b5fd82d 100644 (file)
 #define __ABSTRACTPOINT_HXX__
 
 #include "YACSlibEngineExport.hxx"
+#include "PlayGround.hxx"
+#include "AutoRefCnt.hxx"
 
+#include <map>
 #include <list>
 #include <vector>
 #include <string>
@@ -34,6 +37,7 @@ namespace YACS
     class InGate;
     class OutGate;
     class BlocPoint;
+    class ComposedNode;
     class ForkBlocPoint;
     class LinkedBlocPoint;
     
@@ -63,6 +67,8 @@ namespace YACS
       virtual bool contains(Node *node) = 0;
       virtual int getNumberOfNodes() const = 0;
       virtual int getMaxLevelOfParallelism() const = 0;
+      virtual double getWeightRegardingDPL() const = 0;
+      virtual void partitionRegardingDPL(const PartDefinition *pd, std::map<ComposedNode *, YACS::BASES::AutoRefCnt<PartDefinition> >& zeMap) const = 0;
       virtual std::string getRepr() const = 0;
       virtual ~AbstractPoint();
     public:
index 01d6dc74ca5c5cdde4b0d0c804a99fd9b23cb50a..d7727a16dae9e651006fa4e10a08b3b93b1da6a3 100644 (file)
@@ -31,28 +31,62 @@ BagPoint::BagPoint(const std::list<AbstractPoint *>& nodes, AbstractPoint *fathe
 {
 }
 
-Node *BagPoint::getFirstNode()
+AbstractPoint *BagPoint::getUnique()
 {
   if(_nodes.size()!=1)
-    throw YACS::Exception("BagPoint::getFirstNode : invalid call !");
+    throw YACS::Exception("BagPoint::getUnique : invalid call !");
   else
-    return (*_nodes.begin())->getFirstNode();
+    {
+      AbstractPoint *ret(*_nodes.begin());
+      if(!ret)
+        throw YACS::Exception("BagPoint::getUnique : Ooops !");
+      return ret;
+    }
 }
 
-Node *BagPoint::getLastNode()
+const AbstractPoint *BagPoint::getUnique() const
 {
   if(_nodes.size()!=1)
-    throw YACS::Exception("BagPoint::getLastNode : invalid call !");
+    throw YACS::Exception("BagPoint::getUnique const : invalid call !");
   else
-    return (*_nodes.begin())->getLastNode();
+    {
+      AbstractPoint *ret(*_nodes.begin());
+      if(!ret)
+        throw YACS::Exception("BagPoint::getUnique : Ooops !");
+      return ret;
+    }
+}
+
+AbstractPoint *BagPoint::getUniqueAndReleaseIt()
+{
+  AbstractPoint *ret(getUnique());
+  getOutPoint(ret);
+  return ret;
+}
+
+Node *BagPoint::getFirstNode()
+{
+  return getUnique()->getFirstNode();
+}
+
+Node *BagPoint::getLastNode()
+{
+  return getUnique()->getLastNode();
 }
 
 int BagPoint::getMaxLevelOfParallelism() const
 {
-  if(_nodes.size()!=1)
-    throw YACS::Exception("BagPoint::getMaxLevelOfParallelism : invalid call !");
-  else
-    return (*_nodes.begin())->getMaxLevelOfParallelism();
+  return getUnique()->getMaxLevelOfParallelism();
+}
+
+double BagPoint::getWeightRegardingDPL() const
+{
+  return getUnique()->getWeightRegardingDPL();
+}
+
+void BagPoint::partitionRegardingDPL(const PartDefinition *pd, std::map<ComposedNode *, YACS::BASES::AutoRefCnt<PartDefinition> >& zeMap) const
+{
+  getUnique()->partitionRegardingDPL(pd,zeMap);
 }
 
 std::string BagPoint::getRepr() const
index f08f52c7e37b31e57662380e0719804f07b3fb7f..9568deb07f4377bf31372509d5581d568e5754ba 100644 (file)
@@ -37,7 +37,10 @@ namespace YACS
       Node *getFirstNode();
       Node *getLastNode();
       int getMaxLevelOfParallelism() const;
+      double getWeightRegardingDPL() const;
+      void partitionRegardingDPL(const PartDefinition *pd, std::map<ComposedNode *, YACS::BASES::AutoRefCnt<PartDefinition> >& zeMap) const;
       std::string getRepr() const;
+      AbstractPoint *getUniqueAndReleaseIt();
     public:
       int size() const { return (int)_nodes.size(); }
       void replaceInMe(BlocPoint *aSet);
@@ -45,6 +48,9 @@ namespace YACS
       void deal2(bool& somethingDone);
       void deal2Bis(bool& somethingDone);
       void deal2Ter(bool& somethingDone);
+    private:
+      AbstractPoint *getUnique();
+      const AbstractPoint *getUnique() const;
     };
   }
 }
index 7d5e7b0450360a06e3ab9b2a15e73dd3ae827418..6fc3240abfa88716d1fb14d9d23e3654f04aaa64 100644 (file)
@@ -25,7 +25,9 @@
 #include "OutputDataStreamPort.hxx"
 #include "ElementaryNode.hxx"
 #include "Visitor.hxx"
+#include "ForkBlocPoint.hxx"
 #include "SetOfPoints.hxx"
+#include "PlayGround.hxx"
 
 #include <queue>
 #include <iostream>
@@ -452,16 +454,30 @@ void Bloc::accept(Visitor* visitor)
  * for all concurrent branches in \a this.
  */
 int Bloc::getMaxLevelOfParallelism() const
+{
+  std::list< AbstractPoint * > pts(analyzeParallelism());
+  ForkBlocPoint fbp(pts,NULL);
+  return fbp.getMaxLevelOfParallelism();
+}
+
+std::list< AbstractPoint * > Bloc::analyzeParallelism() const
 {
   std::vector< std::list<Node *> > r(splitIntoIndependantGraph());
-  int ret(0);
+  std::list< AbstractPoint * > pts;
   for(std::vector< std::list<Node *> >::const_iterator it=r.begin();it!=r.end();it++)
     {
       SetOfPoints sop(*it);
       sop.simplify();
-      ret+=sop.getMaxLevelOfParallelism();
+      pts.push_back(sop.getUniqueAndReleaseIt());
     }
-  return ret;
+  return pts;
+}
+
+double Bloc::getWeightRegardingDPL() const
+{
+  std::list< AbstractPoint * > pts(analyzeParallelism());
+  ForkBlocPoint fbp(pts,NULL);
+  return fbp.getWeightRegardingDPL();
 }
 
 void Bloc::removeRecursivelyRedundantCL()
@@ -476,6 +492,15 @@ void Bloc::removeRecursivelyRedundantCL()
   destructCFComputations(info);
 }
 
+void Bloc::partitionRegardingDPL(const PartDefinition *pd, std::map<ComposedNode *, YACS::BASES::AutoRefCnt<PartDefinition> >& zeMap)
+{
+  if(!pd)
+    throw Exception("Bloc::partitionRegardingDPL : NULL pointer !");
+  std::list< AbstractPoint * > pts(analyzeParallelism());
+  ForkBlocPoint fbp(pts,NULL);
+  fbp.partitionRegardingDPL(pd,zeMap);
+}
+
 void Bloc::performCFComputationsOnlyOneLevel(LinkInfo& info) const
 {
   delete _fwLinks;//Normally useless
index 3cfec917263b5eab4445c9a4d2530a135dca5d40..3759fc0947804cfd574397f876fd8178cd6a15ed 100644 (file)
 
 #include "YACSlibEngineExport.hxx"
 #include "StaticDefinedComposedNode.hxx"
+#include "AutoRefCnt.hxx"
 
 namespace YACS
 {
   namespace ENGINE
   {
+    class PartDefinition;
+    class DynParaLoop;
+    class AbstractPoint;
+    class PlayGround;
     class YACSLIBENGINE_EXPORT Bloc : public StaticDefinedComposedNode
     {
     protected:
@@ -61,7 +66,10 @@ namespace YACS
       void findAllNodesStartingFrom(Node *start, std::set<Node *>& result, std::map<Node *, std::set<Node *> >& accelStr, LinkInfo& info) const;
       virtual std::string typeName() { return "YACS__ENGINE__Bloc"; }
       int getMaxLevelOfParallelism() const;
+      double getWeightRegardingDPL() const;
       void removeRecursivelyRedundantCL();
+      void partitionRegardingDPL(const PartDefinition *pd, std::map<ComposedNode *, YACS::BASES::AutoRefCnt<PartDefinition> >& zeMap);
+      void fitToPlayGround(const PlayGround *pg);
     protected:
       bool areAllSubNodesFinished() const;
       bool areAllSubNodesDone() const;
@@ -89,6 +97,7 @@ namespace YACS
       void seekOkAndUseless1(std::vector<Node *>& okAndUseless1, std::set<Node *>& allNodes) const;
       void seekUseless2(std::vector<Node *>& useless2, std::set<Node *>& allNodes) const;
     private:
+      std::list< AbstractPoint * > analyzeParallelism() const;
       static void findUselessLinksIn(const std::list< std::vector<Node *> >& res , LinkInfo& info);
       template<bool direction>
       static unsigned appendIfAlreadyFound(std::list< std::vector<Node *> >& res, const std::vector<Node *>& startRes, Node *node, std::map<Node *, std::set<Node *> >& fastFinder);
index 485bcdf2dd747388bcf2cbd10177d683eaf3629d..b351d5cdbe4391975907605b052addeadf1cb19d 100644 (file)
@@ -20,6 +20,8 @@
 #include "BlocPoint.hxx"
 #include "Node.hxx"
 
+#include <algorithm>
+
 using namespace YACS::ENGINE;
 
 BlocPoint::BlocPoint(const std::list<AbstractPoint *>& nodes, AbstractPoint *father):AbstractPoint(father),_nodes(nodes)
@@ -28,6 +30,15 @@ BlocPoint::BlocPoint(const std::list<AbstractPoint *>& nodes, AbstractPoint *fat
     (*it)->setFather(this);
 }
 
+void BlocPoint::getOutPoint(AbstractPoint *node)
+{
+  std::list<AbstractPoint *>::iterator it(std::find(_nodes.begin(),_nodes.end(),node));
+  if(it==_nodes.end())
+    throw YACS::Exception("BlocPoint::getOutPoint : node not in this !");
+  _nodes.erase(it);
+  node->setFather(NULL);
+}
+
 AbstractPoint *BlocPoint::findPointWithNode(Node *node)
 {
   for(std::list<AbstractPoint *>::iterator it=_nodes.begin();it!=_nodes.end();it++)
index eea6b92670664bac64ef4c2c3390db38bf218806..c75f8ef486c93ef566e31f0e878d36125341a392 100644 (file)
@@ -42,6 +42,8 @@ namespace YACS
       int getNumberOfNodes() const;
       const std::list<AbstractPoint *>& getListOfPoints() const { return _nodes; }
       virtual ~BlocPoint();
+    protected:
+      void getOutPoint(AbstractPoint *node);
     };
   }
 }
diff --git a/src/engine/Bloc_impl.cxx b/src/engine/Bloc_impl.cxx
new file mode 100644 (file)
index 0000000..d3f3c6f
--- /dev/null
@@ -0,0 +1,108 @@
+// Copyright (C) 2006-2016  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 "Bloc.hxx"
+#include "Proc.hxx"
+#include "Visitor.hxx"
+#include "ForEachLoop.hxx"
+#include "InlineNode.hxx"
+#include "HomogeneousPoolContainer.hxx"
+
+using namespace YACS::ENGINE;
+
+void Bloc::fitToPlayGround(const PlayGround *pg)
+{
+  static const char MSG[]="Bloc::fitToPlayGround : Not implemented yet for this type of node !";
+  class MyVisitor : public Visitor
+    {
+    public:
+      MyVisitor(ComposedNode *root):Visitor(root),_lev(0),_max_lev(0) { }
+      void visitBloc(Bloc *node) { node->ComposedNode::accept(this); }
+      void visitElementaryNode(ElementaryNode *node) { }
+      void visitForEachLoop(ForEachLoop *node)
+      {
+        _max_lev=std::max(_max_lev,_lev);
+        {
+          _lev++;
+          node->ComposedNode::accept(this);
+          _lev--;
+        }
+        node->edGetNbOfBranchesPort()->edInit(1);
+        if(_lev==_max_lev)
+          {
+          _fes.push_back(node);// locate all leaves ForEach
+          }
+        if(_lev==0)
+          _max_lev=0;
+        }
+      void visitOptimizerLoop(OptimizerLoop *node) { throw YACS::Exception(MSG); }
+      void visitDynParaLoop(DynParaLoop *node) { throw YACS::Exception(MSG); }
+      void visitForLoop(ForLoop *node) { throw YACS::Exception(MSG); }
+      void visitInlineNode(InlineNode *node)
+      {
+          Container *cont(node->getContainer());
+          HomogeneousPoolContainer *cont2(dynamic_cast<HomogeneousPoolContainer *>(cont));
+          if(!cont2)
+            return ;
+          _cont.push_back(cont2);
+          HomogeneousPoolContainer *cont3(cont2->getDirectFather());
+          if(cont3)
+            _cont2.insert(cont3);
+      }
+      void visitInlineFuncNode(InlineFuncNode *node) { throw YACS::Exception(MSG); }
+      void visitLoop(Loop *node) { throw YACS::Exception(MSG); }
+      void visitProc(Proc *node) { node->ComposedNode::accept(this); }
+      void visitServiceNode(ServiceNode *node) { throw YACS::Exception(MSG); }
+      void visitServerNode(ServerNode *node) { throw YACS::Exception(MSG); }
+      void visitServiceInlineNode(ServiceInlineNode *node) { throw YACS::Exception(MSG); }
+      void visitSwitch(Switch *node) { throw YACS::Exception(MSG); }
+      void visitWhileLoop(WhileLoop *node) { throw YACS::Exception(MSG); }
+      void visitPresetNode(DataNode *node) { throw YACS::Exception(MSG); }
+      void visitOutNode(DataNode *node) { throw YACS::Exception(MSG); }
+      void visitStudyInNode(DataNode *node) { throw YACS::Exception(MSG); }
+      void visitStudyOutNode(DataNode *node) { throw YACS::Exception(MSG); }
+    public:
+      std::list<ForEachLoop *> _fes;
+      std::list< HomogeneousPoolContainer *> _cont;
+      std::set< HomogeneousPoolContainer * > _cont2;
+      int _lev;
+      int _max_lev;
+  };
+  YACS::BASES::AutoRefCnt<PartDefinition> pd(new AllPartDefinition(pg,1));
+  std::map<ComposedNode *,YACS::BASES::AutoRefCnt<PartDefinition> > zeMap;
+  this->partitionRegardingDPL(pd,zeMap);
+  MyVisitor vis(this);
+  this->accept(&vis);
+  for(std::list<ForEachLoop *>::const_iterator it=vis._fes.begin();it!=vis._fes.end();it++)
+    {
+      std::map<ComposedNode *,YACS::BASES::AutoRefCnt<PartDefinition> >::iterator it2(zeMap.find(*it));
+      if(it2==zeMap.end())
+        throw YACS::Exception("Bloc::fitToPlayGround : internal error !");
+      int maxLev((*it)->getExecNode()->getMaxLevelOfParallelism());
+      int a((*it2).second->getNumberOfCoresConsumed());
+      int res(a/maxLev);
+      if(a%maxLev!=0)
+        res++;
+      (*it)->edGetNbOfBranchesPort()->edInit(res);
+    }
+  for(std::set< HomogeneousPoolContainer * >::const_iterator it=vis._cont2.begin();it!=vis._cont2.end();it++)
+    (*it)->setSizeOfPool(pg->getNumberOfWorkers((*it)->getNumberOfCoresPerWorker()));
+  for(std::list< HomogeneousPoolContainer *>::const_iterator it=vis._cont.begin();it!=vis._cont.end();it++)
+    (*it)->prepareMaskForExecution();
+}
index 9c6d3fbcfc51deb1fe46aa9f48f2519cf22216f8..b1f43ff38dbd73d31643641fb72d9fafbb3e363f 100644 (file)
@@ -106,6 +106,7 @@ SET(YACSlibEngine_HEADERS
   LinkedBlocPoint.hxx
   ElementaryPoint.hxx
   SetOfPoints.hxx
+  PlayGround.hxx
   )
 
 # --- sources ---
@@ -142,6 +143,7 @@ SET(YACSlibEngine_SOURCES
   ServiceInlineNode.cxx
   StaticDefinedComposedNode.cxx
   Bloc.cxx
+  Bloc_impl.cxx
   Proc.cxx
   Loop.cxx
   ForLoop.cxx
@@ -178,6 +180,7 @@ SET(YACSlibEngine_SOURCES
   LinkedBlocPoint.cxx
   ElementaryPoint.cxx
   SetOfPoints.cxx
+  PlayGround.cxx
   )
 SET(YACSlibEngine_HEADERS ${YACSlibEngine_HEADERS} PARENT_SCOPE)  # Make it visible to src/engine_swig to handle dependencies
 
index 0fa2bf8733ebe66efb8a9b94ce518ffc74abee98..e27e72da6f26f18cdf03653757558aea777090da 100644 (file)
@@ -241,7 +241,7 @@ std::vector<Task *> ComposedNode::getNextTasks(bool& isMore)
  * Calls ComposedNode::updateStateFrom to update state from task to root node
  */
 void ComposedNode::notifyFrom(const Task *sender, //* I : task emitting event
-                              YACS::Event event,   //* I : event emitted
+                              YACS::Event event,  //* I : event emitted
                               const Executor *execInst
                               )
 {
@@ -1376,7 +1376,7 @@ OutputDataStreamPort *ComposedNode::getOutputDataStreamPort(const std::string& n
  * Called by ComposedNode::notifyFrom
  */
 YACS::Event ComposedNode::updateStateFrom(Node *node,        //* I : node emitting event
-                                          YACS::Event event,  //* I : event emitted
+                                          YACS::Event event, //* I : event emitted
                                           const Executor *execInst
                                           )
 {
index 73f32524e34f696184ffa3711aae3240df429b41..8f5b6edcf59a75c7f330c3b16fef106a1f578fc3 100644 (file)
@@ -72,7 +72,7 @@ namespace YACS
       virtual std::map<std::string,std::string> getProperties() const = 0;
       virtual std::map<std::string,std::string> getResourceProperties(const std::string& name) const = 0;
       virtual void setProperties(const std::map<std::string,std::string>& properties);
-      std::string getName() const { return _name; }
+      virtual std::string getName() const { return _name; }
       //! \b WARNING ! name is used in edition to identify different containers, it is not the runtime name of the container
       void setName(std::string name) { _name = name; }
       void setProc(Proc* proc) { _proc = proc; }
index 8ca796b751824cff41ebac4c01b29a5a84002246..c957e915d67a745b778b65030f569182014b110a 100644 (file)
@@ -80,11 +80,11 @@ void Dispatcher::printObservers()
 void Dispatcher::dispatch(Node* object, const std::string& event)
 {
   DEBTRACE("Dispatcher::dispatch " << event );
-  typedef std::set<Observer*>::iterator jt;
   std::pair<Node*,std::string> key(object,event);
-  if(_observers.count(key) != 0)
+  std::map< std::pair<Node*,std::string> , std::set<Observer*> >::const_iterator it(_observers.find(key));
+  if(it!=_observers.end())
     {
-      for(jt iter=_observers[key].begin();iter!=_observers[key].end();iter++)
+      for(std::set<Observer*>::const_iterator iter=(*it).second.begin();iter!=(*it).second.end();iter++)
         {
           (*iter)->notifyObserver(object,event);
         }
@@ -93,11 +93,11 @@ void Dispatcher::dispatch(Node* object, const std::string& event)
 
 void Dispatcher::dispatch2(Node* object,const std::string& event, void *something)
 {
-  typedef std::set<Observer*>::iterator jt;
   std::pair<Node*,std::string> key(object,event);
-  if(_observers.count(key) != 0)
+  std::map< std::pair<Node*,std::string> , std::set<Observer*> >::const_iterator it(_observers.find(key));
+  if(it!=_observers.end())
     {
-      for(jt iter=_observers[key].begin();iter!=_observers[key].end();iter++)
+      for(std::set<Observer*>::const_iterator iter=(*it).second.begin();iter!=(*it).second.end();iter++)
         {
           (*iter)->notifyObserver2(object,event,something);
         }
index 26e46e2941ebed18c73a29b951121457bf0d74c9..dbf270dc4520d772abaa9a3eb478e83a32a3e839 100644 (file)
@@ -82,7 +82,6 @@ namespace YACS
       virtual ~Dispatcher();
     protected:
       std::map< std::pair<Node*,std::string> , std::set<Observer*> > _observers;
-      std::map< std::pair<Executor*,std::string> , std::set<Observer*> > _observExec;
       static Dispatcher* _singleton;
     };
 
index cca32828ba0ac1aaf2709accbc8a631a5895b0a8..632f72478c50835cdd4f4188feb26c10e77e8a9f 100644 (file)
@@ -44,7 +44,7 @@ const char DynParaLoop::NAME_OF_NUMBER_OF_BRANCHES[]="nbBranches";
 DynParaLoop::DynParaLoop(const std::string& name, TypeCode *typeOfDataSplitted)
   : ComposedNode(name),_node(0),_initNode(0),_finalizeNode(0),_nbOfEltConsumed(0),
     _nbOfBranches(NAME_OF_NUMBER_OF_BRANCHES,this,Runtime::_tc_int),
-    _splittedPort(NAME_OF_SPLITTED_SEQ_OUT,this,typeOfDataSplitted),_initializingCounter(0),_unfinishedCounter(0),_failedCounter(0)
+    _splittedPort(NAME_OF_SPLITTED_SEQ_OUT,this,typeOfDataSplitted),_initializingCounter(0),_unfinishedCounter(0),_failedCounter(0),_weight(1.)
 {
 }
 
@@ -58,7 +58,7 @@ DynParaLoop::~DynParaLoop()
 DynParaLoop::DynParaLoop(const DynParaLoop& other, ComposedNode *father, bool editionOnly)
   : ComposedNode(other,father), _nbOfBranches(other._nbOfBranches,this),
     _splittedPort(other._splittedPort,this), _node(0), _initNode(0), _finalizeNode(0),
-    _nbOfEltConsumed(0),_initializingCounter(0),_unfinishedCounter(0),_failedCounter(0)
+    _nbOfEltConsumed(0),_initializingCounter(0),_unfinishedCounter(0),_failedCounter(0),_weight(1.)
 {
   if(other._node)
     _node=other._node->clone(this,editionOnly);
@@ -423,6 +423,13 @@ DynParaLoop::TypeOfNode DynParaLoop::getIdentityOfNotifyerNode(const Node *node,
       return FINALIZE_NODE;
 }
 
+void DynParaLoop::setWeight(double newVal)
+{
+  if(newVal<=0.)
+    throw Exception("DynParaLoop::setWeight : invalid input value !");
+  _weight=newVal;
+}
+
 bool DynParaLoop::isMultiplicitySpecified(unsigned& value) const
 {
   if(_nbOfBranches.edIsManuallyInitialized())
@@ -896,6 +903,14 @@ int DynParaLoop::getMaxLevelOfParallelism() const
   return _nbOfBranches.getIntValue() * _node->getMaxLevelOfParallelism();
 }
 
+void DynParaLoop::partitionRegardingDPL(const PartDefinition *pd, std::map<ComposedNode *, YACS::BASES::AutoRefCnt<PartDefinition> >& zeMap)
+{
+  YACS::BASES::AutoRefCnt<PartDefinition> pd2(pd->copy());
+  zeMap[this]=pd2;
+  if(_node)
+    _node->partitionRegardingDPL(pd,zeMap);
+}
+
 void DynParaLoop::shutdown(int level)
 {
   if(level==0)return;
index c00a5e8c599b312701831277f9c09bbcbeafe25e..723b27e2ec43aeab81b29ccf62131d5512e9a11f 100644 (file)
@@ -57,6 +57,7 @@ namespace YACS
       int _initializingCounter;
       int _unfinishedCounter;
       int _failedCounter;
+      double _weight;
     protected:
       static const char NAME_OF_SPLITTED_SEQ_OUT[];
       static const char OLD_NAME_OF_SPLITTED_SEQ_OUT[];
@@ -97,6 +98,9 @@ namespace YACS
       Node *getChildByShortName(const std::string& name) const throw(Exception);
       Node *getChildByNameExec(const std::string& name, unsigned id) const throw(Exception);
       std::vector<Node *> getNodes() const { return _execNodes; } // need to use in GUI part for adding observers for clone nodes
+      double getWeight() const { return _weight; }
+      void setWeight(double newVal);
+      double getWeightRegardingDPL() const { return getWeight(); }
       bool isMultiplicitySpecified(unsigned& value) const;
       void forceMultiplicity(unsigned value);
       virtual void checkBasicConsistency() const throw(Exception);
@@ -106,6 +110,7 @@ namespace YACS
       Node * getExecNode();
       Node * getFinalizeNode();
       int getMaxLevelOfParallelism() const;
+      void partitionRegardingDPL(const PartDefinition *pd, std::map<ComposedNode *, YACS::BASES::AutoRefCnt<PartDefinition> >& zeMap);
     protected:
       void buildDelegateOf(InPort * & port, OutPort *initialStart, const std::list<ComposedNode *>& pointsOfView);
       void buildDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView);
index 5544c86fbbac52299d09242cd22180214d46a63d..d2561e804f9335d7c5fa6a7ff8302b73f0f7e47e 100644 (file)
@@ -107,7 +107,9 @@ namespace YACS
       virtual void ensureLoading();
 
       int getMaxLevelOfParallelism() const { return 1; }
-
+      double getWeightRegardingDPL() const { return 0.; }
+      void partitionRegardingDPL(const PartDefinition *pd, std::map<ComposedNode *, YACS::BASES::AutoRefCnt<PartDefinition> >& zeMap) { }
+      
       //run part
       void begin();
       bool isReady();
index f476c20e4731d1cb57a29b6f45fad88a46ba53ed..aeef403b426173094037f4619f71196877483d75 100644 (file)
@@ -59,6 +59,16 @@ int ElementaryPoint::getMaxLevelOfParallelism() const
   return _node->getMaxLevelOfParallelism();
 }
 
+double ElementaryPoint::getWeightRegardingDPL() const
+{
+  return _node->getWeightRegardingDPL();
+}
+
+void ElementaryPoint::partitionRegardingDPL(const PartDefinition *pd, std::map<ComposedNode *, YACS::BASES::AutoRefCnt<PartDefinition> >& zeMap) const
+{
+  _node->partitionRegardingDPL(pd,zeMap);
+}
+
 std::string ElementaryPoint::getRepr() const
 {
   return _node->getName();
index 5228dd5e49f01849917ddbb03550cce08269755b..08897e80afcdee7b98e6a0ba89a01ac09f6ad0da 100644 (file)
@@ -43,6 +43,8 @@ namespace YACS
       Node *getLastNode();
       int getNumberOfNodes() const;
       int getMaxLevelOfParallelism() const;
+      double getWeightRegardingDPL() const;
+      void partitionRegardingDPL(const PartDefinition *pd, std::map<ComposedNode *, YACS::BASES::AutoRefCnt<PartDefinition> >& zeMap) const;
       std::string getRepr() const;
       virtual ~ElementaryPoint();
     };
index d559230355590a8c16f1147376c84106424800ab..c5e7c7b45e71cd4ae6e6c5d21ee318fe42f46c29 100644 (file)
@@ -651,6 +651,7 @@ bool Executor::saveState(const std::string& xmlFile)
   DEBTRACE("Executor::saveState() in " << xmlFile);
   bool result = false;
   try {
+    YACS::BASES::AutoLocker<YACS::BASES::Mutex> alck(&_mutexForSchedulerUpdate);
     YACS::ENGINE::VisitorSaveState vst(_root);
     vst.openFileDump(xmlFile.c_str());
     _root->accept(&vst);
index 83af9c7e7c9d5b738338da5a7eef930b71dc19ac..838bfb338fb4c6e00c5b4bc58598214db93a10a0 100644 (file)
@@ -318,6 +318,14 @@ ForEachLoopPassedData::ForEachLoopPassedData(const std::vector<unsigned int>& pa
     }
 }
 
+ForEachLoopPassedData::ForEachLoopPassedData(const ForEachLoopPassedData& copy)
+: _passedIds(copy._passedIds),
+  _passedOutputs(copy._passedOutputs),
+  _nameOfOutputs(copy._nameOfOutputs),
+  _flagsIds(copy._flagsIds)
+{
+}
+
 ForEachLoopPassedData::~ForEachLoopPassedData()
 {
   for(std::vector<SequenceAny *>::iterator it=_passedOutputs.begin();it!=_passedOutputs.end();it++)
@@ -878,6 +886,7 @@ YACS::Event ForEachLoop::updateStateOnFailedEventFrom(Node *node, const Executor
 {
   unsigned int id;
   DynParaLoop::TypeOfNode ton(getIdentityOfNotifyerNode(node,id));
+  // TODO: deal with keepgoing without the dependency to Executor
   if(ton!=WORK_NODE || !execInst->getKeepGoingProperty())
     return DynParaLoop::updateStateOnFailedEventFrom(node,execInst);
   else
@@ -915,7 +924,8 @@ void ForEachLoop::buildDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort
         }
       else
         {
-          TypeCodeSeq *newTc=(TypeCodeSeq *)TypeCode::sequenceTc("","",port.first->edGetType());
+          TypeCode *tcTrad((YACS::ENGINE::TypeCode*)finalTarget->edGetType()->subContentType(getFEDeltaBetween(port.first,finalTarget)));
+          TypeCodeSeq *newTc=(TypeCodeSeq *)TypeCode::sequenceTc("","",tcTrad);
           // The out going ports belong to the ForEachLoop, whereas
           // the delegated port belongs to a node child of the ForEachLoop.
           // The name of the delegated port contains dots (bloc.node.outport),
@@ -923,7 +933,7 @@ void ForEachLoop::buildDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort
           std::string outputPortName(getPortName(port.first));
           InterceptorizeNameOfPort(outputPortName);
           AnySplitOutputPort *newPort(new AnySplitOutputPort(outputPortName,this,newTc));
-          InterceptorInputPort *intercptor(new InterceptorInputPort(outputPortName + "_in",this,port.first->edGetType()));
+          InterceptorInputPort *intercptor(new InterceptorInputPort(outputPortName + "_in",this,tcTrad));
           intercptor->setRepr(newPort);
           newTc->decrRef();
           newPort->addRepr(port.first,intercptor);
@@ -1046,7 +1056,8 @@ void ForEachLoop::createOutputOutOfScopeInterceptors(int branchNb)
       //AnyInputPort *interceptor=new AnyInputPort((*iter)->getName(),this,(*iter)->edGetType());
       OutPort *portOut=getDynOutPortByAbsName(branchNb,getOutPortName(((*iter)->getRepr())));
       DEBTRACE( portOut->getName() );
-      AnyInputPort *interceptor=new AnyInputPort((*iter)->getName(),this,portOut->edGetType());
+      TypeCode *tc((TypeCode *)(*iter)->edGetType()->contentType());
+      AnyInputPort *interceptor=new AnyInputPort((*iter)->getName(),this,tc);
       portOut->addInPort(interceptor);
       _execOutGoingPorts[branchNb].push_back(interceptor);
     }
@@ -1171,7 +1182,9 @@ std::vector<unsigned int> ForEachLoop::getPassedResults(Executor *execut, std::v
     return std::vector<unsigned int>();
   if(_execOutGoingPorts.empty())
     return std::vector<unsigned int>();
-  std::size_t sz(_execVals.size()); outputs.resize(sz); nameOfOutputs.resize(sz);
+  std::size_t sz(_execVals.size());
+  outputs.resize(sz);
+  nameOfOutputs.resize(sz);
   const std::vector<AnyInputPort *>& ports(_execOutGoingPorts[0]);
   for(std::size_t i=0;i<sz;i++)
     {
@@ -1192,3 +1205,69 @@ void ForEachLoop::assignPassedResults(const std::vector<unsigned int>& passedIds
   _passedData=new ForEachLoopPassedData(passedIds,passedOutputs,nameOfOutputs);
 }
 
+int ForEachLoop::getFEDeltaBetween(OutPort *start, InPort *end)
+{
+  Node *ns(start->getNode()),*ne(end->getNode());
+  ComposedNode *co(getLowestCommonAncestor(ns,ne));
+  int ret(0);
+  Node *work(ns);
+  while(work!=co)
+    {
+      ForEachLoop *isFE(dynamic_cast<ForEachLoop *>(work));
+      if(isFE)
+        ret++;
+      work=work->getFather();
+    }
+  if(dynamic_cast<AnySplitOutputPort *>(start))
+    ret--;
+  return ret;
+}
+
+/*!
+ * This method is used to obtain the values already processed by the ForEachLoop.
+ * A new ForEachLoopPassedData object is returned. You have to delete it.
+ */
+ForEachLoopPassedData* ForEachLoop::getProcessedData()const
+{
+  std::vector<SequenceAny *> outputs;
+  std::vector<std::string> nameOfOutputs;
+  if(_execVals.empty() || _execOutGoingPorts.empty())
+    return new ForEachLoopPassedData(std::vector<unsigned int>(), outputs, nameOfOutputs);
+  std::size_t sz(_execVals.size());
+  outputs.resize(sz);
+  nameOfOutputs.resize(sz);
+  const std::vector<AnyInputPort *>& ports(_execOutGoingPorts[0]);
+  for(std::size_t i=0;i<sz;i++)
+    {
+      outputs[i]=_execVals[i]->removeUnsetItemsFromThis();
+      nameOfOutputs[i]=ports[i]->getName();
+    }
+  return new ForEachLoopPassedData(_execVals[0]->getSetItems(), outputs, nameOfOutputs);
+}
+
+void ForEachLoop::setProcessedData(ForEachLoopPassedData* processedData)
+{
+  if(_passedData)
+    delete _passedData;
+  _passedData = processedData;
+}
+
+/*!
+ * \param portName : "interceptorized" name of port.
+ */
+const YACS::ENGINE::TypeCode* ForEachLoop::getOutputPortType(const std::string& portName)const
+{
+  const YACS::ENGINE::TypeCode* ret=NULL;
+  vector<AnySplitOutputPort *>::const_iterator it;
+  for(it=_outGoingPorts.begin();it!=_outGoingPorts.end() && ret==NULL;it++)
+  {
+    std::string originalPortName(getPortName(*it));
+    //InterceptorizeNameOfPort(originalPortName);
+    DEBTRACE("ForEachLoop::getOutputPortType compare " << portName << " == " << originalPortName);
+    if(originalPortName == portName)
+    {
+      ret = (*it)->edGetType()->contentType();
+    }
+  }
+  return ret;
+}
index f2cd2d10a957000d0fe2eb62926d0f071433a46b..54aa83aae4a5936818183c7e784a87a9f5ba8862 100644 (file)
@@ -127,6 +127,7 @@ namespace YACS
     {
     public:
       ForEachLoopPassedData(const std::vector<unsigned int>& passedIds, const std::vector<SequenceAny *>& passedOutputs, const std::vector<std::string>& nameOfOutputs);
+      ForEachLoopPassedData(const ForEachLoopPassedData& copy);
       ~ForEachLoopPassedData();
       void init();
       void checkCompatibilyWithNb(int nbOfElts) const;
@@ -136,6 +137,10 @@ namespace YACS
       int toAbsIdNot(int localId) const;
       int getNumberOfElementsToDo() const;
       void assignAlreadyDone(const std::vector<SequenceAny *>& execVals) const;
+      const std::vector<unsigned int>& getIds()const {return _passedIds;}
+      const std::vector<SequenceAny *>& getOutputs()const {return _passedOutputs;}
+      const std::vector<std::string>& getOutputNames()const {return _nameOfOutputs;}
+      //const std::vector<bool>& getFlags()const {return _flagsIds;}
     private:
       std::vector<unsigned int> _passedIds;
       std::vector<SequenceAny *> _passedOutputs;
@@ -195,10 +200,14 @@ namespace YACS
       std::list<ProgressWeight> getProgressWeight() const;
       int getCurrentIndex() const { return _currentIndex; }
       int getNbOfElementsToBeProcessed() const;
+      static int getFEDeltaBetween(OutPort *start, InPort *end);
 #ifndef SWIG
+      ForEachLoopPassedData* getProcessedData()const;
+      void setProcessedData(ForEachLoopPassedData* processedData);
       std::vector<unsigned int> getPassedResults(Executor *execut, std::vector<SequenceAny *>& outputs, std::vector<std::string>& nameOfOutputs) const;
       void assignPassedResults(const std::vector<unsigned int>& passedIds, const std::vector<SequenceAny *>& passedOutputs, const std::vector<std::string>& nameOfOutputs);
 #endif
+     const TypeCode* getOutputPortType(const std::string& portName)const;
     protected:
       Node *simpleClone(ComposedNode *father, bool editionOnly=true) const;
       void checkLinkPossibility(OutPort *start, const std::list<ComposedNode *>& pointsOfViewStart,
index fd7271cd038d62a00e18ec5b909e36ad156120e5..79d30fe6587729443d8034aab193ff925f5de3ac 100644 (file)
@@ -54,6 +54,52 @@ int ForkBlocPoint::getMaxLevelOfParallelism() const
   return ret;
 }
 
+double ForkBlocPoint::getWeightRegardingDPL() const
+{
+  double ret(0.);
+  for(std::list<AbstractPoint *>::const_iterator it=_nodes.begin();it!=_nodes.end();it++)
+    ret+=(*it)->getWeightRegardingDPL();
+  return ret;
+}
+
+void ForkBlocPoint::partitionRegardingDPL(const PartDefinition *pd, std::map<ComposedNode *, YACS::BASES::AutoRefCnt<PartDefinition> >& zeMap) const
+{
+  std::vector< std::pair<const PartDefinition *,double> > parts,parts2;
+  std::vector<std::size_t> v,v2;
+  std::size_t ii(0);
+  for(std::list<AbstractPoint *>::const_iterator it=_nodes.begin();it!=_nodes.end();it++,ii++)
+    {
+      double w((*it)->getWeightRegardingDPL());
+      if(w!=0.)
+        {
+          parts.push_back(std::pair<const PartDefinition *,double >(pd,w));
+          v.push_back(ii);
+        }
+      else
+        {
+          parts2.push_back(std::pair<const PartDefinition *,double >(pd,1.));
+          v2.push_back(ii);
+        }
+    }
+  std::vector<AbstractPoint *> nodes2(_nodes.begin(),_nodes.end());
+  if(!parts.empty())
+    {
+      const PlayGround *pg(pd->getPlayGround());
+      std::vector< YACS::BASES::AutoRefCnt<PartDefinition> > pds(pg->partition(parts));
+      ii=0;
+      for(std::vector<std::size_t>::const_iterator iter=v.begin();iter!=v.end();iter++,ii++)
+        nodes2[*iter]->partitionRegardingDPL(pds[ii],zeMap);
+    }
+  if(!parts2.empty())
+    {
+      const PlayGround *pg(pd->getPlayGround());
+      std::vector< YACS::BASES::AutoRefCnt<PartDefinition> > pds(pg->partition(parts2));
+      ii=0;
+      for(std::vector<std::size_t>::const_iterator iter=v2.begin();iter!=v2.end();iter++,ii++)
+        nodes2[*iter]->partitionRegardingDPL(pds[ii],zeMap);
+    }
+}
+
 std::string ForkBlocPoint::getRepr() const
 {
   std::size_t sz(_nodes.size()),ii(0);
index 97afd34e7c9789a9cd2573d5177e320ae19f0acc..0aa3fbf178b05c31cf0f5dfd94ec132a77e6cd3d 100644 (file)
@@ -34,6 +34,8 @@ namespace YACS
       Node *getFirstNode();
       Node *getLastNode();
       int getMaxLevelOfParallelism() const;
+      double getWeightRegardingDPL() const;
+      void partitionRegardingDPL(const PartDefinition *pd, std::map<ComposedNode *, YACS::BASES::AutoRefCnt<PartDefinition> >& zeMap) const;
       std::string getRepr() const;
       virtual ~ForkBlocPoint();
     };
index fbc0c3fb4081b2c5161f4fc64a324e8852706d31..641a0d32014d641fe7d317c6bbd79e36e76b1aab 100644 (file)
@@ -23,6 +23,7 @@
 #include "YACSlibEngineExport.hxx"
 #include "Exception.hxx"
 #include "Container.hxx"
+#include "PlayGround.hxx"
 
 #include <vector>
 
@@ -30,6 +31,8 @@ namespace YACS
 {
   namespace ENGINE
   {
+    class ForTestOmlyHPContCls;
+    
     /*!
      * This is an abstract class, that represents a set of fixed number of worker "kernelcontainers" homegenous in the sense that can be used indifferently each other.
      * But each of those worker pool can be used once at a time.
@@ -47,6 +50,12 @@ namespace YACS
       virtual std::size_t getNumberOfFreePlace() const = 0;
       virtual void allocateFor(const std::vector<const Task *>& nodes) = 0;
       virtual void release(const Task *node) = 0;
+      virtual YACS::BASES::AutoRefCnt<HomogeneousPoolContainer> decorate(YACS::BASES::AutoConstRefCnt<PartDefinition> pd) = 0;
+      virtual HomogeneousPoolContainer *getDirectFather() = 0;
+      virtual const HomogeneousPoolContainer *getDirectFather() const = 0;
+      virtual int getNumberOfCoresPerWorker() const = 0;
+      virtual void prepareMaskForExecution() const = 0;
+      virtual void forYourTestsOnly(ForTestOmlyHPContCls *data) const = 0;
       static const char SIZE_OF_POOL_KEY[];
       static const char INITIALIZE_SCRIPT_KEY[];
     protected:
index 213d74cee69e724ad7e29afd8227df568f4741e9..ce696f61805937e7fe9fdd35fb747a4372a4ac94 100644 (file)
@@ -20,6 +20,7 @@
 #include "InlineNode.hxx"
 #include "Visitor.hxx"
 #include "Container.hxx"
+#include "HomogeneousPoolContainer.hxx"
 #include <iostream>
 
 #define _DEVDEBUG_
@@ -156,3 +157,17 @@ int InlineNode::getMaxLevelOfParallelism() const
   return ret;
 }
 
+void InlineNode::partitionRegardingDPL(const PartDefinition *pd, std::map<ComposedNode *, YACS::BASES::AutoRefCnt<PartDefinition> >& zeMap)
+{
+  if(!isDeployable())
+    return ;
+  if(!_container)
+    return ;
+  HomogeneousPoolContainer *contC(dynamic_cast<HomogeneousPoolContainer *>(_container));
+  if(!contC)
+    return ;
+  YACS::BASES::AutoConstRefCnt<PartDefinition> zePd;
+  zePd.takeRef(pd);
+  YACS::BASES::AutoRefCnt<HomogeneousPoolContainer> zeCont(contC->decorate(zePd));
+  setContainer(zeCont);
+}
index cd63a222a1fcca4625a25fc9d571a2b0b433e9b1..c97af1c0df351a9fee56566cb1280a82af75afd0 100644 (file)
@@ -68,6 +68,7 @@ namespace YACS
       void performShallowDuplicationOfPlacement(const Node& other);
       bool isDeployable() const;
       int getMaxLevelOfParallelism() const;
+      void partitionRegardingDPL(const PartDefinition *pd, std::map<ComposedNode *, YACS::BASES::AutoRefCnt<PartDefinition> >& zeMap);
     public:
       static const char LOCAL_STR[];
       static const char REMOTE_STR[];
index 49f97a1c2965439fa6239e16357e3f06a0adeda1..666f757e5bbdbd809662c9b1e4ef7a829f2ce4b5 100644 (file)
@@ -48,6 +48,20 @@ int LinkedBlocPoint::getMaxLevelOfParallelism() const
   return ret;
 }
 
+double LinkedBlocPoint::getWeightRegardingDPL() const
+{
+  double ret(0.);
+  for(std::list<AbstractPoint *>::const_iterator it=_nodes.begin();it!=_nodes.end();it++)
+    ret=std::max(ret,(*it)->getWeightRegardingDPL());
+  return ret;
+}
+
+void LinkedBlocPoint::partitionRegardingDPL(const PartDefinition *pd, std::map<ComposedNode *, YACS::BASES::AutoRefCnt<PartDefinition> >& zeMap) const
+{
+  for(std::list<AbstractPoint *>::const_iterator it=_nodes.begin();it!=_nodes.end();it++)
+    (*it)->partitionRegardingDPL(pd,zeMap);
+}
+
 std::string LinkedBlocPoint::getRepr() const
 {
   std::size_t sz(_nodes.size()),ii(0);
index c56a4b04a907e124c4fa38c0c2ac33505ec0cfae..963ca24e02fb4515792ea9baf6d932de65bee3cd 100644 (file)
@@ -36,6 +36,8 @@ namespace YACS
       Node *getFirstNode();
       Node *getLastNode();
       int getMaxLevelOfParallelism() const;
+      double getWeightRegardingDPL() const;
+      void partitionRegardingDPL(const PartDefinition *pd, std::map<ComposedNode *, YACS::BASES::AutoRefCnt<PartDefinition> >& zeMap) const;
       std::string getRepr() const;
       virtual ~LinkedBlocPoint();
     };
index 53e6ff284811fcd1244c418defcb94e6a05c7ed9..cc4f089f96cb4f26f298f8d3ec891b39feedca7b 100644 (file)
@@ -419,6 +419,19 @@ int Loop::getMaxLevelOfParallelism() const
   return _node->getMaxLevelOfParallelism();
 }
 
+double Loop::getWeightRegardingDPL() const
+{
+  if(!_node)
+    return 0.;
+  return _node->getWeightRegardingDPL();
+}
+
+void Loop::partitionRegardingDPL(const PartDefinition *pd, std::map<ComposedNode *, YACS::BASES::AutoRefCnt<PartDefinition> >& zeMap)
+{
+  if(_node)
+    _node->partitionRegardingDPL(pd,zeMap);
+}
+
 Node *Loop::getChildByShortName(const std::string& name) const throw(YACS::Exception)
 {
   if (_node)
index dbe320cbe676194764f8104a7ac0a37792e74b94..a1f533af060104aa9bb84297bc7052cc9fd0a2b8 100644 (file)
@@ -173,6 +173,8 @@ namespace YACS
       std::list<InputPort *> getSetOfInputPort() const;
       int getNumberOfInputPorts() const;
       int getMaxLevelOfParallelism() const;
+      double getWeightRegardingDPL() const;
+      void partitionRegardingDPL(const PartDefinition *pd, std::map<ComposedNode *, YACS::BASES::AutoRefCnt<PartDefinition> >& zeMap);
       Node *getChildByShortName(const std::string& name) const throw(Exception);
       static TypeCode* MappingDF2DS(TypeCode* type) throw(Exception);
       static TypeCode* MappingDS2DF(TypeCode* type) throw(Exception);
index 0c633c86e549b1c87703e0362cd851d45e0eee85..aaa4ed21f164ffb3c01f89047f4bd193845918a5 100644 (file)
@@ -408,6 +408,22 @@ const Proc * Node::getProc() const
   return _father->getProc();
 }
 
+DynParaLoop *Node::getClosestDPLAmongAncestors() const
+{
+  if(!_father)
+    return NULL;
+  ComposedNode *iter(_father);
+  do
+    {
+      DynParaLoop *iter2(dynamic_cast<DynParaLoop *>(iter));
+      if(iter2)
+        return iter2;
+      iter=iter->_father;
+    }
+  while(iter);
+  return NULL;
+}
+
 ComposedNode *Node::getRootNode() const throw(YACS::Exception)
 {
   if(!_father)
index f7d4623940dc2f0449b62939f69bdb5bbde0a36a..f379204821a7677a3385eca4e2ad5619a28bc625 100644 (file)
@@ -21,6 +21,8 @@
 #define __NODE_HXX__
 
 #include "YACSlibEngineExport.hxx"
+#include "PlayGround.hxx"
+#include "AutoRefCnt.hxx"
 #include "InGate.hxx"
 #include "OutGate.hxx"
 #include "Exception.hxx"
@@ -42,8 +44,8 @@ namespace YACS
     class InputPort;
     class OutputPort;
     class InPropertyPort;
-    class DynParaLoop;
     class ForEachLoop;
+    class DynParaLoop;
     class ComposedNode;
     class Proc;
     class ElementaryNode;
@@ -161,6 +163,7 @@ namespace YACS
       bool operator>(const Node& other) const;
       bool operator<(const Node& other) const;
       std::string getImplementation() const;
+      DynParaLoop *getClosestDPLAmongAncestors() const;
       virtual ComposedNode *getRootNode() const throw(Exception);
       virtual void setProperty(const std::string& name,const std::string& value);
       virtual std::string getProperty(const std::string& name);
@@ -172,6 +175,8 @@ namespace YACS
       virtual const Proc *getProc() const;
       virtual void accept(Visitor *visitor) = 0;
       virtual int getMaxLevelOfParallelism() const = 0;
+      virtual double getWeightRegardingDPL() const = 0;
+      virtual void partitionRegardingDPL(const PartDefinition *pd, std::map<ComposedNode *, YACS::BASES::AutoRefCnt<PartDefinition> >& zeMap) = 0;
       std::string getQualifiedName() const;
       int getNumId();
       std::vector<std::pair<std::string,int> > getDPLScopeInfo(ComposedNode *gfn);
index eb382b69eed180370701bc7f8f9317175803cded..6f750852bf62ba6eb03baa56b1b75c8925bd700a 100644 (file)
@@ -42,7 +42,7 @@ namespace YACS
       virtual void checkConsistency(LinkInfo& info) const;
       virtual int edGetNumberOfOutLinks() const;
       virtual std::set<InPort *> edSetInPort() const = 0;
-      virtual bool isAlreadyLinkedWith(InPort *with) const = 0;
+      virtual bool isAlreadyLinkedWith(InPort *withp) const = 0;
       virtual void getAllRepresented(std::set<OutPort *>& represented) const;
       virtual bool addInPort(InPort *inPort) throw(Exception) = 0;
       virtual int removeInPort(InPort *inPort, bool forward) throw(Exception) = 0;
index 564d53f7f8490ee38fa894a6b76dee202a3d2539..8969e9c11b1292988993f6d2ff8f707ea25431f8 100644 (file)
@@ -47,7 +47,7 @@ namespace YACS
       virtual ~OutputDataStreamPort();
       virtual OutputDataStreamPort *clone(Node *newHelder) const;
       std::set<InPort *> edSetInPort() const;
-      bool isAlreadyLinkedWith(InPort *with) const;
+      bool isAlreadyLinkedWith(InPort *withp) const;
       virtual std::string getNameOfTypeOfCurrentInstance() const;
       virtual bool addInPort(InPort *inPort) throw(Exception);
       virtual bool edAddInputDataStreamPort(InputDataStreamPort *port) throw(ConversionException);
index 69dd1dc3550f01f4b0f581dc745d576734714991..f36fc8f9addc87aa8c29e9903e8b3e95b3fc7779 100644 (file)
@@ -50,7 +50,7 @@ namespace YACS
     public:
       virtual ~OutputPort();
       std::set<InPort *> edSetInPort() const;
-      bool isAlreadyLinkedWith(InPort *with) const;
+      bool isAlreadyLinkedWith(InPort *withp) const;
       bool isAlreadyInSet(InputPort *inputPort) const;
       bool isConnected() const;
       std::string getNameOfTypeOfCurrentInstance() const;
diff --git a/src/engine/PlayGround.cxx b/src/engine/PlayGround.cxx
new file mode 100644 (file)
index 0000000..bc96d9b
--- /dev/null
@@ -0,0 +1,635 @@
+// Copyright (C) 2006-2017  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 "PlayGround.hxx"
+#include "Runtime.hxx"
+
+#include <set>
+#include <map>
+#include <sstream>
+#include <iomanip>
+#include <numeric>
+#include <algorithm>
+
+using namespace YACS::ENGINE;
+
+std::string PlayGround::printSelf() const
+{
+  std::ostringstream oss;
+  std::size_t sz(0);
+  for(std::vector< std::pair<std::string,int> >::const_iterator it=_data.begin();it!=_data.end();it++)
+    sz=std::max(sz,(*it).first.length());
+  for(std::vector< std::pair<std::string,int> >::const_iterator it=_data.begin();it!=_data.end();it++)
+    {
+      oss << " - " << std::setw(10) << (*it).first << " : " << (*it).second << std::endl;
+    }
+  return oss.str();
+}
+
+void PlayGround::loadFromKernelCatalog()
+{
+  Runtime *r(getRuntime());
+  if(!r)
+    throw Exception("PlayGround::loadFromKernelCatalog : no runtime  !");
+  std::vector< std::pair<std::string,int> > data(r->getCatalogOfComputeNodes());
+  setData(data);
+}
+
+void PlayGround::setData(const std::vector< std::pair<std::string,int> >& defOfRes)
+{
+  _data=defOfRes;
+  checkCoherentInfo();
+}
+
+int PlayGround::getNumberOfCoresAvailable() const
+{
+  int ret(0);
+  for(std::vector< std::pair<std::string,int> >::const_iterator it=_data.begin();it!=_data.end();it++)
+    ret+=(*it).second;
+  return ret;
+}
+
+int PlayGround::getMaxNumberOfContainersCanBeHostedWithoutOverlap(int nbCoresPerCont) const
+{
+  if(nbCoresPerCont<1)
+    throw Exception("PlayGround::getMaxNumberOfContainersCanBeHostedWithoutOverlap : invalid nbCoresPerCont. Must be >=1 !");
+  int ret(0);
+  for(std::vector< std::pair<std::string,int> >::const_iterator it=_data.begin();it!=_data.end();it++)
+    ret+=(*it).second/nbCoresPerCont;
+  return ret;
+}
+
+std::vector<int> PlayGround::computeOffsets() const
+{
+  std::size_t sz(_data.size()),i(0);
+  std::vector<int> ret(sz+1); ret[0]=0;
+  for(std::vector< std::pair<std::string,int> >::const_iterator it=_data.begin();it!=_data.end();it++,i++)
+    ret[i+1]=ret[i]+(*it).second;
+  return ret;
+}
+
+void PlayGround::checkCoherentInfo() const
+{
+  std::set<std::string> s;
+  for(std::vector< std::pair<std::string,int> >::const_iterator it=_data.begin();it!=_data.end();it++)
+    {
+      s.insert((*it).first);
+      if((*it).second<0)
+        throw Exception("Presence of negative int value !");
+    }
+  if(s.size()!=_data.size())
+    throw Exception("host names entries must be different each other !");
+}
+
+std::vector<bool> PlayGround::FromUItoVB(unsigned int sz, unsigned int v)
+{
+  std::vector<bool> ret(sz);
+  unsigned int p(1);
+  for(std::size_t i=0;i<sz;i++)
+    {
+      ret[i]=p&v;
+      p<<=1;
+    }
+  return ret;
+}
+
+unsigned int PlayGround::FromVBtoUI(const std::vector<bool>& v)
+{
+  std::size_t sz(v.size());
+  unsigned int ret(0);
+  for(std::size_t i=0;i<sz;i++)
+    {
+      if(v[i])
+        ret+=1u<<i;
+    }
+  return ret;
+}
+
+std::vector<int> PlayGround::GetIdsMatching(const std::vector<bool>& bigArr, const std::vector<bool>& pat)
+{
+  std::vector<int> ret;
+  std::size_t szp(pat.size());
+  std::size_t sz(bigArr.size()/szp);
+  for(std::size_t i=0;i<sz;i++)
+    {
+      std::vector<bool> t(bigArr.begin()+i*szp,bigArr.begin()+(i+1)*szp);
+      if(t==pat)
+        ret.push_back(i);
+    }
+  return ret;
+}
+
+std::vector<int> PlayGround::BuildVectOfIdsFromVecBool(const std::vector<bool>& v)
+{
+  std::size_t sz(std::count(v.begin(),v.end(),true)),i(0);
+  std::vector<int> ret(sz);
+  std::vector<bool>::const_iterator it(v.begin());
+  while(i<sz)
+    {
+      it=std::find(it,v.end(),true);
+      ret[i++]=std::distance(v.begin(),it);
+      it++;
+    }
+  return ret;
+}
+
+void PlayGround::highlightOnIds(const std::vector<int>& coreIds, std::vector<bool>& v) const
+{
+  if(v.size()!=getNumberOfCoresAvailable())
+    throw Exception("PlayGround::highlightOnIds : oops ! invalid size !");
+  for(std::vector<int>::const_iterator it=coreIds.begin();it!=coreIds.end();it++)
+    v[*it]=true;
+}
+
+/*! 
+ * you must garantee coherence between PlayGround::deduceMachineFrom, PlayGround::getNumberOfWorkers, and PartDefinition::computeWorkerIdsCovered
+ */
+std::vector<bool> PlayGround::getFetchedCores(int nbCoresPerWorker) const
+{
+  int nbCores(getNumberOfCoresAvailable());
+  std::vector<bool> ret(nbCores,false);
+  if(nbCoresPerWorker==1)
+    std::fill(ret.begin(),ret.end(),true);
+  else
+    {
+      std::size_t posBg(0);
+      for(std::vector< std::pair<std::string,int> >::const_iterator it=_data.begin();it!=_data.end();it++)
+        {
+          int nbElemsToPutOn(((*it).second/nbCoresPerWorker)*nbCoresPerWorker);
+          std::fill(ret.begin()+posBg,ret.begin()+posBg+nbElemsToPutOn,true);
+          posBg+=(*it).second;
+        }
+    }
+  return ret;
+}
+/*!
+ * follow getMaxNumberOfContainersCanBeHostedWithoutOverlap method
+ */
+std::vector<std::size_t> PlayGround::getWorkerIdsFullyFetchedBy(int nbCoresPerComp, const std::vector<bool>& coreFlags) const
+{
+  std::size_t posBg(0),posWorker(0);
+  std::vector<std::size_t> ret;
+  for(std::vector< std::pair<std::string,int> >::const_iterator it=_data.begin();it!=_data.end();it++)
+    {
+      int nbWorker((*it).second/nbCoresPerComp);
+      for(int j=0;j<nbWorker;j++,posWorker++)
+        {
+          std::vector<bool>::const_iterator it2(std::find(coreFlags.begin()+posBg+j*nbCoresPerComp,coreFlags.begin()+posBg+(j+1)*nbCoresPerComp,false));
+          if(it2==coreFlags.begin()+posBg+(j+1)*nbCoresPerComp)
+            ret.push_back(posWorker);
+        }
+      posBg+=(*it).second;
+    }
+  return ret;
+}
+
+std::vector< YACS::BASES::AutoRefCnt<PartDefinition> > PlayGround::partition(const std::vector< std::pair<const PartDefinition *,double> >& parts) const
+{
+  std::size_t sz(parts.size()),szs(getNumberOfCoresAvailable());
+  if(sz==0)
+    return std::vector< YACS::BASES::AutoRefCnt<PartDefinition> >();
+  if(sz==1)
+    {
+      const PartDefinition *pd(parts[0].first);
+      if(!pd)
+        throw Exception("Presence of null pointer as part def  0 !");
+      YACS::BASES::AutoRefCnt<PartDefinition> ret(pd->copy());
+      std::vector< YACS::BASES::AutoRefCnt<PartDefinition> > ret2(1,ret);
+      return ret2;
+    }
+  if(sz>31)
+    throw Exception("PlayGround::partition : not implemented yet for more than 31 ! You need to pay for it :)");
+  std::vector<bool> zeArr(szs*sz,false);
+  std::size_t i(0);
+  for(std::vector< std::pair<const PartDefinition *,double> >::const_iterator it=parts.begin();it!=parts.end();it++,i++)
+    {
+      const PartDefinition *pd((*it).first);
+      if(!pd)
+        throw Exception("Presence of null pointer as part def !");
+      if(pd->getPlayGround()!=this)
+        throw Exception("Presence of non homogeneous playground !");
+      if((*it).second<=0.)
+        throw Exception("Invalid weight !");
+      std::vector<bool> bs(pd->getCoresOn());
+      for(std::size_t j=0;j<szs;j++)
+        zeArr[j*sz+i]=bs[j];
+    }
+  std::set<unsigned int> ss;
+  for(std::size_t i=0;i<szs;i++)
+    {
+      std::vector<bool> vb(zeArr.begin()+i*sz,zeArr.begin()+(i+1)*sz);
+      ss.insert(FromVBtoUI(vb));
+    }
+  std::vector< std::vector<int> > retIds(sz);
+  for(std::set<unsigned int>::const_iterator i=ss.begin();i!=ss.end();i++)
+    {
+      std::vector<bool> code(FromUItoVB(sz,*i));// for this configuration which parts are considered
+      std::vector<int> locIds(GetIdsMatching(zeArr,code));
+      std::vector<int> partsIds(BuildVectOfIdsFromVecBool(code));
+      if(partsIds.empty())
+        continue;
+      std::vector<double> wg;
+      std::vector<int> nbCores2;
+      for(std::vector<int>::const_iterator it=partsIds.begin();it!=partsIds.end();it++)
+        {
+          wg.push_back(parts[*it].second);
+          nbCores2.push_back(parts[*it].first->getNbCoresPerCompo());
+        }
+      std::vector< std::vector<int> > ress(splitIntoParts(locIds,nbCores2,wg));
+      std::size_t k(0);
+      for(std::vector<int>::const_iterator it=partsIds.begin();it!=partsIds.end();it++,k++)
+        {
+          retIds[*it].insert(retIds[*it].end(),ress[k].begin(),ress[k].end());
+        }
+    }
+  //
+  std::vector< YACS::BASES::AutoRefCnt<PartDefinition> > ret(sz);
+  for(std::size_t i=0;i<sz;i++)
+    {
+      std::set<int> s(retIds[i].begin(),retIds[i].end());
+      std::vector<int> v(s.begin(),s.end());
+      ret[i]=PartDefinition::BuildFrom(this,(parts[i].first)->getNbCoresPerCompo(),v);
+    }
+  return ret;
+}
+
+std::vector<int> sortArr(const std::vector<int>& v)
+{
+  std::multimap<int,int> m;
+  int i(v.size()-1);
+  for(std::vector<int>::const_reverse_iterator it=v.rbegin();it!=v.rend();it++)
+    m.insert(std::pair<int,int>(*it,i--));
+  std::vector<int> ret(m.size());
+  i=0;
+  for(std::multimap<int,int>::const_reverse_iterator it=m.rbegin();it!=m.rend();it++)// reverse -> sort from biggest to the finest
+    ret[i++]=(*it).second;
+  return ret;
+}
+
+std::vector< std::vector<int> > PlayGround::splitIntoParts(const std::vector<int>& coreIds, const std::vector<int>& nbCoresConso, const std::vector<double>& weights) const
+{
+  double wgs(std::accumulate(weights.begin(),weights.end(),0.));
+  std::size_t sz(nbCoresConso.size());
+  if(sz!=weights.size())
+    throw Exception("PlayGround::splitIntoParts : internal error !");
+  if(sz==0)
+    return std::vector< std::vector<int> >();
+  int totalSpace(coreIds.size());
+  std::vector< std::vector<int> > ret(sz);
+  std::vector<int> fromBigToTiny(sortArr(nbCoresConso));// start to treat the coarse grain to finish with fine grain
+  std::vector<bool> zeArr(getNumberOfCoresAvailable(),false);
+  highlightOnIds(coreIds,zeArr);
+  int nbOfCoresToSplit(coreIds.size());
+  std::size_t ii(fromBigToTiny.size());
+  for(std::vector<int>::const_iterator it=fromBigToTiny.begin();it!=fromBigToTiny.end();it++,ii--)
+    {
+      int maxNbOfCores((int)(totalSpace*weights[*it]/wgs));// now try to find in zeArr at most maxNbOfCores cores
+      ret[*it]=takePlace(maxNbOfCores,nbCoresConso[*it],zeArr,ii==1);
+    }
+  return ret;
+}
+
+std::vector<int> PlayGround::takePlace(int maxNbOfCoresToAlloc, int nbCoresPerShot, std::vector<bool>& distributionOfCores, bool lastOne) const
+{
+  if(maxNbOfCoresToAlloc<1)
+    throw Exception("PlayGround::takePlace : internal error ! no space to alloc !");
+  int tmpMaxNbOfCoresToAlloc(maxNbOfCoresToAlloc);
+  if(lastOne)
+    tmpMaxNbOfCoresToAlloc=std::max(tmpMaxNbOfCoresToAlloc,(int)std::count(distributionOfCores.begin(),distributionOfCores.end(),true));
+  std::vector<int> ret;
+  std::vector<int> offsets(computeOffsets());
+  int nbFullItem(0);
+  std::size_t sz(offsets.size()-1);
+  for(std::size_t i=0;i<sz && tmpMaxNbOfCoresToAlloc>=nbCoresPerShot;i++)
+    {
+      int d(offsets[i+1]-offsets[i]);
+      if(nbCoresPerShot>d)
+        continue;
+      std::vector<bool> target(nbCoresPerShot,true);
+      for(int j=0;j<=d-nbCoresPerShot && tmpMaxNbOfCoresToAlloc>=nbCoresPerShot;)
+        {
+          std::vector<bool> t(distributionOfCores.begin()+offsets[i]+j,distributionOfCores.begin()+offsets[i]+j+nbCoresPerShot);
+          if(t==target)
+            {
+              nbFullItem++;
+              tmpMaxNbOfCoresToAlloc-=nbCoresPerShot;
+              std::fill(distributionOfCores.begin()+offsets[i]+j,distributionOfCores.begin()+offsets[i]+j+nbCoresPerShot,false);
+              for(int k=offsets[i]+j;k<offsets[i]+j+nbCoresPerShot;k++)
+                ret.push_back(k);
+              j+=nbCoresPerShot;
+            }
+          else
+            j++;
+        }
+    }
+  if(nbFullItem>0)
+    return ret;
+  if(nbCoresPerShot<=1)
+    throw Exception("PlayGround::takePlace : internal error !");
+  // not enough contiguous place. Find the first wider contiguous place
+  for(int kk=std::min(nbCoresPerShot-1,tmpMaxNbOfCoresToAlloc);kk>=1;kk--)
+    {
+      for(std::size_t i=0;i<sz && tmpMaxNbOfCoresToAlloc>=kk;i++)
+        {
+          int d(offsets[i+1]-offsets[i]);
+          if(kk>d)
+            continue;
+          std::vector<bool> target(kk,true);
+          for(int j=0;j<=d-kk && tmpMaxNbOfCoresToAlloc>=kk;)
+            {
+              std::vector<bool> t(distributionOfCores.begin()+offsets[i]+j,distributionOfCores.begin()+offsets[i]+j+kk);
+              if(t==target)
+                {
+                  nbFullItem++;
+                  tmpMaxNbOfCoresToAlloc-=kk;
+                  std::fill(distributionOfCores.begin()+offsets[i]+j,distributionOfCores.begin()+offsets[i]+j+kk,false);
+                  for(int k=offsets[i]+j;k<offsets[i]+j+kk;k++)
+                    ret.push_back(k);
+                  return ret;
+                }
+              else
+                j++;
+            }
+        }
+    }
+  throw Exception("PlayGround::takePlace : internal error ! All cores are occupied !");
+}
+
+int PlayGround::fromWorkerIdToResId(int workerId, int nbProcPerNode) const
+{
+  std::size_t sz2(_data.size());
+  std::vector<int> deltas(sz2+1); deltas[0]=0;
+  for(std::size_t i=0;i<sz2;i++)
+    deltas[i+1]=deltas[i]+(_data[i].second)/nbProcPerNode;
+  int zePos(0);
+  while(zePos<sz2 && (workerId<deltas[zePos] || workerId>=deltas[zePos+1]))
+    zePos++;
+  if(zePos==sz2)
+    zePos=workerId%sz2;
+  return zePos;
+}
+
+/*! 
+ * you must garantee coherence between PlayGround::deduceMachineFrom, PlayGround::getNumberOfWorkers, and PartDefinition::computeWorkerIdsCovered
+ */
+std::string PlayGround::deduceMachineFrom(int workerId, int nbProcPerNode) const
+{
+  int zePos(fromWorkerIdToResId(workerId,nbProcPerNode));
+  return _data[zePos].first;
+}
+
+/*! 
+ * you must garantee coherence between PlayGround::deduceMachineFrom, PlayGround::getNumberOfWorkers, PlayGround::getFetchedCores and PartDefinition::computeWorkerIdsCovered
+ */
+int PlayGround::getNumberOfWorkers(int nbCoresPerWorker) const
+{
+  return getMaxNumberOfContainersCanBeHostedWithoutOverlap(nbCoresPerWorker);
+}
+
+PlayGround::~PlayGround()
+{
+}
+
+//////////////////////
+
+PartDefinition::PartDefinition(const PlayGround *pg, int nbOfCoresPerComp):_nbOfCoresPerComp(nbOfCoresPerComp)
+{
+  _pg.takeRef(pg);
+}
+
+PartDefinition::PartDefinition(const PartDefinition& other):_pg(other._pg),_nbOfCoresPerComp(other._nbOfCoresPerComp)
+{
+}
+
+PartDefinition::~PartDefinition()
+{
+}
+
+std::vector< YACS::BASES::AutoRefCnt<PartDefinition> > PartDefinition::partition(const std::vector< double >& wgs) const
+{
+  std::size_t sz(wgs.size());
+  std::vector< std::pair<const PartDefinition *,double> > elts(sz);
+  for(std::size_t i=0;i<sz;i++)
+    elts[i]=std::pair<const PartDefinition *,double>(this,wgs[i]);
+  return getPlayGround()->partition(elts);
+}
+
+YACS::BASES::AutoRefCnt<PartDefinition> PartDefinition::BuildFrom(const PlayGround *pg, int nbOfCoresPerComp, const std::vector<int>& coreIds)
+{
+  int spaceSz(pg->getNumberOfCoresAvailable()),sz(coreIds.size());
+  if(sz>spaceSz)
+    throw Exception("PartDefinition::BuildFrom : error 1 !");
+  if(sz==0)
+    throw Exception("PartDefinition::BuildFrom : error 2 !");
+  int zeStart(coreIds.front()),zeEnd(coreIds.back());
+  if(zeStart<0 || zeEnd<zeStart)
+    throw Exception("PartDefinition::BuildFrom : error ! The content of core Ids is not OK !");
+  for(std::size_t i=0;i<sz-1;i++)
+    if(coreIds[i+1]<coreIds[i])
+      throw Exception("PartDefinition::BuildFrom : error ! The content of core Ids is not OK 2 !");
+  if(zeEnd-zeStart+1!=sz)
+    {
+      YACS::BASES::AutoRefCnt<PartDefinition> pd(new NonContigPartDefinition(pg,nbOfCoresPerComp,coreIds));
+      return pd;
+    }
+  if(sz==spaceSz)
+    {
+      YACS::BASES::AutoRefCnt<PartDefinition> pd(new AllPartDefinition(pg,nbOfCoresPerComp));
+      return pd;
+    }
+  YACS::BASES::AutoRefCnt<PartDefinition> pd(new ContigPartDefinition(pg,nbOfCoresPerComp,zeStart,zeEnd+1));
+  return pd;
+}
+
+void PartDefinition::stashPart(int nbCoresStashed, double weightOfRemain, YACS::BASES::AutoRefCnt<PartDefinition>& pdStashed, YACS::BASES::AutoRefCnt<PartDefinition>& pdRemain) const
+{
+  if(nbCoresStashed<=0)
+    throw Exception("stashPart : Invalid nbCoresStashed value !");
+  if(weightOfRemain<=0.)
+    throw Exception("stashPart : Invalid weight !");
+  std::vector<bool> coresOn(getCoresOn());
+  int nbCoresAvailable(std::count(coresOn.begin(),coresOn.end(),true));
+  std::vector<int> ids(PlayGround::BuildVectOfIdsFromVecBool(coresOn));
+  if(nbCoresAvailable==0)
+    throw Exception("PartDefinition::stashPart : no available cores !");
+  if(nbCoresAvailable<=nbCoresStashed)
+    {
+      int n0((int)(1./(1.+weightOfRemain)*nbCoresAvailable)); n0=std::max(n0,1);
+      int n1(nbCoresAvailable-n0);
+      if(n1<=0)
+        {
+          pdStashed=PartDefinition::BuildFrom(getPlayGround(),1,ids);
+          pdRemain=PartDefinition::BuildFrom(getPlayGround(),1,ids);
+        }
+      else
+        {
+          std::vector<int> ids0(ids.begin(),ids.begin()+n0),ids1(ids.begin()+n0,ids.end());
+          pdStashed=PartDefinition::BuildFrom(getPlayGround(),1,ids0);
+          pdRemain=PartDefinition::BuildFrom(getPlayGround(),1,ids1);
+        }
+    }
+  else
+    {
+      std::vector<int> ids0(ids.begin(),ids.begin()+nbCoresStashed),ids1(ids.begin()+nbCoresStashed,ids.end());
+      pdStashed=PartDefinition::BuildFrom(getPlayGround(),1,ids0);
+      pdRemain=PartDefinition::BuildFrom(getPlayGround(),1,ids1);
+    }
+}
+
+/*! 
+ * you must garantee coherence between PlayGround::deduceMachineFrom, PlayGround::getNumberOfWorkers, and PartDefinition::computeWorkerIdsCovered
+ */
+std::vector<std::size_t> PartDefinition::computeWorkerIdsCovered(int nbCoresPerComp) const
+{
+  std::vector<bool> coresOn(getCoresOn());
+  return _pg->getWorkerIdsFullyFetchedBy(nbCoresPerComp,coresOn);
+}
+
+//////////////////////
+
+ContigPartDefinition::ContigPartDefinition(const PlayGround *pg, int nbOfCoresPerComp, int zeStart, int zeStop):PartDefinition(pg,nbOfCoresPerComp),_start(zeStart),_stop(zeStop)
+{
+  if(_start<0 || _stop<_start || _stop>getSpaceSize())
+    throw Exception("ContigPartDefinition constructor : Invalid input values");
+}
+
+ContigPartDefinition::ContigPartDefinition(const ContigPartDefinition& other):PartDefinition(other),_start(other._start),_stop(other._stop)
+{
+}
+
+std::string ContigPartDefinition::printSelf() const
+{
+  std::ostringstream oss;
+  oss << "Contiguous : start=" << _start << " stop=" << _stop;
+  return oss.str();
+}
+
+std::vector<bool> ContigPartDefinition::getCoresOn() const
+{
+  std::vector<bool> ret(getSpaceSize(),false);
+  for(int i=_start;i<_stop;i++)
+    ret[i]=true;
+  return ret;
+}
+
+ContigPartDefinition *ContigPartDefinition::copy() const
+{
+  return new ContigPartDefinition(*this);
+}
+
+int ContigPartDefinition::getNumberOfCoresConsumed() const
+{
+  return _stop-_start;
+}
+
+//////////////////////
+
+NonContigPartDefinition::NonContigPartDefinition(const PlayGround *pg, int nbOfCoresPerComp, const std::vector<int>& ids):PartDefinition(pg,nbOfCoresPerComp),_ids(ids)
+{
+  checkOKIds();
+}
+
+NonContigPartDefinition::NonContigPartDefinition(const ContigPartDefinition& other):PartDefinition(other)
+{
+}
+
+std::string NonContigPartDefinition::printSelf() const
+{
+  std::ostringstream oss;
+  oss << "Non contiguous : ";
+  for(std::vector<int>::const_iterator it=_ids.begin();it!=_ids.end();it++)
+    oss << *it << ", ";
+  return oss.str();
+}
+
+std::vector<bool> NonContigPartDefinition::getCoresOn() const
+{
+  std::vector<bool> ret(getSpaceSize(),false);
+  for(std::vector<int>::const_iterator it=_ids.begin();it!=_ids.end();it++)
+    ret[*it]=true;
+  return ret;
+}
+
+NonContigPartDefinition *NonContigPartDefinition::copy() const
+{
+  return new NonContigPartDefinition(*this);
+}
+
+int NonContigPartDefinition::getNumberOfCoresConsumed() const
+{
+  return _ids.size();
+}
+
+void NonContigPartDefinition::checkOKIds() const
+{
+  int maxVal(getSpaceSize());
+  if(_ids.empty())
+    return;
+  int val(_ids.front());
+  if(val<0 || val>=maxVal)
+    throw Exception("checkOKIds : error 2 !");
+  std::size_t sz(_ids.size());
+  for(std::size_t i=0;i<sz-1;i++)
+    {
+      if(_ids[i+1]<=_ids[i])
+        throw Exception("checkOKIds : error 1 !");
+      if(_ids[i+1]>=maxVal)
+        throw Exception("checkOKIds : error 3 !");
+    }
+}
+
+//////////////////////
+
+AllPartDefinition::AllPartDefinition(const AllPartDefinition& other):PartDefinition(other)
+{
+}
+
+std::string AllPartDefinition::printSelf() const
+{
+  std::ostringstream oss;
+  oss << "All";
+  return oss.str();
+}
+
+std::vector<bool> AllPartDefinition::getCoresOn() const
+{
+  std::vector<bool> ret(getSpaceSize(),true);
+  return ret;
+}
+
+AllPartDefinition *AllPartDefinition::copy() const
+{
+  return new AllPartDefinition(*this);
+}
+
+int AllPartDefinition::getNumberOfCoresConsumed() const
+{
+  return getSpaceSize();
+}
+
+//////////////////////
+ std::vector<int> ForTestOmlyHPContCls::getIDS() const
+ {
+   std::size_t sz(_ids.size());
+   std::vector<int> ret(sz);
+   for(std::size_t i=0;i<sz;i++)
+     ret[i]=_ids[i];
+   return ret;
+ }
diff --git a/src/engine/PlayGround.hxx b/src/engine/PlayGround.hxx
new file mode 100644 (file)
index 0000000..b695e65
--- /dev/null
@@ -0,0 +1,162 @@
+// Copyright (C) 2006-2017  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
+//
+
+#ifndef __PLAYGROUND_HXX__
+#define __PLAYGROUND_HXX__
+
+#include "YACSlibEngineExport.hxx"
+#include "RefCounter.hxx"
+#include "AutoRefCnt.hxx"
+
+#include <vector>
+#include <string>
+
+namespace YACS
+{
+  namespace ENGINE
+  {
+    class PartDefinition;
+    
+    class YACSLIBENGINE_EXPORT PlayGround : public RefCounter
+    {
+    public:
+      PlayGround(const std::vector< std::pair<std::string,int> >& defOfRes):_data(defOfRes) { checkCoherentInfo(); }
+      PlayGround() { }
+      std::string printSelf() const;
+      void loadFromKernelCatalog();
+      std::vector< std::pair<std::string,int> > getData() const { return _data; }
+      void setData(const std::vector< std::pair<std::string,int> >& defOfRes);
+      int getNumberOfCoresAvailable() const;
+      int getMaxNumberOfContainersCanBeHostedWithoutOverlap(int nbCoresPerCont) const;
+      std::vector<int> computeOffsets() const;
+      std::vector< YACS::BASES::AutoRefCnt<PartDefinition> > partition(const std::vector< std::pair<const PartDefinition *,double> >& parts) const;
+      int fromWorkerIdToResId(int workerId, int nbProcPerNode) const;
+      std::string deduceMachineFrom(int workerId, int nbProcPerNode) const;
+      int getNumberOfWorkers(int nbCoresPerWorker) const;
+      void highlightOnIds(const std::vector<int>& coreIds, std::vector<bool>& v) const;
+      std::vector<bool> getFetchedCores(int nbCoresPerWorker) const;
+      std::vector<std::size_t> getWorkerIdsFullyFetchedBy(int nbCoresPerComp, const std::vector<bool>& coreFlags) const;
+      static std::vector<int> BuildVectOfIdsFromVecBool(const std::vector<bool>& v);
+      static std::vector<int> GetIdsMatching(const std::vector<bool>& bigArr, const std::vector<bool>& pat);
+      static std::vector<bool> FromUItoVB(unsigned int sz, unsigned int v);
+      static unsigned int FromVBtoUI(const std::vector<bool>& v);
+    private:
+      std::vector< std::vector<int> > splitIntoParts(const std::vector<int>& coreIds, const std::vector<int>& nbCoresConso, const std::vector<double>& weights) const;
+      std::vector<int> takePlace(int maxNbOfCoresToAlloc, int nbCoresPerShot, std::vector<bool>& distributionOfCores, bool lastOne=false) const;
+    private:
+      void checkCoherentInfo() const;
+    private:
+      ~PlayGround();
+    private:
+      std::vector< std::pair<std::string,int> > _data;
+    };
+
+    class YACSLIBENGINE_EXPORT PartDefinition : public RefCounter
+    {
+    protected:
+      PartDefinition(const PlayGround *pg, int nbOfCoresPerComp);
+      PartDefinition(const PartDefinition& other);
+      virtual ~PartDefinition();
+    public:
+      std::vector< YACS::BASES::AutoRefCnt<PartDefinition> > partition(const std::vector< double >& wgs) const;
+      static YACS::BASES::AutoRefCnt<PartDefinition> BuildFrom(const PlayGround *pg, int nbOfCoresPerComp, const std::vector<int>& coreIds);
+      const PlayGround *getPlayGround() const { return _pg; }
+      int getNbCoresPerCompo() const { return _nbOfCoresPerComp; }
+      void setNbCoresPerCompo(int newNbCores) { _nbOfCoresPerComp=newNbCores; }
+      int getSpaceSize() const { return _pg->getNumberOfCoresAvailable(); }
+      void stashPart(int nbCoresStashed, double weightOfRemain, YACS::BASES::AutoRefCnt<PartDefinition>& pdStashed, YACS::BASES::AutoRefCnt<PartDefinition>& pdRemain) const;
+      std::vector<std::size_t> computeWorkerIdsCovered(int nbCoresPerComp) const;
+      virtual std::string printSelf() const = 0;
+      virtual std::vector<bool> getCoresOn() const = 0;
+      virtual PartDefinition *copy() const = 0;
+      virtual int getNumberOfCoresConsumed() const = 0;
+    private:
+      YACS::BASES::AutoConstRefCnt<PlayGround> _pg;
+      int _nbOfCoresPerComp;
+    };
+
+    class YACSLIBENGINE_EXPORT ContigPartDefinition : public PartDefinition
+    {
+    public:
+      ContigPartDefinition(const PlayGround *pg, int nbOfCoresPerComp, int zeStart, int zeStop);
+      ContigPartDefinition(const ContigPartDefinition& other);
+      std::string printSelf() const;
+      std::vector<bool> getCoresOn() const;
+      int getStart() const { return _start; }
+      int getStop() const { return _stop; }
+      ContigPartDefinition *copy() const;
+      int getNumberOfCoresConsumed() const;
+    private:
+      ~ContigPartDefinition() { }
+    private:
+      int _start;
+      int _stop;
+    };
+
+    class YACSLIBENGINE_EXPORT NonContigPartDefinition : public PartDefinition
+    {
+    public:
+      NonContigPartDefinition(const PlayGround *pg, int nbOfCoresPerComp, const std::vector<int>& ids);
+      NonContigPartDefinition(const ContigPartDefinition& other);
+      std::string printSelf() const;
+      std::vector<bool> getCoresOn() const;
+      std::vector<int> getIDs() const { return _ids; }
+      NonContigPartDefinition *copy() const;
+      int getNumberOfCoresConsumed() const;
+    private:
+      void checkOKIds() const;
+      ~NonContigPartDefinition() { }
+    private:
+      std::vector<int> _ids;
+    };
+      
+    class AllPartDefinition : public PartDefinition
+    {
+    public:
+      AllPartDefinition(const PlayGround *pg, int nbOfCoresPerComp):PartDefinition(pg,nbOfCoresPerComp) { }
+      AllPartDefinition(const AllPartDefinition& other);
+      std::string printSelf() const;
+      std::vector<bool> getCoresOn() const;
+      AllPartDefinition *copy() const;
+      int getNumberOfCoresConsumed() const;
+    private:
+      ~AllPartDefinition() { }
+    };
+
+    class ForTestOmlyHPContCls
+    {
+    public:
+
+#ifndef SWIG
+      void setContainerType(const std::string& ct) { _container_type=ct; }
+      void setPD(YACS::BASES::AutoConstRefCnt<PartDefinition> pd) { _pd=pd; }
+      void setIDS(const std::vector<std::size_t>& ids) { _ids=ids; }
+#endif
+      std::string getContainerType() const { return _container_type; }
+      const PartDefinition *getPD() const { return _pd; }
+      std::vector<int> getIDS() const;
+    private:
+      std::string _container_type;
+      YACS::BASES::AutoConstRefCnt<PartDefinition> _pd;
+      std::vector<std::size_t> _ids;
+    };
+  }
+}
+
+#endif
index f2a7ea96c34b0ed8b1db6baf53466a82dc2d33cd..95cc82d5700c1c0350482f8cbefdc6ab7543d46c 100644 (file)
@@ -98,6 +98,8 @@ namespace YACS
       virtual void setEdition(bool edition);
       virtual void modified();
       virtual void saveSchema(const std::string& xmlSchemaFile);
+      //! deprecated. See VisitorSalomeSaveState and schemaSaveState in order
+      //! to deal with the execution state of ForEachLoop.
       virtual void saveState(const std::string& xmlStateFile);
     protected:
       void removeContainers();
index 7c4c89279a8b76254df01c2ceceb8feb3562a795..c75e473fea42bb232a33057a902509e67d7e5858 100644 (file)
@@ -45,7 +45,7 @@ void RefCounter::incrRef() const
   _globalMutexForTS.unLock();
 }
 
-bool RefCounter::decrRef()
+bool RefCounter::decrRef() const
 {
   _globalMutexForTS.lock();
 #ifdef REFCNT
index 989911561eca2ba054d7bb90411f549817bb26fe..90401e8c536ce42d9f7c8ea17bd6dd9b1718de95 100644 (file)
@@ -31,7 +31,7 @@ namespace YACS
     public:
       unsigned int getRefCnt() const { return _cnt; }
       void incrRef() const;
-      bool decrRef();
+      bool decrRef() const;
       static unsigned int _totalCnt;
     protected:
       RefCounter();
index 91745b68dfb7c06e9bd46f293fb5b6250d3d45eb..749eaf2321de06ffa86e065b7c48b37c443ee5b2 100644 (file)
@@ -70,7 +70,7 @@ namespace YACS
     public:
       virtual void init() { }
       virtual void fini() { }
-
+      virtual std::vector< std::pair<std::string,int> > getCatalogOfComputeNodes() const = 0;
       virtual Catalog* loadCatalog(const std::string& sourceKind,const std::string& path);
       virtual InlineFuncNode* createFuncNode(const std::string& kind,const std::string& name);
       virtual InlineNode* createScriptNode(const std::string& kind,const std::string& name);
index 148930b5dc2ecdf1a8e9fb69a3ca33fdd5ca200b..e869b88ca2ad2695635005ffceaad6cd76f7527b 100644 (file)
@@ -86,3 +86,18 @@ int SetOfPoints::getMaxLevelOfParallelism() const
 {
   return _bp->getMaxLevelOfParallelism();
 }
+
+double SetOfPoints::getWeightRegardingDPL() const
+{
+  return _bp->getWeightRegardingDPL();
+}
+
+void SetOfPoints::partitionRegardingDPL(const PartDefinition *pd, std::map<ComposedNode *, YACS::BASES::AutoRefCnt<PartDefinition> >& zeMap) const
+{
+  _bp->partitionRegardingDPL(pd,zeMap);
+}
+
+AbstractPoint *SetOfPoints::getUniqueAndReleaseIt() const
+{
+  return _bp->getUniqueAndReleaseIt();
+}
index b4fd278bf1cf6ea2f295ade85b1700a2c3ecb6bd..d670ff692dc0c697f5335ad7a0e6398a3fc7cfc8 100644 (file)
 #define __SETOFPOINTS_HXX__
 
 #include "YACSlibEngineExport.hxx"
+#include "PlayGround.hxx"
+#include "AutoRefCnt.hxx"
 
+#include <map>
 #include <list>
 #include <string>
 
@@ -32,7 +35,8 @@ namespace YACS
     class Node;
     class BagPoint;
     class AbstractPoint;
-
+    class ComposedNode;
+    
     class YACSLIBENGINE_EXPORT SetOfPoints
     {
     public:
@@ -43,6 +47,9 @@ namespace YACS
       AbstractPoint *findPointWithNode(Node *node);
       const std::list<AbstractPoint *>& getListOfPoints() const;
       int getMaxLevelOfParallelism() const;
+      double getWeightRegardingDPL() const;
+      void partitionRegardingDPL(const PartDefinition *pd, std::map<ComposedNode *, YACS::BASES::AutoRefCnt<PartDefinition> >& zeMap) const;
+      AbstractPoint *getUniqueAndReleaseIt() const;
     private:
       BagPoint *_bp;
     };
index a65e8425f49ca0d0b1c540a90491ee80a84888ca..5c0b7a2d85cff08f0ad5489a6b2c4ddc82deea6a 100644 (file)
@@ -408,6 +408,20 @@ int Switch::getMaxLevelOfParallelism() const
   return ret;
 }
 
+double Switch::getWeightRegardingDPL() const
+{
+  double ret(0);
+  for(std::map< int , Node * >::const_iterator it=_mapOfNode.begin();it!=_mapOfNode.end();it++)
+    ret=std::max(ret,((*it).second)->getWeightRegardingDPL());
+  return ret;
+}
+
+void Switch::partitionRegardingDPL(const PartDefinition *pd, std::map<ComposedNode *, YACS::BASES::AutoRefCnt<PartDefinition> >& zeMap)
+{
+  for(std::map< int , Node * >::const_iterator it=_mapOfNode.begin();it!=_mapOfNode.end();it++)
+    (*it).second->partitionRegardingDPL(pd,zeMap);
+}
+
 void Switch::edRemoveChild(Node *node) throw(YACS::Exception)
 {
   map< int , Node * >::iterator iter=_mapOfNode.begin();
index 49c620c5cde536ecaf85068e2253cd52639b2203..be5b1c16fcb03f78102f8094d0c87ad8d4f555ed 100644 (file)
@@ -40,7 +40,7 @@ namespace YACS
     private:
       int edGetNumberOfOutLinks() const;
       std::set<InPort *> edSetInPort() const;
-      bool isAlreadyLinkedWith(InPort *with) const;
+      bool isAlreadyLinkedWith(InPort *withp) const;
       std::string getNameOfTypeOfCurrentInstance() const;
       void edRemoveAllLinksLinkedWithMe() throw(Exception);
       TypeOfChannel getTypeOfChannel() const;
@@ -116,6 +116,8 @@ namespace YACS
       void writeDot(std::ostream &os) const;
       int getNumberOfInputPorts() const;
       int getMaxLevelOfParallelism() const;
+      double getWeightRegardingDPL() const;
+      void partitionRegardingDPL(const PartDefinition *pd, std::map<ComposedNode *, YACS::BASES::AutoRefCnt<PartDefinition> >& zeMap);
       void edRemoveChild(Node *node) throw(Exception);
       std::list<InputPort *> getSetOfInputPort() const;
       std::list<InputPort *> getLocalInputPorts() const;
index 89de9eb035134de094945787129c79c3bc260b02..0c822a2bf89650d48b703e450a78b0b6445c4617 100644 (file)
@@ -34,6 +34,11 @@ void RuntimeForEngineIntegrationTest::setRuntime()
     Runtime::_singleton = new RuntimeForEngineIntegrationTest;
 }
 
+std::vector< std::pair<std::string,int> > RuntimeForEngineIntegrationTest::getCatalogOfComputeNodes() const
+{
+  throw Exception("RuntimeForEngineIntegrationTest not implemented !");
+}
+
 ElementaryNode* RuntimeForEngineIntegrationTest::createNode(const std::string& implementation, const std::string& name) throw (YACS::Exception)
 {
   if (implementation == ToyNode::MY_IMPL_NAME)
index 77ec42bb905aa18c628d52972f2764455c0b5696..cbfdbf1e6f1c761f7d6f6554461b1c6ddf89c2d5 100644 (file)
@@ -30,6 +30,7 @@ namespace YACS
     {
     public:
       static void setRuntime();
+      std::vector< std::pair<std::string,int> > getCatalogOfComputeNodes() const;
       ElementaryNode* createNode(const std::string& implementation, const std::string& name) throw(Exception);
       InputPort* createInputPort(const std::string& name, const std::string& impl, Node * node, TypeCode * type);
       OutputPort* createOutputPort(const std::string& name, const std::string& impl, Node * node, TypeCode * type);
index 5f6bd37970ea2a8614cae030a09fe6321c1b7a29..53537a9f718c8af6b23daf5e824c358044740d2b 100644 (file)
@@ -106,6 +106,11 @@ void RuntimeForEngineTest::setRuntime()
     Runtime::_singleton = new RuntimeForEngineTest;
 }
 
+std::vector< std::pair<std::string,int> > RuntimeForEngineTest::getCatalogOfComputeNodes() const
+{
+  throw Exception("RuntimeForEngineTest::getCatalogOfComputeNodes : not implemented !");
+}
+
 ElementaryNode* RuntimeForEngineTest::createNode(const string& implementation, const string& name) throw(YACS::Exception)
 {
   return new TestElemNode(name);
index 0495ab60a4f95ee6a7c7212a89551718e9a81d7d..d5e5a7ea36e2bff62860bfa5ce3302f8dab2c33c 100644 (file)
@@ -66,6 +66,7 @@ namespace YACS
     {
     public:
       static void setRuntime();
+      std::vector< std::pair<std::string,int> > getCatalogOfComputeNodes() const;
       ElementaryNode* createNode(const std::string& implementation, const std::string& name) throw(Exception);
       InputPort* createInputPort(const std::string& name, const std::string& impl, Node * node, TypeCode * type);
       OutputPort* createOutputPort(const std::string& name, const std::string& impl, Node * node, TypeCode * type);
index 38560cf0cf28e265a07644e6d6f7ba60e15ae9df..f7c4774474b2a1a5575d51a67074d753ee8306ef 100644 (file)
@@ -139,6 +139,11 @@ int TypeCode::isAdaptable(const TypeCode* tc) const
     }
 }
 
+std::string TypeCode::getPrintStr() const
+{
+  return id();
+}
+
 //! Check if this TypeCode can be used in place of tc
 /*!
  * this TypeCode is equivalent to tc if they have the same kind
@@ -200,6 +205,23 @@ const char *TypeCode::getKindRepr(DynType kind)
   return KIND_STR_REPR[(int)kind];
 }
 
+const TypeCode *TypeCode::subContentType(int lev) const
+{
+  if(lev<0)
+    throw YACS::Exception("subContentType: Invalid input val !");
+  if(lev==0)
+    return this;
+  const TypeCode *ret(this);
+  for(int i=0;i<lev;i++)
+    {
+      const TypeCode *cand(ret->contentType());
+      if(!cand)
+        throw YACS::Exception("subContentType : Invalid input val 2 !");
+      ret=cand;
+    }
+  return ret;
+}
+
 const char * TypeCode::getKindRepr() const
 {
   return KIND_STR_REPR[(int)_kind];
@@ -447,6 +469,12 @@ const char * TypeCodeSeq::shortName() const
   return _shortName.c_str();
 }
 
+std::string TypeCodeSeq::getPrintStr() const
+{
+  std::ostringstream oss; oss << "seq[" << contentType()->getPrintStr() << "]";
+  return oss.str();
+}
+
 const TypeCode * TypeCodeSeq::contentType() const throw(YACS::Exception)
 {
   return _content;
index 5d16a01ac45f4962f96a5449147efb0e5a69d181..1856e73a2008d6b1d54ca5f73ec2e87a4207a6fa 100644 (file)
@@ -71,7 +71,7 @@ namespace YACS
 
       DynType kind() const;
       const char * getKindRepr() const;
-      
+      const TypeCode *subContentType(int lev) const;
       virtual TypeCode *clone() const;
       virtual void putReprAtPlace(char *pt, const char *val, bool deepCpy) const;
       virtual void destroyZippedAny(char *data) const;
@@ -85,6 +85,7 @@ namespace YACS
       virtual int isAdaptable(const TypeCode* tc) const;
       virtual int isEquivalent(const TypeCode* tc) const;
       virtual unsigned getSizeInByteOfAnyReprInSeq() const;
+      virtual std::string getPrintStr() const;
 
       static const char *getKindRepr(DynType kind);
       static TypeCode * interfaceTc(const char* id, const char* name);
@@ -168,6 +169,7 @@ namespace YACS
       const char * id()   const throw(Exception);
       const char * name() const throw(Exception);
       const char * shortName() const;
+      virtual std::string getPrintStr() const;
 
       virtual const TypeCode * contentType() const throw(Exception);
       virtual int isA(const TypeCode* tc) const ;
index ef6890f4fccc4ba18ee2e73b087d9398c6acc842..4e33796b94c1ecc2d5f8da76b066c73c4a50811a 100644 (file)
@@ -134,6 +134,7 @@ void VisitorSaveSchema::visitForEachLoop(ForEachLoop *node)
     _out << " state=\"disabled\"";
   if (!nbranch->isEmpty())
     _out << " nbranch=\"" << nbranch->getIntValue() << "\"";
+  _out << " weight=\"" << node->getWeight() << "\"";
   if (node->edGetSamplePort())
     _out << " type=\"" << node->edGetSamplePort()->edGetType()->name() << "\"";
   _out << ">" << endl;
@@ -159,6 +160,7 @@ void VisitorSaveSchema::visitOptimizerLoop(OptimizerLoop *node)
     _out << " state=\"disabled\"";
   if (!nbranch->isEmpty())
     _out << " nbranch=\"" << nbranch->getIntValue() << "\"";
+  _out << " weight=\"" << node->getWeight() << "\"";
   _out << " lib=\"" << node->getAlgLib() << "\"";
   _out << " entry=\"" << node->getSymbol() << "\"";
   _out << ">" << endl;
index 4c525af2e9e56b848297705cb2a9ed05aaf5d309..e534b89ed86aca462f3c32f66cb98d99044d89e9 100644 (file)
@@ -109,6 +109,7 @@ SET(SWIGINCLUDES ${ENGINEINCL}
 
 SET(SWIG_MODULE_pilot_EXTRA_DEPS engtypemaps.i ${SWIGINCLUDES})
 SWIG_ADD_MODULE(pilot python pilot.i ExecutorSwig.cxx)
+SWIG_CHECK_GENERATION(pilot)
 
 SET(SWIG_MODULE_pypilot_EXTRA_DEPS pilot.i engtypemaps.i _pilot ${SWIGINCLUDES})
 SWIG_ADD_MODULE(pypilot python pypilot.i)
@@ -123,3 +124,13 @@ ENDIF(WIN32)
 INSTALL(TARGETS ${SWIG_MODULE_pilot_REAL_NAME} ${SWIG_MODULE_pypilot_REAL_NAME} DESTINATION ${SALOME_INSTALL_PYTHON})
 
 SALOME_INSTALL_SCRIPTS("${_swig_SCRIPTS}"  ${SALOME_INSTALL_PYTHON})
+
+### Test
+
+SALOME_GENERATE_TESTS_ENVIRONMENT(tests_env)
+ADD_TEST(NAME PlayGround0 COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/testPlayGround0.py)
+SET_TESTS_PROPERTIES(PlayGround0 PROPERTIES ENVIRONMENT "${tests_env}")
+SET(LOCAL_TEST_DIR ${SALOME_YACS_INSTALL_TEST}/engine_swig)
+SET(LOCAL_TEST_FILES testPlayGround0.py)
+INSTALL(FILES ${LOCAL_TEST_FILES} DESTINATION ${LOCAL_TEST_DIR})
+INSTALL(FILES CTestTestfileInstall.cmake DESTINATION ${LOCAL_TEST_DIR} RENAME CTestTestfile.cmake)
diff --git a/src/engine_swig/CTestTestfileInstall.cmake b/src/engine_swig/CTestTestfileInstall.cmake
new file mode 100644 (file)
index 0000000..745df03
--- /dev/null
@@ -0,0 +1,24 @@
+# Copyright (C) 2015-2016  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(NOT WIN32)
+  SET(TEST_NAME ${COMPONENT_NAME}_PlayGround0)
+  ADD_TEST(${TEST_NAME} python testPlayGround0.py)
+  SET_TESTS_PROPERTIES(${TEST_NAME} PROPERTIES LABELS "${COMPONENT_NAME}")
+ENDIF()
diff --git a/src/engine_swig/PlayGround.i b/src/engine_swig/PlayGround.i
new file mode 100644 (file)
index 0000000..859ed1f
--- /dev/null
@@ -0,0 +1,169 @@
+// Copyright (C) 2006-2016  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
+//
+
+%template()              std::pair< YACS::ENGINE::PartDefinition *, double>;
+%template(vecppdd)       std::vector< std::pair< YACS::ENGINE::PartDefinition *, double> >;
+
+%newobject YACS::ENGINE::PlayGround::copy;
+
+%{
+PyObject *convertPartDefinition(YACS::ENGINE::PartDefinition *pd)
+{
+  if(!pd)
+    return SWIG_NewPointerObj(SWIG_as_voidptr(pd),SWIGTYPE_p_YACS__ENGINE__PartDefinition, SWIG_POINTER_OWN | 0 );
+  YACS::ENGINE::ContigPartDefinition *pd1(dynamic_cast<YACS::ENGINE::ContigPartDefinition *>(pd));
+  if(pd1)
+    return SWIG_NewPointerObj(SWIG_as_voidptr(pd1),SWIGTYPE_p_YACS__ENGINE__ContigPartDefinition, SWIG_POINTER_OWN | 0 );
+  YACS::ENGINE::NonContigPartDefinition *pd2(dynamic_cast<YACS::ENGINE::NonContigPartDefinition *>(pd));
+  if(pd2)
+    return SWIG_NewPointerObj(SWIG_as_voidptr(pd2),SWIGTYPE_p_YACS__ENGINE__NonContigPartDefinition, SWIG_POINTER_OWN | 0 );
+  YACS::ENGINE::AllPartDefinition *pd3(dynamic_cast<YACS::ENGINE::AllPartDefinition *>(pd));
+  if(pd3)
+    return SWIG_NewPointerObj(SWIG_as_voidptr(pd3),SWIGTYPE_p_YACS__ENGINE__AllPartDefinition, SWIG_POINTER_OWN | 0 );
+  return SWIG_NewPointerObj(SWIG_as_voidptr(pd),SWIGTYPE_p_YACS__ENGINE__PartDefinition, SWIG_POINTER_OWN | 0 );
+  
+}
+%}
+
+%typemap(out) std::vector< YACS::BASES::AutoRefCnt<YACS::ENGINE::PartDefinition> >
+{
+  std::size_t sz($1.size());
+  std::vector< YACS::BASES::AutoRefCnt<YACS::ENGINE::PartDefinition> >::iterator it($1.begin());
+  $result = PyList_New($1.size());
+  for (std::size_t i=0; i<sz; i++,it++)
+    PyList_SetItem($result,i,convertPartDefinition((*it).retn())); 
+}
+
+namespace YACS
+{
+  namespace ENGINE
+  {
+    class PartDefinition;
+
+    class PlayGround : public RefCounter
+    {
+    public:
+      PlayGround();
+      void loadFromKernelCatalog();
+      PlayGround(const std::vector< std::pair<std::string,int> >& defOfRes);
+      std::string printSelf() const;
+      std::vector< std::pair<std::string,int> > getData() const;
+      void setData(const std::vector< std::pair<std::string,int> >& defOfRes);
+      int getNumberOfCoresAvailable() const;
+      int getMaxNumberOfContainersCanBeHostedWithoutOverlap(int nbCoresPerCont) const;
+      std::string deduceMachineFrom(int workerId, int nbProcPerNode) const;
+      %extend
+         {
+           std::string __str__() const
+           {
+             return self->printSelf();
+           }
+
+           std::vector< YACS::BASES::AutoRefCnt<YACS::ENGINE::PartDefinition> > partition(const std::vector< std::pair< YACS::ENGINE::PartDefinition *,double> >& parts) const
+           {
+             std::size_t sz(parts.size());
+             std::vector< std::pair< const YACS::ENGINE::PartDefinition *,double> > partsCpp(sz);
+             for(std::size_t i=0;i<sz;i++)
+               partsCpp[i]=std::pair<const YACS::ENGINE::PartDefinition *,double >(parts[i].first,parts[i].second);
+             return self->partition(partsCpp);
+           }
+         }
+    private:
+      ~PlayGround();
+    };
+
+    class PartDefinition : public RefCounter
+    {
+    public:
+      virtual PartDefinition *copy() const;
+      virtual std::string printSelf() const;
+      virtual int getNumberOfCoresConsumed() const;
+    protected:
+      PartDefinition();
+      ~PartDefinition();
+    };
+
+    class ContigPartDefinition : public PartDefinition
+    {
+    public:
+      ContigPartDefinition(const PlayGround *pg, int nbOfCoresPerComp, int zeStart, int zeStop);
+      int getStart() const;
+      int getStop() const;
+      %extend
+         {
+           std::string __str__() const
+           {
+             return self->printSelf();
+           }
+         }
+    private:
+      ~ContigPartDefinition();
+    };
+
+    class NonContigPartDefinition : public PartDefinition
+    {
+    public:
+      NonContigPartDefinition(const PlayGround *pg, int nbOfCoresPerComp, const std::vector<int>& ids);
+      std::vector<int> getIDs() const;
+      %extend
+         {
+           std::string __str__() const
+           {
+             return self->printSelf();
+           }
+         }
+    private:
+      ~NonContigPartDefinition();
+    };
+
+    class AllPartDefinition : public PartDefinition
+    {
+    public:
+      AllPartDefinition(const PlayGround *pg, int nbOfCoresPerComp);
+      %extend
+         {
+           std::string __str__() const
+           {
+             return self->printSelf();
+           }
+         }
+    private:
+      ~AllPartDefinition();
+    };
+
+    class PartDefinition;
+    
+    class ForTestOmlyHPContCls
+    {
+    public:
+      std::string getContainerType() const;
+      std::vector<int> getIDS() const;
+    %extend
+       {
+         PyObject *getPD() const
+         {
+           const PartDefinition *ret(self->getPD());
+           if(ret)
+             ret->incrRef();
+           return convertPartDefinition(const_cast<PartDefinition *>(ret));
+         }
+       }
+    };
+  }
+}
index 6b93d661450955965b697322b4437cb6a6e8333e..98a7296db3b0330b204bd02fc2a3b40e79146ec2 100644 (file)
@@ -58,7 +58,8 @@
 #include "DeploymentTree.hxx"
 #include "ComponentInstance.hxx"
 #include "DataNode.hxx"
-
+#include "PlayGround.hxx"
+  
 using namespace YACS::ENGINE;
 
 %}
@@ -104,6 +105,7 @@ using namespace YACS::ENGINE;
 %template()              std::pair<std::string, YACS::ENGINE::Container *>;
 %template()              std::pair<YACS::ENGINE::OutPort *,YACS::ENGINE::InPort *>;
 %template()              std::pair<YACS::ENGINE::InPort *,YACS::ENGINE::OutPort *>;
+%template()              std::pair< std::string, int >;
 //%template(TCmap)         std::map<std::string, YACS::ENGINE::TypeCode *>;
 REFCOUNT_TEMPLATE(TCmap,YACS::ENGINE::TypeCode)
 %template(NODEmap)       std::map<std::string, YACS::ENGINE::Node *>;
@@ -113,11 +115,13 @@ REFCOUNT_TEMPLATE(TCmap,YACS::ENGINE::TypeCode)
 REFCOUNT_TEMPLATE(CONTAINmap,YACS::ENGINE::Container)
 %template(strvec)        std::vector<std::string>;
 %template(uivec)         std::vector<unsigned int>;
+%template(ivec)          std::vector<int>;
 %template(linksvec)      std::vector< std::pair<YACS::ENGINE::OutPort *,YACS::ENGINE::InPort *> >;
 %template(linkvec)       std::vector< std::pair<YACS::ENGINE::InPort *,YACS::ENGINE::OutPort *> >;
 %template(instreamlist)  std::list<YACS::ENGINE::InputDataStreamPort *>;
 %template(outstreamlist) std::list<YACS::ENGINE::OutputDataStreamPort *>;
-
+%template(vpsi)          std::vector< std::pair< std::string, int > >;
+          
 %template()              std::pair<std::string, YACS::ENGINE::CatalogLoader *>;
 %template(loadermap)     std::map<std::string,YACS::ENGINE::CatalogLoader *>;
 %template()              std::pair<std::string, YACS::ENGINE::ComposedNode *>;
@@ -349,6 +353,7 @@ EXCEPTION(YACS::ENGINE::ExecutorSwig::waitPause)
 // OptimizerAlgASync in module SALOMERuntime
 %ignore YACS::ENGINE::OptimizerAlgASync;
 %include <OptimizerAlg.hxx>
+%include "PlayGround.i"
 
 %extend YACS::ENGINE::ConditionInputPort
 {
diff --git a/src/engine_swig/testPlayGround0.py b/src/engine_swig/testPlayGround0.py
new file mode 100644 (file)
index 0000000..3128e21
--- /dev/null
@@ -0,0 +1,76 @@
+# Copyright (C) 2006-2017  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
+#
+
+import pilot
+import unittest
+
+class TestPlayGround0(unittest.TestCase):
+    def test0(self):
+        pg=pilot.PlayGround([("a0",28),("a1",28),("a2",28)])
+        pd=pilot.ContigPartDefinition(pg,4,0,3*28)
+        res=pg.partition([(pd,1.),(pd,1.)])
+        assert(len(res)==2)
+        assert(isinstance(res[0],pilot.ContigPartDefinition))
+        assert(isinstance(res[1],pilot.ContigPartDefinition))
+        assert(res[0].getStart()==0 and res[0].getStop()==40)
+        assert(res[1].getStart()==40 and res[1].getStop()==84)
+        assert(sum([elt.getNumberOfCoresConsumed() for elt in res])==pg.getNumberOfCoresAvailable())
+        pd2=pilot.AllPartDefinition(pg,4)
+        assert(pd2.getNumberOfCoresConsumed()==84)
+        res=pg.partition([(pd2,1.),(pd2,1.),(pd2,1.)])
+        assert(len(res)==3)
+        assert(isinstance(res[0],pilot.ContigPartDefinition))
+        assert(isinstance(res[1],pilot.ContigPartDefinition))
+        assert(isinstance(res[2],pilot.ContigPartDefinition))
+        assert(res[0].getStart()==0 and res[0].getStop()==28)
+        assert(res[1].getStart()==28 and res[1].getStop()==56)
+        assert(res[2].getStart()==56 and res[2].getStop()==84)
+        #
+        pg.setData([("a0",2),("a1",8),("a2",8)])
+        res=pg.partition([(pilot.AllPartDefinition(pg,4),1.),(pilot.AllPartDefinition(pg,1),1.)])
+        assert(len(res)==2)
+        assert(isinstance(res[0],pilot.ContigPartDefinition))
+        assert(isinstance(res[1],pilot.NonContigPartDefinition))
+        assert(res[0].getStart()==2 and res[0].getStop()==10)
+        assert(res[1].getIDs()==(0,1,10,11,12,13,14,15,16,17))
+        pass
+
+    def test1(self):
+        """ test focused on complicated cut due to lack of cores"""
+        pg=pilot.PlayGround([("a0",13)])
+        pd=pilot.ContigPartDefinition(pg,4,0,13)
+        res=pg.partition([(pd,1.),(pd,1.)])
+        assert(len(res)==2)
+        assert(isinstance(res[0],pilot.ContigPartDefinition) and isinstance(res[1],pilot.ContigPartDefinition))
+        assert(res[0].getStart()==0 and res[0].getStop()==4)
+        assert(res[1].getStart()==4 and res[1].getStop()==12)# 1 core lost
+        #
+        pg=pilot.PlayGround([("a0",2),("a1",11)])
+        pd=pilot.ContigPartDefinition(pg,4,0,13)
+        res=pg.partition([(pd,1.),(pd,1.)])
+        assert(len(res)==2)
+        assert(isinstance(res[0],pilot.ContigPartDefinition) and isinstance(res[1],pilot.ContigPartDefinition))
+        assert(res[0].getStart()==2 and res[0].getStop()==6)
+        assert(res[1].getStart()==6 and res[1].getStop()==10)# 5 cores lost
+        pass
+    
+    pass
+
+if __name__ == '__main__':
+    unittest.main()
index 4206e551d2a08b4789a9fc88d786ece5da30df1e..0a6f9208bbb72d80d7b776f20d2d296da38dc27b 100644 (file)
@@ -34,14 +34,6 @@ YACSEvalSeqAny *YACSEvalSeqAny::BuildEmptyFromType(const std::string& dataType)
     throw YACS::Exception("YACSEvalSeqAny::BuildEmptyFromType : Only int and double are actualy managed !");
 }
 
-template<class T>
-std::size_t YACSEvalSeqAnyInternal<T>::size() const
-{
-  if(!_arr)
-    throw YACS::Exception("YACSEvalSeqAnyDouble<T>::size : empty array !");
-  return _arr->size();
-}
-
 YACSEvalSeqAnyDouble::YACSEvalSeqAnyDouble(const std::vector<double>& arr):_arr(0)
 {
   std::vector<double> *zeArr(new std::vector<double>(arr));
index 195319e0c156b4fa846d107ab7df58899193ed13..b766131c68283e86616a54012fe8983fb4a85c7e 100644 (file)
@@ -94,4 +94,12 @@ private:
   YACSEvalSeqAnyInternal<int> *_arr;
 };
 
+template<class T>
+std::size_t YACSEvalSeqAnyInternal<T>::size() const
+{
+  if(!_arr)
+    throw YACS::Exception("YACSEvalSeqAnyDouble<T>::size : empty array !");
+  return _arr->size();
+}
+
 #endif
index 69039c3a1eea4d40c85151cfc7067e8f6b7599b5..d08aa9c49db0d7846cfd9ce12a87a721468b7ce4 100644 (file)
@@ -36,13 +36,8 @@ const char YACSEvalSession::NSPORT_VAR_NAME[]="NSPORT";
 
 YACSEvalSession::YACSEvalSession():_isAttached(false),_isLaunched(false),_isForcedPyThreadSaved(false),_port(-1),_salomeInstanceModule(0),_salomeInstance(0),_internal(new YACSEvalSessionInternal)
 {
-  if(!Py_IsInitialized())
-    Py_Initialize();
-  //
-  {
-    YACS::ENGINE::AutoGIL gal;
-    _salomeInstanceModule=PyImport_ImportModule(const_cast<char *>("salome_instance"));
-  }
+  YACS::ENGINE::AutoGIL gal;
+  _salomeInstanceModule=PyImport_ImportModule(const_cast<char *>("salome_instance"));
 }
 
 YACSEvalSession::~YACSEvalSession()
@@ -90,10 +85,7 @@ void YACSEvalSession::launchUsingCurrentSession()
 
 bool YACSEvalSession::isAlreadyPyThreadSaved() const
 {
-  if(!_isForcedPyThreadSaved)
-    return isAttached();
-  else
-    return true;
+  return _isForcedPyThreadSaved;
 }
 
 void YACSEvalSession::checkLaunched() const
index 47b19bd0fedc79e2b49736507f4a5b180dd877d9..43b6b6b9dd49c191142eac4e83c00f1a64ba3781 100644 (file)
@@ -73,8 +73,19 @@ const char YACSEvalYFXGraphGen::GATHER_NODE_NAME[]="__gather__";
 class MyAutoThreadSaver
 {
 public:
-  MyAutoThreadSaver(bool isToSave):_isToSave(isToSave),_save(0) { if(_isToSave) _save=PyEval_SaveThread(); }
-  ~MyAutoThreadSaver() { if(_isToSave) PyEval_RestoreThread(_save); }
+  MyAutoThreadSaver(bool isToSave):_isToSave(isToSave),_save(0)
+  {
+    if(_isToSave)
+      {
+        PyThreadState *save(PyThreadState_Swap(NULL));// safe call of PyEval_SaveThread()
+        if(save)
+          {
+            _save=save;
+            PyEval_ReleaseLock();
+          }
+      }
+  }
+  ~MyAutoThreadSaver() { if(_isToSave) if(_save) { PyEval_AcquireLock(); PyThreadState_Swap(_save); /*safe call of PyEval_RestoreThread*/ } }
 private:
   bool _isToSave;
   PyThreadState *_save;
index 38cd7b29b27840f46465d9e66455eea9af3ebb57..3d7693171b2a93cdcf1e2bacc1c3afddb4af1b36 100644 (file)
@@ -54,6 +54,7 @@ SET(_swig_SCRIPTS ${CMAKE_CURRENT_BINARY_DIR}/evalyfx.py)
 SWIG_ADD_MODULE(evalyfx python evalyfx.i)
 
 SWIG_LINK_LIBRARIES(evalyfx ${_link_LIBRARIES})
+SWIG_CHECK_GENERATION(evalyfx)
 IF(WIN32)
   SET_TARGET_PROPERTIES(_evalyfx PROPERTIES DEBUG_OUTPUT_NAME _evalyfx_d)
 ENDIF(WIN32)
index cf007a4b352f91bdf908847369123219ee4a15d8..0ab9abe3fa02807a897860508012c805965b9b28 100755 (executable)
@@ -32,7 +32,7 @@
 #include <iostream>
 #include <fstream>
 
-#ifndef WIN32
+#if !defined WIN32 && !defined __APPLE__
 #include <fpu_control.h>
 #endif
 
@@ -45,7 +45,7 @@
 
 int main(int argc, char* argv[])
 {
-#ifndef WIN32
+#if !defined WIN32 && !defined __APPLE__
   fpu_control_t cw = _FPU_DEFAULT & ~(_FPU_MASK_IM | _FPU_MASK_ZM | _FPU_MASK_OM);
   _FPU_SETCW(cw);
 #endif
@@ -57,7 +57,7 @@ int main(int argc, char* argv[])
   controller.addListener( &result );        
 
   // ---  Add a listener that print dots as test run.
-#ifdef WIN32
+#if !defined WIN32 && !defined __APPLE__
   CPPUNIT_NS::TextTestProgressListener progress;
 #else
   CPPUNIT_NS::BriefTestProgressListener progress;
index 91afd6cc8ab252063767ab204030ae63dd6ee52b..7cf11feba01a088027958a2e4c7639c64f7adb19 100755 (executable)
@@ -4,7 +4,7 @@
   <ul>
     $navpath
     <li class="footer">
-      Copyright &copy; 2007-2016  CEA/DEN, EDF R&amp;D, OPEN CASCADE<br>
+      Copyright &copy; 2007-2017  CEA/DEN, EDF R&amp;D, OPEN CASCADE<br>
       Copyright &copy; 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, CEDRAT, EDF R&amp;D, LEG, PRINCIPIA R&amp;D, BUREAU VERITAS<br>
     </li>
   </ul>
index 39b24d4bb2ede9df80d5cc3c8d891a03c820dbf0..b2c97276547e5c287618e5ce1cff37099dcbb746 100755 (executable)
@@ -49,7 +49,7 @@ SET (SWIG_MODULE_PMML_EXTRA_DEPS ${PMML_SWIG_DPYS_FILES}
 SET_SOURCE_FILES_PROPERTIES(PMMLsalome.i PROPERTIES SWIG_MODULE_NAME PMML)
 SWIG_ADD_MODULE(PMML python PMMLsalome.i)
 SWIG_LINK_LIBRARIES(PMML ${PYTHON_LIBRARIES} ${PLATFORM_LIBS} pmmlLib)
-
+SWIG_CHECK_GENERATION(PMML)
 # _ABR_ Ensure dependency mechanism on all SWIG files and headers
 
 IF(WIN32)
diff --git a/src/py2yacs/CMakeLists.txt b/src/py2yacs/CMakeLists.txt
new file mode 100644 (file)
index 0000000..8e32b7c
--- /dev/null
@@ -0,0 +1,61 @@
+# Copyright (C) 2012-2016  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_DIRECTORIES(
+  ${PYTHON_INCLUDE_DIR}
+  ${SALOME_INCL_PATH}
+  ${PROJECT_SOURCE_DIR}/src/bases
+  ${PROJECT_SOURCE_DIR}/src/engine
+  ${PROJECT_SOURCE_DIR}/src/runtime
+  ${PROJECT_SOURCE_DIR}
+  )
+
+ADD_DEFINITIONS(
+  ${PYTHON_DEFINITIONS}
+  ${OMNIORB_DEFINITIONS}
+  )
+
+IF(SALOME_BUILD_TESTS)
+  ADD_SUBDIRECTORY(Test)
+ENDIF(SALOME_BUILD_TESTS)
+
+SET(_link_LIBRARIES
+  ${PYTHON_LIBRARIES}
+  YACSRuntimeSALOME
+  )
+
+SET(_py2yacs_sources
+  py2yacs.cxx
+  )
+
+SET(_py2yacs_headers
+  py2yacs.hxx
+  )
+
+ADD_LIBRARY(py2yacslib ${_py2yacs_sources})
+TARGET_LINK_LIBRARIES(py2yacslib ${_link_LIBRARIES})
+
+INSTALL(TARGETS py2yacslib EXPORT ${PROJECT_NAME}TargetGroup DESTINATION ${SALOME_INSTALL_LIBS})
+INSTALL(FILES ${_py2yacs_headers} DESTINATION ${SALOME_INSTALL_HEADERS})
+
+SET( _py_SCRIPTS
+  py2yacs.py
+  )
+
+SALOME_INSTALL_SCRIPTS("${_py_SCRIPTS}"  ${SALOME_INSTALL_PYTHON})
diff --git a/src/py2yacs/Test/CMakeLists.txt b/src/py2yacs/Test/CMakeLists.txt
new file mode 100644 (file)
index 0000000..ad8303c
--- /dev/null
@@ -0,0 +1,62 @@
+# Copyright (C) 2012-2016  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_DIRECTORIES(
+  ${CPPUNIT_INCLUDE_DIRS}
+  ${CMAKE_CURRENT_SOURCE_DIR}/..
+)
+
+SET(_link_LIBRARIES
+  ${CPPUNIT_LIBRARIES} 
+  py2yacslib
+)
+
+SET(Py2yacsTest_SOURCES
+  TestPy2yacs.cxx
+  Py2yacsTest.cxx
+  Py2yacsTest.hxx
+)
+
+ADD_EXECUTABLE(TestPy2yacs ${Py2yacsTest_SOURCES})
+TARGET_LINK_LIBRARIES(TestPy2yacs ${_link_LIBRARIES})
+
+ADD_EXECUTABLE(test_py2yacs test_py2yacs.cxx)
+TARGET_LINK_LIBRARIES(test_py2yacs py2yacslib)
+
+# For salome test
+IF(NOT WIN32)
+  ADD_TEST(TestPy2yacs TestPy2yacs)
+  SET_TESTS_PROPERTIES(TestPy2yacs PROPERTIES
+                       ENVIRONMENT "PYTHONPATH=${CMAKE_CURRENT_SOURCE_DIR}:${CMAKE_CURRENT_SOURCE_DIR}/..:$ENV{PYTHONPATH}"
+                      )
+
+  SET(LOCAL_TEST_DIR ${SALOME_YACS_INSTALL_TEST}/py2yacs)
+  SET(LOCAL_TEST_FILES
+    bad_parsers.py
+    err_py2yacs_invalid.py
+    )
+  INSTALL(FILES ${LOCAL_TEST_FILES}
+          DESTINATION ${LOCAL_TEST_DIR})
+  INSTALL(FILES CTestTestfileInstall.cmake
+          DESTINATION ${LOCAL_TEST_DIR}
+          RENAME CTestTestfile.cmake)
+  INSTALL(TARGETS TestPy2yacs test_py2yacs
+          DESTINATION ${LOCAL_TEST_DIR})
+
+ENDIF()
\ No newline at end of file
diff --git a/src/py2yacs/Test/CTestTestfileInstall.cmake b/src/py2yacs/Test/CTestTestfileInstall.cmake
new file mode 100644 (file)
index 0000000..808eefd
--- /dev/null
@@ -0,0 +1,28 @@
+# Copyright (C) 2012-2016  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(NOT WIN32)
+  SET(TEST_NAME ${COMPONENT_NAME}_Py2YacsTest)
+  # No need of a salome session for this test
+  ADD_TEST(${TEST_NAME} TestPy2yacs)
+  SET_TESTS_PROPERTIES(${TEST_NAME} PROPERTIES
+                                    LABELS "${COMPONENT_NAME}"
+                      )
+
+ENDIF()
diff --git a/src/py2yacs/Test/Py2yacsTest.cxx b/src/py2yacs/Test/Py2yacsTest.cxx
new file mode 100644 (file)
index 0000000..1ba389d
--- /dev/null
@@ -0,0 +1,344 @@
+// Copyright (C) 2006-2016  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 <Python.h>
+#include <fstream>
+#include <string>
+#include <sstream>
+
+#include "Py2yacsTest.hxx"
+#include "py2yacs.hxx"
+#include "Proc.hxx"
+#include "Executor.hxx"
+
+#include "RuntimeSALOME.hxx"
+#include "PythonPorts.hxx"
+#include "InputPort.hxx"
+//#include "parsers.hxx"
+
+void Py2yacsTest::setUp()
+{
+  YACS::ENGINE::RuntimeSALOME::setRuntime();
+  //YACS::ENGINE::getRuntime()->init();
+}
+
+void Py2yacsTest::tearDown()
+{
+  //YACS::ENGINE::getRuntime()->fini();
+}
+
+static
+void verifyCorrectPycode(const char * code_py, const char * function_name,
+                         int nbInputPorts, const char** input_ports,
+                         int nbOutputPorts, const char** output_ports)
+{
+  std::cerr << std::endl;
+  std::cerr << "-----------------------------------------------" << std::endl;
+  std::cerr << code_py << std::endl;
+  std::cerr << "-----------------------------------------------" << std::endl;
+  std::cerr << "Function :" << function_name << std::endl;
+  Py2yacs parser;
+  try
+  {
+    parser.load(code_py);
+  }
+  catch(Py2yacsException& e)
+  {
+    CPPUNIT_FAIL(e.what());
+  }
+  catch(...)
+  {
+    CPPUNIT_FAIL("Unknown exception");
+  }
+  YACS::ENGINE::Proc* p = parser.createProc(function_name);
+  CPPUNIT_ASSERT( p != NULL);
+  YACS::ENGINE::Node* n = p->getChildByShortName("default_name");
+  CPPUNIT_ASSERT( n != NULL);
+  CPPUNIT_ASSERT( n->getNumberOfInputPorts() == nbInputPorts);
+  for(int i = 0; i < nbInputPorts; i++)
+    CPPUNIT_ASSERT( n->getInputPort(input_ports[i]) != NULL);
+  CPPUNIT_ASSERT( n->getNumberOfOutputPorts() == nbOutputPorts);
+  for(int i = 0; i < nbOutputPorts; i++)
+    CPPUNIT_ASSERT( n->getOutputPort(output_ports[i]) != NULL);
+  delete p;
+}
+
+static
+void verifyWrongPycode(const char* code_py, const char* function_name,
+                       const char* error_message)
+{
+  Py2yacs parser;
+  try
+  {
+    parser.load(code_py);
+    YACS::ENGINE::Proc* p = parser.createProc(function_name);
+    CPPUNIT_FAIL("Exception expected and no exception occured.");
+  }
+  catch(Py2yacsException& e)
+  {
+    std::string what = e.what();
+    std::cerr << std::endl;
+    std::cerr << "-----------------------------------------------" << std::endl;
+    std::cerr << code_py << std::endl;
+    std::cerr << "-----------------------------------------------" << std::endl;
+    std::cerr << "Function :" << function_name << std::endl;
+    std::cerr << "==========EXCEPTION TEXT=======================" << std::endl;
+    std::cerr << what << std::endl;
+    std::cerr << "===============================================" << std::endl;
+    CPPUNIT_ASSERT(what.find(error_message) != std::string::npos);
+  }
+}
+
+static
+void verifyWrongParser(const char* parser_module, const char* parser_function,
+                       const char* error_message)
+{
+  const char* code_py = "def f():\n"
+                        "  return\n";
+  Py2yacs parser(parser_module, parser_function);
+  try
+  {
+    parser.load(code_py);
+    CPPUNIT_FAIL("Exception expected and no exception occured.");
+  }
+  catch(Py2yacsException& e)
+  {
+    std::string what = e.what();
+    std::cerr << std::endl;
+    std::cerr << "==========EXCEPTION TEXT=======================" << std::endl;
+    std::cerr << what << std::endl;
+    std::cerr << "===============================================" << std::endl;
+    CPPUNIT_ASSERT(what.find(error_message) != std::string::npos);
+  }
+}
+
+void Py2yacsTest::t1()
+{
+  const char * code_py = "def f1(a, b, c):\n"
+                         "  y = a*b + c\n"
+                         "  return y\n";
+  const char* input_ports[] = {"a", "b", "c"};
+  const char* output_ports[] = {"y"};
+  verifyCorrectPycode(code_py, "f1", 3, input_ports, 1, output_ports);
+}
+
+void Py2yacsTest::t2()
+{
+  const char * code_py = "def f1(a, b, c):\n"
+                         "  x = a + b + c\n"
+                         "  y = a*b + c\n"
+                         "  z = a*b*c\n"
+                         "  return x, y, z\n";
+  const char* input_ports[] = {"a", "b", "c"};
+  const char* output_ports[] = {"x", "y", "z"};
+  verifyCorrectPycode(code_py, "f1", 3, input_ports, 3, output_ports);
+}
+
+void Py2yacsTest::t3()
+{
+  const char * code_py = "def f1(a, b, c):\n"
+                         "  print a\n"
+                         "  print b\n"
+                         "  print c\n";
+  const char* input_ports[] = {"a", "b", "c"};
+  const char** output_ports;
+  verifyCorrectPycode(code_py, "f1", 3, input_ports, 0, output_ports);
+}
+
+void Py2yacsTest::t4()
+{
+  const char * code_py = "def f1():\n"
+                         "  print 'toto'\n"
+                         "  return\n";
+  const char* input_ports[] = {"a", "b", "c"};
+  const char** output_ports;
+  verifyCorrectPycode(code_py, "f1", 0, input_ports, 0, output_ports);
+}
+
+void Py2yacsTest::t5()
+{
+  const char * code_py = "def f1(a):\n"
+                         "  x = -a\n"
+                         "  if a > 0:\n"
+                         "    return a\n"
+                         "  else:\n"
+                         "    return x\n"
+                         "class ignoremoi:\n"
+                         "  def ignoreF(t):\n"
+                         "    return t+1\n"
+                         "def f2(v):\n"
+                         "  ret = f1(v)\n"
+                         "  return ret\n";
+  const char* input_ports[] = {"v"};
+  const char* output_ports[] = {"ret"};
+  verifyCorrectPycode(code_py, "f2", 1, input_ports, 1, output_ports);
+}
+
+void Py2yacsTest::no_multiple_returns()
+{
+  const char * code_py = "def f(a):\n"
+                         "  x = -a\n"
+                         "  if a > 0:\n"
+                         "    return a\n"
+                         "  else:\n"
+                         "    return x\n";
+  verifyWrongPycode(code_py, "f", "multiple returns.");
+}
+
+void Py2yacsTest::unaccepted_statement()
+{
+  const char * code_py = "def f(a):\n"
+                         "  return a\n"
+                         "x=5\n";
+  verifyWrongPycode(code_py, "f", "not accepted statement");
+}
+
+void Py2yacsTest::unaccepted_statement2()
+{
+  const char * code_py = "def f(a):\n"
+                         "  return a\n"
+                         "if __name__ == '__main__':"
+                         "  print 'toto'\n";
+  verifyWrongPycode(code_py, "f", "not accepted statement");
+}
+
+void Py2yacsTest::unaccepted_return()
+{
+  const char * code_py = "def f(a):\n"
+                         "  return 7\n";
+  verifyWrongPycode(code_py, "f", "invalid type returned");
+}
+
+void Py2yacsTest::unaccepted_return2()
+{
+  const char * code_py = "def f1(a):\n"
+                         "  return 7\n"
+                         "def f2(x):\n"
+                         "  return f1(x)\n";
+  verifyWrongPycode(code_py, "f2", "invalid type returned");
+}
+
+void Py2yacsTest::syntaxError()
+{
+  const char * code_py = "bla bla bla\n"
+                         "  return f1(x)\n";
+  verifyWrongPycode(code_py, "f2", "SyntaxError");
+}
+
+void Py2yacsTest::badFunctionName()
+{
+  const char * code_py = "def f1(a):\n"
+                         "  x=7\n"
+                         "  return x\n"
+                         "def f2(x):\n"
+                         "  y=8\n"
+                         "  return y\n";
+  verifyWrongPycode(code_py, "nonexistant", "Function not found:");
+}
+
+void Py2yacsTest::schemaExec()
+{
+  const char * code_py = "def f(a):\n"
+                         "  x = a\n"
+                         "  return x\n";
+  Py2yacs parser;
+  try
+  {
+    parser.load(code_py);
+  }
+  catch(Py2yacsException& e)
+  {
+    CPPUNIT_FAIL(e.what());
+  }
+  catch(...)
+  {
+    CPPUNIT_FAIL("Unknown exception");
+  }
+  YACS::ENGINE::Proc* p = parser.createProc("f");
+  CPPUNIT_ASSERT( p != NULL);
+  YACS::ENGINE::Node* n = p->getChildByShortName("default_name");
+  CPPUNIT_ASSERT( n != NULL);
+  CPPUNIT_ASSERT( n->getInputPort("a") != NULL);
+  CPPUNIT_ASSERT( n->getOutputPort("x") != NULL);
+  // run the schema
+  n->getInputPort("a")->edInit(42.);
+  YACS::ENGINE::Executor executor;
+  executor.RunW(p, 0);
+  // verify the output port value
+  YACS::ENGINE::OutputPyPort* var = dynamic_cast<YACS::ENGINE::OutputPyPort*>(n->getOutputPort("x"));
+  CPPUNIT_ASSERT(var);
+  PyObject* pyVal = var->get();
+  CPPUNIT_ASSERT(pyVal);
+  CPPUNIT_ASSERT(PyFloat_Check(pyVal));
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(42., PyFloat_AsDouble(pyVal), 1.E-12);
+}
+
+// Test the behaviour when there is an error in the python parser
+void Py2yacsTest::parserErrors()
+{
+  verifyWrongParser("bad_parsers", "p1", "argument");
+  verifyWrongParser("bad_parsers", "p2", "Attribute 'name' not found");
+  verifyWrongParser("bad_parsers", "p3", "should be a python list");
+  verifyWrongParser("bad_parsers", "p4", "Traceback");
+  verifyWrongParser("bad_parsers", "f", "Cannot find the parsing function");
+  verifyWrongParser("err_py2yacs_invalid", "get_properties", "invalid syntax");
+  verifyWrongParser("no_file", "f", "Failed to load");
+  verifyWrongParser("bad_parsers", "p5", " ");
+  verifyWrongParser("bad_parsers", "p6", " ");
+  verifyWrongParser("bad_parsers", "p7", " ");
+  verifyWrongParser("bad_parsers", "p8", "Attribute 'name' should be a string.");
+  verifyWrongParser("bad_parsers", "p9", " ");
+  verifyWrongParser("bad_parsers", "p10", " ");
+}
+
+void Py2yacsTest::globalVerification()
+{
+  std::ifstream file_stream("exemple_py2yacs.py");
+  if(!file_stream)
+    return;
+
+  std::stringstream buffer;
+  buffer << file_stream.rdbuf();
+  Py2yacs parser;
+  parser.load(buffer.str());
+  std::list<FunctionProperties>::const_iterator it_fp;
+  const std::list<FunctionProperties>& functions = parser.getFunctionProperties();
+  for(it_fp=functions.begin();it_fp!=functions.end();it_fp++)
+  {
+    std::cerr << "Function :" << it_fp->_name << std::endl;
+    std::list<std::string>::const_iterator it;
+    std::cerr << "Input ports :" ;
+    for(it=it_fp->_input_ports.begin();it!=it_fp->_input_ports.end();it++)
+      std::cerr << *it << ",";
+    std::cerr << std::endl;
+    std::cerr << "Output ports :" ;
+    for(it=it_fp->_output_ports.begin();it!=it_fp->_output_ports.end();it++)
+      std::cerr << *it << ",";
+    std::cerr << std::endl;
+    std::cerr << "Imports :" ;
+    for(it=it_fp->_imports.begin();it!=it_fp->_imports.end();it++)
+      std::cerr << *it << ",";
+    std::cerr << std::endl;
+    std::cerr << "Errors :" ;
+    for(it=it_fp->_errors.begin();it!=it_fp->_errors.end();it++)
+      std::cerr << *it << std::endl;
+    std::cerr << std::endl;
+    std::cerr << "-----------------------------------------" << std::endl;
+  }
+
+}
\ No newline at end of file
diff --git a/src/py2yacs/Test/Py2yacsTest.hxx b/src/py2yacs/Test/Py2yacsTest.hxx
new file mode 100644 (file)
index 0000000..e328c88
--- /dev/null
@@ -0,0 +1,65 @@
+// Copyright (C) 2006-2016  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
+//
+#ifndef _Py2yacsTest_hxx_
+#define _Py2yacsTest_hxx_
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class Py2yacsTest: public CppUnit::TestFixture
+{
+  CPPUNIT_TEST_SUITE(Py2yacsTest);
+  CPPUNIT_TEST(t1);
+  CPPUNIT_TEST(t2);
+  CPPUNIT_TEST(t3);
+  CPPUNIT_TEST(t4);
+  CPPUNIT_TEST(t5);
+  CPPUNIT_TEST(no_multiple_returns);
+  CPPUNIT_TEST(unaccepted_statement);
+  CPPUNIT_TEST(unaccepted_statement2);
+  CPPUNIT_TEST(unaccepted_return);
+  CPPUNIT_TEST(unaccepted_return2);
+  CPPUNIT_TEST(syntaxError);
+  CPPUNIT_TEST(badFunctionName);
+  CPPUNIT_TEST(schemaExec);
+  CPPUNIT_TEST(parserErrors);
+  CPPUNIT_TEST(globalVerification);
+  CPPUNIT_TEST_SUITE_END();
+  
+  public:
+    void setUp();
+    void tearDown();
+    
+    void t1();
+    void t2();
+    void t3();
+    void t4();
+    void t5();
+    void no_multiple_returns();
+    void unaccepted_statement();
+    void unaccepted_statement2();
+    void unaccepted_return();
+    void unaccepted_return2();
+    void syntaxError();
+    void badFunctionName();
+    void schemaExec();
+    void parserErrors();
+    void globalVerification();
+};
+
+#endif
\ No newline at end of file
diff --git a/src/py2yacs/Test/TestPy2yacs.cxx b/src/py2yacs/Test/TestPy2yacs.cxx
new file mode 100644 (file)
index 0000000..6b20289
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright (C) 2006-2016  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 "Py2yacsTest.hxx"
+#define UNIT_TEST_HEADER " --- TEST Py2yacsTest"
+
+CPPUNIT_TEST_SUITE_REGISTRATION( Py2yacsTest );
+
+#include "BasicMainTest.hxx"
diff --git a/src/py2yacs/Test/bad_parsers.py b/src/py2yacs/Test/bad_parsers.py
new file mode 100644 (file)
index 0000000..ed18c1a
--- /dev/null
@@ -0,0 +1,72 @@
+# -*- coding: utf-8 -*-
+# Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
+#
+# Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+# CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, 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
+#
+def p1():
+  return ["a"], ["b"]
+
+def p2(x):
+  return ["a"], ["b"]
+
+def p3(x):
+  return 5, 6
+
+def p4(a):
+  x= a / 0
+  return ["a"], ["b"]
+
+class FunctionProperties:
+  def __init__(self, function_name):
+    self.name = function_name
+    self.inputs=[]
+    self.outputs=None
+    self.errors=[]
+    self.imports=[]
+    pass
+
+def p5(f):
+  fp = FunctionProperties("boo")
+  fp.inputs=["a", 5]
+  return [fp], ["a", "b", "c"]
+
+def p6(f):
+  fp = FunctionProperties("boo")
+  fp.outputs=[7, 5]
+  return [fp], ["a", "b", "c"]
+
+def p7(f):
+  fp = FunctionProperties("boo")
+  fp.errors=[7, 5]
+  return [fp], ["a", "b", "c"]
+
+def p8(f):
+  fp = FunctionProperties("boo")
+  fp.name=[5]
+  return [fp], ["a", "b", "c"]
+
+def p9(f):
+  fp = FunctionProperties("boo")
+  return [fp], "a"
+
+def p10(f):
+  fp = FunctionProperties("boo")
+  return [fp], ["a", fp, "c"]
+
diff --git a/src/py2yacs/Test/err_py2yacs_invalid.py b/src/py2yacs/Test/err_py2yacs_invalid.py
new file mode 100644 (file)
index 0000000..046bdf6
--- /dev/null
@@ -0,0 +1,5 @@
+invalid python file
+{
+}
+x += 4;
+return
\ No newline at end of file
diff --git a/src/py2yacs/Test/test_py2yacs.cxx b/src/py2yacs/Test/test_py2yacs.cxx
new file mode 100644 (file)
index 0000000..08aae0d
--- /dev/null
@@ -0,0 +1,63 @@
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <cerrno>
+#include "py2yacs.hxx"
+#include "RuntimeSALOME.hxx"
+
+/*
+#include "Proc.hxx"
+#include "Node.hxx"
+#include "CORBAPorts.hxx"
+#include "InputPort.hxx"
+#include "Executor.hxx"
+*/
+
+int main(int argc, char *argv[])
+{
+  if (argc != 4)
+  {
+    std::cerr << "Usage: " <<  argv[0] << " pythonfile funcname outfile" << std::endl;
+    return 1;
+  }
+  YACS::ENGINE::RuntimeSALOME::setRuntime();
+  //Py_Initialize();
+  Py2yacs parser;
+  std::ifstream file_stream(argv[1]);
+  if(!file_stream)
+  {
+    std::cerr << "Error when opening file " << argv[1]
+             << ": " << strerror(errno)
+             << std::endl;
+    return 1;
+  }
+  std::stringstream buffer;
+  buffer << file_stream.rdbuf();
+  try
+  {
+    parser.load(buffer.str());
+    parser.save(argv[3], argv[2]);
+    
+    /*
+    YACS::ENGINE::Proc* p = parser.createProc(argv[2]);
+    //p->setInPortValue("Schema.default_name", "a", "42.");
+    YACS::ENGINE::Node* n = p->getChildByShortName("default_name");
+    //YACS::ENGINE::Node* n = p->nodeMap["default_name"];
+    if(!n)
+      std::cerr << "Node not found." << std::endl;
+    else
+      n->getInputPort("a")->edInit(42.);
+    p->saveSchema(argv[3]);
+    
+    YACS::ENGINE::Executor executor;
+    executor.RunW(p, 0);
+    n->getOutputPort("x")->dump();
+    */
+  }
+  catch(Py2yacsException& e)
+  {
+    std::cerr << e.what() << std::endl;
+  }
+  YACS::ENGINE::getRuntime()->fini();
+  //Py_Finalize();
+}
\ No newline at end of file
diff --git a/src/py2yacs/py2yacs.cxx b/src/py2yacs/py2yacs.cxx
new file mode 100644 (file)
index 0000000..2ad047d
--- /dev/null
@@ -0,0 +1,379 @@
+// Copyright (C) 2006-2016  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 <Python.h>
+#include <sstream>
+#include "py2yacs.hxx"
+#include "RuntimeSALOME.hxx"
+#include "Proc.hxx"
+#include "InlineNode.hxx"
+#include "AutoGIL.hxx"
+
+Py2yacsException::Py2yacsException(const std::string& what)
+: std::exception(),
+  _what(what)
+{
+}
+
+Py2yacsException::~Py2yacsException()throw ()
+{
+}
+
+const char * Py2yacsException::what() const throw ()
+{
+  return _what.c_str();
+}
+
+
+Py2yacs::Py2yacs()
+: _python_parser_module("py2yacs"),
+  _python_parser_function("get_properties"),
+  _functions(),
+  _global_errors(),
+  _python_code()
+{
+}
+
+Py2yacs::Py2yacs(const std::string& python_parser_module,
+        const std::string& python_parser_function)
+: _python_parser_module(python_parser_module),
+  _python_parser_function(python_parser_function),
+  _functions(),
+  _global_errors(),
+  _python_code()
+{
+}
+
+const std::list<std::string>& Py2yacs::getGlobalErrors() const
+{
+  return _global_errors;
+}
+
+const std::list<FunctionProperties>& Py2yacs::getFunctionProperties()const
+{
+  return _functions;
+}
+
+// Copy a python list of strings to a c++ list of strings.
+// Return an error string. An empty string means no error.
+static
+std::string copyList(PyObject *pyList, std::list<std::string>& cppList)
+{
+  std::string error;
+  if(!PyList_Check(pyList))
+  {
+    error = "Not a python list.\n";
+    //throw Py2yacsException("Not a python list.");
+  }
+  else
+  {
+    int n = PyList_Size(pyList);
+    for(int i=0; i<n; i++)
+    {
+      PyObject *elem = PyList_GetItem(pyList,i);
+      if(!PyString_Check(elem))
+      {
+        std::stringstream message;
+        message << "List element number " << i << " is not a string.\n";
+        error += message.str();
+        // throw Py2yacsException(message.str());
+      }
+      else
+      {
+        const char * portName = PyString_AsString(elem);
+        cppList.push_back(portName);
+      }
+    }
+  }
+  return error;
+}
+
+static
+std::string getPyErrorText()
+{
+  std::string result="";
+  if (PyErr_Occurred())
+  {
+    PyObject *ptype, *pvalue, *ptraceback;
+    PyObject *pystr, *module_name, *pyth_module, *pyth_func;
+    PyErr_Fetch(&ptype, &pvalue, &ptraceback);
+    pystr = PyObject_Str(pvalue);
+    result = PyString_AsString(pystr);
+    result += "\n";
+    Py_DECREF(pystr);
+    
+    /* See if we can get a full traceback */
+    if(ptraceback)
+    {
+      module_name = PyString_FromString("traceback");
+      pyth_module = PyImport_Import(module_name);
+      Py_DECREF(module_name);
+      if (pyth_module)
+      {
+        pyth_func = PyObject_GetAttrString(pyth_module, "format_exception");
+        if (pyth_func && PyCallable_Check(pyth_func))
+        {
+          PyObject *pyList;
+          pyList = PyObject_CallFunctionObjArgs(pyth_func, ptype, pvalue, ptraceback, NULL);
+          if(pyList)
+          {
+            int n = PyList_Size(pyList);
+            for(int i=0; i<n; i++)
+            {
+              pystr = PyList_GetItem(pyList,i);
+              result += PyString_AsString(pystr);
+            }
+            Py_DECREF(pyList);
+          }
+        }
+        Py_XDECREF(pyth_func);
+        Py_DECREF(pyth_module);
+      }
+    }
+    Py_XDECREF(ptype);
+    Py_XDECREF(pvalue);
+    Py_XDECREF(ptraceback);
+  }
+  return result;
+}
+
+static
+PyObject* checkAndGetAttribute(PyObject *p,
+                               const char* attribute,
+                               std::string& error)
+{
+  PyObject *pAttribute = PyObject_GetAttrString(p, attribute);
+  if(!pAttribute)
+  {
+    error += "Attribute '";
+    error += attribute;
+    error += "' not found in the returned value of the parsing function.\n";
+    error += getPyErrorText();
+  }
+  return pAttribute;
+}
+
+void Py2yacs::load(const std::string& python_code)
+{
+    PyObject *pModule, *pDict, *pFunc;
+    PyObject *pArgs, *pValue;
+    int i;
+    std::string errorMessage="";
+    _python_code = python_code;
+    _functions.clear();
+    _global_errors.clear();
+    
+    // Py_Initialize();
+    YACS::ENGINE::AutoGIL agil;
+    pValue = PyString_FromString(_python_parser_module.c_str());
+    pModule = PyImport_Import(pValue);
+    Py_DECREF(pValue);
+
+    if (!pModule)
+    {
+      errorMessage  = getPyErrorText();
+      errorMessage += "\nFailed to load ";
+      errorMessage += _python_parser_module;
+      errorMessage += ".\n";
+    }
+    else
+    {
+      pFunc = PyObject_GetAttrString(pModule, _python_parser_function.c_str());
+
+      if (pFunc && PyCallable_Check(pFunc))
+      {
+        pArgs = PyTuple_New(1);
+        pValue = PyString_FromString(python_code.c_str());
+        PyTuple_SetItem(pArgs, 0, pValue);
+        
+        pValue = PyObject_CallObject(pFunc, pArgs);
+        Py_DECREF(pArgs);
+        if (!pValue)
+            errorMessage = getPyErrorText();
+        else
+        {
+          if (!PyTuple_Check(pValue))
+          {
+            errorMessage += "Parsing function should return a tuple of two string lists.\n";
+          }
+          int n = PyTuple_Size(pValue);
+          if(n != 2)
+          {
+            errorMessage += "Parsing function should return two string lists.\n";
+          }
+          PyObject *pyList = PyTuple_GetItem(pValue, 0);
+          if(!PyList_Check(pyList))
+          {
+            errorMessage += "The first returned value of the parsing function"
+                            " should be a python list.\n";
+          }
+          else
+          {
+            n = PyList_Size(pyList);
+            for(int i=0; i<n; i++)
+            {
+              PyObject *fpy = PyList_GetItem(pyList,i);
+              PyObject *pAttribute;
+              
+              if(pAttribute = checkAndGetAttribute(fpy, "name", errorMessage))
+              {
+                if(!PyString_Check(pAttribute))
+                {
+                  errorMessage += "Attribute 'name' should be a string.\n";
+                  Py_DECREF(pAttribute);
+                }
+                else
+                {
+                  _functions.push_back(FunctionProperties());
+                  FunctionProperties& fcpp = _functions.back();
+                  fcpp._name=PyString_AsString(pAttribute);
+                  Py_DECREF(pAttribute);
+                  
+                  if(pAttribute = checkAndGetAttribute(fpy, "inputs", errorMessage))
+                    errorMessage += copyList(pAttribute, fcpp._input_ports);
+                  Py_XDECREF(pAttribute);
+                  
+                  if(pAttribute = checkAndGetAttribute(fpy, "outputs", errorMessage))
+                    // None value means no return statement in the function
+                    if(pAttribute != Py_None)
+                      errorMessage += copyList(pAttribute,fcpp._output_ports);
+                  Py_XDECREF(pAttribute);
+                    
+                  if(pAttribute = checkAndGetAttribute(fpy, "errors", errorMessage))
+                    errorMessage += copyList(pAttribute, fcpp._errors);
+                  Py_XDECREF(pAttribute);
+                  
+                  if(pAttribute = checkAndGetAttribute(fpy, "imports", errorMessage))
+                    errorMessage += copyList(pAttribute, fcpp._imports);
+                  Py_XDECREF(pAttribute);
+                }
+              }
+            }
+          }
+          errorMessage += copyList(PyTuple_GetItem(pValue, 1), _global_errors);
+          Py_DECREF(pValue);
+        }
+      }
+      else
+      {
+        errorMessage  = getPyErrorText();
+        errorMessage += "\nCannot find the parsing function '";
+        errorMessage += _python_parser_function;
+        errorMessage += "' in python module '";
+        errorMessage += _python_parser_module;
+        errorMessage += "'.\n";
+      }
+      Py_XDECREF(pFunc);
+      Py_DECREF(pModule);
+    }
+    
+    if(!errorMessage.empty())
+      throw Py2yacsException(errorMessage);
+    // Py_Finalize();
+}
+
+void Py2yacs::save(const std::string& file_path,
+                   const std::string& python_function)const
+{
+  YACS::ENGINE::Proc* schema = createProc(python_function);
+  schema->saveSchema(file_path);
+  delete schema;
+}
+
+YACS::ENGINE::Proc* Py2yacs::createProc(const std::string& python_function)const
+{
+  if(!_global_errors.empty())
+  {
+    std::string error_message = "The python script contains errors.\n";
+    std::list<std::string>::const_iterator it;
+    for(it = _global_errors.begin(); it != _global_errors.end(); it++)
+      error_message += (*it) + "\n";
+    throw Py2yacsException(error_message);
+  }
+  
+  // find function properties
+  std::list<FunctionProperties>::const_iterator fn_prop = _functions.begin();
+  while(fn_prop != _functions.end() && fn_prop->_name != python_function)
+    fn_prop++;
+  
+  if(fn_prop == _functions.end())
+  {
+    throw Py2yacsException(std::string("Function not found: ")+python_function);
+  }
+  
+  if(!fn_prop->_errors.empty())
+  {
+    std::string error_message = "Function contains errors.\n";
+    std::list<std::string>::const_iterator it;
+    for(it = fn_prop->_errors.begin(); it != fn_prop->_errors.end(); it++)
+      error_message += (*it) + "\n";
+    throw Py2yacsException(error_message);
+  }
+  
+  // add the call to the function at the end of the script
+  std::stringstream fn_call;
+  fn_call << std::endl;
+  std::list<std::string>::const_iterator it;
+  bool first = true;
+  for(it=fn_prop->_output_ports.begin();
+      it!=fn_prop->_output_ports.end();
+      it++)
+  {
+    if (!first)
+      fn_call << ",";
+    first = false;
+    fn_call << *it;
+  }
+  fn_call << "=" << python_function << "(";
+  first = true;
+  for(it = fn_prop->_input_ports.begin();
+      it != fn_prop->_input_ports.end();
+      it++)
+  {
+    if (!first)
+      fn_call << ",";
+    first = false;
+    fn_call << *it;
+  }
+  fn_call << ")" << std::endl;
+  std::string node_body = _python_code + fn_call.str();
+  
+  YACS::ENGINE::Proc* schema;
+  YACS::ENGINE::RuntimeSALOME::setRuntime();
+  YACS::ENGINE::RuntimeSALOME* runtime = YACS::ENGINE::getSALOMERuntime();
+  
+  // build the YACS schema
+  const char * node_name = "default_name";
+  schema = runtime->createProc("Schema");
+  YACS::ENGINE::InlineNode* node = runtime->createScriptNode("", node_name);
+  schema->edAddChild(node);
+  node->setScript(node_body);
+  YACS::ENGINE::TypeCode *tc_double = runtime->getTypeCode("double");
+  
+  for(it = fn_prop->_input_ports.begin();
+      it != fn_prop->_input_ports.end();
+      it++)
+    node->edAddInputPort(*it, tc_double);
+  
+  for(it = fn_prop->_output_ports.begin();
+      it != fn_prop->_output_ports.end();
+      it++)
+    node->edAddOutputPort(*it, tc_double);
+  
+  return schema;
+}
\ No newline at end of file
diff --git a/src/py2yacs/py2yacs.hxx b/src/py2yacs/py2yacs.hxx
new file mode 100644 (file)
index 0000000..ee052cd
--- /dev/null
@@ -0,0 +1,118 @@
+// Copyright (C) 2006-2016  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
+//
+#ifndef _PY2YACS_H_
+#define _PY2YACS_H_
+
+#ifdef WIN32
+#  if defined py2yacslib_EXPORTS
+#    define PY2YACSLIB_EXPORT __declspec( dllexport )
+#  else
+#    define PY2YACSLIB_EXPORT __declspec( dllimport )
+#  endif
+#else
+#  define PY2YACSLIB_EXPORT
+#endif
+
+
+#include <string>
+#include <list>
+#include <exception>
+
+class PY2YACSLIB_EXPORT Py2yacsException: std::exception
+{
+  public:
+    Py2yacsException(const std::string& what);
+    virtual ~Py2yacsException()throw ();
+    virtual const char *what() const throw ();
+  private:
+    std::string _what;
+};
+
+namespace YACS
+{
+  namespace ENGINE
+  {
+    class Proc;
+  };
+};
+
+struct PY2YACSLIB_EXPORT FunctionProperties
+{
+  public:
+    std::string _name;
+    std::list<std::string> _input_ports;
+    std::list<std::string> _output_ports;
+    std::list<std::string> _errors;
+    std::list<std::string> _imports;
+};
+
+/*! \brief Converter of a python script to a yacs schema.
+ *  This class converts a string containing a python script to a yacs schema
+ *  containing a python script node.
+ */
+class PY2YACSLIB_EXPORT Py2yacs
+{
+  public:
+    Py2yacs();
+    
+    /*!
+     * This constructor can be used if you want to define your own python parser.
+     * The parser function should be a python function and return a tuple of
+     * two lists.
+     * The first list contains the properties of all the functions in the script
+     * and the second one contains global errors.
+     * \param python_parser_module: name of the parser module
+     * \param python_parser_function: name of the parser function
+     */
+    Py2yacs(const std::string& python_parser_module,
+            const std::string& python_parser_function);
+
+    /*!
+     * \param python_code: contains the python code that will be converted
+     *                     to a yacs schema.
+     */
+    void load(const std::string& python_code);
+
+    /*!
+     * \param file_path: path to the xml file where to save the yacs schema.
+     * \param python_function: function defined in the python code that will be
+     *                         called in the yacs node.
+     */
+    void save(const std::string& file_path,
+              const std::string& python_function)const;
+
+    /*!
+     * A new schema is created.
+     * \param python_function: function defined in the python code that will be
+     *                         called in the yacs node.
+     */
+    YACS::ENGINE::Proc* createProc(const std::string& python_function)const;
+    
+    const std::list<std::string>& getGlobalErrors() const;
+    const std::list<FunctionProperties>& getFunctionProperties()const;
+
+  private:
+    std::string _python_parser_module;
+    std::string _python_parser_function;
+    std::list<FunctionProperties> _functions;
+    std::list<std::string> _global_errors;
+    std::string _python_code;
+};
+
+#endif //_PY2YACS_H_
\ No newline at end of file
diff --git a/src/py2yacs/py2yacs.py b/src/py2yacs/py2yacs.py
new file mode 100644 (file)
index 0000000..84ac997
--- /dev/null
@@ -0,0 +1,201 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 *-
+# Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
+#
+# Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+# CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, 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
+#
+import ast
+
+class FunctionProperties:
+  def __init__(self, function_name):
+    self.name = function_name
+    self.inputs=[]
+    self.outputs=None
+    self.errors=[]
+    self.imports=[]
+    pass
+  def __str__(self):
+    result = "Function:" + self.name + "\n"
+    result+= "  Inputs:" + str(self.inputs) + "\n"
+    result+= "  Outputs:"+ str(self.outputs) + "\n"
+    result+= "  Errors:" + str(self.errors) + "\n"
+    result+= "  Imports:"+ str(self.imports) + "\n"
+    return result
+
+class v(ast.NodeVisitor):
+  def visit_Module(self, node):
+    #print type(node).__name__, ":"
+    accepted_tokens = ["Import", "ImportFrom", "FunctionDef", "ClassDef"]
+    #print "module body:"
+    self.global_errors=[]
+    for e in node.body:
+      type_name = type(e).__name__
+      if type_name not in accepted_tokens:
+        error="py2yacs error at line %s: not accepted statement '%s'." % (
+               e.lineno, type_name)
+        self.global_errors.append(error)
+      #print type_name
+    #print "------------------------------------------------------------------"
+    self.functions=[]
+    self.lastfn=""
+    self.infunc=False
+    self.inargs=False
+    self.generic_visit(node)
+    pass
+  def visit_FunctionDef(self, node):
+    #print type(node).__name__, ":", node.name
+    if not self.infunc:
+      self.lastfn = FunctionProperties(node.name)
+      self.functions.append(self.lastfn)
+      self.infunc=True
+      #
+      self.generic_visit(node)
+      #
+      self.lastfn = None
+      self.infunc=False
+    pass
+  def visit_arguments(self, node):
+    #print type(node).__name__, ":"
+    self.inargs=True
+    self.generic_visit(node)
+    self.inargs=False
+    pass
+  def visit_Name(self, node):
+    if self.inargs :
+      #print type(node).__name__, ":", node.id
+      self.lastname=node.id
+      self.generic_visit(node)
+    pass
+  def visit_Param(self, node):
+    #print type(node).__name__, ":", self.lastname
+    self.lastfn.inputs.append(self.lastname)
+    pass
+  def visit_Return(self, node):
+    #print type(node).__name__, ":", node.value
+    if self.lastfn.outputs is not None :
+      error="py2yacs error at line %s: multiple returns." % node.lineno
+      self.lastfn.errors.append(error)
+      return
+    self.lastfn.outputs = []
+    if node.value is None :
+      pass
+    elif 'Tuple' == type(node.value).__name__ :
+      for e in node.value.elts:
+        if 'Name' == type(e).__name__ :
+          self.lastfn.outputs.append(e.id)
+        else :
+          error="py2yacs error at line %s: invalid type returned '%s'." % (
+                  node.lineno, type(e).__name__)
+          self.lastfn.errors.append(error)
+    else:
+      if 'Name' == type(node.value).__name__ :
+        self.lastfn.outputs.append(node.value.id)
+      else :
+        error="py2yacs error at line %s: invalid type returned '%s'." %(
+                  node.lineno, type(node.value).__name__)
+        self.lastfn.errors.append(error)
+        pass
+      pass
+    pass
+
+  def visit_ClassDef(self, node):
+    # just ignore classes
+    pass
+
+  def visit_Import(self, node):
+    if self.infunc:
+      for n in node.names:
+        self.lastfn.imports.append(n.name)
+  def visit_ImportFrom(self, node):
+    if self.infunc:
+      m=node.module
+      for n in node.names:
+        self.lastfn.imports.append(m+"."+n.name)
+
+class vtest(ast.NodeVisitor):
+  def generic_visit(self, node):
+    #print type(node).__name__
+    ast.NodeVisitor.generic_visit(self, node)
+
+def create_yacs_schema(text, fn_name, fn_args, fn_returns, file_name):
+  import pilot
+  import SALOMERuntime
+  #import loader
+  SALOMERuntime.RuntimeSALOME_setRuntime()
+  runtime = pilot.getRuntime()
+  schema = runtime.createProc("schema")
+  node = runtime.createFuncNode("", "default_name")
+  schema.edAddChild(node)
+  fncall = "\n%s=%s(%s)\n"%(",".join(fn_returns),
+                            fn_name,
+                            ",".join(fn_args))
+  node.setScript(text+fncall)
+  node.setFname(fn_name)
+  td=schema.getTypeCode("double")
+  for p in fn_args:
+    node.edAddInputPort(p, td)
+  for p in fn_returns:
+    node.edAddOutputPort(p, td)
+  schema.saveSchema(file_name)
+
+def get_properties(text_file):
+  bt=ast.parse(text_file)
+  w=v()
+  w.visit(bt)
+  return w.functions, w.global_errors
+
+if __name__ == '__main__':
+  import argparse
+  parser = argparse.ArgumentParser(description="Generate a YACS schema from a python file containing a function to run.")
+  parser.add_argument("file", help='Path to the python file')
+  parser.add_argument("-o","--output",
+        help='Path to the output file (yacs_schema.xml by default)',
+        default='yacs_schema.xml')
+  parser.add_argument("-d","--def_name",
+        help='Name of the function to call in the yacs node (_exec by default)',
+        default='_exec')
+  args = parser.parse_args()
+  with open(args.file, 'r') as f:
+    text_file = f.read()
+  #bt=ast.parse(text_file)
+  #w=vtest()
+  #w=v()
+  #w.visit(bt)
+  #print "global errors:", w.global_errors
+  #for f in w.functions:
+  #  print f
+  
+  fn_name = args.def_name
+  functions,errors = get_properties(text_file)
+  print "global errors:", errors
+  for f in functions:
+    print f
+  
+  fn_properties = next((f for f in functions if f.name == fn_name), None)
+  if fn_properties is not None :
+    if not fn_properties.errors :
+      create_yacs_schema(text_file, fn_name,
+                       fn_properties.inputs, fn_properties.outputs,
+                       args.output)
+    else:
+      print "\n".join(fn_properties.errors)
+  else:
+    print "Function not found:", fn_name
+  
\ No newline at end of file
index 3e24bbc7bc98a8ed4851ce9893f55b49d810c23f..b2b1c67131bc7111db79f045707f454e84703408 100644 (file)
@@ -145,6 +145,7 @@ SET(YACSRuntimeSALOME_HEADERS
   SalomeOptimizerLoop.hxx
   DistributedPythonNode.hxx
   PyOptimizerAlg.hxx
+  VisitorSalomeSaveState.hxx
   )
 
 # --- sources ---
@@ -211,6 +212,7 @@ SET(YACSRuntimeSALOME_SOURCES
   PyStdout.cxx                   
   SalomeOptimizerLoop.cxx        
   PyOptimizerAlg.cxx             
+  VisitorSalomeSaveState.cxx
   )
 
 # --- rules ---
index 3b56b5b94573e8c49965debf872058993467c9ba..0f2b8fceb9995056fa8aa85b0d0f6186490a2510 100644 (file)
@@ -324,7 +324,11 @@ LocalLibrary  LocalContainer::loadComponentLibrary(const std::string & aCompName
     }
   
 #ifndef WIN32
+#ifdef __APPLE__
+  std::string impl_name = std::string ("lib") + aCompName + std::string("Local.dylib");
+#else
   std::string impl_name = std::string ("lib") + aCompName + std::string("Local.so");
+#endif
   if(sprefix != "")
     impl_name = sprefix + std::string("/") + impl_name;
 #else
index edd891af98413381e2bebdb4c751263ac7ee27fc..8a2ccd7a71f93307a684e328290e467e6f0f2b08 100644 (file)
@@ -113,13 +113,12 @@ void DistributedPythonNode::load()
     if(!_container)
       throw Exception("No container specified !");
     SalomeContainer *containerCast0(dynamic_cast<SalomeContainer *>(_container));
-    SalomeHPContainer *containerCast1(dynamic_cast<SalomeHPContainer *>(_container));
+    SalomeHPContainerBase *containerCast1(dynamic_cast<SalomeHPContainerBase *>(_container));
     if(containerCast0)
       objContainer=containerCast0->getContainerPtr(this);
     else if(containerCast1)
       {
-        YACS::BASES::AutoCppPtr<SalomeContainerTmpForHP> tmpCont(SalomeContainerTmpForHP::BuildFrom(containerCast1,this));
-        objContainer=tmpCont->getContainerPtr(this);
+        objContainer=containerCast1->getContainerPtr(this);
       }
     else
       throw Exception("Unrecognized type of container ! Salome one is expected !");
index b6b7bc47d39a80505bef12575e6cddd93be503ff..e1db34ebbe40d79958a392846bc171e878ad6e5e 100644 (file)
@@ -127,13 +127,12 @@ Engines::Container_var PythonEntry::commonRemoteLoadPart2(InlineNode *reqNode, b
   if(!container)
     throw Exception("No container specified !");
   SalomeContainer *containerCast0(dynamic_cast<SalomeContainer *>(container));
-  SalomeHPContainer *containerCast1(dynamic_cast<SalomeHPContainer *>(container));
+  SalomeHPContainerBase *containerCast1(dynamic_cast<SalomeHPContainerBase *>(container));
   if(containerCast0)
     objContainer=containerCast0->getContainerPtr(reqNode);
   else if(containerCast1)
     {
-      YACS::BASES::AutoCppPtr<SalomeContainerTmpForHP> tmpCont(SalomeContainerTmpForHP::BuildFrom(containerCast1,reqNode));
-      objContainer=tmpCont->getContainerPtr(reqNode);
+      objContainer=containerCast1->getContainerPtr(reqNode);
     }
   else
     throw Exception("Unrecognized type of container ! Salome one is expected for PythonNode/PyFuncNode !");
index 71afc05a120a00fcb425057710da417c9ca3ba66..39b0b795fe7cf2f175b0838490e86c5566ceca76 100644 (file)
 #ifdef SALOME_KERNEL
 #include "SALOME_NamingService.hxx"
 #include "SALOME_LifeCycleCORBA.hxx"
+#include "SALOME_NamingService.hxx"
+#include "SALOME_ResourcesManager.hxx"
+#include "SALOME_ContainerManager.hxx"
+#include "SALOMEconfig.h"
+#include CORBA_CLIENT_HEADER(SALOME_ContainerManager)
+
 #endif
   
 #include <libxml/parser.h>
@@ -139,8 +145,8 @@ void RuntimeSALOME::setRuntime(long flags, int argc, char* argv[]) // singleton
 
 RuntimeSALOME* YACS::ENGINE::getSALOMERuntime()
 {
-  YASSERT(Runtime::_singleton);
-  return dynamic_cast< RuntimeSALOME* >(Runtime::_singleton);
+  YASSERT(RuntimeSALOME::getSingleton());
+  return dynamic_cast< RuntimeSALOME* >(RuntimeSALOME::getSingleton());
 }
 
 /**
@@ -428,6 +434,44 @@ void RuntimeSALOME::fini()
     }
 }
 
+std::vector< std::pair<std::string,int> > RuntimeSALOME::getCatalogOfComputeNodes() const
+{
+  CORBA::ORB_ptr orb(getOrb());
+  SALOME_NamingService namingService;
+  try
+  {
+    namingService.init_orb(orb);
+  }
+  catch(SALOME_Exception& e)
+  {
+    throw Exception("SalomeContainerToolsSpreadOverTheResDecorator::getParameters : Unable to contact the SALOME Naming Service");
+  }
+  CORBA::Object_var obj(namingService.Resolve(SALOME_ResourcesManager::_ResourcesManagerNameInNS));
+  if(CORBA::is_nil(obj))
+    throw Exception("SalomeContainerToolsSpreadOverTheResDecorator::getParameters : Unable to access to the resource manager !");
+  Engines::ResourcesManager_var resManager(Engines::ResourcesManager::_narrow(obj));
+  if(CORBA::is_nil(resManager))
+    throw Exception("SalomeContainerToolsSpreadOverTheResDecorator::getParameters : Internal error ! The entry attached to the res manager in NS does not have right type !");
+  std::vector< std::pair<std::string,int> > ret;
+  {
+    Engines::ResourceList *rl(0);
+    Engines::IntegerList *il(0);
+    resManager->ListAllAvailableResources(rl,il);
+    int sz(rl->length());
+    if(il->length()!=sz)
+      throw Exception("SalomeContainerToolsSpreadOverTheResDecorator::getParameters : Internal error ! Invalid size !");
+    ret.resize(sz);
+    for(int i=0;i<sz;i++)
+      {
+        std::string s((*rl)[i]);
+        ret[i]=std::pair<std::string,int>(s,(*il)[i]);
+      }
+    delete rl;
+    delete il;
+  }
+  return ret;
+}
+
 std::string RuntimeSALOME::getVersion() const
 {
 #ifdef YACS_DEVELOPMENT
@@ -806,6 +850,11 @@ InputPort* RuntimeSALOME::adaptNeutralToPython(InputPort* inport,
       //convertible type
       return new PyNeutral(inport);
     }
+  //last chance : an py output that is seq[objref] can be connected to a neutral input objref (P13268)
+  else if(type->kind()==Sequence && type->contentType()->kind()==Objref && inport->edGetType()->kind()==Objref)
+    {
+      return new PyNeutral(inport);
+    }
   //non convertible type
   stringstream msg;
   msg << "Cannot connect Python output port with type: " << type->id() ;
@@ -1771,22 +1820,22 @@ InputPort* RuntimeSALOME::adapt(InputCppPort* source,
 //   return result;
 // }
 
-CORBA::ORB_ptr RuntimeSALOME::getOrb()
+CORBA::ORB_ptr RuntimeSALOME::getOrb() const
 {
   return _orb;
 }
 
-PyObject * RuntimeSALOME::getPyOrb()
+PyObject * RuntimeSALOME::getPyOrb() const
 {
   return _pyorb;
 }
 
-PyObject * RuntimeSALOME::getBuiltins()
+PyObject * RuntimeSALOME::getBuiltins() const
 {
   return _bltins;
 }
 
-DynamicAny::DynAnyFactory_ptr RuntimeSALOME::getDynFactory()
+DynamicAny::DynAnyFactory_ptr RuntimeSALOME::getDynFactory() const
 {
   return _dynFactory;
 }
index c34b9594a953c39c5e7a54a0e1ca35fd38c51f6f..06515767dee92bd8749b4f74e4ba06a353896a48 100644 (file)
@@ -74,6 +74,8 @@ namespace YACS
 
     class YACSRUNTIMESALOME_EXPORT RuntimeSALOME: public Runtime
     {
+      static Runtime* getSingleton() { return Runtime::_singleton; }
+
     public:
       
       enum 
@@ -96,7 +98,7 @@ namespace YACS
 
       virtual void init(long flags, int argc, char* argv[]);
       virtual void fini();
-
+      virtual std::vector< std::pair<std::string,int> > getCatalogOfComputeNodes() const;
       virtual InputPort* createInputPort(const std::string& name,
                                          const std::string& impl,
                                          Node * node,
@@ -122,7 +124,9 @@ namespace YACS
       virtual ServiceInlineNode *createSInlineNode(const std::string& kind, const std::string& name);
       virtual ComponentInstance* createComponentInstance(const std::string& name,
                                                          const std::string& kind="");
+#ifndef SWIG
       virtual Container *createContainer(const std::string& kind="");
+#endif
       virtual WhileLoop* createWhileLoop(const std::string& name);
       virtual ForLoop* createForLoop(const std::string& name);
       virtual OptimizerLoop* createOptimizerLoop(const std::string& name,const std::string& algLib,
@@ -243,10 +247,10 @@ namespace YACS
 
       virtual ~RuntimeSALOME(); 
 
-      CORBA::ORB_ptr getOrb();
-      PyObject * getPyOrb();
-      PyObject * getBuiltins();
-      DynamicAny::DynAnyFactory_ptr getDynFactory();
+      CORBA::ORB_ptr getOrb() const;
+      PyObject * getPyOrb() const;
+      PyObject * getBuiltins() const;
+      DynamicAny::DynAnyFactory_ptr getDynFactory() const;
       omniORBpyAPI* getApi();
       PyObject * get_omnipy();
 
index f35fe882abfadb3117478533b32d6a940cf4bbf3..0e54975741eff60bbb33e6fb780d4715db1c8b9e 100644 (file)
@@ -81,8 +81,15 @@ void SalomeContainerMonoHelper::setContainer(const Task *askingNode, Engines::Co
 #endif
 }
 
+bool SalomeContainerMonoHelper::isKernelContNull() const
+{
+  return CORBA::is_nil(_trueCont);
+}
+
 void SalomeContainerMonoHelper::shutdown()
 {
+  if(CORBA::is_nil(_trueCont))
+    return ;
   try
   {
       DEBTRACE("shutdown SALOME container: " );
@@ -98,6 +105,15 @@ void SalomeContainerMonoHelper::shutdown()
   _trueCont=Engines::Container::_nil();
 }
 
+std::string SalomeContainerMonoHelper::getKernelContainerName() const
+{
+  if(CORBA::is_nil(_trueCont))
+    return std::string("NULL");
+  CORBA::String_var containerName(_trueCont->name());
+  std::string ret(containerName);
+  return ret;
+}
+
 SalomeContainerMonoHelper::~SalomeContainerMonoHelper()
 {
 }
index 08ecb7c70ab615ac1b164048939bb01084b13053..0236f81a4320579331accd3736436035583a8fab 100644 (file)
@@ -61,7 +61,9 @@ namespace YACS
       Engines::Container_var getContainer(const Task *askingNode) const;
       bool isAlreadyStarted(const Task *askingNode) const;
       void setContainer(const Task *askingNode, Engines::Container_var cont);
+      bool isKernelContNull() const;
       void shutdown();
+      std::string getKernelContainerName() const;
     private:
       ~SalomeContainerMonoHelper();
     public:
index aaf96813f95e203a948dc75bc651136a3c3a7bea..6f785c8539c79b124401b1c8f56ac1f348a6e4ef 100644 (file)
@@ -30,6 +30,7 @@
 #include "ServiceNode.hxx"
 #include "ComponentInstance.hxx"
 #include "SalomeContainerHelper.hxx"
+#include "SalomeHPContainerTools.hxx"
 #include "RuntimeSALOME.hxx"
 #include "Exception.hxx"
 
 
 using namespace YACS::ENGINE;
 
-SalomeContainerTools::SalomeContainerTools()
+/*!
+ * \param [in] compoNames
+ * \param [in,out] shutdownLevel
+ */
+void SalomeContainerToolsBase::Start(const std::vector<std::string>& compoNames, SalomeContainerHelper *schelp, SalomeContainerToolsBase& sct, int& shutdownLevel, const Container *cont, const Task *askingNode)
 {
-  /* Init ContainerParameters */
-  SALOME_LifeCycleCORBA::preSet(_params);
+  CORBA::ORB_ptr orb(getSALOMERuntime()->getOrb());
+  SALOME_NamingService ns;
+  try
+  {
+      ns.init_orb(orb);
+  }
+  catch(SALOME_Exception& e)
+  {
+      throw Exception("SalomeContainer::start : Unable to contact the SALOME Naming Service");
+  }
+  CORBA::Object_var obj(ns.Resolve(SALOME_ContainerManager::_ContainerManagerNameInNS));
+  Engines::ContainerManager_var contManager(Engines::ContainerManager::_narrow(obj));
+
+  bool isEmptyName;
+  std::string str(sct.getNotNullContainerName(cont,askingNode,isEmptyName));
+  DEBTRACE("SalomeContainer::start " << str <<";"<< sct.getHostName() <<";"<< schelp->getType());
+
+  // Finalize parameters with components found in the container
+
+  for(std::vector<std::string>::const_iterator iter=compoNames.begin();iter!=compoNames.end();iter++)
+    sct.addToComponentList(*iter);
+
+  Engines::ContainerParameters myparams(sct.getParameters());
+  {
+    std::string dftLauchMode(schelp->getDftLaunchMode());
+    myparams.mode=CORBA::string_dup(dftLauchMode.c_str());
+  }
+
+  //If a container_name is given try to find an already existing container in naming service
+  //If not found start a new container with the given parameters
+  if (dynamic_cast<SalomeContainerMonoHelper *>(schelp) && !isEmptyName)
+    {
+      myparams.mode=CORBA::string_dup("getorstart");
+    }
+
+  if (isEmptyName)
+    {
+      shutdownLevel=1;
+    }
+  //sct.setContainerName(str);
+  SetContainerNameOf(myparams,str);
+  Engines::Container_var trueCont(Engines::Container::_nil());
+  if(!isEmptyName && shutdownLevel==999)
+    {
+      //Make this only the first time start is called (_shutdownLevel==999)
+      //If the container is named, first try to get an existing container
+      //If there is an existing container use it and set the shutdown level to 3
+      //If there is no existing container, try to launch a new one and set the shutdown level to 2
+      myparams.mode="get";
+      try
+      {
+          trueCont=contManager->GiveContainer(myparams);
+      }
+      catch( const SALOME::SALOME_Exception& ex )
+      {
+          std::string msg="SalomeContainer::start : no existing container : ";
+          msg += '\n';
+          msg += ex.details.text.in();
+          DEBTRACE( msg );
+      }
+      catch(...)
+      {
+      }
+
+      if(!CORBA::is_nil(trueCont))
+        {
+          shutdownLevel=3;
+          DEBTRACE( "container found: " << str << " " << _shutdownLevel );
+        }
+      else
+        {
+          shutdownLevel=2;
+          myparams.mode="start";
+          DEBTRACE( "container not found: " << str << " " << _shutdownLevel);
+        }
+    }
+
+  if(CORBA::is_nil(trueCont))
+    try
+  {
+        // --- GiveContainer is used in batch mode to retreive launched containers,
+        //     and is equivalent to StartContainer when not in batch.
+        trueCont=contManager->GiveContainer(myparams);
+  }
+  catch( const SALOME::SALOME_Exception& ex )
+  {
+      std::string msg="SalomeContainer::start : Unable to launch container in Salome : ";
+      msg += '\n';
+      msg += ex.details.text.in();
+      throw Exception(msg);
+  }
+  catch(CORBA::COMM_FAILURE&)
+  {
+      throw Exception("SalomeContainer::start : Unable to launch container in Salome : CORBA Comm failure detected");
+  }
+  catch(CORBA::Exception&)
+  {
+      throw Exception("SalomeContainer::start : Unable to launch container in Salome : Unexpected CORBA failure detected");
+  }
+
+  if(CORBA::is_nil(trueCont))
+    throw Exception("SalomeContainer::start : Unable to launch container in Salome. Check your CatalogResources.xml file");
+
+  schelp->setContainer(askingNode,trueCont);
+
+  CORBA::String_var containerName(trueCont->name()),hostName(trueCont->getHostName());
+  std::cerr << "SalomeContainer launched : " << containerName << " " << hostName << " " << trueCont->getPID() << std::endl;
 }
 
-SalomeContainerTools::SalomeContainerTools(const SalomeContainerTools& other):_params(other._params),_propertyMap(other._propertyMap)
+CORBA::Object_ptr SalomeContainerToolsBase::LoadComponent(SalomeContainerHelper *launchModeType, Container *cont, Task *askingNode)
 {
+  DEBTRACE("SalomeContainer::loadComponent ");
+  const ComponentInstance *inst(askingNode?askingNode->getComponent():0);
+  {
+    YACS::BASES::AutoLocker<Container> alck(cont);//To be sure
+    if(!cont->isAlreadyStarted(askingNode))
+      cont->start(askingNode);
+  }
+  if(!inst)
+    throw Exception("SalomeContainerTools::LoadComponent : no instance of component in the task requesting for a load of its component !");
+  CORBA::Object_ptr objComponent=CORBA::Object::_nil();
+  {
+    YACS::BASES::AutoLocker<Container> alck(cont);//To be sure
+    std::string compoName(inst->getCompoName());
+    Engines::Container_var container(launchModeType->getContainer(askingNode));
+
+    char *reason;
+    bool isLoadable(container->load_component_Library(compoName.c_str(), reason));
+    if(isLoadable)
+      objComponent=CreateComponentInstance(cont,container,inst);
+  }
+  return objComponent;
 }
 
-void SalomeContainerTools::clearProperties()
+CORBA::Object_ptr SalomeContainerToolsBase::CreateComponentInstance(Container *cont, Engines::Container_ptr contPtr, const ComponentInstance *inst)
+{
+  if(!inst)
+    throw Exception("SalomeContainerTools::CreateComponentInstance : no instance of component in the task requesting for a load of its component !");
+  char *reason(0);
+  std::string compoName(inst->getCompoName());
+  CORBA::Object_ptr objComponent=CORBA::Object::_nil();
+  int studyid(1);
+  Proc* p(cont->getProc());
+  if(p)
+    {
+      std::string value(p->getProperty("DefaultStudyID"));
+      if(!value.empty())
+        studyid= atoi(value.c_str());
+    }
+  // prepare component instance properties
+  Engines::FieldsDict_var env(new Engines::FieldsDict);
+  std::map<std::string, std::string> properties(inst->getProperties());
+  if(p)
+    {
+      std::map<std::string,std::string> procMap=p->getProperties();
+      properties.insert(procMap.begin(),procMap.end());
+    }
+
+  std::map<std::string, std::string>::const_iterator itm;
+  env->length(properties.size());
+  int item=0;
+  for(itm = properties.begin(); itm != properties.end(); ++itm, item++)
+    {
+      DEBTRACE("envname="<<itm->first<<" envvalue="<< itm->second);
+      env[item].key= CORBA::string_dup(itm->first.c_str());
+      env[item].value <<= itm->second.c_str();
+    }
+
+  objComponent=contPtr->create_component_instance_env(compoName.c_str(), env, reason);
+  if(CORBA::is_nil(objComponent))
+    {
+      std::string text="Error while trying to create a new component: component '"+ compoName;
+      text=text+"' is not installed or it's a wrong name";
+      text += '\n';
+      text += reason;
+      CORBA::string_free(reason);
+      throw Exception(text);
+    }
+  return objComponent;
+}
+
+std::string SalomeContainerToolsBase::GetPlacementId(const SalomeContainerHelper *launchModeType, const Container *cont, const Task *askingNode)
+{
+  if(cont->isAlreadyStarted(askingNode))
+    {
+      Engines::Container_var container(launchModeType->getContainer(askingNode));
+      const char *what="/";
+      CORBA::String_var corbaStr(container->name());
+      std::string ret(corbaStr);
+
+      //Salome FOREVER ...
+      std::string::size_type i=ret.find_first_of(what,0);
+      i=ret.find_first_of(what, i==std::string::npos ? i:i+1);
+      if(i!=std::string::npos)
+        return ret.substr(i+1);
+      return ret;
+    }
+  else
+    return "Not placed yet !!!";
+}
+
+std::string SalomeContainerToolsBase::GetFullPlacementId(const SalomeContainerHelper *launchModeType, const Container *cont, const Task *askingNode)
+{
+  if(cont->isAlreadyStarted(askingNode))
+    {
+      Engines::Container_var container(launchModeType->getContainer(askingNode));
+      try
+      {
+          CORBA::String_var corbaStr(container->name());
+          std::string ret(corbaStr);
+          return ret;
+      }
+      catch(...)
+      {
+          return "Unknown_placement";
+      }
+    }
+  else
+    return "Not_placed_yet";
+}
+
+void SalomeContainerToolsBase::SetContainerNameOf(Engines::ContainerParameters& params, const std::string& name)
+{
+  params.container_name=CORBA::string_dup(name.c_str());
+}
+
+
+/////////////////////////////////
+
+SalomeContainerToolsInter::SalomeContainerToolsInter(const SalomeContainerToolsInter& other):_propertyMap(other._propertyMap)
+{
+}
+
+void SalomeContainerToolsInter::clearProperties()
 {
   _propertyMap.clear();
-  _params=Engines::ContainerParameters();
 }
 
-std::string SalomeContainerTools::getProperty(const std::string& name) const
+std::string SalomeContainerToolsInter::getProperty(const std::string& name) const
 {
   std::map<std::string,std::string>::const_iterator it(_propertyMap.find(name));
   if(it!=_propertyMap.end())
@@ -67,6 +296,69 @@ std::string SalomeContainerTools::getProperty(const std::string& name) const
     return std::string();
 }
 
+std::map<std::string,std::string> SalomeContainerToolsInter::getResourceProperties(const std::string& name) const
+{
+  std::map<std::string,std::string> properties;
+
+  YACS::ENGINE::RuntimeSALOME* runTime = YACS::ENGINE::getSALOMERuntime();
+  CORBA::ORB_ptr orb = runTime->getOrb();
+  if (!orb) return properties;
+  SALOME_NamingService namingService(orb);
+  SALOME_LifeCycleCORBA lcc(&namingService);
+  CORBA::Object_var obj = namingService.Resolve(SALOME_ResourcesManager::_ResourcesManagerNameInNS);
+  if (CORBA::is_nil(obj))
+    return properties;
+  Engines::ResourcesManager_var resManager = Engines::ResourcesManager::_narrow(obj);
+  if (CORBA::is_nil(resManager))
+    return properties;
+
+  std::ostringstream value;
+  Engines::ResourceDefinition_var resource_definition = resManager->GetResourceDefinition(name.c_str());
+  properties["hostname"]=resource_definition->hostname.in();
+  properties["OS"]=resource_definition->OS.in();
+  value.str(""); value << resource_definition->mem_mb;
+  properties["mem_mb"]=value.str();
+  value.str(""); value << resource_definition->cpu_clock;
+  properties["cpu_clock"]=value.str();
+  value.str(""); value << resource_definition->nb_node;
+  properties["nb_node"]=value.str();
+  value.str(""); value << resource_definition->nb_proc_per_node;
+  properties["nb_proc_per_node"]=value.str();
+  /*
+  properties["component_list"]="";
+  for(CORBA::ULong i=0; i < resource_definition->componentList.length(); i++)
+    {
+      if(i > 0)
+        properties["component_list"]=properties["component_list"]+",";
+      properties["component_list"]=properties["component_list"]+resource_definition->componentList[i].in();
+    }
+    */
+  return properties;
+}
+
+////////////////////////
+
+SalomeContainerTools::SalomeContainerTools()
+{
+  /* Init ContainerParameters */
+  SALOME_LifeCycleCORBA::preSet(_params);
+}
+
+SalomeContainerTools::SalomeContainerTools(const SalomeContainerTools& other):SalomeContainerToolsInter(other),_params(other._params)
+{
+}
+
+int SalomeContainerTools::getNumberOfCoresPerWorker() const
+{
+  return _params.resource_params.nb_proc_per_node;
+}
+
+void SalomeContainerTools::clearProperties()
+{
+  SalomeContainerToolsInter::clearProperties();
+  _params=Engines::ContainerParameters();
+}
+
 void SalomeContainerTools::setProperty(const std::string& name, const std::string& value)
 {
   //DEBTRACE("SalomeContainer::setProperty : " << name << " ; " << value);
@@ -235,6 +527,11 @@ void SalomeContainerTools::setContainerName(const std::string& name)
   SetContainerNameOf(_params,name);
 }
 
+std::string SalomeContainerTools::getHostName() const
+{
+  return std::string(_params.resource_params.hostname);
+}
+
 std::string SalomeContainerTools::getNotNullContainerName(const Container *contPtr, const Task *askingNode, bool& isEmpty) const
 {
   isEmpty=true;
@@ -257,272 +554,82 @@ std::string SalomeContainerTools::getNotNullContainerName(const Container *contP
     }
 }
 
-std::string SalomeContainerTools::getHostName() const
+//////////////////////////
+
+std::string SalomeContainerToolsDecoratorBase::getProperty(const std::string& name) const
 {
-  return std::string(_params.resource_params.hostname);
+  return _sct->getProperty(name);
 }
 
-void SalomeContainerTools::SetContainerNameOf(Engines::ContainerParameters& params, const std::string& name)
+void SalomeContainerToolsDecoratorBase::setProperty(const std::string& name, const std::string& value)
 {
-  params.container_name=CORBA::string_dup(name.c_str());
+  _sct->setProperty(name,value);
 }
 
-std::map<std::string,std::string> SalomeContainerTools::getResourceProperties(const std::string& name) const
+const std::map<std::string,std::string>& SalomeContainerToolsDecoratorBase::getProperties() const
 {
-  std::map<std::string,std::string> properties;
-
-  YACS::ENGINE::RuntimeSALOME* runTime = YACS::ENGINE::getSALOMERuntime();
-  CORBA::ORB_ptr orb = runTime->getOrb();
-  if (!orb) return properties;
-  SALOME_NamingService namingService(orb);
-  SALOME_LifeCycleCORBA lcc(&namingService);
-  CORBA::Object_var obj = namingService.Resolve(SALOME_ResourcesManager::_ResourcesManagerNameInNS);
-  if (CORBA::is_nil(obj))
-    return properties;
-  Engines::ResourcesManager_var resManager = Engines::ResourcesManager::_narrow(obj);
-  if (CORBA::is_nil(resManager))
-    return properties;
-
-  std::ostringstream value;
-  Engines::ResourceDefinition_var resource_definition = resManager->GetResourceDefinition(name.c_str());
-  properties["hostname"]=resource_definition->hostname.in();
-  properties["OS"]=resource_definition->OS.in();
-  value.str(""); value << resource_definition->mem_mb;
-  properties["mem_mb"]=value.str();
-  value.str(""); value << resource_definition->cpu_clock;
-  properties["cpu_clock"]=value.str();
-  value.str(""); value << resource_definition->nb_node;
-  properties["nb_node"]=value.str();
-  value.str(""); value << resource_definition->nb_proc_per_node;
-  properties["nb_proc_per_node"]=value.str();
-  /*
-  properties["component_list"]="";
-  for(CORBA::ULong i=0; i < resource_definition->componentList.length(); i++)
-    {
-      if(i > 0)
-        properties["component_list"]=properties["component_list"]+",";
-      properties["component_list"]=properties["component_list"]+resource_definition->componentList[i].in();
-    }
-    */
-  return properties;
+  return _sct->getProperties();
 }
 
-/*!
- * \param [in] compoNames
- * \param [in,out] shutdownLevel
- */
-void SalomeContainerTools::Start(const std::vector<std::string>& compoNames, SalomeContainerHelper *schelp, SalomeContainerTools& sct, int& shutdownLevel, const Container *cont, const Task *askingNode)
+void SalomeContainerToolsDecoratorBase::clearProperties()
 {
-  CORBA::ORB_ptr orb(getSALOMERuntime()->getOrb());
-  SALOME_NamingService ns;
-  try
-  {
-      ns.init_orb(orb);
-  }
-  catch(SALOME_Exception& e)
-  {
-      throw Exception("SalomeContainer::start : Unable to contact the SALOME Naming Service");
-  }
-  CORBA::Object_var obj(ns.Resolve(SALOME_ContainerManager::_ContainerManagerNameInNS));
-  Engines::ContainerManager_var contManager(Engines::ContainerManager::_narrow(obj));
-
-  bool isEmptyName;
-  std::string str(sct.getNotNullContainerName(cont,askingNode,isEmptyName));
-  DEBTRACE("SalomeContainer::start " << str <<";"<< _sct.getHostName() <<";"<<_type);
-
-  // Finalize parameters with components found in the container
-
-  for(std::vector<std::string>::const_iterator iter=compoNames.begin();iter!=compoNames.end();iter++)
-    sct.addToComponentList(*iter);
-
-  Engines::ContainerParameters myparams(sct.getParameters());
-  {
-    std::string dftLauchMode(schelp->getDftLaunchMode());
-    myparams.mode=CORBA::string_dup(dftLauchMode.c_str());
-  }
-
-  //If a container_name is given try to find an already existing container in naming service
-  //If not found start a new container with the given parameters
-  if (dynamic_cast<SalomeContainerMonoHelper *>(schelp) && !isEmptyName)
-    {
-      myparams.mode=CORBA::string_dup("getorstart");
-    }
-
-  if (isEmptyName)
-    {
-      shutdownLevel=1;
-    }
-  //sct.setContainerName(str);
-  SetContainerNameOf(myparams,str);
-  Engines::Container_var trueCont(Engines::Container::_nil());
-  if(!isEmptyName && shutdownLevel==999)
-    {
-      //Make this only the first time start is called (_shutdownLevel==999)
-      //If the container is named, first try to get an existing container
-      //If there is an existing container use it and set the shutdown level to 3
-      //If there is no existing container, try to launch a new one and set the shutdown level to 2
-      myparams.mode="get";
-      try
-      {
-          trueCont=contManager->GiveContainer(myparams);
-      }
-      catch( const SALOME::SALOME_Exception& ex )
-      {
-          std::string msg="SalomeContainer::start : no existing container : ";
-          msg += '\n';
-          msg += ex.details.text.in();
-          DEBTRACE( msg );
-      }
-      catch(...)
-      {
-      }
-
-      if(!CORBA::is_nil(trueCont))
-        {
-          shutdownLevel=3;
-          DEBTRACE( "container found: " << str << " " << _shutdownLevel );
-        }
-      else
-        {
-          shutdownLevel=2;
-          myparams.mode="start";
-          DEBTRACE( "container not found: " << str << " " << _shutdownLevel);
-        }
-    }
-
-  if(CORBA::is_nil(trueCont))
-    try
-  {
-        // --- GiveContainer is used in batch mode to retreive launched containers,
-        //     and is equivalent to StartContainer when not in batch.
-        trueCont=contManager->GiveContainer(myparams);
-  }
-  catch( const SALOME::SALOME_Exception& ex )
-  {
-      std::string msg="SalomeContainer::start : Unable to launch container in Salome : ";
-      msg += '\n';
-      msg += ex.details.text.in();
-      throw Exception(msg);
-  }
-  catch(CORBA::COMM_FAILURE&)
-  {
-      throw Exception("SalomeContainer::start : Unable to launch container in Salome : CORBA Comm failure detected");
-  }
-  catch(CORBA::Exception&)
-  {
-      throw Exception("SalomeContainer::start : Unable to launch container in Salome : Unexpected CORBA failure detected");
-  }
-
-  if(CORBA::is_nil(trueCont))
-    throw Exception("SalomeContainer::start : Unable to launch container in Salome. Check your CatalogResources.xml file");
-
-  schelp->setContainer(askingNode,trueCont);
+  _sct->clearProperties();
+}
 
-  CORBA::String_var containerName(trueCont->name()),hostName(trueCont->getHostName());
-  std::cerr << "SalomeContainer launched : " << containerName << " " << hostName << " " << trueCont->getPID() << std::endl;
+std::map<std::string,std::string> SalomeContainerToolsDecoratorBase::getResourceProperties(const std::string& name) const
+{
+  return _sct->getResourceProperties(name);
 }
 
-CORBA::Object_ptr SalomeContainerTools::LoadComponent(SalomeContainerHelper *launchModeType, Container *cont, Task *askingNode)
+void SalomeContainerToolsDecoratorBase::addToComponentList(const std::string& name)
 {
-  DEBTRACE("SalomeContainer::loadComponent ");
-  const ComponentInstance *inst(askingNode?askingNode->getComponent():0);
-  {
-    YACS::BASES::AutoLocker<Container> alck(cont);//To be sure
-    if(!cont->isAlreadyStarted(askingNode))
-      cont->start(askingNode);
-  }
-  if(!inst)
-    throw Exception("SalomeContainerTools::LoadComponent : no instance of component in the task requesting for a load of its component !");
-  CORBA::Object_ptr objComponent=CORBA::Object::_nil();
-  {
-    YACS::BASES::AutoLocker<Container> alck(cont);//To be sure
-    std::string compoName(inst->getCompoName());
-    Engines::Container_var container(launchModeType->getContainer(askingNode));
+  _sct->addToComponentList(name);
+}
 
-    char *reason;
-    bool isLoadable(container->load_component_Library(compoName.c_str(), reason));
-    if(isLoadable)
-      objComponent=CreateComponentInstance(cont,container,inst);
-  }
-  return objComponent;
+void SalomeContainerToolsDecoratorBase::addToResourceList(const std::string& name)
+{
+  _sct->addToResourceList(name);
 }
 
-CORBA::Object_ptr SalomeContainerTools::CreateComponentInstance(Container *cont, Engines::Container_ptr contPtr, const ComponentInstance *inst)
+Engines::ContainerParameters SalomeContainerToolsDecoratorBase::getParameters() const
 {
-  if(!inst)
-    throw Exception("SalomeContainerTools::CreateComponentInstance : no instance of component in the task requesting for a load of its component !");
-  char *reason(0);
-  std::string compoName(inst->getCompoName());
-  CORBA::Object_ptr objComponent=CORBA::Object::_nil();
-  Proc* p(cont->getProc());
-  // prepare component instance properties
-  Engines::FieldsDict_var env(new Engines::FieldsDict);
-  std::map<std::string, std::string> properties(inst->getProperties());
-  if(p)
-    {
-      std::map<std::string,std::string> procMap=p->getProperties();
-      properties.insert(procMap.begin(),procMap.end());
-    }
+  return _sct->getParameters();
+}
 
-  std::map<std::string, std::string>::const_iterator itm;
-  env->length(properties.size());
-  int item=0;
-  for(itm = properties.begin(); itm != properties.end(); ++itm, item++)
-    {
-      DEBTRACE("envname="<<itm->first<<" envvalue="<< itm->second);
-      env[item].key= CORBA::string_dup(itm->first.c_str());
-      env[item].value <<= itm->second.c_str();
-    }
+std::string SalomeContainerToolsDecoratorBase::getContainerName() const
+{
+  return _sct->getContainerName();
+}
 
-  objComponent=contPtr->create_component_instance_env(compoName.c_str(), env, reason);
-  if(CORBA::is_nil(objComponent))
-    {
-      std::string text="Error while trying to create a new component: component '"+ compoName;
-      text=text+"' is not installed or it's a wrong name";
-      text += '\n';
-      text += reason;
-      CORBA::string_free(reason);
-      throw Exception(text);
-    }
-  return objComponent;
+void SalomeContainerToolsDecoratorBase::setContainerName(const std::string& name)
+{
+  _sct->setContainerName(name);
 }
 
-std::string SalomeContainerTools::GetPlacementId(const SalomeContainerHelper *launchModeType, const Container *cont, const Task *askingNode)
+std::string SalomeContainerToolsDecoratorBase::getHostName() const
 {
-  if(cont->isAlreadyStarted(askingNode))
-    {
-      Engines::Container_var container(launchModeType->getContainer(askingNode));
-      const char *what="/";
-      CORBA::String_var corbaStr(container->name());
-      std::string ret(corbaStr);
+  return _sct->getHostName();
+}
 
-      //Salome FOREVER ...
-      std::string::size_type i=ret.find_first_of(what,0);
-      i=ret.find_first_of(what, i==std::string::npos ? i:i+1);
-      if(i!=std::string::npos)
-        return ret.substr(i+1);
-      return ret;
-    }
-  else
-    return "Not placed yet !!!";
+
+std::string SalomeContainerToolsDecoratorBase::getNotNullContainerName(const Container *contPtr, const Task *askingNode, bool& isEmpty) const
+{
+  return _sct->getNotNullContainerName(contPtr,askingNode,isEmpty);
 }
 
-std::string SalomeContainerTools::GetFullPlacementId(const SalomeContainerHelper *launchModeType, const Container *cont, const Task *askingNode)
+//////////////////////////////
+
+Engines::ContainerParameters SalomeContainerToolsSpreadOverTheResDecorator::getParameters() const
 {
-  if(cont->isAlreadyStarted(askingNode))
-    {
-      Engines::Container_var container(launchModeType->getContainer(askingNode));
-      try
-      {
-          CORBA::String_var corbaStr(container->name());
-          std::string ret(corbaStr);
-          return ret;
-      }
-      catch(...)
-      {
-          return "Unknown_placement";
-      }
-    }
-  else
-    return "Not_placed_yet";
+  Engines::ContainerParameters ret(getWorker()->getParameters());
+  std::string st(ret.resource_params.hostname);
+  if(!st.empty())
+    return ret;
+  int nbProcPerNode(ret.resource_params.nb_proc_per_node);
+  std::size_t iPos(_vh->locateTask(_node)),nPos(_vh->size());
+  if(_vh->size()!=_pg->getNumberOfWorkers(nbProcPerNode))
+    throw YACS::Exception("SalomeContainerToolsSpreadOverTheResDecorator::getParameters : Internal error !");
+  std::string zeMachine(_pg->deduceMachineFrom(iPos,nbProcPerNode));
+  ret.resource_params.hostname=CORBA::string_dup(zeMachine.c_str());
+  return ret;
 }
index 5955eee3f40f39e12c103dcb130492c42fad7a7f..793cf3488d563462b7ad3ad1d7b9430c4c9e5084 100644 (file)
@@ -37,34 +37,102 @@ namespace YACS
     class ComponentInstance;
     class SalomeContainerHelper;
 
-    class YACSRUNTIMESALOME_EXPORT SalomeContainerTools
+    class YACSRUNTIMESALOME_EXPORT SalomeContainerToolsBase
+    {
+    public:
+      virtual ~SalomeContainerToolsBase() { }
+      virtual std::string getProperty(const std::string& name) const = 0;
+      virtual void setProperty(const std::string& name, const std::string& value) = 0;
+      virtual const std::map<std::string,std::string>& getProperties() const = 0;
+      virtual void clearProperties() = 0;
+      virtual std::map<std::string,std::string> getResourceProperties(const std::string& name) const = 0;
+      virtual void addToComponentList(const std::string& name) = 0;
+      virtual void addToResourceList(const std::string& name) = 0;
+      virtual Engines::ContainerParameters getParameters() const = 0;
+      virtual std::string getContainerName() const = 0;
+      virtual void setContainerName(const std::string& name) = 0;
+      virtual std::string getHostName() const = 0;
+      virtual std::string getNotNullContainerName(const Container *contPtr, const Task *askingNode, bool& isEmpty) const = 0;
+    public:
+      static void Start(const std::vector<std::string>& compoNames, SalomeContainerHelper *schelp, SalomeContainerToolsBase& sct, int& shutdownLevel, const Container *cont, const Task *askingNode);
+      static CORBA::Object_ptr LoadComponent(SalomeContainerHelper *launchModeType, Container *cont, Task *askingNode);
+      static CORBA::Object_ptr CreateComponentInstance(Container *cont, Engines::Container_ptr contPtr, const ComponentInstance *inst);
+      static std::string GetPlacementId(const SalomeContainerHelper *launchModeType, const Container *cont, const Task *askingNode);
+      static std::string GetFullPlacementId(const SalomeContainerHelper *launchModeType, const Container *cont, const Task *askingNode);
+      static void SetContainerNameOf(Engines::ContainerParameters& params, const std::string& name);
+    };
+    
+    class YACSRUNTIMESALOME_EXPORT SalomeContainerToolsInter : public SalomeContainerToolsBase
+    {
+    public:
+      SalomeContainerToolsInter() { }
+      SalomeContainerToolsInter(const SalomeContainerToolsInter& other);
+      std::string getProperty(const std::string& name) const;
+      const std::map<std::string,std::string>& getProperties() const { return _propertyMap; }
+      void clearProperties();
+      std::map<std::string,std::string> getResourceProperties(const std::string& name) const;
+    protected:
+      std::map<std::string,std::string> _propertyMap;
+    };
+
+    class YACSRUNTIMESALOME_EXPORT SalomeContainerTools : public SalomeContainerToolsInter
     {
     public:
       SalomeContainerTools();
       SalomeContainerTools(const SalomeContainerTools& other);
+      int getNumberOfCoresPerWorker() const;
+    public:
+      Engines::ContainerParameters getParameters() const { return _params; }
+      void clearProperties();
+      void setProperty(const std::string& name, const std::string& value);
+      void addToComponentList(const std::string& name);
+      void addToResourceList(const std::string& name);
+      std::string getContainerName() const;
+      void setContainerName(const std::string& name);
+      std::string getHostName() const;
+      std::string getNotNullContainerName(const Container *contPtr, const Task *askingNode, bool& isEmpty) const;
+    protected:
+      Engines::ContainerParameters _params;
+    };
+
+    class PlayGround;
+    
+    class YACSRUNTIMESALOME_EXPORT SalomeContainerToolsDecoratorBase : public SalomeContainerToolsBase
+    {
+    protected:
+      SalomeContainerToolsDecoratorBase(SalomeContainerToolsBase *sct):_sct(sct) { }
+      SalomeContainerToolsBase *getWorker() { return _sct; }
+      const SalomeContainerToolsBase *getWorker() const { return _sct; }
+    public:
       std::string getProperty(const std::string& name) const;
       void setProperty(const std::string& name, const std::string& value);
-      const std::map<std::string,std::string>& getProperties() const { return _propertyMap; }
+      const std::map<std::string,std::string>& getProperties() const;
       void clearProperties();
       std::map<std::string,std::string> getResourceProperties(const std::string& name) const;
       void addToComponentList(const std::string& name);
       void addToResourceList(const std::string& name);
-    public:
+      Engines::ContainerParameters getParameters() const;
       std::string getContainerName() const;
       void setContainerName(const std::string& name);
-      std::string getNotNullContainerName(const Container *contPtr, const Task *askingNode, bool& isEmpty) const;
       std::string getHostName() const;
-      Engines::ContainerParameters getParameters() const { return _params; }
-      static void SetContainerNameOf(Engines::ContainerParameters& params, const std::string& name);
+      std::string getNotNullContainerName(const Container *contPtr, const Task *askingNode, bool& isEmpty) const;
+    private:
+      SalomeContainerToolsBase *_sct;
+    };
+
+    class SalomeHPContainerVectOfHelper;
+    
+    class YACSRUNTIMESALOME_EXPORT SalomeContainerToolsSpreadOverTheResDecorator : public SalomeContainerToolsDecoratorBase
+    {
     public:
-      static void Start(const std::vector<std::string>& compoNames, SalomeContainerHelper *schelp, SalomeContainerTools& sct, int& shutdownLevel, const Container *cont, const Task *askingNode);
-      static CORBA::Object_ptr LoadComponent(SalomeContainerHelper *launchModeType, Container *cont, Task *askingNode);
-      static CORBA::Object_ptr CreateComponentInstance(Container *cont, Engines::Container_ptr contPtr, const ComponentInstance *inst);
-      static std::string GetPlacementId(const SalomeContainerHelper *launchModeType, const Container *cont, const Task *askingNode);
-      static std::string GetFullPlacementId(const SalomeContainerHelper *launchModeType, const Container *cont, const Task *askingNode);
-    protected:
-      std::map<std::string,std::string> _propertyMap;
-      Engines::ContainerParameters _params;
+      SalomeContainerToolsSpreadOverTheResDecorator(SalomeContainerToolsBase *sct, const PlayGround *pg, const SalomeHPContainerVectOfHelper *vh, const Task *node):SalomeContainerToolsDecoratorBase(sct),_pg(pg),_vh(vh),_node(node) { }
+      Engines::ContainerParameters getParameters() const;
+    private:
+      static std::string DeduceMachineFrom(const std::vector< std::pair<std::string,int> >& allResInfo, int iPos, int sz, int nbProcPerNode);
+    private:
+      const PlayGround *_pg;
+      const SalomeHPContainerVectOfHelper *_vh;
+      const Task *_node;
     };
   }
 }
index b7204fd3e69749f004f6f115b4eb6be91568f83e..b198882dbf49419b0b5d0490d258180910b618ab 100644 (file)
@@ -21,6 +21,7 @@
 #include "SalomeHPComponent.hxx"
 #include "SalomeContainerTmpForHP.hxx"
 #include "AutoLocker.hxx"
+#include "AutoRefCnt.hxx"
 
 #include <algorithm>
 
@@ -28,108 +29,238 @@ using namespace YACS::ENGINE;
 
 const char SalomeHPContainer::KIND[]="HPSalome";
 
-SalomeHPContainer::SalomeHPContainer():_shutdownLevel(999)
+SalomeHPContainerBase::SalomeHPContainerBase(SalomeHPContainerVectOfHelper *resShared):_launchModeType(resShared),_shutdownLevel(999)
 {
 }
 
-SalomeHPContainer::SalomeHPContainer(const SalomeHPContainer& other):_componentNames(other._componentNames),_shutdownLevel(999),_sct(other._sct),_initScript(other._initScript)
+SalomeHPContainerBase::SalomeHPContainerBase(const SalomeHPContainerBase& other):_shutdownLevel(999),_launchModeType(new SalomeHPContainerVectOfHelper),_initScript(other._initScript)
 {
 }
 
-void SalomeHPContainer::setSizeOfPool(int sz)
+SalomeHPContainer *SalomeHPContainerBase::getTheBoss()
 {
-  _launchModeType.resize(sz);
+  HomogeneousPoolContainer *ret(this);
+  while(ret->getDirectFather())
+    ret=ret->getDirectFather();
+  SalomeHPContainer *retC(dynamic_cast<SalomeHPContainer *>(ret));
+  if(!retC)
+    throw Exception("SalomeHPContainerBase::getTheBoss : unexpected type of object !");
+  return retC;
 }
 
-int SalomeHPContainer::getSizeOfPool() const
+const SalomeHPContainer *SalomeHPContainerBase::getTheBoss() const
 {
-  return _launchModeType.size();
+  const HomogeneousPoolContainer *ret(this);
+  while(ret->getDirectFather())
+    ret=ret->getDirectFather();
+  const SalomeHPContainer *retC(dynamic_cast<const SalomeHPContainer *>(ret));
+  if(!retC)
+    throw Exception("SalomeHPContainerBase::getTheBoss : unexpected type of object !");
+  return retC;
 }
 
-std::size_t SalomeHPContainer::getNumberOfFreePlace() const
+void SalomeHPContainerBase::startInternal(const Task *askingNode, SalomeContainerToolsBase& sct, const std::vector<std::string>& compoNames)
 {
-  return _launchModeType.getNumberOfFreePlace();
+  SalomeContainerMonoHelper *helper(_launchModeType->getHelperOfTaskThreadSafe(askingNode));
+  SalomeContainerTools::Start(compoNames,helper,sct,_shutdownLevel,this,askingNode);
 }
 
-void SalomeHPContainer::allocateFor(const std::vector<const Task *>& nodes)
+void SalomeHPContainerBase::shutdown(int level)
 {
-  _launchModeType.allocateFor(nodes);
+  if(level < _shutdownLevel)
+      return;
+  _shutdownLevel=999;
+  _launchModeType->shutdown();
 }
 
-void SalomeHPContainer::release(const Task *node)
+SalomeHPContainerBase::SalomeHPContainerBase(SalomeHPContainerVectOfHelper *resShared, bool isRefEaten):_launchModeType(resShared)
 {
-  _launchModeType.release(node);
+  if(!isRefEaten)
+    if(_launchModeType.isNotNull())
+      _launchModeType->incrRef();
 }
 
-SalomeHPContainer::~SalomeHPContainer()
+bool SalomeHPContainerBase::isAlreadyStarted(const Task *askingNode) const
 {
+  const SalomeContainerMonoHelper *helper(_launchModeType->getHelperOfTaskThreadSafe(askingNode));
+  return helper->isAlreadyStarted(askingNode);
 }
 
-void SalomeHPContainer::lock()
+void SalomeHPContainerBase::release(const Task *node)
 {
-  _mutex.lock();
+  _launchModeType->release(node);
 }
 
-void SalomeHPContainer::unLock()
+void SalomeHPContainerBase::lock()
 {
-  _mutex.unLock();
+  _launchModeType->lock();
 }
 
-std::string SalomeHPContainer::getKind() const
+void SalomeHPContainerBase::unLock()
 {
-  return KIND;
+  _launchModeType->unLock();
 }
 
-std::string SalomeHPContainer::getDiscreminantStrOfThis(const Task *askingNode) const
+void SalomeHPContainerBase::setSizeOfPool(int sz)
 {
-  YACS::BASES::AutoCppPtr<SalomeContainerTmpForHP> tmpCont(SalomeContainerTmpForHP::BuildFrom(this,askingNode));
-  return tmpCont->getDiscreminantStrOfThis(askingNode);
+  _launchModeType->resize(sz);
 }
 
-bool SalomeHPContainer::isAlreadyStarted(const Task *askingNode) const
+int SalomeHPContainerBase::getSizeOfPool() const
 {
-  const SalomeContainerMonoHelper *helper(_launchModeType.getHelperOfTaskThreadSafe(this,askingNode));
-  return helper->isAlreadyStarted(askingNode);
+  return _launchModeType->size();
 }
 
-void SalomeHPContainer::start(const Task *askingNode) throw(YACS::Exception)
+void SalomeHPContainerBase::setProperty(const std::string& name,const std::string& value)
 {
-  SalomeContainerMonoHelper *helper(_launchModeType.getHelperOfTaskThreadSafe(this,askingNode));
-  SalomeContainerTools::Start(_componentNames,helper,_sct,_shutdownLevel,this,askingNode);
+  if(name==AOC_ENTRY)//no sense to set it ! It is always true ! ignore it !
+    return ;
+  else if(name==SIZE_OF_POOL_KEY)
+    {
+      std::istringstream iss(value);
+      int val(0);
+      iss >> val;
+      setSizeOfPool(val);
+    }
+  else if(name==INITIALIZE_SCRIPT_KEY)
+    {
+      _initScript=value;
+    }
+  else
+    getTheBoss()->getContainerInfo().setProperty(name,value);
 }
 
-void SalomeHPContainer::shutdown(int level)
+std::string SalomeHPContainerBase::getProperty(const std::string& name) const
 {
-  if(level < _shutdownLevel)
-      return;
-  _shutdownLevel=999;
-  for(std::size_t i=0;i<_launchModeType.size();i++)
+  if(name==AOC_ENTRY)
     {
-      SalomeContainerMonoHelper *helper(_launchModeType.at(i));
-      helper->shutdown();
+      return std::string("1");
     }
+  else if(name==SIZE_OF_POOL_KEY)
+    {
+      std::ostringstream oss; oss << getSizeOfPool();
+      return oss.str();
+    }
+  else if(name==INITIALIZE_SCRIPT_KEY)
+    {
+      return _initScript;
+    }
+  else
+    return getTheBoss()->getContainerInfo().getProperty(name);
+}
+
+std::map<std::string,std::string> SalomeHPContainerBase::getProperties() const
+{
+  std::map<std::string,std::string> ret(getTheBoss()->getContainerInfo().getProperties());
+  std::ostringstream oss; oss << getSizeOfPool();
+  ret[SIZE_OF_POOL_KEY]=oss.str();
+  if(!_initScript.empty())
+    ret[INITIALIZE_SCRIPT_KEY]=_initScript;
+  return ret;
+}
+
+void SalomeHPContainerBase::clearProperties()
+{
+  _initScript.clear();
+  getTheBoss()->getContainerInfo().clearProperties();
 }
 
-std::string SalomeHPContainer::getPlacementId(const Task *askingNode) const
+std::string SalomeHPContainerBase::getPlacementId(const Task *askingNode) const
 {
   const SalomeContainerMonoHelper *helper(0);
   {
-    YACS::BASES::AutoLocker<Container> alckCont(const_cast<SalomeHPContainer *>(this));
-    helper=_launchModeType.getHelperOfTask(askingNode);
+    YACS::BASES::AutoLocker<Container> alckCont(const_cast<SalomeHPContainerBase *>(this));
+    helper=_launchModeType->getHelperOfTask(askingNode);
   }
   return SalomeContainerTools::GetPlacementId(helper,this,askingNode);
 }
 
-std::string SalomeHPContainer::getFullPlacementId(const Task *askingNode) const
+std::string SalomeHPContainerBase::getFullPlacementId(const Task *askingNode) const
 {
   const SalomeContainerMonoHelper *helper(0);
   {
-    YACS::BASES::AutoLocker<Container> alckCont(const_cast<SalomeHPContainer *>(this));
-    helper=_launchModeType.getHelperOfTask(askingNode);
+    YACS::BASES::AutoLocker<Container> alckCont(const_cast<SalomeHPContainerBase *>(this));
+    helper=_launchModeType->getHelperOfTask(askingNode);
   }
   return SalomeContainerTools::GetFullPlacementId(helper,this,askingNode);
 }
 
+std::map<std::string,std::string> SalomeHPContainerBase::getResourceProperties(const std::string& name) const
+{
+  return getTheBoss()->getResourceProperties(name);
+}
+
+void SalomeHPContainerBase::addComponentName(const std::string& name)
+{
+  getTheBoss()->addComponentNameSpe(name);
+}
+
+void SalomeHPContainerBase::checkCapabilityToDealWith(const ComponentInstance *inst) const throw(YACS::Exception)
+{
+  getTheBoss()->checkCapabilityToDealWith(inst);
+}
+
+YACS::BASES::AutoRefCnt<HomogeneousPoolContainer> SalomeHPContainerBase::decorate(YACS::BASES::AutoConstRefCnt<PartDefinition> pd)
+{
+  YACS::BASES::AutoRefCnt<HomogeneousPoolContainer> ret(new SalomeHPContainerShared(pd,_launchModeType,this));
+  return ret;
+}
+
+Engines::Container_var SalomeHPContainerBase::getContainerPtr(const Task *askingNode) const
+{
+  const SalomeContainerMonoHelper *helper(0);
+  {
+    YACS::BASES::AutoLocker<SalomeHPContainerBase> alck(const_cast<SalomeHPContainerBase *>(this));
+    helper=_launchModeType->getHelperOfTask(askingNode);
+  }
+  return helper->getContainer(NULL);
+}
+
+std::vector<std::string> SalomeHPContainerBase::getKernelContainerNames() const
+{
+  return _launchModeType->getKernelContainerNames();
+}
+
+////////////////
+
+SalomeHPContainer::SalomeHPContainer():SalomeHPContainerBase(new SalomeHPContainerVectOfHelper)
+{
+}
+
+SalomeHPContainer::SalomeHPContainer(const SalomeHPContainer& other):SalomeHPContainerBase(other),_sct(other._sct),_componentNames(other._componentNames)
+{
+}
+
+std::size_t SalomeHPContainer::getNumberOfFreePlace() const
+{
+  return _launchModeType->getNumberOfFreePlace();
+}
+
+void SalomeHPContainer::allocateFor(const std::vector<const Task *>& nodes)
+{
+  _launchModeType->allocateFor(nodes);
+}
+
+SalomeHPContainer::~SalomeHPContainer()
+{
+}
+
+std::string SalomeHPContainer::getKind() const
+{
+  return KIND;
+}
+
+std::string SalomeHPContainer::getDiscreminantStrOfThis(const Task *askingNode) const
+{
+  YACS::BASES::AutoCppPtr<SalomeContainerTmpForHP> tmpCont(SalomeContainerTmpForHP::BuildFrom(this,askingNode));
+  return tmpCont->getDiscreminantStrOfThis(askingNode);
+}
+
+void SalomeHPContainer::start(const Task *askingNode) throw(Exception)
+{
+  startInternal(askingNode,_sct,_componentNames);
+}
+
 /*!
  * It is not a bug here ! clone for homogeneous container is not supposed to be copied !
  */
@@ -144,72 +275,100 @@ Container *SalomeHPContainer::cloneAlways() const
   return new SalomeHPContainer(*this);
 }
 
-void SalomeHPContainer::setProperty(const std::string& name,const std::string& value)
+int SalomeHPContainer::getNumberOfCoresPerWorker() const
 {
-  if(name==AOC_ENTRY)//no sense to set it ! It is always true ! ignore it !
-    return ;
-  else if(name==SIZE_OF_POOL_KEY)
-    {
-      std::istringstream iss(value);
-      int val(0);
-      iss >> val;
-      setSizeOfPool(val);
-    }
-  else if(name==INITIALIZE_SCRIPT_KEY)
-    {
-      _initScript=value;
-    }
-  else
-    _sct.setProperty(name,value);
+  return _sct.getNumberOfCoresPerWorker();
 }
 
-std::string SalomeHPContainer::getProperty(const std::string& name) const
+std::map<std::string,std::string> SalomeHPContainer::getResourcePropertiesSpe(const std::string& name) const
 {
-  if(name==AOC_ENTRY)
-    {
-      return std::string("1");
-    }
-  else if(name==SIZE_OF_POOL_KEY)
-    {
-      std::ostringstream oss; oss << getSizeOfPool();
-      return oss.str();
-    }
-  else if(name==INITIALIZE_SCRIPT_KEY)
-    {
-      return _initScript;
-    }
-  else
-    return _sct.getProperty(name);
+  return _sct.getResourceProperties(name);
 }
 
-void SalomeHPContainer::clearProperties()
+void SalomeHPContainer::addComponentNameSpe(const std::string& name)
 {
-  _initScript.clear();
-  _sct.clearProperties();
+  _componentNames.push_back(name);
 }
 
-void SalomeHPContainer::addComponentName(const std::string& name)
+void SalomeHPContainer::checkCapabilityToDealWithSpe(const ComponentInstance *inst) const throw(YACS::Exception)
 {
-  _componentNames.push_back(name);
+  if(inst->getKind()!=SalomeHPComponent::KIND)
+    throw Exception("SalomeHPContainer::checkCapabilityToDealWithSpe : SalomeContainer is not able to deal with this type of ComponentInstance.");
 }
 
-std::map<std::string,std::string> SalomeHPContainer::getProperties() const
+void SalomeHPContainer::forYourTestsOnly(ForTestOmlyHPContCls *data) const
 {
-  std::map<std::string,std::string> ret(_sct.getProperties());
-  std::ostringstream oss; oss << getSizeOfPool();
-  ret[SIZE_OF_POOL_KEY]=oss.str();
-  if(!_initScript.empty())
-    ret[INITIALIZE_SCRIPT_KEY]=_initScript;
-  return ret;
+  data->setContainerType("HPContainer");
 }
 
-std::map<std::string,std::string> SalomeHPContainer::getResourceProperties(const std::string& name) const
+//////////////////////////////////
+
+SalomeHPContainerShared::SalomeHPContainerShared(YACS::BASES::AutoConstRefCnt<PartDefinition> pd, SalomeHPContainerVectOfHelper *resShared, SalomeHPContainerBase *directFather):SalomeHPContainerBase(resShared,false),_pd(pd)
 {
-  return _sct.getResourceProperties(name);
+  if(!directFather)
+    throw Exception("SalomeHPContainerShared : NULL pointer not allowed !");
+  _directFather.takeRef(directFather);
 }
 
-void SalomeHPContainer::checkCapabilityToDealWith(const ComponentInstance *inst) const throw(YACS::Exception)
+std::string SalomeHPContainerShared::getKind() const
 {
-  if(inst->getKind()!=SalomeHPComponent::KIND)
-    throw Exception("SalomeHPContainer::checkCapabilityToDealWith : SalomeContainer is not able to deal with this type of ComponentInstance.");
+  return SalomeHPContainer::KIND;
 }
+
+void SalomeHPContainerShared::prepareMaskForExecution() const
+{
+  _idsOfKernelContainers=_pd->computeWorkerIdsCovered(getNumberOfCoresPerWorker());
+}
+
+/*!
+ * It is not a bug here ! clone for homogeneous container is not supposed to be copied !
+ */
+Container *SalomeHPContainerShared::clone() const
+{
+  incrRef();
+  return const_cast<SalomeHPContainerShared*>(this);
+}
+
+Container *SalomeHPContainerShared::cloneAlways() const
+{
+  throw Exception("SalomeHPContainerShared::cloneAlways : you are not supposed to be in this situation ! This type of container has only existence during execution !");
+}
+
+std::string SalomeHPContainerShared::getName() const
+{
+  return getTheBoss()->getName();
+}
+
+std::string SalomeHPContainerShared::getDiscreminantStrOfThis(const Task *askingNode) const
+{
+  return getTheBoss()->getDiscreminantStrOfThis(askingNode);
+}
+
+void SalomeHPContainerShared::start(const Task *askingNode) throw(Exception)
+{
+  SalomeContainerToolsSpreadOverTheResDecorator sct(&getTheBoss()->getContainerInfo(),_pd->getPlayGround(),_launchModeType,askingNode);
+  startInternal(askingNode,sct,getTheBoss()->getComponentNames());
+}
+
+void SalomeHPContainerShared::allocateFor(const std::vector<const Task *>& nodes)
+{
+  _launchModeType->allocateForAmong(_idsOfKernelContainers,nodes);
+}
+
+std::size_t SalomeHPContainerShared::getNumberOfFreePlace() const
+{
+  return _launchModeType->getNumberOfFreePlaceAmong(_idsOfKernelContainers);
+}
+
+void SalomeHPContainerShared::forYourTestsOnly(ForTestOmlyHPContCls *data) const
+{
+  data->setContainerType("HPContainerShared");
+  data->setPD(_pd);
+  data->setIDS(_idsOfKernelContainers);
+}
+
+/*
+ * SalomeHPContainerVectOfHelper is an holder of vector of SalomeContainerMonoHelper (holding itself a Kernel Container)
+ * SalomeContainerTools is a Engines::ContainerParameters holder. It is the data keeper for GiveContainer invokation.
+ * 
+ */
index f97bf8dfa76e9bc31a33e7125bff473c6cbe325a..c6fedbd3461a4914ddad0b8b6cc323191461d928 100644 (file)
 #include "SalomeContainerHelper.hxx"
 #include "SalomeContainerTools.hxx"
 #include "SalomeHPContainerTools.hxx"
+#include "PlayGround.hxx"
+
 #include "Mutex.hxx"
+#include "AutoRefCnt.hxx"
+
 #include <string>
 #include <vector>
 #include <map>
@@ -39,49 +43,83 @@ namespace YACS
   {
     class Task;
     class SalomeComponent;
-
-    class YACSRUNTIMESALOME_EXPORT SalomeHPContainer : public HomogeneousPoolContainer
+    class SalomeHPContainer;
+    
+    class YACSRUNTIMESALOME_EXPORT SalomeHPContainerBase : public HomogeneousPoolContainer
     {
+    protected:
+      SalomeHPContainerBase(SalomeHPContainerVectOfHelper *resShared);
+      SalomeHPContainerBase(SalomeHPContainerVectOfHelper *resShared, bool isRefEaten);
+      SalomeHPContainerBase(const SalomeHPContainerBase& other);
+      void startInternal(const Task *askingNode, SalomeContainerToolsBase& sct, const std::vector<std::string>& compoNames);
+      SalomeHPContainer *getTheBoss();
+      const SalomeHPContainer *getTheBoss() const;
     public:
-      SalomeHPContainer();
-      SalomeHPContainer(const SalomeHPContainer& other);
-      //HP specific part
-      void setSizeOfPool(int sz);
-      int getSizeOfPool() const;
-      std::size_t getNumberOfFreePlace() const;
-      void allocateFor(const std::vector<const Task *>& nodes);
       void release(const Task *node);
+      //
+      bool isAlreadyStarted(const Task *askingNode) const;
+      void shutdown(int level);
       //! For thread safety for concurrent load operation on same Container.
       void lock();
       //! For thread safety for concurrent load operation on same Container.
       void unLock();
+      void setSizeOfPool(int sz);
+      int getSizeOfPool() const;
+      void setProperty(const std::string& name,const std::string& value);
+      std::string getProperty(const std::string& name) const;
+      std::map<std::string,std::string> getProperties() const;
+      void clearProperties();
+      std::string getPlacementId(const Task *askingNode) const;
+      std::string getFullPlacementId(const Task *askingNode) const;
+      std::map<std::string,std::string> getResourceProperties(const std::string& name) const;
+      void addComponentName(const std::string& name);
+      void checkCapabilityToDealWith(const ComponentInstance *inst) const throw(YACS::Exception);
+      Engines::Container_var getContainerPtr(const Task *askingNode) const;
+      std::vector<std::string> getKernelContainerNames() const;
+    public:
+      int getShutdownLev() const { return _shutdownLevel; }
+      YACS::BASES::AutoRefCnt<HomogeneousPoolContainer> decorate(YACS::BASES::AutoConstRefCnt<PartDefinition> pd);
+#ifndef SWIG
+      const SalomeHPContainerVectOfHelper *getDirectAccessToVecOfCont() const { return _launchModeType; }
+#endif
+    protected:
+      int _shutdownLevel;
+      YACS::BASES::AutoRefCnt<SalomeHPContainerVectOfHelper> _launchModeType;
+      std::string _initScript;
+    };
+    
+    class YACSRUNTIMESALOME_EXPORT SalomeHPContainer : public SalomeHPContainerBase
+    {
+    public:
+      SalomeHPContainer();
+      SalomeHPContainer(const SalomeHPContainer& other);
+      //HP specific part
+      std::size_t getNumberOfFreePlace() const;
+      void allocateFor(const std::vector<const Task *>& nodes);
       //
       std::string getKind() const;
       std::string getDiscreminantStrOfThis(const Task *askingNode) const;
-      bool isAlreadyStarted(const Task *askingNode) const;
       void start(const Task *askingNode) throw(Exception);
-      void shutdown(int level);
-      std::string getPlacementId(const Task *askingNode) const;
-      std::string getFullPlacementId(const Task *askingNode) const;
       Container *clone() const;
       Container *cloneAlways() const;
-      void setProperty(const std::string& name,const std::string& value);
-      std::string getProperty(const std::string& name) const;
-      void clearProperties();
-      void addComponentName(const std::string& name);
-      std::map<std::string,std::string> getProperties() const;
-      std::map<std::string,std::string> getResourceProperties(const std::string& name) const;
-      void checkCapabilityToDealWith(const ComponentInstance *inst) const throw(YACS::Exception);
+      int getNumberOfCoresPerWorker() const;
+      //! do nothing. because no special actions to do. Only for decorators
+      void prepareMaskForExecution() const { }
       //
 #ifndef SWIG
-      std::size_t locateTask(const Task *askingNode) const { return _launchModeType.locateTask(askingNode); }
+      void forYourTestsOnly(ForTestOmlyHPContCls *data) const;
+      std::map<std::string,std::string> getResourcePropertiesSpe(const std::string& name) const;
+      void addComponentNameSpe(const std::string& name);
+      void checkCapabilityToDealWithSpe(const ComponentInstance *inst) const throw(YACS::Exception);
+      std::size_t locateTask(const Task *askingNode) const { return _launchModeType->locateTask(askingNode); }
       const SalomeContainerTools &getContainerInfo() const { return _sct; }
+      SalomeContainerTools &getContainerInfo() { return _sct; }
       std::vector<std::string> getComponentNames() const { return _componentNames; }
-      int getShutdownLev() const { return _shutdownLevel; }
-      SalomeContainerMonoHelper *getHelperOfTask(const Task *node) { return _launchModeType.getHelperOfTask(node); }
-      const SalomeContainerMonoHelper *getHelperOfTask(const Task *node) const { return _launchModeType.getHelperOfTask(node); }
+      SalomeContainerMonoHelper *getHelperOfTask(const Task *node) { return _launchModeType->getHelperOfTask(node); }
+      const SalomeContainerMonoHelper *getHelperOfTask(const Task *node) const { return _launchModeType->getHelperOfTask(node); }
       //
-      YACS::BASES::Mutex& getLocker() { return _mutex; }
+      HomogeneousPoolContainer *getDirectFather() { return NULL; }
+      const HomogeneousPoolContainer *getDirectFather() const { return NULL; }
 #endif
     public:
       static const char KIND[];
@@ -90,14 +128,38 @@ namespace YACS
       ~SalomeHPContainer();
 #endif
     protected:
-      int _shutdownLevel;
       SalomeContainerTools _sct;
-      YACS::BASES::Mutex _mutex;
       std::vector<std::string> _componentNames;
+    };
+
+#ifndef SWIG
+    class YACSRUNTIMESALOME_EXPORT SalomeHPContainerShared : public SalomeHPContainerBase
+    {
+    public:
+      SalomeHPContainerShared(YACS::BASES::AutoConstRefCnt<PartDefinition> pd, SalomeHPContainerVectOfHelper *resShared, SalomeHPContainerBase *directFather);
+      HomogeneousPoolContainer *getDirectFather() { return _directFather; }
+      const HomogeneousPoolContainer *getDirectFather() const { return _directFather; }
+      int getNumberOfCoresPerWorker() const { return _directFather->getNumberOfCoresPerWorker(); }
+      std::string getProperty(const std::string& name) const { return _directFather->getProperty(name); }
+      void prepareMaskForExecution() const;
+      void forYourTestsOnly(ForTestOmlyHPContCls *data) const;
+      std::string getName() const;
+      std::string getDiscreminantStrOfThis(const Task *askingNode) const;
+    public:
+      std::string getKind() const;
+      void start(const Task *askingNode) throw(Exception);
+      Container *clone() const;
+      Container *cloneAlways() const;
       //
-      SalomeHPContainerVectOfHelper _launchModeType;
-      std::string _initScript;
+      void allocateFor(const std::vector<const Task *>& nodes);
+      std::size_t getNumberOfFreePlace() const;
+    private:
+      YACS::BASES::AutoRefCnt<SalomeHPContainerBase> _directFather;
+      YACS::BASES::AutoConstRefCnt<PartDefinition> _pd;
+      //! ids in _launchModeType covered by _pd.
+      mutable std::vector<std::size_t> _idsOfKernelContainers;
     };
+#endif
   }
 }
 
index 4e8f971e169b4c82c6396d638a1c9cafdbadaf32..59a9b1e42c983630defd77b9288b9cd52be512bf 100644 (file)
@@ -23,6 +23,7 @@
 #include "Exception.hxx"
 
 #include <algorithm>
+#include <limits>
 
 using namespace YACS::ENGINE;
 
@@ -44,6 +45,15 @@ std::size_t SalomeHPContainerVectOfHelper::getNumberOfFreePlace() const
   return std::count(_whichOccupied.begin(),_whichOccupied.end(),false);
 }
 
+std::size_t SalomeHPContainerVectOfHelper::getNumberOfFreePlaceAmong(const std::vector<std::size_t>& idsOfKernelContainers) const
+{
+  std::size_t ret;
+  for(std::vector<std::size_t>::const_iterator it=idsOfKernelContainers.begin();it!=idsOfKernelContainers.end();it++)
+    if(!_whichOccupied[*it])
+      ret++;
+  return ret;
+}
+
 void SalomeHPContainerVectOfHelper::allocateFor(const std::vector<const Task *>& nodes)
 {
   for(std::vector<const Task *>::const_iterator it=nodes.begin();it!=nodes.end();it++)
@@ -60,6 +70,27 @@ void SalomeHPContainerVectOfHelper::allocateFor(const std::vector<const Task *>&
     }
 }
 
+void SalomeHPContainerVectOfHelper::allocateForAmong(const std::vector<std::size_t>& idsOfKernelContainers, const std::vector<const Task *>& nodes)
+{
+  for(std::vector<const Task *>::const_iterator it=nodes.begin();it!=nodes.end();it++)
+    {
+      if(!(*it))
+        continue;
+      if(_currentlyWorking.find(*it)!=_currentlyWorking.end())
+        throw Exception("Searching 2 to allocate for a ServiceNode instance already declared as allocated !");
+      std::size_t it2(std::numeric_limits<std::size_t>::max());
+      for(std::vector<std::size_t>::const_iterator it=idsOfKernelContainers.begin();it!=idsOfKernelContainers.end();it++)
+        if(!_whichOccupied[*it])
+          {
+            it2=*it;
+            break;
+          }
+      if(it2==std::numeric_limits<std::size_t>::max())
+        throw Exception("All 2 ressources are already occupied ! You are expected to wait for released resources !");
+      _currentlyWorking[*it]=it2; _whichOccupied[it2]=true;
+    }
+}
+
 void SalomeHPContainerVectOfHelper::release(const Task *node)
 {
   if(!node)
@@ -81,9 +112,9 @@ std::size_t SalomeHPContainerVectOfHelper::locateTask(const Task *node) const
   return ret;
 }
 
-const SalomeContainerMonoHelper *SalomeHPContainerVectOfHelper::getHelperOfTaskThreadSafe(const SalomeHPContainer *cont, const Task *node) const
+const SalomeContainerMonoHelper *SalomeHPContainerVectOfHelper::getHelperOfTaskThreadSafe(const Task *node) const
 {
-  YACS::BASES::AutoLocker<Container> alck(const_cast<SalomeHPContainer *>(cont));
+  YACS::BASES::AutoLocker<SalomeHPContainerVectOfHelper> alck(const_cast<SalomeHPContainerVectOfHelper *>(this));
   return _launchModeType[locateTask(node)];
 }
 
@@ -92,9 +123,9 @@ const SalomeContainerMonoHelper *SalomeHPContainerVectOfHelper::getHelperOfTask(
   return _launchModeType[locateTask(node)];
 }
 
-SalomeContainerMonoHelper *SalomeHPContainerVectOfHelper::getHelperOfTaskThreadSafe(SalomeHPContainer *cont, const Task *node)
+SalomeContainerMonoHelper *SalomeHPContainerVectOfHelper::getHelperOfTaskThreadSafe(const Task *node)
 {
-  YACS::BASES::AutoLocker<Container> alck(cont);
+  YACS::BASES::AutoLocker<SalomeHPContainerVectOfHelper> alck(this);
   return _launchModeType[locateTask(node)];
 }
 
@@ -118,3 +149,36 @@ void SalomeHPContainerVectOfHelper::checkPosInVec(std::size_t pos) const
   if(pos<0 || pos>=_launchModeType.size())
     throw Exception("The task has been found, but its id is not in the correct range ! resize of of container size during run ?");
 }
+
+void SalomeHPContainerVectOfHelper::shutdown()
+{
+  for(std::vector< BASES::AutoRefCnt<YACS::ENGINE::SalomeContainerMonoHelper> >::iterator it=_launchModeType.begin();it!=_launchModeType.end();it++)
+    if((*it).isNotNull())
+      if(!(*it)->isKernelContNull())
+        (*it)->shutdown();
+}
+
+std::vector<std::string> SalomeHPContainerVectOfHelper::getKernelContainerNames() const
+{
+  std::vector<std::string> ret;
+  {
+    YACS::BASES::AutoLocker<SalomeHPContainerVectOfHelper> alck(const_cast<SalomeHPContainerVectOfHelper *>(this));
+    std::size_t sz(_launchModeType.size());
+    ret.resize(sz);
+    for(std::size_t i=0;i<sz;i++)
+      {
+        ret[i]=_launchModeType[i]->getKernelContainerName();
+      }
+  }
+  return ret;
+}
+
+void SalomeHPContainerVectOfHelper::lock()
+{
+  _mutex.lock();
+}
+
+void SalomeHPContainerVectOfHelper::unLock()
+{
+  _mutex.unLock();
+}
index 895fa6405ce6ffa2f4a4c297d922375f9769732d..f3a0ccb217bc773e54d451e9b74b20c2df6c1ae7 100644 (file)
@@ -23,6 +23,9 @@
 #include "YACSRuntimeSALOMEExport.hxx"
 #include "SalomeContainerHelper.hxx"
 
+#include "RefCounter.hxx"
+
+#include "Mutex.hxx"
 #include "AutoRefCnt.hxx"
 
 #include <map>
@@ -36,25 +39,36 @@ namespace YACS
     class SalomeComponent;
     class SalomeHPContainer;
     class SalomeContainerMonoHelper;
-    class SalomeHPContainerVectOfHelper
+    class SalomeHPContainerVectOfHelper : public RefCounter
     {
     public:
       std::size_t size() const { return _launchModeType.size(); }
       void resize(std::size_t sz);
       std::size_t getNumberOfFreePlace() const;
+      std::size_t getNumberOfFreePlaceAmong(const std::vector<std::size_t>& idsOfKernelContainers) const;
       void allocateFor(const std::vector<const Task *>& nodes);
+      void allocateForAmong(const std::vector<std::size_t>& idsOfKernelContainers, const std::vector<const Task *>& nodes);
       void release(const Task *node);
       std::size_t locateTask(const Task *node) const;
       const SalomeContainerMonoHelper *at(std::size_t pos) const { checkPosInVec(pos); return _launchModeType[pos]; }
       SalomeContainerMonoHelper *at(std::size_t pos) { checkPosInVec(pos); return _launchModeType[pos]; }
-      const SalomeContainerMonoHelper *getHelperOfTaskThreadSafe(const SalomeHPContainer *cont, const Task *node) const;
+      const SalomeContainerMonoHelper *getHelperOfTaskThreadSafe(const Task *node) const;
       const SalomeContainerMonoHelper *getHelperOfTask(const Task *node) const;
-      SalomeContainerMonoHelper *getHelperOfTaskThreadSafe(SalomeHPContainer *cont, const Task *node);
+      SalomeContainerMonoHelper *getHelperOfTaskThreadSafe(const Task *node);
       SalomeContainerMonoHelper *getHelperOfTask(const Task *node);
+      void shutdown();
+      //! For thread safety for concurrent load operation on same Container.
+      void lock();
+      //! For thread safety for concurrent load operation on same Container.
+      void unLock();
+    public:
+      std::vector<std::string> getKernelContainerNames() const;
     private:
+      ~SalomeHPContainerVectOfHelper() { }
       void checkNoCurrentWork() const;
       void checkPosInVec(std::size_t pos) const;
     private:
+      YACS::BASES::Mutex _mutex;
       std::vector<bool> _whichOccupied;
       std::vector< BASES::AutoRefCnt<YACS::ENGINE::SalomeContainerMonoHelper> > _launchModeType;
       std::map<const Task *,std::size_t > _currentlyWorking;
index cd3a330a1d5eab5ba36b1bf29b5e8d9861b455b1..fe030312dd1994036b2b8e44f726008924926073 100644 (file)
@@ -44,45 +44,47 @@ namespace YACS
     class TypeCode;
     class Any;
 
-    CORBA::TypeCode_ptr getCorbaTC(const TypeCode *t);
+    YACSRUNTIMESALOME_EXPORT CORBA::TypeCode_ptr getCorbaTC(const TypeCode *t);
 
-    int isAdaptableCorbaPyObject(const TypeCode * t1, const TypeCode * t2);
-    int isAdaptableCorbaNeutral(const TypeCode * t1, const TypeCode * t2);
-    int isAdaptableCorbaCorba(const TypeCode * t1, const TypeCode * t2);
+    YACSRUNTIMESALOME_EXPORT int isAdaptableCorbaPyObject(const TypeCode * t1, const TypeCode * t2);
+    YACSRUNTIMESALOME_EXPORT int isAdaptableCorbaNeutral(const TypeCode * t1, const TypeCode * t2);
+    YACSRUNTIMESALOME_EXPORT int isAdaptableCorbaCorba(const TypeCode * t1, const TypeCode * t2);
 
-    int isAdaptableNeutralCorba(const TypeCode * t1, const TypeCode * t2);
-    int isAdaptableNeutralNeutral(const TypeCode * t1, const TypeCode * t2);
-    int isAdaptableNeutralXml(const TypeCode * t1, const TypeCode * t2);
-    int isAdaptableNeutralPyObject(const TypeCode * t1, const TypeCode * t2);
+    YACSRUNTIMESALOME_EXPORT int isAdaptableNeutralCorba(const TypeCode * t1, const TypeCode * t2);
+    YACSRUNTIMESALOME_EXPORT int isAdaptableNeutralNeutral(const TypeCode * t1, const TypeCode * t2);
+    YACSRUNTIMESALOME_EXPORT int isAdaptableNeutralXml(const TypeCode * t1, const TypeCode * t2);
+    YACSRUNTIMESALOME_EXPORT int isAdaptableNeutralPyObject(const TypeCode * t1, const TypeCode * t2);
 
-    int isAdaptablePyObjectPyObject(const TypeCode * t1, const TypeCode * t2);
-    int isAdaptablePyObjectCorba(const TypeCode * t1, const TypeCode * t2);
-    int isAdaptablePyObjectNeutral(const TypeCode * t1, const TypeCode * t2);
+    YACSRUNTIMESALOME_EXPORT int isAdaptablePyObjectPyObject(const TypeCode * t1, const TypeCode * t2);
+    YACSRUNTIMESALOME_EXPORT int isAdaptablePyObjectCorba(const TypeCode * t1, const TypeCode * t2);
+    YACSRUNTIMESALOME_EXPORT int isAdaptablePyObjectNeutral(const TypeCode * t1, const TypeCode * t2);
 
-    int isAdaptableXmlNeutral(const TypeCode *t1,const TypeCode *t2);
-    int isAdaptableXmlCorba(const TypeCode *t1, const TypeCode *t2);
+    YACSRUNTIMESALOME_EXPORT int isAdaptableXmlNeutral(const TypeCode *t1,const TypeCode *t2);
+    YACSRUNTIMESALOME_EXPORT int isAdaptableXmlCorba(const TypeCode *t1, const TypeCode *t2);
 
-    PyObject *convertCorbaPyObject(const TypeCode * t,CORBA::Any* ob);
-    CORBA::Any *convertCorbaCorba(const TypeCode * t,CORBA::Any* ob);
-    YACS::ENGINE::Any *convertCorbaNeutral(const TypeCode *t,CORBA::Any* ob);
-    std::string convertCorbaXml(const TypeCode * t,CORBA::Any* ob);
+    YACSRUNTIMESALOME_EXPORT PyObject *convertCorbaPyObject(const TypeCode * t,CORBA::Any* ob);
+    YACSRUNTIMESALOME_EXPORT PyObject *convertCorbaPyObject(const TypeCode * t,CORBA::Any* ob);
+    YACSRUNTIMESALOME_EXPORT PyObject *convertCorbaPyObject(const TypeCode * t,CORBA::Any* ob);
+    YACSRUNTIMESALOME_EXPORT CORBA::Any *convertCorbaCorba(const TypeCode * t,CORBA::Any* ob);
+    YACSRUNTIMESALOME_EXPORT YACS::ENGINE::Any *convertCorbaNeutral(const TypeCode *t,CORBA::Any* ob);
+    YACSRUNTIMESALOME_EXPORT std::string convertCorbaXml(const TypeCode * t,CORBA::Any* ob);
 
-    CORBA::Any *convertPyObjectCorba(const TypeCode *t,PyObject *ob);
+    YACSRUNTIMESALOME_EXPORT CORBA::Any *convertPyObjectCorba(const TypeCode *t,PyObject *ob);
     YACSRUNTIMESALOME_EXPORT std::string convertPyObjectXml(const TypeCode * t,PyObject* ob);
-    YACS::ENGINE::Any *convertPyObjectNeutral(const TypeCode *t,PyObject* ob);
-    PyObject* convertPyObjectPyObject(const TypeCode *t,PyObject *ob);
-    std::string convertPyObjectToString(PyObject* ob);
-    bool checkPyObject(const TypeCode *t,PyObject* ob);
-
-    PyObject *convertXmlPyObject(const TypeCode * t,xmlDocPtr doc,xmlNodePtr cur );
-    PyObject *convertXmlStrPyObject(const TypeCode * t,std::string data );
-    CORBA::Any *convertXmlCorba(const TypeCode * t,xmlDocPtr doc,xmlNodePtr cur );
-    YACS::ENGINE::Any *convertXmlNeutral(const TypeCode * t,xmlDocPtr doc,xmlNodePtr cur );
-
-    PyObject *convertNeutralPyObject(const TypeCode * t,YACS::ENGINE::Any* ob);
-    std::string convertNeutralXml(const TypeCode * t,YACS::ENGINE::Any* ob);
-    CORBA::Any *convertNeutralCorba(const TypeCode *t,YACS::ENGINE::Any *ob);
-    YACS::ENGINE::Any *convertNeutralNeutral(const TypeCode *t, YACS::ENGINE::Any* ob);
+    YACSRUNTIMESALOME_EXPORT YACS::ENGINE::Any *convertPyObjectNeutral(const TypeCode *t,PyObject* ob);
+    YACSRUNTIMESALOME_EXPORT PyObject* convertPyObjectPyObject(const TypeCode *t,PyObject *ob);
+    YACSRUNTIMESALOME_EXPORT std::string convertPyObjectToString(PyObject* ob);
+    YACSRUNTIMESALOME_EXPORT bool checkPyObject(const TypeCode *t,PyObject* ob);
+
+    YACSRUNTIMESALOME_EXPORT PyObject *convertXmlPyObject(const TypeCode * t,xmlDocPtr doc,xmlNodePtr cur );
+    YACSRUNTIMESALOME_EXPORT PyObject *convertXmlStrPyObject(const TypeCode * t,std::string data );
+    YACSRUNTIMESALOME_EXPORT CORBA::Any *convertXmlCorba(const TypeCode * t,xmlDocPtr doc,xmlNodePtr cur );
+    YACSRUNTIMESALOME_EXPORT YACS::ENGINE::Any *convertXmlNeutral(const TypeCode * t,xmlDocPtr doc,xmlNodePtr cur );
+
+    YACSRUNTIMESALOME_EXPORT PyObject *convertNeutralPyObject(const TypeCode * t,YACS::ENGINE::Any* ob);
+    YACSRUNTIMESALOME_EXPORT std::string convertNeutralXml(const TypeCode * t,YACS::ENGINE::Any* ob);
+    YACSRUNTIMESALOME_EXPORT CORBA::Any *convertNeutralCorba(const TypeCode *t,YACS::ENGINE::Any *ob);
+    YACSRUNTIMESALOME_EXPORT YACS::ENGINE::Any *convertNeutralNeutral(const TypeCode *t, YACS::ENGINE::Any* ob);
   }
 
 }
diff --git a/src/runtime/VisitorSalomeSaveState.cxx b/src/runtime/VisitorSalomeSaveState.cxx
new file mode 100644 (file)
index 0000000..e6b3d7e
--- /dev/null
@@ -0,0 +1,123 @@
+// Copyright (C) 2006-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 "VisitorSalomeSaveState.hxx"
+#include "TypeConversions.hxx"
+#include "ForEachLoop.hxx"
+#include "Proc.hxx"
+#include "Executor.hxx"
+#include "AutoLocker.hxx"
+
+#include "YacsTrace.hxx"
+
+using namespace YACS::ENGINE;
+
+VisitorSalomeSaveState::VisitorSalomeSaveState(ComposedNode *root)
+:VisitorSaveState(root)
+{
+}
+
+VisitorSalomeSaveState::~VisitorSalomeSaveState()
+{
+}
+
+void VisitorSalomeSaveState::visitForEachLoop(ForEachLoop *node)
+{
+  node->ComposedNode::accept(this);
+  if (!_out) throw Exception("No file open for dump state");
+  std::string name = _root->getName();
+  if (static_cast<ComposedNode*>(node) != _root) name = _root->getChildName(node);
+  DEBTRACE("VisitorSaveState::visitForEachLoop ------ " << name);
+  _out << "  <node type='forEachLoop'>" << std::endl;
+  _out << "    <name>" << name << "</name>" << std::endl;
+  _out << "    <state>" << _nodeStateName[node->getState()] << "</state>" << std::endl;
+//  VisitorSaveState::visitForEachLoop(node);
+  std::list<InputPort *> setOfInputPort = node->getLocalInputPorts();
+  std::list<InputPort *>::iterator iter;
+  for(iter = setOfInputPort.begin(); iter != setOfInputPort.end(); iter++)
+  {
+    _out << "    <inputPort>" << std::endl;
+    _out << "      <name>" << (*iter)->getName() << "</name>" << std::endl;
+    try
+      {
+        _out << "      ";
+        _out << (*iter)->dump();
+      }
+    catch (YACS::Exception &e)
+      {
+        DEBTRACE("caught YACS:Exception: " << e.what());
+        _out << "<value><error><![CDATA[" << e.what() << "]]></error></value>" << std::endl;
+      }
+    _out << "    </inputPort>" << std::endl;
+  }
+  
+  StatesForNode state = node->getState();
+  if(YACS::LOADED == state ||
+    YACS::ACTIVATED == state ||
+    YACS::SUSPENDED == state ||
+    YACS::EXECFAILED == state ||
+    YACS::PAUSE == state ||
+    YACS::TORECONNECT == state ||
+    YACS::INTERNALERR == state ||
+    YACS::FAILED == state ||
+    YACS::ERROR == state)
+  {
+    ForEachLoopPassedData* processedData = node->getProcessedData();
+    if(processedData)
+    {
+      const std::vector<unsigned int>& processedIndexes = processedData->getIds();
+      std::vector<SequenceAny *>::const_iterator it_outputs;
+      std::vector<std::string>::const_iterator it_names;
+      
+      for(it_outputs = processedData->getOutputs().begin(), it_names = processedData->getOutputNames().begin();
+          it_names != processedData->getOutputNames().end();
+          it_outputs++, it_names++)
+      {
+        _out << "    <loopOutputPort>" << std::endl;
+        _out << "      <name>" << (*it_names) << "</name>" << std::endl;
+        for(unsigned int i = 0; i < (*it_outputs)->size(); i++)
+        {
+          AnyPtr value = (*(*it_outputs))[i];
+          _out << "      <sample><index>" << processedIndexes[i]<< "</index>";
+          if(value)
+            _out << convertNeutralXml(value->getType(), value);
+          else
+            _out << "<value>None</value>";
+          _out << "      </sample>" << std::endl;
+        }
+        _out << "    </loopOutputPort>" << std::endl;
+      }
+      
+      delete processedData;
+      processedData = NULL;
+    }
+  }
+  _out << "  </node>" << std::endl;
+}
+
+void YACS::ENGINE::schemaSaveState(Proc* proc,
+                                  Executor* exec,
+                                  const std::string& xmlSchemaFile)
+{
+  YACS::BASES::AutoLocker<YACS::BASES::Mutex> alck(&(exec->getTheMutexForSchedulerUpdate()));
+  VisitorSalomeSaveState vss(proc);
+  vss.openFileDump(xmlSchemaFile);
+  proc->accept(&vss);
+  vss.closeFileDump();
+}
diff --git a/src/runtime/VisitorSalomeSaveState.hxx b/src/runtime/VisitorSalomeSaveState.hxx
new file mode 100644 (file)
index 0000000..ceb4afd
--- /dev/null
@@ -0,0 +1,44 @@
+// Copyright (C) 2006-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
+//
+
+#ifndef VISITORSALOMESAVESTATE_HXX
+#define VISITORSALOMESAVESTATE_HXX
+
+#include "VisitorSaveState.hxx"
+#include "YACSRuntimeSALOMEExport.hxx"
+
+namespace YACS
+{
+  namespace ENGINE
+  {
+    class Executor;
+    class YACSRUNTIMESALOME_EXPORT VisitorSalomeSaveState : public VisitorSaveState
+    {
+      public:
+      VisitorSalomeSaveState(ComposedNode *root);
+      virtual ~VisitorSalomeSaveState();
+      virtual void visitForEachLoop(ForEachLoop *node);
+    };
+
+    YACSLIBENGINE_EXPORT void schemaSaveState(Proc* proc,
+                                              Executor* exec,
+                                              const std::string& xmlSchemaFile);
+  }
+}
+#endif // VISITORSALOMESAVESTATE_HXX
index b562d26106f27d4923670d287bfa7a8cc210b2bb..856df28e4687d933af62b9258b2d8417db6d9e26 100644 (file)
@@ -37,6 +37,9 @@
 #include <io.h>
 #define chmod _chmod
 #endif
+#ifdef __APPLE__
+#include <unistd.h> // for mkdtemp
+#endif
 
 //#define _DEVDEBUG_
 #include "YacsTrace.hxx"
index 1f3e47394eb58687c45896a7a8d68b2adb1a5c23..27e3d41fb2bf9e772b0586ca0a7c74b97c3043bb 100644 (file)
@@ -92,6 +92,7 @@ SET(SWIGINCLUDES
   ${PROJECT_SOURCE_DIR}/src/runtime/CORBAPorts.hxx
   ${PROJECT_SOURCE_DIR}/src/runtime/TypeConversions.hxx
   ${PROJECT_SOURCE_DIR}/src/runtime/SalomeOptimizerLoop.hxx
+  ${PROJECT_SOURCE_DIR}/src/runtime/VisitorSalomeSaveState.hxx
   )
 SET(SWIG_MODULE_SALOMERuntime_EXTRA_DEPS 
     ${PROJECT_SOURCE_DIR}/src/engine_swig/pilot.i 
@@ -100,6 +101,7 @@ SET(SWIG_MODULE_SALOMERuntime_EXTRA_DEPS
 SWIG_ADD_MODULE(SALOMERuntime python SALOMERuntime.i)
 
 SWIG_LINK_LIBRARIES(SALOMERuntime ${_link_LIBRARIES})
+SWIG_CHECK_GENERATION(SALOMERuntime)
 IF(WIN32)
   SET_TARGET_PROPERTIES(_SALOMERuntime PROPERTIES DEBUG_OUTPUT_NAME _SALOMERuntime_d)
 ENDIF(WIN32)
index d0d45bb5573c2dc27f20da59d4854864720ae1ae..1de04b0af039bae26b4f74cdd798289fd3859c72 100644 (file)
 #include "TypeConversions.hxx"
 #include "TypeCode.hxx"
 #include "VisitorSaveSalomeSchema.hxx"
+#include "VisitorSalomeSaveState.hxx"
 #include "SalomeOptimizerLoop.hxx"
 #include "DistributedPythonNode.hxx"
 #include "PyOptimizerAlg.hxx"
 #include "PyStdout.hxx"
+#include "ExecutorSwig.hxx"
 #include <sstream>
 %}
 
   Py_DECREF(pyapi);
 %}
 
+%{
+static PyObject *convertContainer2(YACS::ENGINE::Container *cont, int owner=0)
+{
+  if(!cont)
+    return SWIG_NewPointerObj((void*)cont,SWIGTYPE_p_YACS__ENGINE__Container, owner);
+  if(dynamic_cast<YACS::ENGINE::SalomeHPContainer *>(cont))
+    {
+      return SWIG_NewPointerObj((void*)dynamic_cast<YACS::ENGINE::SalomeHPContainer *>(cont),SWIGTYPE_p_YACS__ENGINE__SalomeHPContainer, owner);
+    }
+  if(dynamic_cast<YACS::ENGINE::SalomeContainer *>(cont))
+    {
+      return SWIG_NewPointerObj((void*)dynamic_cast<YACS::ENGINE::SalomeContainer *>(cont),SWIGTYPE_p_YACS__ENGINE__SalomeContainer, owner);
+    }
+  return SWIG_NewPointerObj((void*)cont,SWIGTYPE_p_YACS__ENGINE__Container, owner);
+}
+%}
+
 // ----------------------------------------------------------------------------
 
 #ifdef SWIGPYTHON
 %include "SalomeOptimizerLoop.hxx"
 %include "DistributedPythonNode.hxx"
 
+namespace YACS
+{
+  namespace ENGINE
+  {
+    void schemaSaveState(Proc* proc,
+                         Executor* exec,
+                         const std::string& xmlSchemaFile);
+  }
+}
+
+
 %extend YACS::ENGINE::OutputPresetPort
 {
   void setDataPy(PyObject *ob)
 %rename(OptimizerAlgSync) YACS::ENGINE::PyOptimizerAlgBase;
 %rename(OptimizerAlgASync) YACS::ENGINE::PyOptimizerAlgASync;
 %include "PyOptimizerAlg.hxx"
+
+%extend YACS::ENGINE::RuntimeSALOME
+{
+  PyObject *createContainer(const std::string& kind="")
+  {
+    YACS::ENGINE::Container *ret(self->createContainer(kind));
+    return convertContainer2(ret,SWIG_POINTER_OWN | 0);
+  }
+}
index db0ca172ac97a3601c2671cc3dcd725a85a2e2e8..9d1255437cbeba54daedb35029dab4fd236cb66c 100644 (file)
@@ -90,6 +90,7 @@ SET(SWIG_MODULE_libYACS_Swig_EXTRA_DEPS YACSGUI_Swig.hxx)
 SWIG_ADD_MODULE(libYACS_Swig python libYACS_Swig.i YACSGUI_Swig.cxx)
 
 SWIG_LINK_LIBRARIES(libYACS_Swig "${_link_LIBRARIES}")
+SWIG_CHECK_GENERATION(libYACS_Swig)
 IF(WIN32)
   SET_TARGET_PROPERTIES(_libYACS_Swig PROPERTIES DEBUG_OUTPUT_NAME _libYACS_Swig_d)
 ENDIF(WIN32)
index 77ac92086a29364c781bd71ac931b49ea1ceeff4..71a9807f818689ea6286e6f49d71ebd45c1ca2e7 100644 (file)
@@ -73,6 +73,7 @@ SET(YACSloader_LIBRARIES
   ${OMNIORB_LIBRARIES}
   ${LIBXML2_LIBRARIES}
   YACSlibEngine
+  YACSRuntimeSALOME
   )
 SET(_link_LIBRARIES
   YACSloader
@@ -144,6 +145,9 @@ SET(resume_SOURCES
 SET(debugger_SOURCES
   debugger.cxx
   )
+SET(ExampleOfObserversPluginForDriver_SOURCES
+  ExampleOfObserversPluginForDriver.cxx
+  )
 
 # --- rules ---
 
@@ -151,6 +155,10 @@ ADD_LIBRARY(YACSloader ${YACSloader_SOURCES})
 TARGET_LINK_LIBRARIES(YACSloader ${YACSloader_LIBRARIES})
 INSTALL(TARGETS YACSloader EXPORT ${PROJECT_NAME}TargetGroup DESTINATION ${SALOME_INSTALL_LIBS})
 
+ADD_LIBRARY(ExampleOfObserversPluginForDriver ${ExampleOfObserversPluginForDriver_SOURCES})
+TARGET_LINK_LIBRARIES(ExampleOfObserversPluginForDriver ${_link_LIBRARIES})
+INSTALL(TARGETS ExampleOfObserversPluginForDriver DESTINATION ${SALOME_INSTALL_LIBS})
+
 ADD_EXECUTABLE(driver ${driver_SOURCES})
 TARGET_LINK_LIBRARIES(driver ${_link_LIBRARIES})
 
diff --git a/src/yacsloader/ExampleOfObserversPluginForDriver.cxx b/src/yacsloader/ExampleOfObserversPluginForDriver.cxx
new file mode 100644 (file)
index 0000000..e0c0f2f
--- /dev/null
@@ -0,0 +1,92 @@
+// Copyright (C) 2016  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)
+
+
+// This is an example of plugin implementation you can write to intercept events sent by YACS engine during execution
+// 1 - Build your shared library with 2 symboles defined : DefineCustomObservers and CleanUpObservers (warning respect the API !).
+// 2 - At run time set YACS_DRIVER_PLUGIN_PATH in your environement to the shared library
+
+#include "Dispatcher.hxx"
+#include "ForEachLoop.hxx"
+
+#include <iostream>
+#include <sstream>
+
+class PluginObserver : public YACS::ENGINE::Observer
+{
+public:
+  PluginObserver(YACS::ENGINE::ForEachLoop *fe):_fe(fe) { }
+private:
+  void notifyObserver(YACS::ENGINE::Node* object,const std::string& event);
+  void notifyObserver2(YACS::ENGINE::Node* object,const std::string& event, void *something);
+private:
+  YACS::ENGINE::ForEachLoop *_fe;
+};
+
+void PluginObserver::notifyObserver(YACS::ENGINE::Node* object,const std::string& event)
+{// Customize here !
+  std::cerr << "------------" << event << std::endl;
+}
+
+void PluginObserver::notifyObserver2(YACS::ENGINE::Node* object,const std::string& event, void *something)
+{// Customize here !
+  std::ostringstream oss;
+  if(event=="progress_ok")
+    {
+      int itemOk(*reinterpret_cast<int *>(something));
+      oss << event << " " << itemOk;
+      std::cerr << oss.str() << std::endl;
+    }
+}
+
+class PluginObserverKeeper
+{
+public:
+  ~PluginObserverKeeper() { clean(); }
+  void clean() { for(std::vector<YACS::ENGINE::Observer *>::iterator it=_observers.begin();it!=_observers.end();it++) delete *it; _observers.clear(); }
+  void registerObserver(YACS::ENGINE::Observer *newObs) { _observers.push_back(newObs); }
+private:
+  std::vector<YACS::ENGINE::Observer *> _observers;
+};
+
+PluginObserverKeeper pok;
+
+#include "ForEachLoop.hxx"
+
+extern "C"
+{
+  void DefineCustomObservers(YACS::ENGINE::Dispatcher *disp, YACS::ENGINE::ComposedNode *rootNode, YACS::ENGINE::Executor *executor)
+  {// Customize here !
+    YACS::ENGINE::Node *n(rootNode->getChildByName("ForEachLoop_pyobj1"));
+    YACS::ENGINE::ForEachLoop *nc(dynamic_cast<YACS::ENGINE::ForEachLoop *>(n));
+    if(!nc)
+      throw YACS::Exception("Expect to have a ForEach node called ForEachLoop_pyobj1 !");
+    PluginObserver *myCustomObsever(new PluginObserver(nc));
+    pok.registerObserver(myCustomObsever);
+    disp->addObserver(myCustomObsever,nc,"progress_ok");
+  }
+  
+  void CleanUpObservers()
+  {// Customize here !
+    pok.clean();
+  }
+}
+
index a146499ad3da86cd77f6b8f29d664b4f98219edb..6e6e3faeee93592e1e4810f428481e4c2abb2d8e 100644 (file)
@@ -27,6 +27,9 @@
 #include "Runtime.hxx"
 #include "InputPort.hxx"
 #include "ElementaryNode.hxx"
+#include "ForEachLoop.hxx"
+#include "Any.hxx"
+#include "TypeConversions.hxx"
 
 #include <iostream>
 #include <string>
@@ -80,6 +83,7 @@ void stateParser::init(const xmlChar** p, xmlParserBase* father)
   _nodeStateValue["DISABLED"] =YACS::DISABLED;
   _nodeStateValue["FAILED"] =YACS::FAILED;
   _nodeStateValue["ERROR"] =YACS::ERROR;
+  _nodeStates.clear();
 }
 
 
@@ -230,6 +234,7 @@ public:
 void nodeParser::init(const xmlChar** p, xmlParserBase* father)
 {
   DEBTRACE("nodeParser::init()");
+  _loopSamples.clear();
   _state = XMLINNODE;
   _father = father;
   _stackState.push(_state);
@@ -249,6 +254,12 @@ void nodeParser::onStart (const XML_Char* elem, const xmlChar** p)
   else if (element == "nbdone")    parser = new attrParser();
   else if (element == "condition") parser = new attrParser();
   else if (element == "outputPort") parser = new outputParser();
+  else if (element == "loopOutputPort")
+  {
+    loopPortParser* sparser = new loopPortParser();
+    _loopSamples.push_back(sparser);
+    parser = sparser;
+  }
   else
     { 
       _what = "expected name, state or inputPort, got <" + element + ">";
@@ -361,10 +372,118 @@ void nodeParser::onEnd   (const XML_Char* name)
         }
       mySwitch->edGetConditionPort()->edInit(condition);
     }
+  else if (nodeType == "forEachLoop")
+  {
+    ForEachLoop* feNode = dynamic_cast<ForEachLoop*>(node);
+    if(!feNode)
+    {
+      _what = "node is not a ForEachLoop: " + _mapAttrib["name"];
+      _state = XMLFATALERROR;
+      stopParse(_what);
+    }
+    else
+    {
+      std::vector<unsigned int> passedIds;
+      std::vector<SequenceAny *> passedOutputs;
+      std::vector<std::string> nameOfOutputs;
+      bool firstPort = true;
+      std::list<loopPortParser*>::const_iterator itPort;
+      for(itPort=_loopSamples.begin(); itPort!=_loopSamples.end(); itPort++)
+      {
+        const std::string& portName =(*itPort)->getPortName();
+        nameOfOutputs.push_back(portName);
+        const YACS::ENGINE::TypeCode* tc = feNode->getOutputPortType(portName);
+        if(!tc)
+        {
+          _what = "Impossible to find the type of the port " + portName;
+          _state = XMLFATALERROR;
+          stopParse(_what);
+          return;
+        }
+        unsigned int nbSamples = (*itPort)->getNbSamples();
+        SequenceAny* seqValues = SequenceAny::New(tc, nbSamples);
+        passedOutputs.push_back(seqValues);
+        for(unsigned int i = 0; i < nbSamples; i++)
+        {
+          unsigned int sampleId = (*itPort)->getSampleId(i);
+          const std::string& sampleData = (*itPort)->getSampleData(i);
+          Any* value = xmlToAny(sampleData, tc);
+          if(firstPort)
+          {
+            passedIds.push_back(sampleId);
+            seqValues->setEltAtRank(i, value);
+          }
+          else
+          {
+            unsigned int pos = 0;
+            while(pos < passedIds.size() && sampleId != passedIds[pos])
+              pos++;
+            if(pos < passedIds.size())
+              seqValues->setEltAtRank(pos, value);
+            else
+            {
+              _what = "Inconsistent sample id in foreach node " + _mapAttrib["name"];
+              _state = XMLFATALERROR;
+              stopParse(_what);
+              itPort=_loopSamples.end();
+              return;
+            }
+          }
+        }
+        firstPort = false;
+      }
+      feNode->assignPassedResults(passedIds, passedOutputs, nameOfOutputs);
+    }
+  }
 
   stateParser::onEnd(name);
 }
 
+Any* nodeParser::xmlToAny(const std::string& data, const YACS::ENGINE::TypeCode* tc)const
+{
+  xmlDocPtr doc;
+  xmlNodePtr cur;
+  //YACS::ENGINE::Any *ob=YACS::ENGINE::AtomAny::New(0);
+  YACS::ENGINE::Any *ob=NULL;
+  {
+    doc = xmlParseMemory(data.c_str(), data.length());
+    if (doc == NULL )
+      {
+        stringstream msg;
+        msg << "Problem in conversion: XML Document not parsed successfully ";
+        msg << " (" << __FILE__ << ":" << __LINE__ << ")";
+        throw ConversionException(msg.str());
+      }
+    cur = xmlDocGetRootElement(doc);
+    if (cur == NULL)
+      {
+        xmlFreeDoc(doc);
+        stringstream msg;
+        msg << "Problem in conversion: empty XML Document";
+        msg << " (" << __FILE__ << ":" << __LINE__ << ")";
+        throw ConversionException(msg.str());
+      }
+    while (cur != NULL)
+      {
+        if ((!xmlStrcmp(cur->name, (const xmlChar *)"value")))
+          {
+            ob=convertXmlNeutral(tc,doc,cur);
+            break;
+          }
+        cur = cur->next;
+      }
+    xmlFreeDoc(doc);
+    if(ob==NULL)
+      {
+        stringstream msg;
+        msg << "Problem in conversion: incorrect XML value";
+        msg << " (" << __FILE__ << ":" << __LINE__ << ")";
+        throw ConversionException(msg.str());
+      }
+  }
+  return ob;
+}
+
 // ----------------------------------------------------------------------------
 
 void attrParser::init(const xmlChar** p, xmlParserBase* father)
@@ -469,11 +588,13 @@ void portParser::onEnd   (const XML_Char* name)
       what += " in node " + nodeName + " of type " + nodeType;
       throw Exception(what);
     }
-  else if (nodeType == "foreachLoop")
+  else if (nodeType == "forEachLoop")
     {
-      string what="no way to set a port value on port " +  _mapAttrib["name"];
-      what += " in node " + nodeName + " of type " + nodeType;
-      throw Exception(what);
+      ForEachLoop* eNode = dynamic_cast<ForEachLoop*>(node);
+      YASSERT(eNode);
+      InputPort *port = eNode->getInputPort(_mapAttrib["name"]);
+      if(_data != "")
+        port->edInit("XML",_data.c_str());
     }
   else 
     {
@@ -659,7 +780,130 @@ void simpleTypeParser::charData(std::string data)
   _data = _data + data;
 }
 
+// ----------------------------------------------------------------------------
+
+void loopPortParser::init(const xmlChar** p, xmlParserBase* father)
+{
+  DEBTRACE("loopPortParser::init()");
+  //_state = XMLINPORT;
+  _father = father;
+  _stackState.push(_state);
+  _ids.clear();
+  _sampleData.clear();
+  if (p) getAttributes(p);
+}
+
+void loopPortParser::onStart(const XML_Char* elem, const xmlChar** p)
+{
+  DEBTRACE("loopPortParser::onStart" << elem);
+  string element(elem);
+  stateParser *parser = 0;
+  if (element == "name")      parser = new attrParser();
+  else if (element == "sample") parser = new sampleParser(this);
+  else
+    { 
+      _what = "expected name or sample, got <" + element + ">";
+      _state = XMLFATALERROR;
+      stopParse(_what);
+    }
+  if (parser)
+    {
+      _stackParser.push(parser);
+      XML_SetUserData(_xmlParser, parser);
+      parser->init(p, this);
+    }
+}
+
+void loopPortParser::onEnd(const XML_Char* name)
+{
+  stateParser::onEnd(name);
+}
+
+void loopPortParser::charData(std::string data)
+{
+}
+
+void loopPortParser::addSample(int index, const std::string data)
+{
+  _ids.push_back(index);
+  _sampleData.push_back(data);
+}
+
+unsigned int loopPortParser::getNbSamples()const
+{
+  return _ids.size();
+}
+
+unsigned int loopPortParser::getSampleId(unsigned int i)const
+{
+  return _ids[i];
+}
+
+const std::string& loopPortParser::getSampleData(unsigned int i)const
+{
+  return _sampleData[i];
+}
+
+const std::string& loopPortParser::getPortName()const
+{
+  return _mapAttrib.at("name");
+}
+
+// ----------------------------------------------------------------------------
+
+sampleParser::sampleParser(loopPortParser* father)
+: stateParser(),
+  _sampleFather(father)
+{
+}
+
+void sampleParser::init(const xmlChar** p, xmlParserBase* father)
+{
+  DEBTRACE("sampleParser::init()");
+  //_state = XMLINPORT;
+  _father = father;
+  _stackState.push(_state);
+  if (p) getAttributes(p);
+}
+
+void sampleParser::onStart(const XML_Char* elem, const xmlChar** p)
+{
+  DEBTRACE("sampleParser::onStart" << elem);
+  string element(elem);
+  stateParser *parser = 0;
+  if (element == "index")      parser = new attrParser();
+  else if (element == "value") parser = new valueParser();
+  else
+    { 
+      _what = "expected index or value, got <" + element + ">";
+      _state = XMLFATALERROR;
+      stopParse(_what);
+    }
+  if (parser)
+    {
+      _stackParser.push(parser);
+      XML_SetUserData(_xmlParser, parser);
+      parser->init(p, this);
+    }
+}
 
+void sampleParser::onEnd(const XML_Char* name)
+{
+  if (_mapAttrib.find("index") == _mapAttrib.end())
+    {
+      _what = "no attribute index in sample ";
+      _state = XMLFATALERROR;
+      stopParse(_what);
+    }
+  int index =  atoi(_mapAttrib["index"].c_str());
+  _sampleFather->addSample(index, _data);
+  stateParser::onEnd(name);
+}
+
+void sampleParser::charData(std::string data)
+{
+  _data = _data + data;
+}
 
 // ----------------------------------------------------------------------------
 
index 3935d569ee57d9504a8e3157f2de9ed5e20ebb7e..1e74f2889002f855fc5dd9462366f95288c32daa 100644 (file)
 
 #include "YACSloaderExport.hxx"
 #include "xmlParserBase.hxx"
+#include "InputPort.hxx"
 
 #include "define.hxx"
 #include "Exception.hxx"
+#include <vector>
+#include <list>
 
 namespace YACS
 {
@@ -32,6 +35,9 @@ namespace YACS
   {
     class Proc;
     class Runtime;
+    class SequenceAny;
+    class Any;
+    class TypeCode;
 
     //! Load state from a file into a Proc
     /*!
@@ -96,6 +102,7 @@ namespace YACS
       static std::map<std::string, YACS::StatesForNode> _nodeStates;
     };
 
+#ifndef SWIG
     class YACSLOADER_EXPORT graphParser: public stateParser
     {
     public:
@@ -105,14 +112,18 @@ namespace YACS
     };
 
 
+    class loopPortParser;
     class YACSLOADER_EXPORT nodeParser: public stateParser
     {
     public:
       virtual void init(const xmlChar** p, xmlParserBase* father=0);
       virtual void onStart (const XML_Char* elem, const xmlChar** p);
       virtual void onEnd   (const XML_Char* name);
+      Any* xmlToAny(const std::string& data, const TypeCode* tc)const;
       std::string _nodeName;
       std::string _nodeState;
+    private:
+      std::list<loopPortParser*> _loopSamples;
     };
 
     class YACSLOADER_EXPORT attrParser: public stateParser
@@ -172,6 +183,37 @@ namespace YACS
       virtual void charData(std::string data);
     };
 
+    class YACSLOADER_EXPORT loopPortParser: public stateParser
+    {
+    public:
+      virtual void init(const xmlChar** p, xmlParserBase* father=0);
+      virtual void onStart (const XML_Char* elem, const xmlChar** p);
+      virtual void onEnd   (const XML_Char* name);
+      virtual void charData(std::string data);
+      void addSample(int index, const std::string data);
+      unsigned int getNbSamples()const;
+      unsigned int getSampleId(unsigned int i)const;
+      const std::string& getSampleData(unsigned int i)const;
+      const std::string& getPortName()const;
+    private:
+      std::vector<unsigned int> _ids;
+      std::vector<std::string> _sampleData;
+    };
+
+    class YACSLOADER_EXPORT sampleParser: public stateParser
+    {
+    public:
+      sampleParser(loopPortParser* father);
+      virtual void init(const xmlChar** p, xmlParserBase* father=0);
+      virtual void onStart (const XML_Char* elem, const xmlChar** p);
+      virtual void onEnd   (const XML_Char* name);
+      virtual void charData(std::string data);
+    //protected:
+    //  Any* xmlToAny()throw(ConversionException);
+    private:
+      loopPortParser* _sampleFather;
+    };
+#endif
   }
 }
 #endif
index 529cb599f705019aacca303123b979fbdfb1e6d7..a26298375d163a22c8f8bbff4740039a76b4f146 100644 (file)
@@ -24,7 +24,7 @@
 #include "Exception.hxx"
 #include "Executor.hxx"
 #include "parsers.hxx"
-#include "VisitorSaveState.hxx"
+#include "VisitorSalomeSaveState.hxx"
 #include "VisitorSaveSalomeSchema.hxx"
 #include "LoadState.hxx"
 #include "Dispatcher.hxx"
@@ -41,7 +41,7 @@
 #include <signal.h>
 #include <list>
 
-#ifdef WIN32
+#if defined WIN32 || defined __APPLE__
 #else
 #include <argp.h>
 #endif
@@ -58,7 +58,7 @@ const char *argp_program_bug_address ="<nepal@nepal.edf.fr>";
 static char doc[] ="driver -- a SALOME YACS graph executor";
 static char args_doc[] = "graph.xml";
 
-#ifdef WIN32
+#if defined WIN32 || defined __APPLE__
 #else
 static struct argp_option options[] =
   {
@@ -101,14 +101,70 @@ typedef struct {
   string lockFile;
 } thread_st;
 
-#ifdef WIN32
+#ifndef WIN32
+#include <dlfcn.h>
+#include <stdlib.h>
+#endif
+
+std::string LoadedDriverPluginLibrary;
+void *HandleOnLoadedPlugin=0;
+void (*DefineCustomObservers)(YACS::ENGINE::Dispatcher *, YACS::ENGINE::ComposedNode *, YACS::ENGINE::Executor *)=0;
+void (*CleanUpObservers) ()=0;
+
+void LoadObserversPluginIfAny(YACS::ENGINE::ComposedNode *rootNode, YACS::ENGINE::Executor *executor)
+{
+  static const char SYMBOLE_NAME_1[]="DefineCustomObservers";
+  static const char SYMBOLE_NAME_2[]="CleanUpObservers";
+#ifndef WIN32
+  Dispatcher *disp(Dispatcher::getDispatcher());
+  if(!disp)
+    throw YACS::Exception("Internal error ! No dispatcher !");
+  char *yacsDriverPluginPath(getenv("YACS_DRIVER_PLUGIN_PATH"));
+  if(!yacsDriverPluginPath)
+    return ;
+  void *handle(dlopen(yacsDriverPluginPath, RTLD_LAZY | RTLD_GLOBAL));
+  if(!handle)
+    {
+      std::string message(dlerror());
+      std::ostringstream oss; oss << "Error during load of \"" << yacsDriverPluginPath << "\" defined by the YACS_DRIVER_PLUGIN_PATH env var : " << message;
+      throw YACS::Exception(oss.str());
+    }
+  DefineCustomObservers=(void (*)(YACS::ENGINE::Dispatcher *, YACS::ENGINE::ComposedNode *, YACS::ENGINE::Executor *))(dlsym(handle,SYMBOLE_NAME_1));
+  if(!DefineCustomObservers)
+    {
+      std::ostringstream oss; oss << "Error during load of \"" << yacsDriverPluginPath << "\" ! Library has been correctly loaded but symbol " << SYMBOLE_NAME_1 << " does not exists !";
+      throw YACS::Exception(oss.str());
+    }
+  CleanUpObservers=(void (*)())(dlsym(handle,SYMBOLE_NAME_2));
+  if(!CleanUpObservers)
+    {
+      std::ostringstream oss; oss << "Error during load of \"" << yacsDriverPluginPath << "\" ! Library has been correctly loaded but symbol " << SYMBOLE_NAME_2 << " does not exists !";
+      throw YACS::Exception(oss.str());
+    }
+  HandleOnLoadedPlugin=handle;
+  DefineCustomObservers(disp,rootNode,executor);
+#endif
+}
+
+void UnLoadObserversPluginIfAny()
+{
+#ifndef WIN32
+  if(HandleOnLoadedPlugin)
+    {
+      CleanUpObservers();
+      dlclose(HandleOnLoadedPlugin);
+    }
+#endif
+}
+
+#if defined WIN32 || defined __APPLE__
 static int
 #else
 static error_t
 #endif
 parse_opt (int key, char *arg, struct argp_state *state)
 {
-#ifdef WIN32
+#if defined WIN32 || defined __APPLE__
 #else
   // Get the input argument from argp_parse, which we
   // know is a pointer to our arguments structure. 
@@ -186,14 +242,14 @@ parse_opt (int key, char *arg, struct argp_state *state)
 }
 
 // Our argp parser.
-#ifdef WIN32
+#if defined WIN32 || defined __APPLE__
 #else
 static struct argp argp = { options, parse_opt, args_doc, doc };
 #endif
 
 void timer(std::string msg)
 {
-#ifdef WIN32
+#if defined WIN32 || defined __APPLE__
 #else
   struct timeval tv;
   gettimeofday(&tv,NULL);
@@ -216,7 +272,7 @@ void Handler(int theSigId)
       bool isFinalDump = (strlen(myArgs.finalDump) != 0);
       if (isFinalDump)
         {
-          YACS::ENGINE::VisitorSaveState vst(p);
+          YACS::ENGINE::VisitorSalomeSaveState vst(p);
           vst.openFileDump(myArgs.finalDump);
           p->accept(&vst);
           vst.closeFileDump();
@@ -252,7 +308,7 @@ void * dumpState(void *arg)
 #endif
     string cmd = "touch " + st->lockFile;
     system(cmd.c_str());
-    YACS::ENGINE::VisitorSaveState vst(p);
+    YACS::ENGINE::VisitorSalomeSaveState vst(p);
     vst.openFileDump(st->dumpFile);
     p->accept(&vst);
     vst.closeFileDump();
@@ -311,7 +367,7 @@ int main (int argc, char* argv[])
   myArgs.init_ports.clear();
 
   // Parse our arguments; every option seen by parse_opt will be reflected in arguments.
-#ifdef WIN32
+#if defined WIN32 || defined __APPLE__
 #else
   argp_parse (&argp, argc, argv, 0, 0, &myArgs);
   std::cerr << "graph = " << myArgs.args[0];
@@ -509,7 +565,7 @@ int main (int argc, char* argv[])
           st->lockFile = rootFile + ".lock";
           pthread_create(&th,NULL,&dumpState,(void*)st);
         }
-
+      LoadObserversPluginIfAny(p,&executor);
       cerr << "+++++++++++++++++++ start calculation +++++++++++++++++++" << endl;
       executor.RunW(p,myArgs.display, fromScratch);
       cerr << "+++++++++++++++++++  end calculation  +++++++++++++++++++" << endl;
@@ -544,7 +600,7 @@ int main (int argc, char* argv[])
       bool isFinalDump = (strlen(myArgs.finalDump) != 0);
       if (isFinalDump)
         {
-          YACS::ENGINE::VisitorSaveState vst(p);
+          YACS::ENGINE::VisitorSalomeSaveState vst(p);
           vst.openFileDump(myArgs.finalDump);
           p->accept(&vst);
           vst.closeFileDump();
@@ -559,6 +615,7 @@ int main (int argc, char* argv[])
       r->fini();
       delete r;
       delete disp;
+      UnLoadObserversPluginIfAny();
       return return_value;
     }
   catch (YACS::Exception& e)
index 570925302101d200a890635797c967cd90c78fe6..db84e6ff144094528ebf5116156741eb12139b72 100644 (file)
@@ -506,6 +506,7 @@ struct foreachlooptypeParser:dynparalooptypeParser<T>
           if(std::string(attr[i]) == "name")name(attr[i+1]);
           if(std::string(attr[i]) == "state")this->state(attr[i+1]);
           if(std::string(attr[i]) == "nbranch")nbranch(atoi(attr[i+1]));
+          if(std::string(attr[i]) == "weight")weight(atof(attr[i+1]));
           if(std::string(attr[i]) == "type")datatype(attr[i+1]);
         }
       postAttr();
@@ -513,6 +514,7 @@ struct foreachlooptypeParser:dynparalooptypeParser<T>
   virtual void pre ()
     {
       _nbranch=0;
+      _weight=1;
       this->looptypeParser<T>::pre();
     }
   virtual void name (const std::string& name)
@@ -526,6 +528,11 @@ struct foreachlooptypeParser:dynparalooptypeParser<T>
       DEBTRACE("foreach_nbranch: " << n )
       _nbranch=n;
     }
+  virtual void weight (const double& x)
+    {
+      DEBTRACE("foreach_weight: " << x )
+      _weight=x;
+    }
   virtual void datatype (const std::string& type)
     {
       DEBTRACE("foreach_datatype: "<< type)
@@ -552,6 +559,7 @@ struct foreachlooptypeParser:dynparalooptypeParser<T>
       this->_cnode=theRuntime->createForEachLoop(_name,currentProc->typeMap[_datatype]);
       //set number of branches
       if(_nbranch > 0)this->_cnode->edGetNbOfBranchesPort()->edInit(_nbranch);
+      this->_cnode->setWeight(_weight);
       this->_cnodes.push_back(this->_cnode);
       currentProc->names.push_back(_fullname + '.');
     }
@@ -565,6 +573,7 @@ struct foreachlooptypeParser:dynparalooptypeParser<T>
       return b;
     }
   int _nbranch;
+  double _weight;
   std::string _fullname;
   std::string _name;
   std::string _datatype;
@@ -595,6 +604,7 @@ struct optimizerlooptypeParser:dynparalooptypeParser<T>
           if(std::string(attr[i]) == "name")name(attr[i+1]);
           if(std::string(attr[i]) == "state")this->state(attr[i+1]);
           if(std::string(attr[i]) == "nbranch")nbranch(atoi(attr[i+1]));
+          if(std::string(attr[i]) == "weight")weight(atof(attr[i+1]));
           if(std::string(attr[i]) == "lib")lib(attr[i+1]);
           if(std::string(attr[i]) == "entry")entry(attr[i+1]);
           if(std::string(attr[i]) == "kind")kind(attr[i+1]);
@@ -604,6 +614,7 @@ struct optimizerlooptypeParser:dynparalooptypeParser<T>
   virtual void pre ()
     {
       _nbranch=0;
+      _weight=1;
       this->looptypeParser<T>::pre();
     }
   virtual void name (const std::string& name)
@@ -625,6 +636,11 @@ struct optimizerlooptypeParser:dynparalooptypeParser<T>
       DEBTRACE("optimizer_nbranch: " << n )
       _nbranch=n;
     }
+  virtual void weight (const double& x)
+    {
+      DEBTRACE("foreach_weight: " << x )
+      _weight=x;
+    }
   virtual void kind (const std::string& name)
     {
       _kind=name;
@@ -634,6 +650,7 @@ struct optimizerlooptypeParser:dynparalooptypeParser<T>
       this->_cnode=theRuntime->createOptimizerLoop(_name,_lib,_entry,true,_kind, currentProc);
       //set number of branches
       if(_nbranch > 0)this->_cnode->edGetNbOfBranchesPort()->edInit(_nbranch);
+      this->_cnode->setWeight(_weight);
       this->_cnodes.push_back(this->_cnode);
       currentProc->names.push_back(_fullname + '.');
     }
@@ -648,6 +665,7 @@ struct optimizerlooptypeParser:dynparalooptypeParser<T>
     }
 
   int _nbranch;
+  double _weight;
   std::string _fullname;
   std::string _name;
   std::string _entry;
index cf007a4b352f91bdf908847369123219ee4a15d8..26038678c1b4b4d4389fd5c74009a73b35c5b011 100755 (executable)
@@ -32,7 +32,7 @@
 #include <iostream>
 #include <fstream>
 
-#ifndef WIN32
+#if !defined WIN32 && !defined __APPLE__
 #include <fpu_control.h>
 #endif
 
@@ -45,7 +45,7 @@
 
 int main(int argc, char* argv[])
 {
-#ifndef WIN32
+#if !defined WIN32 && !defined __APPLE__
   fpu_control_t cw = _FPU_DEFAULT & ~(_FPU_MASK_IM | _FPU_MASK_ZM | _FPU_MASK_OM);
   _FPU_SETCW(cw);
 #endif
@@ -57,7 +57,7 @@ int main(int argc, char* argv[])
   controller.addListener( &result );        
 
   // ---  Add a listener that print dots as test run.
-#ifdef WIN32
+#if defined WIN32 || defined __APPLE__
   CPPUNIT_NS::TextTestProgressListener progress;
 #else
   CPPUNIT_NS::BriefTestProgressListener progress;
index a2ffe302def98059b1b70f42010ca18d286da916..285f6c8424741fac0c074e396bb6fbf8aaeefc22 100644 (file)
@@ -91,6 +91,7 @@ SET(SWIG_MODULE_loader_EXTRA_DEPS
 SWIG_ADD_MODULE(loader python loader.i)
 
 SWIG_LINK_LIBRARIES(loader ${_link_LIBRARIES})
+SWIG_CHECK_GENERATION(loader)
 IF(WIN32)
   SET_TARGET_PROPERTIES(_loader PROPERTIES DEBUG_OUTPUT_NAME _loader_d)
 ENDIF(WIN32)
index f079c81d2305ecc75afde00ead21fc929dde92ce..22965a4771ba404c2329ef6a17f99dd987440260 100644 (file)
@@ -41,6 +41,7 @@ IF(NOT WIN32)
     testResume.py
     testSave.py
     testSaveLoadRun.py
+    testHPDecorator.py
     optim_plugin.py
     testValidationChecks.py
     testProgress.py
index 6c4d0699d739efba2e264162eea8f39240dace60..f673b7a83a6b5f67968148fcdfc557d884d0199e 100644 (file)
@@ -28,5 +28,6 @@ IF(NOT WIN32)
   ADD_TEST(${TEST_NAME} python ${SALOME_TEST_DRIVER} ${TIMEOUT} python StdAloneYacsLoaderTest1.py)
   SET_TESTS_PROPERTIES(${TEST_NAME} PROPERTIES
                                     LABELS "${COMPONENT_NAME}"
-                      )
+                                   )
+
 ENDIF()
index ee7278e6affb76549965eb1bc1ab5b67a723667e..8fe5e26b7cd14b7969bff88b9aadb7162be99045 100644 (file)
@@ -192,6 +192,90 @@ def sum(i):
     self.assertEqual(n.getState(),pilot.DISABLED) # <- test is here.
     pass
 
+  def test5(self):
+    """ Test focusing P13268. If I connect a list[pyobj] output inside a ForEach to a list[pyobj] outside a foreach it works now."""
+    #self.assertTrue(False)
+    fname="testP1328.xml"
+    p=self.r.createProc("testP1328")
+    tc0=p.createInterfaceTc("python:obj:1.0","pyobj",[])
+    tc1=p.createSequenceTc("list[pyobj]","list[pyobj]",tc0)
+    n0=self.r.createScriptNode("","n0")
+    n1=self.r.createForEachLoop("n1",tc0)
+    n10=self.r.createScriptNode("","n10")
+    n2=self.r.createScriptNode("","n2")
+    p.edAddChild(n0) ; p.edAddChild(n1) ; p.edAddChild(n2) ; n1.edAddChild(n10)
+    n0.setScript("o2=[[elt] for elt in range(10)]")
+    n10.setScript("o6=2*i5")
+    n2.setScript("assert(i8==[[0,0],[1,1],[2,2],[3,3],[4,4],[5,5],[6,6],[7,7],[8,8],[9,9]])")
+    o2=n0.edAddOutputPort("o2",tc1)
+    i5=n10.edAddInputPort("i5",tc0)
+    o6=n10.edAddOutputPort("o6",tc1) # the goal of test is here ! tc1 NOT tc0 !
+    i8=n2.edAddInputPort("i8",tc1)
+    #
+    p.edAddCFLink(n0,n1)
+    p.edAddCFLink(n1,n2)
+    #
+    p.edAddLink(o2,n1.edGetSeqOfSamplesPort())
+    p.edAddLink(n1.edGetSamplePort(),i5)
+    p.edAddLink(o6,i8) # important link for the test !
+    #
+    n1.edGetNbOfBranchesPort().edInitInt(1)
+    #
+    p.saveSchema(fname)
+    #
+    ex=pilot.ExecutorSwig()
+    self.assertEqual(p.getState(),pilot.READY)
+    ex.RunW(p,0)
+    self.assertEqual(p.getState(),pilot.DONE)
+    self.assertEqual(p.getChildByName("n2").getInputPort("i8").getPyObj(),[[0,0],[1,1],[2,2],[3,3],[4,4],[5,5],[6,6],[7,7],[8,8],[9,9]])
+    pass
+
+  def test6(self):
+    """ Test focusing on P13766. Test of a connection of 2 foreach at same level where the output pyobj is connected to the list[pyobj] input samples of the 2nd foreach"""
+    fname="testP13766.xml"
+    p=self.r.createProc("testP13766")
+    tc0=p.createInterfaceTc("python:obj:1.0","pyobj",[])
+    tc1=p.createSequenceTc("list[pyobj]","list[pyobj]",tc0)
+    n0=self.r.createScriptNode("","n0")
+    n1=self.r.createForEachLoop("n1",tc0)
+    n2=self.r.createForEachLoop("n2",tc0)
+    n10=self.r.createScriptNode("","n10")
+    n20=self.r.createScriptNode("","n20")
+    n3=self.r.createScriptNode("","n3")
+    p.edAddChild(n0) ; p.edAddChild(n1) ; p.edAddChild(n2) ; p.edAddChild(n3) ; n1.edAddChild(n10) ; n2.edAddChild(n20)
+    n0.setScript("o2=[[elt] for elt in range(10)]")
+    n10.setScript("o6=3*i5")
+    n3.setScript("assert(i8==[[0,0,0,0,0,0],[1,1,1,1,1,1],[2,2,2,2,2,2],[3,3,3,3,3,3],[4,4,4,4,4,4],[5,5,5,5,5,5],[6,6,6,6,6,6],[7,7,7,7,7,7],[8,8,8,8,8,8],[9,9,9,9,9,9]])")
+    n20.setScript("o10=2*i9")
+    o2=n0.edAddOutputPort("o2",tc1)
+    i5=n10.edAddInputPort("i5",tc0)
+    o6=n10.edAddOutputPort("o6",tc0)
+    i9=n20.edAddInputPort("i9",tc0)
+    o10=n20.edAddOutputPort("o10",tc0)
+    i8=n3.edAddInputPort("i8",tc1)
+    #
+    p.edAddCFLink(n0,n1)
+    p.edAddCFLink(n1,n2)
+    p.edAddCFLink(n2,n3)
+    #
+    p.edAddLink(o2,n1.edGetSeqOfSamplesPort())
+    p.edAddLink(o6,n2.edGetSeqOfSamplesPort())# test is here !
+    p.edAddLink(n1.edGetSamplePort(),i5)
+    p.edAddLink(n2.edGetSamplePort(),i9)
+    p.edAddLink(o10,i8) 
+    #
+    n1.edGetNbOfBranchesPort().edInitInt(1)
+    n2.edGetNbOfBranchesPort().edInitInt(1)
+    #
+    p.saveSchema(fname)
+    #
+    ex=pilot.ExecutorSwig()
+    self.assertEqual(p.getState(),pilot.READY)
+    ex.RunW(p,0)
+    self.assertEqual(p.getState(),pilot.DONE)
+    self.assertEqual(p.getChildByName("n3").getInputPort("i8").getPyObj(),[[0,0,0,0,0,0],[1,1,1,1,1,1],[2,2,2,2,2,2],[3,3,3,3,3,3],[4,4,4,4,4,4],[5,5,5,5,5,5],[6,6,6,6,6,6],[7,7,7,7,7,7],[8,8,8,8,8,8],[9,9,9,9,9,9]])
+    pass
+  
   def tearDown(self):
     del self.r
     del self.l
index 03846640e361ba245bee07caba4acad2ff669904..29b9d06d31a4fb451409a3805ed86317f466cb0f 100644 (file)
@@ -95,7 +95,14 @@ if [ $ret7 -gt 0 ]; then
   exit $ret7
 fi
 
-let ret=$ret0+$ret1+$ret2+$ret3+$ret4+$ret5+$ret6+$ret7
+python  @CMAKE_CURRENT_SOURCE_DIR@/testHPDecorator.py
+ret8=$?
+if [ $ret8 -gt 0 ]; then
+  echo "exec status testProgress : " $ret8
+  exit $ret8
+fi
+
+let ret=$ret0+$ret1+$ret2+$ret3+$ret4+$ret5+$ret6+$ret7+$ret8
 
 # --- return unit tests status
 
diff --git a/src/yacsloader_swig/Test/testHPDecorator.py b/src/yacsloader_swig/Test/testHPDecorator.py
new file mode 100644 (file)
index 0000000..aa15b60
--- /dev/null
@@ -0,0 +1,363 @@
+# Copyright (C) 2006-2016  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
+#
+
+import pilot
+import SALOMERuntime
+import unittest
+
+class TestHPDecortator(unittest.TestCase):
+    def test0(self):
+        """ First test coming from the big boss."""
+        SALOMERuntime.RuntimeSALOME.setRuntime()
+        r=SALOMERuntime.getSALOMERuntime()
+        pg=pilot.PlayGround()
+        pg.loadFromKernelCatalog()
+        assert(len(pg.getData())!=0)
+        p=r.createProc("p0")
+        td=p.createType("double","double")
+        tdd=p.createSequenceTc("seqdouble","seqdouble",td)
+        hp1=p.createContainer("HP1","HPSalome")
+        hp4=p.createContainer("HP4","HPSalome")
+        #
+        n0=r.createScriptNode("Salome","n0")
+        n0.setExecutionMode("remote")
+        out0_0=n0.edAddOutputPort("o1",tdd)
+        n0.setScript("""o1=[float(i)+0.1 for i in range(1000)]""")
+        n0.setContainer(hp4)
+        p.edAddChild(n0)
+        #
+        n1_0=r.createForEachLoop("n1_0",td)
+        p.edAddChild(n1_0)
+        p.edAddCFLink(n0,n1_0)
+        p.edAddLink(out0_0,n1_0.edGetSeqOfSamplesPort())
+        ##
+        n1_0_sc=r.createScriptNode("Salome","n1_0_sc")
+        n1_0.edAddChild(n1_0_sc)
+        n1_0_sc.setExecutionMode("remote")
+        n1_0_sc.setScript("""2*i1""")
+        i1_0_sc=n1_0_sc.edAddInputPort("i1",td)
+        p.edAddLink(n1_0.edGetSamplePort(),i1_0_sc)
+        n1_0_sc.setContainer(hp4)
+        ##
+        #
+        n1_1=r.createForEachLoop("n1_1",td)
+        p.edAddChild(n1_1)
+        p.edAddCFLink(n0,n1_1)
+        p.edAddLink(out0_0,n1_1.edGetSeqOfSamplesPort())
+        ##
+        n1_1_sc=r.createScriptNode("Salome","n1_1_sc")
+        n1_1.edAddChild(n1_1_sc)
+        n1_1_sc.setExecutionMode("remote")
+        n1_1_sc.setScript("""3*i1""")
+        i1_1_sc=n1_1_sc.edAddInputPort("i1",td)
+        p.edAddLink(n1_1.edGetSamplePort(),i1_1_sc)
+        n1_1_sc.setContainer(hp1)
+        ##
+        hp1.setProperty("nb_proc_per_node","1")
+        hp4.setProperty("nb_proc_per_node","4")
+        pg.setData([("m0",8),("m1",8),("m2",8),("m3",8)]) # virtual machine with 32 cores spread over 4 nodes
+        assert(n1_0.getWeight()==1.)
+        assert(n1_1.getWeight()==1.)
+        p.fitToPlayGround(pg)########### ZE CALL
+        fyto=pilot.ForTestOmlyHPContCls()
+        assert(hp4.getSizeOfPool()==8)# 32/4
+        n1_0_sc.getContainer().forYourTestsOnly(fyto)
+        assert(fyto.getContainerType()=="HPContainerShared")
+        pd=fyto.getPD()
+        assert(isinstance(pd,pilot.ContigPartDefinition))
+        assert(pd.getStart()==0 and pd.getStop()==16)
+        assert(fyto.getIDS()==(0,1,2,3))
+        #
+        assert(hp1.getSizeOfPool()==32)# 32/1
+        fyto=pilot.ForTestOmlyHPContCls()
+        n1_1_sc.getContainer().forYourTestsOnly(fyto)
+        assert(fyto.getContainerType()=="HPContainerShared")
+        pd=fyto.getPD()
+        assert(isinstance(pd,pilot.ContigPartDefinition))
+        assert(pd.getStart()==16 and pd.getStop()==32)
+        assert(fyto.getIDS()==(16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31))
+        assert(n1_0.edGetNbOfBranchesPort().getPyObj()==4)
+        assert(n1_1.edGetNbOfBranchesPort().getPyObj()==16)
+        #
+        fyto=pilot.ForTestOmlyHPContCls()
+        n0.getContainer().forYourTestsOnly(fyto)
+        assert(fyto.getContainerType()=="HPContainerShared")
+        pd=fyto.getPD()
+        assert(isinstance(pd,pilot.AllPartDefinition))
+        assert(list(fyto.getIDS())==range(8))
+        #############################
+        #  Change weight of ForEach #
+        #############################
+        n1_0.setWeight(2)
+        p.fitToPlayGround(pg)########### ZE CALL
+        assert(hp4.getSizeOfPool()==8)# 32/4
+        n1_0_sc.getContainer().forYourTestsOnly(fyto)
+        assert(fyto.getContainerType()=="HPContainerShared")
+        pd=fyto.getPD()
+        assert(isinstance(pd,pilot.ContigPartDefinition))
+        assert(pd.getStart()==0 and pd.getStop()==21)
+        assert(fyto.getIDS()==(0,1,2,3,4))
+        assert(hp1.getSizeOfPool()==32)# 32/1
+        fyto=pilot.ForTestOmlyHPContCls()
+        n1_1_sc.getContainer().forYourTestsOnly(fyto)
+        assert(fyto.getContainerType()=="HPContainerShared")
+        pd=fyto.getPD()
+        assert(isinstance(pd,pilot.ContigPartDefinition))
+        assert(pd.getStart()==21 and pd.getStop()==32)
+        assert(fyto.getIDS()==(21,22,23,24,25,26,27,28,29,30,31))
+        assert(n1_0.edGetNbOfBranchesPort().getPyObj()==6)
+        assert(n1_1.edGetNbOfBranchesPort().getPyObj()==11)
+        #
+        fyto=pilot.ForTestOmlyHPContCls()
+        n0.getContainer().forYourTestsOnly(fyto)
+        assert(fyto.getContainerType()=="HPContainerShared")
+        pd=fyto.getPD()
+        assert(isinstance(pd,pilot.AllPartDefinition))
+        assert(list(fyto.getIDS())==range(8))
+        pass
+
+    def test1(self):
+        """ Second test as test0 + script node in // with 2 FE"""
+        SALOMERuntime.RuntimeSALOME.setRuntime()
+        r=SALOMERuntime.getSALOMERuntime()
+        pg=pilot.PlayGround()
+        pg.loadFromKernelCatalog()
+        assert(len(pg.getData())!=0)
+        p=r.createProc("p0")
+        td=p.createType("double","double")
+        tdd=p.createSequenceTc("seqdouble","seqdouble",td)
+        hp1=p.createContainer("HP1","HPSalome")
+        hp4=p.createContainer("HP4","HPSalome")
+        #
+        n0=r.createScriptNode("Salome","n0")
+        n0.setExecutionMode("remote")
+        out0_0=n0.edAddOutputPort("o1",tdd)
+        n0.setScript("""o1=[float(i)+0.1 for i in range(1000)]""")
+        n0.setContainer(hp4)
+        p.edAddChild(n0)
+        #
+        n1_0=r.createForEachLoop("n1_0",td)
+        p.edAddChild(n1_0)
+        p.edAddCFLink(n0,n1_0)
+        p.edAddLink(out0_0,n1_0.edGetSeqOfSamplesPort())
+        ##
+        n1_0_sc=r.createScriptNode("Salome","n1_0_sc")
+        n1_0.edAddChild(n1_0_sc)
+        n1_0_sc.setExecutionMode("remote")
+        n1_0_sc.setScript("""2*i1""")
+        i1_0_sc=n1_0_sc.edAddInputPort("i1",td)
+        p.edAddLink(n1_0.edGetSamplePort(),i1_0_sc)
+        n1_0_sc.setContainer(hp4)
+        ##
+        #
+        n1_1=r.createForEachLoop("n1_1",td)
+        p.edAddChild(n1_1)
+        p.edAddCFLink(n0,n1_1)
+        p.edAddLink(out0_0,n1_1.edGetSeqOfSamplesPort())
+        ##
+        n1_1_sc=r.createScriptNode("Salome","n1_1_sc")
+        n1_1.edAddChild(n1_1_sc)
+        n1_1_sc.setExecutionMode("remote")
+        n1_1_sc.setScript("""3*i1""")
+        i1_1_sc=n1_1_sc.edAddInputPort("i1",td)
+        p.edAddLink(n1_1.edGetSamplePort(),i1_1_sc)
+        n1_1_sc.setContainer(hp1)
+        #
+        n1_2=r.createScriptNode("Salome","n1_2")
+        p.edAddChild(n1_2)
+        n1_2.setExecutionMode("remote")
+        n1_2.setContainer(hp4)
+        n1_2.setScript("""my_container""")
+        p.edAddCFLink(n0,n1_2)
+        ##
+        hp1.setProperty("nb_proc_per_node","1")
+        hp4.setProperty("nb_proc_per_node","4")
+        pg.setData([("m0",8),("m1",8),("m2",8),("m3",8)]) # virtual machine with 32 cores spread over 4 nodes
+        assert(n1_0.getWeight()==1.)
+        assert(n1_1.getWeight()==1.)
+        p.fitToPlayGround(pg)########### ZE CALL
+        assert(hp4.getSizeOfPool()==8)# 32/4
+        fyto=pilot.ForTestOmlyHPContCls()
+        n1_0_sc.getContainer().forYourTestsOnly(fyto)
+        assert(fyto.getContainerType()=="HPContainerShared")
+        pd=fyto.getPD()
+        assert(isinstance(pd,pilot.ContigPartDefinition))
+        assert(pd.getStart()==0 and pd.getStop()==16)
+        assert(fyto.getIDS()==(0,1,2,3))
+        #
+        assert(hp1.getSizeOfPool()==32)# 32/1
+        fyto=pilot.ForTestOmlyHPContCls()
+        n1_1_sc.getContainer().forYourTestsOnly(fyto)
+        assert(fyto.getContainerType()=="HPContainerShared")
+        pd=fyto.getPD()
+        assert(isinstance(pd,pilot.ContigPartDefinition))
+        assert(pd.getStart()==16 and pd.getStop()==32)
+        assert(fyto.getIDS()==(16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31))
+        assert(n1_0.edGetNbOfBranchesPort().getPyObj()==4)
+        assert(n1_1.edGetNbOfBranchesPort().getPyObj()==16)
+        #
+        fyto=pilot.ForTestOmlyHPContCls()
+        n0.getContainer().forYourTestsOnly(fyto)
+        assert(fyto.getContainerType()=="HPContainerShared")
+        pd=fyto.getPD()
+        assert(isinstance(pd,pilot.AllPartDefinition))
+        assert(list(fyto.getIDS())==range(8))
+        fyto=pilot.ForTestOmlyHPContCls()
+        n1_2.getContainer().forYourTestsOnly(fyto)
+        assert(fyto.getContainerType()=="HPContainerShared")
+        pd=fyto.getPD()
+        assert(isinstance(pd,pilot.AllPartDefinition))
+        assert(list(fyto.getIDS())==range(8))
+        pass
+
+    @unittest.skip("requires 2 machines in catalog")
+    def test2(self):
+        """ This test is desactivated because it requires multi nodes. To be moved at the right place to support this.
+        This test is not launched here because it requires 2 machines in catalog"""
+        m1="dsp0764200"
+        m2="dsp0764412"
+        SALOMERuntime.RuntimeSALOME.setRuntime()
+        r=SALOMERuntime.getSALOMERuntime()
+        pg=pilot.PlayGround()
+        pg.loadFromKernelCatalog()
+        assert(len(pg.getData())!=0)
+        p=r.createProc("p0")
+        td=p.createType("double","double")
+        tdd=p.createSequenceTc("seqdouble","seqdouble",td)
+        hp1=p.createContainer("HP1","HPSalome")
+        #
+        n0=r.createScriptNode("Salome","n0")
+        n0.setExecutionMode("remote")
+        out0_0=n0.edAddOutputPort("o1",tdd)
+        n0.setScript("""o1=[float(i)+0.1 for i in range(1000)]""")
+        n0.setContainer(hp1)
+        p.edAddChild(n0)
+        ##
+        n1_0_sc=r.createScriptNode("Salome","n1_0_sc")
+        p.edAddChild(n1_0_sc)
+        p.edAddCFLink(n0,n1_0_sc)
+        n1_0_sc.setExecutionMode("remote")
+        n1_0_sc.setScript("""assert(my_container.getHostName()=="%s")"""%m1)
+        n1_0_sc.setContainer(hp1)
+        ##
+        n1_1_sc=r.createScriptNode("Salome","n1_1_sc")
+        p.edAddChild(n1_1_sc)
+        p.edAddCFLink(n0,n1_1_sc)
+        n1_1_sc.setExecutionMode("remote")
+        n1_1_sc.setScript("""assert(my_container.getHostName()=="%s")"""%m2)
+        n1_1_sc.setContainer(hp1)
+        ##
+        hp1.setProperty("nb_proc_per_node","1")
+        pg.setData([(m1,8),(m2,8)])
+        p.fitToPlayGround(pg)########### ZE CALL
+        assert(hp1.getSizeOfPool()==16)# 16/1
+        fyto=pilot.ForTestOmlyHPContCls()
+        n1_0_sc.getContainer().forYourTestsOnly(fyto)
+        assert(fyto.getContainerType()=="HPContainerShared")
+        pd=fyto.getPD()
+        assert(isinstance(pd,pilot.ContigPartDefinition))
+        assert(pd.getStart()==0 and pd.getStop()==8)
+        assert(fyto.getIDS()==(0,1,2,3,4,5,6,7))
+        #
+        fyto=pilot.ForTestOmlyHPContCls()
+        n1_1_sc.getContainer().forYourTestsOnly(fyto)
+        assert(fyto.getContainerType()=="HPContainerShared")
+        pd=fyto.getPD()
+        assert(isinstance(pd,pilot.ContigPartDefinition))
+        assert(pd.getStart()==8 and pd.getStop()==16)
+        assert(fyto.getIDS()==(8,9,10,11,12,13,14,15))
+        #
+        exe=pilot.ExecutorSwig()
+        assert(p.getState()==pilot.READY)
+        exe.RunW(p,0)
+        assert(p.getState()==pilot.DONE)
+        pass
+
+    def test3(self):
+        """ First test coming from the big boss."""
+        SALOMERuntime.RuntimeSALOME.setRuntime()
+        r=SALOMERuntime.getSALOMERuntime()
+        pg=pilot.PlayGround()
+        pg.loadFromKernelCatalog()
+        assert(len(pg.getData())!=0)
+        p=r.createProc("p0")
+        td=p.createType("double","double")
+        tdd=p.createSequenceTc("seqdouble","seqdouble",td)
+        hp1=r.createContainer("HPSalome") ; hp1.setName("HP1")
+        #
+        n0=r.createScriptNode("Salome","n0")
+        n0.setExecutionMode("local")
+        out0_0=n0.edAddOutputPort("o1",tdd)
+        n0.setScript("""o1=[float(i)+0.1 for i in range(1000)]""")
+        p.edAddChild(n0)
+        #
+        n1_0=r.createForEachLoop("n1_0",td)
+        n2_0=r.createForEachLoop("n2_0",td)
+        p.edAddChild(n1_0)
+        p.edAddChild(n2_0)
+        p.edAddCFLink(n0,n1_0)
+        p.edAddCFLink(n1_0,n2_0)
+        p.edAddLink(out0_0,n1_0.edGetSeqOfSamplesPort())
+        p.edAddLink(out0_0,n2_0.edGetSeqOfSamplesPort())
+        ##
+        n1_0_sc=r.createScriptNode("Salome","n1_0_sc")
+        n1_0.edAddChild(n1_0_sc)
+        n1_0_sc.setExecutionMode("remote")
+        n1_0_sc.setScript("""2*i1""")
+        i1_0_sc=n1_0_sc.edAddInputPort("i1",td)
+        p.edAddLink(n1_0.edGetSamplePort(),i1_0_sc)
+        n1_0_sc.setContainer(hp1)
+        ##
+        n2_0_sc=r.createScriptNode("Salome","n2_0_sc")
+        n2_0.edAddChild(n2_0_sc)
+        n2_0_sc.setExecutionMode("remote")
+        n2_0_sc.setScript("""2*i1""")
+        i2_0_sc=n2_0_sc.edAddInputPort("i1",td)
+        p.edAddLink(n2_0.edGetSamplePort(),i2_0_sc)
+        n2_0_sc.setContainer(hp1)
+        ##
+        hp1.setProperty("nb_proc_per_node","1")
+        pg.setData([("localhost",3)])
+        p.fitToPlayGround(pg)########### ZE CALL
+        assert(hp1.getSizeOfPool()==3)
+        fyto=pilot.ForTestOmlyHPContCls()
+        n1_0_sc.getContainer().forYourTestsOnly(fyto)
+        assert(fyto.getContainerType()=="HPContainerShared")
+        pd=fyto.getPD()
+        assert(isinstance(pd,pilot.AllPartDefinition))
+        assert(fyto.getIDS()==(0,1,2))
+        fyto=pilot.ForTestOmlyHPContCls()
+        n2_0_sc.getContainer().forYourTestsOnly(fyto)
+        assert(fyto.getContainerType()=="HPContainerShared")
+        pd=fyto.getPD()
+        assert(isinstance(pd,pilot.AllPartDefinition))
+        assert(fyto.getIDS()==(0,1,2))
+        assert(n1_0.edGetNbOfBranchesPort().getPyObj()==3)
+        assert(n2_0.edGetNbOfBranchesPort().getPyObj()==3)
+        #
+        exe=pilot.ExecutorSwig()
+        assert(p.getState()==pilot.READY)
+        exe.RunW(p,0)
+        assert(len(set(hp1.getKernelContainerNames()))==3)
+        pass
+    
+    pass
+
+if __name__ == '__main__':
+    unittest.main()
index 351cf71676ac4076f7b2cb1f50a6e61abb9bd0a7..de5c7ed541350df2c92b7c4d97fe9660d2097cc7 100755 (executable)
@@ -68,7 +68,7 @@ class TestResume(unittest.TestCase):
         sl.parse('dumpPartialBloc2.xml')
         #self.e.displayDot(self.p)
         self.e.setExecMode(0) # YACS::CONTINUE
-        run2 = threading.Thread(None, self.e.RunPy, "loadState", (self.p,0,1,1))
+        run2 = threading.Thread(None, self.e.RunPy, "loadState", (self.p,0,True,True))
         run2.start()
         time.sleep(0.1)
         self.e.waitPause()
@@ -93,4 +93,4 @@ if __name__ == '__main__':
   suite = unittest.makeSuite(TestResume)
   result=unittest.TextTestRunner(f, descriptions=1, verbosity=1).run(suite)
   f.close()
-  sys.exit(not result.wasSuccessful())
\ No newline at end of file
+  sys.exit(not result.wasSuccessful())
index 5334bfc795c089f3f018191eee3d90d714c6bb21..6a35686d27828304e587f468ddf54d25a52dba5e 100755 (executable)
@@ -454,7 +454,7 @@ for i in xrange(nb):
     node2000.setScript("o6=2+i5")
     p.edAddLink(node200.edGetSamplePort(),i5)
     #
-    node3=self.r.createForEachLoop("node3",td)
+    node3=self.r.createForEachLoop("node3",td2)
     p.edAddChild(node3)
     p.edAddCFLink(node2,node3)
     p.edAddLink(o6,node3.edGetSeqOfSamplesPort())
@@ -540,7 +540,7 @@ for i in xrange(nb):
     node2000.setScript("def ff(x):\n  return 2+x")
     p.edAddLink(node200.edGetSamplePort(),i5)
     #
-    node3=self.r.createForEachLoop("node3",td)
+    node3=self.r.createForEachLoop("node3",td2)
     p.edAddChild(node3)
     p.edAddCFLink(node2,node3)
     p.edAddLink(o6,node3.edGetSeqOfSamplesPort())
@@ -1459,6 +1459,180 @@ dd=range(10)""")
 
   pass
 
+  def test21(self):
+    "test if we restart from a saved state in a foreach loop"
+    fname="test21.xml"
+    xmlStateFileName="saveState21.xml"
+    from datetime import datetime
+    p=self.r.createProc("prTest21")
+    cont=p.createContainer("gg","Salome")
+    cont.setProperty("name","localhost")
+    cont.setProperty("hostname","localhost")
+    cont.setProperty("type","multi")
+    td=p.createType("double","double")
+    ti=p.createType("int","int")
+    tsi=p.createSequenceTc("seqint","seqint",ti)
+    tsd=p.createSequenceTc("seqdbl","seqdbl",td)
+    n0=self.r.createScriptNode("","n0")
+    o0=n0.edAddOutputPort("o0",tsi)
+    n0.setScript("o0=[ elt for elt in range(6) ]")
+    p.edAddChild(n0)
+    n1=self.r.createForEachLoop("n1",ti)
+    n10=self.r.createScriptNode("","n10")
+    n10.setExecutionMode("remote")
+    n10.setContainer(cont)
+    n1.edAddChild(n10)
+    n10.setScript("""
+import time
+time.sleep(2)
+o2=2*i1
+""")
+    i1=n10.edAddInputPort("i1",ti)
+    o2=n10.edAddOutputPort("o2",ti)
+    p.edAddChild(n1)
+    p.edAddLink(o0,n1.edGetSeqOfSamplesPort())
+    p.edAddLink(n1.edGetSamplePort(),i1)
+    p.edAddCFLink(n0,n1)
+    n1.edGetNbOfBranchesPort().edInitPy(2)
+    n2=self.r.createScriptNode("","n2")
+    n2.setScript("o4=i3")
+    i3=n2.edAddInputPort("i3",tsi)
+    o4=n2.edAddOutputPort("o4",tsi)
+    n2.setScript("o4=i3")
+    p.edAddChild(n2)
+    p.edAddCFLink(n1,n2)
+    p.edAddLink(o2,i3)
+    p.saveSchema(fname)
+    #
+    l=loader.YACSLoader()
+    p=l.load(fname)
+    n1=p.getChildByName("n1")
+    ex=pilot.ExecutorSwig()
+    ex.setKeepGoingProperty(True)
+    #
+    startt=datetime.now()
+    import threading
+    myRun=threading.Thread(None, ex.RunW, None, (p,0))
+    myRun.start()
+    import time
+    time.sleep(5)
+    SALOMERuntime.schemaSaveState(p, ex, xmlStateFileName)
+    a,b,c=n1.getPassedResults(ex)
+    myRun.join()
+    t0=datetime.now()-startt
+    #
+    self.assertEqual(p.getState(),pilot.DONE)
+    self.assertEqual(n1.getState(),pilot.DONE)
+    self.assertEqual(a,[0,1])
+    self.assertEqual([elt.getPyObj() for elt in b],[[0L,2L]])
+    #
+    p.getChildByName("n0").setScript("o0=[ 3*elt for elt in range(6) ]")
+    p.getChildByName("n1").getChildByName("n10").setScript("""
+import time
+time.sleep(0.1)
+o2=5*i1
+""")
+    loader.loadState(p, xmlStateFileName)
+    p.resetState(1)
+    p.getChildByName("n1").assignPassedResults(a,b,c)
+    p.exUpdateState();
+    #
+    startt=datetime.now()
+    ex.RunW(p,0,False)
+    t1=datetime.now()-startt
+    #
+    self.assertEqual(n1.getState(),pilot.DONE)
+    self.assertEqual(p.getState(),pilot.DONE)
+    self.assertEqual(p.getChildByName("n2").getOutputPort("o4").getPyObj(),[0L,2L,10L,15L,20L,25L])
+    pass
+  pass
+
+  def test22(self):
+    """Restart from a saved state in a foreach loop without using assignPassedResults.
+       This test uses the files test21.xml and saveState21.xml produced by test21.
+    """
+    fname="test21.xml"
+    xmlStateFileName="saveState21.xml"
+
+    ex=pilot.ExecutorSwig()
+    l=loader.YACSLoader()
+    q=l.load(fname)
+    q.getChildByName("n0").setScript("o0=[ 3*elt for elt in range(6) ]")
+    q.getChildByName("n1").getChildByName("n10").setScript("""
+import time
+time.sleep(0.1)
+print "execution n10:", i1
+o2=5*i1
+""")
+    q.getChildByName("n2").setScript("""
+print "execution n2:", i3
+o4=i3
+""")
+    loader.loadState(q, xmlStateFileName)
+    q.resetState(1)
+    q.exUpdateState()
+    #
+    ex.RunW(q,0,False)
+    #
+    self.assertEqual(q.getChildByName("n1").getState(),pilot.DONE)
+    self.assertEqual(q.getState(),pilot.DONE)
+    self.assertEqual(q.getChildByName("n2").getOutputPort("o4").getPyObj(),[0L,2L,10L,15L,20L,25L])
+    pass
+
+  def test23(self):
+    """ test focused on weight attribut after a dump and reload from a xml file
+    """
+    fname="test23.xml"
+    xmlStateFileName="saveState23.xml"
+    from datetime import datetime
+    p=self.r.createProc("prTest23")
+    cont=p.createContainer("gg","Salome")
+    cont.setProperty("name","localhost")
+    cont.setProperty("hostname","localhost")
+    cont.setProperty("type","multi")
+    td=p.createType("double","double")
+    ti=p.createType("int","int")
+    tsi=p.createSequenceTc("seqint","seqint",ti)
+    tsd=p.createSequenceTc("seqdbl","seqdbl",td)
+    n0=self.r.createScriptNode("","n0")
+    o0=n0.edAddOutputPort("o0",tsi)
+    n0.setScript("o0=[ elt for elt in range(6) ]")
+    p.edAddChild(n0)
+    n1=self.r.createForEachLoop("n1",ti)
+    n1.setWeight(3)
+    n10=self.r.createScriptNode("","n10")
+    n10.setExecutionMode("remote")
+    n10.setContainer(cont)
+    n1.edAddChild(n10)
+    n10.setScript("""
+import time
+time.sleep(2)
+o2=2*i1
+""")
+    i1=n10.edAddInputPort("i1",ti)
+    o2=n10.edAddOutputPort("o2",ti)
+    p.edAddChild(n1)
+    p.edAddLink(o0,n1.edGetSeqOfSamplesPort())
+    p.edAddLink(n1.edGetSamplePort(),i1)
+    p.edAddCFLink(n0,n1)
+    n1.edGetNbOfBranchesPort().edInitPy(2)
+    n2=self.r.createScriptNode("","n2")
+    n2.setScript("o4=i3")
+    i3=n2.edAddInputPort("i3",tsi)
+    o4=n2.edAddOutputPort("o4",tsi)
+    n2.setScript("o4=i3")
+    p.edAddChild(n2)
+    p.edAddCFLink(n1,n2)
+    p.edAddLink(o2,i3)
+    p.saveSchema(fname)
+    #
+    l=loader.YACSLoader()
+    p=l.load(fname)
+    self.assertEqual(p.getChildByName("n1").getWeight(),3.0)
+    pass
+
+  pass
+
 if __name__ == '__main__':
   import os,sys
   U = os.getenv('USER')
index 49fb73138e84e46a96ed9e6dd018332ec3af9d65..79b88b0f879585f92bb82ff4c5c1fb965622d273 100644 (file)
@@ -112,7 +112,7 @@ class proc_i(YACS_ORB__POA.ProcExec):
             self.run1 = None
 
         if self.run1 is None:
-            self.run1 = threading.Thread(None, self.runProc, "CORBAExec", (0,1,1))
+            self.run1 = threading.Thread(None, self.runProc, "CORBAExec", (0,True,True))
             self.run1.start()
 
     def RunFromState(self, xmlFile):
@@ -146,7 +146,7 @@ class proc_i(YACS_ORB__POA.ProcExec):
             return
 
         if self.run1 is None:
-            self.run1 = threading.Thread(None, self.runProc, "CORBAExec", (0,1,0))
+            self.run1 = threading.Thread(None, self.runProc, "CORBAExec", (0,True,False))
             self.run1.start()
 
     def RestartFromState(self, xmlFile):
@@ -175,7 +175,7 @@ class proc_i(YACS_ORB__POA.ProcExec):
             pass
 
         if self.run1 is None:
-            self.run1 = threading.Thread(None, self.runProc, "CORBAExec", (0,1,0))
+            self.run1 = threading.Thread(None, self.runProc, "CORBAExec", (0,True,False))
             self.run1.start()
 
     def addObserver(self, obs, numid, event):
@@ -243,7 +243,7 @@ class YACS(YACS_ORB__POA.YACS_Gen,
         print "YACS.__init__: ", containerName, ';', instanceName
         SALOME_ComponentPy.SALOME_ComponentPy_i.__init__(self, orb, poa, contID,
                                                          containerName, instanceName,
-                                                         interfaceName, 0)
+                                                         interfaceName, False)
         SALOME_DriverPy.SALOME_DriverPy_i.__init__(self, interfaceName)
 
         # --- store a naming service interface instance in _naming_service atribute