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