Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

/Go4HistogramServer/TGo4HistogramServer.cxx

Go to the documentation of this file.
00001 //---------------------------------------------------------------
00002 //        Go4 Release Package v2.10-5 (build 21005) 
00003 //                      03-Nov-2005
00004 //---------------------------------------------------------------
00005 //       The GSI Online Offline Object Oriented (Go4) Project
00006 //       Experiment Data Processing at DVEE 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 <iostream.h>
00019 
00020 #include "TFile.h"
00021 
00022 #include "Go4Log/TGo4Log.h"
00023 #include "Go4LockGuard/TGo4LockGuard.h"
00024 #include "Go4Socket/TGo4Socket.h"
00025 
00026 #include "TGo4HisConnectorRunnable.h"
00027 #include "TGo4ObjConnectorRunnable.h"
00028 #include "TGo4ObjConnectorTimer.h"
00029 #include "Go4CommandsBase/TGo4CommandInvoker.h"
00030 #include "Go4AnalysisClient/TGo4AnalysisClientImp.h"
00031 #include "Go4Analysis/TGo4AnalysisImp.h"
00032 #include "Go4Analysis/TGo4AnalysisObjectNames.h"
00033 #include "Go4TaskHandler/TGo4TaskManager.h"
00034 #include "Go4Exceptions/Go4Exceptions.h"
00035 #include "Go4ThreadManager/TGo4Thread.h"
00036 #include "Go4ThreadManager/TGo4ThreadManager.h"
00037 #include "Go4ThreadManager/TGo4TerminateException.h"
00038 #include "Go4TaskHandler/TGo4TaskHandler.h"
00039 
00040 extern "C"
00041 {
00042 //#include "MbsAPI/f_stccomm.h"
00043 #include "MbsAPI/f_his_hist.h"
00044 }
00045 
00046 #include "TGo4MbsHist.h"
00047 
00048 const Text_t TGo4HistogramServer::fgcCONTHREADNAME[]="HISTOSERV-";
00049 const Text_t TGo4HistogramServer::fgcSHUTDOWNNAME[]="__HServLast__";
00050 const Text_t TGo4HistogramServer::fgcCOMGETLIST[]="__OServNamesList__";
00051 
00052 const Text_t TGo4HistogramServer::fgcOBJTHREADNAME[]="OBJECTSERV-";
00053 const UInt_t TGo4HistogramServer::fguTIMERPERIOD=200; // time in ms (20)
00054 const Int_t TGo4HistogramServer::fgiOPENWAITCYCLES=100; // wait cycles (100)
00055 const UInt_t TGo4HistogramServer::fguOPENWAITCYCLETIME=500; // time in ms (20)
00056 const Int_t TGo4HistogramServer::fgiCLOSEWAITCYCLES=100; // wait cycles (100)
00057 const UInt_t TGo4HistogramServer::fguCLOSEWAITCYCLETIME=500; // time in ms (20)
00058 const Int_t TGo4HistogramServer::fgiCONNECTWAITCYCLES=20; // wait cycles (20)
00059 const UInt_t TGo4HistogramServer::fguCONNECTWAITCYCLETIME=500; // time in ms (20)
00060 
00061 TGo4HistogramServer::TGo4HistogramServer(TGo4AnalysisClient* owner,
00062                                          const char* servername, 
00063                                          const char* password,
00064                                          Bool_t useobjectserver)
00065 : fxAnalysisClient(owner), fxThreadHandler(0), fiServerPort(0),
00066 fxTransport(0), fuObjectPort(0), fxConnectTransport(0), fxDisConnectTransport(0),
00067 fuConnectPort(0),
00068 fbConnectRequest(kFALSE), fbDisConnectRequest(kFALSE),
00069 fbConnectIsOpen(kFALSE), fbConnectIsDone(kFALSE),fbConnectIsClose(kTRUE),
00070 fxConnectorTimer(0),
00071 fbUseObjectServer(useobjectserver)
00072 {
00073    TGo4CommandInvoker::Instance(); // make sure we have an invoker instance!
00074    TGo4CommandInvoker::Register("HistogramServer", this);
00075    if(fbUseObjectServer)   
00076       fxTransport = new TGo4Socket(kFALSE); // raw transport in server mode for object server
00077    // we use the histogram api instead of stccomm:
00078    Int_t result=f_his_server((CHARS*) servername, (CHARS*) password, &fiServerPort);
00079    if(result==COMM__SUCCESS) {
00080 //      cout <<"Created Histogram server "<< servername <<" on port "<< fiServerPort << endl;
00081        fxServerName = servername;
00082        fxServerPass = password;
00083        TGo4Analysis::Instance()->Message(1,
00084              "Created Histogram server %s on port %d",
00085                servername, fiServerPort);
00086    }
00087 else
00088    {
00089       //cout <<"ERROR on creation of Histogram server: "<< result << endl;
00090       TGo4Analysis::Instance()->Message(3,
00091              "ERROR %d on creation of Histogram server",
00092                result);
00093    }
00094  // start connector thread:
00095    const Text_t* ownername;
00096    if(fxAnalysisClient)
00097       {
00098          fxThreadHandler= fxAnalysisClient->GetThreadHandler();
00099          fxAnalysis=fxAnalysisClient->GetAnalysis();
00100          ownername=fxAnalysisClient->GetName();
00101       }
00102    else
00103       {
00104          ownername="never-come-here";
00105       }
00106    
00107 if(fbUseObjectServer)
00108    {  
00109         fxConnectorTimer= new TGo4ObjConnectorTimer(this,fguTIMERPERIOD);
00110         fxConnectorTimer->TurnOn();
00111    }   
00112 if(fxThreadHandler)
00113       {
00114          // thread to serve gsi histogram api:
00115          fxConnectorName = fgcCONTHREADNAME;
00116          fxConnectorName += ownername;
00117          
00118          TGo4HisConnectorRunnable* crun = new TGo4HisConnectorRunnable(ConnectorName(), this);
00119          fxThreadHandler->NewThread(ConnectorName(),crun);
00120          fxThreadHandler->Start(ConnectorName());
00121          if(fbUseObjectServer)
00122             {
00123      
00124             // thread for root object server:
00125             fxObjectThreadName = fgcOBJTHREADNAME;
00126             fxObjectThreadName += ownername;
00127             
00128             TGo4ObjConnectorRunnable* orun = new TGo4ObjConnectorRunnable(ObjectThreadName(), this);
00129             fxThreadHandler->NewThread(ObjectThreadName(), orun);
00130             fxThreadHandler->Start(ObjectThreadName());
00131             }
00132       }
00133    else
00134       {
00135           cerr <<" Histogram Server constructor FATAL ERROR: no threadmanager !!" << endl;
00136           throw TGo4RuntimeException();
00137       }
00138 }
00139 
00140 TGo4HistogramServer::TGo4HistogramServer()
00141 : fxAnalysisClient(0), fxThreadHandler(0), fiServerPort(0),
00142 fxTransport(0), fuObjectPort(0), fxConnectTransport(0), fxDisConnectTransport(0),
00143 fcConnectHost(0), fuConnectPort(0),
00144 fbConnectRequest(kFALSE), fbDisConnectRequest(kFALSE),
00145 fbConnectIsOpen(kFALSE), fbConnectIsDone(kFALSE),fbConnectIsClose(kTRUE),
00146 fbUseObjectServer(kFALSE)
00147 {
00148 TGo4CommandInvoker::Instance(); // make sure we have an invoker instance!
00149 TGo4CommandInvoker::Register("HistogramServer", this);
00150 }
00151 
00152 
00153 TGo4HistogramServer::~TGo4HistogramServer()
00154 {
00155 // prepare stopped flag:
00156 if(fbUseObjectServer && fxThreadHandler) fxThreadHandler->Stop(ConnectorName());
00157 
00158 // for clean shutdown, we have to connect one last time to get out of the wait:
00159 INTS4 * pl_all =NULL;
00160 s_his_head * ps_his_head=NULL;
00161 INTS4 l_size=0;
00162 f_his_gethis("localhost"   , fiServerPort ,
00163             (char*) fxServerName.Data(),
00164             (char*) fxServerPass.Data(),
00165             (char*) fgcSHUTDOWNNAME,
00166             (s_his_head **)&ps_his_head,
00167             (INTS4 **)&pl_all,
00168             (INTS4 *)&l_size);
00169 
00170 if(fxThreadHandler)
00171     {
00172     fxThreadHandler->RemoveThread(ConnectorName());
00174     if(fbUseObjectServer)
00175       {
00176        fxThreadHandler->Stop(ObjectThreadName());
00177       // here we might connect last time to object server, to investigate!!
00179        fxThreadHandler->RemoveThread(ObjectThreadName());
00180       // this will cancel thread and delete runnable
00181       }
00182     }
00183 delete fxConnectorTimer;
00184 f_his_close(); // this will delete api server for histograms
00185 
00186 if(fxTransport)
00187       {
00188          fxTransport->Close(); // close go4 server socket for object server
00189          delete fxTransport;
00190          fxTransport=0;
00191       }
00192 
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::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::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::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::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::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::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::fgcOK); // let client know the object exists
00356    TGo4LockGuard mainguard;
00357       rootbuffer = new TBuffer(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::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::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 ClassImp(TGo4HistogramServer)
00583 
00584 //----------------------------END OF GO4 SOURCE FILE ---------------------

Generated on Tue Nov 8 10:56:03 2005 for Go4-v2.10-5 by doxygen1.2.15