doing backward compatibility correctly
[u/mrichter/AliRoot.git] / HLT / rec / AliRawReaderHLT.cxx
index 0bde3220b1a6f1673517524e1534fe6553dd4a70..bd11a1ebcfe0e0e7f0789f5f78c6c88b91e68bc2 100644 (file)
@@ -31,6 +31,9 @@
 #include "AliRawReaderHLT.h"
 #include "AliHLTOUTRawReader.h"
 #include "AliHLTModuleAgent.h"
+#include "AliHLTOUTHandler.h"
+#include "AliHLTOUTHandlerEquId.h"
+#include "AliHLTSystem.h"
 #include "AliLog.h"
 #include "AliDAQ.h"            // RAW, for detector names and equipment ids
 #include "TObjString.h"
@@ -42,15 +45,20 @@ ClassImp(AliRawReaderHLT)
 AliRawReaderHLT::AliRawReaderHLT(AliRawReader* pRawreader, const char* options)
   :
   AliRawReader(),
+  AliHLTReconstructorBase(),
   fpParentReader(pRawreader),
   fOptions(),
+  fSystemOptions(),
   fpData(NULL),
   fDataSize(0),
   fOffset(0),
+  fPosition(0),
   fEquipmentId(-1),
   fbHaveHLTData(false),
   fDetectors(),
