#include <iostream>
#include <unistd.h>
#include <stdio.h>
+#include <errno.h>
#include "OpUtil.hxx"
#include "DataFlowBase_SwitchNode.hxx"
#include "DataFlowBase_EndOfSwitchNode.hxx"
-#include "DataFlowExecutor_OutNode.hxx"
+#include "DataFlowExecutor_DataFlow.hxx"
+#include "DataFlowEditor_DataFlow.hxx" // GraphEditor package must be built BEFORE
static void InitInNode( int &_RewindStack ,
SUPERV::ControlState &_ControlState ,
ORB ) ;
SetDebug( ORB , Graph_prof_debug , Graph_fdebug ) ;
+ _Loading = false ;
_ComputingNode = NULL ;
_FactoryNode = NULL ;
_InLineNode = NULL ;
_FactoryNode->Component()->ping() ;
}
catch( ... ) {
- cdebug << "InNode::Ping() catched" << endl ;
+ cdebug << "InNode::Ping() ERROR catched" << endl ;
State( GraphExecutor::ErroredState ) ;
_OutNode->State( GraphExecutor::ErroredState ) ;
RetVal = false ;
bool GraphExecutor::InNode::Suspend() {
cdebug_in << "GraphExecutor::InNode::Suspend " << Name() << " " << ThreadNo()
- << endl;
+ << " " << Automaton()->StateName( State() ) << endl;
bool RetVal = false ;
if ( IsDone() ) {
//If loop we need to suspend also ControlState( SUPERV::VoidState ) ;
else if ( IsRunning() ) {
ControlState( SUPERV::ToSuspendState ) ;
if ( IsFactoryNode() || IsComputingNode() ) {
- if ( !CORBA::is_nil( Component() ) ) {
- try {
- RetVal = Component()->Suspend_impl() ;
- }
- catch( ... ) {
- cdebug << "InNode::Suspend() catched" << endl ;
- State( GraphExecutor::ErroredState ) ;
- _OutNode->State( GraphExecutor::ErroredState ) ;
- RetVal = false ;
- }
- if ( RetVal ) {
- if ( IsRunning() ) {
- cdebug << pthread_self() << "GraphExecutor::InNode::Suspend_impl " << Name()
- << " --> thread" << ThreadNo() << " SuspendEvent " << endl;
- SendEvent( GraphExecutor::SuspendEvent ) ;
- cdebug << pthread_self() << "GraphExecutor::InNode::Suspended_impl in Container"
- << Name() << " --> thread" << ThreadNo() << endl;
- }
- else if ( IsDone() ) {
- ControlState( SUPERV::VoidState ) ;
- RetVal = false ; // Too late ...
+// We have to suspend in the container of that node
+ int TrySuspend = 10 ;
+ while ( TrySuspend ) {
+ if ( !CORBA::is_nil( Component() ) ) {
+// We can call that component
+ try {
+ RetVal = Component()->Suspend_impl() ;
+ }
+ catch( ... ) {
+ cdebug << "InNode::Suspend() ERROR catched" << endl ;
+ State( GraphExecutor::ErroredState ) ;
+ _OutNode->State( GraphExecutor::ErroredState ) ;
+ RetVal = false ;
+ TrySuspend = 1 ;
+ }
+ cdebug << "Component()->Suspend_impl() returns status " << RetVal << endl ;
+ if ( RetVal ) {
+ if ( IsRunning() ) {
+ cdebug << pthread_self() << "GraphExecutor::InNode::Suspend_impl " << Name()
+ << " --> thread" << ThreadNo() << " SuspendEvent " << endl;
+ SendEvent( GraphExecutor::SuspendEvent ) ;
+ cdebug << pthread_self() << "GraphExecutor::InNode::Suspended_impl in Container"
+ << Name() << " --> thread" << ThreadNo() << endl;
+ TrySuspend = 1 ;
+ }
+ else if ( IsDone() ) {
+ ControlState( SUPERV::VoidState ) ;
+ RetVal = false ; // Too late ...
+ TrySuspend = 1 ;
+ }
+ else {
+ cdebug << "InNode::Suspend component Suspended and !IsDone and !IsRunning !"
+ << endl ;
+ MESSAGE("InNode::Suspend component Suspended and !IsDone and !IsRunning !") ;
+ TrySuspend = 1 ;
+ }
}
else {
- cdebug << "component Suspended and !IsDone and !IsRunning !"
+// Suspend in the Container failed : it is always false if it is a Python Container
+ cdebug << "InNode::Suspend cannot Suspend component ! Python Component ?"
<< endl ;
+ if ( TrySuspend == 1 ) {
+ if ( IsSuspended() ) {
+ RetVal = true ;
+ }
+ else {
+ RetVal = false ;
+ }
+ }
+ }
+ }
+ else {
+ cdebug << "InNode::Suspend with nilComponent while RunningState !. Loading Component ?"
+ << endl ;
+// Wait for the end of loading of the component
+ while ( IsLoading() ) {
+ sleep( 1 ) ;
+ }
+ if ( TrySuspend == 1 ) {
+ if ( IsSuspended() ) {
+ RetVal = true ;
+ }
+ else {
+ RetVal = false ;
+ }
}
}
+ TrySuspend -= 1 ;
+ if ( TrySuspend ) {
+ sleep( 1 ) ;
+ }
}
- else {
- cdebug << "Suspend cannot Suspend component !" << endl ;
- RetVal = false ;
+ }
+ else if ( IsMacroNode() ) {
+// It should be like that but it is not completely implemented
+ GraphBase::Graph * aGraph = (GraphBase::Graph * ) GraphMacroNode()->CoupledNode() ;
+ RetVal = aGraph->GraphEditor()->Executor()->Suspend() ;
+ if ( RetVal ) {
+ State( GraphExecutor::SuspendedState ) ;
}
}
else {
- cdebug << "Suspend with nilComponent while RunningState !" << endl ;
- RetVal = false ;
+// Now we can suspend an InLineNode with the handler of the SuperVision Container
+ if ( pthread_kill( _OutNode->MainThreadId() , SIGUSR2 ) == -1 ) {
+ perror("Suspend pthread_kill error") ;
+ State( GraphExecutor::ErroredState ) ;
+ _OutNode->State( GraphExecutor::ErroredState ) ;
+ RetVal = false ;
+ }
+ else {
+ RetVal = true ;
+ }
+ if ( RetVal ) {
+ if ( IsRunning() ) {
+ cdebug << pthread_self() << "GraphExecutor::InNode::Suspend " << Name()
+ << " --> thread" << ThreadNo() << " SuspendEvent " << endl;
+ SendEvent( GraphExecutor::SuspendEvent ) ;
+ cdebug << pthread_self() << "GraphExecutor::InNode::Suspended in SuperVision Container"
+ << Name() << " --> thread" << ThreadNo() << endl;
+ }
+ else if ( IsDone() ) {
+ ControlState( SUPERV::VoidState ) ;
+ RetVal = false ; // Too late ...
+ }
+ else {
+ cdebug << "component Suspended and !IsDone and !IsRunning !"
+ << endl ;
+ }
+ }
}
}
else {
- cdebug << "Suspend and !IsDone and !IsRunning and !IsWaiting ?"
- << endl ;
+ cdebug << "Suspend and IsDone " << IsDone() << " and IsRunning " << IsRunning()
+ << " and IsWaiting " << IsWaiting() << " and IsReady " << IsReady()
+ << " ?" << endl ;
RetVal = false ;
}
cdebug_out << "GraphExecutor::InNode::Suspend " << RetVal << " "
bool GraphExecutor::InNode::Kill() {
cdebug_in << "GraphExecutor::InNode::Kill " << Name() << " " << ThreadNo() << " "
<< Automaton()->StateName( State() ) << " Threads " << _OutNode->Threads()
- << " SuspendedThreads " << _OutNode->SuspendedThreads() << endl;
+ << " SuspendedThreads " << _OutNode->SuspendedThreads()
+ << " EventQSize " << _OutNode->EventQSize() << endl;
bool RetVal ;
if ( IsDone() ) {
ControlState( SUPERV::ToKillState ) ; // if loop
else {
if ( IsRunning() ) {
if ( IsFactoryNode() || IsComputingNode() ) {
- if ( !CORBA::is_nil( Component() ) ) {
- try {
- RetVal = Component()->Kill_impl() ;
- }
- catch( ... ) {
- cdebug << "InNode::Suspend() catched" << endl ;
- State( GraphExecutor::ErroredState ) ;
- _OutNode->State( GraphExecutor::ErroredState ) ;
- RetVal = false ;
- }
- cdebug << "Component()->Kill_impl() returns status " << RetVal << endl ;
- RetVal = true ;
- if ( IsRunning() ) {
- cdebug << pthread_self() << "GraphExecutor::InNode::Kill_impl " << Name()
- << " --> thread" << ThreadNo() << " SuspendEvent " << endl;
- SendEvent( GraphExecutor::KillEvent ) ;
- cdebug << pthread_self() << "GraphExecutor::InNode::Killed_impl in Container"
- << Name() << " --> thread" << ThreadNo() << endl;
- }
- else if ( IsDone() ) {
- ControlState( SUPERV::VoidState ) ;
- RetVal = false ; // Too late ...
+// We have to suspend in the container of that node
+ int TryKill = 10 ;
+ while ( TryKill ) {
+ if ( !CORBA::is_nil( Component() ) ) {
+// We can call that component
+ try {
+ RetVal = Component()->Kill_impl() ;
+ }
+ catch( ... ) {
+ cdebug << "InNode::Kill_impl ERROR catched" << endl ;
+ State( GraphExecutor::ErroredState ) ;
+ _OutNode->State( GraphExecutor::ErroredState ) ;
+ RetVal = false ;
+ TryKill = 1 ;
+ }
+ cdebug << "Component()->Kill_impl() returns status " << RetVal << endl ;
+ if ( RetVal ) {
+ if ( IsRunning() ) {
+ cdebug << pthread_self() << "GraphExecutor::InNode::Kill_impl " << Name()
+ << " --> thread" << ThreadNo() << " KillEvent " << endl;
+ SendEvent( GraphExecutor::KillEvent ) ;
+ cdebug << pthread_self() << "GraphExecutor::InNode::Killed_impl in Container"
+ << Name() << " --> thread" << ThreadNo() << endl;
+ TryKill = 1 ;
+ }
+ else if ( IsDone() ) {
+ ControlState( SUPERV::VoidState ) ;
+ RetVal = false ; // Too late ...
+ TryKill = 1 ;
+ }
+ else {
+ cdebug << "Kill component Killed and !IsDone and !IsRunning !"
+ << endl ;
+ TryKill = 1 ;
+ }
+ }
+ else {
+// Kill in the Container failed : it is always false if it is a Python Container
+ cdebug << "InNode::Suspend cannot Kill component ! Python Component ?"
+ << endl ;
+ if ( TryKill == 1 ) {
+ if ( IsKilled() ) {
+ RetVal = true ;
+ }
+ else {
+ RetVal = false ;
+ }
+ }
+ }
}
else {
- cdebug << "component Killed and !IsDone and !IsRunning !"
+ cdebug << "InNode::Kill with nilComponent while RunningState !. Loading Component ?"
<< endl ;
+// Wait for the end of loading of the component
+ while ( IsLoading() ) {
+ sleep( 1 ) ;
+ }
+ if ( TryKill == 1 ) {
+ if ( IsKilled() ) {
+ RetVal = true ;
+ }
+ else {
+ RetVal = false ;
+ }
+ }
}
+ TryKill -= 1 ;
+ if ( TryKill ) {
+ sleep( 1 ) ;
+ }
}
- else {
- cdebug << "Kill with nilComponent cannot Kill component !" << endl ;
+ }
+ else if ( IsMacroNode() ) {
+// It should be like that but it is not completely implemented
+ GraphBase::Graph * aGraph = (GraphBase::Graph * ) GraphMacroNode()->CoupledNode() ;
+ RetVal = aGraph->GraphEditor()->Executor()->Kill() ;
+ if ( RetVal ) {
+ State( GraphExecutor::KilledState ) ;
+ }
+ }
+ else {
+//PAL6886
+// Now we can kill an InLineNode with the handler of the SuperVision Container
+ cdebug << pthread_self() << "Kill of InLineNode " << Name() << " MainThreadId "
+ << _OutNode->MainThreadId() << " :" << endl ;
+ MESSAGE( pthread_self() << "Kill of InLineNode " << Name() << " MainThreadId "
+ << _OutNode->MainThreadId() << " :" ) ;
+ if ( pthread_kill( _OutNode->MainThreadId() , SIGINT ) == -1 ) {
+// python signals run only in main thread ...
+ perror("Kill pthread_kill error") ;
+ State( GraphExecutor::ErroredState ) ;
+ _OutNode->State( GraphExecutor::ErroredState ) ;
RetVal = false ;
}
+ else {
+ cdebug << pthread_self() << "pthread_kill of InLineNode " << Name()
+ << " done. MainThreadId " << _OutNode->MainThreadId() << endl ;
+ MESSAGE( pthread_self() << "pthread_kill of InLineNode " << Name()
+ << " done. MainThreadId " << _OutNode->MainThreadId() ) ;
+ RetVal = true ;
+ }
}
}
else if ( IsSuspended() ) {
cdebug << pthread_self() << "GraphExecutor::InNode::Kill " << Name()
<< " --> thread" << ThreadNo() << " Resume()" << endl;
- Resume() ;
- RetVal = true ;
+ if ( Resume() ) {
+ RetVal = Kill() ;
+ }
+ else {
+ RetVal = false ;
+ }
}
else if ( IsWaiting() ) {
- RetVal = true ;
+ RetVal = false ;
}
else if ( IsReady() ) {
RetVal = true ;
}
else {
- cdebug << "Kill and !IsDone and !IsRunning and !IsWaiting and !IsReady ?"
- << endl ;
+ cdebug << "Kill and IsDone " << IsDone() << " and IsRunning " << IsRunning()
+ << " and IsWaiting " << IsWaiting() << " and IsReady " << IsReady()
+ << " ?" << endl ;
RetVal = false ;
}
}
}
- cdebug_out << "GraphExecutor::InNode::Kill" << Name() << " " << ThreadNo() << " "
+ cdebug_out << "GraphExecutor::InNode::Kill " << Name() << " " << ThreadNo() << " "
<< Automaton()->StateName( State() ) << " Threads " << _OutNode->Threads()
- << " SuspendedThreads " << _OutNode->SuspendedThreads() << endl ;
+ << " SuspendedThreads " << _OutNode->SuspendedThreads()
+ << " EventQSize " << _OutNode->EventQSize() << endl ;
return RetVal ;
}
RetVal = Component()->Stop_impl() ;
}
catch( ... ) {
- cdebug << "InNode::Stop() catched" << endl ;
+ cdebug << "InNode::Stop() ERROR catched" << endl ;
State( GraphExecutor::ErroredState ) ;
_OutNode->State( GraphExecutor::ErroredState ) ;
RetVal = false ;
}
}
else {
- cdebug << "Suspend cannot Suspend component !" << endl ;
+ cdebug << "Suspend cannot Stop component ! Python Component ?" << endl ;
RetVal = false ;
}
}
}
else if ( State() == GraphExecutor::SuspendedExecutingState ) {
if ( IsFactoryNode() || IsComputingNode() ) {
+ if ( pthread_mutex_lock( &_MutexWait ) ) {
+ perror("ResumeAction pthread_mutex_lock ") ;
+ exit( 0 ) ;
+ }
try {
RetVal = Component()->Resume_impl() ;
+ if ( RetVal ) {
+ State( GraphExecutor::ExecutingState ) ;
+ }
}
catch( ... ) {
- cdebug << "InNode::Resume() catched" << endl ;
+ cdebug << "InNode::Resume() ERROR catched" << endl ;
State( GraphExecutor::ErroredState ) ;
_OutNode->State( GraphExecutor::ErroredState ) ;
RetVal = false ;
}
+ if ( pthread_mutex_unlock( &_MutexWait ) ) {
+ perror("ResumeAction pthread_mutex_unlock ") ;
+ exit( 0 ) ;
+ }
+ }
+ else if ( IsMacroNode() ) {
+ cdebug << "Suspend of MacroNode not yet implemented ? Trying" << endl ;
+ GraphBase::Graph * aGraph = (GraphBase::Graph * ) GraphMacroNode()->CoupledNode() ;
+ RetVal = aGraph->GraphEditor()->Executor()->Resume() ;
+ if ( RetVal ) {
+ State( GraphExecutor::ExecutingState ) ;
+ }
+ }
+ else {
+// Resume of InLinePythonNode in the Node of the SuperVisionContainer ...
+ cdebug << ThreadNo() << "/" << pthread_self()
+ << "Resume of InLineNode pthread_kill" << Name() << endl ;
+ if ( pthread_kill( _OutNode->MainThreadId() , SIGCONT ) == -1 ) {
+ perror("Resume pthread_kill error") ;
+ State( GraphExecutor::ErroredState ) ;
+ _OutNode->State( GraphExecutor::ErroredState ) ;
+ RetVal = false ;
+ }
+ else {
+ State( GraphExecutor::ExecutingState ) ;
+ RetVal = true ;
+ }
}
}
else if ( State() == GraphExecutor::SuspendedSuccessedState ) {
}
}
#endif
- cdebug_out << "GraphExecutor::InNode::Resume " << RetVal << endl ;
+ cdebug_out << "GraphExecutor::InNode::Resume " << Name() << " " << RetVal << " "
+ << Automaton()->StateName( State() ) << endl ;
return RetVal ;
}
if ( aState == GraphExecutor::SuspendedReadyState ||
aState == GraphExecutor::SuspendedExecutingState ||
aState == GraphExecutor::SuspendedSuccessedState ||
- aState == GraphExecutor::SuspendedErroredState )
+ aState == GraphExecutor::SuspendedErroredState ||
+ aState == GraphExecutor::SuspendedState )
aret = true ;
// cdebug_out << "GraphExecutor::InNode::IsSuspended" << endl ;
return aret ;
<< " " << Automaton()->StateName( _currentState )
<< " pthread_cond_wait _RunningWait " << Name() << endl ;
while ( !RetVal && !IsDone() ) {
- cdebug << pthread_self() << " pthread_cond_wait RunningWait" << endl ;
+ cdebug << pthread_self() << " pthread_cond_wait RunningWait " << Name() << endl ;
pthread_cond_wait( &_RunningWait , &_MutexWait );
- RetVal = IsRunning() ;
+//We may have pthread_cond_waited but !IsRunning and !IsDone :
+ RetVal = IsRunning() || State() == GraphExecutor::SuccessedExecutingState ||
+ State() == GraphExecutor::ErroredExecutingState ;
cdebug << pthread_self() << " pthread_cond_waited RunningWait "
<< Automaton()->StateName( _currentState ) << " " << RetVal
- << endl ;
+ << " " << Name() << endl ;
}
cdebug_out << pthread_self() << " StateWait( Running ) " << RetVal
<< " " << Automaton()->StateName( _currentState )
}
bool GraphExecutor::InNode::RunningWait() {
-// cdebug_in << "GraphExecutor::InNode::RunningWait " << Name() << endl;
+ cdebug_in << pthread_self() << "GraphExecutor::InNode::RunningWait " << Name()
+ << " " << Automaton()->StateName( State() ) << endl;
bool aret ;
aret = StateWait( SUPERV::RunningState ) ;
+ cdebug_out << pthread_self() << "GraphExecutor::InNode::RunningWait " << Name()
+ << " " << Automaton()->StateName( State() ) << endl;
return aret ;
}
return aret ;
}
-void GraphExecutor::InNode::InitialState( GraphExecutor::OutNode * theOutNode )
+void GraphExecutor::InNode::InitialState()
{
cdebug_in << "GraphExecutor::InNode::InitialState Node " << Name() << endl;
- _OutNode = theOutNode ;
-
int i;
_ControlState = SUPERV::VoidState ;
CreateNewThread( false ) ;
CreateNewThreadIf( false ) ;
_SuspendSync = false ;
_ResumeSync = false ;
+ IsLoading( true ) ;
// ThreadNo( pthread_self() ) ;
ThreadNo( 0 ) ;