GSI Object Oriented Online Offline (Go4)  GO4-5.3.2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
TGo4HistogramServer.cxx
Go to the documentation of this file.
1 // $Id: TGo4HistogramServer.cxx 999 2013-07-25 11:58:59Z linev $
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 für 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 "TGo4HistogramServer.h"
15 
16 #include "Riostream.h"
17 #include "TFile.h"
18 
19 #include "TGo4Log.h"
20 #include "TGo4LockGuard.h"
21 #include "TGo4Socket.h"
22 #include "TGo4Buffer.h"
23 
26 #include "TGo4ObjConnectorTimer.h"
27 #include "TGo4CommandInvoker.h"
28 #include "TGo4AnalysisClientImp.h"
29 #include "TGo4AnalysisImp.h"
31 #include "TGo4Task.h"
32 #include "TGo4TaskManager.h"
33 #include "TGo4Thread.h"
34 #include "TGo4ThreadManager.h"
35 #include "TGo4ThreadHandler.h"
36 #include "TGo4TerminateException.h"
37 #include "TGo4TaskHandler.h"
38 
39 extern "C"
40 {
41 #include "f_his_hist.h"
42 }
43 
44 const char* TGo4HistogramServer::fgcCONTHREADNAME="HISTOSERV-";
45 const char* TGo4HistogramServer::fgcSHUTDOWNNAME="__HServLast__";
46 const char* TGo4HistogramServer::fgcCOMGETLIST="__OServNamesList__";
47 
48 const char* TGo4HistogramServer::fgcOBJTHREADNAME="OBJECTSERV-";
49 const UInt_t TGo4HistogramServer::fguTIMERPERIOD=200; // time in ms (20)
50 const Int_t TGo4HistogramServer::fgiOPENWAITCYCLES=100; // wait cycles (100)
51 const UInt_t TGo4HistogramServer::fguOPENWAITCYCLETIME=500; // time in ms (20)
52 const Int_t TGo4HistogramServer::fgiCLOSEWAITCYCLES=100; // wait cycles (100)
53 const UInt_t TGo4HistogramServer::fguCLOSEWAITCYCLETIME=500; // time in ms (20)
54 const Int_t TGo4HistogramServer::fgiCONNECTWAITCYCLES=20; // wait cycles (20)
55 const UInt_t TGo4HistogramServer::fguCONNECTWAITCYCLETIME=500; // time in ms (20)
56 
58  const char* servername,
59  const char* password,
60  Bool_t useobjectserver)
61 : fxAnalysisClient(owner), fxThreadHandler(0), fiServerPort(0),
62 fxTransport(0), fuObjectPort(0), fxConnectTransport(0), fxDisConnectTransport(0),
63 fuConnectPort(0),
64 fbConnectRequest(kFALSE), fbDisConnectRequest(kFALSE),
65 fbConnectIsOpen(kFALSE), fbConnectIsDone(kFALSE),fbConnectIsClose(kTRUE),
66 fxConnectorTimer(0),
67 fbUseObjectServer(useobjectserver)
68 {
69  TGo4CommandInvoker::Instance(); // make sure we have an invoker instance!
70  TGo4CommandInvoker::Register("HistogramServer", this);
72  fxTransport = new TGo4Socket(kFALSE); // raw transport in server mode for object server
73  // we use the histogram api instead of stccomm:
74  Int_t result=f_his_server((CHARS*) servername, (CHARS*) password, &fiServerPort);
75  if(result==COMM__SUCCESS) {
76  fxServerName = servername;
77  fxServerPass = password;
79  "Created Histogram server %s on port %d",
80  servername, fiServerPort);
81  }
82 else
83  {
84  //std::cout <<"ERROR on creation of Histogram server: "<< result << std::endl;
86  "ERROR %d on creation of Histogram server",
87  result);
88  }
89  // start connector thread:
90  const char* ownername;
92  {
95  ownername=fxAnalysisClient->GetName();
96  }
97  else
98  {
99  ownername="never-come-here";
100  }
101 
103  {
105  fxConnectorTimer->TurnOn();
106  }
107 if(fxThreadHandler)
108  {
109  // thread to serve gsi histogram api:
111  fxConnectorName += ownername;
112 
117  {
118 
119  // thread for root object server:
121  fxObjectThreadName += ownername;
122 
126  }
127  }
128  else
129  {
130  std::cerr <<" Histogram Server constructor FATAL ERROR: no threadmanager !!" << std::endl;
131  throw TGo4RuntimeException();
132  }
133 }
134 
136 : fxAnalysisClient(0), fxThreadHandler(0), fiServerPort(0),
137 fxTransport(0), fuObjectPort(0), fxConnectTransport(0), fxDisConnectTransport(0),
138 fcConnectHost(0), fuConnectPort(0),
139 fbConnectRequest(kFALSE), fbDisConnectRequest(kFALSE),
140 fbConnectIsOpen(kFALSE), fbConnectIsDone(kFALSE),fbConnectIsClose(kTRUE),
141 fbUseObjectServer(kFALSE)
142 {
143 TGo4CommandInvoker::Instance(); // make sure we have an invoker instance!
144 TGo4CommandInvoker::Register("HistogramServer", this);
145 }
146 
147 
149 {
150 // prepare stopped flag:
152 
153 // for clean shutdown, we have to connect one last time to get out of the wait:
154 INTS4 * pl_all =NULL;
155 s_his_head * ps_his_head=NULL;
156 INTS4 l_size=0;
157 f_his_gethis((char*)"localhost",
158  fiServerPort ,
159  (char*) fxServerName.Data(),
160  (char*) fxServerPass.Data(),
161  (char*) fgcSHUTDOWNNAME,
162  (s_his_head **)&ps_his_head,
163  (INTS4 **)&pl_all,
164  (INTS4 *)&l_size);
165 
166 if(fxThreadHandler)
167  {
171  {
173  // here we might connect last time to object server, to investigate!!
176  // this will cancel thread and delete runnable
177  }
178  }
179 delete fxConnectorTimer;
180 f_his_close(); // this will delete api server for histograms
181 
182 if(fxTransport)
183  {
184  fxTransport->Close(); // close go4 server socket for object server
185  delete fxTransport;
186  fxTransport=0;
187  }
188 
190 }
191 
193 {
194 Int_t rev=ConnectObjectClient();
195 if(rev<0) return rev;
196 if(rev==0 && CheckLogin())
197  {
199  } else {}
201 return rev;
202 }
203 
205 {
206 //
207 SetDisConnect(fxTransport); // timer shall do the Close() of negotiation
208 //TGo4Log::Debug(" HistogramServer: Waiting for timer Close() of client ... ");
209 WaitForClose(); // poll until timer has returned from close
210 //TGo4Log::Debug(" HistogramServer: Client connection closed. ");
211 }
212 
214 {
215 
216  static Bool_t isfirsttime=kTRUE;
217  // we delegate the actual TSocket open to the taskconnector timer:
218  SetConnect(fxTransport, "Server mode does not need hostname", 0); // for portscan
219  Int_t waitresult=WaitForOpen(); // wait for the server Open() call by timer
220  if(waitresult==-2) return waitresult; // return in termination mode
221  if(waitresult<0)
222  {
223  // open timeout
224  TGo4Log::Debug(" HistogramServer: Negotiation channel open TIMEOUT");
225  std::cerr <<" HistogramServer TIMEOUT ERROR opening socket connection !!! Terminating..." << std::endl;
227  }
228  Int_t count=0;
229  while(GetObjPort()==0)
230  {
233  {
234  TGo4Log::Debug(" HistogramServer: Negotiation port getter TIMEOUT");
235  std::cerr <<" HistogramServer TIMEOUT ERROR retrieving port number !!! Terminating..." << std::endl;
237  }
238  else if(task==0 || task->IsTerminating())
239  {
240  return -1;
241  }
242  else
243  {
245  ++count;
246  }
247  }
248 // TGo4Log::Debug(" HistogramServer is waiting to serve object client request on port %d ... ",
249 // fuObjectPort);
250  if(isfirsttime)
251  {
252  // only tell gui the first time the port number; performance!
254  "Object Server %s is waiting on port %d",
255  fxServerName.Data(),
256  fuObjectPort);
257  isfirsttime=kFALSE;
258  } else {}
259  Int_t connectwaitseconds=WaitForConnection(); // timer tells us by flag when the transport is opened
260  if(connectwaitseconds<0)
261  {
262  // case of threadmanager termination:
263  // connector runnable shall stop on return from ServeClient method
264  return connectwaitseconds;
265  }
266  else
267  {
268  // just proceed to the client server negotiations
269  }
270 
271 return 0;
272 }
273 
275 {
277  // check for basename:
278  //std::cout <<"##### check login " << std::endl;
279  char* recvchar=0;
280  recvchar=fxTransport->RecvRaw("dummy");
281  if(recvchar && !strcmp(recvchar,fxServerName.Data()))
282  {
283  fxTransport->Send(TGo4TaskHandler::Get_fgcOK()); // handshake to assure the client
284  }
285  else
286  {
287  //TGo4Analysis::Instance()->Message(2,
288  // "Object server connection attempt with wrong basename");
289  std::cerr <<"##### check login with wrong base" << std::endl;
292  return kFALSE;
293  }
294  // check for password:
295  recvchar=fxTransport->RecvRaw("dummy");
296  if(recvchar && !strcmp(recvchar,fxServerPass.Data()))
297  {
298  fxTransport->Send(TGo4TaskHandler::Get_fgcOK()); // handshake to assure the client
299  }
300  else
301  {
302 // TGo4Analysis::Instance()->Message(2,
303 // "Object server connection attempt with wrong password");
304  std::cerr <<"##### check login with wrong passwd" << std::endl;
307  return kFALSE;
308  }
309 return kTRUE;
310 }
311 
313 {
314  char objectname[TGo4ThreadManager::fguTEXTLENGTH];
315  char* recvchar=0;
316  // get object name
317  recvchar=fxTransport->RecvRaw("dummy");
318  if(recvchar==0)
319  {
320  std::cerr <<"-----Object server received null character for object request!"<< std::endl;
321  return kFALSE;
322  }
323  strncpy(objectname, recvchar,TGo4ThreadManager::fguTEXTLENGTH -1); // get the client name
324  //std::cout <<"-----Object server got request for object "<< objectname << std::endl;
325  // check here if object is requested or nameslist? :
326  TObject* object=0;
327  if(!strcmp(objectname,fgcCOMGETLIST))
328  {
329  // get analysis nameslist object
330  TGo4LockGuard mainguard; // protect creation of new nameslist
332  object=fxAnalysis->GetNamesList();
333  //std::cout <<"---------Retrieving nameslist" << std::endl;
334  }
335  else
336  {
337  // get object from analysis
338  object=fxAnalysis->GetObject(objectname);
339  //std::cout <<"---------Retrieving object" << std::endl;
340  }
341  return (SendObject(object));
342 }
343 
344 Bool_t TGo4HistogramServer::SendObject(TObject* object)
345 {
346 
347  Bool_t retval=kTRUE;
348  // stream object into TBuffer:
349  TBuffer* rootbuffer=0;
350  if(object!=0)
351  {
352  fxTransport->Send(TGo4TaskHandler::Get_fgcOK()); // let client know the object exists
353  TGo4LockGuard mainguard;
354  rootbuffer = new TGo4Buffer(TBuffer::kWrite);
355  TFile *filsav = gFile;
356  gFile = 0;
357  rootbuffer->WriteObject(object);
358  gFile = filsav;
359  fxTransport->SendBuffer(rootbuffer);
360  delete rootbuffer;
361  }
362  else
363  {
364  //std::cout <<"Error: object not found in analysis!" << std::endl;
366  retval=kFALSE;
367  }
368  char* recvchar=fxTransport->RecvRaw("dummy"); // get exit message
369  if(recvchar==0)
370  {
371  TGo4Log::Debug(" HistogramServer: null character on finishing object client channel ");
372  retval=kFALSE;
373  }
374  else if(strcmp(recvchar,TGo4TaskHandler::Get_fgcOK()))
375  {
376  TGo4Log::Debug(" HistogramServer: ERROR on finishing object client channel ");
377  retval=kFALSE;
378  }
379  else
380  {
381  //std::cout <<"##### send object is finished with ok." << std::endl;
382  }
383  return retval;
384 }
385 
386 
387 void TGo4HistogramServer::SetConnect(TGo4Socket * trans, const char* host, UInt_t port)
388 {
389  GO4TRACE((12,"TGo4HistogramServer::SetConnect(TGo4Socket *)",__LINE__, __FILE__));
390  fxConnectTransport = trans;
391  fcConnectHost = host;
392  fuConnectPort = port;
393  fbConnectRequest = kTRUE;
394 }
395 
397 {
398  GO4TRACE((12,"TGo4HistogramServer::SetDisConnect(TGo4Socket *)",__LINE__, __FILE__));
399  fxDisConnectTransport=trans;
400  fbDisConnectRequest=kTRUE;
401 }
402 
404 {
405  GO4TRACE((12,"TGo4HistogramServer::TimerConnect()",__LINE__, __FILE__));
406  Int_t rev=0;
410  {
411  GO4TRACE((15,"TGo4HistogramServer::TimerConnect()--DisConnectRequest",__LINE__, __FILE__));
412  if(fxDisConnectTransport!=0)
413  {
414  // we have a transport instance to disconnect
416  fbConnectIsClose=kTRUE;
417  fbDisConnectRequest=kFALSE; // we served the request, reset it
418  rev+=1;
419  }
420  else
421  {
422  // error, zero pointer given
423  rev+=32;
424  }
425  }
426  else
427  {
428  GO4TRACE((15,"TGo4HistogramServer::TimerConnect()--NO DisConnectRequest",__LINE__, __FILE__));
429  // no open request, continue
430  rev+=2;
431  }
432 
435  if(fbConnectRequest)
436  {
437  GO4TRACE((15,"TGo4HistogramServer::TimerConnect()--ConnectRequest",__LINE__, __FILE__));
438  // timer shall open a transport as server
439  if(fxConnectTransport!=0)
440  {
441  if(!fxConnectTransport->IsOpen())
442  {
443  GO4TRACE((10,"TGo4HistogramServer::TimerConnect()--transport is not open",__LINE__, __FILE__));
444  // transport is not open, so do it
445  fbConnectIsOpen=kTRUE; // tell connector thread that we try to open
446  //std::cout <<"TimerConnect: connect before open" << std::endl;
447  Int_t result=fxConnectTransport->Open(ConnectHost(), fuConnectPort, kTRUE);
448  if(result==0)
449  {
450  fbConnectIsDone=kTRUE; // tell connector thread we returned from open
451  fbConnectRequest=kFALSE; // we served the request, reset it
452  rev+=4;
453  }
454  else
455  {
456  rev=-4;
457  // open was not finished, we poll once again...
458  }
459  }
460  else
461  {
462  GO4TRACE((10,"TGo4HistogramServer::TimerConnect()--transport already open",__LINE__, __FILE__));
463  // transport was already open, do nothing
464  rev+=8;
465  }
466  } // if(fxConnectTransport!=0)
467  else
468  {
469  GO4TRACE((10,"TGo4HistogramServer::TimerConnect()--no transport specified",__LINE__, __FILE__));
470  rev+=64;
471  }
472  }
473  else
474  {
475  GO4TRACE((15,"TGo4HistogramServer::TimerConnect()--NO ConnectRequest",__LINE__, __FILE__));
476  // no open request, continue
477  rev+=16;
478  }
479 // std::cout <<"TimerConnect: before return" << std::endl;
480  return rev;
481 }
482 
483 
484 
486 
487 {
488  GO4TRACE((12,"TGo4HistogramServer::WaitForOpen()",__LINE__, __FILE__));
489  Int_t count=0;
490  while(!fbConnectIsOpen)
491  {
494  {
495  count = -1; // timeout
496  break;
497  }
498  else if(task==0 || task->IsTerminating())
499  {
500  // note: task==0 is case of shutdown of analysis server!
501  count = -2;
502  break;
503  }
504  else
505  {
507  ++count;
508  }
509  //std::cout << "*****WaitForOpen()"<< std::endl;
510  }
511  fbConnectIsOpen=kFALSE; // reset for next time
512  return count;
513 
514 }
515 
516 
518 
519 {
520  GO4TRACE((12,"TGo4HistogramServer::WaitForClose()",__LINE__, __FILE__));
521  Int_t count=0;
522  while(!fbConnectIsClose)
523  {
524  //std::cout <<"Waiting for close..." << std::endl;
526  {
527  //std::cout <<"reached closewaitcycles "<< count << std::endl;
528  count = -1; // timeout
529  break;
530  }
531  else
532  {
534  ++count;
535  }
536  //std::cout << "*****WaitForClose() "<<count<< std::endl;
537  }
538  fbConnectIsClose=kFALSE; // reset for next time
539  return count;
540 
541 }
542 
544 
545 {
546  GO4TRACE((12,"TGo4HistogramServer::WaitForConnection()",__LINE__, __FILE__));
547  Int_t count=0;
548  while(!fbConnectIsDone)
549  {
551  if(task==0 || task->IsTerminating())
552  {
553  // note: task==0 is case of shutdown of analysis server!
554  count = -2; // termination mode
555  break;
556  }
557  else
558  {
560  ++count;
561  }
562  //std::cout << "*****WaitForConnection()"<< std::endl;
563  }
564  fbConnectIsDone=kFALSE; // reset for next time
565  return count;
566 
567 }
568 
569 
571 {
572  if(fxTransport)
573  {
575  }
576  return fuObjectPort;
577 }
TGo4ThreadHandler * GetThreadHandler()
Definition: TGo4Slave.cxx:138
virtual Int_t Close(Option_t *opt="")
Definition: TGo4Socket.cxx:226
static UInt_t Get_fguPORTWAITTIME()
virtual Int_t Send(TObject *obj)
Definition: TGo4Socket.cxx:352
const char * ConnectHost() const
Int_t SendBuffer(TBuffer *buf)
Definition: TGo4Socket.cxx:236
static void UnRegister(TGo4CommandReceiver *p)
static const char * fgcCONTHREADNAME
#define COMM__SUCCESS
Definition: s_his_comm.h:27
TGo4ObjConnectorTimer * fxConnectorTimer
TGo4AnalysisClient * fxAnalysisClient
static const Int_t fgiCLOSEWAITCYCLES
static const char * Get_fgcERROR()
const char * ObjectThreadName() const
static void Sleep(UInt_t millisecs)
Definition: TGo4Thread.cxx:336
static const char * Get_fgcOK()
friend class TGo4HisConnectorRunnable
static void Register(const char *name, TGo4CommandReceiver *p)
virtual Int_t Open(const char *host, Int_t port, Bool_t keepservsock=kFALSE)
Definition: TGo4Socket.cxx:106
Bool_t NewThread(const char *name, TGo4Runnable *runnable)
static const Int_t fgiOPENWAITCYCLES
int INTS4
Definition: typedefs.h:28
TGo4ThreadHandler * fxThreadHandler
static const char * fgcSHUTDOWNNAME
static TGo4CommandInvoker * Instance()
void Message(Int_t prio, const char *text,...)
TGo4Task * GetTask()
Definition: TGo4TaskOwner.h:41
TGo4Analysis * GetAnalysis() const
static const UInt_t fguCONNECTWAITCYCLETIME
static const char * fgcOBJTHREADNAME
Bool_t Stop(const char *thname)
static const UInt_t fguTIMERPERIOD
const char * GetName() const
void SetDisConnect(TGo4Socket *trans)
Bool_t Start(const char *thname)
const char * ConnectorName() const
#define TGo4Buffer
Definition: TGo4Buffer.h:27
TGo4Socket * fxConnectTransport
#define GO4TRACE(X)
Definition: TGo4Log.h:26
INTS4 f_his_close()
Definition: f_his_hist.c:706
INTS4 f_his_gethis(const char *, int, const char *, const char *, const char *, s_his_head **, INTS4 **, INTS4 *)
TGo4AnalysisObjectNames * GetNamesList() const
virtual Int_t TimerConnect()
static const UInt_t fguOPENWAITCYCLETIME
Bool_t RemoveThread(const char *name)
static const Int_t fgiCONNECTWAITCYCLES
static const UInt_t fguCLOSEWAITCYCLETIME
TNamed * GetObject(const char *name, const char *folder=0)
Bool_t IsTerminating() const
static Int_t Get_fgiPORTWAITCYCLES()
Int_t GetPort() const
Definition: TGo4Socket.h:40
Bool_t IsOpen() const
Definition: TGo4Socket.h:36
char CHARS
Definition: typedefs.h:21
INTS4 f_his_server(CHARS *pc_base, CHARS *pc_access, INTS4 *pl_port)
Definition: f_his_hist.c:418
static const char * fgcCOMGETLIST
static TGo4Analysis * Instance()
virtual char * RecvRaw(const char *name=0)
Definition: TGo4Socket.cxx:421
TGo4Socket * fxDisConnectTransport
Bool_t SendObject(TObject *obj)
void SetConnect(TGo4Socket *trans, const char *host, UInt_t port)
static void Debug(const char *text,...)
Definition: TGo4Log.cxx:270