Technical hotfixes for the event display in ACR.
[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   // GUI components.
41   fRunList = new TGListBox(this);
42   AddFrame(fRunList, new TGLayoutHints(kLHintsNormal | kLHintsExpandX | kLHintsExpandY));
43
44   TGHorizontalFrame *hf = new TGHorizontalFrame(this, 1, 20);
45
46   fAutoRun = new TGCheckButton(hf, "AutoRun");
47   hf->AddFrame(fAutoRun, new TGLayoutHints(kLHintsNormal | kLHintsExpandX | kLHintsExpandY));
48   fAutoRun->Connect("Clicked()", "AliOnlineReco", this, "DoAutoRun()");
49
50   fStartButt = new TGTextButton(hf, "Start");
51   hf->AddFrame(fStartButt, new TGLayoutHints(kLHintsNormal | kLHintsExpandX | kLHintsExpandY));
52   fStartButt->Connect("Clicked()", "AliOnlineReco", this, "DoStart()");
53
54   fStopButt = new TGTextButton(hf, "Stop");
55   hf->AddFrame(fStopButt, new TGLayoutHints(kLHintsNormal | kLHintsExpandX | kLHintsExpandY));
56   fStopButt->Connect("Clicked()", "AliOnlineReco", this, "DoStop()");
57
58   fExitButt = new TGTextButton(hf, "Exit");
59   hf->AddFrame(fExitButt, new TGLayoutHints(kLHintsNormal | kLHintsExpandX | kLHintsExpandY));
60   fExitButt->Connect("Clicked()", "AliOnlineReco", this, "DoExit()");
61
62   AddFrame(hf, new TGLayoutHints(kLHintsNormal | kLHintsExpandX));
63
64   MapSubwindows();
65   Layout();
66   SetWindowName("Alice Online Reconstruction");
67
68   // DIM interface.  
69   for (Int_t i = 0; i < 5; ++i)
70   {
71     if (i == 0)
72     {
73       fSOR[i] = new AliDimIntNotifier("/LOGBOOK/SUBSCRIBE/DAQ_SOR_PHYSICS");
74       fEOR[i] = new AliDimIntNotifier("/LOGBOOK/SUBSCRIBE/DAQ_EOR_PHYSICS");
75     }
76     else
77     {
78       fSOR[i] = new AliDimIntNotifier(Form("/LOGBOOK/SUBSCRIBE/DAQ_SOR_PHYSICS_%d", i));
79       fEOR[i] = new AliDimIntNotifier(Form("/LOGBOOK/SUBSCRIBE/DAQ_EOR_PHYSICS_%d", i));
80     }
81
82     fSOR[i]->Connect("DimMessage(Int_t)", "AliOnlineReco", this, "StartOfRun(Int_t)");
83     fEOR[i]->Connect("DimMessage(Int_t)", "AliOnlineReco", this, "EndOfRun(Int_t)");
84   }
85
86   const Int_t autoRunDelay = 10; // should go to config
87   fAutoRunTimer = new TTimer(autoRunDelay * 1000l);
88   fAutoRunTimer->Connect("Timeout()", "AliOnlineReco", this, "AutoRunTimerTimeout()");
89
90   // Signal handlers
91   // ROOT's TSignalHAndler works not SIGCHLD ...
92   AliChildProcTerminator::Instance()->Connect("ChildProcTerm(Int_t,Int_t)", "AliOnlineReco", this, "ChildProcTerm(Int_t,Int_t)");
93 }
94
95 AliOnlineReco::~AliOnlineReco()
96 {
97   delete fAutoRunTimer;
98 }
99
100 Int_t AliOnlineReco::GetLastRun() const
101 {
102   return fRun2PidMap.empty() ? 0 : fRun2PidMap.rbegin()->first;
103 }
104
105 Bool_t AliOnlineReco::GetAutoRunMode() const
106 {
107   return fAutoRun->IsOn();
108 }
109
110 void AliOnlineReco::SetAutoRunMode(Bool_t ar)
111 {
112   if (ar == fAutoRun->IsOn())
113     return;
114
115   fAutoRun->SetState(ar ? kButtonDown : kButtonUp, kTRUE);
116 }
117
118 //------------------------------------------------------------------------------
119 // Private methods
120 //------------------------------------------------------------------------------
121
122 AliOnlineReco::mIntInt_i AliOnlineReco::FindMapEntryByPid(Int_t pid)
123 {
124   for (mIntInt_i i = fRun2PidMap.begin(); i != fRun2PidMap.end(); ++i)
125   {
126     if (i->second == pid)
127       return i;
128   }
129
130   return fRun2PidMap.end();
131 }
132
133 void AliOnlineReco::StartAliEve(mIntInt_i& mi)
134 {
135   Int_t run = mi->first;
136
137   if (mi->second == 0)
138   {
139     pid_t pid = fork();
140     if (pid == -1)
141     {
142       perror("DoStart -- Fork failed");
143       return;
144     }
145
146     if (pid)
147     {
148       mi->second = pid;
149       fRunList->RemoveEntry(run);
150       fRunList->AddEntrySort(TString::Format("%-20d -- RUNNING", run), run);
151       fRunList->Layout();
152     }
153     else
154     {
155       gCINTMutex = 0;
156
157       struct sigaction sac;
158       sac.sa_handler = 0;
159       sigemptyset(&sac.sa_mask);
160       sac.sa_flags = 0;
161       sigaction(SIGCHLD, &sac, 0);
162
163       int s;
164       if (fTestMode)
165       {
166         s = execlp("alitestproc", "alitestproc", TString::Format("%d", run).Data(), (char*) 0);
167       }
168       else
169       {
170         Int_t procPID = gSystem->GetPid();
171         TString logFile = Form("%s/reco/log/run%d_%d.log",
172                                gSystem->Getenv("ONLINERECO_BASE_DIR"),
173                                run,
174                                (Int_t)procPID);
175         Info("DoStart","Reconstruction log will be written to %s",logFile.Data());
176         gSystem->RedirectOutput(logFile.Data());
177
178         gSystem->cd(Form("%s/reco",gSystem->Getenv("ONLINERECO_BASE_DIR")));
179
180         TString gdcs;
181         if (RetrieveGRP(run,gdcs) <= 0 || gdcs.IsNull()) 
182           gSystem->Exit(1);
183
184         gSystem->Setenv("DATE_RUN_NUMBER", Form("%d", run));
185         // Setting CDB
186 //      AliCDBManager * man = AliCDBManager::Instance();
187 //      man->SetDefaultStorage("local:///local/cdb");
188 //      man->SetSpecificStorage("GRP/GRP/Data",
189 //                            Form("local://%s",gSystem->pwd()));
190 //      man->SetSpecificStorage("GRP/CTP/Config",
191 //                            Form("local://%s",gSystem->pwd()));
192 //      man->SetSpecificStorage("ACORDE/Align/Data",
193 //                              "local://$ALICE_ROOT/OCDB");
194
195         gSystem->mkdir(Form("run%d_%d", run, (Int_t)procPID));
196         gSystem->cd(Form("run%d_%d", run, (Int_t)procPID));
197
198         TString recMacroPath(gSystem->Getenv("ONLINERECO_MACRO"));
199         if (recMacroPath.IsNull()) {
200           recMacroPath = "$ALICE_ROOT/MONITOR/rec.C";
201         }
202
203         s = execlp("alieve",
204                    "alieve",
205                    "-q",
206                    Form("%s(\"mem://@*:\")", gSystem->ExpandPathName(recMacroPath.Data())),
207                    (char*) 0);
208       }
209
210       if (s == -1)
211       {
212         perror("execlp failed - this will not end well");
213         gSystem->Exit(1);
214       }
215     }
216   }
217   else
218   {
219     Error("DoStart", "Process already running.");
220   }
221 }
222
223 void AliOnlineReco::KillPid(Int_t pid)
224 {
225   // Send terminate signal to process ...
226
227   if (fTestMode)
228   {
229     kill(pid, SIGTERM);
230   }
231   else
232   {
233     // alieve will auto-destruct on SIGUSR1
234     kill(pid, SIGUSR1);
235   }
236 }
237
238 void AliOnlineReco::StartAutoRunTimer(Int_t run)
239 {
240   // Start timer for given run.
241   // If an auto-started run is already active, this call is ignored.
242   // If timer is already active, it is restarted.
243
244   if (fAutoRunRunning)
245     return;
246
247   fAutoRunTimer->Reset();
248   fAutoRunTimer->TurnOn();
249   fAutoRunScheduled = run;
250
251   Info("StartAutoRunTimer", "Scheduling run %d for auto-display.", run);
252 }
253
254 void AliOnlineReco::StopAutoRunTimer()
255 {
256   fAutoRunTimer->TurnOff();
257   fAutoRunScheduled = 0;
258 }
259
260 void AliOnlineReco::AutoRunTimerTimeout()
261 {
262   Int_t run = fAutoRunScheduled;
263
264   StopAutoRunTimer();
265
266   mIntInt_i i = fRun2PidMap.find(run);
267
268   if (i == fRun2PidMap.end())
269   {
270     Warning("AutoRunTimerTimeout", "run no longer active.");
271     return;
272   }
273
274   Info("AutoRunTimerTimeout", "Starting display for run %d.", run);
275
276   StartAliEve(i);
277   fAutoRunRunning = run;
278 }
279
280 //------------------------------------------------------------------------------
281 // Handlers of DIM signals.
282 //------------------------------------------------------------------------------
283
284 void AliOnlineReco::StartOfRun(Int_t run)
285 {
286   mIntInt_i i = fRun2PidMap.find(run);
287   if (i == fRun2PidMap.end())
288   {
289     fRun2PidMap[run] = 0;
290     fRunList->AddEntrySort(TString::Format("%d", run), run);
291     fRunList->Layout();
292
293     if (fAutoRun->IsOn())
294     {
295       StartAutoRunTimer(run);
296     }
297   }
298   else
299   {
300     Error("StartOfRun", "Run %d already registered.", run);
301   }
302 }
303
304 void AliOnlineReco::EndOfRun(Int_t run)
305 {
306   mIntInt_i i = fRun2PidMap.find(run);
307   if (i != fRun2PidMap.end())
308   {
309     Int_t pid = i->second;
310     fRunList->RemoveEntry(run);
311     fRunList->Layout();
312     fRun2PidMap.erase(i);
313     if (pid)
314     {
315       KillPid(pid);
316     }
317     gClient->NeedRedraw(fRunList);
318
319     if (fAutoRunRunning == run)
320     {
321       fAutoRunRunning = 0;
322     }
323   }
324   else
325   {
326     Error("EndOfRun", "Run %d not registered.", run);
327   }
328 }
329
330 //------------------------------------------------------------------------------
331 // Handlers of OS signals.
332 //------------------------------------------------------------------------------
333
334 void AliOnlineReco::ChildProcTerm(Int_t pid, Int_t status)
335 {
336   printf("child process termination pid=%d, status=%d...\n", pid, status);
337
338   mIntInt_i i = FindMapEntryByPid(pid);
339   if (i != fRun2PidMap.end())
340   {
341     Int_t run = i->first;
342     fRunList->RemoveEntry(run);
343     if (status == 0)
344     {
345       fRunList->AddEntrySort(TString::Format("%-20d -- PROCESSED", run), run);
346     }
347     else
348     {
349       fRunList->AddEntrySort(TString::Format("%-20d -- PROCESSED [%d]", run, status), run);
350     }
351     fRunList->Layout();
352     i->second = 0;
353
354     if (fAutoRunRunning == run && fAutoRun->IsOn())
355     {
356       fAutoRunRunning = 0;
357       StartAutoRunTimer(run);
358     }
359     else
360     {
361       fAutoRunRunning = 0;
362     }
363   }
364   else
365   {
366     Warning("ChildProcTerm", "Process with pid=%d not registered.", pid);
367   }
368 }
369
370 //------------------------------------------------------------------------------
371 // Handlers of button signals.
372 //------------------------------------------------------------------------------
373
374 void AliOnlineReco::DoAutoRun()
375 {
376   Bool_t autoRun = fAutoRun->IsOn();
377
378   if (autoRun)
379     fStartButt->SetEnabled(kFALSE);
380   else
381     fStartButt->SetEnabled(kTRUE);    
382 }
383
384 void AliOnlineReco::DoStart()
385 {
386   Int_t run = fRunList->GetSelected();
387   mIntInt_i i = fRun2PidMap.find(run);
388
389   if (i == fRun2PidMap.end())
390   {
391     Error("DoStart", "no selection");
392     return;
393   }
394
395   StartAliEve(i);
396 }
397
398 void AliOnlineReco::DoStop()
399 {
400   Int_t run = fRunList->GetSelected();
401   mIntInt_i i = fRun2PidMap.find(run);
402
403   if (i == fRun2PidMap.end())
404   {
405     Error("DoStop", "no selection");
406     return;
407   }
408
409   Int_t pid = i->second;
410   if (pid)
411   {
412     KillPid(pid);
413   }
414   else
415   {
416     Error("DoStop", "Process not running.");
417   }
418 }
419
420 void AliOnlineReco::DoExit()
421 {
422   gSystem->ExitLoop();
423 }
424
425 void AliOnlineReco::CloseWindow()
426 {
427   gSystem->ExitLoop();
428 }
429
430 Int_t AliOnlineReco::RetrieveGRP(UInt_t run, TString &gdc) {
431
432   Int_t ret=AliGRPPreprocessor::ReceivePromptRecoParameters(run, "aldaqdb", 0, "LOGBOOK", "logbook", "alice",
433                                                             Form("local://%s",gSystem->pwd()),
434                                                             gdc);
435   if(ret>0) Info("RetrieveGRP","Last run of the same type is: %d",ret);
436   else if(ret==0) Warning("RetrieveGRP","No previous run of the same type found");
437   else if(ret<0) Error("Retrieve","Error code while retrieving GRP parameters returned: %d",ret);
438   return(ret);
439 }