+// Copyright (C) 2006-2016 CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
#include "ComposedNode.hxx"
#include "LinkInfo.hxx"
#include "Container.hxx"
#include "InputPort.hxx"
#include "OutputPort.hxx"
#include "ServiceNode.hxx"
+#include "InlineNode.hxx"
#include "DataFlowPort.hxx"
#include "DataStreamPort.hxx"
#include "ElementaryNode.hxx"
using namespace YACS::ENGINE;
using namespace std;
+/*! \class YACS::ENGINE::ComposedNode
+ * \brief Base class for all composed nodes.
+ *
+ * This is an abstract class that must be specialized.
+ *
+ * \ingroup Nodes
+ */
+
const char ComposedNode::SEP_CHAR_BTW_LEVEL[]=".";
ComposedNode::ComposedNode(const std::string& name):Node(name)
DeploymentTree treeToDup=otherC.getDeploymentTree();
list< ElementaryNode * > clones=otherC.getRecursiveConstituents();
vector<Container *> conts=treeToDup.getAllContainers();
+ //iterate on all containers
for(vector<Container *>::iterator iterCt=conts.begin();iterCt!=conts.end();iterCt++)
{
vector<ComponentInstance *> comps=treeToDup.getComponentsLinkedToContainer(*iterCt);
Container *contCloned=0;
if((*iterCt))
contCloned=(*iterCt)->clone();
+
+ //iterate on all component instances linked to the container
for(vector<ComponentInstance *>::iterator iterCp=comps.begin();iterCp!=comps.end();iterCp++)
{
vector<Task *> tasks=treeToDup.getTasksLinkedToComponent(*iterCp);
}
curCloned->decrRef();
}
+
+ // iterate on all tasks linked to the container
+ vector<Task *> tasks=treeToDup.getTasksLinkedToContainer(*iterCt);
+ for(vector<Task *>::iterator iterT=tasks.begin();iterT!=tasks.end();iterT++)
+ {
+ std::list< ElementaryNode * >::iterator res=find(clones.begin(),clones.end(),(ElementaryNode *)(*iterT));
+ InlineFuncNode *nodeC=(InlineFuncNode *)getChildByName(otherC.getChildName(*res));
+ nodeC->setContainer(contCloned);
+ }
+
+ // ended with current container
if(contCloned)
contCloned->decrRef();
}
}
+void ComposedNode::performShallowDuplicationOfPlacement(const Node& other)
+{
+ const ComposedNode &otherC=*(dynamic_cast<const ComposedNode *>(&other));
+ DeploymentTree treeToDup=otherC.getDeploymentTree();
+ list< ElementaryNode * > clones=otherC.getRecursiveConstituents();
+ vector<Container *> conts=treeToDup.getAllContainers();
+ //iterate on all containers
+ for(vector<Container *>::iterator iterCt=conts.begin();iterCt!=conts.end();iterCt++)
+ {
+ vector<ComponentInstance *> comps=treeToDup.getComponentsLinkedToContainer(*iterCt);
+ Container *contCloned((*iterCt));
+
+ //iterate on all component instances linked to the container
+ for(vector<ComponentInstance *>::iterator iterCp=comps.begin();iterCp!=comps.end();iterCp++)
+ {
+ vector<Task *> tasks=treeToDup.getTasksLinkedToComponent(*iterCp);
+ ComponentInstance *curCloned((*iterCp));
+ curCloned->setContainer(contCloned);
+ for(vector<Task *>::iterator iterT=tasks.begin();iterT!=tasks.end();iterT++)
+ {
+ //No risk for static cast : appendTask called by ComposedNode.
+ list< ElementaryNode * >::iterator res=find(clones.begin(),clones.end(),(ElementaryNode *)(*iterT));
+ //No risk here to because called only on cloning process...
+ ServiceNode *nodeC=(ServiceNode *)getChildByName(otherC.getChildName(*res));
+ nodeC->setComponent(curCloned);
+ }
+ }
+
+ // iterate on all tasks linked to the container
+ vector<Task *> tasks=treeToDup.getTasksLinkedToContainer(*iterCt);
+ for(vector<Task *>::iterator iterT=tasks.begin();iterT!=tasks.end();iterT++)
+ {
+ std::list< ElementaryNode * >::iterator res=find(clones.begin(),clones.end(),(ElementaryNode *)(*iterT));
+ InlineFuncNode *nodeC=(InlineFuncNode *)getChildByName(otherC.getChildName(*res));
+ nodeC->setContainer(contCloned);
+ }
+ }
+}
+
bool ComposedNode::isFinished()
{
if(_state==YACS::DONE)return true;
/*!
* \param deep if \b true a deep check is perfomed. Typically has to be called by an executor before any attempt to launch an execution.
*/
-DeploymentTree ComposedNode::checkDeploymentTree(bool deep) const throw(Exception)
+DeploymentTree ComposedNode::checkDeploymentTree(bool deep) const throw(YACS::Exception)
{
DeploymentTree ret;
list< ElementaryNode * > tasks=getRecursiveConstituents();
case DeploymentTree::DUP_TASK_NOT_COMPATIBLE_WITH_EXISTING_TREE:
{
string what("ComposedNode::checkDeploymentTree : ServiceNode with name \""); what+=(*iter)->getName();
- what+="\" coexists in a component with an another Task which context is incorrect with it.";
+ what+="\" coexists in a component with an another Task which context is incompatible with it.";
throw Exception(what);
}
- case DeploymentTree::DEPLOYABLE_BUT_NOT_SPECIFIED :
- {
- if(deep)
- {
- string what("ComposedNode::checkDeploymentTree : ServiceNode with name \""); what+=(*iter)->getName();
- what+="\" is deployable but no component is specified on it.";
- throw Exception(what);
- }
- }
+ case DeploymentTree::DEPLOYABLE_BUT_NOT_SPECIFIED :
+ {
+ if(deep)
+ {
+ string what("ComposedNode::checkDeploymentTree : ServiceNode with name \""); what+=(*iter)->getName();
+ what+="\" is deployable but no component is specified on it.";
+ throw Exception(what);
+ }
+ }
}
}
return ret;
* Calls ComposedNode::updateStateFrom to update state from task to root node
*/
void ComposedNode::notifyFrom(const Task *sender, //* I : task emitting event
- YACS::Event event //* I : event emitted
+ YACS::Event event, //* I : event emitted
+ const Executor *execInst
)
{
+ DEBTRACE("ComposedNode::notifyFrom " << event);
ElementaryNode *taskTyped=dynamic_cast<ElementaryNode *>((Task *)sender);
YACS::Event curEvent=event;
Node *lminus1LevelNode=taskTyped;
ComposedNode *curLevelNode=taskTyped->_father;
if(!curLevelNode)//Specific case of loop when 0 turn is specified without any enclosing bloc.
return ;
- curEvent=curLevelNode->updateStateFrom(lminus1LevelNode,curEvent);
+ curEvent=curLevelNode->updateStateFrom(lminus1LevelNode,curEvent,execInst);
while(curEvent!=YACS::NOEVENT && curLevelNode!=this)
{
lminus1LevelNode=curLevelNode;
curLevelNode=curLevelNode->_father;
- curEvent=curLevelNode->updateStateFrom(lminus1LevelNode,curEvent);
+ curEvent=curLevelNode->updateStateFrom(lminus1LevelNode,curEvent,execInst);
}
}
* \return true if a new link has been created, false otherwise.
*/
-bool ComposedNode::edAddLink(OutPort *start, InPort *end) throw(Exception)
+bool ComposedNode::edAddLink(OutPort *start, InPort *end) throw(YACS::Exception)
{
DEBTRACE("ComposedNode::edAddLink");
set<OutPort *> represented;
* \param end : the InPort to connect
* \return true if a new link has been created, false otherwise.
*/
-bool ComposedNode::edAddDFLink(OutPort *start, InPort *end) throw(Exception)
+bool ComposedNode::edAddDFLink(OutPort *start, InPort *end) throw(YACS::Exception)
{
Node* n1=start->getNode();
Node* n2=end->getNode();
* supporting it.
* \return true if a new link has been created, false otherwise.
*/
-bool ComposedNode::edAddLink(OutGate *start, InGate *end) throw(Exception)
+bool ComposedNode::edAddLink(OutGate *start, InGate *end) throw(YACS::Exception)
{
Node* n1=start->getNode();
Node* n2=end->getNode();
if(n1==n2)
- throw Exception("ComposedNode::edAddLink: can not add a control link to a node with itself");
+ throw Exception("ComposedNode::edAddLink: can not add a control link to a node with itself",1);
ComposedNode* father=checkHavingCommonFather(start->getNode(),end->getNode());
if(father==0)
throw Exception("ComposedNode::edAddLink: Trying to add CF link on orphan nodes.");
/*!
* Add a controlflow link between two nodes by calling edAddLink on their control ports
*/
-bool ComposedNode::edAddCFLink(Node *nodeS, Node *nodeE) throw(Exception)
+bool ComposedNode::edAddCFLink(Node *nodeS, Node *nodeE) throw(YACS::Exception)
{
return edAddLink(nodeS->getOutGate(),nodeE->getInGate());
}
//! Remove a controlflow link.
-void ComposedNode::edRemoveCFLink(Node *nodeS, Node *nodeE) throw(Exception)
+void ComposedNode::edRemoveCFLink(Node *nodeS, Node *nodeE) throw(YACS::Exception)
{
edRemoveLink(nodeS->getOutGate(),nodeE->getInGate());
}
* implies DF/DS gateway.
*/
-void ComposedNode::edRemoveLink(OutPort *start, InPort *end) throw(Exception)
+void ComposedNode::edRemoveLink(OutPort *start, InPort *end) throw(YACS::Exception)
{
if(!start->isAlreadyLinkedWith(end))
throw Exception("ComposedNode::edRemoveLink : unexisting link");
{
iterS=nodeOTemp->_father;
while(iterS!=lwstCmnAnctr)
- {
- if (!iterS)
- {
- stringstream what;
- what << "ComposedNode::edRemoveLink: "
- << start->getNode()->getName() << "." <<start->getName() << "->"
- << end->getNode()->getName() << "." << end->getName();
- throw Exception(what.str());
- }
- OutPort *tmp=currentPortO.first;
- iterS->getDelegateOf(currentPortO, end, allAscendanceOfNodeEnd);
- needsToDestroyO.push_back(pair< ComposedNode * , pair < OutPort* , OutPort *> >(iterS,pair<OutPort* , OutPort *> (tmp,currentPortO.first)));
- iterS=iterS->_father;
- }
+ {
+ if (!iterS)
+ {
+ stringstream what;
+ what << "ComposedNode::edRemoveLink: "
+ << start->getNode()->getName() << "." <<start->getName() << "->"
+ << end->getNode()->getName() << "." << end->getName();
+ throw Exception(what.str());
+ }
+ OutPort *tmp=currentPortO.first;
+ iterS->getDelegateOf(currentPortO, end, allAscendanceOfNodeEnd);
+ needsToDestroyO.push_back(pair< ComposedNode * , pair < OutPort* , OutPort *> >(iterS,pair<OutPort* , OutPort *> (tmp,currentPortO.first)));
+ iterS=iterS->_father;
+ }
}
Node *nodeTemp=end->getNode();
InPort * currentPortI=end;
}
//! Remove a controlflow link.
-void ComposedNode::edRemoveLink(OutGate *start, InGate *end) throw(Exception)
+void ComposedNode::edRemoveLink(OutGate *start, InGate *end) throw(YACS::Exception)
{
ComposedNode* father=checkHavingCommonFather(start->getNode(),end->getNode());
if(father!=this)
start->edRemoveInGate(end);
}
+bool ComposedNode::edAddChild(Node *DISOWNnode) throw(YACS::Exception)
+{
+ return false; // --- reimplemented in derived classes
+}
+
//! Remove a child node.
-void ComposedNode::edRemoveChild(Node *node) throw(Exception)
+void ComposedNode::edRemoveChild(Node *node) throw(YACS::Exception)
{
if(!node)
return;
* separator was not found).
*/
bool ComposedNode::splitNamesBySep(const std::string& globalName, const char separator[],
- std::string& firstPart, std::string& lastPart, bool priority) throw(Exception)
+ std::string& firstPart, std::string& lastPart, bool priority) throw(YACS::Exception)
{
const string delims(separator);
string portName, nodeName;
}
firstPart = globalName.substr(0,idx);
lastPart = globalName.substr(idx+1);
- if ((firstPart.empty()) or (lastPart.empty()))
+ if ((firstPart.empty()) || (lastPart.empty()))
{
string what("the name "); what+= globalName ; what+=" is not a valid port name";
throw Exception(what);
return ret;
}
-void ComposedNode::checkConsistency(LinkInfo& info) const throw(Exception)
+void ComposedNode::checkConsistency(LinkInfo& info) const throw(YACS::Exception)
{
info.clearAll();
info.setPointOfView((ComposedNode *)this);
}
if(!candidateForAdvCheck.empty())
//End of filtering. Now regarding CF constraints for the current InPutPort.
- checkLinksCoherenceRegardingControl(candidateForAdvCheck,*iter1,info);
+ try
+ {
+ checkLinksCoherenceRegardingControl(candidateForAdvCheck,*iter1,info);
+ }
+ catch(YACS::Exception& ex)
+ {
+ std::string what=ex.what();
+ what += "\nfor input port: ";
+ what += (*iter1)->getNode()->getName();
+ what += ".";
+ what += (*iter1)->getName();
+
+ destructCFComputations(info);
+ throw YACS::Exception(what);
+ }
else
//No backlinks
- if(!(*iter1)->edIsManuallyInitialized())
+ if(!(*iter1)->canBeNull() && !(*iter1)->edIsManuallyInitialized())
info.pushErrLink(0,*iter1,E_NEVER_SET_INPUTPORT);
}
destructCFComputations(info);
* This method check that G1 <- G2 <- G3 <- G1 does not happened.
* Typically called by methods that set a hierarchy (Bloc::edAddChild, Loop::edSetNode, ...).
*/
-void ComposedNode::checkNoCrossHierachyWith(Node *node) const throw (Exception)
+void ComposedNode::checkNoCrossHierachyWith(Node *node) const throw(YACS::Exception)
{
ComposedNode *nodeC=dynamic_cast<ComposedNode *>(node);
if(!nodeC)
/*!
* call it only for 'starts' to 'end' links \b DEALED by 'this'.
*/
-void ComposedNode::checkLinksCoherenceRegardingControl(const std::vector<OutPort *>& starts, InputPort *end, LinkInfo& info) const throw(Exception)
+void ComposedNode::checkLinksCoherenceRegardingControl(const std::vector<OutPort *>& starts, InputPort *end, LinkInfo& info) const throw(YACS::Exception)
{
map < ComposedNode *, list<OutPort *>, SortHierarc > outputs;//forward link classical
vector<OutPort *> outputsCross;//forward link cross
}
/*!
- * Internal method during CF links. This méthode is in charge to statuate on links consistency in the case that no control flow defined by user
- * is set.
+ * Internal method during CF links. This methode is in charge to statuate on links consistency in the case
+ * that no control flow defined by user is set.
*/
void ComposedNode::solveObviousOrDelegateCFLinks(const std::list<OutPort *>& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const
{
}
}
+//! check control flow links
/*!
* \param starts If different of 0, must aggregate at leat \b 1 element.
+ * \param end :
* \param alreadyFed in/out parameter. Indicates if 'end' ports is already and surely set or fed by an another port.
* \param direction If true : forward direction else backward direction.
+ * \param info : informations collectedduring the check
*/
void ComposedNode::checkCFLinks(const std::list<OutPort *>& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const
{
//This case is typically dedicated when direct son is ElementaryNode and self link is defined on this.
if(!dynamic_cast<ElementaryNode *>(nodeEnd))
throw Exception(what);
+
list< OutPort *>::const_iterator iter=starts.begin();
Node *nodeStart=(*iter)->getNode();
iter++;
if(nodeEnd!=nodeStart)
throw Exception(what);
+
for(;iter!=starts.end();iter++)
if((*iter)->getNode()!=nodeStart)
throw Exception(what);
{
set<OutPort *> temp2=(*iter2)->edSetOutPort();
for(set<OutPort *>::iterator iter3=temp2.begin();iter3!=temp2.end();iter3++)
- if(!isInMyDescendance((*iter3)->getNode()))
- ret.push_back(pair<InPort *, OutPort *>(*iter2,*iter3));
+ {
+ if(isInMyDescendance((*iter3)->getNode()))continue;
+ std::set<OutPort *> trueOutPorts;
+ (*iter3)->getAllRepresented(trueOutPorts);
+ for(std::set<OutPort *>::iterator iter4=trueOutPorts.begin();iter4!=trueOutPorts.end();++iter4)
+ ret.push_back(pair<InPort *, OutPort *>(*iter2,*iter4));
+ }
}
return ret;
}
}
}
-ComposedNode *ComposedNode::getRootNode() const throw(Exception)
+ComposedNode *ComposedNode::getRootNode() const throw(YACS::Exception)
{
if(!_father)
return (ComposedNode *)this;
return 0;
}
-string ComposedNode::getChildName(const Node* node) const throw(Exception)
+string ComposedNode::getChildName(const Node* node) const throw(YACS::Exception)
{
string nodeName=node->getQualifiedName();
if (!isNodeAlreadyAggregated(node))
return directSon->getName();
}
-Node *ComposedNode::getChildByName(const std::string& name) const throw(Exception)
+Node *ComposedNode::getChildByName(const std::string& name) const throw(YACS::Exception)
{
string potentiallyDirectSonName, remainsPath;
bool forwardNeeded=ComposedNode::splitNamesBySep(name, SEP_CHAR_BTW_LEVEL,
* \exception Exception : If 'nodeToTest' is NOT in descendance of 'this' AND not equal to 'this'
* \param nodeToTest : the node to check
*/
-void ComposedNode::checkInMyDescendance(Node *nodeToTest) const throw(Exception)
+void ComposedNode::checkInMyDescendance(Node *nodeToTest) const throw(YACS::Exception)
{
const char whatC[]=" is not the descendance of node ";
if(nodeToTest==0)
* \return The lowest common ancestor if it exists.
*
*/
-ComposedNode *ComposedNode::getLowestCommonAncestor(Node *node1, Node *node2) throw(Exception)
+ComposedNode *ComposedNode::getLowestCommonAncestor(Node *node1, Node *node2) throw(YACS::Exception)
{
- const char what[]="2 nodes does not share the same genealogy";
+ const char what[]="The two nodes do not share the same genealogy";
if(node1==0 || node2==0)
throw Exception(what);
ComposedNode *temp;
return *iter;
}
+/*!
+ * Same as getLowestCommonAncestor method except that absolute string representation is considered here instead of instances.
+ */
+std::string ComposedNode::getLowestCommonAncestorStr(const std::string& node1, const std::string& node2)
+{
+ std::string ret;
+ std::size_t it1_b(0),it1_e(0),it2_b(0),it2_e(0);
+ while(it1_b!=std::string::npos && it2_b!=std::string::npos)
+ {
+ it1_e=node1.find(SEP_CHAR_BTW_LEVEL,it1_b);
+ it2_e=node2.find(SEP_CHAR_BTW_LEVEL,it2_b);
+ if(it1_e!=it2_e && it1_e!=std::string::npos && it2_e!=std::string::npos)
+ break;
+ std::string elt1(node1.substr(it1_b,it1_e-it1_b)),elt2(node2.substr(it2_b,it2_e-it2_b));
+ if(elt1!=elt2)
+ break;
+ if(!ret.empty())
+ ret+=SEP_CHAR_BTW_LEVEL;
+ ret+=elt1;
+ it1_b=node1.find_first_not_of(SEP_CHAR_BTW_LEVEL,it1_e);
+ it2_b=node2.find_first_not_of(SEP_CHAR_BTW_LEVEL,it2_e);
+ }
+ return ret;
+}
+
+/*!
+ * This method recursively all redundant control links in this.
+ */
+void ComposedNode::removeRecursivelyRedundantCL()
+{
+ std::list<Node *> dd(edGetDirectDescendants());
+ for(std::list<Node *>::const_iterator it=dd.begin();it!=dd.end();it++)
+ {
+ ComposedNode *elt(dynamic_cast<ComposedNode *>(*it));
+ if(elt)
+ elt->removeRecursivelyRedundantCL();
+ }
+}
+
list<ElementaryNode *> ComposedNode::getRecursiveConstituents() const
{
list<ElementaryNode *> ret;
return ret;
}
+
+//! Get the progress weight for all elementary nodes
+/*!
+ * Only elementary nodes have weight. A simple composed node only sum up weight of all his descendants
+ * (working is different for loop or switch nodes)
+ */
+list<ProgressWeight> ComposedNode::getProgressWeight() const
+{
+ list<ProgressWeight> ret;
+ list<Node *> setOfNode=edGetDirectDescendants();
+ for(list<Node *>::const_iterator iter=setOfNode.begin();iter!=setOfNode.end();iter++)
+ {
+ list<ProgressWeight> myCurrentSet=((ComposedNode*)(*iter))->getProgressWeight();
+ ret.insert(ret.end(),myCurrentSet.begin(),myCurrentSet.end());
+ }
+ return ret;
+}
+
//! Get the input port name
/*!
* get the input port name used by the current node, recursively built with children names.
*/
-string ComposedNode::getInPortName(const InPort * inPort) const throw (Exception)
+string ComposedNode::getInPortName(const InPort * inPort) const throw(YACS::Exception)
{
return getPortName<InPort>(inPort);
}
-string ComposedNode::getOutPortName(const OutPort *outPort) const throw (Exception)
+string ComposedNode::getOutPortName(const OutPort *outPort) const throw(YACS::Exception)
{
return getPortName<OutPort>(outPort);
}
return ret;
}
-OutPort *ComposedNode::getOutPort(const std::string& name) const throw(Exception)
+OutPort *ComposedNode::getOutPort(const std::string& name) const throw(YACS::Exception)
{
string portName, nodeName;
if(splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,false))
* and so the leaf of type ElementaryNode aggregating
* this InputPort is directly invoked.
*/
-InputPort * ComposedNode::getInputPort(const std::string& name) const throw(Exception)
+InputPort * ComposedNode::getInputPort(const std::string& name) const throw(YACS::Exception)
{
+ try {
+ return Node::getInputPort(name);
+ }
+ catch(Exception& e) {}
+
string portName, nodeName;
if(splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,true))
{
* Contrary to YACS::ENGINE::ComposedNode::getInputPort, this method is recursive and go
* down hierarchy step by step to complete its work.
*/
-OutputPort * ComposedNode::getOutputPort(const std::string& name) const throw(Exception)
+OutputPort * ComposedNode::getOutputPort(const std::string& name) const throw(YACS::Exception)
{
string portName, nodeName;
if(splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,false))
}
}
-InputDataStreamPort *ComposedNode::getInputDataStreamPort(const std::string& name) const throw(Exception)
+InputDataStreamPort *ComposedNode::getInputDataStreamPort(const std::string& name) const throw(YACS::Exception)
{
string portName, nodeName;
if(splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,true))
}
}
-OutputDataStreamPort *ComposedNode::getOutputDataStreamPort(const std::string& name) const throw(Exception)
+OutputDataStreamPort *ComposedNode::getOutputDataStreamPort(const std::string& name) const throw(YACS::Exception)
{
string portName, nodeName;
if(splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,true))
* Called by ComposedNode::notifyFrom
*/
YACS::Event ComposedNode::updateStateFrom(Node *node, //* I : node emitting event
- YACS::Event event //* I : event emitted
+ YACS::Event event, //* I : event emitted
+ const Executor *execInst
)
{
DEBTRACE("updateStateFrom: " << node->getName() << " " << event);
return updateStateOnFinishedEventFrom(node);
break;
case YACS::ABORT:
- return updateStateOnFailedEventFrom(node);
+ return updateStateOnFailedEventFrom(node,execInst);
break;
default:
return YACS::NOEVENT;//TODO unexpected type of event
//unexpected exception: probably a bug in engine
//try to keep a consistent global state
DEBTRACE( "updateStateFrom: " << ex.what() );
+ _errorDetails="Internal error: ";
+ _errorDetails=_errorDetails + ex.what();
setState(YACS::ERROR);
exForwardFailed();
return YACS::ABORT;
}
//! Method used to notify the node that a child node has failed
-YACS::Event ComposedNode::updateStateOnFailedEventFrom(Node *node)
+YACS::Event ComposedNode::updateStateOnFailedEventFrom(Node *node, const Executor *execInst)
{
setState(YACS::FAILED);
return YACS::ABORT;
}
void ComposedNode::checkLinkPossibility(OutPort *start, const std::list<ComposedNode *>& pointsOfViewStart,
- InPort *end, const std::list<ComposedNode *>& pointsOfViewEnd) throw(Exception)
+ InPort *end, const std::list<ComposedNode *>& pointsOfViewEnd) throw(YACS::Exception)
{
- if((dynamic_cast<DataFlowPort *>(start) or dynamic_cast<DataFlowPort *>(end))
- and (dynamic_cast<DataStreamPort *>(start) or dynamic_cast<DataStreamPort *>(end)))
+ if((dynamic_cast<DataFlowPort *>(start) || dynamic_cast<DataFlowPort *>(end))
+ && (dynamic_cast<DataStreamPort *>(start) || dynamic_cast<DataStreamPort *>(end)))
{//cross protocol required : deeper check needed
bool isOK=false;
list<ComposedNode *>::const_iterator iter;
- for(iter=pointsOfViewStart.begin();iter!=pointsOfViewStart.end() and !isOK;iter++)
+ for(iter=pointsOfViewStart.begin();iter!=pointsOfViewStart.end() && !isOK;iter++)
isOK=(*iter)->isRepeatedUnpredictablySeveralTimes();
- for(iter=pointsOfViewEnd.begin();iter!=pointsOfViewEnd.end() and !isOK;iter++)
+ for(iter=pointsOfViewEnd.begin();iter!=pointsOfViewEnd.end() && !isOK;iter++)
isOK=(*iter)->isRepeatedUnpredictablySeveralTimes();
if(!isOK)
throw Exception("ComposedNode::checkLinkPossibility : Request for cross protocol link impossible.");
{
}
-void ComposedNode::getDelegateOf(InPort * & port, OutPort *initialStart, const std::list<ComposedNode *>& pointsOfView) throw(Exception)
+void ComposedNode::getDelegateOf(InPort * & port, OutPort *initialStart, const std::list<ComposedNode *>& pointsOfView) throw(YACS::Exception)
{
}
-void ComposedNode::getDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView) throw(Exception)
+void ComposedNode::getDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView) throw(YACS::Exception)
{
}
-void ComposedNode::releaseDelegateOf(InPort * & port, OutPort *initialStart, const std::list<ComposedNode *>& pointsOfView) throw(Exception)
+void ComposedNode::releaseDelegateOf(InPort * & port, OutPort *initialStart, const std::list<ComposedNode *>& pointsOfView) throw(YACS::Exception)
{
}
-void ComposedNode::releaseDelegateOf(OutPort *portDwn, OutPort *portUp, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView) throw(Exception)
+void ComposedNode::releaseDelegateOf(OutPort *portDwn, OutPort *portUp, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView) throw(YACS::Exception)
{
}
void ComposedNode::loaded()
{
}
+void ComposedNode::connected()
+{
+}
void ComposedNode::accept(Visitor *visitor)
{
DEBTRACE("ComposedNode::edUpdateState(): " << _state << " " << _modified);
YACS::StatesForNode state=YACS::READY;
+ try
+ {
+ checkBasicConsistency();
+ _errorDetails="";
+ }
+ catch(Exception& e)
+ {
+ state=YACS::INVALID;
+ _errorDetails=e.what();
+ }
+ DEBTRACE("ComposedNode::edUpdateState: " << _errorDetails);
+
//update children if needed
list<Node *> constituents=edGetDirectDescendants();
for(list<Node *>::iterator iter=constituents.begin(); iter!=constituents.end(); iter++)
{
DEBTRACE("ComposedNode::getErrorReport: " << getName() << " " << _state);
YACS::StatesForNode effectiveState=getEffectiveState();
- if(effectiveState == YACS::READY || effectiveState == YACS::DONE)
+
+ if(effectiveState != YACS::INVALID && effectiveState != YACS::ERROR && effectiveState != YACS::FAILED)
return "";
std::string report="<error node= " + getName();
+void ComposedNode::checkBasicConsistency() const throw(YACS::Exception)
+{
+ DEBTRACE("ComposedNode::checkBasicConsistency");
+ std::list<InputPort *>::const_iterator iter;
+ std::list<InputPort *> inports=getLocalInputPorts();
+ for(iter=inports.begin();iter!=inports.end();iter++)
+ (*iter)->checkBasicConsistency();
+}
+
+//! Stop all pending activities of the composed node
+/*!
+ * This method should be called when a Proc is finished and must be deleted from the YACS server
+ */
+void ComposedNode::shutdown(int level)
+{
+ if(level==0)return;
+ DEBTRACE("ComposedNode::shutdown");
+ list<Node *> nodes=edGetDirectDescendants();
+ for(list<Node *>::iterator iter=nodes.begin();iter!=nodes.end();iter++)
+ (*iter)->shutdown(level);
+}
+
+//! Clean the composed node in case of not clean exit
+/*!
+ * This method should be called on a control-c or sigterm
+ */
+void ComposedNode::cleanNodes()
+{
+ DEBTRACE("ComposedNode::cleanNodes");
+ list<Node *> nodes=edGetDirectDescendants();
+ for(list<Node *>::iterator iter=nodes.begin();iter!=nodes.end();iter++)
+ (*iter)->cleanNodes();
+}
+
+//! Reset the state of the node and its children depending on the parameter level
+void ComposedNode::resetState(int level)
+{
+ if(level==0)return;
+
+ DEBTRACE("ComposedNode::resetState " << level << "," << _state);
+ if( _state==YACS::ERROR || _state==YACS::FAILED || _state==YACS::ACTIVATED )
+ {
+ Node::resetState(level);
+ std::list<Node *> nodes=edGetDirectDescendants();
+ for(std::list<Node *>::iterator iter=nodes.begin();iter!=nodes.end();iter++)
+ (*iter)->resetState(level);
+ }
+}