Salome HOME
Save foreach state - work in progress.
authorOvidiu Mircescu <ovidiu.mircescu@edf.fr>
Mon, 27 Feb 2017 09:56:37 +0000 (10:56 +0100)
committerOvidiu Mircescu <ovidiu.mircescu@edf.fr>
Mon, 27 Feb 2017 09:56:37 +0000 (10:56 +0100)
20 files changed:
1  2 
src/engine/Bloc.cxx
src/engine/Bloc.hxx
src/engine/ComposedNode.cxx
src/engine/ComposedNode.hxx
src/engine/DynParaLoop.cxx
src/engine/DynParaLoop.hxx
src/engine/Executor.cxx
src/engine/ForEachLoop.cxx
src/engine/ForEachLoop.hxx
src/engine/OptimizerLoop.cxx
src/engine/OptimizerLoop.hxx
src/engine/Scheduler.hxx
src/runtime/CMakeLists.txt
src/runtime_swig/CMakeLists.txt
src/runtime_swig/SALOMERuntime.i
src/yacsloader/CMakeLists.txt
src/yacsloader/LoadState.cxx
src/yacsloader/LoadState.hxx
src/yacsloader/driver.cxx
src/yacsloader_swig/loader.i

diff --combined src/engine/Bloc.cxx
index 7d5e7b0450360a06e3ab9b2a15e73dd3ae827418,4df68b4a638f93fc92af8af2947ac14782172ff4..514d88ff023fec5c495cb3a981e6aaa029e2c2d0
@@@ -1,4 -1,4 +1,4 @@@
 -// Copyright (C) 2006-2015  CEA/DEN, EDF R&D
 +// 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
@@@ -403,7 -403,7 +403,7 @@@ YACS::Event Bloc::updateStateOnFinished
   * \param node : node that has emitted the event
   * \return the event to notify to bloc's father
   */
- YACS::Event Bloc::updateStateOnFailedEventFrom(Node *node, const Executor *execInst)
+ YACS::Event Bloc::updateStateOnFailedEventFrom(Node *node)
  {
    node->exForwardFailed();
    if(areAllSubNodesFinished())
diff --combined src/engine/Bloc.hxx
index 3cfec917263b5eab4445c9a4d2530a135dca5d40,190b360541da60ad350b41ea2fdcb4d717fd3468..23ceabdad66c6693a3ff4215d556ba787c946181
@@@ -1,4 -1,4 +1,4 @@@
 -// Copyright (C) 2006-2015  CEA/DEN, EDF R&D
 +// 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
@@@ -69,7 -69,7 +69,7 @@@ namespace YAC
        void checkNoCyclePassingThrough(Node *node) throw(Exception);
        std::vector< std::pair<OutGate *, InGate *> > getSetOfInternalCFLinks() const;
        YACS::Event updateStateOnFinishedEventFrom(Node *node);
-       YACS::Event updateStateOnFailedEventFrom(Node *node, const Executor *execInst);
+       YACS::Event updateStateOnFailedEventFrom(Node *node);
        void initComputation() const;
        void performCFComputationsOnlyOneLevel(LinkInfo& info) const;
        void performCFComputations(LinkInfo& info) const;
index 0fa2bf8733ebe66efb8a9b94ce518ffc74abee98,71576cd2bd823ae5dddfee5159f4b3faa827de2b..bbc28e56d2a11630054e0ee33b8ac66a566cbeb7
@@@ -1,4 -1,4 +1,4 @@@
 -// Copyright (C) 2006-2015  CEA/DEN, EDF R&D
 +// 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
@@@ -241,8 -241,7 +241,7 @@@ std::vector<Task *> ComposedNode::getNe
   * 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
-                               const Executor *execInst
+                               YACS::Event event   //* I : event emitted
                                )
  {
    DEBTRACE("ComposedNode::notifyFrom " << event);
    ComposedNode *curLevelNode=taskTyped->_father;
    if(!curLevelNode)//Specific case of loop when 0 turn is specified without any enclosing bloc.
      return ;
-   curEvent=curLevelNode->updateStateFrom(lminus1LevelNode,curEvent,execInst);
+   curEvent=curLevelNode->updateStateFrom(lminus1LevelNode,curEvent);
    while(curEvent!=YACS::NOEVENT && curLevelNode!=this)
      {
        lminus1LevelNode=curLevelNode;
        curLevelNode=curLevelNode->_father;
-       curEvent=curLevelNode->updateStateFrom(lminus1LevelNode,curEvent,execInst);
+       curEvent=curLevelNode->updateStateFrom(lminus1LevelNode,curEvent);
      }
  }
  
