GSI Object Oriented Online Offline (Go4) GO4-6.4.0
Loading...
Searching...
No Matches
TGo4HistogramServer.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 "TGo4HistogramServer.h"
15
16#include <iostream>
17#include "TFile.h"
18#include "TBufferFile.h"
19
20#include "TGo4Log.h"
21#include "TGo4LockGuard.h"
22#include "TGo4Socket.h"
23
27#include "TGo4CommandInvoker.h"
29#include "TGo4AnalysisImp.h"
31#include "TGo4Task.h"
32#include "TGo4Thread.h"
33#include "TGo4ThreadManager.h"
34#include "TGo4ThreadHandler.h"
36#include "TGo4TaskHandler.h"
37
38extern "C" {
39 #include "f_his_hist.h"
40}
41
42const char *TGo4HistogramServer::fgcCONTHREADNAME = "HISTOSERV-";
43const char *TGo4HistogramServer::fgcSHUTDOWNNAME = "__HServLast__";
44const char *TGo4HistogramServer::fgcCOMGETLIST = "__OServNamesList__";
45
46const char *TGo4HistogramServer::fgcOBJTHREADNAME = "OBJECTSERV-";
47const UInt_t TGo4HistogramServer::fguTIMERPERIOD = 200; // time in ms (20)
48const Int_t TGo4HistogramServer::fgiOPENWAITCYCLES = 100; // wait cycles (100)
49const UInt_t TGo4HistogramServer::fguOPENWAITCYCLETIME = 500; // time in ms (20)
50const Int_t TGo4HistogramServer::fgiCLOSEWAITCYCLES = 100; // wait cycles (100)
51const UInt_t TGo4HistogramServer::fguCLOSEWAITCYCLETIME = 500; // time in ms (20)
52const Int_t TGo4HistogramServer::fgiCONNECTWAITCYCLES = 20; // wait cycles (20)
53const UInt_t TGo4HistogramServer::fguCONNECTWAITCYCLETIME = 500; // time in ms (20)
54
55TGo4HistogramServer::TGo4HistogramServer(TGo4AnalysisClient *owner, const char *servername, const char *password,
56 Bool_t useobjectserver)
57 : fxAnalysisClient(owner), fxThreadHandler(nullptr), fiServerPort(0), fxTransport(nullptr), fuObjectPort(0),
60 fxConnectorTimer(nullptr), fbUseObjectServer(useobjectserver)
61{
62 TGo4CommandInvoker::Instance(); // make sure we have an invoker instance!
63 TGo4CommandInvoker::Register("HistogramServer", this);
65 fxTransport = new TGo4Socket(kFALSE); // raw transport in server mode for object server
66 // we use the histogram api instead of stccomm:
67 Int_t result = f_his_server((CHARS *)servername, (CHARS *)password, &fiServerPort);
68 if (result == COMM__SUCCESS) {
69 fxServerName = servername;
70 fxServerPass = password;
71 TGo4Analysis::Instance()->Message(1, "Created Histogram server %s on port %d", servername, fiServerPort);
72 } else {
73 TGo4Analysis::Instance()->Message(3, "ERROR %d on creation of Histogram server", result);
74 }
75 // start connector thread:
76 const char *ownername;
77 if (fxAnalysisClient) {
78 fxThreadHandler = fxAnalysisClient->GetThreadHandler();
79 fxAnalysis = fxAnalysisClient->GetAnalysis();
80 ownername = fxAnalysisClient->GetName();
81 } else {
82 ownername = "never-come-here";
83 }
84
87 fxConnectorTimer->TurnOn();
88 }
89 if (fxThreadHandler) {
90 // thread to serve gsi histogram api:
92 fxConnectorName += ownername;
93
95 fxThreadHandler->NewThread(ConnectorName(), crun);
98
99 // thread for root object server:
101 fxObjectThreadName += ownername;
102
104 fxThreadHandler->NewThread(ObjectThreadName(), orun);
106 }
107 } else {
108 std::cerr << " Histogram Server constructor FATAL ERROR: no threadmanager !!" << std::endl;
109 throw TGo4RuntimeException();
110 }
111}
112
114 : fxAnalysisClient(nullptr), fxThreadHandler(nullptr), fiServerPort(0), fxTransport(nullptr), fuObjectPort(0), fxConnectTransport(nullptr),
117 fbUseObjectServer(kFALSE)
118{
119 TGo4CommandInvoker::Instance(); // make sure we have an invoker instance!
120 TGo4CommandInvoker::Register("HistogramServer", this);
121}
122
124{
125 // prepare stopped flag:
128
129 // for clean shutdown, we have to connect one last time to get out of the wait:
130 INTS4 *pl_all = nullptr;
131 s_his_head *ps_his_head = nullptr;
132 INTS4 l_size = 0;
133 f_his_gethis((char *)"localhost", fiServerPort, (char *)fxServerName.Data(), (char *)fxServerPass.Data(),
134 (char *)fgcSHUTDOWNNAME, (s_his_head **)&ps_his_head, &pl_all, &l_size);
135
136 if (fxThreadHandler) {
137 fxThreadHandler->RemoveThread(ConnectorName());
139 if (fbUseObjectServer) {
141 // here we might connect last time to object server, to investigate!!
143 fxThreadHandler->RemoveThread(ObjectThreadName());
144 // this will cancel thread and delete runnable
145 }
146 }
147 delete fxConnectorTimer;
148 f_his_close(); // this will delete api server for histograms
149
150 if (fxTransport) {
151 fxTransport->Close(); // close go4 server socket for object server
152 delete fxTransport;
153 fxTransport = nullptr;
154 }
155
157}
158
160{
161 Int_t rev = ConnectObjectClient();
162 if (rev < 0)
163 return rev;
164 if (rev == 0 && CheckLogin()) {
166 } else {
167 }
169 return rev;
170}
171
173{
174 //
175 SetDisConnect(fxTransport); // timer shall do the Close() of negotiation
176 // TGo4Log::Debug(" HistogramServer: Waiting for timer Close() of client ... ");
177 WaitForClose(); // poll until timer has returned from close
178 // TGo4Log::Debug(" HistogramServer: Client connection closed. ");
179}
180
182{
183
184 static Bool_t isfirsttime = kTRUE;
185 // we delegate the actual TSocket open to the taskconnector timer:
186 SetConnect(fxTransport, "Server mode does not need hostname", 0); // for portscan
187 Int_t waitresult = WaitForOpen(); // wait for the server Open() call by timer
188 if (waitresult == -2)
189 return waitresult; // return in termination mode
190 if (waitresult < 0) {
191 // open timeout
192 TGo4Log::Debug(" HistogramServer: Negotiation channel open TIMEOUT");
193 std::cerr << " HistogramServer TIMEOUT ERROR opening socket connection !!! Terminating..." << std::endl;
195 }
196 Int_t count = 0;
197 while (GetObjPort() == 0) {
198 TGo4Task *task = fxAnalysisClient->GetTask();
200 TGo4Log::Debug(" HistogramServer: Negotiation port getter TIMEOUT");
201 std::cerr << " HistogramServer TIMEOUT ERROR retrieving port number !!! Terminating..." << std::endl;
203 } else if (!task || task->IsTerminating()) {
204 return -1;
205 } else {
207 ++count;
208 }
209 }
210 // TGo4Log::Debug(" HistogramServer is waiting to serve object client request on port %d ... ",
211 // fuObjectPort);
212 if (isfirsttime) {
213 // only tell gui the first time the port number; performance!
214 TGo4Analysis::Instance()->Message(1, "Object Server %s is waiting on port %d", fxServerName.Data(), fuObjectPort);
215 isfirsttime = kFALSE;
216 } else {
217 }
218 Int_t connectwaitseconds = WaitForConnection(); // timer tells us by flag when the transport is opened
219 if (connectwaitseconds < 0) {
220 // case of threadmanager termination:
221 // connector runnable shall stop on return from ServeClient method
222 return connectwaitseconds;
223 } else {
224 // just proceed to the client server negotiations
225 }
226
227 return 0;
228}
229
231{
233 // check for basename:
234 const char *recvchar = fxTransport->RecvRaw("dummy");
235 if (recvchar && !strcmp(recvchar, fxServerName.Data())) {
236 fxTransport->Send(TGo4TaskHandler::Get_fgcOK()); // handshake to assure the client
237 } else {
238 // TGo4Analysis::Instance()->Message(2,
239 // "Object server connection attempt with wrong basename");
240 std::cerr << "##### check login with wrong base" << std::endl;
243 return kFALSE;
244 }
245 // check for password:
246 recvchar = fxTransport->RecvRaw("dummy");
247 if (recvchar && !strcmp(recvchar, fxServerPass.Data())) {
248 fxTransport->Send(TGo4TaskHandler::Get_fgcOK()); // handshake to assure the client
249 } else {
250 // TGo4Analysis::Instance()->Message(2,
251 // "Object server connection attempt with wrong password");
252 std::cerr << "##### check login with wrong passwd" << std::endl;
255 return kFALSE;
256 }
257 return kTRUE;
258}
259
261{
262 char objectname[TGo4ThreadManager::fguTEXTLENGTH];
263 // get object name
264 char *recvchar = fxTransport->RecvRaw("dummy");
265 if (!recvchar) {
266 std::cerr << "-----Object server received null character for object request!" << std::endl;
267 return kFALSE;
268 }
269 strncpy(objectname, recvchar, TGo4ThreadManager::fguTEXTLENGTH - 1); // get the client name
270 // check here if object is requested or nameslist? :
271 TObject *object = nullptr;
272 if (!strcmp(objectname, fgcCOMGETLIST)) {
273 // get analysis nameslist object
274 TGo4LockGuard mainguard; // protect creation of new nameslist
275 fxAnalysis->UpdateNamesList();
276 object = fxAnalysis->GetNamesList();
277 } else {
278 // get object from analysis
279 object = fxAnalysis->GetObject(objectname);
280 }
281 return SendObject(object);
282}
283
284Bool_t TGo4HistogramServer::SendObject(TObject *object)
285{
286 Bool_t retval = kTRUE;
287 // stream object into TBuffer:
288 TBuffer *rootbuffer = nullptr;
289 if (object) {
290 fxTransport->Send(TGo4TaskHandler::Get_fgcOK()); // let client know the object exists
291 TGo4LockGuard mainguard;
292 rootbuffer = new TBufferFile(TBuffer::kWrite);
293 TFile *filsav = gFile;
294 gFile = nullptr;
295 rootbuffer->WriteObject(object);
296 gFile = filsav;
297 fxTransport->SendBuffer(rootbuffer);
298 delete rootbuffer;
299 } else {
301 retval = kFALSE;
302 }
303 char *recvchar = fxTransport->RecvRaw("dummy"); // get exit message
304 if (!recvchar) {
305 TGo4Log::Debug(" HistogramServer: null character on finishing object client channel ");
306 retval = kFALSE;
307 } else if (strcmp(recvchar, TGo4TaskHandler::Get_fgcOK())) {
308 TGo4Log::Debug(" HistogramServer: ERROR on finishing object client channel ");
309 retval = kFALSE;
310 } else {
311 // send object is finished with ok
312 }
313 return retval;
314}
315
316void TGo4HistogramServer::SetConnect(TGo4Socket *trans, const char *host, UInt_t port)
317{
318 GO4TRACE((12, "TGo4HistogramServer::SetConnect(TGo4Socket *)", __LINE__, __FILE__));
319 fxConnectTransport = trans;
320 fcConnectHost = host;
321 fuConnectPort = port;
322 fbConnectRequest = kTRUE;
323}
324
326{
327 GO4TRACE((12, "TGo4HistogramServer::SetDisConnect(TGo4Socket *)", __LINE__, __FILE__));
328 fxDisConnectTransport = trans;
329 fbDisConnectRequest = kTRUE;
330}
331
333{
334 GO4TRACE((12, "TGo4HistogramServer::TimerConnect()", __LINE__, __FILE__));
335 Int_t rev = 0;
339 GO4TRACE((15, "TGo4HistogramServer::TimerConnect()--DisConnectRequest", __LINE__, __FILE__));
341 // we have a transport instance to disconnect
342 fxDisConnectTransport->Close();
343 fbConnectIsClose = kTRUE;
344 fbDisConnectRequest = kFALSE; // we served the request, reset it
345 rev += 1;
346 } else {
347 // error, zero pointer given
348 rev += 32;
349 }
350 } else
351 {
352 GO4TRACE((15, "TGo4HistogramServer::TimerConnect()--NO DisConnectRequest", __LINE__, __FILE__));
353 // no open request, continue
354 rev += 2;
355 }
356
359 if (fbConnectRequest) {
360 GO4TRACE((15, "TGo4HistogramServer::TimerConnect()--ConnectRequest", __LINE__, __FILE__));
361 // timer shall open a transport as server
362 if (fxConnectTransport) {
363 if (!fxConnectTransport->IsOpen()) {
364 GO4TRACE((10, "TGo4HistogramServer::TimerConnect()--transport is not open", __LINE__, __FILE__));
365 // transport is not open, so do it
366 fbConnectIsOpen = kTRUE; // tell connector thread that we try to open
367 Int_t result = fxConnectTransport->Open(ConnectHost(), fuConnectPort, kTRUE);
368 if (result == 0) {
369 fbConnectIsDone = kTRUE; // tell connector thread we returned from open
370 fbConnectRequest = kFALSE; // we served the request, reset it
371 rev += 4;
372 } else {
373 rev = -4;
374 // open was not finished, we poll once again...
375 }
376 } else {
377 GO4TRACE((10, "TGo4HistogramServer::TimerConnect()--transport already open", __LINE__, __FILE__));
378 // transport was already open, do nothing
379 rev += 8;
380 }
381 }
382 else {
383 GO4TRACE((10, "TGo4HistogramServer::TimerConnect()--no transport specified", __LINE__, __FILE__));
384 rev += 64;
385 }
386 }
387 else {
388 GO4TRACE((15, "TGo4HistogramServer::TimerConnect()--NO ConnectRequest", __LINE__, __FILE__));
389 // no open request, continue
390 rev += 16;
391 }
392 // std::cout <<"TimerConnect: before return" << std::endl;
393 return rev;
394}
395
397{
398 GO4TRACE((12, "TGo4HistogramServer::WaitForOpen()", __LINE__, __FILE__));
399 Int_t count = 0;
400 while (!fbConnectIsOpen) {
401 TGo4Task *task = fxAnalysisClient->GetTask();
403 count = -1; // timeout
404 break;
405 } else if (!task || task->IsTerminating()) {
406 // note: task == nullptr is case of shutdown of analysis server!
407 count = -2;
408 break;
409 } else {
411 ++count;
412 }
413 }
414 fbConnectIsOpen = kFALSE; // reset for next time
415 return count;
416}
417
419{
420 GO4TRACE((12, "TGo4HistogramServer::WaitForClose()", __LINE__, __FILE__));
421 Int_t count = 0;
422 while (!fbConnectIsClose) {
423 // Waiting for close...
425 count = -1; // timeout
426 break;
427 } else {
429 ++count;
430 }
431 }
432 fbConnectIsClose = kFALSE; // reset for next time
433 return count;
434}
435
437{
438 GO4TRACE((12, "TGo4HistogramServer::WaitForConnection()", __LINE__, __FILE__));
439 Int_t count = 0;
440 while (!fbConnectIsDone) {
441 TGo4Task *task = fxAnalysisClient->GetTask();
442 if (!task || task->IsTerminating()) {
443 // note: task == nullptr is case of shutdown of analysis server!
444 count = -2; // termination mode
445 break;
446 } else {
448 ++count;
449 }
450 }
451 fbConnectIsDone = kFALSE; // reset for next time
452 return count;
453}
454
456{
457 if (fxTransport) {
458 fuObjectPort = fxTransport->GetPort();
459 }
460 return fuObjectPort;
461}
#define TGo4LockGuard
#define GO4TRACE(X)
Definition TGo4Log.h:25
static TGo4Analysis * Instance()
return analysis instance
void Message(Int_t prio, const char *text,...)
Display a user message.
static TGo4CommandInvoker * Instance()
static void UnRegister(TGo4CommandReceiver *p)
static void Register(const char *name, TGo4CommandReceiver *p)
TGo4ObjConnectorTimer * fxConnectorTimer
timer responsible for the connection/disconnection of clients; independent of application control tim...
Bool_t fbConnectIsOpen
True if fxConnectTransport waits in server Open() call.
Bool_t fbDisConnectRequest
True if fxConnectTransport shall be Close() by Timer.
static const char * fgcSHUTDOWNNAME
This string is send as histogram name for termination connection.
TGo4Socket * fxConnectTransport
link to the next TaskHandler transport instance that shall be connected by the Object connector Timer...
TString fxServerPass
contains api server password
const char * ConnectorName() const
static const char * fgcCOMGETLIST
command string for object server nameslist request
Bool_t SendObject(TObject *obj)
Send object to the current object client.
void DisconnectObjectClient()
Terminate connection to current object client, keep waiting for the next one.
static const UInt_t fguCONNECTWAITCYCLETIME
Time for each connect wait cycle, in ms.
static const char * fgcOBJTHREADNAME
object server connector thread name
static const UInt_t fguOPENWAITCYCLETIME
Time for each open wait cycle, in ms.
Bool_t fbConnectIsDone
True if fxConnectTransport has returned from Open(), i.e.
TString fxServerName
contains api server name
TString fcConnectHost
hostname for timer connect
Bool_t CheckLogin()
Checks basename and passwd login of connected client.
friend class TGo4HisConnectorRunnable
Bool_t fbConnectRequest
True if fxConnectTransport shall be Open() by Timer.
Bool_t fbConnectIsClose
True if fxConnectTransport has returned from Close(), i.e.
UInt_t fuConnectPort
port number for timer connect
virtual Int_t TimerConnect()
This method is used by the object connectortimer Notify to connect or disconnect a transportchannel (...
TGo4ThreadHandler * fxThreadHandler
UInt_t fuObjectPort
port number for the object server connections
Bool_t HandleObjectRequest()
Ask for which object to send and give it to the client.
static const Int_t fgiCONNECTWAITCYCLES
Maximum cycles to wait until transport is connected.
static const char * fgcCONTHREADNAME
histogram server connector thread name
TString fxObjectThreadName
Name of object server thread.
void SetDisConnect(TGo4Socket *trans)
Int_t ConnectObjectClient()
Starts server socket waiting for the next client.
void SetConnect(TGo4Socket *trans, const char *host, UInt_t port)
const char * ConnectHost() const
TString fxConnectorName
Name of connector thread.
TGo4AnalysisClient * fxAnalysisClient
UInt_t GetObjPort()
returns the portnumber for object server connection
Int_t fiServerPort
port number for server socket
const char * ObjectThreadName() const
static const Int_t fgiCLOSEWAITCYCLES
Maximum cycles to wait until transport is closed.
TGo4Socket * fxTransport
socket for object server
Int_t ServeObjectClient()
Used by object connector runnable to serve client request.
static const Int_t fgiOPENWAITCYCLES
Maximum cycles to wait until transport is open.
static const UInt_t fguCLOSEWAITCYCLETIME
Time for each close wait cycle, in ms.
static const UInt_t fguTIMERPERIOD
Period of connector timer, in ms.
TGo4Socket * fxDisConnectTransport
link to the next TaskHandler transport instance that shall be disconnected by the connector Timer wit...
Bool_t fbUseObjectServer
Switches Go4 objectserver option on/off.
static void Debug(const char *text,...) GO4_PRINTF_ARGS
User shortcut for message with prio 0.
Definition TGo4Log.cxx:281
Runnable that serves an object request for object client.
timer aggregated to the histogram server which is responsible to establish connections of the go4 obj...
static UInt_t Get_fguPORTWAITTIME()
static const char * Get_fgcERROR()
static const char * Get_fgcOK()
static Int_t Get_fgiPORTWAITCYCLES()
Go4 Task.
Definition TGo4Task.h:39
Exception which terminates the threadmanager and the application.
Bool_t IsTerminating() const
returns termination status of Threadmanager
static void Sleep(UInt_t millisecs)
wrapper for gSystem->Sleep with consecutive TThread::CancelPoint - necessary for proper pthread termi...
INTS4 f_his_gethis(CHARS *pc_server, INTS4 l_port, CHARS *pc_base, CHARS *pc_access, CHARS *pc_histo, s_his_head **p_head, INTS4 **p_buffer, INTS4 *pl_size)
Definition f_his_hist.c:311
INTS4 f_his_close(void)
Definition f_his_hist.c:706
INTS4 f_his_server(CHARS *pc_base, CHARS *pc_access, INTS4 *pl_port)
Definition f_his_hist.c:418
#define COMM__SUCCESS
Definition s_his_comm.h:27
int INTS4
Definition typedefs.h:28
char CHARS
Definition typedefs.h:21