adding helper component for the automatic generation of compressed TPC cluster data...
[u/mrichter/AliRoot.git] / MONITOR / AliOnlineReco.cxx
1 // @(#)root/eve:$Id$
2 // Author: Matevz Tadel 2007
3
4 /**************************************************************************
5  * Copyright(c) 1998-2008, ALICE Experiment at CERN, all rights reserved. *)
6  * See http://aliceinfo.cern.ch/Offline/AliRoot/License.html for          *
7  * full copyright notice.                                                 *
8  **************************************************************************/
9
10 #include "AliOnlineReco.h"
11 #include "AliChildProcTerminator.h"
12 #include "AliDimIntNotifier.h"
13 #include "AliCDBManager.h"
14 #include "AliGRPPreprocessor.h"
15
16 #include <TTimer.h>
17
18 #include <TGListBox.h>
19 #include <TGButton.h>
20
21 #include <TInterpreter.h>
22
23 #include <unistd.h>
24 #include <signal.h>
25
26 //______________________________________________________________________________
27 // Full description of AliOnlineReco
28 //
29
30 ClassImp(AliOnlineReco)
31
32 AliOnlineReco::AliOnlineReco() :
33   TGMainFrame(gClient->GetRoot(), 400, 400),
34
35   fRunList(0), fAutoRun(0), fStartButt(0), fStopButt(0), fExitButt(0),
36   fAutoRunTimer(0), fAutoRunScheduled(0), fAutoRunRunning(0),
37   fRun2PidMap(),
38   fTestMode(kFALSE)
39 {
40   // Constructor.
41
42   // GUI components.
43   fRunList = new TGListBox(this);
44   AddFrame(fRunList, new TGLayoutHints(kLHintsNormal | kLHintsExpandX | kLHintsExpandY));
45
46   TGHorizontalFrame *hf = new TGHorizontalFrame(this, 1, 20);
47
48   fAutoRun = new TGCheckButton(hf, "AutoRun");
49   hf->AddFrame(fAutoRun, new TGLayoutHints(kLHintsNormal | kLHintsExpandX | kLHintsExpandY));
50   fAutoRun->Connect("Clicked()", "AliOnlineReco", this, "DoAutoRun()");
51
52   fStartButt = new TGTextButton(hf, "Start");
53   hf->AddFrame(fStartButt, new TGLayoutHints(kLHintsNormal | kLHintsExpandX | kLHintsExpandY));
54   fStartButt->Connect("Clicked()", "AliOnlineReco", this, "DoStart()");
55
56   fStopButt = new TGTextButton(hf, "Stop");
57   hf->AddFrame(fStopButt, new TGLayoutHints(kLHintsNormal | kLHintsExpandX | kLHintsExpandY));
58   fStopButt->Connect("Clicked()", "AliOnlineReco", this, "DoStop()");
59
60   fExitButt = new TGTextButton(hf, "Exit");
61   hf->AddFrame(fExitButt, new TGLayoutHints(kLHintsNormal | kLHintsExpandX | kLHintsExpandY));
62   fExitButt->Connect("Clicked()", "AliOnlineReco", this, "DoExit()");
63
64   AddFrame(hf, new TGLayoutHints(kLHintsNormal | kLHintsExpandX));
65
66   MapSubwindows();
67   Layout();
68   SetWindowName("Alice Online Reconstruction");
69
70   // DIM interface.  
71   for (Int_t i = 0; i < 5; ++i)
72   {
73     if (i == 0)
74     {
75       fSOR[i] = new AliDimIntNotifier("/LOGBOOK/SUBSCRIBE/DAQ_SOR_PHYSICS");
76       fEOR[i] = new AliDimIntNotifier("/LOGBOOK/SUBSCRIBE/DAQ_EOR_PHYSICS");
77     }
78     else
79     {
80       fSOR[i] = new AliDimIntNotifier(Form("/LOGBOOK/SUBSCRIBE/DAQ_SOR_PHYSICS_%d", i));
81       fEOR[i] = new AliDimIntNotifier(Form("/LOGBOOK/SUBSCRIBE/DAQ_EOR_PHYSICS_%d", i));
82     }
83
84     fSOR[i]->Connect("DimMessage(Int_t)", "AliOnlineReco", this, "StartOfRun(Int_t)");
85     fEOR[i]->Connect("DimMessage(Int_t)", "AliOnlineReco", this, "EndOfRun(Int_t)");
86   }
87
88   const Int_t autoRunDelay = 10; // should go to config
89   fAutoRunTimer = new TTimer(autoRunDelay * 1000l);
90   fAutoRunTimer->Connect("Timeout()", "AliOnlineReco", this, "AutoRunTimerTimeout()");
91
92   // Signal handlers
93   // ROOT's TSignalHAndler works not SIGCHLD ...
94   AliChildProcTerminator::Instance()->Connect("ChildProcTerm(Int_t,Int_t)", "AliOnlineReco", this, "ChildProcTerm(Int_t,Int_t)");
95 }
96
97 AliOnlineReco::~AliOnlineReco()
98 {
99   // Destructor.
100
101   delete fAutoRunTimer;
102 }
103
104 Int_t AliOnlineReco::GetLastRun() const
105 {
106   // Returns the last started run.
107
108   return fRun2PidMap.empty() ? 0 : fRun2PidMap.rbegin()->first;
109 }
110
111 Bool_t AliOnlineReco::GetAutoRunMode() const
112 {
113   // Return state of auto-run flag.
114
115   return fAutoRun->IsOn();
116 }
117
118 void AliOnlineReco::SetAutoRunMode(Bool_t ar)
119 {
120   // Set auto-run flag.
121
122   if (ar == fAutoRun->IsOn())
123     return;
124
125   fAutoRun->SetState(ar ? kButtonDown : kButtonUp, kTRUE);
126 }
127
128 //------------------------------------------------------------------------------
129 // Private methods
130 //------------------------------------------------------------------------------
131
132 AliOnlineReco::mIntInt_i AliOnlineReco::FindMapEntryByPid(Int_t pid)
133 {
134   // Find run-to-pid map iterator by pid.
135   // Requires iteration over map.
136
137   for (mIntInt_i i = fRun2PidMap.begin(); i != fRun2PidMap.end(); ++i)
138   {
139     if (i->second == pid)
140       return i;
141   }
142
143   return fRun2PidMap.end();
144 }
145
146 void AliOnlineReco::StartAliEve(mIntInt_i& mi)
147 {
148   // Start alieve to process run given my the run-pid entry.
149
150   Int_t run = mi->first;
151
152   if (mi->second == 0)
153   {
154     pid_t pid = fork();
155     if (pid == -1)
156     {
157       perror("DoStart -- Fork failed");
158       return;
159     }
160
161     if (pid)
162     {
163       mi->second = pid;
164       fRunList->RemoveEntry(run);
165       fRunList->AddEntrySort(TString::Format("%-20d -- RUNNING", run), run);
166       fRunList->Layout();
167     }
168     else
169     {
170       gCINTMutex = 0;
171
172       struct sigaction sac;
173       sac.sa_handler = 0;
174       sigemptyset(&sac.sa_mask);
175       sac.sa_flags = 0;
176       sigaction(SIGCHLD, &sac, 0);
177
178       int s;
179       if (fTestMode)
180       {
181         s = execlp("alitestproc", "alitestproc", TString::Format("%d", run).Data(), (char*) 0);
182       }
183       else
184       {
185         Int_t procPID = gSystem->GetPid();
186         TString logFile = Form("%s/reco/log/run%d_%d.log",
187                                gSystem->Getenv("ONLINERECO_BASE_DIR"),
188                                run,
189                                (Int_t)procPID);
190         Info("DoStart","Reconstruction log will be written to %s",logFile.Data());
191         gSystem->RedirectOutput(logFile.Data());
192
193         gSystem->cd(Form("%s/reco",gSystem->Getenv("ONLINERECO_BASE_DIR")));
194
195         TString gdcs;
196         if (RetrieveGRP(run,gdcs) <= 0 || gdcs.IsNull()) 
197           gSystem->Exit(1);
198
199         gSystem->Setenv("DATE_RUN_NUMBER", Form("%d", run));
200         // Setting CDB
201 //      AliCDBManager * man = AliCDBManager::Instance();
202 //      man->SetDefaultStorage("local:///local/cdb");
203 //      man->SetSpecificStorage("GRP/GRP/Data",
204 //                            Form("local://%s",gSystem->pwd()));
205 //      man->SetSpecificStorage("GRP/CTP/Config",
206 //                            Form("local://%s",gSystem->pwd()));
207 //      man->SetSpecificStorage("ACORDE/Align/Data",
208 //                              "local://$ALICE_ROOT/OCDB");
209
210         gSystem->mkdir(Form("run%d_%d", run, (Int_t)procPID));
211         gSystem->cd(Form("run%d_%d", run, (Int_t)procPID));
212
213         TString recMacroPath(gSystem->Getenv("ONLINERECO_MACRO"));
214         if (recMacroPath.IsNull()) {
215           recMacroPath = "$ALICE_ROOT/MONITOR/rec.C";
216         }
217
218         s = execlp("alieve",
219                    "alieve",
220                    "-q",
221                    Form("%s(\"mem://@*:\")", gSystem->ExpandPathName(recMacroPath.Data())),
222                    (char*) 0);
223
224         gSystem->Exec(Form("rm -rf %s/reco/run%d_%d",gSystem->Getenv("ONLINERECO_BASE_DIR"),run,(Int_t)procPID));
225       }
226
227       if (s == -1)
228       {
229         perror("execlp failed - this will not end well");
230         gSystem->Exit(1);
231       }
232     }
233   }
234   else
235   {
236     Error("DoStart", "Process already running.");
237   }
238 }
239
240 void AliOnlineReco::KillPid(Int_t pid)
241 {
242   // Terminate process given by pid.
243
244   // Send terminate signal to process ...
245
246   if (fTestMode)
247   {
248     kill(pid, SIGTERM);
249   }
250   else
251   {
252     // alieve will auto-destruct on SIGUSR1
253     kill(pid, SIGUSR1);
254   }
255 }
256
257 void AliOnlineReco::StartAutoRunTimer(Int_t run)
258 {
259   // Start timer for given run.
260   // If an auto-started run is already active, this call is ignored.
261   // If timer is already active, it is restarted.
262
263   if (fAutoRunRunning)
264     return;
265
266   fAutoRunTimer->Reset();
267   fAutoRunTimer->TurnOn();
268   fAutoRunScheduled = run;
269
270   Info("StartAutoRunTimer", "Scheduling run %d for auto-display.", run);
271 }
272
273 void AliOnlineReco::StopAutoRunTimer()
274 {
275   // Stop auto-run timer.
276
277   fAutoRunTimer->TurnOff();
278   fAutoRunScheduled = 0;
279 }
280
281 void AliOnlineReco::AutoRunTimerTimeout()
282 {
283   // Slot called on auto-timer timeout.
284
285   Int_t run = fAutoRunScheduled;
286
287   StopAutoRunTimer();
288
289   mIntInt_i i = fRun2PidMap.find(run);
290
291   if (i == fRun2PidMap.end())
292   {
293     Warning("AutoRunTimerTimeout", "run no longer active.");
294     return;
295   }
296
297   Info("AutoRunTimerTimeout", "Starting display for run %d.", run);
298
299   StartAliEve(i);
300   fAutoRunRunning = run;
301 }
302
303 //------------------------------------------------------------------------------
304 // Handlers of DIM signals.
305 //------------------------------------------------------------------------------
306
307 void AliOnlineReco::StartOfRun(Int_t run)
308 {
309   // Slot called from DIM handler on start of run.
310
311   mIntInt_i i = fRun2PidMap.find(run);
312   if (i == fRun2PidMap.end())
313   {
314     fRun2PidMap[run] = 0;
315     fRunList->AddEntrySort(TString::Format("%d", run), run);
316     fRunList->Layout();
317
318     if (fAutoRun->IsOn())
319     {
320       StartAutoRunTimer(run);
321     }
322   }
323   else
324   {
325     Error("StartOfRun", "Run %d already registered.", run);
326   }
327 }
328
329 void AliOnlineReco::EndOfRun(Int_t run)
330 {
331   // Slot called from DIM handler on stop of run.
332
333   mIntInt_i i = fRun2PidMap.find(run);
334   if (i != fRun2PidMap.end())
335   {
336     Int_t pid = i->second;
337     fRunList->RemoveEntry(run);
338     fRunList->Layout();
339     fRun2PidMap.erase(i);
340     if (pid)
341     {
342       KillPid(pid);
343     }
344     gClient->NeedRedraw(fRunList);
345
346     if (fAutoRunRunning == run)
347     {
348       fAutoRunRunning = 0;
349     }
350   }
351   else
352   {
353     Error("EndOfRun", "Run %d not registered.", run);
354   }
355 }
356
357 //------------------------------------------------------------------------------
358 // Handlers of OS signals.
359 //------------------------------------------------------------------------------
360
361 void AliOnlineReco::ChildProcTerm(Int_t pid, Int_t status)
362 {
363   // Slot called on termination of child process.
364
365   printf("child process termination pid=%d, status=%d...\n", pid, status);
366
367   mIntInt_i i = FindMapEntryByPid(pid);
368   if (i != fRun2PidMap.end())
369   {
370     Int_t run = i->first;
371     fRunList->RemoveEntry(run);
372     if (status == 0)
373     {
374       fRunList->AddEntrySort(TString::Format("%-20d -- PROCESSED", run), run);
375     }
376     else
377     {
378       fRunList->AddEntrySort(TString::Format("%-20d -- PROCESSED [%d]", run, status), run);
379     }
380     fRunList->Layout();
381     i->second = 0;
382
383     if (fAutoRunRunning == run && fAutoRun->IsOn())
384     {
385       fAutoRunRunning = 0;
386       StartAutoRunTimer(run);
387     }
388     else
389     {
390       fAutoRunRunning = 0;
391     }
392   }
393   else
394   {
395     Warning("ChildProcTerm", "Process with pid=%d not registered.", pid);
396   }
397 }
398
399 //------------------------------------------------------------------------------
400 // Handlers of button signals.
401 //------------------------------------------------------------------------------
402
403 void AliOnlineReco::DoAutoRun()
404 {
405   // Slot called from auto-run check-box.
406
407   Bool_t autoRun = fAutoRun->IsOn();
408
409   if (autoRun)
410     fStartButt->SetEnabled(kFALSE);
411   else
412     fStartButt->SetEnabled(kTRUE);    
413 }
414
415 void AliOnlineReco::DoStart()
416 {
417   // Slot called from Start button.
418
419   Int_t run = fRunList->GetSelected();
420   mIntInt_i i = fRun2PidMap.find(run);
421
422   if (i == fRun2PidMap.end())
423   {
424     Error("DoStart", "no selection");
425     return;
426   }
427
428   StartAliEve(i);
429 }
430
431 void AliOnlineReco::DoStop()
432 {
433   // Slot called from Stop button.
434
435   Int_t run = fRunList->GetSelected();
436   mIntInt_i i = fRun2PidMap.find(run);
437
438   if (i == fRun2PidMap.end())
439   {
440     Error("DoStop", "no selection");
441     return;
442   }
443
444   Int_t pid = i->second;
445   if (pid)
446   {
447     KillPid(pid);
448   }
449   else
450   {
451     Error("DoStop", "Process not running.");
452   }
453 }
454
455 void AliOnlineReco::DoExit()
456 {
457   // Slot called from Exit button.
458
459   gSystem->ExitLoop();
460 }
461
462 void AliOnlineReco::CloseWindow()
463 {
464   // Virtual method called when window-manager close-window button is pressed.
465
466   gSystem->ExitLoop();
467 }
468
469 Int_t AliOnlineReco::RetrieveGRP(UInt_t run, TString &gdc)
470 {
471   // Retrieve GRP entry for given run from aldaqdb.
472
473   TString dbHost = gSystem->Getenv("ONLINERECO_DB_HOST");
474   if (dbHost.IsNull())
475   {
476     dbHost = "aldaqdb";
477   }
478
479   TString dbPort = gSystem->Getenv("ONLINERECO_DB_PORT");
480   if (dbPort.IsNull())
481   {
482     dbPort = "0";
483   }
484
485   TString dbName = gSystem->Getenv("ONLINERECO_DB_NAME");
486   if (dbName.IsNull())
487   {
488     dbName = "LOGBOOK";
489   }
490
491   TString user = gSystem->Getenv("ONLINERECO_DB_USER");
492   if (user.IsNull())
493   {
494     user = "logbook";
495   }
496
497   TString password = gSystem->Getenv("ONLINERECO_DB_PASSWORD");
498   if (password.IsNull())
499   {
500     password = "alice";
501   }
502
503   Int_t ret=AliGRPPreprocessor::ReceivePromptRecoParameters(run, dbHost.Data(),
504                                                         dbPort.Atoi(), dbName.Data(),
505                                                         user.Data(), password.Data(),
506                                                         Form("local://%s",gSystem->pwd()),
507                                                         gdc);
508
509   if(ret>0) Info("RetrieveGRP","Last run of the same type is: %d",ret);
510   else if(ret==0) Warning("RetrieveGRP","No previous run of the same type found");
511   else if(ret<0) Error("Retrieve","Error code while retrieving GRP parameters returned: %d",ret);
512   return(ret);
513 }