@@@ -1376,8 -1375,7 +1375,7 @@@ OutputDataStreamPort *ComposedNode::get
   * Called by ComposedNode::notifyFrom
   */
  YACS::Event ComposedNode::updateStateFrom(Node *node,        //* I : node emitting event
-                                           YACS::Event event,  //* I : event emitted
-                                           const Executor *execInst
+                                           YACS::Event event  //* I : event emitted
                                            )
  {
    DEBTRACE("updateStateFrom: " << node->getName() << " " << event);
            return updateStateOnFinishedEventFrom(node);
            break;
          case YACS::ABORT:
-           return updateStateOnFailedEventFrom(node,execInst);
+           return updateStateOnFailedEventFrom(node);
            break;
          default:
            return YACS::NOEVENT;//TODO unexpected type of event
@@@ -1434,7 -1432,7 +1432,7 @@@ YACS::Event ComposedNode::updateStateOn
  }
  
  //! Method used to notify the node that a child node has failed
- YACS::Event ComposedNode::updateStateOnFailedEventFrom(Node *node, const Executor *execInst)
+ YACS::Event ComposedNode::updateStateOnFailedEventFrom(Node *node)
  {
     setState(YACS::FAILED);
     return YACS::ABORT;
index 013950a7ff1a7d558c5ed69dd39cac381c5efb96,a4a06626e4c7905dbcd6cb871ad0f74434964fb8..82685ef6fa154f02a140196e4af25505bd7f85a8
@@@ -1,4 -1,4 +1,4 @@@
 -// Copyright (C) 2006-2015  CEA/DEN, EDF R&D
 +// 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
@@@ -64,7 -64,7 +64,7 @@@ namespace YAC
        DeploymentTree checkDeploymentTree(bool deep) const throw(Exception);
        std::vector<Task *> getNextTasks(bool& isMore);
        virtual bool isPlacementPredictableB4Run() const = 0;
-       void notifyFrom(const Task *sender, YACS::Event event, const Executor *execInst);
+       void notifyFrom(const Task *sender, YACS::Event event);
        bool edAddLink(OutPort *start, InPort *end) throw(Exception);
        virtual bool edAddDFLink(OutPort *start, InPort *end) throw(Exception);
        //Node* DISOWNnode is a SWIG notation to indicate that the ownership of the node is transfered to C++
        static bool splitNamesBySep(const std::string& globalName, const char separator[],
                                    std::string& firstPart, std::string& lastPart, bool priority) throw(Exception);
        virtual Node *getChildByShortName(const std::string& name) const throw(Exception) = 0;
-       YACS::Event updateStateFrom(Node *node, YACS::Event event, const Executor *execInst);//update the state of this. Precondition : node->_father == this
+       YACS::Event updateStateFrom(Node *node, YACS::Event event);//update the state of this. Precondition : node->_father == this
        virtual YACS::Event updateStateOnStartEventFrom(Node *node);//transition 3 doc P.R
        virtual YACS::Event updateStateOnFinishedEventFrom(Node *node) = 0;//transition 9 doc P.R.
-       virtual YACS::Event updateStateOnFailedEventFrom(Node *node, const Executor *execInst);//transition 9 doc P.R.
+       virtual YACS::Event updateStateOnFailedEventFrom(Node *node);//transition 9 doc P.R.
        virtual void checkLinkPossibility(OutPort *start, const std::list<ComposedNode *>& pointsOfViewStart,
                                          InPort *end, const std::list<ComposedNode *>& pointsOfViewEnd) throw(Exception);
        virtual void buildDelegateOf(InPort * & port, OutPort *initialStart, const std::list<ComposedNode *>& pointsOfView);
index cca32828ba0ac1aaf2709accbc8a631a5895b0a8,97ed761fe498647a8a1368c1d0ddbd1c1e9e882e..996e6625ccbf518cd0631cb0fb1172eb9dfe54a6
@@@ -1,4 -1,4 +1,4 @@@
 -// Copyright (C) 2006-2015  CEA/DEN, EDF R&D
 +// 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
@@@ -696,7 -696,7 +696,7 @@@ void DynParaLoop::forwardExecStateToOri
   *  \param node : the child node that has failed
   *  \return the state change
   */
- YACS::Event DynParaLoop::updateStateOnFailedEventFrom(Node *node, const Executor *execInst)
+ YACS::Event DynParaLoop::updateStateOnFailedEventFrom(Node *node)
  {
    DEBTRACE("DynParaLoop::updateStateOnFailedEventFrom " << node->getName());
    setState(YACS::FAILED);
index c00a5e8c599b312701831277f9c09bbcbeafe25e,513b0153aa9140a3702166b9db5855366bb92307..7160e761b5322015696f1fe2f382ab5382e4206b
@@@ -1,4 -1,4 +1,4 @@@
 -// Copyright (C) 2006-2015  CEA/DEN, EDF R&D
 +// 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
@@@ -124,7 -124,7 +124,7 @@@ namespace YAC
        TypeOfNode getIdentityOfNotifyerNode(const Node *node, unsigned& id);
        InputPort *getDynInputPortByAbsName(int branchNb, const std::string& name, bool initNodeAdmitted);
        virtual void forwardExecStateToOriginalBody(Node *execNode);
-       virtual YACS::Event updateStateOnFailedEventFrom(Node *node, const Executor *execInst);
+       virtual YACS::Event updateStateOnFailedEventFrom(Node *node);
        std::vector<Node *> cloneAndPlaceNodesCoherently(const std::vector<Node *> & origNodes);
        Node * checkConsistencyAndSetNode(Node* &nodeToReplace, Node* DISOWNnode);
        Node * removeNode(Node* &nodeToRemove);
diff --combined src/engine/Executor.cxx
index d559230355590a8c16f1147376c84106424800ab,213b0bacff75dc73b75fe06d003576b0b516bdf1..3fe2336838fb1fc092aa15dcefaf35996609829a
@@@ -1,4 -1,4 +1,4 @@@
 -// Copyright (C) 2006-2015  CEA/DEN, EDF R&D
 +// 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
@@@ -651,6 -651,7 +651,7 @@@ bool Executor::saveState(const std::str
    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);
@@@ -828,7 -829,7 +829,7 @@@ void Executor::loadTask(Task *task, con
    traceExec(task, "state:TOLOAD", ComputePlacement(task));
    {//Critical section
      YACS::BASES::AutoLocker<YACS::BASES::Mutex> alck(&_mutexForSchedulerUpdate);
-     _mainSched->notifyFrom(task,YACS::START,execInst);
+     _mainSched->notifyFrom(task,YACS::START);
    }//End of critical section
    try
      {
        {//Critical section
          YACS::BASES::AutoLocker<YACS::BASES::Mutex> alck(&_mutexForSchedulerUpdate);
          task->aborted();
-         _mainSched->notifyFrom(task,YACS::ABORT,execInst);
+         _mainSched->notifyFrom(task,YACS::ABORT);
          traceExec(task, "state:"+Node::getStateName(task->getState()), ComputePlacement(task));
        }//End of critical section
      }
        {//Critical section
          YACS::BASES::AutoLocker<YACS::BASES::Mutex> alck(&_mutexForSchedulerUpdate);
          task->aborted();
-         _mainSched->notifyFrom(task,YACS::ABORT,execInst);
+         _mainSched->notifyFrom(task,YACS::ABORT);
          traceExec(task, "state:"+Node::getStateName(task->getState()), ComputePlacement(task));
        }//End of critical section
      }
@@@ -926,7 -927,7 +927,7 @@@ void Executor::launchTasks(const std::v
            {//Critical section
              YACS::BASES::AutoLocker<YACS::BASES::Mutex> alck(&_mutexForSchedulerUpdate);
              (*iter)->aborted();
-             _mainSched->notifyFrom(*iter,YACS::ABORT,this);
+             _mainSched->notifyFrom(*iter,YACS::ABORT);
            }//End of critical section
          }
        catch(...) 
            {//Critical section
              YACS::BASES::AutoLocker<YACS::BASES::Mutex> alck(&_mutexForSchedulerUpdate);
              (*iter)->aborted();
-             _mainSched->notifyFrom(*iter,YACS::ABORT,this);
+             _mainSched->notifyFrom(*iter,YACS::ABORT);
            }//End of critical section
          }
        if((*iter)->getState() == YACS::ERROR)
                {//Critical section
                  YACS::BASES::AutoLocker<YACS::BASES::Mutex> alck(&_mutexForSchedulerUpdate);
                  t->aborted();
-                 _mainSched->notifyFrom(t,YACS::ABORT,this);
+                 _mainSched->notifyFrom(t,YACS::ABORT);
                }//End of critical section
                traceExec(t, "state:"+Node::getStateName(t->getState()),ComputePlacement(*iter));
              }
