Salome HOME
Correction of bug MANTIS23234 CEA1726.
[modules/yacs.git] / src / engine / DynParaLoop.cxx
index 582ca5680706d18cd57f5bfc45e6a5596fd9d3ab..db101aebadadf8de673135da8abc0b6eee390f4a 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2006-2014  CEA/DEN, EDF R&D
+// 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
@@ -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)
+    _splittedPort(NAME_OF_SPLITTED_SEQ_OUT,this,typeOfDataSplitted),_initializingCounter(0),_unfinishedCounter(0),_failedCounter(0)
 {
 }
 
@@ -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)
+    _nbOfEltConsumed(0),_initializingCounter(0),_unfinishedCounter(0),_failedCounter(0)
 {
   if(other._node)
     _node=other._node->clone(this,editionOnly);
@@ -117,6 +117,7 @@ void DynParaLoop::init(bool start)
   _nbOfBranches.exInit(start);
   _splittedPort.exInit();
   _nbOfEltConsumed=0;
+  _failedCounter=0;
 }
 
 Node *DynParaLoop::edSetInitNode(Node *node)
@@ -153,6 +154,34 @@ int DynParaLoop::getNumberOfOutputPorts() const
   return ComposedNode::getNumberOfOutputPorts()+1;
 }
 
+/*!
+ * DynParaLoop creates at runtime (exupdateState) clone of nodes. One clone per branch.
+ * This method returns the id of the branch given the node \a node.
+ * If \a node is not a dynamically created node in \a this -1 is returned.
+ */
+int DynParaLoop::getBranchIDOfNode(Node *node) const
+{
+  if(_node)
+    {
+      for(std::vector<Node *>::const_iterator it=_execNodes.begin();it!=_execNodes.end();it++)
+        if(node==*it)
+          return std::distance(_execNodes.begin(),it);
+    }
+  if(_finalizeNode)
+    {
+      for(std::vector<Node *>::const_iterator it=_execFinalizeNodes.begin();it!=_execFinalizeNodes.end();it++)
+        if(node==*it)
+          return std::distance(_execFinalizeNodes.begin(),it);
+    }
+  if(_initNode)
+    {
+      for(std::vector<Node *>::const_iterator it=_execInitNodes.begin();it!=_execInitNodes.end();it++)
+        if(node==*it)
+          return std::distance(_execInitNodes.begin(),it);
+    }
+  return -1;
+}
+
 std::list<OutputPort *> DynParaLoop::getSetOfOutputPort() const
 {
   list<OutputPort *> ret=ComposedNode::getSetOfOutputPort();
@@ -415,16 +444,29 @@ void DynParaLoop::buildDelegateOf(InPort * & port, OutPort *initialStart, const
 {
   string typeOfPortInstance=port->getNameOfTypeOfCurrentInstance();
   if(typeOfPortInstance!=InputPort::NAME)
-    throw Exception("DynParaLoop::buildDelegateOf : A link with datastream end inside DynParaLoop this is not possible");
+    throw Exception("DynParaLoop::buildDelegateOf : A link with datastream end inside DynParaLoop is not possible");
 }
 
 void DynParaLoop::buildDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView)
 {
+  std::string linkName("(");
+  linkName += port.first->getName()+" to "+finalTarget->getName()+")";
   if(_initNode)
     if(isInMyDescendance(port.first->getNode())==_initNode)
-      throw Exception("DynParaLoop::buildDelegateOf : uncorrect ForEach link : a link starting from init node can't leave the scope of ForEachLoop node it belongs to.");
+      throw Exception(std::string("Illegal link within a parallel loop: \
+a link starting from the init node can't leave the scope of the loop.")
+                    + linkName);
+
+  if(_finalizeNode)
+    if(isInMyDescendance(port.first->getNode())==_finalizeNode)
+      throw Exception(std::string("Illegal link within a parallel loop: \
+an output port of the finalize node can't be linked.")
+                    + linkName);
+
   if(port.first==&_splittedPort)
-    throw Exception("DynParaLoop::buildDelegateOf : uncorrect ForEach link : splitted port must be link within the scope of ForEachLoop node it belongs to.");
+    throw Exception(std::string("Illegal link within a parallel loop: \
+the 'evalSamples' port must be linked within the scope of the loop.")
+                    + linkName);
 }
 
 void DynParaLoop::checkCFLinks(const std::list<OutPort *>& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const
@@ -438,8 +480,6 @@ void DynParaLoop::checkCFLinks(const std::list<OutPort *>& starts, InputPort *en
       if(starts.size()!=1)
         throw Exception(what);
       //ASSERT(direction) : see DynParaLoop::checkControlDependancy only 'fw' filled.
-      if(*(starts.begin())!=&_splittedPort)
-        throw Exception(what);
       if(alreadyFed==FREE_ST)
         alreadyFed=FED_ST;
       else if(alreadyFed==FED_ST)
@@ -464,10 +504,37 @@ void DynParaLoop::checkControlDependancy(OutPort *start, InPort *end, bool cross
                                          std::map< ComposedNode *, std::list < OutPort *>, SortHierarc >& bw,
                                          LinkInfo& info) const
 {
-  if(start==&_splittedPort)
     fw[(ComposedNode *)this].push_back(start);
-  else
-    throw Exception("DynParaLoop::checkControlDependancy : Internal error occured - should never been called !");
+}
+
+void DynParaLoop::checkLinkPossibility(OutPort *start, const std::list<ComposedNode *>& pointsOfViewStart,
+                                InPort *end, const std::list<ComposedNode *>& pointsOfViewEnd) throw(YACS::Exception)
+{
+  ComposedNode::checkLinkPossibility(start, pointsOfViewStart, end, pointsOfViewEnd);
+  Node * startNode = isInMyDescendance(start->getNode());
+  Node * endNode = isInMyDescendance(end->getNode());
+  std::string linkName("(");
+  linkName += start->getName()+" to "+end->getName()+")";
+  
+  if(start == &_splittedPort && endNode != _node)
+    throw Exception(std::string("Illegal link within a parallel loop: \
+the 'evalSamples' port can only be connected to the working node of the loop.")
+                    + linkName);
+  
+  if(_finalizeNode && _finalizeNode == startNode)
+    throw Exception(std::string("Illegal link within a parallel loop: \
+the finalize node can't be the origin of a link.")
+                    + linkName);
+  
+  if(_initNode && _node == startNode && _initNode == endNode)
+    throw Exception(std::string("Illegal link within a parallel loop: \
+can't make a link from the working node to the init node.")
+                    + linkName);
+  
+  if(_finalizeNode && _node == startNode && _finalizeNode == endNode)
+    throw Exception(std::string("Illegal link within a parallel loop: \
+can't make a link from the working node to the finalize node.")
+                    + linkName);
 }
 
 /*!
@@ -629,7 +696,7 @@ void DynParaLoop::forwardExecStateToOriginalBody(Node *execNode)
  *  \param node : the child node that has failed
  *  \return the state change
  */
-YACS::Event DynParaLoop::updateStateOnFailedEventFrom(Node *node)
+YACS::Event DynParaLoop::updateStateOnFailedEventFrom(Node *node, const Executor *execInst)
 {
   DEBTRACE("DynParaLoop::updateStateOnFailedEventFrom " << node->getName());
   setState(YACS::FAILED);
@@ -684,6 +751,26 @@ vector<Node *> DynParaLoop::cloneAndPlaceNodesCoherently(const vector<Node *> &
             treeToDup.appendTask(*iter, (*iter)->getDynClonerIfExists(this));
         }
     }
+  
+  // Build the links between clones.
+  // Only the links starting from initNode are possible.
+  if(_initNode)
+  {
+    std::vector< std::pair<OutPort *, InPort *> > outLinks = _initNode->getSetOfLinksLeavingCurrentScope();
+    std::vector< std::pair<OutPort *, InPort *> >::const_iterator it;
+    for(it=outLinks.begin(); it!=outLinks.end(); it++)
+    {
+      OutPort *startPort = it->first;
+      InPort *endPort = it->second;
+      Node* destNode = isInMyDescendance(endPort->getNode());
+      if(destNode == _node)
+        edAddLink(clones[0]->getOutPort(startPort->getName()),
+                  clones[1]->getInPort(endPort->getName()));
+      if(destNode == _finalizeNode)
+        edAddLink(clones[0]->getOutPort(startPort->getName()),
+                  clones[2]->getInPort(endPort->getName()));
+    }
+  }
 
   DEBTRACE("Placing nodes...")
   vector<Container *> conts=treeToDup.getAllContainers();
@@ -804,6 +891,11 @@ Node * DynParaLoop::getFinalizeNode()
   return _finalizeNode;
 }
 
+int DynParaLoop::getMaxLevelOfParallelism() const
+{
+  return _nbOfBranches.getIntValue() * _node->getMaxLevelOfParallelism();
+}
+
 void DynParaLoop::shutdown(int level)
 {
   if(level==0)return;