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