extending component to be the generic TPC data publisher for raw data and compressed...
authorrichterm <richterm@f7af4fe6-9843-0410-8265-dc069ae4e863>
Thu, 16 Feb 2012 20:41:02 +0000 (20:41 +0000)
committerrichterm <richterm@f7af4fe6-9843-0410-8265-dc069ae4e863>
Thu, 16 Feb 2012 20:41:02 +0000 (20:41 +0000)
HLT/TPCLib/AliHLTTPCRawReaderPublisherComponent.cxx
HLT/TPCLib/AliHLTTPCRawReaderPublisherComponent.h

index c5ad3be..fba2547 100644 (file)
@@ -1,10 +1,9 @@
 // $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>        *
-//*                  for The ALICE HLT Project.                            *
 //*                                                                        *
 //* Permission to use, copy, modify and distribute this software and its   *
 //* documentation strictly for non-commercial purposes is hereby granted   *
 
 #include "AliHLTTPCRawReaderPublisherComponent.h"
 #include "AliHLTTPCDefinitions.h"
+#include "AliHLTTPCTransform.h"
+#include "AliHLTTPCClusterMCData.h"
+#include "AliHLTTPCDataCompressionDecoder.h"
 #include "AliHLTPluginBase.h"
 #include "AliHLTSystem.h"
 #include "AliHLTOUT.h"
+#include "AliHLTDAQ.h"
+#include "AliHLTTemplates.h"
 #include "AliLog.h"
 #include <vector>
+#include <memory>
+#include <algorithm>
 
 ClassImp(AliHLTTPCRawReaderPublisherComponent)
 
 AliHLTTPCRawReaderPublisherComponent::AliHLTTPCRawReaderPublisherComponent()
   : AliHLTRawReaderPublisherComponent()
   , fArraySelected(NULL)
+  , fClusters(NULL)
+  , fpDecoder(NULL)
 {
+  /// constructor
 }
 
 AliHLTTPCRawReaderPublisherComponent::~AliHLTTPCRawReaderPublisherComponent()
 {
   /// destructor
+  if (fpDecoder) delete fpDecoder;
+  fpDecoder=NULL;
 }
 
 
 const char* AliHLTTPCRawReaderPublisherComponent::GetComponentID()
 {
   /// inherited from AliHLTComponent: id of the component
-  return "TPCRawReaderPublisher";
+  return "TPCDataPublisher";
 }
 
 AliHLTComponent* AliHLTTPCRawReaderPublisherComponent::Spawn()
@@ -59,18 +70,86 @@ int AliHLTTPCRawReaderPublisherComponent::GetEvent(const AliHLTComponentEventDat
                                                   AliHLTComponentTriggerData& trigData, 
                                                   AliHLTUInt8_t* outputPtr, 
                                                   AliHLTUInt32_t& size, 
-                                                  vector<AliHLTComponentBlockData>& outputBlocks)
+                                                  AliHLTComponentBlockDataList& outputBlocks)
 {
   /// inherited from AliHLTProcessor: data processing
   if (!IsDataEvent()) return 0;
 
+  int iResult=0;
 
-  return AliHLTRawReaderPublisherComponent::GetEvent(evtData, trigData, outputPtr, size, outputBlocks);
+  AliHLTComponentBlockDataList clusterBlocks;
+  AliHLTUInt32_t offset=0;
+  AliHLTUInt32_t capacity=size;
+  size=0;
+  if (fClusters) {
+    fClusters->Clear();
+    fClusters->SetTargetBuffer(outputPtr+offset, capacity-offset);
+    if ((iResult=ReadClusterFromHLTOUT(fClusters))>=0) {
+      if ((iResult=fClusters->GetState())>=0) {
+       if (fClusters->CopyBlockDescriptors(clusterBlocks)>0) {
+         for (AliHLTComponentBlockDataList::const_iterator bd=clusterBlocks.begin();
+              bd!=clusterBlocks.end(); bd++) {
+           if (offset<bd->fOffset+bd->fSize)
+             offset=bd->fOffset+bd->fSize;
+         }
+       }
+      } else if (iResult==-ENOSPC) {
+       offset=fClusters->GetBlockCount()*sizeof(AliHLTTPCRawClusterData)+
+         fClusters->GetClusterCount()*sizeof(AliHLTTPCRawCluster);
+       iResult=0; // keep going to also accumulate the size for raw data blocks
+      }
+    }
+    if (iResult==-ENODATA) {
+      // return indicates absense of compressed clusters in HLTOUT
+      // but is not treated as an error further downstream
+      iResult=0;
+    }
+  }
+
+  if (offset<=capacity) {
+    size=capacity-offset;
+    outputPtr+=offset;
+  } else {
+    // there is clearly not enough space, keep the full buffer to
+    // publish the raw data blocks and determine the size of those
+    // data will be overwritten
+    size=capacity;
+  }
+  if (iResult>=0) {
+    iResult=AliHLTRawReaderPublisherComponent::GetEvent(evtData, trigData, outputPtr, size, outputBlocks);
+    if (iResult==-ENOSPC) {
+      // not enough space in the buffer, fMaxSize has been updated by base class
+      fMaxSize+=offset;
+    } else if (iResult>=0) {
+      // correct for the shifted buffer which was provided to the
+      // GetEvent method
+      for (AliHLTComponentBlockDataList::iterator bd=outputBlocks.begin();
+          bd!=outputBlocks.end(); bd++) {
+       bd->fOffset+=offset;
+      }
+      offset+=size;
+    }
+  }
+
+  if (iResult>=0 && capacity<offset && fMaxSize<(int)offset) {
+    // update the size requirement
+    fMaxSize=offset;
+    outputBlocks.clear();
+    iResult=-ENOSPC;
+  }
+
+  if (iResult>=0) {
+    size=offset;
+    outputBlocks.insert(outputBlocks.begin(), clusterBlocks.begin(), clusterBlocks.end());
+  }
+
+  return iResult;
 }
 
