]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - HLT/sim/AliHLTOUTComponent.cxx
ALIROOT-5433 Transition to CDHv3 in HLT
[u/mrichter/AliRoot.git] / HLT / sim / AliHLTOUTComponent.cxx
index f6b99c073c05f03ac2883ac03977ca03058b9c4b..71eb1fb39e4309e24058e6093ed22894e708d8bf 100644 (file)
@@ -1,7 +1,7 @@
 // $Id$
 
 //**************************************************************************
-//* This file is property of and copyright by the ALICE HLT Project        * 
+//* This file is property of and copyright by the                          * 
 //* ALICE Experiment at CERN, All rights reserved.                         *
 //*                                                                        *
 //* Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no>        *
 //* provided "as is" without express or implied warranty.                  *
 //**************************************************************************
 
-//  @file   AliHLTOUTComponent.cxx
-//  @author Matthias Richter
-//  @date   
-//  @brief  The HLTOUT data sink component similar to HLTOUT nodes
-//  @note   Used in the AliRoot environment only.
-
-#if __GNUC__>= 3
-using namespace std;
-#endif
+/// @file   AliHLTOUTComponent.cxx
+/// @author Matthias Richter
+/// @date   
+/// @brief  The HLTOUT data sink component similar to HLTOUT nodes
+/// @note   Used in the AliRoot environment only.
 
 #include <cassert>
 //#include <iostream>
@@ -32,90 +28,110 @@ using namespace std;
 #include "AliHLTOUT.h"
 #include "AliHLTHOMERLibManager.h"
 #include "AliHLTHOMERWriter.h"
+#include "AliHLTErrorGuard.h"
 #include "AliDAQ.h" // equipment Ids
-#include "AliRawDataHeader.h" // Common Data Header 
+#include "AliRawDataHeaderV3.h" // Common Data Header 
 #include <TDatime.h> // seed for TRandom
 #include <TRandom.h> // random int generation for DDL no
 #include <TFile.h>
 #include <TTree.h>
 #include <TArrayC.h>
+#include <TSystem.h>
+
+using namespace std;
 
 /** ROOT macro for the implementation of ROOT specific class methods */
 ClassImp(AliHLTOUTComponent)
 
-AliHLTOUTComponent::AliHLTOUTComponent()
-  : AliHLTOfflineDataSink()
+AliHLTOUTComponent::AliHLTOUTComponent(EType type)
+  : AliHLTDataSink()
   , fWriters()
   , fNofDDLs(10)
   , fIdFirstDDL(7680) // 0x1e<<8
   , fBuffer()
   , fpLibManager(NULL)
+  , fOptions(0)
   , fDigitFileName("HLT.Digits.root")
   , fpDigitFile(NULL)
   , fpDigitTree(NULL)
   , fppDigitArrays(NULL)
   , fReservedWriter(-1)
   , fReservedData(0)
+  , fType(type)
+  , fRoundRobinCounter(0)
 {
-  // see header file for class documentation
-  // or
-  // refer to README to build package
-  // or
-  // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
-
-  // I guess DDL definitions should never change any more
-  assert(fNofDDLs==AliDAQ::NumberOfDdls("HLT"));
+  // The HLTOUT data sink component which models the behavior of the HLTOUT
+  // nodes of the HLT cluster.
+  // The HLTOUT component is attached at the end of a chain. It stores all input
+  // block in the HOMER format, distributed over a number of DDL link. The data
+  // is stored in a digit file or in raw ddl files.
+  fIdFirstDDL=AliDAQ::DdlIDOffset("HLT");
   fNofDDLs=AliDAQ::NumberOfDdls("HLT");
   
-  /* AliDAQ::DdlIDOffset returns wrong offset for HLT links
-  assert(fIdFirstDDL==AliDAQ::DdlIDOffset("HLT"));
-  fIdFirstDDL=AliDAQ::DdlIDOffset("HLT");
-  */
+  if (fType!=kGlobal && fType!=kDigits && fType!=kRaw) {
+    ALIHLTERRORGUARD(1, "invalid component type %d", fType);
+  }
 }
 
 int AliHLTOUTComponent::fgOptions=kWriteRawFiles|kWriteDigits;
 
 AliHLTOUTComponent::~AliHLTOUTComponent()
 {
-  // see header file for class documentation
+  // destructor
   if (fpLibManager) delete fpLibManager;
   fpLibManager=NULL;
 }
 
 const char* AliHLTOUTComponent::GetComponentID()
 {
-  // see header file for class documentation
-  return "HLTOUT";
+  // overloaded from AliHLTComponent: get component id
+  switch (fType) {
+  case kDigits: return "HLTOUTdigits";
+  case kRaw:    return "HLTOUTraw";
+  case kGlobal:
+  default:
+    return "HLTOUT";
+  }
+  return NULL;
 }
 
