]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - MONITOR/AliOnlineReco.cxx
bugfix: correct range of DDL for specified detector
[u/mrichter/AliRoot.git] / MONITOR / AliOnlineReco.cxx
index c604cd626603b131cad793a35ab53bfc0085c9a0..80498331460dacf3a53794f95c205f94eb44fe64 100644 (file)
@@ -2,7 +2,7 @@
 // Author: Matevz Tadel 2007
 
 /**************************************************************************
- * Copyright(c) 1998-2008, ALICE Experiment at CERN, all rights reserved. *
+ * Copyright(c) 1998-2008, ALICE Experiment at CERN, all rights reserved. *)
  * See http://aliceinfo.cern.ch/Offline/AliRoot/License.html for          *
  * full copyright notice.                                                 *
  **************************************************************************/
 #include "AliOnlineReco.h"
 #include "AliChildProcTerminator.h"
 #include "AliDimIntNotifier.h"
+#include "AliCDBManager.h"
+#include "AliGRPPreprocessor.h"
+
+#include <TTimer.h>
 
 #include <TGListBox.h>
 #include <TGButton.h>
 
+#include <TInterpreter.h>
+#include <TROOT.h>
+
 #include <unistd.h>
 #include <signal.h>
 
@@ -26,19 +33,24 @@ ClassImp(AliOnlineReco)
 AliOnlineReco::AliOnlineReco() :
   TGMainFrame(gClient->GetRoot(), 400, 400),
 
-  fRunList(0), fStartButt(0), fStopButt(0), fXyzzButt(0),
-
-  fSOR(new AliDimIntNotifier("/LOGBOOK/SUBSCRIBE/DAQ_SOR_PHYSICS")),
-  fEOR(new AliDimIntNotifier("/LOGBOOK/SUBSCRIBE/DAQ_EOR_PHYSICS")),
-
-  fTestMode(kFALSE)
+  fRunList(0), fAutoRun(0), fStartButt(0), fStopButt(0), fExitButt(0),
+  fAutoRunTimer(0), fAutoRunScheduled(0), fAutoRunRunning(0),
+  fRun2PidMap(),
+  fTestMode(kFALSE),
+  fDoExit(kFALSE)
 {
+  // Constructor.
+
   // GUI components.
   fRunList = new TGListBox(this);
   AddFrame(fRunList, new TGLayoutHints(kLHintsNormal | kLHintsExpandX | kLHintsExpandY));
 
   TGHorizontalFrame *hf = new TGHorizontalFrame(this, 1, 20);
 
+  fAutoRun = new TGCheckButton(hf, "AutoRun");
+  hf->AddFrame(fAutoRun, new TGLayoutHints(kLHintsNormal | kLHintsExpandX | kLHintsExpandY));
+  fAutoRun->Connect("Clicked()", "AliOnlineReco", this, "DoAutoRun()");
+
   fStartButt = new TGTextButton(hf, "Start");
   hf->AddFrame(fStartButt, new TGLayoutHints(kLHintsNormal | kLHintsExpandX | kLHintsExpandY));
   fStartButt->Connect("Clicked()", "AliOnlineReco", this, "DoStart()");
@@ -47,9 +59,9 @@ AliOnlineReco::AliOnlineReco() :
   hf->AddFrame(fStopButt, new TGLayoutHints(kLHintsNormal | kLHintsExpandX | kLHintsExpandY));
   fStopButt->Connect("Clicked()", "AliOnlineReco", this, "DoStop()");
 
-  fXyzzButt = new TGTextButton(hf, "Exit");
-  hf->AddFrame(fXyzzButt, new TGLayoutHints(kLHintsNormal | kLHintsExpandX | kLHintsExpandY));
-  fXyzzButt->Connect("Clicked()", "AliOnlineReco", this, "DoXyzz()");
+  fExitButt = new TGTextButton(hf, "Exit");
+  hf->AddFrame(fExitButt, new TGLayoutHints(kLHintsNormal | kLHintsExpandX | kLHintsExpandY));
+  fExitButt->Connect("Clicked()", "AliOnlineReco", this, "DoExit()");
 
   AddFrame(hf, new TGLayoutHints(kLHintsNormal | kLHintsExpandX));
 
@@ -57,17 +69,76 @@ AliOnlineReco::AliOnlineReco() :
   Layout();
   SetWindowName("Alice Online Reconstruction");
 
-  // DIM interface.
-  fSOR->Connect("DimMessage(Int_t)", "AliOnlineReco", this, "StartOfRun(Int_t)");
-  fEOR->Connect("DimMessage(Int_t)", "AliOnlineReco", this, "EndOfRun(Int_t)");
+  // DIM interface.  
+  for (Int_t i = 0; i < 5; ++i)
+  {
+    if (i == 0)
+    {
+      fSOR[i] = new AliDimIntNotifier("/LOGBOOK/SUBSCRIBE/DAQ_SOR_PHYSICS");
+      fEOR[i] = new AliDimIntNotifier("/LOGBOOK/SUBSCRIBE/DAQ_EOR_PHYSICS");
+    }
+    else
+    {
+      fSOR[i] = new AliDimIntNotifier(Form("/LOGBOOK/SUBSCRIBE/DAQ_SOR_PHYSICS_%d", i));
+      fEOR[i] = new AliDimIntNotifier(Form("/LOGBOOK/SUBSCRIBE/DAQ_EOR_PHYSICS_%d", i));
+    }
+
+    fSOR[i]->Connect("DimMessage(Int_t)", "AliOnlineReco", this, "StartOfRun(Int_t)");
+    fEOR[i]->Connect("DimMessage(Int_t)", "AliOnlineReco", this, "EndOfRun(Int_t)");
+  }
+
+  const Int_t autoRunDelay = 10; // should go to config
+  fAutoRunTimer = new TTimer(autoRunDelay * 1000l);
+  fAutoRunTimer->Connect("Timeout()", "AliOnlineReco", this, "AutoRunTimerTimeout()");
 
-  // Signal handlers
+  // OS Signal handlers
   // ROOT's TSignalHAndler works not SIGCHLD ...
   AliChildProcTerminator::Instance()->Connect("ChildProcTerm(Int_t,Int_t)", "AliOnlineReco", this, "ChildProcTerm(Int_t,Int_t)");
+  
+  // we need this by OnExit() to kill next process child after another
+  Connect("ChildProcTerm(Int_t,Int_t)", "AliOnlineReco", this, "ExitLoopChildProcTerm()");
+}
+
+AliOnlineReco::~AliOnlineReco()
+{
+  // Destructor.
+
+  delete fAutoRunTimer;
+}
+
+Int_t AliOnlineReco::GetLastRun() const
+{
+  // Returns the last started run.
+
+  return fRun2PidMap.empty() ? 0 : fRun2PidMap.rbegin()->first;
+}
+
+Bool_t AliOnlineReco::GetAutoRunMode() const
+{
+  // Return state of auto-run flag.
+
+  return fAutoRun->IsOn();
+}
+
+void AliOnlineReco::SetAutoRunMode(Bool_t ar)
+{
+  // Set auto-run flag.
+
+  if (ar == fAutoRun->IsOn())
+    return;
+
+  fAutoRun->SetState(ar ? kButtonDown : kButtonUp, kTRUE);
 }
 
