3 #include "LinkInfo.hxx"
9 using namespace YACS::ENGINE;
12 const char Switch::DEFAULT_NODE_NAME[]="default";
13 const int Switch::ID_FOR_DEFAULT_NODE=-1973012217;
14 const char Switch::SELECTOR_INPUTPORT_NAME[]="select";
16 int CollectorSwOutPort::edGetNumberOfOutLinks() const
21 std::set<InPort *> CollectorSwOutPort::edSetInPort() const
25 ret.insert(_consumer);
29 bool CollectorSwOutPort::isAlreadyLinkedWith(InPort *with) const
32 with->getAllRepresentants(s);
33 return s.find(_consumer)!=s.end();
36 std::string CollectorSwOutPort::getNameOfTypeOfCurrentInstance() const
41 void CollectorSwOutPort::edRemoveAllLinksLinkedWithMe() throw(Exception)
43 map<int, OutPort *>::iterator pt;
45 for(pt=_potentialProducers.begin();pt!=_potentialProducers.end();pt++)
46 ((*pt).second)->removeInPort(_consumer,true);
49 TypeOfChannel CollectorSwOutPort::getTypeOfChannel() const
51 return (*(_potentialProducers.begin())).second->getTypeOfChannel();
54 void CollectorSwOutPort::getAllRepresented(std::set<OutPort *>& represented) const
56 map<int, OutPort *>::const_iterator pt;
57 for(pt=_potentialProducers.begin();pt!=_potentialProducers.end();pt++)
58 ((*pt).second)->getAllRepresented(represented);
61 bool CollectorSwOutPort::addInPort(InPort *inPort) throw(Exception)
64 {//a specific link is beeing done
65 bool ret=_currentProducer->addInPort(inPort);
69 else//global links asked
70 for(map<int, OutPort *>::iterator iter=_potentialProducers.begin();iter!=_potentialProducers.end();iter++)
71 (*iter).second->addInPort(inPort);
74 int CollectorSwOutPort::removeInPort(InPort *inPort, bool forward) throw(Exception)
78 return _currentProducer->removeInPort(inPort,forward);
81 throw Exception("CollectorSwOutputPort::edRemoveInputPort : internal error on link removal.");
86 * \note : 'master' specifies the instance of Switch of which 'this' collects all of these direct
87 * or indirect outports going to the same port 'port' (which is out of scope of 'master').
89 CollectorSwOutPort::CollectorSwOutPort(Switch *master, InPort *port):OutPort("",master,port->edGetType()),
90 DataPort("",master,port->edGetType()),
92 _consumer(port),_currentProducer(0)
94 _name="Representant_of_"; _name+=master->getName(); _name+="_for_inport_"; _name+=master->getRootNode()->getInPortName(_consumer);
97 CollectorSwOutPort::CollectorSwOutPort(const CollectorSwOutPort& other, Switch *master):OutPort("",master,other.edGetType()),
98 DataPort("",master,other.edGetType()),
100 _consumer(0),_currentProducer(0)
103 Switch *othSw=(Switch *)other._node;
104 for(map<int, OutPort *>::const_iterator iter=other._potentialProducers.begin();iter!=other._potentialProducers.end();iter++)
106 string name=othSw->getOutPortName((*iter).second);
107 _potentialProducers[(*iter).first]=master->getOutPort(name);
111 void CollectorSwOutPort::addPotentialProducerForMaster(OutPort *port)
113 int i=((Switch *)_node)->getRankOfNode(port->getNode());
114 map<int, OutPort *>::iterator pt=_potentialProducers.find(i);
115 if(pt==_potentialProducers.end())
117 _potentialProducers[i]=port;
118 _currentProducer=port;
122 _currentProducer=(*pt).second;
123 if(_currentProducer!=port)
125 string what("CollectorSwOutPort::addPotentialProducerForMaster : In switch node "); what+=_node->getName();
126 what+=" for input named \'"; what+=_consumer->getName(); what+="\' the output "; what+=_currentProducer->getName();
127 what+=" already got out for case of label ";
128 what+=Switch::getRepresentationOfCase((*pt).first);
129 throw Exception(what);
132 _className=port->getNameOfTypeOfCurrentInstance();
135 bool CollectorSwOutPort::removePotentialProducerForMaster()
138 map<int, OutPort *>::iterator result;
139 for(result=_potentialProducers.begin();result!=_potentialProducers.end();result++)
140 if((*result).second==_currentProducer)
145 if(result==_potentialProducers.end())
147 ostringstream stream; stream << "CollectorSwOutPort::removePotentialProducerForMaster : link from the branch whith id ";
148 stream << i << " not defined";
149 throw Exception(stream.str());
151 if((*result).second!=_currentProducer)
153 ostringstream stream; stream << "CollectorSwOutPort::removePotentialProducerForMaster : link from the branch whith id ";
154 stream << i << " defined but the output specified is not compatible";
155 throw Exception(stream.str());
157 _potentialProducers.erase(result);
158 return _potentialProducers.empty();
161 bool CollectorSwOutPort::checkManagementOfPort(OutPort *port) throw(Exception)
163 for(map<int, OutPort *>::iterator iter=_potentialProducers.begin();iter!=_potentialProducers.end();iter++)
164 if((*iter).second==port)
166 _currentProducer=port;
167 return _potentialProducers.size()==1;
169 throw Exception("CollectorSwOutPort::checkManagementOfPort : unexported port");
173 * Called by Switch::checkCFLinks.
175 void CollectorSwOutPort::checkConsistency(LinkInfo& info) const
177 if(((Switch *)_node)->getNbOfCases()!=_potentialProducers.size())
178 info.pushErrSwitch((CollectorSwOutPort *)this);
179 for(map<int, OutPort *>::const_iterator iter=_potentialProducers.begin();iter!=_potentialProducers.end();iter++)
180 (*iter).second->checkConsistency(info);
184 * Called by LinkInfo::getErrRepr to have a comprehensible message on throw.
185 * When called, typically checkCompletenessOfCases has detected that some potential producers were laking...
187 void CollectorSwOutPort::getHumanReprOfIncompleteCases(std::ostream& stream) const
189 set<int> lackingCases;
190 for(map< int ,Node * >::const_iterator iter=((Switch *)_node)->_mapOfNode.begin();iter!=((Switch *)_node)->_mapOfNode.end();iter++)
192 if(_potentialProducers.find((*iter).first)==_potentialProducers.end())
193 lackingCases.insert((*iter).first);
195 ostringstream streamForExc;
196 stream << "For link to " << _consumer->getName() << " of node " << _consumer->getNode()->getName()
197 << " the cases of switch node named " << _node->getName()
198 << " do not define links for following cases ids :";
199 for(set<int>::iterator iter=lackingCases.begin();iter!=lackingCases.end();iter++)
200 stream << Switch::getRepresentationOfCase(*iter) << " ";
204 FakeNodeForSwitch::FakeNodeForSwitch(Switch *sw, bool normalFinish, bool internalError):ElementaryNode("thisIsAFakeNode"),
206 _normalFinish(normalFinish),
207 _internalError(internalError)
209 _state=YACS::TOACTIVATE;
210 _father=_sw->getFather();
213 FakeNodeForSwitch::FakeNodeForSwitch(const FakeNodeForSwitch& other):ElementaryNode(other),_sw(0),
214 _normalFinish(false),
219 Node *FakeNodeForSwitch::simpleClone(ComposedNode *father, bool editionOnly) const
221 return new FakeNodeForSwitch(*this);
224 void FakeNodeForSwitch::exForwardFailed()
226 _sw->exForwardFailed();
227 FakeNodeForSwitch *normallyThis=_sw->_undispatchableNotificationNode;
228 _sw->_undispatchableNotificationNode=0;
232 void FakeNodeForSwitch::exForwardFinished()
234 _sw->exForwardFinished();
235 FakeNodeForSwitch *normallyThis=_sw->_undispatchableNotificationNode;
236 _sw->_undispatchableNotificationNode=0;
240 void FakeNodeForSwitch::execute()
243 throw Exception("");//only to trigger ABORT on Executor
246 void FakeNodeForSwitch::aborted()
249 _sw->_state!=YACS::INTERNALERR;
251 _sw->setState(YACS::ERROR);
254 void FakeNodeForSwitch::finished()
256 _sw->setState(YACS::DONE);
259 Switch::Switch(const Switch& other, ComposedNode *father, bool editionOnly):StaticDefinedComposedNode(other,father),_condition(other._condition,this),
260 _undispatchableNotificationNode(0)
262 for(map<int,Node *>::const_iterator iter=other._mapOfNode.begin();iter!=other._mapOfNode.end();iter++)
263 _mapOfNode[(*iter).first]=(*iter).second->clone(this,editionOnly);
265 for(map<InPort *, CollectorSwOutPort * >::const_iterator iter2=other._outPortsCollector.begin();iter2!=other._outPortsCollector.end();iter2++)
267 CollectorSwOutPort *newCol=new CollectorSwOutPort(*((*iter2).second),this);
268 _alreadyExistingCollectors.push_back(newCol);
272 Switch::Switch(const std::string& name):StaticDefinedComposedNode(name),_condition(SELECTOR_INPUTPORT_NAME,this,Runtime::_tc_int),_undispatchableNotificationNode(0)
278 for(map< int , Node * >::iterator iter=_mapOfNode.begin();iter!=_mapOfNode.end();iter++)
279 delete (*iter).second;
280 for(map<InPort *, CollectorSwOutPort * >::iterator iter2=_outPortsCollector.begin();iter2!=_outPortsCollector.end();iter2++)
281 delete (*iter2).second;
282 for(vector<CollectorSwOutPort *>::iterator iter3=_alreadyExistingCollectors.begin();iter3!=_alreadyExistingCollectors.end();iter3++)
286 Node *Switch::simpleClone(ComposedNode *father, bool editionOnly) const
288 return new Switch(*this,father,editionOnly);
291 void Switch::exUpdateState()
293 if(_state == YACS::DISABLED)
295 if(_inGate.exIsReady())
297 setState(YACS::TOACTIVATE);
298 if(_condition.isEmpty())
299 _undispatchableNotificationNode=new FakeNodeForSwitch(this,false,true);
302 map< int , Node * >::iterator iter=_mapOfNode.find(_condition.getIntValue());
303 if(iter==_mapOfNode.end())
305 iter=_mapOfNode.find(ID_FOR_DEFAULT_NODE);
306 if(iter==_mapOfNode.end())
308 bool normalFinish=getAllOutPortsLeavingCurrentScope().empty();
309 delete _undispatchableNotificationNode;
310 _undispatchableNotificationNode=new FakeNodeForSwitch(this,normalFinish);
313 ((*iter).second)->exUpdateState();
316 ((*iter).second)->exUpdateState();
321 void Switch::init(bool start)
323 StaticDefinedComposedNode::init(start);
325 for(map< int , Node * >::iterator iter=_mapOfNode.begin();iter!=_mapOfNode.end();iter++, i++)
329 ostringstream stream;
330 stream << "Switch::init : initialization failed due to unitialized branch of id " << (*iter).first;
331 throw Exception(stream.str());
333 ((*iter).second)->init(start);
337 void Switch::getReadyTasks(std::vector<Task *>& tasks)
340 * To change the way ComposedNode state is handled, uncomment the following line
341 * see Bloc::getReadyTasks
343 if(_state==YACS::TOACTIVATE) setState(YACS::ACTIVATED);
344 if(_state==YACS::TOACTIVATE || _state==YACS::ACTIVATED)
346 map< int , Node * >::iterator iter=_mapOfNode.find(_condition.getIntValue());
347 if(iter!=_mapOfNode.end())
348 ((*iter).second)->getReadyTasks(tasks);
351 iter=_mapOfNode.find(ID_FOR_DEFAULT_NODE);
352 if(iter!=_mapOfNode.end())
353 (*iter).second->getReadyTasks(tasks);//Default Node is returned
355 if(_undispatchableNotificationNode)
356 _undispatchableNotificationNode->getReadyTasks(tasks);
358 throw Exception("Switch::getReadyTasks : internal error");
363 void Switch::selectRunnableTasks(std::vector<Task *>& tasks)
367 list<Node *> Switch::edGetDirectDescendants() const
370 for(map< int , Node * >::const_iterator iter=_mapOfNode.begin();iter!=_mapOfNode.end();iter++)
372 ret.push_back((*iter).second);
376 int Switch::getNumberOfInputPorts() const
378 return StaticDefinedComposedNode::getNumberOfInputPorts()+1;
381 void Switch::edRemoveChild(Node *node) throw(Exception)
383 map< int , Node * >::iterator iter=_mapOfNode.begin();
384 for(;iter!=_mapOfNode.end();iter++)
385 if(node==(*iter).second)
387 edReleaseCase((*iter).first);
390 ostringstream what; what << "Switch::edRemoveChild : node with name " << node->getName() << " is not a direct child of Switch node " << _name;
391 throw Exception(what.str());
394 std::list<InputPort *> Switch::getSetOfInputPort() const
396 list<InputPort *> ret=StaticDefinedComposedNode::getSetOfInputPort();
397 ret.push_back((InputPort *)&_condition);
402 std::list<InputPort *> Switch::getLocalInputPorts() const
404 list<InputPort *> ret=StaticDefinedComposedNode::getLocalInputPorts();
405 ret.push_back((InputPort *)&_condition);
408 OutPort *Switch::getOutPort(const std::string& name) const throw(Exception)
410 for(map<InPort *, CollectorSwOutPort * >::const_iterator iter=_outPortsCollector.begin();iter!=_outPortsCollector.end();iter++)
411 if(name==(*iter).second->getName())
412 return (*iter).second;
413 for(vector<CollectorSwOutPort *>::const_iterator iter2=_alreadyExistingCollectors.begin();iter2!=_alreadyExistingCollectors.end();iter2++)
414 if(name==(*iter2)->getName())
416 return StaticDefinedComposedNode::getOutPort(name);
419 InputPort *Switch::getInputPort(const std::string& name) const throw(Exception)
421 if(name==SELECTOR_INPUTPORT_NAME)
422 return (InputPort *)&_condition;
423 return StaticDefinedComposedNode::getInputPort(name);
426 Node *Switch::getChildByShortName(const std::string& name) const throw(Exception)
428 if(name==DEFAULT_NODE_NAME)
430 map< int , Node * >::const_iterator iter=_mapOfNode.find(ID_FOR_DEFAULT_NODE);
431 if(iter!=_mapOfNode.end())
432 return (Node *)((*iter).second);
435 string what("Switch::getChildByShortName : no default node defined for switch of name "); what+=getName();
436 throw Exception(what);
439 for(map< int , Node * >::const_iterator iter=_mapOfNode.begin();iter!=_mapOfNode.end();iter++)
441 if(name==((*iter).second)->getQualifiedName())
442 return (*iter).second;
444 string what("node "); what+= name ; what+=" is not a child of node switch "; what += getName();
445 throw Exception(what);
448 Node *Switch::edSetDefaultNode(Node *node)
450 return edSetNode(ID_FOR_DEFAULT_NODE,node);
453 Node *Switch::edReleaseDefaultNode() throw(Exception)
455 return edReleaseCase(ID_FOR_DEFAULT_NODE);
458 Node *Switch::edReleaseCase(int caseId) throw(Exception)
460 map< int , Node * >::iterator iter=_mapOfNode.find(caseId);
461 if(iter==_mapOfNode.end())
463 string what("Switch::edReleaseCase : the case # "); what+=getRepresentationOfCase(caseId); what+=" is not set yet.";
464 throw Exception(what);
468 Node *ret=(*iter).second;
469 StaticDefinedComposedNode::edRemoveChild(ret);
470 _mapOfNode.erase(iter);
476 * \param caseId : the case ID chosen to place 'node'
477 * \param node : the node for the specified 'caseId'
478 * \return : If an old node with id equal to 'caseId' exists before, this old node is returned so that to be deallocated.
479 * 0 is returned if caseId is a new ID.
480 * \b WARNING : 'node' is held by 'this' after call, whereas returned node is no more held.
482 Node *Switch::edSetNode(int caseId, Node *node) throw(Exception)
485 throw Exception("Switch::edSetNode : null node cannot be set as a case in switch node");
487 throw Exception("Switch::edSetNode : node already held by another father");
488 checkNoCrossHierachyWith(node);
490 map< int , Node * >::iterator iter=_mapOfNode.find(caseId);
492 if(iter==_mapOfNode.end())
494 _mapOfNode[caseId]=node;
499 if(node!=(*iter).second)
501 Node *ret=(*iter).second;
508 YACS::Event Switch::updateStateOnFinishedEventFrom(Node *node)
510 setState(YACS::DONE);
511 return YACS::FINISH;//notify to father node that 'this' has becomed finished.
514 std::set<InPort *> Switch::getAllInPortsComingFromOutsideOfCurrentScope() const
516 set<InPort *> ret=StaticDefinedComposedNode::getAllInPortsComingFromOutsideOfCurrentScope();
517 set<OutPort *> temp2=_condition.edSetOutPort();
518 for(set<OutPort *>::iterator iter3=temp2.begin();iter3!=temp2.end();iter3++)
519 if(!isInMyDescendance((*iter3)->getNode()))
521 ret.insert((InPort *)&_condition);
527 void Switch::checkCFLinks(const std::list<OutPort *>& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const
529 map<InPort *, CollectorSwOutPort * >::const_iterator iter=_outPortsCollector.find(end);
530 if(iter!=_outPortsCollector.end())
532 set<OutPort *> represented;
533 (*iter).second->getAllRepresented(represented);
534 list<OutPort *> others;
535 for(list<OutPort *>::const_iterator iter2=starts.begin();iter2!=starts.end();iter2++)
536 if(represented.find(*iter2)==represented.end())
537 others.push_back(*iter2);
541 StaticDefinedComposedNode::checkCFLinks(others,end,alreadyFed,direction,info);//should never happend;
544 StaticDefinedComposedNode::checkCFLinks(starts,end,alreadyFed,direction,info);
547 void Switch::checkControlDependancy(OutPort *start, InPort *end, bool cross,
548 std::map < ComposedNode *, std::list < OutPort * > >& fw,
549 std::vector<OutPort *>& fwCross,
550 std::map< ComposedNode *, std::list < OutPort *> >& bw,
551 LinkInfo& info) const
553 throw Exception("Switch::checkControlDependancy : a link was dectected between 2 cases of a switch. Impossible !");
556 void Switch::checkNoCyclePassingThrough(Node *node) throw(Exception)
558 throw Exception("Switch::checkNoCyclePassingThrough : uncorrect control flow link relative to switch");
561 void Switch::checkLinkPossibility(OutPort *start, const std::list<ComposedNode *>& pointsOfViewStart,
562 InPort *end, const std::list<ComposedNode *>& pointsOfViewEnd) throw(Exception)
564 throw Exception("Switch::checkLinkPossibility : A link between 2 different cases of a same Switch requested -> Impossible");
567 void Switch::buildDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView)
569 map<InPort *, CollectorSwOutPort * >::iterator result=_outPortsCollector.find(finalTarget);
570 CollectorSwOutPort *newCollector;
571 if(result!=_outPortsCollector.end())
572 newCollector=(*result).second;
575 newCollector=new CollectorSwOutPort(this,finalTarget);
576 newCollector->edSetType((port.first)->edGetType());
577 _outPortsCollector[finalTarget]=newCollector;
579 newCollector->addPotentialProducerForMaster(port.first);
580 port.second=newCollector;
581 port.first=newCollector;
584 void Switch::getDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView) throw(Exception)
586 map<InPort *, CollectorSwOutPort * >::iterator iter=_outPortsCollector.find(finalTarget);
587 if(iter==_outPortsCollector.end())
589 string what("Switch::getDelegateOf : not exported OuputPort with name "); what+=(port.first)->getName(); what+=" for target inport of name ";
590 what+=finalTarget->getName();
591 throw Exception(what);
593 ((*iter).second)->checkManagementOfPort(port.first);
594 port.second=(*iter).second;
595 port.first=(*iter).second;
598 void Switch::releaseDelegateOf(OutPort *portDwn, OutPort *portUp, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView) throw(Exception)
601 portDwn->getAllRepresented(repr);
604 CollectorSwOutPort *portCasted=dynamic_cast<CollectorSwOutPort *>(portUp);
605 if(portCasted->removePotentialProducerForMaster())//normally always true
608 _outPortsCollector.erase(finalTarget);
613 int Switch::getNbOfCases() const
615 return _mapOfNode.size();
618 int Switch::getRankOfNode(Node *node) const
620 Node *directSon=isInMyDescendance(node);
621 for(map< int , Node * >::const_iterator iter=_mapOfNode.begin();iter!=_mapOfNode.end();iter++)
622 if((*iter).second==directSon)
623 return (*iter).first;
624 throw Exception("Switch::getRankOfNode : node not in switch");
627 string Switch::getRepresentationOfCase(int i)
629 if(i!=ID_FOR_DEFAULT_NODE)
631 ostringstream stream;
636 return DEFAULT_NODE_NAME;
639 //! Return the effective state of a node in the context of this switch (its father)
641 * \param node: the node which effective state is queried
642 * \return the effective node state
644 YACS::StatesForNode Switch::getEffectiveState(const Node* node) const
646 YACS::StatesForNode effectiveState=Node::getEffectiveState();
647 if(effectiveState==YACS::READY)
649 if(effectiveState==YACS::TOACTIVATE)
651 if(effectiveState==YACS::DISABLED)
652 return YACS::DISABLED;
653 map< int , Node * >::const_iterator iter=_mapOfNode.find(_condition.getIntValue());
654 if(iter!=_mapOfNode.end() && (*iter).second==node)
655 return node->getState();
659 YACS::StatesForNode Switch::getEffectiveState() const
661 return Node::getEffectiveState();
664 void Switch::writeDot(std::ostream &os) const
666 os << " subgraph cluster_" << getId() << " {\n" ;
667 for(map<int,Node*>::const_iterator iter=_mapOfNode.begin();iter!=_mapOfNode.end();iter++)
669 Node* n=(*iter).second;
671 os << getId() << " -> " << n->getId() << ";\n";
674 os << getId() << "[fillcolor=\"" ;
675 YACS::StatesForNode state=Node::getEffectiveState();
676 os << getColorState(state);
677 os << "\" label=\"" << "Switch:" ;
678 os << getQualifiedName() <<"\"];\n";
681 std::string Switch::getMyQualifiedName(const Node *directSon) const
683 string id=getCaseId(directSon);
684 id+=directSon->getName();
688 std::string Switch::getCaseId(const Node *node) const throw(Exception)
691 map<int, Node*>::const_iterator iter;
692 for (iter = _mapOfNode.begin(); iter != _mapOfNode.end(); iter++)
693 if (iter->second == node)
696 if (iter->first == Switch::ID_FOR_DEFAULT_NODE)
697 a << DEFAULT_NODE_NAME << sep;
698 else if (iter->first <0)
699 a << "m" << -iter->first << sep;
700 else a << "p" << iter->first << sep;
703 string what("node "); what+= node->getName() ; what+=" is not a child of node "; what += getName();
704 throw Exception(what);
707 void Switch::accept(Visitor *visitor)
709 visitor->visitSwitch(this);