@@@ -1224,7 -1225,7 +1225,7 @@@ void *Executor::functionForTaskExecutio
              task->aborted();
            }
          execInst->traceExec(task, "state:"+Node::getStateName(task->getState()),placement);
-         sched->notifyFrom(task,ev,execInst);
+         sched->notifyFrom(task,ev);
        }
      catch(Exception& ex)
        {
index 54535a140d33a0fc73d74d506e73d1821ecdb437,4c767b5b7385fcd61667c0806a2f74421a449a46..4ed7f7ac5e030a41ee3b8bad5c2f31245272e6ac
@@@ -1,4 -1,4 +1,4 @@@
 -// Copyright (C) 2006-2015  CEA/DEN, EDF R&D
 +// 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
@@@ -29,7 -29,7 +29,7 @@@
  #include <sstream>
  #include <algorithm>    // std::replace_if
  
--//#define _DEVDEBUG_
++#define _DEVDEBUG_
  #include "YacsTrace.hxx"
  
  using namespace YACS::ENGINE;
@@@ -318,6 -318,14 +318,14 @@@ ForEachLoopPassedData::ForEachLoopPasse
      }
  }
  
+ 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++)
@@@ -761,16 -769,8 +769,16 @@@ YACS::Event ForEachLoop::updateStateFor
        int globalId(_execIds[id]);
        if(_passedData)
          globalId=_passedData->toAbsId(globalId);
 +      sendEvent2("progress_ok",&globalId);
        storeOutValsInSeqForOutOfScopeUse(globalId,id);
      }
 +  else
 +    {
 +      int globalId(_execIds[id]);
 +      if(_passedData)
 +        globalId=_passedData->toAbsId(globalId);
 +      sendEvent2("progress_ko",&globalId);
 +    }
    //
    if(_execCurrentId==getFinishedId())
      {//No more elements of _dataPortToDispatch to treat
@@@ -874,12 -874,14 +882,14 @@@ YACS::Event ForEachLoop::updateStateFor
      return YACS::NOEVENT;
  }
  
