Coding convention violations fixes (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 <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
225       if (s == -1)
226       {
227         perror("execlp failed - this will not end well");
228         gSystem->Exit(1);
229       }
230     }
231   }
232   else
233   {
234     Error("DoStart", "Process already running.");
235   }
236 }
237
238 void AliOnlineReco::KillPid(Int_t pid)
239 {
240   // Terminate process given by pid.
241
242   // Send terminate signal to process ...
243
244   if (fTestMode)
245   {
246     kill(pid, SIGTERM);
247   }
248   else
249   {
250     // alieve will auto-destruct on SIGUSR1
251     kill(pid, SIGUSR1);
252   }
253 }
254
255 void AliOnlineReco::StartAutoRunTimer(Int_t run)
256 {
257   // Start timer for given run.
258   // If an auto-started run is already active, this call is ignored.
259   // If timer is already active, it is restarted.
260
261   if (fAutoRunRunning)
262     return;
263
264   fAutoRunTimer->Reset();
265   fAutoRunTimer->TurnOn();
266   fAutoRunScheduled = run;
267
268   Info("StartAutoRunTimer", "Scheduling run %d for auto-display.", run);
269 }
270
271 void AliOnlineReco::StopAutoRunTimer()
272 {
273   // Stop auto-run timer.
274
275   fAutoRunTimer->TurnOff();
276   fAutoRunScheduled = 0;
277 }
278
279 void AliOnlineReco::AutoRunTimerTimeout()
280 {
281   // Slot called on auto-timer timeout.
282
283   Int_t run = fAutoRunScheduled;
284
285   StopAutoRunTimer();
286
287   mIntInt_i i = fRun2PidMap.find(run);
288
289   if (i == fRun2PidMap.end())
290   {
291     Warning("AutoRunTimerTimeout", "run no longer active.");
292     return;
293   }
294
295   Info("AutoRunTimerTimeout", "Starting display for run %d.", run);
296
297   StartAliEve(i);
298   fAutoRunRunning = run;
299 }
300
301 //------------------------------------------------------------------------------
302 // Handlers of DIM signals.
303 //------------------------------------------------------------------------------
304
305 void AliOnlineReco::StartOfRun(Int_t run)
306 {
307   // Slot called from DIM handler on start of run.
308
309   mIntInt_i i = fRun2PidMap.find(run);
310   if (i == fRun2PidMap.end())
311   {
312     fRun2PidMap[run] = 0;
313     fRunList->AddEntrySort(TString::Format("%d", run), run);
314     fRunList->Layout();
315
316     if (fAutoRun->IsOn())
317     {
318       StartAutoRunTimer(run);
319     }
320   }
321   else
322   {
323     Error("StartOfRun", "Run %d already registered.", run);
324   }
325 }
326
327 void AliOnlineReco::EndOfRun(Int_t run)
328 {
329   // Slot called from DIM handler on stop of run.
330
331   mIntInt_i i = fRun2PidMap.find(run);
332   if (i != fRun2PidMap.end())
333   {
334     Int_t pid = i->second;
335     fRunList->RemoveEntry(run);
336     fRunList->Layout();
337     fRun2PidMap.erase(i);
338     if (pid)
339     {
340       KillPid(pid);
341     }
342     gClient->NeedRedraw(fRunList);
343
344     if (fAutoRunRunning == run)
345     {
346       fAutoRunRunning = 0;
347     }
348   }
349   else
350   {
351     Error("EndOfRun", "Run %d not registered.", run);
352   }
353 }
354
355 //------------------------------------------------------------------------------
356 // Handlers of OS signals.
357 //------------------------------------------------------------------------------
358
359 void AliOnlineReco::ChildProcTerm(Int_t pid, Int_t status)
360 {
361   // Slot called on termination of child process.
362
363   printf("child process termination pid=%d, status=%d...\n", pid, status);
364
365   mIntInt_i i = FindMapEntryByPid(pid);
366   if (i != fRun2PidMap.end())
367   {
368     Int_t run = i->first;
369     fRunList->RemoveEntry(run);
370     if (status == 0)
371     {
372       fRunList->AddEntrySort(TString::Format("%-20d -- PROCESSED", run), run);
373     }
374     else
375     {
376       fRunList->AddEntrySort(TString::Format("%-20d -- PROCESSED [%d]", run, status), run);
377     }
378     fRunList->Layout();
379     i->second = 0;
380
381     if (fAutoRunRunning == run && fAutoRun->IsOn())
382     {
383       fAutoRunRunning = 0;
384       StartAutoRunTimer(run);
385     }
386     else
387     {
388       fAutoRunRunning = 0;
389     }
390   }
391   else
392   {
393     Warning("ChildProcTerm", "Process with pid=%d not registered.", pid);
394   }
395 }
396
397 //------------------------------------------------------------------------------
398 // Handlers of button signals.
399 //------------------------------------------------------------------------------
400
401 void AliOnlineReco::DoAutoRun()
402 {
403   // Slot called from auto-run check-box.
404
405   Bool_t autoRun = fAutoRun->IsOn();
406
407   if (autoRun)
408     fStartButt->SetEnabled(kFALSE);
409   else
410     fStartButt->SetEnabled(kTRUE);    
411 }
412
413 void AliOnlineReco::DoStart()
414 {
415   // Slot called from Start button.
416
417   Int_t run = fRunList->GetSelected();
418   mIntInt_i i = fRun2PidMap.find(run);
419
420   if (i == fRun2PidMap.end())
421   {
422     Error("DoStart", "no selection");
423     return;
424   }
425
426   StartAliEve(i);
427 }
428
429 void AliOnlineReco::DoStop()
430 {
431   // Slot called from Stop button.
432
433   Int_t run = fRunList->GetSelected();
434   mIntInt_i i = fRun2PidMap.find(run);
435
436   if (i == fRun2PidMap.end())
437   {
438     Error("DoStop", "no selection");
439     return;
440   }
441
442   Int_t pid = i->second;
443   if (pid)
444   {
445     KillPid(pid);
446   }
447   else
448   {
449     Error("DoStop", "Process not running.");
450   }
451 }
452
453 void AliOnlineReco::DoExit()
454 {
455   // Slot called from Exit button.
456
457   gSystem->ExitLoop();
458 }
459
460 void AliOnlineReco::CloseWindow()
461 {
462   // Virtual method called when window-manager close-window button is pressed.
463
464   gSystem->ExitLoop();
465 }
466
467 Int_t AliOnlineReco::RetrieveGRP(UInt_t run, TString &gdc)
468 {
469   // Retrieve GRP entry for given run from aldaqdb.
470
471   Int_t ret=AliGRPPreprocessor::ReceivePromptRecoParameters(run, "aldaqdb", 0, "LOGBOOK", "logbook", "alice",
472                                                             Form("local://%s",gSystem->pwd()),
473                                                             gdc);
474   if(ret>0) Info("RetrieveGRP","Last run of the same type is: %d",ret);
475   else if(ret==0) Warning("RetrieveGRP","No previous run of the same type found");
476   else if(ret<0) Error("Retrieve","Error code while retrieving GRP parameters returned: %d",ret);
477   return(ret);
478 }