-  fpHLTOUT(NULL)
+  fpHLTOUT(NULL),
+  fbReadFirst(true),
+  fpDataHandler(NULL)
 {
   // see header file for class documentation
   // or
@@ -64,6 +72,7 @@ AliRawReaderHLT::AliRawReaderHLT(AliRawReader* pRawreader, const char* options)
 AliRawReaderHLT::~AliRawReaderHLT()
 {
   // see header file for class documentation
+  ReleaseHLTData();
 }
 
 UInt_t AliRawReaderHLT::GetType() const
@@ -179,8 +188,35 @@ Int_t    AliRawReaderHLT::GetEquipmentId() const
 Bool_t   AliRawReaderHLT::ReadHeader()
 {
   // see header file for class documentation
-  Bool_t result=fpParentReader->ReadHeader();
-  fHeader=const_cast<AliRawDataHeader*>(fpParentReader->GetDataHeader());
+  Bool_t result=kFALSE;
+  Bool_t firstParentCycle=fbHaveHLTData;
+  while (fbHaveHLTData=(fbHaveHLTData && ReadNextHLTData())) {
+    // all internal data variables set
+    assert(fpData!=NULL);
+    fHeader=reinterpret_cast<AliRawDataHeader*>(const_cast<AliHLTUInt8_t*>(fpData));
+    fOffset=sizeof(AliRawDataHeader);
+    fPosition=fOffset;
+    if (result=IsSelected()) break;
+  }
+  firstParentCycle&=!fbHaveHLTData; // true if it just changed from true to false
+  while (!result) {
+    if (firstParentCycle) {
+      firstParentCycle=kFALSE;
+      // reset and set the selection back to the original one
+      fpParentReader->Reset();
+      fpParentReader->SelectEquipment(fSelectEquipmentType, fSelectMinEquipmentId, fSelectMaxEquipmentId);
+    }
+
+    if (!(result=fpParentReader->ReadHeader())) {
+      fHeader=NULL;
+      break;
+    }
+    fHeader=const_cast<AliRawDataHeader*>(fpParentReader->GetDataHeader());
+
+    // filter out all equipment ids which should be taken from the HLT stream
+    int id=fpParentReader->GetEquipmentId();
+    if (result=!IsHLTInput(id)) break;
+  }
   return result;
 }
 
@@ -191,40 +227,32 @@ Bool_t   AliRawReaderHLT::ReadNextData(UChar_t*& data)
   // this function is the backbone of the ReadNext functions, it gets the
   // whole data block either from the HLT stream or the parent raw reader.
   // Each call of ReadNextData directly jumps to the next data set.
-  Bool_t result=kFALSE;
-  if (fbHaveHLTData&=ReadNextHLTData()) {
-    // all internal data variables set
-    assert(fpData!=NULL);
-    data=const_cast<AliHLTUInt8_t*>(fpData);
-    result=kTRUE;
-  }
-  if (!result) {
-    // no data in the HLT stream, read real data
-    //AliInfo(Form("read from parent reader: min=%d max=%d", fSelectMinEquipmentId, fSelectMaxEquipmentId));
-
-    // first set the selection back to the original one
-    fpParentReader->SelectEquipment(fSelectEquipmentType, fSelectMinEquipmentId, fSelectMaxEquipmentId);
-
-    // read data
-    while (result=fpParentReader->ReadNextData(data)) {
-      // continue if the Equipment Id is supposed to be replaced by the HLT stream
-      // in that case we do not want to read it from the parent raw reader
-      if (!IsHLTInput(fpParentReader->GetEquipmentId())) break;
-    }
-
-    // set the header of this reader from the parent reader.
-    // This is necessary because of a few base class methods working directly
-    // on the header
-    fHeader=const_cast<AliRawDataHeader*>(fpParentReader->GetDataHeader());
-    if (result) {
-      fpData=data;
-      fDataSize=fpParentReader->GetDataSize();
+  Bool_t result=kTRUE;
+
+  // read new header if data already read
+  if (fPosition<fDataSize || (result=ReadHeader())) {
+    if (fbHaveHLTData && fpHLTOUT!=NULL) {
+      // all internal data variables set
+      result=kTRUE;
+      data=const_cast<AliHLTUInt8_t*>(fpData+sizeof(AliRawDataHeader));
     } else {
-      fpData=NULL;
-      fDataSize=0;
+      // no data in the HLT stream, read real data
+      //AliInfo(Form("read from parent reader: min=%d max=%d", fSelectMinEquipmentId, fSelectMaxEquipmentId));
+
+      // read data
+      result=fpParentReader->ReadNextData(data);
+      if (result) {
+       fpData=data;
+       fDataSize=fpParentReader->GetDataSize();
+      } else {
+       fpData=NULL;
+       fDataSize=0;
+      }
+
+      fEquipmentId=-1;
     }
-    fOffset=0;
-    fEquipmentId=-1;
+    fOffset=sizeof(AliRawDataHeader);
+    fPosition=fDataSize;
   }
   return result;
 }
@@ -294,29 +322,25 @@ Bool_t   AliRawReaderHLT::ReadNext(UChar_t* data, Int_t size)
 Bool_t   AliRawReaderHLT::Reset()
 {
   // see header file for class documentation
+  ReleaseHLTData(false/* keep HLTOUT instance */);
   Bool_t result=fpParentReader->Reset();
-  fpData=NULL;
-  fDataSize=0;
-  fOffset=0;
   fEquipmentId=-1;
-  if (fbHaveHLTData=(fDetectors.size()>0)) {
-    vector<int>::iterator detector=fDetectors.begin();
-    for (; detector!=fDetectors.end(); detector++) {
-      int ddlOffset=AliDAQ::DdlIDOffset(*detector);
-      int nofDDLs=AliDAQ::NumberOfDdls(*detector);
-      if ((fSelectMinEquipmentId>=0 && fSelectMinEquipmentId>ddlOffset+nofDDLs) ||
-         (fSelectMinEquipmentId>=0 && fSelectMaxEquipmentId<ddlOffset))
-       continue;
-      break;
-    }
-    fbHaveHLTData=detector!=fDetectors.end();
-  }
+
+  // check if redirection is enabled for at least one detector in the selected range
+  fbHaveHLTData=EvaluateSelection();
+
+  // start reading HLTOUT data blocks from the beginning
+  fbReadFirst=true;
+
   return result;
 }
 
 Bool_t   AliRawReaderHLT::NextEvent()
 {
   // see header file for class documentation
+
+  ReleaseHLTData();
+
   Bool_t result=fpParentReader->NextEvent();
   if (result) {
     fEventNumber++;
@@ -338,6 +362,7 @@ void AliRawReaderHLT::Select(Int_t detectorID, Int_t minDDLID, Int_t maxDDLID)
   // see header file for class documentation
   AliRawReader::Select(detectorID, minDDLID, maxDDLID);
   fpParentReader->Select(detectorID, minDDLID, maxDDLID);
+  fbHaveHLTData=EvaluateSelection();
 }
 
 // most likely we do not need this method since the base class directly forwards
@@ -354,8 +379,9 @@ void AliRawReaderHLT::SelectEquipment(Int_t equipmentType, Int_t minEquipmentId,
   // see header file for class documentation
 
   //AliInfo(Form("equipmentType=%d, minEquipmentId=%d, maxEquipmentId=%d", equipmentType, minEquipmentId, maxEquipmentId));
-  AliRawReader::Select(equipmentType, minEquipmentId, maxEquipmentId);
-  fpParentReader->Select(equipmentType, minEquipmentId, maxEquipmentId);
+  AliRawReader::SelectEquipment(equipmentType, minEquipmentId, maxEquipmentId);
+  fpParentReader->SelectEquipment(equipmentType, minEquipmentId, maxEquipmentId);
+  fbHaveHLTData=EvaluateSelection();
 }
 
 void AliRawReaderHLT::SkipInvalid(Bool_t skip)
@@ -394,6 +420,9 @@ int AliRawReaderHLT::ScanOptions(const char* options)
       int detId=AliDAQ::DetectorID(argument.Data());
       if (detId>=0) {
        fDetectors.push_back(detId);
+      } else {
+       if (!fSystemOptions.IsNull()) fSystemOptions+=" ";
+       fSystemOptions+=argument;
       }
     }
     delete pTokens;
@@ -406,33 +435,63 @@ Bool_t   AliRawReaderHLT::ReadNextHLTData()
 {
   // see header file for class documentation
   bool result=kTRUE;
-  if (!fpHLTOUT) {
+  if (fbReadFirst || !fpHLTOUT) {
+    if (!fpHLTOUT) {
     fpHLTOUT=new AliHLTOUTRawReader(fpParentReader);
     if (result=(fpHLTOUT!=NULL)) {
+      AliHLTSystem* pSystem=GetInstance();
+      if (pSystem) {
+       pSystem->ScanOptions(fSystemOptions.Data());
+      }
       if (result=(fpHLTOUT->Init()>=0)) {
-       result=fpHLTOUT->SelectFirstDataBlock(kAliHLTAnyDataType, kAliHLTVoidDataSpec,
-                                             AliHLTModuleAgent::kRawReader)>=0;
       }
     }
-  } else {
-    fpHLTOUT->ReleaseDataBuffer(fpData);
-    if (!(result=fpHLTOUT->SelectNextDataBlock()>=0)) {
-      delete fpHLTOUT;
-      fpHLTOUT=NULL;
     }
+    if (result) {
+      result=fpHLTOUT->SelectFirstDataBlock(kAliHLTAnyDataType, kAliHLTVoidDataSpec,
+                                           AliHLTModuleAgent::kRawReader)>=0;
+    }
+    fbReadFirst=false;
+  } else {
+    // first release the data buffer
+    ReleaseHLTData(false /* keep HLTOUT instance */);
+    result=fpHLTOUT->SelectNextDataBlock()>=0;
   }
   if (result) {
+    AliHLTComponentDataType dt=kAliHLTVoidDataType;
+    AliHLTUInt32_t spec=kAliHLTVoidDataSpec;
+    fpHLTOUT->GetDataBlockDescription(dt, spec);
     AliHLTUInt32_t size=0;
-    result=fpHLTOUT->GetDataBuffer(fpData, size)>=0;
-    fDataSize=(int)size;
-    fEquipmentId=-1;
+    AliHLTOUTHandler* pHandler=fpHLTOUT->GetHandler();
+    if (pHandler) {
+      if (dynamic_cast<AliHLTOUTHandlerEquId*>(pHandler)!=NULL) {
+       AliHLTOUT::AliHLTOUTLockGuard g(fpHLTOUT);
+       fEquipmentId=pHandler->ProcessData(fpHLTOUT);
+       fpData=NULL;
+       fDataSize=pHandler->GetProcessedData(fpData);
+       if (!fpData) {
+         result=fpHLTOUT->GetDataBuffer(fpData, size)>=0;
+         fpDataHandler=NULL;
+         AliDebug(AliLog::kDebug, Form("forward data block from HLTOUT stream to equipment %d", fEquipmentId));
+         fDataSize=(int)size;
+       } else {
+         // remember the current handler in order to properly release the data buffer
+         fpDataHandler=pHandler;
+         AliDebug(AliLog::kDebug, Form("forward decoded data block provided by handler to equipment %d", fEquipmentId));
+       }
+       return kTRUE;
+      } else {
+       AliError(Form("handler is not of type AliHLTOUTHandlerEquId for block %x data type %s spec %#x; data block skipped",
+                     fpHLTOUT->GetDataBlockIndex(), AliHLTComponent::DataType2Text(dt).c_str(), spec));
+      }
+    } else {
+      AliWarning(Form("no data handler found for block %x data type %s spec %#x; data block skipped",
+                     fpHLTOUT->GetDataBlockIndex(), AliHLTComponent::DataType2Text(dt).c_str(), spec));
+    }
   } else {
-    fpData=NULL;
-    fDataSize=0;
-    fOffset=0;
-    fEquipmentId=-1;
+    ReleaseHLTData(false /* keep HLTOUT instance */);
   }
-  return false;
+  return kFALSE;
 }
 
 Bool_t AliRawReaderHLT::IsHLTInput(int ddlid)
@@ -448,6 +507,46 @@ Bool_t AliRawReaderHLT::IsHLTInput(int ddlid)
   return kFALSE;
 }
 
+int AliRawReaderHLT::ReleaseHLTData(bool bReleaseHLTOUT)
+{
+  // see header file for class documentation
+  if (fpHLTOUT) {
+    if (fpDataHandler) fpDataHandler->ReleaseProcessedData(fpData, fDataSize);
+    else fpHLTOUT->ReleaseDataBuffer(fpData);
+    fpDataHandler=NULL;
+    if (bReleaseHLTOUT) {
+      delete fpHLTOUT;
+      fpHLTOUT=NULL;
+    }
+  }
+
+  fpData=NULL;
+  fDataSize=0;
+  fOffset=0;
+  fPosition=0;
+  fEquipmentId=-1;
+
+  return 0;
+}
+
+Bool_t AliRawReaderHLT::EvaluateSelection()
+{
+  // see header file for class documentation
+  Bool_t bHaveHLTData=kFALSE;
+  if (bHaveHLTData=(fDetectors.size()>0)) {
+    vector<int>::iterator detector=fDetectors.begin();
+    for (; detector!=fDetectors.end(); detector++) {
+      int ddlOffset=AliDAQ::DdlIDOffset(*detector);
+      int nofDDLs=AliDAQ::NumberOfDdls(*detector);
+      if ((fSelectMinEquipmentId<0 || fSelectMinEquipmentId<ddlOffset+nofDDLs) &&
+         (fSelectMaxEquipmentId<0 || fSelectMaxEquipmentId>=ddlOffset))
+       break;
+    }
+    bHaveHLTData=detector!=fDetectors.end();
+  }
+  return bHaveHLTData;
+}
+
 AliRawReader* AliRawReaderHLTCreateInstance(AliRawReader* pParentReader, const char* options)
 {
   // see header file for class documentation