1 // Copyright (C) 2006-2019 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include "DynParaLoop.hxx"
21 #include "LinkInfo.hxx"
22 #include "OutPort.hxx"
23 #include "Container.hxx"
24 #include "ComponentInstance.hxx"
25 #include "ServiceNode.hxx"
26 #include "InlineNode.hxx"
27 #include "ElementaryNode.hxx"
28 #include "Visitor.hxx"
34 #include "YacsTrace.hxx"
37 using namespace YACS::ENGINE;
39 const char DynParaLoop::NAME_OF_SPLITTED_SEQ_OUT[] = "evalSamples";
40 const char DynParaLoop::OLD_NAME_OF_SPLITTED_SEQ_OUT[] = "SmplPrt"; // For backward compatibility with 5.1.4
42 const char DynParaLoop::NAME_OF_NUMBER_OF_BRANCHES[]="nbBranches";
44 DynParaLoop::DynParaLoop(const std::string& name, TypeCode *typeOfDataSplitted)
45 : ComposedNode(name),_node(0),_initNode(0),_finalizeNode(0),_nbOfEltConsumed(0),
46 _nbOfBranches(NAME_OF_NUMBER_OF_BRANCHES,this,Runtime::_tc_int),
47 _splittedPort(NAME_OF_SPLITTED_SEQ_OUT,this,typeOfDataSplitted),_initializingCounter(0),_unfinishedCounter(0),_failedCounter(0),_weight(), _loopWeight(0)
49 _weight.setDefaultLoop();
52 DynParaLoop::~DynParaLoop()
59 DynParaLoop::DynParaLoop(const DynParaLoop& other, ComposedNode *father, bool editionOnly)
60 : ComposedNode(other,father), _nbOfBranches(other._nbOfBranches,this),
61 _splittedPort(other._splittedPort,this), _node(0), _initNode(0), _finalizeNode(0),
62 _nbOfEltConsumed(0),_initializingCounter(0),_unfinishedCounter(0),_failedCounter(0),_weight(other._weight), _loopWeight(other._loopWeight)
65 _node=other._node->clone(this,editionOnly);
67 _initNode=other._initNode->clone(this,editionOnly);
68 if(other._finalizeNode)
69 _finalizeNode = other._finalizeNode->clone(this,editionOnly);
70 const AnyOutputPort& startOfLinksToReproduce=other._splittedPort;
71 set<InPort *> endsOfLinksToReproduce=startOfLinksToReproduce.edSetInPort();
72 for(set<InPort *>::iterator iter=endsOfLinksToReproduce.begin();iter!=endsOfLinksToReproduce.end();iter++)
73 edAddLink(&_splittedPort,getInPort(other.getPortName(*iter)));
76 Node *DynParaLoop::edSetNode(Node *node)
78 return checkConsistencyAndSetNode(_node, node);
81 //! This method is used to factorize methods edSetNode, edSetInitNode and edSetFinalizeNode
82 Node * DynParaLoop::checkConsistencyAndSetNode(Node* &nodeToReplace, Node* node)
84 if (node == NULL || nodeToReplace == node)
87 throw Exception(string("Can't set node: node ") + node->getName() + " is not orphan.");
88 if (_node && _node != nodeToReplace && _node->getName() == node->getName())
89 throw Exception(string("Can't set node: node ") + node->getName() +
90 " has the same name than exec node already in " + _name + ".");
91 if (_initNode && _initNode != nodeToReplace && _initNode->getName() == node->getName())
92 throw Exception(string("Can't set node: node ") + node->getName() +
93 " has the same name than init node already in " + _name + ".");
94 if (_finalizeNode && _finalizeNode != nodeToReplace && _finalizeNode->getName() == node->getName())
95 throw Exception(string("Can't set node: node ") + node->getName() +
96 " has the same name than finalize node already in " + _name + ".");
97 checkNoCrossHierachyWith(node);
98 ComposedNode::edRemoveChild(nodeToReplace);
99 Node * ret = nodeToReplace;
100 nodeToReplace = node;
101 nodeToReplace->_father = this;
102 // set _modified flag so that edUpdateState can refresh state
107 void DynParaLoop::init(bool start)
109 ComposedNode::init(start);
112 string what("DynParaLoop::init : no node specified for ForEachLoop with name "); what +=_name;
113 throw Exception(what);
116 if (_initNode) _initNode->init(start);
117 if (_finalizeNode) _finalizeNode->init(start);
118 _nbOfBranches.exInit(start);
119 _splittedPort.exInit();
124 Node *DynParaLoop::edSetInitNode(Node *node)
126 return checkConsistencyAndSetNode(_initNode, node);
129 Node * DynParaLoop::edSetFinalizeNode(Node * node)
131 return checkConsistencyAndSetNode(_finalizeNode, node);
134 //! Connect an OutPort to an InPort and add control link if necessary
136 * Connect the ports with a data link (edAddLink)
137 * In a Loop don't add control flow link : use this only to add data back links
139 * \param start : the OutPort to connect
140 * \param end : the InPort to connect
141 * \return true if a new link has been created, false otherwise.
143 bool DynParaLoop::edAddDFLink(OutPort *start, InPort *end) throw(YACS::Exception)
145 return edAddLink(start,end);
148 int DynParaLoop::getNumberOfInputPorts() const
150 return ComposedNode::getNumberOfInputPorts()+1;
153 int DynParaLoop::getNumberOfOutputPorts() const
155 return ComposedNode::getNumberOfOutputPorts()+1;
159 * DynParaLoop creates at runtime (exupdateState) clone of nodes. One clone per branch.
160 * This method returns the id of the branch given the node \a node.
161 * If \a node is not a dynamically created node in \a this -1 is returned.
163 int DynParaLoop::getBranchIDOfNode(Node *node) const
167 for(std::vector<Node *>::const_iterator it=_execNodes.begin();it!=_execNodes.end();it++)
169 return std::distance(_execNodes.begin(),it);
173 for(std::vector<Node *>::const_iterator it=_execFinalizeNodes.begin();it!=_execFinalizeNodes.end();it++)
175 return std::distance(_execFinalizeNodes.begin(),it);
179 for(std::vector<Node *>::const_iterator it=_execInitNodes.begin();it!=_execInitNodes.end();it++)
181 return std::distance(_execInitNodes.begin(),it);
186 std::list<OutputPort *> DynParaLoop::getSetOfOutputPort() const
188 list<OutputPort *> ret=ComposedNode::getSetOfOutputPort();
189 ret.push_back((OutputPort *)&_splittedPort);
193 std::list<OutputPort *> DynParaLoop::getLocalOutputPorts() const
195 list<OutputPort *> ret=ComposedNode::getLocalOutputPorts();
196 ret.push_back((OutputPort *)&_splittedPort);
200 OutPort *DynParaLoop::getOutPort(const std::string& name) const throw(YACS::Exception)
202 if (name == NAME_OF_SPLITTED_SEQ_OUT || name == OLD_NAME_OF_SPLITTED_SEQ_OUT)
203 return (OutPort *)&_splittedPort;
204 return ComposedNode::getOutPort(name);
208 OutputPort *DynParaLoop::getOutputPort(const std::string& name) const throw(YACS::Exception)
210 if (name == NAME_OF_SPLITTED_SEQ_OUT || name == OLD_NAME_OF_SPLITTED_SEQ_OUT)
211 return (OutputPort *)&_splittedPort;
212 return ComposedNode::getOutputPort(name);
215 bool DynParaLoop::isPlacementPredictableB4Run() const
220 Node *DynParaLoop::edRemoveNode()
222 return removeNode(_node);
225 //! This method is used to factorize methods edRemoveNode, edRemoveInitNode and edRemoveFinalizeNode
226 Node * DynParaLoop::removeNode(Node* &nodeToRemove)
230 ComposedNode::edRemoveChild(nodeToRemove);
231 Node * ret = nodeToRemove;
237 Node *DynParaLoop::edRemoveInitNode()
239 return removeNode(_initNode);
242 Node * DynParaLoop::edRemoveFinalizeNode()
244 return removeNode(_finalizeNode);
247 void DynParaLoop::edRemoveChild(Node *node) throw(YACS::Exception)
249 ComposedNode::edRemoveChild(node);
254 if(node==_finalizeNode)
259 bool DynParaLoop::edAddChild(Node *DISOWNnode) throw(YACS::Exception)
261 return edSetNode(DISOWNnode);
264 std::list<Node *> DynParaLoop::edGetDirectDescendants() const
268 ret.push_back(_node);
270 ret.push_back(_initNode);
272 ret.push_back(_finalizeNode);
276 std::list<InputPort *> DynParaLoop::getSetOfInputPort() const
278 list<InputPort *> ret=ComposedNode::getSetOfInputPort();
279 ret.push_back((InputPort *)&_nbOfBranches);
283 InputPort *DynParaLoop::getInputPort(const std::string& name) const throw(YACS::Exception)
285 if(name==NAME_OF_NUMBER_OF_BRANCHES)
286 return (InputPort *)&_nbOfBranches;
287 return ComposedNode::getInputPort(name);
290 std::list<InputPort *> DynParaLoop::getLocalInputPorts() const
292 list<InputPort *> ret=ComposedNode::getLocalInputPorts();
293 ret.push_back((InputPort *)&_nbOfBranches);
297 unsigned DynParaLoop::getNumberOfBranchesCreatedDyn() const throw(YACS::Exception)
299 if(_execNodes.empty())
300 throw Exception("ForEachLoop::getNumberOfBranches : No branches created dynamically ! - ForEachLoop needs to run or to be runned to call getNumberOfBranches");
302 return _execNodes.size();
305 Node *DynParaLoop::getChildByShortName(const std::string& name) const throw(YACS::Exception)
307 if (_node && name == _node->getName())
309 if (_initNode && name == _initNode->getName())
311 if (_finalizeNode && name == _finalizeNode->getName())
312 return _finalizeNode;
313 std::string what("node "); what+= name ; what+=" is not a child of DynParaLoop node "; what += getName();
314 throw Exception(what);
317 Node *DynParaLoop::getChildByNameExec(const std::string& name, unsigned id) const throw(YACS::Exception)
319 if(id>=getNumberOfBranchesCreatedDyn())
320 throw Exception("ForEachLoop::getChildByNameExec : invalid id - too large compared with dynamically created branches.");
321 if (_node && name == _node->getName())
322 return _execNodes[id];
323 if (_initNode && name == _initNode->getName())
324 return _execInitNodes[id];
325 if (_finalizeNode && name == _finalizeNode->getName())
326 return _execFinalizeNodes[id];
327 std::string what("node "); what+= name ; what+=" is not a child of DynParaLoop node "; what += getName();
328 throw Exception(what);
331 void DynParaLoop::cleanDynGraph()
333 vector<Node *>::iterator iter;
334 for(iter=_execNodes.begin() ; iter!=_execNodes.end() ; iter++)
337 for(iter=_execInitNodes.begin() ; iter!=_execInitNodes.end() ; iter++)
339 _execInitNodes.clear();
340 for(iter=_execFinalizeNodes.begin() ; iter!=_execFinalizeNodes.end() ; iter++)
342 _execFinalizeNodes.clear();
346 * This method applies on newly cloned on exec nodes (_execNodes/_execInitNodes)
347 * the setting of input ports coming from outside of 'this'
349 void DynParaLoop::prepareInputsFromOutOfScope(int branchNb)
351 set< InPort * > portsToSetVals=getAllInPortsComingFromOutsideOfCurrentScope();
353 // This tweak is to fix problems with nested dynamic loops where links are not cloned properly
354 list<InPort *> temp = getSetOfInPort();
355 for(list<InPort *>::iterator iter2=temp.begin();iter2!=temp.end();iter2++)
357 if ((*iter2)->edSetOutPort().size() == 1 && *(*iter2)->edSetOutPort().begin() == NULL)
359 portsToSetVals.insert(*iter2);
363 // local input ports are not candidates for dynamically duplicated inport.
364 list<InputPort *> localPorts = getLocalInputPorts();
365 for(list<InputPort *>::iterator iter = localPorts.begin() ; iter != localPorts.end() ; iter++)
366 portsToSetVals.erase(*iter);
367 for(set< InPort * >::iterator iter=portsToSetVals.begin();iter!=portsToSetVals.end();iter++)
369 InputPort *curPortCasted=(InputPort *) *iter;//Cast granted by ForEachLoop::buildDelegateOf(InPort)
370 void *val=curPortCasted->get();
371 InputPort *portToSet=getDynInputPortByAbsName(branchNb,getInPortName(*iter),true);
372 if(portToSet)//portToSet==0 in case of portToSet==_splitterNode._dataPortToDispatch of ForEach
374 portToSet->put((const void *)val);
375 portToSet->edNotifyReferencedBy(nullptr,false);//This is to indicate that somewhere somebody deals with this inputport
376 //even if no direct physical link exists. This exclusively for _execNodes[branchNb]::init on the next turn of loop.
377 //false is put as 2nd parameter to tell to portToSet, do not touch to the data in case of squeezeMemory.
382 void DynParaLoop::putValueOnBranch(Any *val, unsigned branchId, bool first)
384 bool isDispatched = false;
385 set<InPort *> inPrtLkdWthSplttdPrt=_splittedPort.edSetInPort();
386 for(set<InPort *>::iterator iter=inPrtLkdWthSplttdPrt.begin();iter!=inPrtLkdWthSplttdPrt.end();iter++)
388 std::string portNameOnCurPrt=getPortName(*iter);
389 InputPort *portOnGivenBranch=getDynInputPortByAbsName(branchId,portNameOnCurPrt,first);//Cast granted because impossible to have cross protocol with _splittedPort
390 //see OptimizerLoop::buildDelegateOf
391 if(portOnGivenBranch)
394 portOnGivenBranch->edNotifyReferencedBy(0);
395 InputPort *traducer=getRuntime()->adapt(portOnGivenBranch,
396 Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME,_splittedPort.edGetType());
397 traducer->put((const void *)val);
399 if(traducer!=portOnGivenBranch)
405 Any *tmp=val->clone();
406 _splittedPort.setValue(tmp);
411 DynParaLoop::TypeOfNode DynParaLoop::getIdentityOfNotifyerNode(const Node *node, unsigned& id)
413 vector<Node *>::iterator iter;
415 for (iter=_execNodes.begin() ; iter!=_execNodes.end() ; iter++,id++)
419 for (iter=_execInitNodes.begin() ; iter!=_execInitNodes.end() ; iter++,id++)
423 for (iter=_execFinalizeNodes.begin() ; iter!=_execFinalizeNodes.end() ; iter++,id++)
425 return FINALIZE_NODE;
428 void DynParaLoop::setWeight(double loopWeight)
431 throw Exception("DynParaLoop::setWeight : invalid input value !");
432 _loopWeight=loopWeight;
435 ComplexWeight* DynParaLoop::getWeight()
438 _weight.setLoopWeight(_loopWeight, _node->getMaxLevelOfParallelism()); // not done in setWeight because _node can be null at that time
442 bool DynParaLoop::isMultiplicitySpecified(unsigned& value) const
444 if(_nbOfBranches.edIsManuallyInitialized())
445 if(_nbOfBranches.edGetNumberOfLinks()==0)
447 value=_nbOfBranches.getIntValue();
453 void DynParaLoop::forceMultiplicity(unsigned value)
455 _nbOfBranches.edRemoveAllLinksLinkedWithMe();
456 _nbOfBranches.edInit((int)value);
459 void DynParaLoop::buildDelegateOf(InPort * & port, OutPort *initialStart, const std::list<ComposedNode *>& pointsOfView)
461 string typeOfPortInstance=port->getNameOfTypeOfCurrentInstance();
462 if(typeOfPortInstance!=InputPort::NAME)
463 throw Exception("DynParaLoop::buildDelegateOf : A link with datastream end inside DynParaLoop is not possible");
466 void DynParaLoop::buildDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView)
468 std::string linkName("(");
469 linkName += port.first->getName()+" to "+finalTarget->getName()+")";
471 if(isInMyDescendance(port.first->getNode())==_initNode)
472 throw Exception(std::string("Illegal link within a parallel loop: \
473 a link starting from the init node can't leave the scope of the loop.")
477 if(isInMyDescendance(port.first->getNode())==_finalizeNode)
478 throw Exception(std::string("Illegal link within a parallel loop: \
479 an output port of the finalize node can't be linked.")
482 if(port.first==&_splittedPort)
483 throw Exception(std::string("Illegal link within a parallel loop: \
484 the 'evalSamples' port must be linked within the scope of the loop.")
488 void DynParaLoop::checkCFLinks(const std::list<OutPort *>& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const
490 const char what[]="DynParaLoop::checkCFLinks : internal error.";
491 //First dealing checkCFLinks forwarding...
492 if(isInMyDescendance(end->getNode())==0)//no chance that _splittedPort is in starts due to buildDelegate.
493 solveObviousOrDelegateCFLinks(starts,end,alreadyFed,direction,info);
495 {//no forwarding here.
497 throw Exception(what);
498 //ASSERT(direction) : see DynParaLoop::checkControlDependancy only 'fw' filled.
499 if(alreadyFed==FREE_ST)
501 else if(alreadyFed==FED_ST)
502 {//Shame ! splittedPort fills a port already fed...
503 info.pushInfoLink(*(starts.begin()),end,I_USELESS);
509 * \param start : start port
510 * \param end : end port
511 * \param cross indicates if start -> end link is a DS link behind.
512 * \param fw out parameter.
513 * \param fwCross out parameter storing links where a cross has been detected.
514 * \param bw out parameter where backward links are stored.
515 * \param info : collected information
517 void DynParaLoop::checkControlDependancy(OutPort *start, InPort *end, bool cross,
518 std::map < ComposedNode *, std::list < OutPort * >, SortHierarc >& fw,
519 std::vector<OutPort *>& fwCross,
520 std::map< ComposedNode *, std::list < OutPort *>, SortHierarc >& bw,
521 LinkInfo& info) const
523 fw[(ComposedNode *)this].push_back(start);
526 void DynParaLoop::checkLinkPossibility(OutPort *start, const std::list<ComposedNode *>& pointsOfViewStart,
527 InPort *end, const std::list<ComposedNode *>& pointsOfViewEnd) throw(YACS::Exception)
529 ComposedNode::checkLinkPossibility(start, pointsOfViewStart, end, pointsOfViewEnd);
530 Node * startNode = isInMyDescendance(start->getNode());
531 Node * endNode = isInMyDescendance(end->getNode());
532 std::string linkName("(");
533 linkName += start->getName()+" to "+end->getName()+")";
535 if(start == &_splittedPort && endNode != _node)
536 throw Exception(std::string("Illegal link within a parallel loop: \
537 the 'evalSamples' port can only be connected to the working node of the loop.")
540 if(_finalizeNode && _finalizeNode == startNode)
541 throw Exception(std::string("Illegal link within a parallel loop: \
542 the finalize node can't be the origin of a link.")
545 if(_initNode && _node == startNode && _initNode == endNode)
546 throw Exception(std::string("Illegal link within a parallel loop: \
547 can't make a link from the working node to the init node.")
550 if(_finalizeNode && _node == startNode && _finalizeNode == endNode)
551 throw Exception(std::string("Illegal link within a parallel loop: \
552 can't make a link from the working node to the finalize node.")
557 * \note : For a given name 'name' of port in absolute form from this, returns the corresponding InputPort
558 * instance of the port for the branch # 'branchNb'.
559 * The port can be part of _node or _initNode if it exists (if 'initNodeAdmitted' is true).
560 * \b WARNING : no check performed on 'branchNb' value to see if it is compatible with size of '_execNodes'.
561 * This method is called to dispatch value on each InputPort linked to this->._splitterNode._splittedPort
563 InputPort *DynParaLoop::getDynInputPortByAbsName(int branchNb, const std::string& name, bool initNodeAdmitted)
565 string portName, nodeName;
566 splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,true);
567 Node *staticChild = getChildByName(nodeName);
568 Node *desc=isInMyDescendance(staticChild);
571 splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,false);
572 return _execNodes[branchNb]->getInputPort(portName);
574 else if(desc==_initNode)
577 splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,false);
578 return _execInitNodes[branchNb]->getInputPort(portName);
583 void DynParaLoop::checkBasicConsistency() const throw(YACS::Exception)
585 DEBTRACE("DynParaLoop::checkBasicConsistency");
586 ComposedNode::checkBasicConsistency();
588 throw Exception("For a dynamic loop, internal node is mandatory");
591 std::string DynParaLoop::getErrorReport()
593 DEBTRACE("DynParaLoop::getErrorReport: " << getName() << " " << _state);
594 YACS::StatesForNode effectiveState=getEffectiveState();
596 if(effectiveState != YACS::INVALID && effectiveState != YACS::ERROR && effectiveState != YACS::FAILED)
599 std::string report="<error node= " + getName();
600 switch(effectiveState)
603 report=report+" state= INVALID";
606 report=report+" state= ERROR";
609 report=report+" state= FAILED";
614 report=report + ">\n" ;
615 if(_errorDetails != "")
616 report=report+_errorDetails+"\n";
618 if(_execNodes.empty())
621 list<Node *> constituents=edGetDirectDescendants();
622 for(list<Node *>::iterator iter=constituents.begin(); iter!=constituents.end(); iter++)
624 std::string rep=(*iter)->getErrorReport();
627 report=report+rep+"\n";
634 for(vector<Node *>::iterator iter=_execInitNodes.begin();iter!=_execInitNodes.end();iter++)
636 std::string rep=(*iter)->getErrorReport();
639 report=report+rep+"\n";
642 for(vector<Node *>::iterator iter=_execNodes.begin();iter!=_execNodes.end();iter++)
646 std::string rep=(*iter)->getErrorReport();
649 report=report+rep+"\n";
653 for(vector<Node *>::iterator iter=_execFinalizeNodes.begin();iter!=_execFinalizeNodes.end();iter++)
655 std::string rep=(*iter)->getErrorReport();
658 report=report+rep+"\n";
663 report=report+"</error>";
667 void DynParaLoop::forwardExecStateToOriginalBody(Node *execNode)
670 Node * origNode = NULL;
671 switch (getIdentityOfNotifyerNode(execNode,id))
675 origNode = _initNode;
685 origNode = _finalizeNode;
692 YASSERT(origNode != NULL)
693 origNode->setState(execNode->getState());
694 origNode->setErrorDetails(execNode->getErrorDetails());
696 ComposedNode* compNode = dynamic_cast<ComposedNode*>(origNode);
697 ComposedNode* compNodeExe = dynamic_cast<ComposedNode*>(execNode);
698 if (compNode && compNodeExe)
700 list<Node *> aChldn = compNodeExe->getAllRecursiveConstituents();
701 list<Node *>::iterator iter=aChldn.begin();
702 for(;iter!=aChldn.end();iter++)
704 Node* node=compNode->getChildByName(compNodeExe->getChildName(*iter));
705 node->setState((*iter)->getState());
706 node->setErrorDetails((*iter)->getErrorDetails());
711 //! Method used to notify the node that a child node has failed
713 * Update the current state and return the change state
715 * \param node : the child node that has failed
716 * \return the state change
718 YACS::Event DynParaLoop::updateStateOnFailedEventFrom(Node *node, const Executor *execInst)
720 DEBTRACE("DynParaLoop::updateStateOnFailedEventFrom " << node->getName());
721 setState(YACS::FAILED);
722 forwardExecStateToOriginalBody(node);
724 switch (getIdentityOfNotifyerNode(node,id))
728 _node->setState(YACS::FAILED);
729 if (_finalizeNode != NULL) _finalizeNode->setState(YACS::FAILED);
734 if (_finalizeNode != NULL) _finalizeNode->setState(YACS::FAILED);
741 //! Clone nodes and make their placement consistent with the placement of the original ones.
743 * For instance, if two original nodes are placed on a component comp1 in a container cont1
744 * and a third one is placed on a component comp2 in the container cont1, the clones of the two
745 * first nodes will be placed on a component comp3 in a container cont2 and the third clone
746 * will be placed on a component comp4 in the container cont2.
748 vector<Node *> DynParaLoop::cloneAndPlaceNodesCoherently(const vector<Node *> & origNodes)
750 DEBTRACE("Begin cloneAndPlaceNodesCoherently")
751 vector<Node *> clones;
752 DeploymentTree treeToDup;
753 vector<list<ElementaryNode *> > origElemNodeList;
754 for (int i=0 ; i<origNodes.size() ; i++)
756 DEBTRACE("Cloning node " << i)
757 if (origNodes[i] == NULL)
759 DEBTRACE("Cloning node " << i << ", NULL" )
760 clones.push_back(NULL);
761 origElemNodeList.push_back(list<ElementaryNode *>());
765 DEBTRACE("Cloning node " << i << "," << origNodes[i]->getName())
766 clones.push_back(origNodes[i]->simpleClone(this, false));
767 list<ElementaryNode *> tasks = origNodes[i]->getRecursiveConstituents();
768 origElemNodeList.push_back(tasks);
769 for (list< ElementaryNode *>::iterator iter=tasks.begin() ; iter!=tasks.end() ; iter++)
770 treeToDup.appendTask(*iter, (*iter)->getDynClonerIfExists(this));
774 // Build the links between clones.
775 // Only the links starting from initNode are possible.
778 std::vector< std::pair<OutPort *, InPort *> > outLinks = _initNode->getSetOfLinksLeavingCurrentScope();
779 std::vector< std::pair<OutPort *, InPort *> >::const_iterator it;
780 for(it=outLinks.begin(); it!=outLinks.end(); it++)
782 OutPort *startPort = it->first;
783 InPort *endPort = it->second;
784 Node* destNode = isInMyDescendance(endPort->getNode());
785 if(destNode == _node)
786 edAddLink(clones[0]->getOutPort(startPort->getName()),
787 clones[1]->getInPort(endPort->getName()));
788 if(destNode == _finalizeNode)
789 edAddLink(clones[0]->getOutPort(startPort->getName()),
790 clones[2]->getInPort(endPort->getName()));
794 DEBTRACE("Placing nodes...")
795 vector<Container *> conts=treeToDup.getAllContainers();
797 //iterate on all containers
798 for(vector<Container *>::iterator iterCt=conts.begin();iterCt!=conts.end();iterCt++)
800 DEBTRACE("Container " << ((*iterCt)?(*iterCt)->getName():"NULL"))
801 vector<ComponentInstance *> comps=treeToDup.getComponentsLinkedToContainer(*iterCt);
802 Container *contCloned=0;
804 contCloned=(*iterCt)->clone();
806 //iterate on all component instances linked to the container
807 for(vector<ComponentInstance *>::iterator iterCp=comps.begin();iterCp!=comps.end();iterCp++)
809 DEBTRACE("Component " << (*iterCp)->getCompoName())
810 vector<Task *> tasks=treeToDup.getTasksLinkedToComponent(*iterCp);
811 ComponentInstance *curCloned=(*iterCp)->clone();
812 DEBTRACE("Assign container " << (*iterCp)->getCompoName())
813 curCloned->setContainer(contCloned);
814 for(vector<Task *>::iterator iterT=tasks.begin();iterT!=tasks.end();iterT++)
816 DEBTRACE("Task " << ((ElementaryNode *)(*iterT))->getName())
818 ElementaryNode * origElemNode = NULL;
819 for (i=0 ; i<origNodes.size() ; i++)
820 if (origNodes[i] != NULL)
822 DEBTRACE("Looking in original node " << i)
823 list<ElementaryNode *>::iterator res=find(origElemNodeList[i].begin(),
824 origElemNodeList[i].end(),
825 (ElementaryNode *)(*iterT));
826 if (res != origElemNodeList[i].end()) {
832 YASSERT(origElemNode != NULL)
833 DEBTRACE("Found task in node " << i)
834 ServiceNode * nodeC = NULL;
835 if (origNodes[i] == origElemNode)
836 nodeC = (ServiceNode *)clones[i];
839 string childName = ((ComposedNode *)origNodes[i])->getChildName(origElemNode);
840 nodeC = (ServiceNode *)clones[i]->getChildByName(childName);
842 DEBTRACE("Assign component: " << (*iterCp)->getCompoName() << "," << nodeC->getName())
843 nodeC->setComponent(curCloned);
845 curCloned->decrRef();
848 // iterate on all tasks linked to the container
849 vector<Task *> tasks=treeToDup.getTasksLinkedToContainer(*iterCt);
850 for(vector<Task *>::iterator iterT=tasks.begin();iterT!=tasks.end();iterT++)
852 DEBTRACE("Task " << ((ElementaryNode *)(*iterT))->getName())
854 ElementaryNode * origElemNode = NULL;
855 for (i=0 ; i<origNodes.size() ; i++)
856 if (origNodes[i] != NULL)
858 DEBTRACE("Looking in original node " << i)
859 list<ElementaryNode *>::iterator res=find(origElemNodeList[i].begin(),
860 origElemNodeList[i].end(),
861 (ElementaryNode *)(*iterT));
862 if (res != origElemNodeList[i].end())
868 YASSERT(origElemNode != NULL)
869 DEBTRACE("Found task in node " << i)
870 InlineFuncNode * nodeC = NULL;
871 if (origNodes[i] == origElemNode)
873 nodeC = (InlineFuncNode *)clones[i];
877 string childName = ((ComposedNode *)origNodes[i])->getChildName(origElemNode);
878 nodeC = (InlineFuncNode *)clones[i]->getChildByName(childName);
880 DEBTRACE("Assign container " << nodeC->getName() << "," << contCloned->getName())
881 nodeC->setContainer(contCloned);
884 // ended with current container
886 contCloned->decrRef();
889 DEBTRACE("End cloneAndPlaceNodesCoherently")
893 void DynParaLoop::accept(Visitor *visitor)
895 visitor->visitDynParaLoop(this);
898 Node * DynParaLoop::getInitNode()
903 Node * DynParaLoop::getExecNode()
908 Node * DynParaLoop::getFinalizeNode()
910 return _finalizeNode;
913 int DynParaLoop::getMaxLevelOfParallelism() const
915 return _nbOfBranches.getIntValue() * _node->getMaxLevelOfParallelism();
918 void DynParaLoop::partitionRegardingDPL(const PartDefinition *pd, std::map<ComposedNode *, YACS::BASES::AutoRefCnt<PartDefinition> >& zeMap)
920 YACS::BASES::AutoRefCnt<PartDefinition> pd2(pd->copy());
923 _node->partitionRegardingDPL(pd,zeMap);
926 void DynParaLoop::shutdown(int level)
931 std::vector<Node *>::iterator iter;
932 for (iter=_execNodes.begin() ; iter!=_execNodes.end() ; iter++)
933 (*iter)->shutdown(level);
934 for (iter=_execInitNodes.begin() ; iter!=_execInitNodes.end() ; iter++)
935 (*iter)->shutdown(level);
936 for (iter=_execFinalizeNodes.begin() ; iter!=_execFinalizeNodes.end() ; iter++)
937 (*iter)->shutdown(level);