-void AliHLTOUTComponent::GetInputDataTypes( vector<AliHLTComponentDataType>& list)
+void AliHLTOUTComponent::GetInputDataTypes( AliHLTComponentDataTypeList& list)
 {
-  // see header file for class documentation
+  // overloaded from AliHLTComponent: indicate input data types
   list.clear();
   list.push_back(kAliHLTAnyDataType);
 }
 
 AliHLTComponent* AliHLTOUTComponent::Spawn()
 {
-  // see header file for class documentation
-  return new AliHLTOUTComponent;
+  // overloaded from AliHLTComponent: create instance
+  return new AliHLTOUTComponent(fType);
 }
 
 int AliHLTOUTComponent::DoInit( int argc, const char** argv )
 {
-  // see header file for class documentation
+  // overloaded from AliHLTComponent: initialization
   int iResult=0;
-  if ((iResult=ConfigureFromArgumentString(argc, argv))<0) return iResult;
 
-  // Make sure there is no library manager before we try and create a new one.
-  if (fpLibManager) {
-    delete fpLibManager;
-    fpLibManager=NULL;
+  switch (fType) {
+  case kDigits:
+    fOptions|=kWriteDigits; fOptions&=~kWriteRawFiles;
+    HLTInfo("initializing HLTOUT component for digits generation");
+    break;
+  case kRaw:
+    fOptions|=kWriteRawFiles; fOptions&=~kWriteDigits;
+    HLTInfo("initializing HLTOUT component for raw data generation");
+    break;
+  case kGlobal:
+  default:
+    fOptions=fgOptions;
   }
-  
+
+  if ((iResult=ConfigureFromArgumentString(argc, argv))<0) return iResult;
+
   // Create a new library manager and allocate the appropriate number of
   // HOMER writers for the HLTOUT component.
-  fpLibManager=new AliHLTHOMERLibManager;
+  if (!fpLibManager) fpLibManager=new AliHLTHOMERLibManager;
   if (fpLibManager) {
     int writerNo=0;
     for (writerNo=0; writerNo<fNofDDLs; writerNo++) {
@@ -138,7 +154,7 @@ int AliHLTOUTComponent::DoInit( int argc, const char** argv )
 
 int AliHLTOUTComponent::ScanConfigurationArgument(int argc, const char** argv)
 {
-  // see header file for class documentation
+  // overloaded from AliHLTComponent: argument scan
   if (argc<=0) return 0;
   int i=0;
   TString argument=argv[i];
@@ -173,11 +189,11 @@ int AliHLTOUTComponent::ScanConfigurationArgument(int argc, const char** argv)
   if (argument.Contains(key)) {
     argument.ReplaceAll(key, "");
     if (argument.IsNull()) {
-      fgOptions|=kWriteRawFiles;
+      fOptions|=kWriteRawFiles;
     } else if (argument.CompareTo("=off")==0) {
-      fgOptions&=~kWriteRawFiles;
+      fOptions&=~kWriteRawFiles;
     } else if (argument.CompareTo("=on")==0) {
-      fgOptions|=kWriteRawFiles;
+      fOptions|=kWriteRawFiles;
     } else {
       HLTError("invalid parameter for argument %s: possible %s=off/%s=on", key, key, key);
       return -EPROTO;
@@ -191,11 +207,11 @@ int AliHLTOUTComponent::ScanConfigurationArgument(int argc, const char** argv)
   if (argument.Contains(key)) {
     argument.ReplaceAll(key, "");
     if (argument.IsNull()) {
-      fgOptions|=kWriteDigits;
+      fOptions|=kWriteDigits;
     } else if (argument.CompareTo("=off")==0) {
-      fgOptions&=~kWriteDigits;
+      fOptions&=~kWriteDigits;
     } else if (argument.CompareTo("=on")==0) {
-      fgOptions|=kWriteDigits;
+      fOptions|=kWriteDigits;
     } else {
       HLTError("invalid parameter for argument %s: possible %s=off/%s=on", key, key, key);
       return -EPROTO;
@@ -204,13 +220,21 @@ int AliHLTOUTComponent::ScanConfigurationArgument(int argc, const char** argv)
     return 1;
   }
 
+  // -distribute-blocks
+  key="-distribute-blocks";
+  if (argument.CompareTo(key)==0) {
+    fRoundRobinCounter=-1;
+
+    return 1;
+  }
+
   // unknown argument
   return -EINVAL;
 }
 
 int AliHLTOUTComponent::DoDeinit()
 {
-  // see header file for class documentation
+  // overloaded from AliHLTComponent: cleanup
   int iResult=0;
 
   if (fpLibManager) {
@@ -259,7 +283,7 @@ int AliHLTOUTComponent::DumpEvent( const AliHLTComponentEventData& evtData,
                         const AliHLTComponentBlockData* blocks, 
                         AliHLTComponentTriggerData& /*trigData*/ )
 {
-  // see header file for class documentation
+  // overloaded from AliHLTDataSink: event processing
   int iResult=0;
   HLTInfo("write %d output block(s)", evtData.fBlockCnt);
   int writerNo=0;
@@ -349,31 +373,26 @@ int AliHLTOUTComponent::DumpEvent( const AliHLTComponentEventData& evtData,
   }
 
   if (iResult>=0 && bIsDataEvent) {
-    iResult=Write(GetEventCount(), GetRunLoader());
+    iResult=Write(GetEventCount());
   }
 
-  return iResult;
-}
-
+  if (fRoundRobinCounter>=0) {
+    if (++fRoundRobinCounter>=fNofDDLs) fRoundRobinCounter=0;
+  }
 
-int AliHLTOUTComponent::FillESD(int eventNo, AliRunLoader* runLoader, AliESDEvent* /*esd*/)
-{
-  // see header file for class documentation
-  // 2010-04-14 nothing to do any more. The data is written at the end of
-  // DumpEvent
-  return 0;
+  return iResult;
 }
 
-int AliHLTOUTComponent::Write(int eventNo, AliRunLoader* runLoader)
+int AliHLTOUTComponent::Write(int eventNo)
 {
-  // see header file for class documentation
+  // write digits and raw files for the current event
   int iResult=0;
 
   if (fWriters.size()==0) return 0;
 
   if (fReservedWriter>=0) {
-    if (fgOptions&kWriteDigits) WriteDigitArray(fReservedWriter, &fBuffer[0], fReservedData);
-    if (fgOptions&kWriteRawFiles) WriteRawFile(eventNo, runLoader, fReservedWriter, &fBuffer[0], fReservedData);
+    if (fOptions&kWriteDigits) WriteDigitArray(fReservedWriter, &fBuffer[0], fReservedData);
+    if (fOptions&kWriteRawFiles) WriteRawFile(eventNo, fReservedWriter, &fBuffer[0], fReservedData);
     fReservedData=0;
   }
 
@@ -399,19 +418,37 @@ int AliHLTOUTComponent::Write(int eventNo, AliRunLoader* runLoader)
     int bufferSize=0;
     
     if ((bufferSize=FillOutputBuffer(eventNo, fWriters[*ddlno], pBuffer))>0) {
-      if (fgOptions&kWriteDigits) WriteDigitArray(*ddlno, pBuffer, bufferSize);
-      if (fgOptions&kWriteRawFiles) WriteRawFile(eventNo, runLoader, *ddlno, pBuffer, bufferSize);
+      if (fOptions&kWriteDigits) WriteDigitArray(*ddlno, pBuffer, bufferSize);
+      if (fOptions&kWriteRawFiles &&
+         (fRoundRobinCounter<0 || fRoundRobinCounter==*ddlno))
+       WriteRawFile(eventNo, *ddlno, pBuffer, bufferSize);
     }
     fWriters[*ddlno]->Clear();
     ddlno++;
   }
-  if (fgOptions&kWriteDigits) WriteDigits(eventNo, runLoader);
+  if (fOptions&kWriteDigits) WriteDigits(eventNo);
   return iResult;
 }
 
 int AliHLTOUTComponent::ShuffleWriters(AliHLTMonitoringWriterPVector &list, AliHLTUInt32_t /*size*/)
 {
-  // see header file for class documentation
+  /// get a writer for the next block
+  /// in round robin mode (like the online HLTOUT) all blocks of one event go to the same link
+  /// this is now also the default behavior of the HLTOUTComponent and indicated by
+  /// fRoundRobinCounter>=0
+  /// Writers are selected randomly otherwise.
+  if (fRoundRobinCounter>=0) {
+    if (fRoundRobinCounter==fReservedWriter) {
+      if (++fRoundRobinCounter>=fNofDDLs) fRoundRobinCounter=0;
+      if (fRoundRobinCounter==fReservedWriter) {
+       HLTWarning("there are not enough links to use a reserved writer, discarding data in reserved writer %d (total %d)",
+                  fReservedWriter, fNofDDLs);
+       fReservedWriter=-1;
+      }
+    }
+    return fRoundRobinCounter;
+  }
+
   int iResult=-ENOENT;
   assert(list.size()>0);
   if (list.size()==0) return iResult;
@@ -446,13 +483,16 @@ int AliHLTOUTComponent::ShuffleWriters(AliHLTMonitoringWriterPVector &list, AliH
 
 int AliHLTOUTComponent::FillOutputBuffer(int eventNo, AliHLTMonitoringWriter* pWriter, const AliHLTUInt8_t* &pBuffer)
 {
-  // see header file for class documentation
+  // prepare the output buffer for writing, consists of
+  // - CDH
+  // - HLTOUT header
+  // - HOMER data
+  // buffer is allocated internally and data is valid until next call
   int iResult=0;
   unsigned int bufferSize=0;
 
   // space for common data header
-  bufferSize+=sizeof(AliRawDataHeader);
-  assert(sizeof(AliRawDataHeader)==32);
+  bufferSize+=sizeof(AliRawDataHeaderV3);
 
   // space for HLT event header
   bufferSize+=sizeof(AliHLTOUT::AliHLTOUTEventHeader);
@@ -471,14 +511,14 @@ int AliHLTOUTComponent::FillOutputBuffer(int eventNo, AliHLTMonitoringWriter* pW
   memset(&fBuffer[bufferSize-4], 0, 4);
 
   if (bufferSize<=fBuffer.size()) {
-    AliRawDataHeader* pCDH=reinterpret_cast<AliRawDataHeader*>(&fBuffer[0]);
-    AliHLTOUT::AliHLTOUTEventHeader* pHLTH=reinterpret_cast<AliHLTOUT::AliHLTOUTEventHeader*>(&fBuffer[sizeof(AliRawDataHeader)]);
-    *pCDH = AliRawDataHeader();  // Fill with default values.
+    AliRawDataHeaderV3* pCDH=reinterpret_cast<AliRawDataHeaderV3*>(&fBuffer[0]);
+    AliHLTOUT::AliHLTOUTEventHeader* pHLTH=reinterpret_cast<AliHLTOUT::AliHLTOUTEventHeader*>(&fBuffer[sizeof(AliRawDataHeaderV3)]);
+    *pCDH = AliRawDataHeaderV3();  // Fill with default values.
     memset(pHLTH, 0, sizeof(AliHLTOUT::AliHLTOUTEventHeader));
 
     if (pWriter) {
       // copy payload
-      pWriter->Copy(&fBuffer[sizeof(AliRawDataHeader)+sizeof(AliHLTOUT::AliHLTOUTEventHeader)], 0, 0, 0, 0);
+      pWriter->Copy(&fBuffer[sizeof(AliRawDataHeaderV3)+sizeof(AliHLTOUT::AliHLTOUTEventHeader)], 0, 0, 0, 0);
       pHLTH->fLength=pWriter->GetTotalMemorySize();
       // set status bit to indicate HLT payload
       pCDH->fStatusMiniEventID|=0x1<<(AliHLTOUT::kCDHStatusFlagsOffset+AliHLTOUT::kCDHFlagsHLTPayload);
@@ -504,7 +544,7 @@ int AliHLTOUTComponent::FillOutputBuffer(int eventNo, AliHLTMonitoringWriter* pW
 
 int AliHLTOUTComponent::WriteDigitArray(int hltddl, const AliHLTUInt8_t* pBuffer, unsigned int bufferSize)
 {
-  // see header file for class documentation
+  // wite a buffer to the associated digit array
   int iResult=0;
   assert(hltddl<fNofDDLs);
   if (hltddl>=fNofDDLs) return -ERANGE;
@@ -525,9 +565,12 @@ int AliHLTOUTComponent::WriteDigitArray(int hltddl, const AliHLTUInt8_t* pBuffer
   return iResult;
 }
 
-int AliHLTOUTComponent::WriteDigits(int /*eventNo*/, AliRunLoader* /*runLoader*/)
+int AliHLTOUTComponent::WriteDigits(int /*eventNo*/)
 {
-  // see header file for class documentation
+  // fill tree with digit arrays and write to file
+  // all links must be written, even in round robin mode, where all links but one
+  // do not contain any data blocks.
+  // This is a limitation of storing the links in a tree
   int iResult=0;
   if (!fpDigitFile) {
     fpDigitFile=new TFile(fDigitFileName, "RECREATE");
@@ -543,11 +586,17 @@ int AliHLTOUTComponent::WriteDigits(int /*eventNo*/, AliRunLoader* /*runLoader*/
       }
     }
     if (fpDigitTree) {
+#ifdef __DEBUG
       int res=fpDigitTree->Fill();
       HLTDebug("writing digit tree: %d", res);
       fpDigitFile->cd();
       res=fpDigitTree->Write("",TObject::kOverwrite);
       HLTDebug("writing digit tree: %d", res);
+#else
+      fpDigitTree->Fill();
+      fpDigitFile->cd();
+      fpDigitTree->Write("",TObject::kOverwrite);
+#endif
       if (fppDigitArrays) for (int i=0; i<fNofDDLs; i++) {
        if (fppDigitArrays[i]) fppDigitArrays[i]->Set(0);
       }
@@ -565,14 +614,20 @@ int AliHLTOUTComponent::WriteDigits(int /*eventNo*/, AliRunLoader* /*runLoader*/
   return iResult;
 }
 
-int AliHLTOUTComponent::WriteRawFile(int eventNo, AliRunLoader* /*runLoader*/, int hltddl, const AliHLTUInt8_t* pBuffer, unsigned int bufferSize)
+int AliHLTOUTComponent::WriteRawFile(int eventNo, int hltddl, const AliHLTUInt8_t* pBuffer, unsigned int bufferSize)
 {
-  // see header file for class documentation
+  // write buffer to raw file in the current directory
+  // creates the event raw directories in the current directory
   int iResult=0;
   const char* fileName=AliDAQ::DdlFileName("HLT", hltddl);
   assert(fileName!=NULL);
   TString filePath;
   filePath.Form("raw%d/", eventNo);
+  if (gSystem->AccessPathName(filePath)!=0) {
+    // note: AccessPathName return 0 if the path is existing
+    TString command="mkdir "; command+=filePath;
+    gSystem->Exec(command);
+  }
   filePath+=fileName;
   if (fileName) {
     ios::openmode filemode=(ios::openmode)0;
@@ -595,12 +650,18 @@ int AliHLTOUTComponent::WriteRawFile(int eventNo, AliRunLoader* /*runLoader*/, i
 
 void AliHLTOUTComponent::SetGlobalOption(unsigned int options)
 {
-  // see header file for class documentation
+  // set the global options
   fgOptions|=options;
 }
 
 void AliHLTOUTComponent::ClearGlobalOption(unsigned int options)
 {
-  // see header file for class documentation
+  // reset the global options
   fgOptions&=~options;
 }
+
+bool AliHLTOUTComponent::TestGlobalOption(unsigned int option)
+{
+  // check option
+  return (fgOptions&option)!=0;
+}