]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - HLT/trigger/AliHLTGlobalTriggerComponent.cxx
Fixing bug caused by UUID not being generated properly.
[u/mrichter/AliRoot.git] / HLT / trigger / AliHLTGlobalTriggerComponent.cxx
index df4ca0a6505ec9eb2b79031cdfac1c6f61b55248..ee37cc5345a42d1d9a38303b920fe268b84afb40 100644 (file)
@@ -33,6 +33,8 @@
 #include "AliCDBStorage.h"
 #include "AliCDBEntry.h"
 #include "TUUID.h"
+#include "TMD5.h"
+#include "TRandom3.h"
 #include "TROOT.h"
 #include "TSystem.h"
 #include "TRegexp.h"
@@ -160,7 +162,15 @@ Int_t AliHLTGlobalTriggerComponent::DoInit(int argc, const char** argv)
         HLTError("The include path was not specified." );
         return -EINVAL;
       }
-      new (fIncludePaths[fIncludePaths.GetEntriesFast()]) TObjString(argv[i+1]);
+      try
+      {
+        new (fIncludePaths[fIncludePaths.GetEntriesFast()]) TObjString(argv[i+1]);
+      }
+      catch (const std::bad_alloc&)
+      {
+        HLTError("Could not allocate more memory for the fIncludePaths array.");
+        return -ENOMEM;
+      }
       i++;
       continue;
     }
@@ -172,7 +182,15 @@ Int_t AliHLTGlobalTriggerComponent::DoInit(int argc, const char** argv)
         HLTError("The include file name was not specified." );
         return -EINVAL;
       }
-      new (fIncludeFiles[fIncludeFiles.GetEntriesFast()]) TObjString(argv[i+1]);
+      try
+      {
+        new (fIncludeFiles[fIncludeFiles.GetEntriesFast()]) TObjString(argv[i+1]);
+      }
+      catch (const std::bad_alloc&)
+      {
+        HLTError("Could not allocate more memory for the fIncludeFiles array.");
+        return -ENOMEM;
+      }
       i++;
       continue;
     }
@@ -313,7 +331,15 @@ Int_t AliHLTGlobalTriggerComponent::DoInit(int argc, const char** argv)
   }
   if (result != 0) return result;
   
-  fTrigger = AliHLTGlobalTrigger::CreateNew(fClassName.Data());
+  try
+  {
+    fTrigger = AliHLTGlobalTrigger::CreateNew(fClassName.Data());
+  }
+  catch (const std::bad_alloc&)
+  {
+    HLTError("Could not allocate memory for the AliHLTGlobalTrigger instance.");
+    return -ENOMEM;
+  }
   if (fTrigger == NULL)
   {
     HLTError("Could not create a new instance of '%s'.", fClassName.Data());
@@ -368,8 +394,17 @@ Int_t AliHLTGlobalTriggerComponent::DoDeinit()
 AliHLTComponent* AliHLTGlobalTriggerComponent::Spawn()
 {
   // Creates a new object instance.
-  
-  return new AliHLTGlobalTriggerComponent;
+  AliHLTComponent* comp = NULL;
+  try
+  {
+    comp = new AliHLTGlobalTriggerComponent;
+  }
+  catch (const std::bad_alloc&)
+  {
+    HLTError("Could not allocate memory for a new instance of AliHLTGlobalTriggerComponent.");
+    return NULL;
+  }
+  return comp;
 }
 
 
@@ -388,7 +423,7 @@ int AliHLTGlobalTriggerComponent::DoTrigger()
     if (eventType==gkAliEventTypeEndOfRun) PrintStatistics(fTrigger, kHLTLogImportant, 0);
     if (fDataEventsOnly)
     {
-      IgnoreEvent();
+      IgnoreEvent();  // dont generate any trigger decision.
       return 0;
     }
   }
@@ -430,69 +465,69 @@ int AliHLTGlobalTriggerComponent::DoTrigger()
       (triggerResult == true) ? description.Data() : GetDescription()
     );
 
-  // mask the readout list according to the CTP trigger
-  // if the classes have been initialized (mask non-zero)
-  if (pCTPData && pCTPData->Mask()) {
-    AliHLTEventDDL eventDDL=pCTPData->ReadoutList(*GetTriggerData());
-    AliHLTReadoutList ctpreadout(eventDDL);
-    ctpreadout.Enable(AliHLTReadoutList::kHLT);
-    AliHLTReadoutList maskedList=decision.ReadoutList();
-    maskedList.AndEq(ctpreadout);
-    decision.ReadoutList(maskedList);
-  }
-
   decision.SetCounters(fTrigger->GetCounters(), GetEventCount()+1);
   if (fTrigger->CallFailed()) return -EPROTO;
   
