GSI Object Oriented Online Offline (Go4)  GO4-6.3.0
TGo4CommandRunnable.cxx
Go to the documentation of this file.
1 // $Id$
2 //-----------------------------------------------------------------------
3 // The GSI Online Offline Object Oriented (Go4) Project
4 // Experiment Data Processing at EE department, GSI
5 //-----------------------------------------------------------------------
6 // Copyright (C) 2000- GSI Helmholtzzentrum fuer Schwerionenforschung GmbH
7 // Planckstr. 1, 64291 Darmstadt, Germany
8 // Contact: http://go4.gsi.de
9 //-----------------------------------------------------------------------
10 // This software can be used under the license agreements as stated
11 // in Go4License.txt file which is part of the distribution.
12 //-----------------------------------------------------------------------
13 
14 #include "TGo4CommandRunnable.h"
15 
16 #include <sstream>
17 #include <iostream>
18 
19 #include "TGo4Log.h"
20 #include "TGo4Thread.h"
21 #include "TGo4BufferQueue.h"
22 #include "TGo4Socket.h"
24 #include "TGo4CommandInvoker.h"
25 #include "TGo4TaskHandler.h"
27 #include "TGo4ClientTask.h"
28 #include "TGo4ComQuit.h"
29 
30 
32  TGo4TaskHandler *hand, Bool_t receivermode) :
33  TGo4TaskHandlerRunnable(name,man,hand,receivermode)
34 {
38 }
39 
40 
42 {
43 }
44 
45 Int_t TGo4CommandRunnable::Run(void *ptr)
46 {
47  if(!CheckTransportOpen()) return 0;
48  if(fbReceiverMode)
49  {
50  // wait for something from socket
51  Int_t rev=fxTransport->ReceiveBuffer();
52  if(rev >= 0)
53  {
54  TBuffer *buffer = const_cast<TBuffer *> (fxTransport->GetBuffer());
55  Int_t val = 0;
56  if(CheckStopBuffer(buffer,&val)) return 0; // stop for disconnect mode
57  if(val >= 0)
58  {
59  fxTransport->Send(TGo4TaskHandler::Get_fgcOK()); //acknowledge before execute
60  TGo4Task* cli = dynamic_cast<TGo4Task*>(fxManager);
61  // we have a direct command, execute this here:
62  TGo4ComQuit* qcommand = nullptr;
64  // test here for different command values
65  switch(comvalue)
66  {
67  case kComQuit:
69  fxManager->SetBeingQuit(kTRUE); // flag for the application that we expect to be quit soon
70  TGo4Log::Debug(" Command runnable executing direct command QUIT... ");
71  //cli->Quit();
72  // note: need execution of quit in local command thread,
73  // because we are inside thread to be cancelled...
74  qcommand = new TGo4ComQuit;
75  cli->SubmitLocalCommand(qcommand);
76  break;
77  case kComKillMain:
79  TGo4Log::Debug(" Command runnable executing direct command KILL MAIN... ");
80  cli->KillMain();
81  break;
82  case kComRestartMain:
84  TGo4Log::Debug(" Command runnable executing direct command RESTART MAIN... ");
85  cli->RestartMain();
86  break;
87  case kComCloseInput:
88  // this case should be treated by CheckStopBuffer, so:
89  TGo4Log::Debug("NEVER COME HERE: Command runnable has direct command CLOSE INPUT");
90  // TGo4Log::Debug(" Command runnable executing direct command CLOSE INPUT... ");
91  // GetThread()->Stop();
92  break;
93  case kComAbortTask:
94  TGo4Log::Debug("Command runnable kComAbortTask");
95  break;
96  default:
97  TGo4Log::Debug(" Command runnable direct command value %d UNKNOWN!", comvalue);
98  break;
99 
100  }
101  // end direct command section
102  } // if(val>0)
103  else
104  {
105  fxBufferQueue->AddBuffer(buffer, kTRUE);
107  } // end if((val>0))
108  } // if(rev >= 0)
109  else
110  {
112  {
113  // TSocket error because of window resize, do not abort!
114  TGo4Log::Debug(" %s: caught SIGWINCH ", GetName());
116  }
117  else if(fxManager->IsTerminating())
118  {
119  TGo4Log::Debug("Receive Error in %s during threadmanager termination. Ignored.",GetName());
120  GetThread()->Stop();
121  }
122  else
123  {
124  if(fxTaskHandler->IsClientMode()) RedirectIO(); // only suppress output for analysis clients (correct shutdown if run in QtWindow!)
125  TGo4Log::Debug("Receive Error in %s, aborting taskhandler...",GetName());
126  throw TGo4TaskHandlerAbortException(this);
127  }
128  } // end if (rev >= 0)
129  } //end if(fbReceiverMode)
130  else
131  {
132  // get next command from queue or wait for it
133  TBuffer *buf= fxBufferQueue->WaitBuffer();
134  if (buf)
135  // check if there is really an object from queue
136  {
137  Bool_t stopmode=CheckStopBuffer(buf);
138  // send over inter task transport
139  fxTransport->SendBuffer(buf);
141  if(stopmode) return 0; // no handshake after stop buffer
142  char *revchar = fxTransport->RecvRaw("dummy"); // wait for o.k. string
143  if(!revchar)
144  {
145  // error, received garbage
147  //if (TGo4SocketSignalHandler::fgxLastSignal == kSigWindowChanged)
148  {
149  // TSocket error because of window resize, do not abort!
150  TGo4Log::Debug(" %s: caught SIGWINCH ",GetName());
152  //TGo4SocketSignalHandler::fgxLastSignal = (ESignals) 0;
153  }
154  else
155  {
156  //RedirectIO(); // do not redirect output for command sender, will not terminate!
157  TGo4Log::Debug(" !!!Connection Error -1 in CommandRunnable ''%s''!!!",GetName());
158  throw TGo4TaskHandlerAbortException(this);
159  }
160  }
161  else
162  {
163  // we received something, proceed
164  }
165 
166  if(!strcmp(revchar,TGo4TaskHandler::Get_fgcOK()) )
167  {
168  // fine, command has reached its destination, anyhow..
169  }
170  else if(!strcmp(revchar,TGo4TaskHandler::Get_fgcERROR()))
171  // client signals any kind of error with last command
172  {
173  // client signals any kind of error == 0 with last command
174  TGo4Log::Debug(" CommandRunnable ''%s'' received command error string!!!",GetName());
175  }
176  else
177  {
178  // error, received something else
179  TGo4Log::Debug(" !!!Connection Error -3 in CommandRunnable ''%s''!!!",GetName());
180  //throw TGo4TerminateException(this);
181  }
182  }
183  else
184  {
185  if(!GetThread()->IsRunning())
186  {
187  // when gui client is disconnected by slave server itself
188  // (server shutdown from other gui), we have to react on Queue wakeup
189  // in command queue from the TGo4TaskHandler::StopTransportThreads
190  return 0;
191  }
192  // do nothing, return for next wait
193  }
194  } // end else if(fbReceiverMode)
195  return 0;
196 }
197 
198 
200 {
201  // note: this method is only called in case of aborting,
202  // so we do not care about our memory leak...JA
203  std::ostringstream* strout = new std::ostringstream;
204  //std::streambuf* ccc_buffer = std::cout.rdbuf(); // would need it to recover std::cout
205  std::cout.rdbuf(strout->rdbuf());
206  std::ostringstream* strerr = new std::ostringstream;
207  //std::streambuf* std::cerr_buffer = std::cerr.rdbuf(); // would need to recover std::cerr later
208  std::cerr.rdbuf(strerr->rdbuf());
209 }
TGo4Thread * GetThread() const
Definition: TGo4Runnable.h:44
Go4EmergencyCommand_t
Bool_t SubmitLocalCommand(TGo4Command *com)
Definition: TGo4Task.cxx:508
TGo4ThreadManager * fxManager
Definition: TGo4Runnable.h:70
Bool_t CheckStopBuffer(TBuffer *buf, Int_t *result=nullptr)
virtual Int_t Send(TObject *obj)
Definition: TGo4Socket.cxx:332
Int_t SendBuffer(TBuffer *buf)
Definition: TGo4Socket.cxx:220
Bool_t Stop()
Definition: TGo4Thread.cxx:287
static const char * Get_fgcERROR()
static const char * Get_fgcOK()
TGo4Socket * GetCommandTransport() const
virtual void RestartMain()
Definition: TGo4Task.cxx:125
static void SetLastSignal(Int_t v=0)
TBuffer * WaitBuffer()
Bool_t IsClientMode() const
static void Debug(const char *text,...) GO4_PRINTF_ARGS
Definition: TGo4Log.cxx:281
Int_t Run(void *ptr) override
Int_t ReceiveBuffer()
Definition: TGo4Socket.cxx:273
virtual char * RecvRaw(const char *name=nullptr)
Definition: TGo4Socket.cxx:401
static TGo4CommandInvoker * Instance()
TGo4CommandInvoker * fxInvoker
void AddBuffer(TBuffer *buffer, Bool_t clone=kFALSE)
TGo4Queue * GetCommandQueue() const
Go4CommandMode_t GetRole()
virtual void KillMain()
Definition: TGo4Task.cxx:120
void SetBeingQuit(Bool_t on)
Bool_t IsTerminating() const
void FreeBuffer(TBuffer *buffer)
const TBuffer * GetBuffer() const
Definition: TGo4Socket.h:59