Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

TGo4HistogramServer.cxx

Go to the documentation of this file.
00001 //-------------------------------------------------------------
00002 //        Go4 Release Package v3.04-01 (build 30401)
00003 //                      28-November-2008
00004 //---------------------------------------------------------------
00005 //   The GSI Online Offline Object Oriented (Go4) Project
00006 //   Experiment Data Processing at EE department, GSI
00007 //---------------------------------------------------------------
00008 //
00009 //Copyright (C) 2000- Gesellschaft f. Schwerionenforschung, GSI
00010 //                    Planckstr. 1, 64291 Darmstadt, Germany
00011 //Contact:            http://go4.gsi.de
00012 //----------------------------------------------------------------
00013 //This software can be used under the license agreements as stated
00014 //in Go4License.txt file which is part of the distribution.
00015 //----------------------------------------------------------------
00016 #include "TGo4HistogramServer.h"
00017 
00018 #include "Riostream.h"
00019 
00020 #include "TFile.h"
00021 
00022 #include "TGo4Log.h"
00023 #include "TGo4LockGuard.h"
00024 #include "TGo4Socket.h"
00025 #include "TGo4Buffer.h"
00026 
00027 #include "TGo4HisConnectorRunnable.h"
00028 #include "TGo4ObjConnectorRunnable.h"
00029 #include "TGo4ObjConnectorTimer.h"
00030 #include "TGo4CommandInvoker.h"
00031 #include "TGo4AnalysisClientImp.h"
00032 #include "TGo4AnalysisImp.h"
00033 #include "TGo4AnalysisObjectNames.h"
00034 #include "TGo4Task.h"
00035 #include "TGo4TaskManager.h"
00036 #include "TGo4Thread.h"
00037 #include "TGo4ThreadManager.h"
00038 #include "TGo4ThreadHandler.h"
00039 #include "TGo4TerminateException.h"
00040 #include "TGo4TaskHandler.h"
00041 
00042 extern "C"
00043 {
00044 #include "f_his_hist.h"
00045 }
00046 
00047 const Text_t TGo4HistogramServer::fgcCONTHREADNAME[]="HISTOSERV-";
00048 const Text_t TGo4HistogramServer::fgcSHUTDOWNNAME[]="__HServLast__";
00049 const Text_t TGo4HistogramServer::fgcCOMGETLIST[]="__OServNamesList__";
00050 
00051 const Text_t TGo4HistogramServer::fgcOBJTHREADNAME[]="OBJECTSERV-";
00052 const UInt_t TGo4HistogramServer::fguTIMERPERIOD=200; // time in ms (20)
00053 const Int_t TGo4HistogramServer::fgiOPENWAITCYCLES=100; // wait cycles (100)
00054 const UInt_t TGo4HistogramServer::fguOPENWAITCYCLETIME=500; // time in ms (20)
00055 const Int_t TGo4HistogramServer::fgiCLOSEWAITCYCLES=100; // wait cycles (100)
00056 const UInt_t TGo4HistogramServer::fguCLOSEWAITCYCLETIME=500; // time in ms (20)
00057 const Int_t TGo4HistogramServer::fgiCONNECTWAITCYCLES=20; // wait cycles (20)
00058 const UInt_t TGo4HistogramServer::fguCONNECTWAITCYCLETIME=500; // time in ms (20)
00059 
00060 TGo4HistogramServer::TGo4HistogramServer(TGo4AnalysisClient* owner,
00061                                          const char* servername,
00062                                          const char* password,
00063                                          Bool_t useobjectserver)
00064 : fxAnalysisClient(owner), fxThreadHandler(0), fiServerPort(0),
00065 fxTransport(0), fuObjectPort(0), fxConnectTransport(0), fxDisConnectTransport(0),
00066 fuConnectPort(0),
00067 fbConnectRequest(kFALSE), fbDisConnectRequest(kFALSE),
00068 fbConnectIsOpen(kFALSE), fbConnectIsDone(kFALSE),fbConnectIsClose(kTRUE),
00069 fxConnectorTimer(0),
00070 fbUseObjectServer(useobjectserver)
00071 {
00072    TGo4CommandInvoker::Instance(); // make sure we have an invoker instance!
00073    TGo4CommandInvoker::Register("HistogramServer", this);
00074    if(fbUseObjectServer)
00075       fxTransport = new TGo4Socket(kFALSE); // raw transport in server mode for object server
00076    // we use the histogram api instead of stccomm:
00077    Int_t result=f_his_server((CHARS*) servername, (CHARS*) password, &fiServerPort);
00078    if(result==COMM__SUCCESS) {
00079        fxServerName = servername;
00080        fxServerPass = password;
00081        TGo4Analysis::Instance()->Message(1,
00082              "Created Histogram server %s on port %d",
00083                servername, fiServerPort);
00084    }
00085 else
00086    {
00087       //cout <<"ERROR on creation of Histogram server: "<< result << endl;
00088       TGo4Analysis::Instance()->Message(3,
00089              "ERROR %d on creation of Histogram server",
00090                result);
00091    }
00092  // start connector thread:
00093    const Text_t* ownername;
00094    if(fxAnalysisClient)
00095       {
00096          fxThreadHandler= fxAnalysisClient->GetThreadHandler();
00097          fxAnalysis=fxAnalysisClient->GetAnalysis();
00098          ownername=fxAnalysisClient->GetName();
00099       }
00100    else
00101       {
00102          ownername="never-come-here";
00103       }
00104 
00105 if(fbUseObjectServer)
00106    {
00107         fxConnectorTimer= new TGo4ObjConnectorTimer(this,fguTIMERPERIOD);
00108         fxConnectorTimer->TurnOn();
00109    }
00110 if(fxThreadHandler)
00111       {
00112          // thread to serve gsi histogram api:
00113          fxConnectorName = fgcCONTHREADNAME;
00114          fxConnectorName += ownername;
00115 
00116          TGo4HisConnectorRunnable* crun = new TGo4HisConnectorRunnable(ConnectorName(), this);
00117          fxThreadHandler->NewThread(ConnectorName(),crun);
00118          fxThreadHandler->Start(ConnectorName());
00119          if(fbUseObjectServer)
00120             {
00121 
00122             // thread for root object server:
00123             fxObjectThreadName = fgcOBJTHREADNAME;
00124             fxObjectThreadName += ownername;
00125 
00126             TGo4ObjConnectorRunnable* orun = new TGo4ObjConnectorRunnable(ObjectThreadName(), this);
00127             fxThreadHandler->NewThread(ObjectThreadName(), orun);
00128             fxThreadHandler->Start(ObjectThreadName());
00129             }
00130       }
00131    else
00132       {
00133           cerr <<" Histogram Server constructor FATAL ERROR: no threadmanager !!" << endl;
00134           throw TGo4RuntimeException();
00135       }
00136 }
00137 
00138 TGo4HistogramServer::TGo4HistogramServer()
00139 : fxAnalysisClient(0), fxThreadHandler(0), fiServerPort(0),
00140 fxTransport(0), fuObjectPort(0), fxConnectTransport(0), fxDisConnectTransport(0),
00141 fcConnectHost(0), fuConnectPort(0),
00142 fbConnectRequest(kFALSE), fbDisConnectRequest(kFALSE),
00143 fbConnectIsOpen(kFALSE), fbConnectIsDone(kFALSE),fbConnectIsClose(kTRUE),
00144 fbUseObjectServer(kFALSE)
00145 {
00146 TGo4CommandInvoker::Instance(); // make sure we have an invoker instance!
00147 TGo4CommandInvoker::Register("HistogramServer", this);
00148 }
00149 
00150 
00151 TGo4HistogramServer::~TGo4HistogramServer()
00152 {
00153 // prepare stopped flag:
00154 if(fbUseObjectServer && fxThreadHandler) fxThreadHandler->Stop(ConnectorName());
00155 
00156 // for clean shutdown, we have to connect one last time to get out of the wait:
00157 INTS4 * pl_all =NULL;
00158 s_his_head * ps_his_head=NULL;
00159 INTS4 l_size=0;
00160 f_his_gethis((char*)"localhost", 
00161              fiServerPort ,
00162             (char*) fxServerName.Data(),
00163             (char*) fxServerPass.Data(),
00164             (char*) fgcSHUTDOWNNAME,
00165             (s_his_head **)&ps_his_head,
00166             (INTS4 **)&pl_all,
00167             (INTS4 *)&l_size);
00168 
00169 if(fxThreadHandler)
00170     {
00171     fxThreadHandler->RemoveThread(ConnectorName());
00173     if(fbUseObjectServer)
00174       {
00175        fxThreadHandler->Stop(ObjectThreadName());
00176       // here we might connect last time to object server, to investigate!!
00178        fxThreadHandler->RemoveThread(ObjectThreadName());
00179       // this will cancel thread and delete runnable
00180       }
00181     }
00182 delete fxConnectorTimer;
00183 f_his_close(); // this will delete api server for histograms
00184 
00185 if(fxTransport)
00186       {
00187          fxTransport->Close(); // close go4 server socket for object server
00188          delete fxTransport;
00189          fxTransport=0;
00190       }
00191 
00192 TGo4CommandInvoker::UnRegister(this);
00193 }
00194 
00195 Int_t TGo4HistogramServer::ServeObjectClient()
00196 {
00197 Int_t rev=ConnectObjectClient();
00198 if(rev<0) return rev;
00199 if(rev==0 && CheckLogin())
00200    {
00201       HandleObjectRequest();
00202    }  else {}
00203 DisconnectObjectClient();
00204 return rev;
00205 }
00206 
00207 void TGo4HistogramServer::DisconnectObjectClient()
00208 {
00209 //
00210 SetDisConnect(fxTransport); // timer shall do the Close() of negotiation
00211 //TGo4Log::Debug(" HistogramServer: Waiting for timer Close() of client  ... ");
00212 WaitForClose(); // poll until timer has returned from close
00213 //TGo4Log::Debug(" HistogramServer: Client connection closed. ");
00214 }
00215 
00216 Int_t TGo4HistogramServer::ConnectObjectClient()
00217 {
00218 
00219    static Bool_t isfirsttime=kTRUE;
00220    // we delegate the actual TSocket open to the taskconnector timer:
00221    SetConnect(fxTransport, "Server mode does not need hostname", 0); // for portscan
00222    Int_t waitresult=WaitForOpen(); // wait for the server Open() call by timer
00223    if(waitresult==-2) return waitresult; // return in termination mode
00224    if(waitresult<0)
00225    {
00226       // open timeout
00227       TGo4Log::Debug(" HistogramServer: Negotiation channel open TIMEOUT");
00228       cerr <<" HistogramServer TIMEOUT ERROR opening socket connection !!! Terminating..." << endl;
00229       throw TGo4TerminateException(fxAnalysisClient->GetTask());
00230    }
00231    Int_t count=0;
00232    while(GetObjPort()==0)
00233    {
00234       TGo4Task* task=fxAnalysisClient->GetTask();
00235       if(count>TGo4TaskHandler::Get_fgiPORTWAITCYCLES())
00236             {
00237                TGo4Log::Debug(" HistogramServer: Negotiation port getter TIMEOUT");
00238                cerr <<" HistogramServer TIMEOUT ERROR retrieving port number  !!! Terminating..." << endl;
00239                throw TGo4TerminateException(fxAnalysisClient->GetTask());
00240             }
00241       else if(task==0 || task->IsTerminating())
00242             {
00243                return -1;
00244             }
00245       else
00246             {
00247               TGo4Thread::Sleep(TGo4TaskHandler::Get_fguPORTWAITTIME());
00248               ++count;
00249             }
00250    }
00251 //   TGo4Log::Debug(" HistogramServer is waiting to serve object client request on port %d ... ",
00252 //            fuObjectPort);
00253    if(isfirsttime)
00254       {
00255          // only tell gui the first time the port number; performance!
00256          TGo4Analysis::Instance()->Message(1,
00257              "Object Server %s is waiting on port %d",
00258                       fxServerName.Data(),
00259                       fuObjectPort);
00260          isfirsttime=kFALSE;
00261       } else {}
00262    Int_t connectwaitseconds=WaitForConnection(); // timer tells us by flag when the transport is opened
00263    if(connectwaitseconds<0)
00264       {
00265          // case of threadmanager termination:
00266          // connector runnable shall stop on return from ServeClient method
00267          return connectwaitseconds;
00268       }
00269    else
00270       {
00271          // just proceed to the client server negotiations
00272       }
00273 
00274 return 0;
00275 }
00276 
00277 Bool_t TGo4HistogramServer::CheckLogin()
00278 {
00280    // check for basename:
00281    //cout <<"##### check login " << endl;
00282    Text_t* recvchar=0;
00283    recvchar=fxTransport->RecvRaw("dummy");
00284    if(recvchar && !strcmp(recvchar,fxServerName.Data()))
00285       {
00286          fxTransport->Send(TGo4TaskHandler::Get_fgcOK()); // handshake to assure the client
00287       }
00288    else
00289       {
00290          //TGo4Analysis::Instance()->Message(2,
00291          //       "Object server connection attempt with wrong basename");
00292          cerr <<"##### check login with wrong base" << endl;
00293          fxTransport->Send(TGo4TaskHandler::Get_fgcERROR());
00294          DisconnectObjectClient();
00295          return kFALSE;
00296       }
00297    // check for password:
00298    recvchar=fxTransport->RecvRaw("dummy");
00299    if(recvchar && !strcmp(recvchar,fxServerPass.Data()))
00300       {
00301          fxTransport->Send(TGo4TaskHandler::Get_fgcOK()); // handshake to assure the client
00302       }
00303    else
00304       {
00305 //         TGo4Analysis::Instance()->Message(2,
00306 //                "Object server connection attempt with wrong password");
00307          cerr <<"##### check login with wrong passwd" << endl;
00308          fxTransport->Send(TGo4TaskHandler::Get_fgcERROR());
00309          DisconnectObjectClient();
00310          return kFALSE;
00311       }
00312 return kTRUE;
00313 }
00314 
00315 Bool_t TGo4HistogramServer::HandleObjectRequest()
00316 {
00317 Text_t objectname[TGo4ThreadManager::fguTEXTLENGTH];
00318 Text_t* recvchar=0;
00319 // get object name
00320 recvchar=fxTransport->RecvRaw("dummy");
00321 if(recvchar==0)
00322    {
00323       cerr <<"-----Object server received null character for object request!"<<endl;
00324       return kFALSE;
00325    }
00326 strncpy(objectname, recvchar,TGo4ThreadManager::fguTEXTLENGTH -1); // get the client name
00327 //cout <<"-----Object server got request for object "<< objectname << endl;
00328 // check here if object is requested or nameslist? :
00329 TObject* object=0;
00330 if(!strcmp(objectname,fgcCOMGETLIST))
00331    {
00332       // get analysis nameslist object
00333       TGo4LockGuard mainguard; // protect creation of new nameslist
00334       fxAnalysis->UpdateNamesList();
00335       object=fxAnalysis->GetNamesList();
00336       //cout <<"---------Retrieving nameslist" << endl;
00337    }
00338 else
00339    {
00340       // get object from analysis
00341       object=fxAnalysis->GetObject(objectname);
00342       //cout <<"---------Retrieving object" << endl;
00343    }
00344 return (SendObject(object));
00345 }
00346 
00347 Bool_t TGo4HistogramServer::SendObject(TObject* object)
00348 {
00349 
00350 Bool_t retval=kTRUE;
00351 // stream object into TBuffer:
00352 TBuffer* rootbuffer=0;
00353 if(object!=0)
00354    {
00355    fxTransport->Send(TGo4TaskHandler::Get_fgcOK()); // let client know the object exists
00356    TGo4LockGuard mainguard;
00357       rootbuffer = new TGo4Buffer(TBuffer::kWrite);
00358       TFile *filsav = gFile;
00359       gFile = 0;
00360       rootbuffer->WriteObject(object);
00361       gFile = filsav;
00362       fxTransport->SendBuffer(rootbuffer);
00363       delete rootbuffer;
00364    }
00365 else
00366    {
00367       //cout <<"Error: object not found in analysis!" << endl;
00368       fxTransport->Send(TGo4TaskHandler::Get_fgcERROR());
00369       retval=kFALSE;
00370    }
00371 Text_t* recvchar=fxTransport->RecvRaw("dummy"); // get exit message
00372 if(recvchar==0)
00373    {
00374     TGo4Log::Debug(" HistogramServer: null character on finishing object client channel ");
00375     retval=kFALSE;
00376    }
00377 else if(strcmp(recvchar,TGo4TaskHandler::Get_fgcOK()))
00378    {
00379       TGo4Log::Debug(" HistogramServer: ERROR on finishing object client channel ");
00380       retval=kFALSE;
00381    }
00382 else
00383    {
00384       //cout <<"##### send object is finished with ok." << endl;
00385    }
00386 return retval;
00387 }
00388 
00389 
00390 void TGo4HistogramServer::SetConnect(TGo4Socket * trans, const char* host, UInt_t port)
00391 {
00392    TRACE((12,"TGo4HistogramServer::SetConnect(TGo4Socket *)",__LINE__, __FILE__));
00393    fxConnectTransport = trans;
00394    fcConnectHost = host;
00395    fuConnectPort = port;
00396    fbConnectRequest = kTRUE;
00397 }
00398 
00399 void TGo4HistogramServer::SetDisConnect(TGo4Socket * trans)
00400 {
00401    TRACE((12,"TGo4HistogramServer::SetDisConnect(TGo4Socket *)",__LINE__, __FILE__));
00402    fxDisConnectTransport=trans;
00403    fbDisConnectRequest=kTRUE;
00404 }
00405 
00406 Int_t TGo4HistogramServer::TimerConnect()
00407 {
00408    TRACE((12,"TGo4HistogramServer::TimerConnect()",__LINE__, __FILE__));
00409    Int_t rev=0;
00412    if(fbDisConnectRequest)
00413       {
00414       TRACE((15,"TGo4HistogramServer::TimerConnect()--DisConnectRequest",__LINE__, __FILE__));
00415          if(fxDisConnectTransport!=0)
00416             {
00417                // we have a transport instance to disconnect
00418                fxDisConnectTransport->Close();
00419                fbConnectIsClose=kTRUE;
00420                fbDisConnectRequest=kFALSE; // we served the request, reset it
00421             rev+=1;
00422             }
00423          else
00424             {
00425                // error, zero pointer given
00426                rev+=32;
00427             }
00428       }
00429    else 
00430       {
00431       TRACE((15,"TGo4HistogramServer::TimerConnect()--NO DisConnectRequest",__LINE__, __FILE__));
00432          // no open request, continue
00433          rev+=2;
00434       }
00435 
00438    if(fbConnectRequest)
00439       {
00440       TRACE((15,"TGo4HistogramServer::TimerConnect()--ConnectRequest",__LINE__, __FILE__));
00441          // timer shall open a transport as server
00442       if(fxConnectTransport!=0)
00443          {
00444             if(!fxConnectTransport->IsOpen())
00445                {
00446                 TRACE((10,"TGo4HistogramServer::TimerConnect()--transport is not open",__LINE__, __FILE__));
00447                   // transport is not open, so do it
00448                   fbConnectIsOpen=kTRUE; // tell connector thread that we try to open
00449                   //cout <<"TimerConnect: connect before open" << endl;
00450                   Int_t result=fxConnectTransport->Open(ConnectHost(), fuConnectPort, kTRUE);
00451                   if(result==0)
00452                      {
00453                         fbConnectIsDone=kTRUE; // tell connector thread we returned from open
00454                         fbConnectRequest=kFALSE; // we served the request, reset it
00455                         rev+=4;
00456                      }
00457                   else
00458                      {
00459                         rev=-4;
00460                         // open was not finished, we poll once again...
00461                      }
00462                }
00463             else
00464                {
00465                 TRACE((10,"TGo4HistogramServer::TimerConnect()--transport already open",__LINE__, __FILE__));
00466                   // transport was already open, do nothing
00467                   rev+=8;
00468                }
00469          } // if(fxConnectTransport!=0)
00470       else
00471          {
00472                TRACE((10,"TGo4HistogramServer::TimerConnect()--no transport specified",__LINE__, __FILE__));
00473                rev+=64;
00474          }
00475       } 
00476    else
00477       {
00478       TRACE((15,"TGo4HistogramServer::TimerConnect()--NO ConnectRequest",__LINE__, __FILE__));
00479          // no open request, continue
00480          rev+=16;
00481       }
00482 //   cout <<"TimerConnect: before return" << endl;
00483    return rev;
00484 }
00485 
00486 
00487 
00488 Int_t TGo4HistogramServer::WaitForOpen()
00489 
00490 {
00491    TRACE((12,"TGo4HistogramServer::WaitForOpen()",__LINE__, __FILE__));
00492    Int_t count=0;
00493    while(!fbConnectIsOpen)
00494       {
00495          TGo4Task* task=fxAnalysisClient->GetTask();
00496          if(count>TGo4HistogramServer::fgiOPENWAITCYCLES)
00497             {
00498                count = -1; // timeout
00499                break;
00500             }
00501          else if(task==0 || task->IsTerminating())
00502             {
00503                // note: task==0 is case of shutdown of analysis server!
00504                count = -2;
00505                break;
00506             }
00507          else
00508             {
00509             TGo4Thread::Sleep(TGo4HistogramServer::fguOPENWAITCYCLETIME);
00510             ++count;
00511             }
00512       //cout << "*****WaitForOpen()"<<endl;
00513       }
00514    fbConnectIsOpen=kFALSE; //  reset for next time
00515    return count;
00516 
00517 }
00518 
00519 
00520 Int_t TGo4HistogramServer::WaitForClose()
00521 
00522 {
00523    TRACE((12,"TGo4HistogramServer::WaitForClose()",__LINE__, __FILE__));
00524    Int_t count=0;
00525    while(!fbConnectIsClose)
00526       {
00527           //cout <<"Waiting for close..." << endl;
00528           if(count>TGo4HistogramServer::fgiCLOSEWAITCYCLES)
00529             {
00530                //cout <<"reached closewaitcycles "<< count << endl;
00531                count = -1; // timeout
00532                break;
00533             }
00534          else
00535             {
00536                TGo4Thread::Sleep(TGo4HistogramServer::fguCLOSEWAITCYCLETIME);
00537                ++count;
00538          }
00539       //cout << "*****WaitForClose() "<<count<< endl;
00540       }
00541    fbConnectIsClose=kFALSE; //  reset for next time
00542    return count;
00543 
00544 }
00545 
00546 Int_t TGo4HistogramServer::WaitForConnection()
00547 
00548 {
00549    TRACE((12,"TGo4HistogramServer::WaitForConnection()",__LINE__, __FILE__));
00550    Int_t count=0;
00551    while(!fbConnectIsDone)
00552       {
00553          TGo4Task* task=fxAnalysisClient->GetTask();
00554          if(task==0 || task->IsTerminating())
00555             {
00556                // note: task==0 is case of shutdown of analysis server!
00557                count = -2; // termination mode
00558                break;
00559             }
00560          else
00561             {
00562                TGo4Thread::Sleep(TGo4HistogramServer::fguCONNECTWAITCYCLETIME);
00563                ++count;
00564             }
00565          //cout << "*****WaitForConnection()"<<endl;
00566       }
00567    fbConnectIsDone=kFALSE; //  reset for next time
00568    return count;
00569 
00570 }
00571 
00572 
00573 UInt_t TGo4HistogramServer::GetObjPort()
00574 {
00575    if(fxTransport)
00576       {
00577          fuObjectPort = fxTransport->GetPort();
00578       }
00579    return fuObjectPort;
00580 }
00581 
00582 //----------------------------END OF GO4 SOURCE FILE ---------------------

Generated on Fri Nov 28 12:59:26 2008 for Go4-v3.04-1 by  doxygen 1.4.2