1 // Copyright (C) 2006-2008 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.
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
19 #include "ElementaryNode.hxx"
20 #include "Runtime.hxx"
21 #include "InputPort.hxx"
22 #include "OutputPort.hxx"
23 #include "ComposedNode.hxx"
24 #include "InputDataStreamPort.hxx"
25 #include "OutputDataStreamPort.hxx"
26 #include "Visitor.hxx"
30 #include "YacsTrace.hxx"
32 using namespace YACS::ENGINE;
35 ElementaryNode::ElementaryNode(const std::string& name):Node(name)
39 ElementaryNode::ElementaryNode(const ElementaryNode& other, ComposedNode *father):Node(other,father)
41 for(list<InputPort *>::const_iterator iter1=other._setOfInputPort.begin();iter1!=other._setOfInputPort.end();iter1++)
42 _setOfInputPort.push_back((InputPort *)(*iter1)->clone(this));
43 for(list<OutputPort *>::const_iterator iter2=other._setOfOutputPort.begin();iter2!=other._setOfOutputPort.end();iter2++)
44 _setOfOutputPort.push_back((OutputPort *)(*iter2)->clone(this));
45 for(list<InputDataStreamPort *>::const_iterator iter3=other._setOfInputDataStreamPort.begin();iter3!=other._setOfInputDataStreamPort.end();iter3++)
46 _setOfInputDataStreamPort.push_back((InputDataStreamPort *)(*iter3)->clone(this));
47 for(list<OutputDataStreamPort *>::const_iterator iter4=other._setOfOutputDataStreamPort.begin();iter4!=other._setOfOutputDataStreamPort.end();iter4++)
48 _setOfOutputDataStreamPort.push_back((OutputDataStreamPort *)(*iter4)->clone(this));
51 void ElementaryNode::performDuplicationOfPlacement(const Node& other)
55 ElementaryNode::~ElementaryNode()
57 for(list<InputPort *>::iterator iter1=_setOfInputPort.begin();iter1!=_setOfInputPort.end();iter1++)
59 for(list<OutputPort *>::iterator iter2=_setOfOutputPort.begin();iter2!=_setOfOutputPort.end();iter2++)
61 for(list<InputDataStreamPort *>::iterator iter3=_setOfInputDataStreamPort.begin();iter3!=_setOfInputDataStreamPort.end();iter3++)
63 for(list<OutputDataStreamPort *>::iterator iter4=_setOfOutputDataStreamPort.begin();iter4!=_setOfOutputDataStreamPort.end();iter4++)
67 void ElementaryNode::init(bool start)
69 for(list<OutputPort *>::iterator iter=_setOfOutputPort.begin();iter!=_setOfOutputPort.end();iter++)
71 for(list<InputPort *>::iterator iter2=_setOfInputPort.begin();iter2!=_setOfInputPort.end();iter2++)
72 (*iter2)->exInit(start);
74 if(_state == YACS::DISABLED)
76 exDisabledState(); // to refresh propagation of DISABLED state
79 if(start) //complete initialization
80 setState(YACS::READY);
81 else //partial initialization (inside a loop)
82 setState(YACS::LOADED);
85 bool ElementaryNode::isDeployable() const
90 ComponentInstance *ElementaryNode::getComponent()
95 YACS::StatesForNode ElementaryNode::getState() const
97 return Node::getState();
100 void ElementaryNode::exUpdateState()
102 DEBTRACE("ElementaryNode::exUpdateState: " << getName() << " " << _state );
103 if(_state==YACS::DISABLED)return;
104 if(_inGate.exIsReady())
105 if(areAllInputPortsValid())
107 if(_state == YACS::READY)
109 else if(_state == YACS::LOADED)
110 setState(YACS::TOACTIVATE);
114 string what("ElementaryNode::exUpdateState : Invalid graph given : Node with name \"");
115 what+=_name; what+="\" ready to run whereas some inputports are not set correctly\nCheck coherence DF/CF";
116 setState(YACS::INTERNALERR);
118 throw Exception(what);
122 int ElementaryNode::getNumberOfInputPorts() const
124 return _setOfInputPort.size();
127 int ElementaryNode::getNumberOfOutputPorts() const
129 return _setOfOutputPort.size();
132 InputPort *ElementaryNode::getInputPort(const std::string& name) const throw(Exception)
134 return getPort<InputPort>(name,_setOfInputPort);
137 OutputPort *ElementaryNode::getOutputPort(const std::string& name) const throw(Exception)
139 return getPort<OutputPort>(name,_setOfOutputPort);
142 std::set<OutPort *> ElementaryNode::getAllOutPortsLeavingCurrentScope() const
145 list<OutPort *> temp=getSetOfOutPort();
146 for(list<OutPort *>::iterator iter2=temp.begin();iter2!=temp.end();iter2++)
148 set<InPort *> temp2=(*iter2)->edSetInPort();
155 std::set<InPort *> ElementaryNode::getAllInPortsComingFromOutsideOfCurrentScope() const
158 list<InPort *> temp=getSetOfInPort();
159 for(list<InPort *>::iterator iter2=temp.begin();iter2!=temp.end();iter2++)
161 set<OutPort *> temp2=(*iter2)->edSetOutPort();
168 std::vector< std::pair<OutPort *, InPort *> > ElementaryNode::getSetOfLinksLeavingCurrentScope() const
170 vector< pair<OutPort *, InPort *> > ret;
171 std::set<OutPort *> ports=getAllOutPortsLeavingCurrentScope();
172 for(set<OutPort *>::iterator iter2=ports.begin();iter2!=ports.end();iter2++)
174 set<InPort *> temp2=(*iter2)->edSetInPort();
175 for(set<InPort *>::iterator iter3=temp2.begin();iter3!=temp2.end();iter3++)
176 ret.push_back(pair<OutPort *, InPort *>(*iter2,*iter3));
181 std::vector< std::pair<InPort *, OutPort *> > ElementaryNode::getSetOfLinksComingInCurrentScope() const
183 vector< pair<InPort *, OutPort *> > ret;
184 set<InPort *> ports=getAllInPortsComingFromOutsideOfCurrentScope();
185 for(set<InPort *>::iterator iter2=ports.begin();iter2!=ports.end();iter2++)
187 set<OutPort *> temp2=(*iter2)->edSetOutPort();
188 for(set<OutPort *>::iterator iter3=temp2.begin();iter3!=temp2.end();iter3++)
189 ret.push_back(pair<InPort *, OutPort *>(*iter2,*iter3));
194 InputDataStreamPort *ElementaryNode::getInputDataStreamPort(const std::string& name) const throw(Exception)
196 return getPort<InputDataStreamPort>(name,_setOfInputDataStreamPort);
199 OutputDataStreamPort *ElementaryNode::getOutputDataStreamPort(const std::string& name) const throw(Exception)
201 return getPort<OutputDataStreamPort>(name,_setOfOutputDataStreamPort);
204 void ElementaryNode::edDisconnectAllLinksWithMe()
207 Node::edDisconnectAllLinksWithMe();
210 for(list<InputPort *>::iterator iter=_setOfInputPort.begin();iter!=_setOfInputPort.end();iter++)
211 (*iter)->edRemoveAllLinksLinkedWithMe();
213 for(list<InputDataStreamPort *>::iterator iter2=_setOfInputDataStreamPort.begin();iter2!=_setOfInputDataStreamPort.end();iter2++)
214 (*iter2)->edRemoveAllLinksLinkedWithMe();
217 for(list<OutputPort *>::iterator iter=_setOfOutputPort.begin();iter!=_setOfOutputPort.end();iter++)
218 (*iter)->edRemoveAllLinksLinkedWithMe();
220 for(list<OutputDataStreamPort *>::iterator iter2=_setOfOutputDataStreamPort.begin();iter2!=_setOfOutputDataStreamPort.end();iter2++)
221 (*iter2)->edRemoveAllLinksLinkedWithMe();
225 * checks if all input ports contains a valid data. Used at execution to change the state of the node
229 bool ElementaryNode::areAllInputPortsValid() const
232 for(list<InputPort *>::const_iterator iter=_setOfInputPort.begin();iter!=_setOfInputPort.end();iter++)
234 ret=!(*iter)->isEmpty();
241 * add this node task to a given set of ready tasks, if this task is ready to activate
244 void ElementaryNode::getReadyTasks(std::vector<Task *>& tasks)
246 DEBTRACE("ElementaryNode::getReadyTasks: " << getName() << " " << _state);
247 if(_state==YACS::TOACTIVATE or _state==YACS::TOLOAD)
248 tasks.push_back(this);
252 * remove port from node at edition. Ports are typed.
255 void ElementaryNode::edRemovePort(Port *port) throw(Exception)
257 DEBTRACE("ElementaryNode::edRemovePort ");
258 if(port->getNode()!=this)
259 throw Exception("ElementaryNode::edRemovePort : Port is not held by this node");
260 if(InputPort *p=dynamic_cast<InputPort *>(port))
261 edRemovePortTypedFromSet<InputPort>(p,_setOfInputPort);
262 else if(OutputPort *p=dynamic_cast<OutputPort *>(port))
263 edRemovePortTypedFromSet<OutputPort>(p,_setOfOutputPort);
264 else if(InputDataStreamPort *p=dynamic_cast<InputDataStreamPort *>(port))
265 edRemovePortTypedFromSet<InputDataStreamPort>(p,_setOfInputDataStreamPort);
266 else if(OutputDataStreamPort *p=dynamic_cast<OutputDataStreamPort *>(port))
267 edRemovePortTypedFromSet<OutputDataStreamPort>(p,_setOfOutputDataStreamPort);
269 throw Exception("ElementaryNode::edRemovePort : unknown port type");
275 * @return a set with only this node. (Same method in composed nodes)
278 list<ElementaryNode *> ElementaryNode::getRecursiveConstituents() const
280 list<ElementaryNode *> ret;
281 ret.push_back((ElementaryNode *)this);
285 Node *ElementaryNode::getChildByName(const std::string& name) const throw(Exception)
287 string what("ElementaryNode does not agregate any nodes particullary node with name "); what+=name;
288 throw Exception(what);
291 void ElementaryNode::checkBasicConsistency() const throw(Exception)
293 DEBTRACE("ElementaryNode::checkBasicConsistency");
294 list<InputPort *>::const_iterator iter;
295 for(iter=_setOfInputPort.begin();iter!=_setOfInputPort.end();iter++)
296 (*iter)->checkBasicConsistency();
299 ComposedNode *ElementaryNode::getDynClonerIfExists(const ComposedNode *levelToStop) const
301 for(ComposedNode *iter=_father;iter!=levelToStop && iter!=0; iter=iter->_father)
302 if(!iter->isPlacementPredictableB4Run())
307 InputPort *ElementaryNode::createInputPort(const std::string& inputPortName, TypeCode* type)
309 return getRuntime()->createInputPort(inputPortName, _implementation, this, type);
313 * the input port is also published recursively in ancestors because it may be visible from everywhere.
314 * WARNING: CHECK CASE OF BLOC: ONLY INPUT PORTS NOT INTERNALLY CONNECTED MUST BE VISIBLE.
317 InputPort *ElementaryNode::edAddInputPort(const std::string& inputPortName, TypeCode* type) throw(Exception)
320 if (edCheckAddPort<InputPort, TypeCode*>(inputPortName,_setOfInputPort,type))
322 ret = createInputPort(inputPortName, type);
323 _setOfInputPort.push_back(ret);
326 ComposedNode *iter=_father;
334 void ElementaryNode::edOrderInputPorts(const std::list<InputPort*>& ports)
336 std::set<InputPort *> s1;
337 std::set<InputPort *> s2;
338 for(list<InputPort *>::const_iterator it=_setOfInputPort.begin();it != _setOfInputPort.end();it++)
340 for(list<InputPort *>::const_iterator it=ports.begin();it != ports.end();it++)
344 throw Exception("ElementaryNode::edOrderInputPorts : port list must contain same ports as existing ones");
346 _setOfInputPort.clear();
347 for(list<InputPort *>::const_iterator it=ports.begin();it != ports.end();it++)
348 _setOfInputPort.push_back(*it);
351 void ElementaryNode::edOrderOutputPorts(const std::list<OutputPort*>& ports)
353 std::set<OutputPort *> s1;
354 std::set<OutputPort *> s2;
355 for(list<OutputPort *>::const_iterator it=_setOfOutputPort.begin();it != _setOfOutputPort.end();it++)
357 for(list<OutputPort *>::const_iterator it=ports.begin();it != ports.end();it++)
361 throw Exception("ElementaryNode::edOrderOutputPorts : port list must contain same ports as existing ones");
363 _setOfOutputPort.clear();
364 for(list<OutputPort *>::const_iterator it=ports.begin();it != ports.end();it++)
365 _setOfOutputPort.push_back(*it);
368 OutputPort *ElementaryNode::createOutputPort(const std::string& outputPortName, TypeCode* type)
370 return getRuntime()->createOutputPort(outputPortName, _implementation, this, type);
374 * TO SOLVE : The output port is not published in father. Father must create an output port.
375 * for now, publication is done the same way as input ports
378 OutputPort *ElementaryNode::edAddOutputPort(const std::string& outputPortName, TypeCode* type) throw(Exception)
381 if (edCheckAddPort<OutputPort, TypeCode*>(outputPortName,_setOfOutputPort,type))
383 ret = createOutputPort(outputPortName, type);
384 _setOfOutputPort.push_back(ret);
387 ComposedNode *iter=_father;
395 InputDataStreamPort *ElementaryNode::createInputDataStreamPort(const std::string& inputPortDSName, TypeCode* type)
397 return getRuntime()->createInputDataStreamPort(inputPortDSName, this, type);
400 InputDataStreamPort *ElementaryNode::edAddInputDataStreamPort(const std::string& inputPortDSName, TypeCode* type) throw(Exception)
402 InputDataStreamPort *ret = 0;
403 if (edCheckAddPort<InputDataStreamPort, TypeCode*>(inputPortDSName,_setOfInputDataStreamPort,type))
405 ret = createInputDataStreamPort(inputPortDSName, type);
406 _setOfInputDataStreamPort.push_back(ret);
412 OutputDataStreamPort *ElementaryNode::createOutputDataStreamPort(const std::string& outputPortDSName, TypeCode* type)
414 return getRuntime()->createOutputDataStreamPort(outputPortDSName, this, type);
417 OutputDataStreamPort *ElementaryNode::edAddOutputDataStreamPort(const std::string& outputPortDSName, TypeCode* type) throw(Exception)
419 OutputDataStreamPort *ret = 0;
420 if (edCheckAddPort<OutputDataStreamPort, TypeCode*>(outputPortDSName,_setOfOutputDataStreamPort,type))
422 ret = createOutputDataStreamPort(outputPortDSName, type);
423 _setOfOutputDataStreamPort.push_back(ret);
430 * get the input port name used by the current node (see composed nodes)
433 string ElementaryNode::getInPortName(const InPort * inPort) const throw (Exception)
435 Node *node = inPort->getNode();
438 string what("InputPort "); what += inPort->getName(); what += " does not belong to node "; what += node->getName();
439 throw Exception(what);
441 return inPort->getName();
444 string ElementaryNode::getOutPortName(const OutPort *outPort) const throw (Exception)
446 Node *node = outPort->getNode();
449 string what("OutputPort "); what += outPort->getName(); what += " does not belong to node "; what += node->getName();
450 throw Exception(what);
452 return outPort->getName();
455 void ElementaryNode::begin()
460 bool ElementaryNode::isReady()
462 return _state==TOACTIVATE;
465 void ElementaryNode::finished()
469 void ElementaryNode::aborted()
474 //! Notify this node that it is loaded
476 * When an elementary node has been loaded
477 * It is ready to be connected
480 void ElementaryNode::loaded()
484 //! Notify this node that it is connected
486 * When an elementary node has been connected it goes to TOACTIVATE state
487 * It is then ready to be executed
490 void ElementaryNode::connected()
492 if(_inGate.exIsReady())
493 if(areAllInputPortsValid())
495 setState(TOACTIVATE);
501 void ElementaryNode::accept(Visitor *visitor)
503 visitor->visitElementaryNode(this);
506 //! Give a description of error when node status is ERROR
510 std::string ElementaryNode::getErrorDetails()
512 return _errorDetails;
515 void ElementaryNode::edUpdateState()
517 DEBTRACE("ElementaryNode::edUpdateState: " << getName());
518 YACS::StatesForNode state=YACS::READY;
521 checkBasicConsistency();
527 _errorDetails=e.what();
529 DEBTRACE("ElementaryNode::edUpdateState: " << _errorDetails);
535 //! Put this node into TOLOAD state when possible
537 * Can be called by another ElementaryNode that is connected to this one by a datastream link
538 * These 2 nodes must be loaded at the same time as they are coupled
539 * It's the other node which requests this node loading
541 void ElementaryNode::ensureLoading()
543 DEBTRACE("ElementaryNode::ensureLoading: " << getName());
544 if(_state != YACS::READY)
546 setState(YACS::TOLOAD);
548 // request loading for all nodes connected to this one by datastream link
549 // Be careful that nodes can be connected in a loop. Put first this node in TOLOAD state to break the loop
550 std::list<OutputDataStreamPort *>::iterator iterout;
551 for(iterout = _setOfOutputDataStreamPort.begin(); iterout != _setOfOutputDataStreamPort.end(); iterout++)
553 OutputDataStreamPort *port=(OutputDataStreamPort *)*iterout;
554 std::set<InPort *> ports=port->edSetInPort();
555 std::set<InPort *>::iterator iter;
556 for(iter=ports.begin();iter != ports.end(); iter++)
558 Node* node= (*iter)->getNode();
559 node->ensureLoading();
562 std::list<InputDataStreamPort *>::iterator iterin;
563 for(iterin = _setOfInputDataStreamPort.begin(); iterin != _setOfInputDataStreamPort.end(); iterin++)
565 InputDataStreamPort *port=(InputDataStreamPort *)*iterin;
566 std::set<OutPort *> ports=port->edSetOutPort();
567 std::set<OutPort *>::iterator iter;
568 for(iter=ports.begin();iter != ports.end(); iter++)
570 Node* node= (*iter)->getNode();
571 node->ensureLoading();