- YACS::Event ForEachLoop::updateStateOnFailedEventFrom(Node *node, const Executor *execInst)
+ YACS::Event ForEachLoop::updateStateOnFailedEventFrom(Node *node)
  {
    unsigned int id;
    DynParaLoop::TypeOfNode ton(getIdentityOfNotifyerNode(node,id));
-   if(ton!=WORK_NODE || !execInst->getKeepGoingProperty())
-     return DynParaLoop::updateStateOnFailedEventFrom(node,execInst);
+   // TODO: deal with keepgoing
+   // if(ton!=WORK_NODE || !execInst->getKeepGoingProperty())
+   if(ton!=WORK_NODE )
+     return DynParaLoop::updateStateOnFailedEventFrom(node);
    else
      {
        _failedCounter++;
@@@ -915,8 -917,7 +925,8 @@@ void ForEachLoop::buildDelegateOf(std::
          }
        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),
            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);
@@@ -1047,8 -1048,7 +1057,8 @@@ void ForEachLoop::createOutputOutOfScop
        //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);
      }
@@@ -1173,7 -1173,9 +1183,9 @@@ std::vector<unsigned int> ForEachLoop::
      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++)
      {
@@@ -1194,20 -1196,31 +1206,69 @@@ void ForEachLoop::assignPassedResults(c
    _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 7c1968d38eca47298b28895e43f192aed1679dc7,875b900fa8a2e2a59818f749f5e820da65eab98b..0f3690fb06d157d0981f70e48b6f47cc48d55a2b
@@@ -1,4 -1,4 +1,4 @@@
 -// Copyright (C) 2006-2015  CEA/DEN, EDF R&D
 +// 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
@@@ -127,6 -127,7 +127,7 @@@ namespace YAC
      {
      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;
        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;
        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,
        YACS::Event updateStateForInitNodeOnFinishedEventFrom(Node *node, unsigned int id);
        YACS::Event updateStateForWorkNodeOnFinishedEventFrom(Node *node, unsigned int id, bool isNormalFinish);
        YACS::Event updateStateForFinalizeNodeOnFinishedEventFrom(Node *node, unsigned int id);
-       YACS::Event updateStateOnFailedEventFrom(Node *node, const Executor *execInst);
+       YACS::Event updateStateOnFailedEventFrom(Node *node);
        void buildDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView);
        void getDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView) throw(Exception);
        void releaseDelegateOf(OutPort *portDwn, OutPort *portUp, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView) throw(Exception);
index 91b35f29cdb80175d820a14c8cd7730f10865039,ddb2ac508c3eaadf5e0db410fa8380fb1348e2c9..eeca9c74f419148959318ea31d3ca627d1668dc1
@@@ -1,4 -1,4 +1,4 @@@
 -// Copyright (C) 2006-2015  CEA/DEN, EDF R&D
 +// 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
@@@ -456,7 -456,7 +456,7 @@@ YACS::Event OptimizerLoop::finalize(
   *  \param node : the child node that has failed
   *  \return the state change
   */
- YACS::Event OptimizerLoop::updateStateOnFailedEventFrom(Node *node, const Executor *execInst)
+ YACS::Event OptimizerLoop::updateStateOnFailedEventFrom(Node *node)
  {
    DEBTRACE("OptimizerLoop::updateStateOnFailedEventFrom " << node->getName());
    _alg->setError(string("Error during the execution of YACS node ") + node->getName() +
    _alg->finishProxy();
    _myPool.destroyAll();
    DEBTRACE("OptimizerLoop::updateStateOnFailedEventFrom: returned from error notification.");
-   return DynParaLoop::updateStateOnFailedEventFrom(node,execInst);
+   return DynParaLoop::updateStateOnFailedEventFrom(node);
  }
  
  void OptimizerLoop::checkNoCyclePassingThrough(Node *node) throw(YACS::Exception)
index a5a23cc6818e3bfe9c6dc35fca8f43a04ab735db,2a098438a855d47aa4adfec2c2d1030c535610f2..75c2cf37d3a7f5e69c8be078c879fae5cd5ce855
@@@ -1,4 -1,4 +1,4 @@@
 -// Copyright (C) 2006-2015  CEA/DEN, EDF R&D
 +// 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
@@@ -107,7 -107,7 +107,7 @@@ namespace YAC
        YACS::Event finalize();
  
      protected:
-       virtual YACS::Event updateStateOnFailedEventFrom(Node *node, const Executor *execInst);
+       virtual YACS::Event updateStateOnFailedEventFrom(Node *node);
        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);
        void checkControlDependancy(OutPort *start, InPort *end, bool cross,
diff --combined src/engine/Scheduler.hxx
index d6ee7a1dac11d92d49e7ee3b471678ee23f78ae5,a326f67b6dc5ff855763f026ee75cc6d274f0082..68d9755878541207e719905c72c2933cb973442e
@@@ -1,4 -1,4 +1,4 @@@
 -// Copyright (C) 2006-2015  CEA/DEN, EDF R&D
 +// 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
@@@ -31,7 -31,6 +31,6 @@@ namespace YAC
    namespace ENGINE
    {
      class Task;
-     class Executor;
      
      class Scheduler
      {
@@@ -43,7 -42,7 +42,7 @@@
        virtual std::string getTaskName(Task *task) const = 0;
        virtual std::vector<Task *> getNextTasks(bool& isMore) = 0;
        virtual void selectRunnableTasks(std::vector<Task *>& tasks) = 0;
-       virtual void notifyFrom(const Task *sender, YACS::Event event, const Executor *execInst) = 0;
+       virtual void notifyFrom(const Task *sender, YACS::Event event) = 0;
        //Placement methods
        virtual DeploymentTree getDeploymentTree() const = 0;
        virtual bool isPlacementPredictableB4Run() const = 0;
index 71fb61e96d23320a6e48b77eabe86ac3d8971679,a61b05b3f39298e9298d44f2fc975ad157723a8a..73b64fa7ffcc40a204f7018a3e9f7443b4db9f78
@@@ -1,4 -1,4 +1,4 @@@
 -# Copyright (C) 2012-2015  CEA/DEN, EDF R&D
 +# 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
@@@ -144,6 -144,7 +144,7 @@@ SET(YACSRuntimeSALOME_HEADER
    SalomeOptimizerLoop.hxx
    DistributedPythonNode.hxx
    PyOptimizerAlg.hxx
+   VisitorSalomeSaveState.hxx
    )
  
  # --- sources ---
@@@ -210,6 -211,7 +211,7 @@@ SET(YACSRuntimeSALOME_SOURCE
    PyStdout.cxx                   
    SalomeOptimizerLoop.cxx        
    PyOptimizerAlg.cxx             
+   VisitorSalomeSaveState.cxx
    )
  
  # --- rules ---
index 1f3e47394eb58687c45896a7a8d68b2adb1a5c23,879620de2846edaec5eeae3aa7709034c1d35790..abfcdca0a2d3e5ed40df2a14b4c07696bf774ce0
@@@ -1,4 -1,4 +1,4 @@@
 -# Copyright (C) 2012-2015  CEA/DEN, EDF R&D
 +# 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
@@@ -92,12 -92,15 +92,13 @@@ SET(SWIGINCLUDE
    ${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 
 +    ${PROJECT_SOURCE_DIR}/src/engine_swig/engtypemaps.i  
 +    ${SWIGINCLUDES})
  SWIG_ADD_MODULE(SALOMERuntime python SALOMERuntime.i)
 -ADD_DEPENDENCIES(_SALOMERuntime 
 -                 SALOMERuntime.i 
 -                 ${PROJECT_SOURCE_DIR}/src/engine_swig/pilot.i 
 -                 ${PROJECT_SOURCE_DIR}/src/engine_swig/engtypemaps.i 
 -                 docruntime.i 
 -                 ${SWIGINCLUDES})
  
  SWIG_LINK_LIBRARIES(SALOMERuntime ${_link_LIBRARIES})
  IF(WIN32)
index d0d45bb5573c2dc27f20da59d4854864720ae1ae,258904c9deb26de83b9ed1ba3749ee77fee68af6..c28691cd327c3a360bb853b61da13bd0aa8f5512
@@@ -1,4 -1,4 +1,4 @@@
 -// Copyright (C) 2006-2015  CEA/DEN, EDF R&D
 +// 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
  #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>
  %}
  
  %include "SalomeOptimizerLoop.hxx"
  %include "DistributedPythonNode.hxx"
  
+ namespace YACS
+ {
+   namespace ENGINE
+   {
+     class SchemaSaveState
+     {
+     public:
+       SchemaSaveState(Proc* proc, Executor* exec);
+       virtual void save(std::string xmlSchemaFile);
+     };
+   }
+ }
  %extend YACS::ENGINE::OutputPresetPort
  {
    void setDataPy(PyObject *ob)
index 20052f3721d0c1a7544e13ca1baa66ca60fe6019,ddfc6b004d979049a61cbd3a06e9e7f31273041b..71a9807f818689ea6286e6f49d71ebd45c1ca2e7
@@@ -1,4 -1,4 +1,4 @@@
 -# Copyright (C) 2012-2015  CEA/DEN, EDF R&D
 +# 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
@@@ -73,6 -73,6 +73,7 @@@ SET(YACSloader_LIBRARIE
    ${OMNIORB_LIBRARIES}
    ${LIBXML2_LIBRARIES}
    YACSlibEngine
++  YACSRuntimeSALOME
    )
  SET(_link_LIBRARIES
    YACSloader
@@@ -144,9 -144,6 +145,9 @@@ SET(resume_SOURCE
  SET(debugger_SOURCES
    debugger.cxx
    )
 +SET(ExampleOfObserversPluginForDriver_SOURCES
 +  ExampleOfObserversPluginForDriver.cxx
 +  )
  
  # --- rules ---
  
@@@ -154,10 -151,6 +155,10 @@@ ADD_LIBRARY(YACSloader ${YACSloader_SOU
  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})
  
index faaa1a5fdd5ea162fa6bc29f97458f028418758f,f4222f10c2ebb695f27787a140342c84b13a8d67..2de532554eb27f0990fb9931aa81660f621c132f
@@@ -1,4 -1,4 +1,4 @@@
 -// Copyright (C) 2006-2015  CEA/DEN, EDF R&D
 +// 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
@@@ -27,6 -27,8 +27,9 @@@
  #include "Runtime.hxx"
  #include "InputPort.hxx"
  #include "ElementaryNode.hxx"
+ #include "ForEachLoop.hxx"
+ #include "Any.hxx"
++#include "TypeConversions.hxx"
  
  #include <iostream>
  #include <string>
@@@ -34,7 -36,7 +37,7 @@@
  #include <cstdarg>
  #include <cassert>
  
--//#define _DEVDEBUG_
++#define _DEVDEBUG_
  #include "YacsTrace.hxx"
  
  using namespace YACS::ENGINE;
@@@ -80,7 -82,6 +83,7 @@@ void stateParser::init(const xmlChar** 
    _nodeStateValue["DISABLED"] =YACS::DISABLED;
    _nodeStateValue["FAILED"] =YACS::FAILED;
    _nodeStateValue["ERROR"] =YACS::ERROR;
 +  _nodeStates.clear();
  }
  
  
@@@ -231,6 -232,6 +234,7 @@@ public
  void nodeParser::init(const xmlChar** p, xmlParserBase* father)
  {
    DEBTRACE("nodeParser::init()");
++  _loopSamples.clear();
    _state = XMLINNODE;
    _father = father;
    _stackState.push(_state);
@@@ -250,6 -251,7 +254,12 @@@ void nodeParser::onStart (const XML_Cha
    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") parser = new loopPortParser();
++  else if (element == "loopOutputPort")
++  {
++    loopPortParser* sparser = new loopPortParser();
++    _loopSamples.push_back(sparser);
++    parser = sparser;
++  }
    else
      { 
        _what = "expected name, state or inputPort, got <" + element + ">";
@@@ -362,10 -364,10 +372,118 @@@ void nodeParser::onEnd   (const XML_Cha
          }
        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)
@@@ -660,7 -662,148 +778,130 @@@ void simpleTypeParser::charData(std::st
    _data = _data + data;
  }
  
 -  _state = XMLINPORT;
+ // ----------------------------------------------------------------------------
+ void loopPortParser::init(const xmlChar** p, xmlParserBase* father)
+ {
+   DEBTRACE("loopPortParser::init()");
 -  else if (element == "sample") parser = new sampleParser();
++  //_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();
 -  string portName = _mapAttrib["name"];
 -  string nodeName = _father->getAttribute("name");
 -  string nodeType = _father->getAttribute("type");
 -  Node *node = _p->getChildByName(nodeName);
 -  if (nodeType != "forEachLoop")
 -  {
 -    _what = "loopOutputPort attribute is not valid for node <" + nodeName + ">";
 -    _state = XMLFATALERROR;
 -    stopParse(_what);
 -  }
++  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)
+ {
+ }
  
 -  _state = XMLINPORT;
++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()");
 -  Any * value;
 -  value = xmlToAny();
++  //_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());
 -}
 -
 -Any* sampleParser::xmlToAny() throw(ConversionException)
 -{
 -  xmlDocPtr doc;
 -  xmlNodePtr cur;
 -  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(edGetType(),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;
++  _sampleFather->addSample(index, _data);
++  stateParser::onEnd(name);
+ }
+ void sampleParser::charData(std::string data)
+ {
++  _data = _data + data;
+ }
  
  // ----------------------------------------------------------------------------
  
index 3935d569ee57d9504a8e3157f2de9ed5e20ebb7e,16e423442671c03723ee199c6ee5ab8cd6c00d12..6102e0b3f72407f3fc770a1919f019da7cf17c81
@@@ -1,4 -1,4 +1,4 @@@
 -// Copyright (C) 2006-2015  CEA/DEN, EDF R&D
 +// 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
  
  #include "YACSloaderExport.hxx"
  #include "xmlParserBase.hxx"
+ #include "InputPort.hxx"
  
  #include "define.hxx"
  #include "Exception.hxx"
+ #include <vector>
++#include <list>
  
  namespace YACS
  {
@@@ -32,6 -34,8 +35,9 @@@
    {
      class Proc;
      class Runtime;
+     class SequenceAny;
+     class Any;
++    class TypeCode;
  
      //! Load state from a file into a Proc
      /*!
      };
  
  
++    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
        virtual void charData(std::string data);
      };
  
 -      std::vector<SequenceAny *> _outputValues;
 -      std::vector<std::string> _outputNames;
+     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;
 -    protected:
 -      Any* xmlToAny()throw(ConversionException);
++      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
index 2a898e860d152367b62d799f86f4d3f37e163e2f,f71028e60bffbad176e36c2b5e4b259733c012b8..a26298375d163a22c8f8bbff4740039a76b4f146
@@@ -1,4 -1,4 +1,4 @@@
 -// Copyright (C) 2006-2015  CEA/DEN, EDF R&D
 +// 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
@@@ -24,7 -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 +41,7 @@@
  #include <signal.h>
  #include <list>
  
 -#ifdef WIN32
 +#if defined WIN32 || defined __APPLE__
  #else
  #include <argp.h>
  #endif
@@@ -58,7 -58,7 +58,7 @@@ const char *argp_program_bug_address ="
  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,70 -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. 
  }
  
  // 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);
@@@ -272,7 -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();
@@@ -308,7 -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();
@@@ -367,7 -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];
            return 1;
          }
        // Initialize the ports
 -      for(it=myArgs.init_ports.begin(); it != myArgs.init_ports.end(); it++)
 +      for(std::list<std::string>::iterator it=myArgs.init_ports.begin(); it != myArgs.init_ports.end(); it++)
        {
          std::string node, port, value;
          if(parse_init_port((*it), node, port, value))
            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;
        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();
        r->fini();
        delete r;
        delete disp;
 +      UnLoadObserversPluginIfAny();
        return return_value;
      }
    catch (YACS::Exception& e)
index 4f41b4ad19388381cc3ff7b327dd5e7698d786a5,821157f5da35a507f39e979f5decfd6d2542927d..13dd1bcd9c0bfa5e061813d14d01fd3ad41e9055
@@@ -1,4 -1,4 +1,4 @@@
 -// Copyright (C) 2006-2015  CEA/DEN, EDF R&D
 +// 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
@@@ -67,5 -67,5 +67,5 @@@
  %include "YACSloaderExport.hxx"
  %include "parsers.hxx"
  %import "xmlParserBase.hxx"
--%include "LoadState.hxx"
++//%include "LoadState.hxx"