-int AliHLTTPCRawReaderPublisherComponent::InitMapFromHLTOUT(std::map<AliHLTUInt32_t, bool>& hltoutmap)
+int AliHLTTPCRawReaderPublisherComponent::ReadClusterFromHLTOUT(AliHLTTPCRawReaderPublisherComponent::AliRawClusterContainer* pContainer)
 {
   // check the HLTOUT for availability of compressed data blocks
+  int iResult=0;
   AliHLTSystem* pSystem=AliHLTPluginBase::GetInstance();
   if (!pSystem) {
     // global system not initialized
@@ -82,31 +161,150 @@ int AliHLTTPCRawReaderPublisherComponent::InitMapFromHLTOUT(std::map<AliHLTUInt3
     return 0;
   }
 
-  for (bool bNextBlock=(pHLTOUT->SelectFirstDataBlock(AliHLTTPCDefinitions::RemainingClustersCompressedDataType())>=0);
+  if (!fpDecoder) {
+    fpDecoder=new AliHLTTPCDataCompressionDecoder;
+  }
+
+  if (!fpDecoder) {
+    AliError("failed to create decoder instance");
+    return -ENODEV;
+  }
+
+  AliHLTTPCDataCompressionDecoder& decoder=*fpDecoder;
+  decoder.Clear();
+  decoder.SetVerbosity(GetVerbosity());
+  decoder.EnableClusterMerger();
+
+  bool bNextBlock=false;
+  // add cluster id and mc information data blocks
+  for (bNextBlock=(pHLTOUT->SelectFirstDataBlock()>=0);
        bNextBlock; bNextBlock=(pHLTOUT->SelectNextDataBlock()>=0)) {
-    AliHLTComponentDataType dt=kAliHLTVoidDataType;
-    AliHLTUInt32_t spec=kAliHLTVoidDataSpec;
-    if (pHLTOUT->GetDataBlockDescription(dt, spec)<0)
+    AliHLTComponentBlockData desc;
+    if ((iResult=pHLTOUT->GetDataBuffer(desc))<0) {
       continue;
-
-    hltoutmap[spec]=true;
+    }
+    if (desc.fDataType==AliHLTTPCDefinitions::AliHLTDataTypeClusterMCInfo()) {
+      // add mc information
+      if ((iResult=decoder.AddClusterMCData(&desc))<0) {
+       return iResult;
+      }
+    }
+    if (desc.fDataType==AliHLTTPCDefinitions::RemainingClusterIdsDataType() ||
+       desc.fDataType==AliHLTTPCDefinitions::ClusterIdTracksDataType()) {
+      // add cluster ids
+      if ((iResult=decoder.AddClusterIds(&desc))<0) {
+       return iResult;
+      }
+    }
   }
 
-  for (bool bNextBlock=(pHLTOUT->SelectFirstDataBlock(AliHLTTPCDefinitions::ClusterTracksCompressedDataType())>=0);
+  bool bHavePartitionRawData=false;
+  bool bHavePartitionCompressedData=false;
+  vector<bool> bHavePartitionData(216, false);
+
+  // read data
+  iResult=-ENODATA;
+  int nExtractedClusters=0;
+  for (bNextBlock=(pHLTOUT->SelectFirstDataBlock()>=0);
        bNextBlock; bNextBlock=(pHLTOUT->SelectNextDataBlock()>=0)) {
-    // the first version of this component will not implement support for track model compression data blocks
-    // to implement it
-    // - decode data
-    // - sort into index grid
-    // - check if there is at least one cluster in a partition, that is a sufficient condition
-    //   to decide whether a partition was included or not
-    // The best would be to implement a class which supports the AliHLTTPCDataCompressionDecoder
-    // interface and stores unpacked data in AliHLTTPCRawCluster format and fills the index
-    // grid at the same time
-    AliFatalClass("this functionality needs to be implemented");
+    decoder.SetPadShift(0.0);
+    AliHLTComponentBlockData desc;
+    if ((iResult=pHLTOUT->GetDataBuffer(desc))<0) {
+      continue;
+    }
+    if (desc.fDataType==AliHLTTPCDefinitions::RawClustersDataType()) {
+      // This is a special handling of data blocks produced with v5-01-Release
+      // The pad shift by 0.5 was not included in the data but was applied in the
+      // unpacking in this class. Changed in r51306, the next tag containing this
+      // change in the online system is v5-01-Rev-07. There are only very few runs
+      // of Sep 2011 with recorded clusters not containing the 0.5 shift
+      // There was also a chenge in the data type of the compressed partition
+      // cluster blocks which helps to identify the blocks which need the pad shift
+      // here
+      if (desc.fSize<sizeof(AliHLTTPCRawClusterData)) continue;
+      const AliHLTTPCRawClusterData* clusterData = reinterpret_cast<const AliHLTTPCRawClusterData*>(desc.fPtr);
+      if (!clusterData) continue;
+      if (clusterData->fVersion==1) {
+       // compressed clusters without the pad shift
+       // no raw clusters (version==0) have ever been recorded
+       decoder.SetPadShift(0.5);
+      }
+      AliHLTUInt8_t slice = AliHLTTPCDefinitions::GetMinSliceNr(desc.fSpecification);
+      AliHLTUInt8_t partition = AliHLTTPCDefinitions::GetMinPatchNr(desc.fSpecification);
+      if (slice!=AliHLTTPCDefinitions::GetMaxSliceNr(desc.fSpecification) ||
+         partition!=AliHLTTPCDefinitions::GetMaxPatchNr(desc.fSpecification)) {
+       AliFatal(Form("inconsistent cluster data: can not handle blocks containing multiple partitions, "
+                     "block specification 0x%08x", desc.fSpecification));
+      }
+      iResult=decoder.ReadClustersPartition(pContainer->BeginRemainingClusterBlock(0, desc.fSpecification),
+                                           reinterpret_cast<AliHLTUInt8_t*>(desc.fPtr),
+                                           desc.fSize,
+                                           desc.fSpecification);
+      if (iResult>=0) nExtractedClusters+=iResult;
+      else {
+       AliFatal(Form("processing of cluster block 0x%08x failed with error code %d", desc.fSpecification, iResult));
+      }
+      unsigned index=slice*AliHLTTPCTransform::GetNumberOfPatches()+partition;
+      if (index>=bHavePartitionData.size()) bHavePartitionData.resize(index, false);
+      if (bHavePartitionData[index]) {
+       AliFatal(Form("inconsistent cluster data: multiple data blocks of identical specification indicate a failure "
+                     "in the production of the data. Probably an HLT emulation chain is executed in the reconstruction "
+                     "and produces data in addition to HLTOUT. Option 'ignore-hltout' is required in that case; "
+                     "block specification 0x%08x", desc.fSpecification));
+      }
+      bHavePartitionData[index]=true;
+      if (bHavePartitionCompressedData) {
+       AliFatal(Form("inconsistent cluster data: both compressed and raw cluster blocks present in HLTOUT, indicates a failure "
+                     "in the production of the data. Probably an HLT emulation chain is executed in the reconstruction "
+                     "and produces data in addition to HLTOUT. Option 'ignore-hltout' is required in that case; "
+                     "block specification 0x%08x", desc.fSpecification));
+      }
+      bHavePartitionRawData=true;
+      continue;
+    } else if (desc.fDataType==AliHLTTPCDefinitions::RemainingClustersCompressedDataType()) {
+      AliHLTUInt8_t slice = AliHLTTPCDefinitions::GetMinSliceNr(desc.fSpecification);
+      AliHLTUInt8_t partition = AliHLTTPCDefinitions::GetMinPatchNr(desc.fSpecification);
+      if (slice!=AliHLTTPCDefinitions::GetMaxSliceNr(desc.fSpecification) ||
+         partition!=AliHLTTPCDefinitions::GetMaxPatchNr(desc.fSpecification)) {
+       AliFatal(Form("inconsistent cluster data: can not handle blocks containing multiple partitions, "
+                     "block specification 0x%08x", desc.fSpecification));
+      }
+      iResult=decoder.ReadClustersPartition(pContainer->BeginRemainingClusterBlock(0, desc.fSpecification),
+                                           reinterpret_cast<AliHLTUInt8_t*>(desc.fPtr),
+                                           desc.fSize,
+                                           desc.fSpecification);
+      if (iResult>0) nExtractedClusters+=iResult;
+      unsigned index=slice*AliHLTTPCTransform::GetNumberOfPatches()+partition;
+      if (index>=bHavePartitionData.size()) bHavePartitionData.resize(index, false);
+      if (bHavePartitionData[index]) {
+       AliFatal(Form("inconsistent cluster data: multiple data blocks of identical specification indicate a failure "
+                     "in the production of the data. Probably an HLT emulation chain is executed in the reconstruction "
+                     "and produces data in addition to HLTOUT. Option 'ignore-hltout' is required in that case; "
+                     "block specification 0x%08x", desc.fSpecification));
+      }
+      bHavePartitionData[index]=true;
+      bHavePartitionData[index]=true;
+      if (bHavePartitionRawData) {
+       AliFatal(Form("inconsistent cluster data: both compressed and raw cluster blocks present in HLTOUT, indicates a failure "
+                     "in the production of the data. Probably an HLT emulation chain is executed in the reconstruction "
+                     "and produces data in addition to HLTOUT. Option 'ignore-hltout' is required in that case; "
+                     "block specification 0x%08x", desc.fSpecification));
+      }
+      bHavePartitionCompressedData=true;
+      continue;
+    } else if (desc.fDataType==AliHLTTPCDefinitions::ClusterTracksCompressedDataType()) {
+      iResult=decoder.ReadTrackModelClustersCompressed(pContainer->BeginTrackModelClusterBlock(0),
+                                                       reinterpret_cast<AliHLTUInt8_t*>(desc.fPtr),
+                                                       desc.fSize,
+                                                       desc.fSpecification);
+      continue;
+    }
   }
+
+  pSystem->ReleaseHLTOUT(pHLTOUT);
     
-  return 0;
+  if (iResult<0) return iResult;
+  return nExtractedClusters;
 }
 
 int AliHLTTPCRawReaderPublisherComponent::DoInit( int argc, const char** argv )
@@ -116,7 +314,9 @@ int AliHLTTPCRawReaderPublisherComponent::DoInit( int argc, const char** argv )
 
   // component configuration
   //Stage 1: default initialization.
-  //No default values until now.
+  const char* defaultArguments="-detector TPC -datatype 'DDL_RAW ' 'TPC '";
+  if ((iResult = ConfigureFromArgumentString(1, &defaultArguments)) < 0)
+    return iResult;
 
   //Stage 2: OCDB. - disabled
   //TString cdbPath("HLT/ConfigTPC/");
@@ -129,6 +329,13 @@ int AliHLTTPCRawReaderPublisherComponent::DoInit( int argc, const char** argv )
   //Stage 3: command line arguments.
   if (argc && (iResult = ConfigureFromArgumentString(argc, argv)) < 0)
     return iResult;
+  if ((iResult=AliHLTRawReaderPublisherComponent::DoInit(0, NULL))<0)
+    return iResult;
+
+  auto_ptr<AliRawClusterContainer> container(new AliRawClusterContainer);
+  if (!container.get()) return -ENOMEM;
+
+  fClusters=container.release();
 
   return iResult;
 }
@@ -138,40 +345,26 @@ int AliHLTTPCRawReaderPublisherComponent::DoDeinit()
   /// inherited from AliHLTComponent: component cleanup
   int iResult=0;
 
+  if (fpDecoder) delete fpDecoder;
+  fpDecoder=NULL;
+
   return iResult;
 }
 
 int AliHLTTPCRawReaderPublisherComponent::ScanConfigurationArgument(int argc, const char** argv)
 {
   /// inherited from AliHLTComponent: argument scan
-  int iResult=0;
   if (argc<1) return 0;
-  int bMissingParam=0;
-  int i=0;
-  TString argument=argv[i];
+  // int bMissingParam=0;
+  // int i=0;
+  // TString argument=argv[i];
 
   do {
-    // -mode
-    if (argument.CompareTo("-mode")==0) {
-      if ((bMissingParam=(++i>=argc))) break;
-      TString parameter=argv[i];
-      if (parameter.IsDigit()) {
-
-       return 2;
-      } else {
-       HLTError("invalid parameter for argument %s, expecting number instead of %s", argument.Data(), parameter.Data());
-       return -EPROTO;
-      }
-    }
+    // currently no specific parameters
 
   } while (0); // using do-while only to have break available
 
-  if (bMissingParam) {
-    HLTError("missing parameter for argument %s", argument.Data());
-    iResult=-EPROTO;
-  }
-
-  return iResult;
+  return AliHLTRawReaderPublisherComponent::ScanConfigurationArgument(argc, argv);
 }
 
 int AliHLTTPCRawReaderPublisherComponent::GetSpecificationFromEquipmentId(int id, AliHLTUInt32_t &specification) const
@@ -193,10 +386,194 @@ int AliHLTTPCRawReaderPublisherComponent::GetSpecificationFromEquipmentId(int id
   return 0;
 }
 
-bool AliHLTTPCRawReaderPublisherComponent::IsSelected(int /*equipmentId*/) const
+bool AliHLTTPCRawReaderPublisherComponent::IsSelected(int equipmentId) const
 {
   /// inherited from AliHLTRawReaderPublisherComponent: check if a block is selected or not
+  /// check if a raw data block needs to be published. This is the case if
+  /// there is no corresponding compressed data, i.e. function returns
+  /// only false if the block can be found in the cluster container
+  if (!fClusters)
+    return true;
+
+  int offset=AliHLTDAQ::DdlIDOffset(3);
+  int count=AliHLTDAQ::NumberOfDdls(3);
+  if (offset<0 || count<0)
+    return true;
+  if (equipmentId<offset)
+    return true;
+  equipmentId-=offset;
+  if (equipmentId>=count)
+    return true;
+  int slice=equipmentId<72?equipmentId/2:(equipmentId-72)/4;
+  int partition=equipmentId<72?equipmentId%2:(equipmentId-72)%4;
+  AliHLTUInt32_t specification=AliHLTTPCDefinitions::EncodeDataSpecification(slice, slice, partition, partition);
+  for (AliHLTComponentBlockDataList::const_iterator i=fClusters->GetBlockDescriptors().begin();
+       i!=fClusters->GetBlockDescriptors().end(); i++) {
+    if (i->fSpecification==specification)
+      return false;
+  }
+  return true;
+}
+
+AliHLTTPCRawReaderPublisherComponent::AliRawClusterContainer::AliRawClusterContainer()
+  : AliHLTLogging()
+  , fBlockCount(0)
+  , fTotalClusterCount(0)
+  , fBlockClusterCount(0)
+  , fpBuffer(NULL)
+  , fBufferSize(0)
+  , fDescriptors()
+  , fCurrentBlock(NULL)
+  , fTrackModelClusters(NULL)
+  , fTrackModelClusterMap()
+  , fIterator()
+  , fState(0)
+{
+  // constructor
+}
+
+AliHLTTPCRawReaderPublisherComponent::AliRawClusterContainer::~AliRawClusterContainer()
+{
+  // destructor
+}
+
+int AliHLTTPCRawReaderPublisherComponent::AliRawClusterContainer::SetTargetBuffer(AliHLTUInt8_t* pBuffer, int size)
+{
+  // set/reset the external target buffer
+  Clear();
+  fpBuffer=pBuffer;
+  fBufferSize=pBuffer?size:0;
+  return 0;  
+}
+
+int AliHLTTPCRawReaderPublisherComponent::AliRawClusterContainer::Sort()
+{
+  // merge track model clusters into partition cluster blocks
+
+  // TODO: implement merging
+  // decoding of track model clusters needs to be done after all
+  // partition blocks have been decoded. The track model clusters are
+  // then at the end of the target buffer and have to be sorted into the
+  // other blocks
+  // 1) move track model cluster block by its own size back in buffer
+  //    if not enough space, allocate temporary buffer and increase the
+  //    size estimator for the next event
+  // 2) fill the index grid
+  // 3) make appropriate gaps between the partition cluster blocks
+  // 4) copy clusters into the partitions and update descriptors
+  return -ENOSYS;
+}
+
+int AliHLTTPCRawReaderPublisherComponent::AliRawClusterContainer::CopyBlockDescriptors(AliHLTComponentBlockDataList& target) const
+{
+  // fill block descriptors of extracted partition cluster blocks to target list
+  target.insert(target.begin(), fDescriptors.begin(), fDescriptors.end());
+  return fDescriptors.size();
+}
 
-  // TODO: implement logic
-  return false;
+AliHLTTPCRawReaderPublisherComponent::AliRawClusterContainer::iterator& AliHLTTPCRawReaderPublisherComponent::AliRawClusterContainer::BeginPartitionClusterBlock(int count, AliHLTUInt32_t specification)
+{
+  /// iterator of partition clusters block of specification
+  return ClusterIterator(count, AliHLTTPCDefinitions::RemainingClustersCompressedDataType(), specification, fCurrentBlock);
+}
+
+AliHLTTPCRawReaderPublisherComponent::AliRawClusterContainer::iterator& AliHLTTPCRawReaderPublisherComponent::AliRawClusterContainer::BeginTrackModelClusterBlock(int count)
+{
+  /// iterator of track model clusters
+  return ClusterIterator(count, AliHLTTPCDefinitions::ClusterTracksCompressedDataType(), 0x23000500, fTrackModelClusters);
+}
+
+AliHLTTPCRawReaderPublisherComponent::AliRawClusterContainer::iterator& AliHLTTPCRawReaderPublisherComponent::AliRawClusterContainer::ClusterIterator(int /*count*/, AliHLTComponentDataType dt, AliHLTUInt32_t specification, AliHLTTPCRawClusterData* &pData)
+{
+  /// iterator of partition clusters block of specification
+  fBlockCount++;
+  fIterator.~iterator();
+  fCurrentBlock=NULL;
+  fTrackModelClusters=NULL;
+  fTrackModelClusterMap.clear();
+  fBlockClusterCount=0;
+  AliHLTUInt32_t filled=0;
+  for (AliHLTComponentBlockDataList::const_iterator desc=fDescriptors.begin();
+       desc!=fDescriptors.end(); desc++) {
+    filled+=desc->fSize;
+    if (desc->fSpecification==specification &&
+       desc->fDataType==dt) {
+      HLTFatal("partition cluster block with data type %s and specification 0x%08x has been already processed",
+              AliHLTComponent::DataType2Text(dt).c_str(), specification);
+      filled=fBufferSize;
+    }
+  }
+  // initialize only the header, during filling the cluster count of the header
+  // and the block size will be incremented
+  AliHLTUInt32_t blocksize=sizeof(AliHLTTPCRawClusterData);
+  if (filled+blocksize>(unsigned)fBufferSize || fpBuffer==NULL) {
+    new (&fIterator) iterator;
+    return fIterator;
+  }
+  pData=reinterpret_cast<AliHLTTPCRawClusterData*>(fpBuffer+filled);
+  pData->fVersion=0;
+  pData->fCount=0;
+  AliHLTComponentBlockData bd;
+  AliHLTComponent::FillBlockData(bd);
+  bd.fPtr=NULL;
+  bd.fSize=blocksize;
+  bd.fOffset=filled;
+  bd.fDataType=dt;
+  bd.fSpecification=specification;
+  fDescriptors.push_back(bd);
+  new (&fIterator) iterator(this);
+  return fIterator;
+}
+
+AliHLTTPCRawCluster* AliHLTTPCRawReaderPublisherComponent::AliRawClusterContainer::NextCluster(int slice, int partition)
+{
+  /// increment to next cluster
+  fTotalClusterCount++;
+  fBlockClusterCount++;
+  if (!fCurrentBlock && !fTrackModelClusters)
+    return NULL;
+  if (fDescriptors.size()==0)
+    return NULL;
+  AliHLTTPCRawClusterData* data=fCurrentBlock?fCurrentBlock:fTrackModelClusters;
+  if (int(fDescriptors.back().fOffset+fDescriptors.back().fSize+sizeof(AliHLTTPCRawCluster))>=fBufferSize) {
+    fState=-ENOSPC;
+    return NULL;
+  }
+  data->fCount++;
+  fDescriptors.back().fSize+=sizeof(AliHLTTPCRawCluster);
+  if (fTrackModelClusters)
+    fTrackModelClusterMap.push_back(AliHLTTPCSpacePointData::GetID(slice, partition, fBlockClusterCount));
+  return data->fClusters+(data->fCount-1);
+}
+
+void  AliHLTTPCRawReaderPublisherComponent::AliRawClusterContainer::Clear(Option_t * /*option*/)
+{
+  /// internal cleanup
+  fBlockCount=0;
+  fTotalClusterCount=0;
+  fBlockClusterCount=0;
+  fpBuffer=NULL;
+  fBufferSize=0;
+  fCurrentBlock=NULL;
+  fTrackModelClusters=NULL;
+  fTrackModelClusterMap.clear();
+  fDescriptors.clear();
+  fState=0;
+}
+
+void AliHLTTPCRawReaderPublisherComponent::AliRawClusterContainer::Print(Option_t */*option*/) const
+{
+  /// print info
+}
+
+AliHLTTPCRawReaderPublisherComponent::AliRawClusterContainer::iterator& AliHLTTPCRawReaderPublisherComponent::AliRawClusterContainer::iterator::Next(int slice, int partition)
+{
+  // increment iterator
+  if (fContainer) {
+    fCluster=fContainer->NextCluster(slice, partition);
+    if (fCluster) memset(fCluster, 0, sizeof(AliHLTTPCRawCluster));
+  } else {
+    fCluster=NULL;
+  }
+  return *this;
 }
index c8c7d78..b102a14 100644 (file)
@@ -2,7 +2,7 @@
 // $Id$
 #ifndef ALIHLTTPCRAWREADERPUBLISHERCOMPONENT_H
 #define ALIHLTTPCRAWREADERPUBLISHERCOMPONENT_H
-//* 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.                         *
 //* See cxx source for full Copyright notice                               *
 
 ///         
 
 #include "AliHLTRawReaderPublisherComponent.h"
+#include "AliHLTTPCRawCluster.h"
 #include <map>
 
+class AliHLTTPCClusterMCLabel;
+class AliHLTTPCClusterMCData;
+class AliHLTTPCDataCompressionDecoder;
+
 /**
  * @class AliHLTTPCRawReaderPublisherComponent
  * This component uses the functionality of AliHLTRawReaderPublisherComponent
@@ -66,13 +71,120 @@ public:
   /// inherited from AliHLTComponent: spawn function.
   virtual AliHLTComponent* Spawn();
 
+  /**
+   * @class AliRawClusterContainer
+   * Container of AliHLTTPCRawCluster, The class implements the interface to be
+   * used in the decoding of compressed TPC data.
+   * Data is decoded into an external buffer.
+   */
+  class AliRawClusterContainer : public AliHLTLogging {
+  public:
+    AliRawClusterContainer();
+    virtual ~AliRawClusterContainer();
+
+    /// set/reset the external target buffer
+    int SetTargetBuffer(AliHLTUInt8_t* pBuffer, int size);
+
+    /// merge track model clusters into partition cluster blocks 
+    int Sort();
+
+    /// fill block descriptors of extracted partition cluster blocks to target list
+    int CopyBlockDescriptors(AliHLTComponentBlockDataList& target) const;
+    /// get reference to block descriptor list
+    const AliHLTComponentBlockDataList& GetBlockDescriptors() const {
+      return fDescriptors;
+    }
+
+    struct AliClusterIdBlock {
+      AliClusterIdBlock() : fIds(NULL), fSize(0) {}
+      AliHLTUInt32_t* fIds; //!
+      AliHLTUInt32_t  fSize; //!
+    };
+
+    class iterator {
+    public:
+      iterator() : fClusterNo(-1), fCluster(NULL), fClusterId(kAliHLTVoidDataSpec), fContainer(NULL) {}
+      iterator(AliRawClusterContainer* pContainer) : fClusterNo(-1), fCluster(NULL), fClusterId(kAliHLTVoidDataSpec), fContainer(pContainer) {}
+      iterator(const iterator& other) : fClusterNo(other.fClusterNo), fCluster(other.fCluster), fClusterId(other.fClusterId), fContainer(other.fContainer) {}
+      iterator& operator=(const iterator& other) {
+       if (this==&other) return *this;
+       fClusterNo=other.fClusterNo; fCluster=other.fCluster, fClusterId=other.fClusterId; fContainer=other.fContainer; return *this;
+      }
+      ~iterator() {fCluster=NULL; fContainer=NULL;}
+
+      void SetPadRow(int row)          {if (fCluster) fCluster->SetPadRow(row);}
+      void SetPad(float pad)          {if (fCluster) fCluster->SetPad(pad);}
+      void SetTime(float time)                {if (fCluster) fCluster->SetTime(time);}
+      void SetSigmaY2(float sigmaY2)   {if (fCluster) fCluster->SetSigmaY2(sigmaY2);}
+      void SetSigmaZ2(float sigmaZ2)   {if (fCluster) fCluster->SetSigmaZ2(sigmaZ2);}
+      void SetCharge(unsigned charge)  {if (fCluster) fCluster->SetCharge(charge);}
+      void SetQMax(unsigned qmax)      {if (fCluster) fCluster->SetQMax(qmax);}
+      void SetMC(const AliHLTTPCClusterMCLabel* pMC) {
+       if (!fCluster || !pMC) return;
+      }
+
+      // switch to next cluster
+      iterator& Next(int slice, int partition);
+
+    private:
+      int fClusterNo; //! cluster no in the current block
+      AliHLTTPCRawCluster* fCluster; //! pointer to current cluster
+      AliHLTUInt32_t fClusterId; //! id of the cluster, from optional cluster id blocks
+      AliRawClusterContainer* fContainer; // instance of container
+    };
+
+    /// legacy, to be removed later
+    iterator& BeginRemainingClusterBlock(int count, AliHLTUInt32_t specification) {
+      return BeginPartitionClusterBlock(count, specification);
+    }
+    /// iterator of partition clusters block of specification
+    iterator& BeginPartitionClusterBlock(int count, AliHLTUInt32_t specification);
+    /// iterator of track model clusters
+    iterator& BeginTrackModelClusterBlock(int count);
+    /// base method to start cluster iterator
+    iterator& ClusterIterator(int count, AliHLTComponentDataType dt, AliHLTUInt32_t specification, AliHLTTPCRawClusterData* &pData);
+
+    /// get block count, i.e. number of calls to create an iterator
+    int GetBlockCount() const {return fBlockCount;}
+    /// get number of decoded clusters
+    /// Note: only if there is enough space in the target buffer the clusters
+    //  will be properly written
+    int GetClusterCount() const {return fTotalClusterCount;}
+    /// get the state of the cluster decoding
+    int GetState() const {return fState;}
+
+    /// internal cleanup
+    virtual void  Clear(Option_t * option="");
+    /// print info
+    virtual void Print(Option_t *option=NULL) const;
+
+  protected:
+    AliHLTTPCRawCluster* NextCluster(int slice, int partition);
+
+  private:
+    AliRawClusterContainer(const AliRawClusterContainer&);
+    AliRawClusterContainer& operator=(const AliRawClusterContainer&);
+
+    int fBlockCount; //! number of data blocks with clusters
+    int fTotalClusterCount; //! total number of decoded clusters
+    int fBlockClusterCount; //! number of decoded clusters in current block
+    AliHLTUInt8_t* fpBuffer; //! target buffer for decoded data
+    int fBufferSize; //! size of target buffer
+    AliHLTComponentBlockDataList fDescriptors; //! list of block descriptors
+    AliHLTTPCRawClusterData* fCurrentBlock; // current cluster block
+    AliHLTTPCRawClusterData* fTrackModelClusters; //! track model cluster block
+    vector<AliHLTUInt32_t>   fTrackModelClusterMap; //! slice-partition map for track model clusters
+    iterator fIterator; //! iterator for filling of data
+    int fState; //! state
+  };
+
 protected:
   /// inherited from AliHLTDataSource: get one event
   int GetEvent( const AliHLTComponentEventData& evtData,
                AliHLTComponentTriggerData& trigData,
                AliHLTUInt8_t* outputPtr, 
                AliHLTUInt32_t& size,
-               vector<AliHLTComponentBlockData>& outputBlocks );
+               AliHLTComponentBlockDataList& outputBlocks );
 
   /// inherited from AliHLTComponent: initialize
   int DoInit( int argc, const char** argv );
@@ -83,8 +195,8 @@ protected:
   /// inherited from AliHLTComponent: argument scan
   int ScanConfigurationArgument(int argc, const char** argv);
 
-  /// check the HLTOUT for availability of compressed data blocks
-  int InitMapFromHLTOUT(std::map<AliHLTUInt32_t, bool>& hltoutmap);
+  /// read cluster from HLTOUT
+  int ReadClusterFromHLTOUT(AliRawClusterContainer* pContainer);
 
   /// inherited from AliHLTRawReaderPublisherComponent: get specification
   virtual int GetSpecificationFromEquipmentId(int id, AliHLTUInt32_t &specification) const;
@@ -97,6 +209,8 @@ private:
   AliHLTTPCRawReaderPublisherComponent& operator=(const AliHLTTPCRawReaderPublisherComponent&);
 
   bool* fArraySelected; //! transient
+  AliRawClusterContainer* fClusters; // target for decoded clusters
+  AliHLTTPCDataCompressionDecoder* fpDecoder; // decoder for compressed cluster blocks
 
   ClassDef(AliHLTTPCRawReaderPublisherComponent, 0)
 };