+//------------------------------------------------------------------------------
+// Private methods
+//------------------------------------------------------------------------------
+
 AliOnlineReco::mIntInt_i AliOnlineReco::FindMapEntryByPid(Int_t pid)
 {
+  // Find run-to-pid map iterator by pid.
+  // Requires iteration over map.
+
   for (mIntInt_i i = fRun2PidMap.begin(); i != fRun2PidMap.end(); ++i)
   {
     if (i->second == pid)
@@ -77,18 +148,191 @@ AliOnlineReco::mIntInt_i AliOnlineReco::FindMapEntryByPid(Int_t pid)
   return fRun2PidMap.end();
 }
 
+void AliOnlineReco::StartAliEve(mIntInt_i& mi)
+{
+  // Start alieve to process run given my the run-pid entry.
+
+  Int_t run = mi->first;
+
+  if (mi->second == 0)
+  {
+    pid_t pid = fork();
+    if (pid == -1)
+    {
+      perror("DoStart -- Fork failed");
+      return;
+    }
+
+    if (pid)
+    {
+      mi->second = pid;
+      fRunList->RemoveEntry(run);
+      fRunList->AddEntrySort(TString::Format("%-20d -- RUNNING", run), run);
+      fRunList->Layout();
+    }
+    else
+    {
+      gCINTMutex = 0;
+
+      struct sigaction sac;
+      memset(&sac, 0, sizeof(sac));
+      sac.sa_handler = NULL;
+      sigemptyset(&sac.sa_mask);
+      sac.sa_flags = 0;
+      
+      // The sa_restorer field is Not POSIX and obsolete.
+      // This is for compilation on other systems
+      #if defined(__linux) && \
+          (defined(__i386__) || defined(__x86_64__)) && \
+           defined(__GNUC__)
+      sac.sa_restorer= NULL;
+      #endif
+      sigaction(SIGCHLD, &sac, NULL);
+  
+      int s;
+      if (fTestMode)
+      {
+        s = execlp("alitestproc", "alitestproc", TString::Format("%d", run).Data(), (char*) 0);
+      }
+      else
+      {
+        Int_t procPID = gSystem->GetPid();
+        TString logFile = Form("%s/reco/log/run%d_%d.log",
+             gSystem->Getenv("ONLINERECO_BASE_DIR"),
+             run,
+            (Int_t)procPID);
+        Info("DoStart","Reconstruction log will be written to %s",logFile.Data());
+        gSystem->RedirectOutput(logFile.Data());
+
+        gSystem->cd(Form("%s/reco",gSystem->Getenv("ONLINERECO_BASE_DIR")));
+
+        TString gdcs;
+        if (RetrieveGRP(run,gdcs) <= 0 || gdcs.IsNull()) 
+          gSystem->Exit(1);
+
+        gSystem->Setenv("DATE_RUN_NUMBER", Form("%d", run));
+        // Setting CDB
+        //     AliCDBManager * man = AliCDBManager::Instance();
+        //     man->SetDefaultStorage("local:///local/cdb");
+        //     man->SetSpecificStorage("GRP/GRP/Data",
+        //                           Form("local://%s",gSystem->pwd()));
+        //     man->SetSpecificStorage("GRP/CTP/Config",
+        //                           Form("local://%s",gSystem->pwd()));
+        //     man->SetSpecificStorage("ACORDE/Align/Data",
+        //                             "local://$ALICE_ROOT/OCDB");
+
+        gSystem->mkdir(Form("run%d_%d", run, (Int_t)procPID));
+        gSystem->cd(Form("run%d_%d", run, (Int_t)procPID));
+
+        TString recMacroPath(gSystem->Getenv("ONLINERECO_MACRO"));
+        if (recMacroPath.IsNull()) {
+          recMacroPath = "$ALICE_ROOT/MONITOR/rec.C";
+        }
+        
+        s = execlp("alieve",
+             "alieve",
+             "-q",
+             Form("%s(\"mem://@*:\")", gSystem->ExpandPathName(recMacroPath.Data())),
+             (char*) 0);
+
+        gSystem->Exec(Form("rm -rf %s/reco/run%d_%d",gSystem->Getenv("ONLINERECO_BASE_DIR"),run,(Int_t)procPID));
+      }
+
+      if (s == -1)
+      {
+        perror("execlp failed - this will not end well");
+        gSystem->Exit(1);
+      }
+    }
+  }
+  else
+  {
+    Error("DoStart", "Process already running.");
+  }
+}
+
+void AliOnlineReco::KillPid(Int_t pid)
+{
+  // Terminate process given by pid.
+
+  // Send terminate signal to process ...
+
+  if (fTestMode)
+  {
+    kill(pid, SIGTERM);
+  }
+  else
+  {
+    // alieve will auto-destruct on SIGUSR1
+    kill(pid, SIGUSR1);
+  }
+}
+
+void AliOnlineReco::StartAutoRunTimer(Int_t run)
+{
+  // Start timer for given run.
+  // If an auto-started run is already active, this call is ignored.
+  // If timer is already active, it is restarted.
+
+  if (fAutoRunRunning)
+    return;
+
+  fAutoRunTimer->Reset();
+  fAutoRunTimer->TurnOn();
+  fAutoRunScheduled = run;
+
+  Info("StartAutoRunTimer", "Scheduling run %d for auto-display.", run);
+}
+
+void AliOnlineReco::StopAutoRunTimer()
+{
+  // Stop auto-run timer.
+
+  fAutoRunTimer->TurnOff();
+  fAutoRunScheduled = 0;
+}
+
+void AliOnlineReco::AutoRunTimerTimeout()
+{
+  // Slot called on auto-timer timeout.
+
+  Int_t run = fAutoRunScheduled;
+
+  StopAutoRunTimer();
+
+  mIntInt_i i = fRun2PidMap.find(run);
+
+  if (i == fRun2PidMap.end())
+  {
+    Warning("AutoRunTimerTimeout", "run no longer active.");
+    return;
+  }
+
+  Info("AutoRunTimerTimeout", "Starting display for run %d.", run);
+
+  StartAliEve(i);
+  fAutoRunRunning = run;
+}
+
 //------------------------------------------------------------------------------
 // Handlers of DIM signals.
 //------------------------------------------------------------------------------
 
 void AliOnlineReco::StartOfRun(Int_t run)
 {
+  // Slot called from DIM handler on start of run.
+
   mIntInt_i i = fRun2PidMap.find(run);
   if (i == fRun2PidMap.end())
   {
     fRun2PidMap[run] = 0;
     fRunList->AddEntrySort(TString::Format("%d", run), run);
     fRunList->Layout();
+
+    if (fAutoRun->IsOn())
+    {
+      StartAutoRunTimer(run);
+    }
   }
   else
   {
@@ -98,6 +342,8 @@ void AliOnlineReco::StartOfRun(Int_t run)
 
 void AliOnlineReco::EndOfRun(Int_t run)
 {
+  // Slot called from DIM handler on stop of run.
+
   mIntInt_i i = fRun2PidMap.find(run);
   if (i != fRun2PidMap.end())
   {
@@ -107,18 +353,14 @@ void AliOnlineReco::EndOfRun(Int_t run)
     fRun2PidMap.erase(i);
     if (pid)
     {
-      // Send terminate signal to process ...
-      if (fTestMode)
-      {
-       kill(pid, SIGTERM);
-      }
-      else
-      {
-       // alieve will auto-destruct on SIGUSR1
-       kill(pid, SIGUSR1);
-      }
+      KillPid(pid);
     }
     gClient->NeedRedraw(fRunList);
+
+    if (fAutoRunRunning == run)
+    {
+      fAutoRunRunning = 0;
+    }
   }
   else
   {
@@ -132,6 +374,8 @@ void AliOnlineReco::EndOfRun(Int_t run)
 
 void AliOnlineReco::ChildProcTerm(Int_t pid, Int_t status)
 {
+  // Slot called on termination of child process.
   printf("child process termination pid=%d, status=%d...\n", pid, status);
 
   mIntInt_i i = FindMapEntryByPid(pid);
@@ -141,27 +385,59 @@ void AliOnlineReco::ChildProcTerm(Int_t pid, Int_t status)
     fRunList->RemoveEntry(run);
     if (status == 0)
     {
-      fRunList->AddEntrySort(TString::Format("%-20d -- FINISHED", run), run);
+      fRunList->AddEntrySort(TString::Format("%-20d -- PROCESSED", run), run);
     }
     else
     {
-      fRunList->AddEntrySort(TString::Format("%-20d -- CRASHED [%d]", run, status), run);
+      fRunList->AddEntrySort(TString::Format("%-20d -- PROCESSED [%d]", run, status), run);
     }
     fRunList->Layout();
-    i->second = 0;
+    fRun2PidMap.erase(i);
+
+    if (fAutoRunRunning == run && fAutoRun->IsOn())
+    {
+      fAutoRunRunning = 0;
+      StartAutoRunTimer(run);
+    }
+    else
+    {
+      fAutoRunRunning = 0;
+    }
   }
   else
   {
     Warning("ChildProcTerm", "Process with pid=%d not registered.", pid);
   }
+  Emit("ChildProcTerm(Int_t, Int_t)");
+}
+
+void AliOnlineReco::ExitLoopChildProcTerm()
+{
+  if(fDoExit)
+    DoExit();
 }
 
 //------------------------------------------------------------------------------
 // Handlers of button signals.
 //------------------------------------------------------------------------------
 
+void AliOnlineReco::DoAutoRun()
+{
+  // Slot called from auto-run check-box.
+
+  Bool_t autoRun = fAutoRun->IsOn();
+
+  if (autoRun)
+    fStartButt->SetEnabled(kFALSE);
+  else
+    fStartButt->SetEnabled(kTRUE);    
+}
+
 void AliOnlineReco::DoStart()
 {
+  // Slot called from Start button.
+
   Int_t run = fRunList->GetSelected();
   mIntInt_i i = fRun2PidMap.find(run);
 
@@ -171,50 +447,13 @@ void AliOnlineReco::DoStart()
     return;
   }
 
-  if (i->second == 0)
-  {
-    pid_t pid = fork();
-    if (pid == -1)
-    {
-      perror("DoStart -- Fork failed");
-      return;
-    }
-
-    if (pid)
-    {
-      i->second = pid;
-      fRunList->RemoveEntry(run);
-      fRunList->AddEntrySort(TString::Format("%-20d -- RUNNING", run), run);
-      fRunList->Layout();
-    }
-    else
-    {
-      int s;
-      if (fTestMode)
-      {
-       s = execlp("alitestproc", "alitestproc", TString::Format("%d", run).Data(), (char*) 0);
-      }
-      else
-      {
-       // !!!! Cvetan, add proper args here ...
-       s = execlp("alieve", "alieve", TString::Format("%d", run).Data(), (char*) 0);
-      }
-
-      if (s == -1)
-      {
-       perror("execlp failed - this will not end well");
-       gSystem->Exit(1);
-      }
-    }
-  }
-  else
-  {
-    Error("DoStart", "Process already running.");
-  }
+  StartAliEve(i);
 }
 
 void AliOnlineReco::DoStop()
 {
+  // Slot called from Stop button.
+
   Int_t run = fRunList->GetSelected();
   mIntInt_i i = fRun2PidMap.find(run);
 
@@ -227,15 +466,7 @@ void AliOnlineReco::DoStop()
   Int_t pid = i->second;
   if (pid)
   {
-    if (fTestMode)
-    {
-      kill(pid, SIGTERM);
-    }
-    else
-    {
-      // alieve will auto-destruct on SIGUSR1
-      kill(pid, SIGUSR1);
-    }
+    KillPid(pid);
   }
   else
   {
@@ -243,12 +474,105 @@ void AliOnlineReco::DoStop()
   }
 }
 
-void AliOnlineReco::DoXyzz()
+void AliOnlineReco::DoExit()
 {
-  gSystem->ExitLoop();
+  // Slot called from Exit button or CloseWindow.
+  
+  // kill all started processes
+  Int_t pid;
+  
+  // disable all widgets & AutoRunTimer
+  // so that user does not initiate other GUI signals
+  if(!fDoExit){
+    fAutoRun->SetEnabled(kFALSE);
+    fStartButt->SetEnabled(kFALSE);
+    fStopButt->SetEnabled(kFALSE);
+    fExitButt->SetEnabled(kFALSE);
+      
+    StopAutoRunTimer();
+    fDoExit = kTRUE;
+    gROOT->SetInterrupt(kTRUE);
+  }
+  
+  gSystem->ProcessEvents();
+  
+  // clear runs std::map
+  for(mIntInt_i i = fRun2PidMap.begin(); i != fRun2PidMap.end(); i++)
+  {
+    pid = i->second;
+    
+    if(pid==0)
+    {
+      fRun2PidMap.erase(i); // if process is not started just remove it from map
+    }
+    else
+    {
+      // send kill signal to started process
+      KillPid(pid);
+      
+      // we need to exit loop to let ROOT process events list
+      // after kill signal above, process pid starts signal AliChildProcTerminator::ChildProcTerm(int, int)
+      // and arrives in AliOnlineReco::ChildProcTerm(int, int)
+      // after this we return in DoExit() to process next run
+      break;
+    }
+    
+  }
+  
+  // we can exit after we killed all processes
+  if(fRun2PidMap.empty() ) gSystem->ExitLoop();
 }
 
 void AliOnlineReco::CloseWindow()
 {
-  gSystem->ExitLoop();
+  // Virtual method called when window-manager close-window button is pressed.
+  
+  DoExit();
+  
+}
+
+Int_t AliOnlineReco::RetrieveGRP(UInt_t run, TString &gdc)
+{
+  // Retrieve GRP entry for given run from aldaqdb.
+
+  TString dbHost = gSystem->Getenv("ONLINERECO_DB_HOST");
+  if (dbHost.IsNull())
+  {
+    dbHost = "aldaqdb";
+  }
+
+  TString dbPort = gSystem->Getenv("ONLINERECO_DB_PORT");
+  if (dbPort.IsNull())
+  {
+    dbPort = "0";
+  }
+
+  TString dbName = gSystem->Getenv("ONLINERECO_DB_NAME");
+  if (dbName.IsNull())
+  {
+    dbName = "LOGBOOK";
+  }
+
+  TString user = gSystem->Getenv("ONLINERECO_DB_USER");
+  if (user.IsNull())
+  {
+    user = "logbook";
+  }
+
+  TString password = gSystem->Getenv("ONLINERECO_DB_PASSWORD");
+  if (password.IsNull())
+  {
+    password = "alice";
+  }
+
+  Int_t ret=AliGRPPreprocessor::ReceivePromptRecoParameters(run, dbHost.Data(),
+            dbPort.Atoi(), dbName.Data(),
+            user.Data(), password.Data(),
+            Form("local://%s",gSystem->pwd()),
+            gdc);
+
+  if(ret>0) Info("RetrieveGRP","Last run of the same type is: %d",ret);
+  else if(ret==0) Warning("RetrieveGRP","No previous run of the same type found");
+  else if(ret<0) Error("Retrieve","Error code while retrieving GRP parameters returned: %d",ret);
+  return(ret);
 }