Putting the default rec.C for online reco/viz into svn instead of using the one from...
[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         const char *recMacroPath = "$ALICE_ROOT/MONITOR/rec.C";
189
190         s = execlp("alieve",
191                    "alieve",
192                    "-q",
193                    Form("%s(\"mem://@*:\")", gSystem->ExpandPathName(recMacroPath)),
194                    (char*) 0);
195       }
196
197       if (s == -1)
198       {
199         perror("execlp failed - this will not end well");
200         gSystem->Exit(1);
201       }
202     }
203   }
204   else
205   {
206     Error("DoStart", "Process already running.");
207   }
208 }
209
210 void AliOnlineReco::KillPid(Int_t pid)
211 {
212   // Send terminate signal to process ...
213
214   if (fTestMode)
215   {
216     kill(pid, SIGTERM);
217   }
218   else
219   {
220     // alieve will auto-destruct on SIGUSR1
221     kill(pid, SIGUSR1);
222   }
223 }
224
225 void AliOnlineReco::StartAutoRunTimer(Int_t run)
226 {
227   // Start timer for given run.
228   // If an auto-started run is already active, this call is ignored.
229   // If timer is already active, it is restarted.
230
231   if (fAutoRunRunning)
232     return;
233
234   fAutoRunTimer->Reset();
235   fAutoRunTimer->TurnOn();
236   fAutoRunScheduled = run;
237
238   Info("StartAutoRunTimer", "Scheduling run %d for auto-display.", run);
239 }
240
241 void AliOnlineReco::StopAutoRunTimer()
242 {
243   fAutoRunTimer->TurnOff();
244   fAutoRunScheduled = 0;
245 }
246
247 void AliOnlineReco::AutoRunTimerTimeout()
248 {
249   Int_t run = fAutoRunScheduled;
250
251   StopAutoRunTimer();
252
253   mIntInt_i i = fRun2PidMap.find(run);
254
255   if (i == fRun2PidMap.end())
256   {
257     Warning("AutoRunTimerTimeout", "run no longer active.");
258     return;
259   }
260
261   Info("AutoRunTimerTimeout", "Starting display for run %d.", run);
262
263   StartAliEve(i);
264   fAutoRunRunning = run;
265 }
266
267 //------------------------------------------------------------------------------
268 // Handlers of DIM signals.
269 //------------------------------------------------------------------------------
270
271 void AliOnlineReco::StartOfRun(Int_t run)
272 {
273   mIntInt_i i = fRun2PidMap.find(run);
274   if (i == fRun2PidMap.end())
275   {
276     fRun2PidMap[run] = 0;
277     fRunList->AddEntrySort(TString::Format("%d", run), run);
278     fRunList->Layout();
279
280     if (fAutoRun->IsOn())
281     {
282       StartAutoRunTimer(run);
283     }
284   }
285   else
286   {
287     Error("StartOfRun", "Run %d already registered.", run);
288   }
289 }
290
291 void AliOnlineReco::EndOfRun(Int_t run)
292 {
293   mIntInt_i i = fRun2PidMap.find(run);
294   if (i != fRun2PidMap.end())
295   {
296     Int_t pid = i->second;
297     fRunList->RemoveEntry(run);
298     fRunList->Layout();
299     fRun2PidMap.erase(i);
300     if (pid)
301     {
302       KillPid(pid);
303     }
304     gClient->NeedRedraw(fRunList);
305
306     if (fAutoRunRunning == run)
307     {
308       fAutoRunRunning = 0;
309     }
310   }
311   else
312   {
313     Error("EndOfRun", "Run %d not registered.", run);
314   }
315 }
316
317 //------------------------------------------------------------------------------
318 // Handlers of OS signals.
319 //------------------------------------------------------------------------------
320
321 void AliOnlineReco::ChildProcTerm(Int_t pid, Int_t status)
322 {
323   printf("child process termination pid=%d, status=%d...\n", pid, status);
324
325   mIntInt_i i = FindMapEntryByPid(pid);
326   if (i != fRun2PidMap.end())
327   {
328     Int_t run = i->first;
329     fRunList->RemoveEntry(run);
330     if (status == 0)
331     {
332       fRunList->AddEntrySort(TString::Format("%-20d -- PROCESSED", run), run);
333     }
334     else
335     {
336       fRunList->AddEntrySort(TString::Format("%-20d -- PROCESSED [%d]", run, status), run);
337     }
338     fRunList->Layout();
339     i->second = 0;
340
341     if (fAutoRunRunning == run && fAutoRun->IsOn())
342     {
343       fAutoRunRunning = 0;
344       StartAutoRunTimer(run);
345     }
346     else
347     {
348       fAutoRunRunning = 0;
349     }
350   }
351   else
352   {
353     Warning("ChildProcTerm", "Process with pid=%d not registered.", pid);
354   }
355 }
356
357 //------------------------------------------------------------------------------
358 // Handlers of button signals.
359 //------------------------------------------------------------------------------
360
361 void AliOnlineReco::DoAutoRun()
362 {
363   Bool_t autoRun = fAutoRun->IsOn();
364
365   if (autoRun)
366     fStartButt->SetEnabled(kFALSE);
367   else
368     fStartButt->SetEnabled(kTRUE);    
369 }
370
371 void AliOnlineReco::DoStart()
372 {
373   Int_t run = fRunList->GetSelected();
374   mIntInt_i i = fRun2PidMap.find(run);
375
376   if (i == fRun2PidMap.end())
377   {
378     Error("DoStart", "no selection");
379     return;
380   }
381
382   StartAliEve(i);
383 }
384
385 void AliOnlineReco::DoStop()
386 {
387   Int_t run = fRunList->GetSelected();
388   mIntInt_i i = fRun2PidMap.find(run);
389
390   if (i == fRun2PidMap.end())
391   {
392     Error("DoStop", "no selection");
393     return;
394   }
395
396   Int_t pid = i->second;
397   if (pid)
398   {
399     KillPid(pid);
400   }
401   else
402   {
403     Error("DoStop", "Process not running.");
404   }
405 }
406
407 void AliOnlineReco::DoExit()
408 {
409   gSystem->ExitLoop();
410 }
411
412 void AliOnlineReco::CloseWindow()
413 {
414   gSystem->ExitLoop();
415 }
416
417 Int_t AliOnlineReco::RetrieveGRP(UInt_t run, TString &gdc) {
418
419   Int_t ret=AliGRPPreprocessor::ReceivePromptRecoParameters(run, "aldaqdb", 0, "LOGBOOK", "logbook", "alice",
420                                                             Form("local://%s",gSystem->pwd()),
421                                                             gdc);
422   if(ret>0) Info("RetrieveGRP","Last run of the same type is: %d",ret);
423   else if(ret==0) Warning("RetrieveGRP","No previous run of the same type found");
424   else if(ret<0) Error("Retrieve","Error code while retrieving GRP parameters returned: %d",ret);
425   return(ret);
426 }