Version: 9.15.0
DynParaLoop.cxx
Go to the documentation of this file.
1 // Copyright (C) 2006-2025 CEA, EDF
2 //
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.
7 //
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.
12 //
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
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 
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"
29 
30 #include <list>
31 #include <vector>
32 
33 //#define _DEVDEBUG_
34 #include "YacsTrace.hxx"
35 
36 using namespace std;
37 using namespace YACS::ENGINE;
38 
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
41 
42 DynParaLoop::DynParaLoop(const std::string& name, TypeCode *typeOfDataSplitted, std::unique_ptr<NbBranchesAbstract>&& branchManager)
43  : ComposedNode(name),_node(0),_initNode(0),_finalizeNode(0),_nbOfEltConsumed(0),
44  _nbOfBranches(std::move(branchManager)),
45  _splittedPort(NAME_OF_SPLITTED_SEQ_OUT,this,typeOfDataSplitted),_initializingCounter(0),_unfinishedCounter(0),_failedCounter(0),_weight(), _loopWeight(0)
46 {
48 }
49 
51 {
52  delete _node;
53  delete _initNode;
54  delete _finalizeNode;
55 }
56 
57 DynParaLoop::DynParaLoop(const DynParaLoop& other, ComposedNode *father, bool editionOnly)
58  : ComposedNode(other,father),_nbOfBranches(other._nbOfBranches->copy(this)),
59  _splittedPort(other._splittedPort,this), _node(0), _initNode(0), _finalizeNode(0),
60  _nbOfEltConsumed(0),_initializingCounter(0),_unfinishedCounter(0),_failedCounter(0),_weight(other._weight), _loopWeight(other._loopWeight)
61 {
62  if(other._node)
63  _node=other._node->clone(this,editionOnly);
64  if(other._initNode)
65  _initNode=other._initNode->clone(this,editionOnly);
66  if(other._finalizeNode)
67  _finalizeNode = other._finalizeNode->clone(this,editionOnly);
68  const AnyOutputPort& startOfLinksToReproduce=other._splittedPort;
69  set<InPort *> endsOfLinksToReproduce=startOfLinksToReproduce.edSetInPort();
70  for(set<InPort *>::iterator iter=endsOfLinksToReproduce.begin();iter!=endsOfLinksToReproduce.end();iter++)
72 }
73 
75 {
76  return checkConsistencyAndSetNode(_node, node);
77 }
78 
81 {
82  if (node == NULL || nodeToReplace == node)
83  return 0;
84  if (node->_father)
85  throw Exception(string("Can't set node: node ") + node->getName() + " is not orphan.");
86  if (_node && _node != nodeToReplace && _node->getName() == node->getName())
87  throw Exception(string("Can't set node: node ") + node->getName() +
88  " has the same name than exec node already in " + _name + ".");
89  if (_initNode && _initNode != nodeToReplace && _initNode->getName() == node->getName())
90  throw Exception(string("Can't set node: node ") + node->getName() +
91  " has the same name than init node already in " + _name + ".");
92  if (_finalizeNode && _finalizeNode != nodeToReplace && _finalizeNode->getName() == node->getName())
93  throw Exception(string("Can't set node: node ") + node->getName() +
94  " has the same name than finalize node already in " + _name + ".");
96  ComposedNode::edRemoveChild(nodeToReplace);
97  Node * ret = nodeToReplace;
98  nodeToReplace = node;
99  nodeToReplace->_father = this;
100  // set _modified flag so that edUpdateState can refresh state
101  modified();
102  return ret;
103 }
104 
105 void DynParaLoop::init(bool start)
106 {
107  ComposedNode::init(start);
108  if(!_node)
109  {
110  string what("DynParaLoop::init : no node specified for ForEachLoop with name "); what +=_name;
111  throw Exception(what);
112  }
113  _node->init(start);
114  if (_initNode) _initNode->init(start);
115  if (_finalizeNode) _finalizeNode->init(start);
116  _nbOfBranches->exInit(start);
119  _failedCounter=0;
120 }
121 
123 {
125 }
126 
128 {
130 }
131 
133 
142 {
143  return edAddLink(start,end);
144 }
145 
147 {
149 }
150 
152 {
154 }
155 
162 {
163  if(_node)
164  {
165  for(std::vector<Node *>::const_iterator it=_execNodes.begin();it!=_execNodes.end();it++)
166  if(node==*it)
167  return std::distance(_execNodes.begin(),it);
168  }
169  if(_finalizeNode)
170  {
171  for(std::vector<Node *>::const_iterator it=_execFinalizeNodes.begin();it!=_execFinalizeNodes.end();it++)
172  if(node==*it)
173  return std::distance(_execFinalizeNodes.begin(),it);
174  }
175  if(_initNode)
176  {
177  for(std::vector<Node *>::const_iterator it=_execInitNodes.begin();it!=_execInitNodes.end();it++)
178  if(node==*it)
179  return std::distance(_execInitNodes.begin(),it);
180  }
181  return -1;
182 }
183 
184 std::list<OutputPort *> DynParaLoop::getSetOfOutputPort() const
185 {
186  list<OutputPort *> ret=ComposedNode::getSetOfOutputPort();
187  ret.push_back((OutputPort *)&_splittedPort);
188  return ret;
189 }
190 
191 std::list<OutputPort *> DynParaLoop::getLocalOutputPorts() const
192 {
193  list<OutputPort *> ret=ComposedNode::getLocalOutputPorts();
194  ret.push_back((OutputPort *)&_splittedPort);
195  return ret;
196 }
197 
198 OutPort *DynParaLoop::getOutPort(const std::string& name) const
199 {
201  return (OutPort *)&_splittedPort;
202  return ComposedNode::getOutPort(name);
203 }
204 
205 
206 OutputPort *DynParaLoop::getOutputPort(const std::string& name) const
207 {
209  return (OutputPort *)&_splittedPort;
210  return ComposedNode::getOutputPort(name);
211 }
212 
214 {
215  return false;
216 }
217 
219 {
220  return removeNode(_node);
221 }
222 
225 {
226  if (!nodeToRemove)
227  return NULL;
228  ComposedNode::edRemoveChild(nodeToRemove);
229  Node * ret = nodeToRemove;
230  nodeToRemove = NULL;
231  modified();
232  return ret;
233 }
234 
236 {
237  return removeNode(_initNode);
238 }
239 
241 {
242  return removeNode(_finalizeNode);
243 }
244 
246 {
248  if(node==_node)
249  _node=0;
250  if(node==_initNode)
251  _initNode=0;
252  if(node==_finalizeNode)
253  _finalizeNode=0;
254  modified();
255 }
256 
257 bool DynParaLoop::edAddChild(Node *DISOWNnode)
258 {
259  return edSetNode(DISOWNnode);
260 }
261 
262 std::list<Node *> DynParaLoop::edGetDirectDescendants() const
263 {
264  list<Node *> ret;
265  if(_node)
266  ret.push_back(_node);
267  if(_initNode)
268  ret.push_back(_initNode);
269  if(_finalizeNode)
270  ret.push_back(_finalizeNode);
271  return ret;
272 }
273 
274 std::list<InputPort *> DynParaLoop::getSetOfInputPort() const
275 {
276  list<InputPort *> ret=ComposedNode::getSetOfInputPort();
277  InputPort *port(_nbOfBranches->getPort());
278  if(port)
279  ret.push_back(port);
280  return ret;
281 }
282 
283 InputPort *DynParaLoop::getInputPort(const std::string& name) const
284 {
285  if(_nbOfBranches->isMyName(name))
286  return _nbOfBranches->getPort();
287  return ComposedNode::getInputPort(name);
288 }
289 
290 std::list<InputPort *> DynParaLoop::getLocalInputPorts() const
291 {
292  list<InputPort *> ret=ComposedNode::getLocalInputPorts();
293  InputPort *port(_nbOfBranches->getPort());
294  if(port)
295  ret.push_back(port);
296  return ret;
297 }
298 
300 {
301  if(_execNodes.empty())
302  throw Exception("ForEachLoop::getNumberOfBranches : No branches created dynamically ! - ForEachLoop needs to run or to be runned to call getNumberOfBranches");
303  else
304  return _execNodes.size();
305 }
306 
307 Node *DynParaLoop::getChildByShortName(const std::string& name) const
308 {
309  if (_node && name == _node->getName())
310  return _node;
311  if (_initNode && name == _initNode->getName())
312  return _initNode;
313  if (_finalizeNode && name == _finalizeNode->getName())
314  return _finalizeNode;
315  std::string what("node "); what+= name ; what+=" is not a child of DynParaLoop node "; what += getName();
316  throw Exception(what);
317 }
318 
319 Node *DynParaLoop::getChildByNameExec(const std::string& name, unsigned id) const
320 {
322  throw Exception("ForEachLoop::getChildByNameExec : invalid id - too large compared with dynamically created branches.");
323  if (_node && name == _node->getName())
324  return _execNodes[id];
325  if (_initNode && name == _initNode->getName())
326  return _execInitNodes[id];
327  if (_finalizeNode && name == _finalizeNode->getName())
328  return _execFinalizeNodes[id];
329  std::string what("node "); what+= name ; what+=" is not a child of DynParaLoop node "; what += getName();
330  throw Exception(what);
331 }
332 
334 {
335  vector<Node *>::iterator iter;
336  for(iter=_execNodes.begin() ; iter!=_execNodes.end() ; iter++)
337  delete *iter;
338  _execNodes.clear();
339  for(iter=_execInitNodes.begin() ; iter!=_execInitNodes.end() ; iter++)
340  delete *iter;
341  _execInitNodes.clear();
342  for(iter=_execFinalizeNodes.begin() ; iter!=_execFinalizeNodes.end() ; iter++)
343  delete *iter;
344  _execFinalizeNodes.clear();
345 }
346 
352 {
353  set< InPort * > portsToSetVals=getAllInPortsComingFromOutsideOfCurrentScope();
354 
355  // This tweak is to fix problems with nested dynamic loops where links are not cloned properly
356  list<InPort *> temp = getSetOfInPort();
357  for(list<InPort *>::iterator iter2=temp.begin();iter2!=temp.end();iter2++)
358  {
359  if ((*iter2)->edSetOutPort().size() == 1 && *(*iter2)->edSetOutPort().begin() == NULL)
360  {
361  portsToSetVals.insert(*iter2);
362  }
363  }
364 
365  // local input ports are not candidates for dynamically duplicated inport.
366  list<InputPort *> localPorts = getLocalInputPorts();
367  for(list<InputPort *>::iterator iter = localPorts.begin() ; iter != localPorts.end() ; iter++)
368  portsToSetVals.erase(*iter);
369  for(set< InPort * >::iterator iter=portsToSetVals.begin();iter!=portsToSetVals.end();iter++)
370  {
371  InputPort *curPortCasted=(InputPort *) *iter;//Cast granted by ForEachLoop::buildDelegateOf(InPort)
372  void *val=curPortCasted->get();
373  InputPort *portToSet=getDynInputPortByAbsName(branchNb,getInPortName(*iter),true);
374  if(portToSet)//portToSet==0 in case of portToSet==_splitterNode._dataPortToDispatch of ForEach
375  {
376  portToSet->put((const void *)val);
377  portToSet->edNotifyReferencedBy(nullptr,false);//This is to indicate that somewhere somebody deals with this inputport
378  //even if no direct physical link exists. This exclusively for _execNodes[branchNb]::init on the next turn of loop.
379  //false is put as 2nd parameter to tell to portToSet, do not touch to the data in case of squeezeMemory.
380  }
381  }
382 }
383 
384 void DynParaLoop::putValueOnBranch(Any *val, unsigned branchId, bool first)
385 {
386  bool isDispatched = false;
387  set<InPort *> inPrtLkdWthSplttdPrt=_splittedPort.edSetInPort();
388  for(set<InPort *>::iterator iter=inPrtLkdWthSplttdPrt.begin();iter!=inPrtLkdWthSplttdPrt.end();iter++)
389  {
390  std::string portNameOnCurPrt=getPortName(*iter);
391  InputPort *portOnGivenBranch=getDynInputPortByAbsName(branchId,portNameOnCurPrt,first);//Cast granted because impossible to have cross protocol with _splittedPort
392  //see OptimizerLoop::buildDelegateOf
393  if(portOnGivenBranch)
394  {
395  if(first)
396  portOnGivenBranch->edNotifyReferencedBy(0);
397  InputPort *traducer=getRuntime()->adapt(portOnGivenBranch,
399  traducer->put((const void *)val);
400  isDispatched = true;
401  if(traducer!=portOnGivenBranch)
402  delete traducer;
403  }
404  }
405  if ( isDispatched )
406  {
407  Any *tmp=val->clone();
408  _splittedPort.setValue(tmp);
409  tmp->decrRef();
410  }
411 }
412 
414 {
415  vector<Node *>::iterator iter;
416  id=0;
417  for (iter=_execNodes.begin() ; iter!=_execNodes.end() ; iter++,id++)
418  if (*iter==node)
419  return WORK_NODE;
420  id=0;
421  for (iter=_execInitNodes.begin() ; iter!=_execInitNodes.end() ; iter++,id++)
422  if (*iter==node)
423  return INIT_NODE;
424  id=0;
425  for (iter=_execFinalizeNodes.begin() ; iter!=_execFinalizeNodes.end() ; iter++,id++)
426  if (*iter==node)
427  return FINALIZE_NODE;
428  throw Exception("DynParaLoop::getIdentityOfNotifyerNode: unrecognized node !");
429 }
430 
431 void DynParaLoop::setWeight(double loopWeight)
432 {
433  if(loopWeight<=0.)
434  throw Exception("DynParaLoop::setWeight : invalid input value !");
435  _loopWeight=loopWeight;
436 }
437 
439 {
440  if (_loopWeight>0.)
441  _weight.setLoopWeight(_loopWeight, _node->getMaxLevelOfParallelism()); // not done in setWeight because _node can be null at that time
442  return &_weight;
443 }
444 
445 bool DynParaLoop::isMultiplicitySpecified(unsigned& value) const
446 {
447  return _nbOfBranches->isMultiplicitySpecified(value);
448 }
449 
450 void DynParaLoop::forceMultiplicity(unsigned value)
451 {
452  _nbOfBranches->forceMultiplicity(value);
453 }
454 
455 void DynParaLoop::buildDelegateOf(InPort * & port, OutPort *initialStart, const std::list<ComposedNode *>& pointsOfView)
456 {
457  string typeOfPortInstance=port->getNameOfTypeOfCurrentInstance();
458  if(typeOfPortInstance!=InputPort::NAME)
459  throw Exception("DynParaLoop::buildDelegateOf : A link with datastream end inside DynParaLoop is not possible");
460 }
461 
462 void DynParaLoop::buildDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView)
463 {
464  std::string linkName("(");
465  linkName += port.first->getName()+" to "+finalTarget->getName()+")";
466  if(_initNode)
467  if(isInMyDescendance(port.first->getNode())==_initNode)
468  throw Exception(std::string("Illegal link within a parallel loop: \
469 a link starting from the init node can't leave the scope of the loop.")
470  + linkName);
471 
472  if(_finalizeNode)
473  if(isInMyDescendance(port.first->getNode())==_finalizeNode)
474  throw Exception(std::string("Illegal link within a parallel loop: \
475 an output port of the finalize node can't be linked.")
476  + linkName);
477 
478  if(port.first==&_splittedPort)
479  throw Exception(std::string("Illegal link within a parallel loop: \
480 the 'evalSamples' port must be linked within the scope of the loop.")
481  + linkName);
482 }
483 
484 void DynParaLoop::checkCFLinks(const std::list<OutPort *>& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const
485 {
486  const char what[]="DynParaLoop::checkCFLinks : internal error.";
487  //First dealing checkCFLinks forwarding...
488  if(isInMyDescendance(end->getNode())==0)//no chance that _splittedPort is in starts due to buildDelegate.
489  solveObviousOrDelegateCFLinks(starts,end,alreadyFed,direction,info);
490  else
491  {//no forwarding here.
492  if(starts.size()!=1)
493  throw Exception(what);
494  //ASSERT(direction) : see DynParaLoop::checkControlDependancy only 'fw' filled.
495  if(alreadyFed==FREE_ST)
496  alreadyFed=FED_ST;
497  else if(alreadyFed==FED_ST)
498  {//Shame ! splittedPort fills a port already fed...
499  info.pushInfoLink(*(starts.begin()),end,I_USELESS);
500  }
501  }
502 }
503 
513 void DynParaLoop::checkControlDependancy(OutPort *start, InPort *end, bool cross,
514  std::map < ComposedNode *, std::list < OutPort * >, SortHierarc >& fw,
515  std::vector<OutPort *>& fwCross,
516  std::map< ComposedNode *, std::list < OutPort *>, SortHierarc >& bw,
517  LinkInfo& info) const
518 {
519  fw[(ComposedNode *)this].push_back(start);
520 }
521 
522 void DynParaLoop::checkLinkPossibility(OutPort *start, const std::list<ComposedNode *>& pointsOfViewStart,
523  InPort *end, const std::list<ComposedNode *>& pointsOfViewEnd)
524 {
525  ComposedNode::checkLinkPossibility(start, pointsOfViewStart, end, pointsOfViewEnd);
526  Node * startNode = isInMyDescendance(start->getNode());
527  Node * endNode = isInMyDescendance(end->getNode());
528  std::string linkName("(");
529  linkName += start->getName()+" to "+end->getName()+")";
530 
531  if(start == &_splittedPort && endNode != _node)
532  throw Exception(std::string("Illegal link within a parallel loop: \
533 the 'evalSamples' port can only be connected to the working node of the loop.")
534  + linkName);
535 
536  if(_finalizeNode && _finalizeNode == startNode)
537  throw Exception(std::string("Illegal link within a parallel loop: \
538 the finalize node can't be the origin of a link.")
539  + linkName);
540 
541  if(_initNode && _node == startNode && _initNode == endNode)
542  throw Exception(std::string("Illegal link within a parallel loop: \
543 can't make a link from the working node to the init node.")
544  + linkName);
545 
546  if(_finalizeNode && _node == startNode && _finalizeNode == endNode)
547  throw Exception(std::string("Illegal link within a parallel loop: \
548 can't make a link from the working node to the finalize node.")
549  + linkName);
550 }
551 
559 InputPort *DynParaLoop::getDynInputPortByAbsName(int branchNb, const std::string& name, bool initNodeAdmitted)
560 {
561  string portName, nodeName;
562  splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,true);
563  Node *staticChild = getChildByName(nodeName);
564  Node *desc=isInMyDescendance(staticChild);
565  if(desc==_node)
566  {
567  splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,false);
568  return _execNodes[branchNb]->getInputPort(portName);
569  }
570  else if(desc==_initNode)
571  if(initNodeAdmitted)
572  {
573  splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,false);
574  return _execInitNodes[branchNb]->getInputPort(portName);
575  }
576  return 0;
577 }
578 
580 {
581  DEBTRACE("DynParaLoop::checkBasicConsistency");
583  if(!_node)
584  throw Exception("For a dynamic loop, internal node is mandatory");
585 }
586 
588 {
589  DEBTRACE("DynParaLoop::getErrorReport: " << getName() << " " << _state);
590  YACS::StatesForNode effectiveState=getEffectiveState();
591 
592  if(effectiveState != YACS::INVALID && effectiveState != YACS::ERROR && effectiveState != YACS::FAILED)
593  return "";
594 
595  std::string report="<error node= " + getName();
596  switch(effectiveState)
597  {
598  case YACS::INVALID:
599  report=report+" state= INVALID";
600  break;
601  case YACS::ERROR:
602  report=report+" state= ERROR";
603  break;
604  case YACS::FAILED:
605  report=report+" state= FAILED";
606  break;
607  default:
608  break;
609  }
610  report=report + ">\n" ;
611  if(_errorDetails != "")
612  report=report+_errorDetails+"\n";
613 
614  if(_execNodes.empty())
615  {
616  // edition node
617  list<Node *> constituents=edGetDirectDescendants();
618  for(list<Node *>::iterator iter=constituents.begin(); iter!=constituents.end(); iter++)
619  {
620  std::string rep=(*iter)->getErrorReport();
621  if(rep != "")
622  {
623  report=report+rep+"\n";
624  }
625  }
626  }
627  else
628  {
629  // execution nodes
630  for(vector<Node *>::iterator iter=_execInitNodes.begin();iter!=_execInitNodes.end();iter++)
631  {
632  std::string rep=(*iter)->getErrorReport();
633  if(rep != "")
634  {
635  report=report+rep+"\n";
636  }
637  }
638  for(vector<Node *>::iterator iter=_execNodes.begin();iter!=_execNodes.end();iter++)
639  {
640  if(*iter)
641  {
642  std::string rep=(*iter)->getErrorReport();
643  if(rep != "")
644  {
645  report=report+rep+"\n";
646  }
647  }
648  }
649  for(vector<Node *>::iterator iter=_execFinalizeNodes.begin();iter!=_execFinalizeNodes.end();iter++)
650  {
651  std::string rep=(*iter)->getErrorReport();
652  if(rep != "")
653  {
654  report=report+rep+"\n";
655  }
656  }
657  }
658 
659  report=report+"</error>";
660  return report;
661 }
662 
664 {
665  unsigned int id;
666  Node * origNode = NULL;
667  switch (getIdentityOfNotifyerNode(execNode,id))
668  {
669  case INIT_NODE:
670  {
671  origNode = _initNode;
672  break;
673  }
674  case WORK_NODE:
675  {
676  origNode = _node;
677  break;
678  }
679  case FINALIZE_NODE:
680  {
681  origNode = _finalizeNode;
682  break;
683  }
684  default:
685  YASSERT(false)
686  }
687 
688  YASSERT(origNode != NULL)
689  origNode->setState(execNode->getState());
690  origNode->setErrorDetails(execNode->getErrorDetails());
691 
692  ComposedNode* compNode = dynamic_cast<ComposedNode*>(origNode);
693  ComposedNode* compNodeExe = dynamic_cast<ComposedNode*>(execNode);
694  if (compNode && compNodeExe)
695  {
696  list<Node *> aChldn = compNodeExe->getAllRecursiveConstituents();
697  list<Node *>::iterator iter=aChldn.begin();
698  for(;iter!=aChldn.end();iter++)
699  {
700  Node* node=compNode->getChildByName(compNodeExe->getChildName(*iter));
701  node->setState((*iter)->getState());
702  node->setErrorDetails((*iter)->getErrorDetails());
703  }
704  }
705 }
706 
708 
715 {
716  DEBTRACE("DynParaLoop::updateStateOnFailedEventFrom " << node->getName());
719  unsigned int id;
720  switch (getIdentityOfNotifyerNode(node,id))
721  {
722  case INIT_NODE:
723  {
726  break;
727  }
728  case WORK_NODE:
729  {
731  break;
732  }
733  }
734  return YACS::ABORT;
735 }
736 
738 
744 vector<Node *> DynParaLoop::cloneAndPlaceNodesCoherently(const vector<Node *> & origNodes)
745 {
746  DEBTRACE("Begin cloneAndPlaceNodesCoherently")
747  vector<Node *> clones;
748  DeploymentTree treeToDup;
749  vector<list<ElementaryNode *> > origElemNodeList;
750  for (int i=0 ; i<origNodes.size() ; i++)
751  {
752  DEBTRACE("Cloning node " << i)
753  if (origNodes[i] == NULL)
754  {
755  DEBTRACE("Cloning node " << i << ", NULL" )
756  clones.push_back(NULL);
757  origElemNodeList.push_back(list<ElementaryNode *>());
758  }
759  else
760  {
761  DEBTRACE("Cloning node " << i << "," << origNodes[i]->getName())
762  clones.push_back(origNodes[i]->simpleClone(this, false));
763  list<ElementaryNode *> tasks = origNodes[i]->getRecursiveConstituents();
764  origElemNodeList.push_back(tasks);
765  for (list< ElementaryNode *>::iterator iter=tasks.begin() ; iter!=tasks.end() ; iter++)
766  treeToDup.appendTask(*iter, (*iter)->getDynClonerIfExists(this));
767  }
768  }
769 
770  // Build the links between clones.
771  // Only the links starting from initNode are possible.
772  if(_initNode)
773  {
774  std::vector< std::pair<OutPort *, InPort *> > outLinks = _initNode->getSetOfLinksLeavingCurrentScope();
775  std::vector< std::pair<OutPort *, InPort *> >::const_iterator it;
776  for(it=outLinks.begin(); it!=outLinks.end(); it++)
777  {
778  OutPort *startPort = it->first;
779  InPort *endPort = it->second;
780  Node* destNode = isInMyDescendance(endPort->getNode());
781  if(destNode == _node)
782  edAddLink(clones[0]->getOutPort(startPort->getName()),
783  clones[1]->getInPort(endPort->getName()));
784  if(destNode == _finalizeNode)
785  edAddLink(clones[0]->getOutPort(startPort->getName()),
786  clones[2]->getInPort(endPort->getName()));
787  }
788  }
789 
790  DEBTRACE("Placing nodes...")
791  vector<Container *> conts=treeToDup.getAllContainers();
792 
793  //iterate on all containers
794  for(vector<Container *>::iterator iterCt=conts.begin();iterCt!=conts.end();iterCt++)
795  {
796  DEBTRACE("Container " << ((*iterCt)?(*iterCt)->getName():"NULL"))
797  vector<ComponentInstance *> comps=treeToDup.getComponentsLinkedToContainer(*iterCt);
798  Container *contCloned=0;
799  if((*iterCt))
800  contCloned=(*iterCt)->clone();
801 
802  //iterate on all component instances linked to the container
803  for(vector<ComponentInstance *>::iterator iterCp=comps.begin();iterCp!=comps.end();iterCp++)
804  {
805  DEBTRACE("Component " << (*iterCp)->getCompoName())
806  vector<Task *> tasks=treeToDup.getTasksLinkedToComponent(*iterCp);
807  ComponentInstance *curCloned=(*iterCp)->clone();
808  DEBTRACE("Assign container " << (*iterCp)->getCompoName())
809  curCloned->setContainer(contCloned);
810  for(vector<Task *>::iterator iterT=tasks.begin();iterT!=tasks.end();iterT++)
811  {
812  DEBTRACE("Task " << ((ElementaryNode *)(*iterT))->getName())
813  int i = 0;
814  ElementaryNode * origElemNode = NULL;
815  for (i=0 ; i<origNodes.size() ; i++)
816  if (origNodes[i] != NULL)
817  {
818  DEBTRACE("Looking in original node " << i)
819  list<ElementaryNode *>::iterator res=find(origElemNodeList[i].begin(),
820  origElemNodeList[i].end(),
821  (ElementaryNode *)(*iterT));
822  if (res != origElemNodeList[i].end()) {
823  origElemNode = *res;
824  break;
825  }
826  }
827 
828  YASSERT(origElemNode != NULL)
829  DEBTRACE("Found task in node " << i)
830  ServiceNode * nodeC = NULL;
831  if (origNodes[i] == origElemNode)
832  nodeC = (ServiceNode *)clones[i];
833  else
834  {
835  string childName = ((ComposedNode *)origNodes[i])->getChildName(origElemNode);
836  nodeC = (ServiceNode *)clones[i]->getChildByName(childName);
837  }
838  DEBTRACE("Assign component: " << (*iterCp)->getCompoName() << "," << nodeC->getName())
839  nodeC->setComponent(curCloned);
840  }
841  curCloned->decrRef();
842  }
843 
844  // iterate on all tasks linked to the container
845  vector<Task *> tasks=treeToDup.getTasksLinkedToContainer(*iterCt);
846  for(vector<Task *>::iterator iterT=tasks.begin();iterT!=tasks.end();iterT++)
847  {
848  DEBTRACE("Task " << ((ElementaryNode *)(*iterT))->getName())
849  int i = 0;
850  ElementaryNode * origElemNode = NULL;
851  for (i=0 ; i<origNodes.size() ; i++)
852  if (origNodes[i] != NULL)
853  {
854  DEBTRACE("Looking in original node " << i)
855  list<ElementaryNode *>::iterator res=find(origElemNodeList[i].begin(),
856  origElemNodeList[i].end(),
857  (ElementaryNode *)(*iterT));
858  if (res != origElemNodeList[i].end())
859  {
860  origElemNode = *res;
861  break;
862  }
863  }
864  YASSERT(origElemNode != NULL)
865  DEBTRACE("Found task in node " << i)
866  InlineFuncNode * nodeC = NULL;
867  if (origNodes[i] == origElemNode)
868  {
869  nodeC = (InlineFuncNode *)clones[i];
870  }
871  else
872  {
873  string childName = ((ComposedNode *)origNodes[i])->getChildName(origElemNode);
874  nodeC = (InlineFuncNode *)clones[i]->getChildByName(childName);
875  }
876  DEBTRACE("Assign container " << nodeC->getName() << "," << contCloned->getName())
877  nodeC->setContainer(contCloned);
878  }
879 
880  // ended with current container
881  if(contCloned)
882  contCloned->decrRef();
883  }
884 
885  DEBTRACE("End cloneAndPlaceNodesCoherently")
886  return clones;
887 }
888 
890 {
891  visitor->visitDynParaLoop(this);
892 }
893 
895 {
896  return _initNode;
897 }
898 
900 {
901  return _node;
902 }
903 
905 {
906  return _finalizeNode;
907 }
908 
910 {
911  return _nbOfBranches->getIntValue() * _node->getMaxLevelOfParallelism();
912 }
913 
915 {
917  zeMap[this]=pd2;
918  if(_node)
919  _node->partitionRegardingDPL(pd,zeMap);
920 }
921 
922 void DynParaLoop::shutdown(int level)
923 {
924  if(level==0)return;
925  if(!_node) return;
926 
927  std::vector<Node *>::iterator iter;
928  for (iter=_execNodes.begin() ; iter!=_execNodes.end() ; iter++)
929  (*iter)->shutdown(level);
930  for (iter=_execInitNodes.begin() ; iter!=_execInitNodes.end() ; iter++)
931  (*iter)->shutdown(level);
932  for (iter=_execFinalizeNodes.begin() ; iter!=_execFinalizeNodes.end() ; iter++)
933  (*iter)->shutdown(level);
934 }
#define YASSERT(val)
YASSERT macro is always defined, used like assert, but throw a YACS::Exception instead of abort.
Definition: YacsTrace.hxx:59
#define DEBTRACE(msg)
Definition: YacsTrace.hxx:31
virtual void setValue(Any *data)
store the current dispatched value
: Interface for management of storage of data formated dynamically in its TypeCode....
Definition: Any.hxx:79
virtual Any * clone() const =0
void setLoopWeight(double loopWeight, int nbCoresByIteration)
Base class for all component instances.
virtual bool setContainer(Container *cont)
virtual ComponentInstance * clone() const =0
Base class for all composed nodes.
std::string getChildName(const Node *node) const
Node * getChildByName(const std::string &name) const
static const unsigned char FREE_ST
std::list< InputPort * > getSetOfInputPort() const
std::list< OutputPort * > getLocalOutputPorts() const
redefined on derived class of ComposedNode. by default a ComposedNode has no port by itself
OutPort * getOutPort(const std::string &name) const
void checkNoCrossHierachyWith(Node *node) const
std::string getName() const
void solveObviousOrDelegateCFLinks(const std::list< OutPort * > &starts, InputPort *end, unsigned char &alreadyFed, bool direction, LinkInfo &info) const
OutputPort * getOutputPort(const std::string &name) const
Get an output port given its name.
InputPort * getInputPort(const std::string &name) const
Get an input port given its name.
virtual std::list< Node * > getAllRecursiveConstituents()
Idem getAllRecursiveNodes, but this node is NOT included.
std::list< OutputPort * > getSetOfOutputPort() const
std::list< InputPort * > getLocalInputPorts() const
redefined on derived class of ComposedNode. by default a ComposedNode has no port by itself
virtual void edRemoveChild(Node *node)
Remove a child node.
virtual void checkBasicConsistency() const
std::string getPortName(const PORT *port) const
static bool splitNamesBySep(const std::string &globalName, const char separator[], std::string &firstPart, std::string &lastPart, bool priority)
Splits name globalName in 2 parts using separator.
static const unsigned char FED_ST
std::string getInPortName(const InPort *) const
Get the input port name.
std::set< InPort * > getAllInPortsComingFromOutsideOfCurrentScope() const
List all input ports that are linked to out of scope ports.
void init(bool start=true)
bool edAddLink(OutPort *start, InPort *end)
Add a dataflow link between two data ports.
Node * isInMyDescendance(Node *nodeToTest) const
Returns the parent of a node that is the direct child of this node.
virtual void checkLinkPossibility(OutPort *start, const std::list< ComposedNode * > &pointsOfViewStart, InPort *end, const std::list< ComposedNode * > &pointsOfViewEnd)
virtual Container * clone() const =0
WARNING ! clone behaviour MUST be in coherence with what is returned by isAttachedOnCloning() method
virtual std::string getName() const
Definition: Container.hxx:81
std::string getNameOfTypeOfCurrentInstance() const
Definition: DataPort.cxx:56
TypeCode * edGetType() const
Definition: DataPort.hxx:53
std::string getName() const
Definition: DataPort.hxx:55
std::vector< Task * > getTasksLinkedToComponent(ComponentInstance *comp) const
std::vector< ComponentInstance * > getComponentsLinkedToContainer(Container *cont) const
std::vector< Task * > getTasksLinkedToContainer(Container *cont) const
unsigned char appendTask(Task *task, Scheduler *cloner)
std::vector< Container * > getAllContainers() const
Base class for dynamically (fully or semifully) built graphs.
Definition: DynParaLoop.hxx:41
Node * getChildByShortName(const std::string &name) const
Node * getChildByNameExec(const std::string &name, unsigned id) const
InputPort * getInputPort(const std::string &name) const
Get an input port given its name.
std::list< OutputPort * > getLocalOutputPorts() const
redefined on derived class of ComposedNode. by default a ComposedNode has no port by itself
int getNumberOfInputPorts() const
virtual bool edAddChild(Node *DISOWNnode)
virtual void checkLinkPossibility(OutPort *start, const std::list< ComposedNode * > &pointsOfViewStart, InPort *end, const std::list< ComposedNode * > &pointsOfViewEnd)
Node * removeNode(Node *&nodeToRemove)
This method is used to factorize methods edRemoveNode, edRemoveInitNode and edRemoveFinalizeNode.
std::unique_ptr< NbBranchesAbstract > _nbOfBranches
Definition: DynParaLoop.hxx:56
static const char OLD_NAME_OF_SPLITTED_SEQ_OUT[]
Definition: DynParaLoop.hxx:68
bool isMultiplicitySpecified(unsigned &value) const
virtual bool edAddDFLink(OutPort *start, InPort *end)
Connect an OutPort to an InPort and add control link if necessary.
std::list< OutputPort * > getSetOfOutputPort() const
std::vector< Node * > _execNodes
Definition: DynParaLoop.hxx:58
static const char NAME_OF_SPLITTED_SEQ_OUT[]
Definition: DynParaLoop.hxx:67
std::vector< Node * > cloneAndPlaceNodesCoherently(const std::vector< Node * > &origNodes)
Clone nodes and make their placement consistent with the placement of the original ones.
void setWeight(double loopWeight)
void buildDelegateOf(InPort *&port, OutPort *initialStart, const std::list< ComposedNode * > &pointsOfView)
OutputPort * getOutputPort(const std::string &name) const
Get an output port given its name.
unsigned getNumberOfBranchesCreatedDyn() const
OutPort * getOutPort(const std::string &name) const
bool isPlacementPredictableB4Run() const
For the moment false is returned : impovement about it coming soon.
void checkControlDependancy(OutPort *start, InPort *end, bool cross, std::map< ComposedNode *, std::list< OutPort * >, SortHierarc > &fw, std::vector< OutPort * > &fwCross, std::map< ComposedNode *, std::list< OutPort * >, SortHierarc > &bw, LinkInfo &info) const
std::list< Node * > edGetDirectDescendants() const
virtual std::string getErrorReport()
returns a string that contains an error report if the node is in error
virtual YACS::Event updateStateOnFailedEventFrom(Node *node, const Executor *execInst)
Method used to notify the node that a child node has failed.
int getBranchIDOfNode(Node *node) const
std::list< InputPort * > getLocalInputPorts() const
redefined on derived class of ComposedNode. by default a ComposedNode has no port by itself
void init(bool start=true)
void edRemoveChild(Node *node)
Remove a child node.
Node * edSetFinalizeNode(Node *DISOWNnode)
ComplexWeight * getWeight()
std::vector< Node * > _execFinalizeNodes
Definition: DynParaLoop.hxx:60
virtual void shutdown(int level)
Stop all pending activities of the composed node.
Node * edSetNode(Node *DISOWNnode)
Definition: DynParaLoop.cxx:74
int getNumberOfOutputPorts() const
void prepareInputsFromOutOfScope(int branchNb)
int getMaxLevelOfParallelism() const
virtual void cleanDynGraph()
void checkCFLinks(const std::list< OutPort * > &starts, InputPort *end, unsigned char &alreadyFed, bool direction, LinkInfo &info) const
check control flow links
Node * checkConsistencyAndSetNode(Node *&nodeToReplace, Node *DISOWNnode)
This method is used to factorize methods edSetNode, edSetInitNode and edSetFinalizeNode.
Definition: DynParaLoop.cxx:80
virtual void forwardExecStateToOriginalBody(Node *execNode)
Node * edSetInitNode(Node *DISOWNnode)
void putValueOnBranch(Any *val, unsigned branchId, bool first)
AnyOutputPort _splittedPort
Definition: DynParaLoop.hxx:57
std::vector< Node * > _execInitNodes
Definition: DynParaLoop.hxx:59
void accept(Visitor *visitor)
void forceMultiplicity(unsigned value)
std::list< InputPort * > getSetOfInputPort() const
InputPort * getDynInputPortByAbsName(int branchNb, const std::string &name, bool initNodeAdmitted)
void partitionRegardingDPL(const PartDefinition *pd, std::map< ComposedNode *, YACS::BASES::AutoRefCnt< PartDefinition > > &zeMap)
TypeOfNode getIdentityOfNotifyerNode(const Node *node, unsigned &id)
virtual void checkBasicConsistency() const
Base class for all calculation nodes.
Threaded Executor.
Definition: Executor.hxx:63
virtual void edNotifyReferencedBy(OutPort *fromPort, bool isLoopProof=true)
Definition: InPort.cxx:93
Class for calculation node (function) inlined (and executed) in the schema.
Definition: InlineNode.hxx:93
virtual void setContainer(Container *container)
Definition: InlineNode.cxx:105
Base class for Input Ports.
Definition: InputPort.hxx:44
virtual void put(const void *data)=0
static const char NAME[]
Definition: InputPort.hxx:48
virtual void * get() const =0
Class that deal with list of semantics links for high level analysis.
Definition: LinkInfo.hxx:83
void pushInfoLink(OutPort *semStart, InPort *end, InfoReason reason)
Definition: LinkInfo.cxx:71
Base class for all nodes.
Definition: Node.hxx:70
std::string _name
Definition: Node.hxx:89
virtual Node * simpleClone(ComposedNode *father, bool editionOnly=true) const =0
virtual int getMaxLevelOfParallelism() const =0
virtual void setErrorDetails(const std::string &error)
Definition: Node.hxx:191
ComposedNode * _father
Definition: Node.hxx:90
virtual void modified()
Sets Node in modified state and its father if it exists.
Definition: Node.cxx:805
Node * clone(ComposedNode *father, bool editionOnly=true) const
This method MUST NEVER BE VIRTUAL
Definition: Node.cxx:131
virtual void init(bool start=true)
Definition: Node.cxx:102
friend class DynParaLoop
Definition: Node.hxx:77
std::list< InPort * > getSetOfInPort() const
Definition: Node.cxx:289
void setState(YACS::StatesForNode theState)
Sets the given state for node.
Definition: Node.cxx:652
virtual std::string getErrorDetails() const
Definition: Node.hxx:190
virtual YACS::StatesForNode getState() const
Definition: Node.hxx:118
static const char SEP_CHAR_IN_PORT[]
Definition: Node.hxx:94
InPort * getInPort(const std::string &name) const
Definition: Node.cxx:239
virtual std::vector< std::pair< OutPort *, InPort * > > getSetOfLinksLeavingCurrentScope() const =0
const std::string & getName() const
Definition: Node.hxx:125
std::string _errorDetails
Definition: Node.hxx:93
virtual YACS::StatesForNode getEffectiveState() const
Return the node state in the context of its father.
Definition: Node.cxx:538
YACS::StatesForNode _state
Definition: Node.hxx:91
virtual void partitionRegardingDPL(const PartDefinition *pd, std::map< ComposedNode *, YACS::BASES::AutoRefCnt< PartDefinition > > &zeMap)=0
std::set< InPort * > edSetInPort() const
Definition: OutputPort.cxx:239
virtual void exInit()
Definition: OutputPort.cxx:62
virtual PartDefinition * copy() const =0
Node * getNode() const
Definition: Port.hxx:46
static const char RUNTIME_ENGINE_INTERACTION_IMPL_NAME[]
Definition: Runtime.hxx:135
virtual InputPort * adapt(InputPort *source, const std::string &impl, TypeCode *type, bool init=false)=0
Class for calculation node associated with a component service.
Definition: ServiceNode.hxx:35
virtual void setComponent(ComponentInstance *compo)
Associate an existing component instance to this service node AND check the consistency regarding the...
Base class for all type objects.
Definition: TypeCode.hxx:68
virtual void visitDynParaLoop(DynParaLoop *node)=0
YACSLIBENGINE_EXPORT Runtime * getRuntime()
Definition: Runtime.cxx:61
Event
Definition: define.hxx:56
@ ABORT
Definition: define.hxx:60
StatesForNode
Definition: define.hxx:34
@ INVALID
Definition: define.hxx:36
@ FAILED
Definition: define.hxx:51
@ ERROR
Definition: define.hxx:52
def distance(node, new_node)
Definition: graph.py:275