strsep replaced by strtok (HP,Sun,Alpha)
[u/mrichter/AliRoot.git] / MONITOR / AliMonitorProcess.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 /* $Id$ */
17
18 ///////////////////////////////////////////////////////////////////////////////
19 //                                                                           //
20 //  This is the class for perfoming the monitoring process.                  //
21 //  It checks if a raw data file exists, loops over the events in the raw    //
22 //  data file, reconstructs TPC and ITS clusters and tracks, fills the       //
23 //  monitor histograms and sends the updated histograms to the clients.      //
24 //  Then the raw data file is deleted and it waits for a new file.           //
25 //                                                                           //
26 ///////////////////////////////////////////////////////////////////////////////
27
28
29 #include "AliMonitorProcess.h"
30 #include "AliMonitorTPC.h"
31 #include "AliMonitorITS.h"
32 #include "AliMonitorV0s.h"
33 #include "AliRawReaderRoot.h"
34 #include "AliLoader.h"
35 #include "AliRun.h"
36 #include "AliTPC.h"
37 #include "AliTPCclustererMI.h"
38 #include "AliTPCtrackerMI.h"
39 #include "AliITS.h"
40 #include "AliITSclustererV2.h"
41 #include "AliITStrackerV2.h"
42 #include "AliITSLoader.h"
43 #include "AliV0vertexer.h"
44 #include <TSystem.h>
45 #include <TSocket.h>
46 #include <TMessage.h>
47 #include <TGridResult.h>
48 #include <TROOT.h>
49
50
51 ClassImp(AliMonitorProcess) 
52
53
54 const Int_t AliMonitorProcess::kgPort = 9327;
55
56
57 //_____________________________________________________________________________
58 AliMonitorProcess::AliMonitorProcess(const char* alienDir,
59                                      const char* fileNameGalice)
60 {
61 // initialize the monitoring process and the monitor histograms
62
63   fGrid = TGrid::Connect("alien", gSystem->Getenv("USER"));
64   if (!fGrid || fGrid->IsZombie() || !fGrid->IsConnected()) {
65     delete fGrid;
66     Fatal("AliMonitorProcess", "could not connect to alien");
67   }
68   fGrid->cd(alienDir);
69   fLogicalFileName = "";
70   fFileName = "";
71
72   fRunLoader = AliRunLoader::Open(fileNameGalice);
73   if (!fRunLoader) Fatal("AliMonitorProcess", 
74                          "could not get run loader from file %s", 
75                          fileNameGalice);
76
77   fRunLoader->CdGAFile();
78   fTPCParam = AliTPC::LoadTPCParam(gFile);
79   if (!fTPCParam) Fatal("AliMonitorProcess", "could not load TPC parameters");
80
81   fRunLoader->LoadgAlice();
82   gAlice = fRunLoader->GetAliRun();
83   if (!gAlice) Fatal("AliMonitorProcess", "no gAlice object found");
84   AliITS* ITS = (AliITS*) gAlice->GetModule("ITS");
85   if (!ITS) Fatal("AliMonitorProcess", "no ITS detector found");
86   fITSgeom = ITS->GetITSgeom();
87   if (!fITSgeom) Fatal("AliMonitorProcess", "could not load ITS geometry");
88
89   fRunNumber = 0;
90   fSubRunNumber = 0;
91   fNEvents = 0;
92   fNEventsMin = 2;
93   fWriteHistoList = kFALSE;
94
95   fTopFolder = new TFolder("Monitor", "monitor histograms");
96   fTopFolder->SetOwner(kTRUE);
97
98   fMonitors.Add(new AliMonitorTPC(fTPCParam));
99   fMonitors.Add(new AliMonitorITS(fITSgeom));
100   fMonitors.Add(new AliMonitorV0s);
101
102   for (Int_t iMonitor = 0; iMonitor < fMonitors.GetEntriesFast(); iMonitor++) {
103     ((AliMonitor*) fMonitors[iMonitor])->CreateHistos(fTopFolder);
104   }
105
106   TIterator* iFolder = fTopFolder->GetListOfFolders()->MakeIterator();
107   while (TFolder* folder = (TFolder*) iFolder->Next()) folder->SetOwner(kTRUE);
108   delete iFolder;
109
110   fFile = TFile::Open("monitor_tree.root", "RECREATE");
111   if (!fFile || !fFile->IsOpen()) {
112     Fatal("AliMonitorProcess", "could not open file for tree");
113   }
114   fTree = new TTree("MonitorTree", "tree for monitoring");
115   for (Int_t iMonitor = 0; iMonitor < fMonitors.GetEntriesFast(); iMonitor++) {
116     ((AliMonitor*) fMonitors[iMonitor])->CreateBranches(fTree);
117   }
118   gROOT->cd();
119
120   fServerSocket = new TServerSocket(kgPort, kTRUE);
121   fServerSocket->SetOption(kNoBlock, 1);
122   fDisplaySocket = NULL;
123   CheckForConnections();
124
125   fStatus = kStopped;
126   fStopping = kFALSE;
127 }
128
129 //_____________________________________________________________________________
130 AliMonitorProcess::~AliMonitorProcess()
131 {
132 // clean up
133
134   fMonitors.Delete();
135   delete fTopFolder;
136   delete fRunLoader;
137
138   delete fServerSocket;
139   fSockets.Delete();
140   delete fDisplaySocket;
141
142   fGrid->Close();
143   delete fGrid;
144
145   fFile->Close();
146   delete fFile;
147   gSystem->Unlink("monitor_tree.root");
148 }
149
150
151 //_____________________________________________________________________________
152 const char* AliMonitorProcess::GetRevision()
153 {
154   return "$Revision$";
155 }
156
157
158 //_____________________________________________________________________________
159 void AliMonitorProcess::Run()
160 {
161 // run the monitor process: 
162 //  check for a raw data file, process the raw data file and delete it
163
164   fStopping = kFALSE;
165
166   while (!fStopping) {
167     fStatus = kWaiting;
168     while (!CheckForNewFile()) {
169       CheckForConnections();
170       fStatus = kWaiting;
171       if (fStopping) break;
172       gSystem->Sleep(10);
173     }
174     if (fStopping) break;
175
176     ProcessFile();
177   }
178
179   WriteHistos();
180
181   fStopping = kFALSE;
182   fStatus = kStopped;
183 }
184
185
186 //_____________________________________________________________________________
187 void AliMonitorProcess::Stop()
188 {
189 // set the fStopping flag to terminate the monitor process after the current
190 // event was processed
191
192   if (fStatus != kStopped) fStopping = kTRUE;
193 }
194
195
196 //_____________________________________________________________________________
197 void AliMonitorProcess::ProcessFile(const char* fileName)
198 {
199 // create a file with monitor histograms for a single file
200
201   if (fStatus != kStopped) {
202     Error("ProcessFile", "ProcessFile can not be called"
203           " while the monitor process is running");
204     return;
205   }
206
207   fFileName = fileName;
208   Int_t nEventMin = fNEventsMin;
209   fNEventsMin = 1;
210   ProcessFile();
211   WriteHistos();
212   fNEventsMin = nEventMin;
213   fStatus = kStopped;
214 }
215
216
217 //_____________________________________________________________________________
218 Bool_t AliMonitorProcess::CheckForNewFile()
219 {
220 // check whether a new file was registered in alien
221
222   TGridResult* result = fGrid->Ls();
223   Long_t maxDate = -1;
224   Long_t maxTime = -1;
225   TString fileName;
226
227   while (const char* entry = result->Next()) {
228     // entry = host_date_time.root
229     TString entryCopy(entry);
230     char* p = const_cast<char*>(entryCopy.Data());
231     if (!strtok(p, "_") || !p) continue;  // host name
232     char* dateStr = strtok(p, "_");
233     if (!dateStr || !p) continue;
234     char* timeStr = strtok(p, ".");
235     if (!timeStr || !p) continue;
236     Long_t date = atoi(dateStr);
237     Long_t time = atoi(timeStr);
238
239     if ((date > maxDate) || ((date == maxDate) && (time > maxTime))) {
240       maxDate = date;
241       maxTime = time;
242       fileName = entry;
243     }
244   }
245
246   if (maxDate < 0) return kFALSE;  // no files found
247   if (fLogicalFileName.CompareTo(fileName) == 0) return kFALSE;  // no new file
248
249   fLogicalFileName = fileName;
250   fFileName = fGrid->GetPhysicalFileName(fLogicalFileName.Data());
251   return kTRUE;
252 }
253
254 //_____________________________________________________________________________
255 Bool_t AliMonitorProcess::ProcessFile()
256 {
257 // loop over all events in the raw data file, run the reconstruction
258 // and fill the monitor histograms
259
260   Int_t nEvents = GetNumberOfEvents(fFileName);
261   if (nEvents <= 0) return kFALSE;
262   Info("ProcessFile", "found %d event(s) in file %s", 
263        nEvents, fFileName.Data());
264
265   // loop over the events
266   for (Int_t iEvent = 0; iEvent < nEvents; iEvent++) {
267     fStatus = kReading;
268     fRunLoader->SetEventNumber(0);
269     AliRawReaderRoot rawReader(fFileName, iEvent);
270     if (fStopping) break;
271     if (rawReader.GetRunNumber() != fRunNumber) {
272       WriteHistos();
273       StartNewRun();
274       fRunNumber = rawReader.GetRunNumber();
275       fEventNumber[0] = rawReader.GetEventId()[0];
276       fEventNumber[1] = rawReader.GetEventId()[1];
277       fSubRunNumber = 0;
278       if (fStopping) break;
279     }
280
281     if (!ReconstructTPC(&rawReader)) return kFALSE;
282     if (fStopping) break;
283     if (!ReconstructITS(&rawReader)) return kFALSE;
284     if (fStopping) break;
285     if (!ReconstructV0s()) return kFALSE;
286     if (fStopping) break;
287
288     if (fDisplaySocket) fDisplaySocket->Send("new event");
289
290     Info("ProcessFile", "filling histograms...");
291     fStatus = kFilling;
292     for (Int_t iMonitor = 0; iMonitor < fMonitors.GetEntriesFast(); iMonitor++) {
293       ((AliMonitor*) fMonitors[iMonitor])->FillHistos(fRunLoader, &rawReader);
294       if (fStopping) break;
295     }
296     if (fStopping) break;
297
298     Info("ProcessFile", "updating histograms...");
299     fStatus = kUpdating;
300     TIterator* iFolder = fTopFolder->GetListOfFolders()->MakeIterator();
301     while (TFolder* folder = (TFolder*) iFolder->Next()) {
302       TIterator* iHisto = folder->GetListOfFolders()->MakeIterator();
303       while (AliMonitorPlot* histo = (AliMonitorPlot*) iHisto->Next()) {
304         histo->Update();
305       }
306       delete iHisto;
307     }
308     delete iFolder;
309     if (fStopping) break;
310
311     Info("ProcessFile", "filling the tree...");
312     fTree->Fill();
313
314     Info("ProcessFile", "broadcasting histograms...");
315     CheckForConnections();
316     BroadcastHistos();
317
318     fNEvents++;
319     if (fStopping) break;
320   }
321
322   return kTRUE;
323 }
324
325 //_____________________________________________________________________________
326 void AliMonitorProcess::Reset()
327 {
328 // write the current histograms to a file and reset them
329
330   if (fSubRunNumber == 0) fSubRunNumber++;
331   WriteHistos();
332   StartNewRun();
333   fSubRunNumber++;
334 }
335
336
337 //_____________________________________________________________________________
338 UInt_t AliMonitorProcess::GetEventPeriodNumber()
339 {
340 // get the period number from the event id
341
342   return (fEventNumber[1] >> 4);
343 }
344
345 //_____________________________________________________________________________
346 UInt_t AliMonitorProcess::GetEventOrbitNumber()
347 {
348 // get the orbit number from the event id
349
350   return ((fEventNumber[1] & 0x000F) << 20) + (fEventNumber[0] >> 12);
351 }
352
353 //_____________________________________________________________________________
354 UInt_t AliMonitorProcess::GetEventBunchNumber()
355 {
356 // get the bunch number from the event id
357
358   return (fEventNumber[0] % 0x0FFF);
359 }
360
361 //_____________________________________________________________________________
362 Int_t AliMonitorProcess::GetNumberOfEvents(const char* fileName)
363 {
364 // determine the number of events in the given raw data file
365
366   Int_t nEvents = -1;
367
368   TFile* file = TFile::Open(fileName);
369   if (!file || !file->IsOpen()) {
370     Error("GetNumberOfEvents", "could not open file %s", fileName);
371     if (file) delete file;
372     return -1;
373   }
374
375   TTree* tree = (TTree*) file->Get("RAW");
376   if (!tree) {
377     Error("GetNumberOfEvents", "could not find tree with raw data");
378   } else {
379     nEvents = (Int_t) tree->GetEntries();
380   }
381   file->Close();
382   delete file;
383
384   return nEvents;
385 }
386
387 //_____________________________________________________________________________
388 Bool_t AliMonitorProcess::ReconstructTPC(AliRawReader* rawReader)
389 {
390 // find TPC clusters and tracks
391
392   fStatus = kRecTPC;
393
394   AliLoader* tpcLoader = fRunLoader->GetLoader("TPCLoader");
395   if (!tpcLoader) {
396     Error("ReconstructTPC", "no TPC loader found");
397     return kFALSE;
398   }
399   gSystem->Unlink("TPC.RecPoints.root");
400   gSystem->Unlink("TPC.Tracks.root");
401
402   // cluster finder
403   Info("ReconstructTPC", "reconstructing clusters...");
404   tpcLoader->LoadRecPoints("recreate");
405   AliTPCclustererMI clusterer(fTPCParam);
406   tpcLoader->MakeRecPointsContainer();
407   clusterer.SetOutput(tpcLoader->TreeR());
408   clusterer.Digits2Clusters(rawReader);
409   tpcLoader->WriteRecPoints("OVERWRITE");
410
411   // track finder
412   Info("ReconstructTPC", "reconstructing tracks...");
413   tpcLoader->LoadTracks("recreate");
414   {
415     AliTPCtrackerMI tracker(fTPCParam);
416     tracker.Clusters2Tracks();
417   }
418
419   tpcLoader->UnloadRecPoints();
420   tpcLoader->UnloadTracks();
421   return kTRUE;
422 }
423
424 //_____________________________________________________________________________
425 Bool_t AliMonitorProcess::ReconstructITS(AliRawReader* rawReader)
426 {
427 // find ITS clusters and tracks
428
429   fStatus = kRecITS;
430
431   AliLoader* itsLoader = fRunLoader->GetLoader("ITSLoader");
432   if (!itsLoader) {
433     Error("ReconstructITS", "no ITS loader found");
434     return kFALSE;
435   }
436   AliLoader* tpcLoader = fRunLoader->GetLoader("TPCLoader");
437   if (!tpcLoader) {
438     Error("ReconstructITS", "no TPC loader found");
439     return kFALSE;
440   }
441   gSystem->Unlink("ITS.RecPoints.root");
442   gSystem->Unlink("ITS.Tracks.root");
443
444   // cluster finder
445   Info("ReconstructITS", "reconstructing clusters...");
446   itsLoader->LoadRecPoints("recreate");
447   AliITSclustererV2 clusterer(fITSgeom);
448   itsLoader->MakeRecPointsContainer();
449   clusterer.Digits2Clusters(rawReader);
450
451   // track finder
452   Info("ReconstructITS", "reconstructing tracks...");
453   itsLoader->LoadTracks("recreate");
454   itsLoader->MakeTracksContainer();
455   tpcLoader->LoadTracks();
456   AliITStrackerV2 tracker(fITSgeom);
457   tracker.LoadClusters(itsLoader->TreeR());
458   tracker.Clusters2Tracks(tpcLoader->TreeT(), itsLoader->TreeT());
459   tracker.UnloadClusters();
460   itsLoader->WriteTracks("OVERWRITE");
461
462   itsLoader->UnloadRecPoints();
463   itsLoader->UnloadTracks();
464   tpcLoader->UnloadTracks();
465   return kTRUE;
466 }
467
468 //_____________________________________________________________________________
469 Bool_t AliMonitorProcess::ReconstructV0s()
470 {
471 // find V0s
472
473   fStatus = kRecV0s;
474
475   AliITSLoader* itsLoader = (AliITSLoader*) fRunLoader->GetLoader("ITSLoader");
476   if (!itsLoader) {
477     Error("ReconstructV0", "no ITS loader found");
478     return kFALSE;
479   }
480   gSystem->Unlink("ITS.V0s.root");
481
482   // V0 finder
483   Info("ReconstructV0s", "reconstructing V0s...");
484   itsLoader->LoadTracks("read");
485   itsLoader->LoadV0s("recreate");
486   AliV0vertexer vertexer;
487   TTree* tracks = itsLoader->TreeT();
488   if (!tracks) {
489     Error("ReconstructV0s", "no ITS tracks tree found");
490     return kFALSE;
491   }
492   if (!itsLoader->TreeV0()) itsLoader->MakeTree("V0");
493   TTree* v0s = itsLoader->TreeV0();
494   vertexer.Tracks2V0vertices(tracks, v0s);
495   itsLoader->WriteV0s("OVERWRITE");
496
497   itsLoader->UnloadTracks();
498   itsLoader->UnloadV0s();
499   return kTRUE;
500 }
501
502
503 //_____________________________________________________________________________
504 Bool_t AliMonitorProcess::WriteHistos()
505 {
506 // write the monitor tree and the monitor histograms to the file 
507 // "monitor_<run number>[_<sub_run_number>].root"
508 // if at least fNEventsMin events were monitored
509
510   fStatus = kWriting;
511
512   // rename tree file and create a new one
513   fFile->cd();
514   fTree->Write();
515   fFile->Close();
516   delete fFile;
517
518   char fileName[256];
519   sprintf(fileName, "monitor_tree_%d.root", fRunNumber);
520   if (fSubRunNumber > 0) {
521     sprintf(fileName, "monitor_tree_%d_%d.root", fRunNumber, fSubRunNumber);
522   }
523   if (fNEvents < fNEventsMin) {
524     gSystem->Unlink("monitor_tree.root");
525   } else {
526     gSystem->Rename("monitor_tree.root", fileName);
527   }
528
529   fFile = TFile::Open("monitor_tree.root", "RECREATE");
530   if (!fFile || !fFile->IsOpen()) {
531     Fatal("WriteHistos", "could not open file for tree");
532   }
533   fTree = new TTree("MonitorTree", "tree for monitoring");
534   for (Int_t iMonitor = 0; iMonitor < fMonitors.GetEntriesFast(); iMonitor++) {
535     ((AliMonitor*) fMonitors[iMonitor])->CreateBranches(fTree);
536   }
537   gROOT->cd();
538
539   // write the histograms
540   if (fNEvents < fNEventsMin) return kTRUE;
541
542   if (!fWriteHistoList) {
543     TIterator* iFolder = fTopFolder->GetListOfFolders()->MakeIterator();
544     while (TFolder* folder = (TFolder*) iFolder->Next()) {
545       TIterator* iHisto = folder->GetListOfFolders()->MakeIterator();
546       while (AliMonitorPlot* histo = (AliMonitorPlot*) iHisto->Next()) {
547         histo->ResetList();
548       }
549       delete iHisto;
550     }
551     delete iFolder;
552   }
553
554   Bool_t result = kTRUE;
555   sprintf(fileName, "monitor_%d.root", fRunNumber);
556   if (fSubRunNumber > 0) {
557     sprintf(fileName, "monitor_%d_%d.root", fRunNumber, fSubRunNumber);
558   }
559   TFile* file = TFile::Open(fileName, "recreate");
560   if (!file || !file->IsOpen()) {
561     Error("WriteHistos", "could not open file %s", fileName);
562     result = kFALSE;
563   } else {
564     fTopFolder->Write();
565     file->Close();
566   }
567   if (file) delete file;
568
569   return result;
570 }
571
572 //_____________________________________________________________________________
573 void AliMonitorProcess::StartNewRun()
574 {
575 // reset the histograms for a new run
576
577   fStatus = kResetting;
578   TIterator* iFolder = fTopFolder->GetListOfFolders()->MakeIterator();
579   while (TFolder* folder = (TFolder*) iFolder->Next()) {
580     TIterator* iHisto = folder->GetListOfFolders()->MakeIterator();
581     while (AliMonitorPlot* histo = (AliMonitorPlot*) iHisto->Next()) {
582       histo->Reset();
583     }
584     delete iHisto;
585   }
586   delete iFolder;
587
588   fNEvents = 0;
589 }
590
591
592 //_____________________________________________________________________________
593 void AliMonitorProcess::CheckForConnections()
594 {
595 // check if new clients want to connect and add them to the list of sockets
596
597   TMessage message(kMESS_OBJECT);
598   message.WriteObject(fTopFolder); 
599   fStatus = kConnecting;
600
601   TSocket* socket;
602   while ((socket = fServerSocket->Accept()) != (TSocket*)-1) {
603     char socketType[256];
604     if (!socket->Recv(socketType, 255)) continue;
605     if (strcmp(socketType, "client") == 0) {
606       if ((fNEvents == 0) || (socket->Send(message) >= 0)) {
607         fSockets.Add(socket);
608         TInetAddress adr = socket->GetInetAddress();
609         Info("CheckForConnections", "new client:\n %s (%s), port %d\n",
610              adr.GetHostName(), adr.GetHostAddress(), adr.GetPort());
611       }
612     } else if (strcmp(socketType, "display") == 0) {
613       if (fDisplaySocket) {
614         fDisplaySocket->Close();
615         delete fDisplaySocket;
616       }
617       fDisplaySocket = socket;
618       fDisplaySocket->SetOption(kNoBlock, 1);
619       TInetAddress adr = socket->GetInetAddress();
620       Info("CheckForConnections", "new display:\n %s (%s), port %d\n",
621            adr.GetHostName(), adr.GetHostAddress(), adr.GetPort());
622     }
623   }
624
625   for (Int_t iSocket = 0; iSocket < fSockets.GetEntriesFast(); iSocket++) {
626     socket = (TSocket*) fSockets[iSocket];
627     if (!socket) continue;
628     if (!socket->IsValid()) {
629       // remove invalid sockets from the list
630       TInetAddress adr = socket->GetInetAddress();
631       Info("BroadcastHistos", "disconnect client:\n %s (%s), port %d\n",
632            adr.GetHostName(), adr.GetHostAddress(), adr.GetPort());
633       delete fSockets.RemoveAt(iSocket);
634     }
635   }
636   fSockets.Compress();
637 }
638
639 //_____________________________________________________________________________
640 void AliMonitorProcess::BroadcastHistos()
641 {
642 // send the monitor histograms to the clients
643
644   fStatus = kBroadcasting;
645   TMessage message(kMESS_OBJECT);
646   message.WriteObject(fTopFolder); 
647
648   for (Int_t iSocket = 0; iSocket < fSockets.GetEntriesFast(); iSocket++) {
649     TSocket* socket = (TSocket*) fSockets[iSocket];
650     if (!socket) continue;
651     if (!socket->IsValid() || (socket->Send(message) < 0)) {
652       // remove the socket from the list if there was an error
653       TInetAddress adr = socket->GetInetAddress();
654       Info("BroadcastHistos", "disconnect client:\n %s (%s), port %d\n",
655            adr.GetHostName(), adr.GetHostAddress(), adr.GetPort());
656       delete fSockets.RemoveAt(iSocket);
657     }
658   }
659   fSockets.Compress();
660 }