-  static UInt_t lastTime=0;
-  TDatime time;
-  if (time.Get()-lastTime>60) {
-    lastTime=time.Get();
-    PrintStatistics(fTrigger, kHLTLogImportant);
-  }
+  TClonesArray shortInfo(TNamed::Class(), GetNumberOfInputBlocks());
   
-  // Add the input objects used to the global decision.
-  TClonesArray* pShortInfo=NULL;
-  if (TestBit(kIncludeShort)) {
-    pShortInfo=new TClonesArray(TNamed::Class(), GetNumberOfInputBlocks());
-  }
+  // Add the input objects used to make the global decision.
   obj = GetFirstInputObject();
   while (obj != NULL)
   {
-    if (TestBit(kForwardInput)) {
-      Forward(obj);
-    }
-    if (TestBit(kIncludeInput)) {
-    if (obj->IsA() == AliHLTTriggerDecision::Class())
+    const AliHLTTriggerDecision* intrig = dynamic_cast<const AliHLTTriggerDecision*>(obj);
+    
+    if (TestBit(kForwardInput)) Forward(obj);
+    
+    if (TestBit(kIncludeInput))
     {
-      decision.AddTriggerInput( *static_cast<const AliHLTTriggerDecision*>(obj) );
+      if (intrig != NULL)
+      {
+         decision.AddTriggerInput(*intrig);
+      }
+      else
+      {
+        // The const_cast should be safe in this case because the list of inputObjects
+        // will be added to the global decision with AddInputObjectRef, which only
+        // modifies the kCanDelete bit and nothing else.
+        // This is necessary since GetFirstInputObject only returns const objects.
+        decision.AddInputObjectRef( const_cast<TObject*>(obj) );
+      }
     }
-    else
+    
+    if (TestBit(kIncludeShort))
     {
-      decision.AddInputObject(obj);
-    }
-    }
-
-    if (TestBit(kIncludeShort)) {
-      int entries=pShortInfo->GetEntriesFast();
-      new ((*pShortInfo)[entries]) TNamed(obj->GetName(), obj->GetTitle());
-      if (obj->IsA() == AliHLTTriggerDecision::Class()) {
-       (*pShortInfo)[entries]->SetBit(BIT(16)); // indicate that this is a trigger decision
-       (*pShortInfo)[entries]->SetBit(BIT(15), ((AliHLTTriggerDecision*)obj)->Result());
+      int entries = shortInfo.GetEntriesFast();
+      try
+      {
+        new (shortInfo[entries]) TNamed(obj->GetName(), obj->GetTitle());
+      }
+      catch (const std::bad_alloc&)
+      {
+        HLTError("Could not allocate more memory for the short list of input objects.");
+        return -ENOMEM;
+      }
+      if (intrig != NULL)
+      {
+        shortInfo[entries]->SetBit(BIT(16)); // indicate that this is a trigger decision
+        shortInfo[entries]->SetBit(BIT(15), intrig->Result());
       }
     }
 
     obj = GetNextInputObject();
   }
-  if (pShortInfo) {
-    decision.AddInputObject(pShortInfo);
-    pShortInfo->Delete();
-    delete pShortInfo;
-    pShortInfo=NULL;
+  if (TestBit(kIncludeShort)) decision.AddInputObjectRef(&shortInfo);
+  
+  // The const_cast should be safe in this case because AddInputObjectRef just
+  // modifies the kCanDelete bit and nothing else.
+  if (!TestBit(kSkipCTP) && CTPData()) decision.AddInputObjectRef(const_cast<AliHLTCTPData*>(CTPData()));
+  
+  static UInt_t lastTime=0;
+  TDatime time;
+  if (time.Get()-lastTime>60) {
+    lastTime=time.Get();
+    PrintStatistics(fTrigger, kHLTLogImportant);
   }
 
-  if (!TestBit(kSkipCTP) && CTPData()) decision.AddInputObject(CTPData());
-
   // add readout filter to event done data
   CreateEventDoneReadoutFilter(decision.TriggerDomain(), 3);
   // add monitoring filter to event done data
@@ -537,7 +572,16 @@ int AliHLTGlobalTriggerComponent::Reconfigure(const char* cdbEntry, const char*
   result = GenerateTrigger(menu, className, codeFileName, fIncludePaths, fIncludeFiles);
   if (result != 0) return result;
   
-  AliHLTGlobalTrigger* trigger = AliHLTGlobalTrigger::CreateNew(className.Data());
+  AliHLTGlobalTrigger* trigger = NULL;
+  try
+  {
+    trigger = AliHLTGlobalTrigger::CreateNew(className.Data());
+  }
+  catch (const std::bad_alloc&)
+  {
+    HLTError("Could not allocate memory for the AliHLTGlobalTrigger instance.");
+    return -ENOMEM;
+  }
   if (trigger == NULL)
   {
     HLTError("Could not create a new instance of '%s'.", className.Data());
@@ -623,6 +667,63 @@ int AliHLTGlobalTriggerComponent::LoadTriggerMenu(const char* cdbPath, const Ali
 }
 
 
+void AliHLTGlobalTriggerComponent::GenerateFileName(TString& name, TString& filename) const
+{
+  // Creates a unique file name for the generated code.
+  
+  // Start by creating a new UUID. We cannot use the one automatically generated
+  // by ROOT because the algorithm used will not guarantee unique IDs when generating
+  // these UUIDs at a high rate in parallel.
+  TUUID uuid;
+  // We then use the generated UUID to form part of the random number seeds which
+  // will be used to generate a proper random UUID. For good measure we use a MD5
+  // hash also. Note that we want to use the TUUID class because it will combine the
+  // host address information into the UUID. Using gSystem->GetHostByName() apparently
+  // can cause problems on Windows machines with a firewall, because it always tries
+  // to contact a DNS. The TUUID class handles this case appropriately.
+  union
+  {
+    UChar_t buf[16];
+    UShort_t word[8];
+    UInt_t dword[4];
+  };
+  uuid.GetUUID(buf);
+  TMD5 md5;
+  md5.Update(buf, sizeof(buf));
+  md5.Final(buf);
+  dword[0] += gSystem->GetUid();
+  dword[1] += gSystem->GetGid();
+  dword[2] += gSystem->GetPid();
+  for (int i = 0; i < 4; ++i)
+  {
+    gRandom->SetSeed(dword[i]);
+    dword[i] = gRandom->Integer(0xFFFFFFFF);
+  }
+  md5.Update(buf, sizeof(buf));
+  md5.Final(buf);
+  // To keep to the standard we need to set the version and reserved bits.
+  word[3] = (word[3] & 0x0FFF) | 0x4000;
+  buf[8] = (buf[8] & 0x3F) | 0x80;
+
+  // Create the name of the new class and file.
+  char uuidstr[64];
+  sprintf(uuidstr, "%08x_%04x_%04x_%02x%02x_%02x%02x%02x%02x%02x%02x",
+    dword[0], word[2], word[3], buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]
+  );
+  name = "AliHLTGlobalTriggerImpl_";
+  name += uuidstr;
+  filename = name + ".cxx";
+
+  // For good measure, check that the file names are not used. If they are then regenerate.
+  fstream file(filename.Data(), ios_base::in);
+  if (file.good())
+  {
+    file.close();
+    GenerateFileName(name, filename);
+  }
+}
+
+
 int AliHLTGlobalTriggerComponent::GenerateTrigger(
     const AliHLTTriggerMenu* menu, TString& name, TString& filename,
     const TClonesArray& includePaths, const TClonesArray& includeFiles
@@ -631,21 +732,10 @@ int AliHLTGlobalTriggerComponent::GenerateTrigger(
   // Generates the global trigger class that will implement the specified trigger menu.
   // See header for more details.
   
-  HLTDebug("Generating custom HLT trigger class named %s using trigger menu %p.", ((void*)menu), name.Data());
-  
-  // Create a new UUID and replace the '-' characters with '_' to make it a valid
-  // C++ symbol name.
-  TUUID uuid;
-  TString uuidstr = uuid.AsString();
-  for (Int_t i = 0; i < uuidstr.Length(); i++)
-  {
-    if (uuidstr[i] == '-') uuidstr[i] = '_';
-  }
-  
-  // Create the name of the new class.
-  name = "AliHLTGlobalTriggerImpl_";
-  name += uuidstr;
-  filename = name + ".cxx";
+  GenerateFileName(name, filename);
+  HLTDebug("Generating custom HLT trigger class named %s, in file %s, using trigger menu %p.",
+    name.Data(), filename.Data(), ((void*)menu)
+  );
   
   // Open a text file to write the code and generate the new class.
   fstream code(filename.Data(), ios_base::out | ios_base::trunc);
@@ -661,6 +751,7 @@ int AliHLTGlobalTriggerComponent::GenerateTrigger(
   
   code << "#if !defined(__CINT__) || defined(__MAKECINT__)" << endl;
   code << "#include <cstring>" << endl;
+  code << "#include \"TClass.h\"" << endl;
   code << "#include \"TString.h\"" << endl;
   code << "#include \"TClonesArray.h\"" << endl;
   code << "#include \"AliHLTLogging.h\"" << endl;
@@ -794,6 +885,28 @@ int AliHLTGlobalTriggerComponent::GenerateTrigger(
     code << "      }" << endl;
   }
   code << "    }" << endl;
+  // The following is an optimisation where symbols without any assignment operators
+  // are treated as constant and only initialised in FillFromMenu rather than reseting
+  // them in the NewEvent method.
+  // Note: we putting this initialisation into the constructor can lead to seg faults
+  // under CINT interpretation. Thus we must put it into the FillFromMenu method instead.
+  for (Int_t i = 0; i < symbols.GetEntriesFast(); i++)
+  {
+    AliHLTTriggerMenuSymbol* symbol = static_cast<AliHLTTriggerMenuSymbol*>( symbols.UncheckedAt(i) );
+    if (TString(symbol->AssignExpression()) != "") continue;
+    if (strcmp(symbol->ObjectClass(), "AliHLTTriggerDecision") == 0) continue;
+    // CINT has problems with the implicit equals operator for complex types, so if
+    // the type has an equals operater we need to write the operator call explicitly.
+    TClass* clas = TClass::GetClass(symbol->Type());
+    if (clas != NULL and clas->GetMethodAny("operator=") != NULL)
+    {
+      code << "    " << symbol->Name() << ".operator = (" << symbol->DefaultValue() << ");" << endl;
+    }
+    else
+    {
+      code << "    " << symbol->Name() << " = " << symbol->DefaultValue() << ";" << endl;
+    }
+  }
   if (fDebugMode)
   {
     code << "    HLTDebug(Form(\"Finished filling domain entries from trigger menu symbols.\"));" << endl;
@@ -813,8 +926,12 @@ int AliHLTGlobalTriggerComponent::GenerateTrigger(
   for (Int_t i = 0; i < symbols.GetEntriesFast(); i++)
   {
     AliHLTTriggerMenuSymbol* symbol = static_cast<AliHLTTriggerMenuSymbol*>( symbols.UncheckedAt(i) );
+    // The following is an optimisation. If the symbol does not have an assignment expression
+    // then it is effectively a constant symbol and can be initialised earlier and only once.
+    // In this case we initialise it in the FillFromMenu method instead.
+    if (TString(symbol->AssignExpression()) == "") continue;
     // CINT has problems with the implicit equals operator for complex types, so if
-    // the type has a equals operater we need to write the operator call explicitly.
+    // the type has an equals operater we need to write the operator call explicitly.
     TClass* clas = TClass::GetClass(symbol->Type());
     if (clas != NULL and clas->GetMethodAny("operator=") != NULL)
     {
@@ -836,7 +953,25 @@ int AliHLTGlobalTriggerComponent::GenerateTrigger(
   code << "  }" << endl;
   
   // Generate the Add method.
-  code << "  virtual void Add(const TObject* _object_, const AliHLTComponentDataType& _type_, AliHLTUInt32_t _spec_) {" << endl;
+  bool haveAssignments = false;
+  for (Int_t i = 0; i < symbols.GetEntriesFast(); i++)
+  {
+    // First check if we have any symbols with assignment expressions.
+    // This is needed to get rid of the on the fly compilation warning about '_object_' not being used.
+    AliHLTTriggerMenuSymbol* symbol = static_cast<AliHLTTriggerMenuSymbol*>( symbols.UncheckedAt(i) );
+    TString expr = symbol->AssignExpression();
+    if (expr == "") continue; // Skip entries that have no assignment expression.
+    haveAssignments = true;
+    break;
+  }
+  if (haveAssignments or fDebugMode)
+  {
+    code << "  virtual void Add(const TObject* _object_, const AliHLTComponentDataType& _type_, AliHLTUInt32_t _spec_) {" << endl;
+  }
+  else
+  {
+    code << "  virtual void Add(const TObject* /*_object_*/, const AliHLTComponentDataType& _type_, AliHLTUInt32_t _spec_) {" << endl;
+  }
   if (fDebugMode)
   {
     code << "#ifdef __CINT__" << endl;
@@ -879,7 +1014,7 @@ int AliHLTGlobalTriggerComponent::GenerateTrigger(
     // 30 Oct 2009 - CINT sometimes evaluates the dynamic_cast incorrectly.
     // Have to use the TClass system for extra protection.
     code << "    const " << symbol->ObjectClass() << "* " << symbol->Name() << "_object_ = NULL;" << endl;
-    code << "    if (_object_->IsA() == " << symbol->ObjectClass() << "::Class()) " << symbol->Name()
+    code << "    if (_object_->InheritsFrom(" << symbol->ObjectClass() << "::Class())) " << symbol->Name()
          << "_object_ = dynamic_cast<const " << symbol->ObjectClass()
          << "*>(_object_);" << endl;
     code << "    if (" << symbol->Name() << "_object_ != NULL && ";
@@ -1379,7 +1514,15 @@ int AliHLTGlobalTriggerComponent::BuildSymbolList(const AliHLTTriggerMenu* menu,
       HLTError("Multiple symbols with the name '%s' defined in the trigger menu.", symbol->Name());
       return -EIO;
     }
-    new (list[list.GetEntriesFast()]) AliHLTTriggerMenuSymbol(*symbol);
+    try
+    {
+      new (list[list.GetEntriesFast()]) AliHLTTriggerMenuSymbol(*symbol);
+    }
+    catch (const std::bad_alloc&)
+    {
+      HLTError("Could not allocate more memory for the symbols list when adding a trigger menu symbol.");
+      return -ENOMEM;
+    }
   }
   
   TRegexp exp("[_a-zA-Z][-_a-zA-Z0-9]*");
@@ -1436,7 +1579,15 @@ int AliHLTGlobalTriggerComponent::BuildSymbolList(const AliHLTTriggerMenu* menu,
       newSymbol.DefaultValue("false");
       if (FindSymbol(newSymbol.Name(), list) == -1)
       {
-        new (list[list.GetEntriesFast()]) AliHLTTriggerMenuSymbol(newSymbol);
+        try
+        {
+          new (list[list.GetEntriesFast()]) AliHLTTriggerMenuSymbol(newSymbol);
+        }
+        catch (const std::bad_alloc&)
+        {
+          HLTError("Could not allocate more memory for the symbols list when adding a trigger name symbol.");
+          return -ENOMEM;
+        }
       }
     }
     while (start < str.Length());
@@ -1525,10 +1676,26 @@ int AliHLTGlobalTriggerComponent::AddCTPDecisions(AliHLTGlobalTrigger* pTrigger,
   AliHLTUInt64_t triggerMask=pCTPData->Mask();
   AliHLTUInt64_t bit0=0x1;
   if (!fCTPDecisions) {
-    fCTPDecisions=new TClonesArray(AliHLTTriggerDecision::Class(), gkNCTPTriggerClasses);
+    try
+    {
+      fCTPDecisions=new TClonesArray(AliHLTTriggerDecision::Class(), gkNCTPTriggerClasses);
+    }
+    catch (const std::bad_alloc&)
+    {
+      HLTError("Could not allocate memory for the CTP decisions array.");
+      return -ENOMEM;
+    }
     if (!fCTPDecisions) return -ENOMEM;
 
-    fCTPDecisions->ExpandCreate(gkNCTPTriggerClasses);
+    try
+    {
+      fCTPDecisions->ExpandCreate(gkNCTPTriggerClasses);
+    }
+    catch (const std::bad_alloc&)
+    {
+      HLTError("Could not allocate more memory for the CTP decisions array.");
+      return -ENOMEM;
+    }
     for (int i=0; i<gkNCTPTriggerClasses; i++) {
       const char* name=pCTPData->Name(i);
       if (triggerMask&(bit0<<i) && name) {
@@ -1552,8 +1719,14 @@ int AliHLTGlobalTriggerComponent::AddCTPDecisions(AliHLTGlobalTrigger* pTrigger,
     if (!pDecision) return -ENOENT;
 
     bool result=false;
-    if (trigData) result=pCTPData->EvaluateCTPTriggerClass(name, *trigData);
-    else result=pCTPData->EvaluateCTPTriggerClass(name);
+    // 13 March 2010 - Optimisation:
+    // Dont use the EvaluateCTPTriggerClass method, which uses slow TFormula objects.
+    AliHLTUInt64_t triggers = 0;
+    if (trigData) triggers = pCTPData->ActiveTriggers(*trigData);
+    else triggers = pCTPData->Triggers();
+    result = (triggers&((AliHLTUInt64_t)0x1<<i)) ? true : false;
+    //if (trigData) result=pCTPData->EvaluateCTPTriggerClass(name, *trigData);
+    //else result=pCTPData->EvaluateCTPTriggerClass(name);
     pDecision->Result(result);
     pDecision->TriggerDomain().Clear();
     if (trigData) pDecision->TriggerDomain().Add(pCTPData->ReadoutList(*trigData));