00001
00002
00003
00004 #include "TRootanaEventLoop.hxx"
00005 #include "XmlOdb.h"
00006 #ifdef OLD_SERVER
00007 #include "midasServer.h"
00008 #endif
00009 #ifdef HAVE_LIBNETDIRECTORY
00010 #include "libNetDirectory/netDirectoryServer.h"
00011 #endif
00012 #include "TPeriodicClass.hxx"
00013 #include "MainWindow.hxx"
00014
00015
00016 #include <TSystem.h>
00017 #include <TROOT.h>
00018 #include <TH1D.h>
00019
00020 #include <stdio.h>
00021 #include <sys/time.h>
00022 #include <iostream>
00023 #include <assert.h>
00024 #include <signal.h>
00025
00026 #ifdef HAVE_THTTP_SERVER
00027 #include "THttpServer.h"
00028 #endif
00029
00030 #include "sys/time.h"
00031
00032 struct timeval raLastTime;
00033 int raTotalEventsProcessed = 0;
00034 int raTotalEventsSkippedForAge = 0;
00035
00036
00037 bool gUseOnlyRecent;
00038
00039 void PrintCurrentStats(){
00040
00041 if((raTotalEventsProcessed%500)==0){
00042 if(raTotalEventsProcessed==0){
00043 gettimeofday(&raLastTime, NULL);
00044 }else{
00045
00046 struct timeval nowTime;
00047 gettimeofday(&nowTime, NULL);
00048
00049 double dtime = nowTime.tv_sec - raLastTime.tv_sec + (nowTime.tv_usec - raLastTime.tv_usec)/1000000.0;
00050 double rate = 0;
00051 if (time !=0)
00052 rate = 500.0/(dtime);
00053 printf("Processed %d events. Analysis rate = %f events/seconds. \n",raTotalEventsProcessed,rate);
00054 gettimeofday(&raLastTime, NULL);
00055
00056 if(gUseOnlyRecent){
00057 printf("Skipped %i events that were too old (>1sec old) out of %i events\n",
00058 raTotalEventsSkippedForAge, raTotalEventsSkippedForAge+raTotalEventsProcessed);
00059 }
00060 }
00061 }
00062
00063 raTotalEventsProcessed++;
00064
00065 }
00066
00067
00068
00069
00070 TRootanaEventLoop* TRootanaEventLoop::fTRootanaEventLoop = NULL;
00071
00072 TRootanaEventLoop& TRootanaEventLoop::Get(void) {
00073
00074 if(!fTRootanaEventLoop){
00075 std::cerr << "Singleton Not Instantiated! "
00076 << " Need to call something like SomeClass::CreateSingleton<SomeClass>(); Exiting!"
00077 <<std::endl; exit(0);
00078 }
00079 return *fTRootanaEventLoop;
00080 }
00081
00082
00083
00084 TRootanaEventLoop::TRootanaEventLoop (){
00085
00086 fOutputFile = 0;
00087 fOutputFilename = std::string("output");
00088 fDisableRootOutput = false;
00089 fODB = 0;
00090 fOnlineHistDir = 0;
00091 fMaxEvents = 0;
00092 fCurrentRunNumber = 0;
00093 fIsOffline = true;
00094
00095 fCreateMainWindow = true;
00096 fUseBatchMode = false;
00097 fSuppressTimestampWarnings = false;
00098
00099 gUseOnlyRecent = false;
00100
00101 fBufferName = std::string("SYSTEM");
00102 fOnlineName = std::string("rootana");
00103
00104 fDataContainer = new TDataContainer();
00105
00106
00107 char **argv2 = NULL;
00108 fApp = new TApplication("rootana", 0, argv2);
00109 }
00110
00111 TRootanaEventLoop::~TRootanaEventLoop (){
00112
00113 if(fODB) delete fODB;
00114 CloseRootFile();
00115
00116 }
00117
00118
00119 void TRootanaEventLoop::Initialize(void){};
00120
00121 void TRootanaEventLoop::BeginRun(int transition,int run,int time){};
00122
00123 void TRootanaEventLoop::EndRun(int transition,int run,int time){};
00124
00125 void TRootanaEventLoop::Finalize(){};
00126
00127 void TRootanaEventLoop::Usage(void){};
00128 void TRootanaEventLoop::UsageRAD(void){};
00129
00130
00131 bool TRootanaEventLoop::CheckOption(std::string option){return false;}
00132 bool TRootanaEventLoop::CheckOptionRAD(std::string option){return false;}
00133
00134
00135 bool TRootanaEventLoop::CheckEventID(int eventId){
00136
00137
00138 if(fProcessEventIDs.size()==0) return true;
00139
00140
00141 for(unsigned int i = 0; i < fProcessEventIDs.size(); i++){
00142 if(fProcessEventIDs[i] == (eventId & 0xFFFF))
00143 return true;
00144 }
00145
00146 return false;
00147 }
00148
00149 void TRootanaEventLoop::PrintHelp(){
00150
00151 printf("\nUsage:\n");
00152 printf("\n./analyzer.exe [-h] [-Hhostname] [-Eexptname] [-eMaxEvents] [-P9091] [-p9090] [-m] [-g] [file1 file2 ...]\n");
00153 printf("\n");
00154 printf("\t-h: print this help message\n");
00155 printf("\t-T: test mode - start and serve a test histogram\n");
00156 printf("\t-Hhostname: connect to MIDAS experiment on given host\n");
00157 printf("\t-Eexptname: connect to this MIDAS experiment\n");
00158 printf("\t-bbuffer: connect to this MIDAS buffer\n");
00159 printf("\t-P: Start the TNetDirectory server on specified tcp port (for use with roody -Plocalhost:9091)\n");
00160 printf("\t-p: Start the old midas histogram server on specified tcp port (for use with roody -Hlocalhost:9090)\n");
00161 #ifdef HAVE_THTTP_SERVER
00162 printf("\t-r: Start THttpServer on specified tcp port\n");
00163 #endif
00164 printf("\t-eXXX: Number of events XXX to read from input data files\n");
00165
00166 printf("\t-g: Enable graphics display when processing data files\n");
00167 UsageRAD();
00168 Usage();
00169 printf("\n");
00170 printf("Example1: analyze online data: ./analyzer.exe -P9091\n");
00171 printf("Example2: analyze existing data: ./analyzer.exe /data/alpha/current/run00500.mid\n");
00172
00173 exit(1);
00174 }
00175
00176
00177 int TRootanaEventLoop::ExecuteLoop(int argc, char *argv[]){
00178
00179 setbuf(stdout,NULL);
00180 setbuf(stderr,NULL);
00181
00182 signal(SIGILL, SIG_DFL);
00183 signal(SIGBUS, SIG_DFL);
00184 signal(SIGSEGV, SIG_DFL);
00185
00186 std::vector<std::string> args;
00187 for (int i=0; i<argc; i++)
00188 {
00189 if (strcmp(argv[i],"-h")==0)
00190 PrintHelp();
00191 args.push_back(argv[i]);
00192 }
00193
00194
00195 if(fUseBatchMode){
00196 fCreateMainWindow = false;
00197 }
00198
00199 if(gROOT->IsBatch() && !fUseBatchMode) {
00200 printf("Cannot run in batch mode\n");
00201 return 1;
00202 }
00203
00204 bool forceEnableGraphics = false;
00205 bool testMode = false;
00206 int tcpPort = 0;
00207 int rhttpdPort = 0;
00208 const char* hostname = NULL;
00209 const char* exptname = NULL;
00210
00211 for (unsigned int i=1; i<args.size(); i++)
00212 {
00213 const char* arg = args[i].c_str();
00214
00215
00216 if (strncmp(arg,"-e",2)==0)
00217 fMaxEvents = atoi(arg+2);
00218 else if (strncmp(arg,"-m",2)==0)
00219 ;
00220 else if (strncmp(arg,"-P",2)==0)
00221 tcpPort = atoi(arg+2);
00222 #ifdef HAVE_THTTP_SERVER
00223 else if (strncmp(arg,"-r",2)==0)
00224 rhttpdPort = atoi(arg+2);
00225 #endif
00226 else if (strcmp(arg,"-T")==0)
00227 testMode = true;
00228 else if (strcmp(arg,"-g")==0)
00229 forceEnableGraphics = true;
00230 else if (strncmp(arg,"-H",2)==0)
00231 hostname = strdup(arg+2);
00232 else if (strncmp(arg,"-E",2)==0)
00233 exptname = strdup(arg+2);
00234 else if (strncmp(arg,"-b",2)==0){
00235 fBufferName = std::string(arg+2);
00236 }else if (strcmp(arg,"-h")==0)
00237 PrintHelp();
00238 else if(arg[0] == '-')
00239 if(!CheckOptionRAD(args[i]))
00240 if(!CheckOption(args[i]))
00241 PrintHelp();
00242 }
00243
00244
00245
00246 fIsOffline = false;
00247 for (unsigned int i=1; i<args.size(); i++){
00248 const char* arg = args[i].c_str();
00249 if (arg[0] != '-')
00250 {
00251 fIsOffline = true;
00252 }
00253 }
00254
00255
00256 MainWindow *mainWindow=0;
00257 if(fCreateMainWindow){
00258 std::cout << "Create main window! " << std::endl;
00259 mainWindow = new MainWindow(gClient->GetRoot(), 200, 300);
00260 }
00261
00262 gROOT->cd();
00263 fOnlineHistDir = new TDirectory("rootana", "rootana online plots");
00264
00265 #ifdef HAVE_LIBNETDIRECTORY
00266 if (tcpPort)
00267 StartNetDirectoryServer(tcpPort, fOnlineHistDir);
00268 #else
00269 if (tcpPort)
00270 fprintf(stderr,"ERROR: No support for the TNetDirectory server!\n");
00271 #endif
00272
00273 #ifdef HAVE_THTTP_SERVER
00274
00275 THttpServer *root_http_serv;
00276 if(rhttpdPort){
00277 char address[100];
00278 sprintf(address,"http:%i",rhttpdPort);
00279 root_http_serv = new THttpServer(address);
00280 }
00281 #endif
00282
00283
00284 Initialize();
00285
00286 for (unsigned int i=1; i<args.size(); i++){
00287 const char* arg = args[i].c_str();
00288 if (arg[0] != '-')
00289 {
00290 ProcessMidasFile(fApp,arg);
00291 }
00292 }
00293
00294 if (testMode){
00295 std::cout << "Entering test mode." << std::endl;
00296 fOnlineHistDir->cd();
00297 TH1D* hh = new TH1D("test", "test", 100, 0, 100);
00298 hh->Fill(1);
00299 hh->Fill(10);
00300 hh->Fill(50);
00301
00302 fApp->Run(kTRUE);
00303 if(fCreateMainWindow) delete mainWindow;
00304 return 0;
00305 }
00306
00307
00308
00309 if (fIsOffline){
00310 if(fCreateMainWindow) delete mainWindow;
00311 return 0;
00312 }
00313
00314 #ifdef HAVE_MIDAS
00315 ProcessMidasOnline(fApp, hostname, exptname);;
00316 #endif
00317
00318 if(fCreateMainWindow) delete mainWindow;
00319
00320 Finalize();
00321
00322 return 0;
00323
00324 }
00325
00326
00327
00328 int TRootanaEventLoop::ProcessMidasFile(TApplication*app,const char*fname)
00329 {
00330 TMidasFile f;
00331 bool tryOpen = f.Open(fname);
00332
00333 if (!tryOpen){
00334 printf("Cannot open input file \"%s\"\n",fname);
00335 return -1;
00336 }
00337
00338
00339 gUseOnlyRecent = false;
00340
00341 int i=0;
00342 while (1)
00343 {
00344 TMidasEvent event;
00345 if (!f.Read(&event))
00346 break;
00347
00348
00349 int eventId = event.GetEventId();
00350
00351
00352
00353 if ((eventId & 0xFFFF) == 0x8000){
00354
00355 event.Print();
00356
00357
00358 if (fODB) delete fODB;
00359 fODB = new XmlOdb(event.GetData(),event.GetDataSize());
00360
00361 fCurrentRunNumber = event.GetSerialNumber();
00362 OpenRootFile(fCurrentRunNumber,fname);
00363 BeginRun(0,event.GetSerialNumber(),0);
00364 raTotalEventsProcessed = 0;
00365 raTotalEventsSkippedForAge = 0;
00366
00367 } else if ((eventId & 0xFFFF) == 0x8001){
00368
00369 event.Print();
00370
00371
00372
00373 } else if ((eventId & 0xFFFF) == 0x8002){
00374
00375 event.Print();
00376 printf("Log message: %s\n", event.GetData());
00377
00378 }else if(CheckEventID(eventId)){
00379
00380
00381 event.SetBankList();
00382
00383
00384 fDataContainer->SetMidasEventPointer(event);
00385
00386
00387 if(PreFilter(*fDataContainer))
00388 ProcessMidasEvent(*fDataContainer);
00389
00390
00391 fDataContainer->CleanupEvent();
00392
00393 }
00394
00395 PrintCurrentStats();
00396
00397
00398 i++;
00399 if ((fMaxEvents!=0)&&(i>=fMaxEvents)){
00400 printf("Reached event %d, exiting loop.\n",i);
00401 break;
00402 }
00403 }
00404
00405 f.Close();
00406
00407 EndRun(0,fCurrentRunNumber,0);
00408 CloseRootFile();
00409
00410
00411
00412
00413 return 0;
00414 }
00415
00416 void TRootanaEventLoop::UseOnlyRecent(bool setting){
00417
00418 gUseOnlyRecent = setting;
00419 };
00420
00421
00422 void TRootanaEventLoop::OpenRootFile(int run, std::string midasFilename){
00423
00424 if(fDisableRootOutput) return;
00425
00426 if(fOutputFile) {
00427 fOutputFile->Write();
00428 fOutputFile->Close();
00429 fOutputFile=0;
00430 }
00431
00432 char filename[1024];
00433
00434 sprintf(filename, "%s%08d.root",fOutputFilename.c_str(), run);
00435
00436
00437
00438
00439 if(midasFilename.compare("") != 0){
00440 std::string fullname = SetFullOutputFileName(run,midasFilename);
00441 if(fullname.compare("") != 0){
00442 sprintf(filename, "%s",fullname.c_str());
00443 }
00444 }
00445
00446 fOutputFile = new TFile(filename,"RECREATE");
00447 std::cout << "Opened output file with name : " << filename << std::endl;
00448
00449
00450 #ifdef HAVE_LIBNETDIRECTORY
00451 NetDirectoryExport(fOutputFile, "outputFile");
00452 #endif
00453 }
00454
00455
00456 void TRootanaEventLoop::CloseRootFile(){
00457
00458 if(fOutputFile) {
00459 std::cout << "Closing ROOT file " << std::endl;
00460 fOutputFile->Write();
00461 fOutputFile->Close();
00462 fOutputFile=0;
00463 }
00464
00465 }
00466
00467
00468
00469
00470
00471
00472
00473
00474 #ifdef HAVE_MIDAS
00475
00476
00477
00478 static bool onlineEventLock = false;
00479
00480
00481
00482 int numberConsSkipped=0;
00483 double nextWarn = 1.0;
00484
00485
00486 int numberOldTimestamps=0;
00487 double nextWarnTimestamps = 1.0;
00488 bool disableOnlyRecentMode = false;
00489 struct timeval lastTimeProcessed;
00490
00491
00492
00493
00494
00495 void onlineEventHandler(const void*pheader,const void*pdata,int size)
00496 {
00497
00498
00499
00500
00501 if(onlineEventLock) return;
00502 onlineEventLock = true;
00503
00504
00505
00506
00507
00508
00509 if(TRootanaEventLoop::Get().IsRootOutputEnabled()
00510 && !TRootanaEventLoop::Get().IsRootFileValid()){
00511
00512 numberConsSkipped++;
00513 if(numberConsSkipped >= nextWarn){
00514 printf("onlineEventHandler Warning: Output ROOT file is not validly open, so can't fill histograms. Have skipped %i events now.\n",
00515 numberConsSkipped);
00516 nextWarn *= 3.16227;
00517 }
00518
00519 onlineEventLock = false;
00520 return;
00521 }
00522 numberConsSkipped = 0;
00523 nextWarn = 1.0;
00524
00525
00526
00527 if(gUseOnlyRecent && !disableOnlyRecentMode){
00528 TMidas_EVENT_HEADER *header = (TMidas_EVENT_HEADER*)pheader;
00529
00530 struct timeval now;
00531 gettimeofday(&now, NULL);
00532 if(header->fTimeStamp < now.tv_sec - 1){
00533
00534
00535
00536
00537
00538
00539 if(lastTimeProcessed.tv_sec < now.tv_sec - 5 && raTotalEventsProcessed > 0){
00540 printf("You are running in 'Only Recent Data' mode, but you haven't gotten any new data in more than 5 seconds.\n");
00541 printf("Disabling 'Only Recent Data' mode for this run.\n");
00542 disableOnlyRecentMode = true;
00543 }
00544
00545 raTotalEventsSkippedForAge++;
00546 onlineEventLock = false;
00547 return;
00548
00549 }
00550 }
00551
00552
00553 TMidasEvent event;
00554 memcpy(event.GetEventHeader(), pheader, sizeof(TMidas_EVENT_HEADER));
00555 event.SetData(size, (char*)pdata);
00556 event.SetBankList();
00557
00558
00559
00560
00561 if(!TRootanaEventLoop::Get().CheckEventID(event.GetEventId())){
00562 onlineEventLock = false;
00563 return;
00564 }
00565
00566
00567 TRootanaEventLoop::Get().GetDataContainer()->SetMidasEventPointer(event);
00568
00569
00570 if(TRootanaEventLoop::Get().PreFilter(*TRootanaEventLoop::Get().GetDataContainer())){
00571 TRootanaEventLoop::Get().ProcessMidasEvent(*TRootanaEventLoop::Get().GetDataContainer());
00572 }
00573
00574 gettimeofday(&lastTimeProcessed,NULL);
00575 PrintCurrentStats();
00576
00577
00578 TRootanaEventLoop::Get().GetDataContainer()->CleanupEvent();
00579
00580
00581
00582
00583 if(!TRootanaEventLoop::Get().GetSuppressTimestampWarnings()){
00584 struct timeval now;
00585 gettimeofday(&now, NULL);
00586 if(event.GetTimeStamp() < now.tv_sec - 10){
00587 numberOldTimestamps++;
00588 if(numberOldTimestamps >= nextWarnTimestamps){
00589 printf("onlineEventHandler Warning: the time for this bank (%i) is more than 10 sec older \nthan current time (%i). Has happenned %i times now.",
00590 event.GetTimeStamp(),(int) now.tv_sec,numberOldTimestamps);
00591 printf("Either the analyzer is falling behind the data taking \n(try modifying the fraction of events plotted) or times on different computers are not synchronized.\n");
00592
00593 int buffer_level = TMidasOnline::instance()->getBufferLevel();
00594 int buffer_size = TMidasOnline::instance()->getBufferSize();
00595 printf("Buffer level = %i bytes out of %i bytes maximum \n\n",buffer_level,buffer_size);
00596 nextWarnTimestamps *= 3.16227;
00597 }
00598 }
00599 }
00600
00601 onlineEventLock = false;
00602 }
00603
00604
00605 void onlineBeginRunHandler(int transition,int run,int time)
00606 {
00607 TRootanaEventLoop::Get().OpenRootFile(run);
00608 TRootanaEventLoop::Get().SetCurrentRunNumber(run);
00609 TRootanaEventLoop::Get().BeginRun(transition,run,time);
00610 raTotalEventsProcessed = 0;
00611 raTotalEventsSkippedForAge = 0;
00612 numberOldTimestamps = 0;
00613 nextWarnTimestamps = 1.0;
00614 gettimeofday(&raLastTime, NULL);
00615 disableOnlyRecentMode = false;
00616 }
00617
00618 void onlineEndRunHandler(int transition,int run,int time)
00619 {
00620 TRootanaEventLoop::Get().SetCurrentRunNumber(run);
00621 TRootanaEventLoop::Get().EndRun(transition,run,time);
00622 TRootanaEventLoop::Get().CloseRootFile();
00623 }
00624
00625
00626 void MidasPollHandlerLocal()
00627 {
00628
00629 if (!(TMidasOnline::instance()->poll(0)))
00630 gSystem->ExitLoop();
00631 }
00632
00633 int TRootanaEventLoop::ProcessMidasOnline(TApplication*app, const char* hostname, const char* exptname)
00634 {
00635 TMidasOnline *midas = TMidasOnline::instance();
00636
00637 int err = midas->connect(hostname, exptname, fOnlineName.c_str());
00638 if (err != 0)
00639 {
00640 fprintf(stderr,"Cannot connect to MIDAS, error %d\n", err);
00641 return -1;
00642 }
00643
00644 fODB = midas;
00645
00646
00647
00648 fCurrentRunNumber = fODB->odbReadInt("/runinfo/Run number");
00649
00650
00651
00652 OpenRootFile(fCurrentRunNumber);
00653 BeginRun(0,fCurrentRunNumber,0);
00654
00655
00656 midas->setTransitionHandlers(onlineBeginRunHandler,onlineEndRunHandler,NULL,NULL);
00657 midas->registerTransitions();
00658
00659
00660 midas->setEventHandler(onlineEventHandler);
00661
00662
00663
00664
00665
00666
00667
00668 midas->eventRequest(fBufferName.c_str(),-1,-1,(1<<1));
00669
00670
00671 if(gUseOnlyRecent){
00672 std::cout << "Using 'Only Recent Data' mode; all events more than 1 second old will be discarded." << std::endl;
00673 }
00674
00675
00676
00677 TPeriodicClass tm(100,MidasPollHandlerLocal);
00678
00679
00680
00681
00682 app->Run(kTRUE);
00683
00684
00685 EndRun(0,fCurrentRunNumber,0);
00686 CloseRootFile();
00687
00688
00689 midas->disconnect();
00690
00691 return 0;
00692 }
00693
00694 #endif