Added a feature test macro for sa_restorer field
[u/mrichter/AliRoot.git] / MONITOR / AliOnlineReco.cxx
CommitLineData
c6d78c69 1// @(#)root/eve:$Id$
2// Author: Matevz Tadel 2007
3
4/**************************************************************************
dc836d53 5 * Copyright(c) 1998-2008, ALICE Experiment at CERN, all rights reserved. *)
c6d78c69 6 * See http://aliceinfo.cern.ch/Offline/AliRoot/License.html for *
7 * full copyright notice. *
8 **************************************************************************/
9
10#include "AliOnlineReco.h"
93624d6b 11#include "AliChildProcTerminator.h"
c6d78c69 12#include "AliDimIntNotifier.h"
a15a9f84 13#include "AliCDBManager.h"
14#include "AliGRPPreprocessor.h"
c6d78c69 15
dc836d53 16#include <TTimer.h>
17
c6d78c69 18#include <TGListBox.h>
19#include <TGButton.h>
20
d2a137c1 21#include <TInterpreter.h>
22
c6d78c69 23#include <unistd.h>
24#include <signal.h>
25
26//______________________________________________________________________________
27// Full description of AliOnlineReco
28//
29
30ClassImp(AliOnlineReco)
31
32AliOnlineReco::AliOnlineReco() :
33 TGMainFrame(gClient->GetRoot(), 400, 400),
34
dc836d53 35 fRunList(0), fAutoRun(0), fStartButt(0), fStopButt(0), fExitButt(0),
36 fAutoRunTimer(0), fAutoRunScheduled(0), fAutoRunRunning(0),
4f6eef9f 37 fRun2PidMap(),
c6d78c69 38 fTestMode(kFALSE)
39{
48c0589a 40 // Constructor.
41
c6d78c69 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
dc836d53 48 fAutoRun = new TGCheckButton(hf, "AutoRun");
49 hf->AddFrame(fAutoRun, new TGLayoutHints(kLHintsNormal | kLHintsExpandX | kLHintsExpandY));
50 fAutoRun->Connect("Clicked()", "AliOnlineReco", this, "DoAutoRun()");
51
c6d78c69 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
dc836d53 60 fExitButt = new TGTextButton(hf, "Exit");
61 hf->AddFrame(fExitButt, new TGLayoutHints(kLHintsNormal | kLHintsExpandX | kLHintsExpandY));
62 fExitButt->Connect("Clicked()", "AliOnlineReco", this, "DoExit()");
c6d78c69 63
64 AddFrame(hf, new TGLayoutHints(kLHintsNormal | kLHintsExpandX));
65
66 MapSubwindows();
67 Layout();
68 SetWindowName("Alice Online Reconstruction");
69
e35c7687 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 }
dc836d53 83
e35c7687 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 }
c6d78c69 87
dc836d53 88 const Int_t autoRunDelay = 10; // should go to config
89 fAutoRunTimer = new TTimer(autoRunDelay * 1000l);
90 fAutoRunTimer->Connect("Timeout()", "AliOnlineReco", this, "AutoRunTimerTimeout()");
91
b6269fdc 92 // OS Signal handlers
c6d78c69 93 // ROOT's TSignalHAndler works not SIGCHLD ...
93624d6b 94 AliChildProcTerminator::Instance()->Connect("ChildProcTerm(Int_t,Int_t)", "AliOnlineReco", this, "ChildProcTerm(Int_t,Int_t)");
c6d78c69 95}
96
dc836d53 97AliOnlineReco::~AliOnlineReco()
98{
48c0589a 99 // Destructor.
100
dc836d53 101 delete fAutoRunTimer;
102}
103
104Int_t AliOnlineReco::GetLastRun() const
105{
48c0589a 106 // Returns the last started run.
107
dc836d53 108 return fRun2PidMap.empty() ? 0 : fRun2PidMap.rbegin()->first;
109}
110
111Bool_t AliOnlineReco::GetAutoRunMode() const
112{
48c0589a 113 // Return state of auto-run flag.
114
dc836d53 115 return fAutoRun->IsOn();
116}
117
118void AliOnlineReco::SetAutoRunMode(Bool_t ar)
119{
48c0589a 120 // Set auto-run flag.
121
dc836d53 122 if (ar == fAutoRun->IsOn())
123 return;
124
125 fAutoRun->SetState(ar ? kButtonDown : kButtonUp, kTRUE);
126}
127
128//------------------------------------------------------------------------------
129// Private methods
130//------------------------------------------------------------------------------
131
c6d78c69 132AliOnlineReco::mIntInt_i AliOnlineReco::FindMapEntryByPid(Int_t pid)
133{
48c0589a 134 // Find run-to-pid map iterator by pid.
135 // Requires iteration over map.
136
c6d78c69 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
dc836d53 146void AliOnlineReco::StartAliEve(mIntInt_i& mi)
147{
48c0589a 148 // Start alieve to process run given my the run-pid entry.
149
dc836d53 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 {
d2a137c1 170 gCINTMutex = 0;
171
172 struct sigaction sac;
b6269fdc 173 memset(&sac, 0, sizeof(sac));
174 sac.sa_handler = NULL;
d2a137c1 175 sigemptyset(&sac.sa_mask);
176 sac.sa_flags = 0;
07f75a04 177
178 // The sa_restorer field is Not POSIX and obsolete.
179 // This is for compilation on other systems
180 #if defined(__linux) && \
181 (defined(__i386__) || defined(__x86_64__)) && \
182 defined(__GNUC__)
183 sac.sa_restorer= NULL;
184 #endif
b6269fdc 185 sigaction(SIGCHLD, &sac, NULL);
186
dc836d53 187 int s;
188 if (fTestMode)
189 {
b6269fdc 190 s = execlp("alitestproc", "alitestproc", TString::Format("%d", run).Data(), (char*) 0);
dc836d53 191 }
192 else
193 {
b6269fdc 194 Int_t procPID = gSystem->GetPid();
195 TString logFile = Form("%s/reco/log/run%d_%d.log",
196 gSystem->Getenv("ONLINERECO_BASE_DIR"),
197 run,
198 (Int_t)procPID);
199 Info("DoStart","Reconstruction log will be written to %s",logFile.Data());
200 gSystem->RedirectOutput(logFile.Data());
201
202 gSystem->cd(Form("%s/reco",gSystem->Getenv("ONLINERECO_BASE_DIR")));
203
204 TString gdcs;
205 if (RetrieveGRP(run,gdcs) <= 0 || gdcs.IsNull())
206 gSystem->Exit(1);
207
208 gSystem->Setenv("DATE_RUN_NUMBER", Form("%d", run));
209 // Setting CDB
210 // AliCDBManager * man = AliCDBManager::Instance();
211 // man->SetDefaultStorage("local:///local/cdb");
212 // man->SetSpecificStorage("GRP/GRP/Data",
213 // Form("local://%s",gSystem->pwd()));
214 // man->SetSpecificStorage("GRP/CTP/Config",
215 // Form("local://%s",gSystem->pwd()));
216 // man->SetSpecificStorage("ACORDE/Align/Data",
217 // "local://$ALICE_ROOT/OCDB");
218
219 gSystem->mkdir(Form("run%d_%d", run, (Int_t)procPID));
220 gSystem->cd(Form("run%d_%d", run, (Int_t)procPID));
221
222 TString recMacroPath(gSystem->Getenv("ONLINERECO_MACRO"));
223 if (recMacroPath.IsNull()) {
224 recMacroPath = "$ALICE_ROOT/MONITOR/rec.C";
225 }
226
227 s = execlp("alieve",
228 "alieve",
229 "-q",
230 Form("%s(\"mem://@*:\")", gSystem->ExpandPathName(recMacroPath.Data())),
231 (char*) 0);
232
233 gSystem->Exec(Form("rm -rf %s/reco/run%d_%d",gSystem->Getenv("ONLINERECO_BASE_DIR"),run,(Int_t)procPID));
dc836d53 234 }
235
236 if (s == -1)
237 {
b6269fdc 238 perror("execlp failed - this will not end well");
239 gSystem->Exit(1);
dc836d53 240 }
241 }
242 }
243 else
244 {
245 Error("DoStart", "Process already running.");
246 }
247}
248
249void AliOnlineReco::KillPid(Int_t pid)
250{
48c0589a 251 // Terminate process given by pid.
252
dc836d53 253 // Send terminate signal to process ...
254
255 if (fTestMode)
256 {
257 kill(pid, SIGTERM);
258 }
259 else
260 {
261 // alieve will auto-destruct on SIGUSR1
262 kill(pid, SIGUSR1);
263 }
264}
265
266void AliOnlineReco::StartAutoRunTimer(Int_t run)
267{
268 // Start timer for given run.
269 // If an auto-started run is already active, this call is ignored.
270 // If timer is already active, it is restarted.
271
272 if (fAutoRunRunning)
273 return;
274
275 fAutoRunTimer->Reset();
276 fAutoRunTimer->TurnOn();
277 fAutoRunScheduled = run;
278
279 Info("StartAutoRunTimer", "Scheduling run %d for auto-display.", run);
280}
281
282void AliOnlineReco::StopAutoRunTimer()
283{
48c0589a 284 // Stop auto-run timer.
285
dc836d53 286 fAutoRunTimer->TurnOff();
287 fAutoRunScheduled = 0;
288}
289
290void AliOnlineReco::AutoRunTimerTimeout()
291{
48c0589a 292 // Slot called on auto-timer timeout.
293
dc836d53 294 Int_t run = fAutoRunScheduled;
295
296 StopAutoRunTimer();
297
298 mIntInt_i i = fRun2PidMap.find(run);
299
300 if (i == fRun2PidMap.end())
301 {
302 Warning("AutoRunTimerTimeout", "run no longer active.");
303 return;
304 }
305
306 Info("AutoRunTimerTimeout", "Starting display for run %d.", run);
307
308 StartAliEve(i);
309 fAutoRunRunning = run;
310}
311
c6d78c69 312//------------------------------------------------------------------------------
313// Handlers of DIM signals.
314//------------------------------------------------------------------------------
315
316void AliOnlineReco::StartOfRun(Int_t run)
317{
48c0589a 318 // Slot called from DIM handler on start of run.
319
c6d78c69 320 mIntInt_i i = fRun2PidMap.find(run);
321 if (i == fRun2PidMap.end())
322 {
323 fRun2PidMap[run] = 0;
324 fRunList->AddEntrySort(TString::Format("%d", run), run);
325 fRunList->Layout();
dc836d53 326
327 if (fAutoRun->IsOn())
328 {
329 StartAutoRunTimer(run);
330 }
c6d78c69 331 }
332 else
333 {
334 Error("StartOfRun", "Run %d already registered.", run);
335 }
336}
337
338void AliOnlineReco::EndOfRun(Int_t run)
339{
48c0589a 340 // Slot called from DIM handler on stop of run.
341
c6d78c69 342 mIntInt_i i = fRun2PidMap.find(run);
343 if (i != fRun2PidMap.end())
344 {
345 Int_t pid = i->second;
346 fRunList->RemoveEntry(run);
347 fRunList->Layout();
348 fRun2PidMap.erase(i);
349 if (pid)
350 {
dc836d53 351 KillPid(pid);
c6d78c69 352 }
353 gClient->NeedRedraw(fRunList);
dc836d53 354
355 if (fAutoRunRunning == run)
356 {
357 fAutoRunRunning = 0;
358 }
c6d78c69 359 }
360 else
361 {
362 Error("EndOfRun", "Run %d not registered.", run);
363 }
364}
365
366//------------------------------------------------------------------------------
367// Handlers of OS signals.
368//------------------------------------------------------------------------------
369
93624d6b 370void AliOnlineReco::ChildProcTerm(Int_t pid, Int_t status)
c6d78c69 371{
48c0589a 372 // Slot called on termination of child process.
b6269fdc 373
93624d6b 374 printf("child process termination pid=%d, status=%d...\n", pid, status);
c6d78c69 375
376 mIntInt_i i = FindMapEntryByPid(pid);
377 if (i != fRun2PidMap.end())
378 {
379 Int_t run = i->first;
380 fRunList->RemoveEntry(run);
381 if (status == 0)
382 {
82142d1d 383 fRunList->AddEntrySort(TString::Format("%-20d -- PROCESSED", run), run);
c6d78c69 384 }
385 else
386 {
82142d1d 387 fRunList->AddEntrySort(TString::Format("%-20d -- PROCESSED [%d]", run, status), run);
c6d78c69 388 }
389 fRunList->Layout();
390 i->second = 0;
dc836d53 391
392 if (fAutoRunRunning == run && fAutoRun->IsOn())
393 {
394 fAutoRunRunning = 0;
395 StartAutoRunTimer(run);
396 }
397 else
398 {
399 fAutoRunRunning = 0;
400 }
c6d78c69 401 }
402 else
403 {
93624d6b 404 Warning("ChildProcTerm", "Process with pid=%d not registered.", pid);
c6d78c69 405 }
406}
407
408//------------------------------------------------------------------------------
409// Handlers of button signals.
410//------------------------------------------------------------------------------
411
dc836d53 412void AliOnlineReco::DoAutoRun()
413{
48c0589a 414 // Slot called from auto-run check-box.
415
dc836d53 416 Bool_t autoRun = fAutoRun->IsOn();
417
418 if (autoRun)
419 fStartButt->SetEnabled(kFALSE);
420 else
421 fStartButt->SetEnabled(kTRUE);
422}
423
c6d78c69 424void AliOnlineReco::DoStart()
425{
48c0589a 426 // Slot called from Start button.
427
c6d78c69 428 Int_t run = fRunList->GetSelected();
429 mIntInt_i i = fRun2PidMap.find(run);
430
431 if (i == fRun2PidMap.end())
432 {
433 Error("DoStart", "no selection");
434 return;
435 }
436
dc836d53 437 StartAliEve(i);
c6d78c69 438}
439
440void AliOnlineReco::DoStop()
441{
48c0589a 442 // Slot called from Stop button.
443
c6d78c69 444 Int_t run = fRunList->GetSelected();
445 mIntInt_i i = fRun2PidMap.find(run);
446
447 if (i == fRun2PidMap.end())
448 {
449 Error("DoStop", "no selection");
450 return;
451 }
452
453 Int_t pid = i->second;
454 if (pid)
455 {
dc836d53 456 KillPid(pid);
c6d78c69 457 }
458 else
459 {
460 Error("DoStop", "Process not running.");
461 }
462}
463
dc836d53 464void AliOnlineReco::DoExit()
c6d78c69 465{
48c0589a 466 // Slot called from Exit button.
467
c6d78c69 468 gSystem->ExitLoop();
469}
470
471void AliOnlineReco::CloseWindow()
472{
48c0589a 473 // Virtual method called when window-manager close-window button is pressed.
474
c6d78c69 475 gSystem->ExitLoop();
476}
a15a9f84 477
48c0589a 478Int_t AliOnlineReco::RetrieveGRP(UInt_t run, TString &gdc)
479{
480 // Retrieve GRP entry for given run from aldaqdb.
a15a9f84 481
8f772d4b 482 TString dbHost = gSystem->Getenv("ONLINERECO_DB_HOST");
483 if (dbHost.IsNull())
484 {
485 dbHost = "aldaqdb";
486 }
487
488 TString dbPort = gSystem->Getenv("ONLINERECO_DB_PORT");
489 if (dbPort.IsNull())
490 {
491 dbPort = "0";
492 }
493
494 TString dbName = gSystem->Getenv("ONLINERECO_DB_NAME");
495 if (dbName.IsNull())
496 {
497 dbName = "LOGBOOK";
498 }
499
500 TString user = gSystem->Getenv("ONLINERECO_DB_USER");
501 if (user.IsNull())
502 {
503 user = "logbook";
504 }
505
506 TString password = gSystem->Getenv("ONLINERECO_DB_PASSWORD");
507 if (password.IsNull())
508 {
509 password = "alice";
510 }
511
512 Int_t ret=AliGRPPreprocessor::ReceivePromptRecoParameters(run, dbHost.Data(),
b6269fdc 513 dbPort.Atoi(), dbName.Data(),
514 user.Data(), password.Data(),
515 Form("local://%s",gSystem->pwd()),
516 gdc);
8f772d4b 517
a15a9f84 518 if(ret>0) Info("RetrieveGRP","Last run of the same type is: %d",ret);
519 else if(ret==0) Warning("RetrieveGRP","No previous run of the same type found");
520 else if(ret<0) Error("Retrieve","Error code while retrieving GRP parameters returned: %d",ret);
521 return(ret);
522}