Salome HOME
Management of loading of a Component in a Container for Kill, Suspend because it...
authorrahuel <rahuel@opencascade.com>
Wed, 8 Dec 2004 13:29:58 +0000 (13:29 +0000)
committerrahuel <rahuel@opencascade.com>
Wed, 8 Dec 2004 13:29:58 +0000 (13:29 +0000)
Kill, Suspend and Resume are now possible for InLineNodes.
But they do not run for MacroNodes : developpement is necessary.

src/GraphExecutor/DataFlowExecutor_InNode.cxx

index 485e76d7ecfe2ca7f876ef95fcdc7a7d01add652..32e7cd552cab74c8139e85cd14117598f5421cbb 100644 (file)
@@ -32,6 +32,7 @@ using namespace std;
 #include <iostream>
 #include <unistd.h>
 #include <stdio.h>
+#include <errno.h>
 
 #include "OpUtil.hxx"
 
@@ -47,7 +48,8 @@ using namespace std;
 #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 ,
@@ -218,6 +220,7 @@ GraphExecutor::InNode::InNode( CORBA::ORB_ptr ORB,
               ORB ) ;
   SetDebug( ORB , Graph_prof_debug , Graph_fdebug ) ;
 
+  _Loading = false ;
   _ComputingNode = NULL ;
   _FactoryNode = NULL ;
   _InLineNode = NULL ;
@@ -431,7 +434,7 @@ bool GraphExecutor::InNode::Ping() {
           _FactoryNode->Component()->ping() ;
        }
         catch( ... ) {
-          cdebug << "InNode::Ping() catched" << endl ;
+          cdebug << "InNode::Ping() ERROR catched" << endl ;
           State( GraphExecutor::ErroredState ) ;
           _OutNode->State( GraphExecutor::ErroredState ) ;
           RetVal = false ;
@@ -458,7 +461,7 @@ void GraphExecutor::InNode::ExitThread() {
 
 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 ) ;
@@ -476,47 +479,121 @@ bool GraphExecutor::InNode::Suspend() {
   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 << " "
@@ -539,7 +616,8 @@ bool GraphExecutor::InNode::ContainerKill() {
 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
@@ -559,62 +637,137 @@ bool GraphExecutor::InNode::Kill() {
     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 ;
 }
 
@@ -674,7 +827,7 @@ bool GraphExecutor::InNode::Stop() {
               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 ;
@@ -694,7 +847,7 @@ bool GraphExecutor::InNode::Stop() {
            }
          }
           else {
-            cdebug << "Suspend cannot Suspend component !" << endl ;
+            cdebug << "Suspend cannot Stop component ! Python Component ?" << endl ;
             RetVal = false ;
          }
        }
@@ -752,15 +905,49 @@ bool GraphExecutor::InNode::Resume() {
     }
     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 ) {
@@ -853,7 +1040,8 @@ bool GraphExecutor::InNode::Resume() {
     }
   }
 #endif
-  cdebug_out << "GraphExecutor::InNode::Resume " << RetVal << endl ;
+  cdebug_out << "GraphExecutor::InNode::Resume " << Name() << " " << RetVal << " "
+             << Automaton()->StateName( State() ) << endl ;
   return RetVal ;
 }
 
@@ -957,7 +1145,8 @@ bool GraphExecutor::InNode::IsSuspended() {
   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 ;
@@ -1020,12 +1209,14 @@ bool GraphExecutor::InNode::StateWait( SUPERV::GraphState aState ) {
               << " " << 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 )
@@ -1089,9 +1280,12 @@ bool GraphExecutor::InNode::ReadyWait() {
 }
 
 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 ;
 }
 
@@ -1109,18 +1303,17 @@ bool GraphExecutor::InNode::SuspendedWait() {
   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 ) ;