2 //**************************************************************************
3 //* This file is property of and copyright by the *
4 //* ALICE Experiment at CERN, All rights reserved. *
6 //* Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no> *
8 //* Permission to use, copy, modify and distribute this software and its *
9 //* documentation strictly for non-commercial purposes is hereby granted *
10 //* without fee, provided that the above copyright notice appears in all *
11 //* copies and that both the copyright notice and this permission notice *
12 //* appear in the supporting documentation. The authors make no claims *
13 //* about the suitability of this software for any purpose. It is *
14 //* provided "as is" without express or implied warranty. *
15 //**************************************************************************
17 /// @file AliHLTTPCDataPublisherComponent.cxx
18 /// @author Matthias Richter
23 #include "AliHLTTPCDataPublisherComponent.h"
24 #include "AliHLTTPCDefinitions.h"
25 #include "AliHLTTPCTransform.h"
26 #include "AliHLTTPCClusterMCData.h"
27 #include "AliHLTTPCDataCompressionDecoder.h"
28 #include "AliHLTPluginBase.h"
29 #include "AliHLTSystem.h"
30 #include "AliHLTOUT.h"
31 #include "AliHLTDAQ.h"
32 #include "AliHLTTemplates.h"
38 ClassImp(AliHLTTPCDataPublisherComponent)
40 AliHLTTPCDataPublisherComponent::AliHLTTPCDataPublisherComponent()
41 : AliHLTRawReaderPublisherComponent()
42 , fMode(kPublisherModeDefault)
43 , fArraySelected(NULL)
50 AliHLTTPCDataPublisherComponent::~AliHLTTPCDataPublisherComponent()
53 if (fpDecoder) delete fpDecoder;
58 const char* AliHLTTPCDataPublisherComponent::GetComponentID()
60 /// inherited from AliHLTComponent: id of the component
61 return "TPCDataPublisher";
64 AliHLTComponent* AliHLTTPCDataPublisherComponent::Spawn()
66 /// inherited from AliHLTComponent: spawn function.
67 return new AliHLTTPCDataPublisherComponent;
70 int AliHLTTPCDataPublisherComponent::GetEvent(const AliHLTComponentEventData& evtData,
71 AliHLTComponentTriggerData& trigData,
72 AliHLTUInt8_t* outputPtr,
74 AliHLTComponentBlockDataList& outputBlocks)
76 /// inherited from AliHLTProcessor: data processing
77 if (!IsDataEvent()) return 0;
81 AliHLTComponentBlockDataList clusterBlocks;
82 AliHLTUInt32_t offset=0;
83 AliHLTUInt32_t capacity=size;
87 if (CheckMode(kPublishClustersAll)) {
88 // set the target buffer only if the clusters should be published
89 fClusters->SetTargetBuffer(outputPtr+offset, capacity-offset);
90 } else if (CheckMode(kRegisterClusterBlocks)) {
91 // data blocks are registered in the container, track model cluster blocks
92 // are unpacked but not stored in order to find the included partitions
95 if (CheckMode(kPublishClustersAll) ||
96 CheckMode(kRegisterClusterBlocks)) {
97 if ((iResult=ReadClusterFromHLTOUT(fClusters))>=0) {
98 if ((iResult=fClusters->GetState())>=0) {
99 if (fClusters->CopyBlockDescriptors(clusterBlocks)>0) {
100 for (AliHLTComponentBlockDataList::const_iterator bd=clusterBlocks.begin();
101 bd!=clusterBlocks.end(); bd++) {
102 if (offset<bd->fOffset+bd->fSize)
103 offset=bd->fOffset+bd->fSize;
106 } else if (iResult==-ENOSPC) {
107 offset=fClusters->GetBlockCount()*sizeof(AliHLTTPCRawClusterData)+
108 fClusters->GetClusterCount()*sizeof(AliHLTTPCRawCluster);
109 iResult=0; // keep going to also accumulate the size for raw data blocks
112 if (iResult==-ENODATA) {
113 // return indicates absence of compressed clusters in HLTOUT
114 // but is not treated as an error further downstream
120 if (offset<=capacity) {
121 size=capacity-offset;
124 // there is clearly not enough space, keep the full buffer to
125 // publish the raw data blocks and determine the size of those
126 // data will be overwritten
130 unsigned firstBlock=outputBlocks.size();
131 iResult=AliHLTRawReaderPublisherComponent::GetEvent(evtData, trigData, outputPtr, size, outputBlocks);
132 if (iResult==-ENOSPC) {
133 // not enough space in the buffer, fMaxSize has been updated by base class
135 } else if (iResult>=0) {
136 if (outputBlocks.size()>firstBlock && CheckMode(kPublishRawFiltered)) {
137 AliInfo(Form("publishing %d DDL(s) for emulation of compressed TPC clusters", outputBlocks.size()-firstBlock));
139 // correct for the shifted buffer which was provided to the
141 for (AliHLTComponentBlockDataList::iterator bd=outputBlocks.begin();
142 bd!=outputBlocks.end(); bd++) {
143 if (firstBlock>0) {firstBlock--; continue;}
150 if (iResult>=0 && capacity<offset && fMaxSize<(int)offset) {
151 // update the size requirement
153 outputBlocks.clear();
159 if (clusterBlocks.size()>0 && !CheckMode(kRegisterClusterBlocks)) {
160 outputBlocks.insert(outputBlocks.begin(), clusterBlocks.begin(), clusterBlocks.end());
167 int AliHLTTPCDataPublisherComponent::ReadClusterFromHLTOUT(AliHLTTPCDataPublisherComponent::AliRawClusterContainer* pContainer)
169 // check the HLTOUT for availability of compressed data blocks
171 AliHLTSystem* pSystem=AliHLTPluginBase::GetInstance();
173 // global system not initialized
176 AliHLTOUT* pHLTOUT=pSystem->RequestHLTOUT();
178 // not HLTOUT, hence not clusters
183 fpDecoder=new AliHLTTPCDataCompressionDecoder;
187 AliError("failed to create decoder instance");
191 AliHLTTPCDataCompressionDecoder& decoder=*fpDecoder;
193 decoder.SetVerbosity(GetVerbosity());
194 decoder.EnableClusterMerger();
196 bool bNextBlock=false;
197 // add cluster id and mc information data blocks
198 for (bNextBlock=(pHLTOUT->SelectFirstDataBlock()>=0);
199 bNextBlock; bNextBlock=(pHLTOUT->SelectNextDataBlock()>=0)) {
200 AliHLTComponentBlockData desc;
201 if ((iResult=pHLTOUT->GetDataBuffer(desc))<0) {
204 if (desc.fDataType==AliHLTTPCDefinitions::AliHLTDataTypeClusterMCInfo()) {
205 // add mc information
206 if ((iResult=decoder.AddClusterMCData(&desc))<0) {
210 if (desc.fDataType==AliHLTTPCDefinitions::RemainingClusterIdsDataType() ||
211 desc.fDataType==AliHLTTPCDefinitions::ClusterIdTracksDataType()) {
213 if ((iResult=decoder.AddClusterIds(&desc))<0) {
219 bool bHavePartitionRawData=false;
220 bool bHavePartitionCompressedData=false;
221 vector<bool> bHavePartitionData(216, false);
225 int nExtractedClusters=0;
226 for (bNextBlock=(pHLTOUT->SelectFirstDataBlock()>=0);
227 bNextBlock; bNextBlock=(pHLTOUT->SelectNextDataBlock()>=0)) {
228 decoder.SetPadShift(0.0);
229 AliHLTComponentBlockData desc;
230 if ((iResult=pHLTOUT->GetDataBuffer(desc))<0) {
233 if (desc.fDataType==AliHLTTPCDefinitions::RawClustersDataType()) {
234 // This is a special handling of data blocks produced with v5-01-Release
235 // The pad shift by 0.5 was not included in the data but was applied in the
236 // unpacking in this class. Changed in r51306, the next tag containing this
237 // change in the online system is v5-01-Rev-07. There are only very few runs
238 // of Sep 2011 with recorded clusters not containing the 0.5 shift
239 // There was also a chenge in the data type of the compressed partition
240 // cluster blocks which helps to identify the blocks which need the pad shift
242 if (desc.fSize<sizeof(AliHLTTPCRawClusterData)) continue;
243 const AliHLTTPCRawClusterData* clusterData = reinterpret_cast<const AliHLTTPCRawClusterData*>(desc.fPtr);
244 if (!clusterData) continue;
245 if (clusterData->fVersion==1) {
246 // compressed clusters without the pad shift
247 // no raw clusters (version==0) have ever been recorded
248 decoder.SetPadShift(0.5);
250 AliHLTUInt8_t slice = AliHLTTPCDefinitions::GetMinSliceNr(desc.fSpecification);
251 AliHLTUInt8_t partition = AliHLTTPCDefinitions::GetMinPatchNr(desc.fSpecification);
252 if (slice!=AliHLTTPCDefinitions::GetMaxSliceNr(desc.fSpecification) ||
253 partition!=AliHLTTPCDefinitions::GetMaxPatchNr(desc.fSpecification)) {
254 AliFatal(Form("inconsistent cluster data: can not handle blocks containing multiple partitions, "
255 "block specification 0x%08x", desc.fSpecification));
257 iResult=decoder.ReadClustersPartition(pContainer->BeginRemainingClusterBlock(0, desc.fSpecification),
258 reinterpret_cast<AliHLTUInt8_t*>(desc.fPtr),
260 desc.fSpecification);
261 if (iResult>=0) nExtractedClusters+=iResult;
263 AliFatal(Form("processing of cluster block 0x%08x failed with error code %d", desc.fSpecification, iResult));
265 unsigned index=slice*AliHLTTPCTransform::GetNumberOfPatches()+partition;
266 if (index>=bHavePartitionData.size()) bHavePartitionData.resize(index, false);
267 if (bHavePartitionData[index]) {
268 AliFatal(Form("inconsistent cluster data: multiple data blocks of identical specification indicate a failure "
269 "in the production of the data. Probably an HLT emulation chain is executed in the reconstruction "
270 "and produces data in addition to HLTOUT. Option 'ignore-hltout' is required in that case; "
271 "block specification 0x%08x", desc.fSpecification));
273 bHavePartitionData[index]=true;
274 if (bHavePartitionCompressedData) {
275 AliFatal(Form("inconsistent cluster data: both compressed and raw cluster blocks present in HLTOUT, indicates a failure "
276 "in the production of the data. Probably an HLT emulation chain is executed in the reconstruction "
277 "and produces data in addition to HLTOUT. Option 'ignore-hltout' is required in that case; "
278 "block specification 0x%08x", desc.fSpecification));
280 bHavePartitionRawData=true;
282 } else if (desc.fDataType==AliHLTTPCDefinitions::RemainingClustersCompressedDataType()) {
283 AliHLTUInt8_t slice = AliHLTTPCDefinitions::GetMinSliceNr(desc.fSpecification);
284 AliHLTUInt8_t partition = AliHLTTPCDefinitions::GetMinPatchNr(desc.fSpecification);
285 if (slice!=AliHLTTPCDefinitions::GetMaxSliceNr(desc.fSpecification) ||
286 partition!=AliHLTTPCDefinitions::GetMaxPatchNr(desc.fSpecification)) {
287 AliFatal(Form("inconsistent cluster data: can not handle blocks containing multiple partitions, "
288 "block specification 0x%08x", desc.fSpecification));
290 iResult=decoder.ReadClustersPartition(pContainer->BeginRemainingClusterBlock(0, desc.fSpecification),
291 reinterpret_cast<AliHLTUInt8_t*>(desc.fPtr),
293 desc.fSpecification);
294 if (iResult>0) nExtractedClusters+=iResult;
295 unsigned index=slice*AliHLTTPCTransform::GetNumberOfPatches()+partition;
296 if (index>=bHavePartitionData.size()) bHavePartitionData.resize(index, false);
297 if (bHavePartitionData[index]) {
298 AliFatal(Form("inconsistent cluster data: multiple data blocks of identical specification indicate a failure "
299 "in the production of the data. Probably an HLT emulation chain is executed in the reconstruction "
300 "and produces data in addition to HLTOUT. Option 'ignore-hltout' is required in that case; "
301 "block specification 0x%08x", desc.fSpecification));
303 bHavePartitionData[index]=true;
304 bHavePartitionData[index]=true;
305 if (bHavePartitionRawData) {
306 AliFatal(Form("inconsistent cluster data: both compressed and raw cluster blocks present in HLTOUT, indicates a failure "
307 "in the production of the data. Probably an HLT emulation chain is executed in the reconstruction "
308 "and produces data in addition to HLTOUT. Option 'ignore-hltout' is required in that case; "
309 "block specification 0x%08x", desc.fSpecification));
311 bHavePartitionCompressedData=true;
313 } else if (desc.fDataType==AliHLTTPCDefinitions::ClusterTracksCompressedDataType()) {
314 iResult=decoder.ReadTrackModelClustersCompressed(pContainer->BeginTrackModelClusterBlock(0),
315 reinterpret_cast<AliHLTUInt8_t*>(desc.fPtr),
317 desc.fSpecification);
322 pSystem->ReleaseHLTOUT(pHLTOUT);
324 if (iResult<0) return iResult;
325 return nExtractedClusters;
328 int AliHLTTPCDataPublisherComponent::DoInit( int argc, const char** argv )
330 /// inherited from AliHLTComponent: component initialisation and argument scan.
333 // component configuration
334 //Stage 1: default initialization.
335 const char* defaultArguments="-detector TPC -datatype 'DDL_RAW ' 'TPC ' -skipempty";
336 if ((iResult = ConfigureFromArgumentString(1, &defaultArguments)) < 0)
339 //Stage 2: OCDB. - disabled
340 //TString cdbPath("HLT/ConfigTPC/");
341 //cdbPath += GetComponentID();
343 //iResult = ConfigureFromCDBTObjString(cdbPath);
347 //Stage 3: command line arguments.
348 if (argc && (iResult = ConfigureFromArgumentString(argc, argv)) < 0)
350 if ((iResult=AliHLTRawReaderPublisherComponent::DoInit(0, NULL))<0)
353 auto_ptr<AliRawClusterContainer> container(new AliRawClusterContainer);
354 if (!container.get()) return -ENOMEM;
356 fClusters=container.release();
361 int AliHLTTPCDataPublisherComponent::DoDeinit()
363 /// inherited from AliHLTComponent: component cleanup
366 if (fpDecoder) delete fpDecoder;
372 int AliHLTTPCDataPublisherComponent::ScanConfigurationArgument(int argc, const char** argv)
374 /// inherited from AliHLTComponent: argument scan
375 if (argc<1) return 0;
378 TString argument=argv[i];
382 if (argument.CompareTo("-publish-raw")==0) {
383 if ((bMissingParam=(++i>=argc))) break;
384 TString parameter=argv[i];
385 if (parameter.CompareTo("all")==0) {
386 fMode|=kPublishRawAll;
388 } else if (parameter.CompareTo("filtered")==0) {
389 fMode|=kPublishRawFiltered;
390 fMode|=kRegisterClusterBlocks;
391 fMode&=~kPublishRawAll;
393 } else if (parameter.CompareTo("off")==0) {
394 fMode&=~(kPublishRawAll|kPublishRawFiltered);
397 HLTError("invalid parameter for argument %s, expecting either 'all', 'filtered', or 'off' instead of %s", argument.Data(), parameter.Data());
402 if (argument.CompareTo("-publish-clusters")==0) {
403 if ((bMissingParam=(++i>=argc))) break;
404 TString parameter=argv[i];
405 if (parameter.CompareTo("all")==0) {
406 fMode|=kPublishClustersAll;
408 } else if (parameter.CompareTo("off")==0) {
409 fMode&=~(kPublishClustersAll);
412 HLTError("invalid parameter for argument %s, expecting either 'all', or 'off' instead of %s", argument.Data(), parameter.Data());
417 } while (0); // using do-while only to have break available
419 return AliHLTRawReaderPublisherComponent::ScanConfigurationArgument(argc, argv);
422 int AliHLTTPCDataPublisherComponent::GetSpecificationFromEquipmentId(int id, AliHLTUInt32_t &specification) const
424 /// inherited from AliHLTRawReaderPublisherComponent: get specification
426 // FIXME: add common functionality to AliHLTDAQ
431 slice = (id - 768) / 2;
433 partition = (id % 4) + 2;
434 slice = (id - 840) / 4;
436 specification=(slice<<24)|(slice<<16)|(partition<<8)|partition;
441 bool AliHLTTPCDataPublisherComponent::IsSelected(int equipmentId) const
443 /// inherited from AliHLTRawReaderPublisherComponent: check if a block is selected or not
444 /// check if a raw data block needs to be published. This is the case if
445 /// there is no corresponding compressed data, i.e. function returns
446 /// only false if the block can be found in the cluster container
447 if (CheckMode(kPublishRawAll))
449 if (!CheckMode(kPublishRawFiltered))
455 int offset=AliHLTDAQ::DdlIDOffset(3);
456 int count=AliHLTDAQ::NumberOfDdls(3);
457 if (offset<0 || count<0)
459 if (equipmentId<offset)
462 if (equipmentId>=count)
464 int slice=equipmentId<72?equipmentId/2:(equipmentId-72)/4;
465 int partition=equipmentId<72?equipmentId%2:((equipmentId-72)%4)+2;
466 AliHLTUInt32_t specification=AliHLTTPCDefinitions::EncodeDataSpecification(slice, slice, partition, partition);
467 for (AliHLTComponentBlockDataList::const_iterator i=fClusters->GetBlockDescriptors().begin();
468 i!=fClusters->GetBlockDescriptors().end(); i++) {
469 if (i->fSpecification==specification)
475 AliHLTTPCDataPublisherComponent::AliRawClusterContainer::AliRawClusterContainer()
478 , fTotalClusterCount(0)
479 , fBlockClusterCount(0)
483 , fCurrentBlock(NULL)
484 , fTrackModelClusters(NULL)
485 , fTrackModelClusterMap()
492 AliHLTTPCDataPublisherComponent::AliRawClusterContainer::~AliRawClusterContainer()
497 int AliHLTTPCDataPublisherComponent::AliRawClusterContainer::SetTargetBuffer(AliHLTUInt8_t* pBuffer, int size)
499 // set/reset the external target buffer
502 fBufferSize=pBuffer?size:0;
506 int AliHLTTPCDataPublisherComponent::AliRawClusterContainer::Sort()
508 // merge track model clusters into partition cluster blocks
510 // TODO: implement merging
511 // decoding of track model clusters needs to be done after all
512 // partition blocks have been decoded. The track model clusters are
513 // then at the end of the target buffer and have to be sorted into the
515 // 1) move track model cluster block by its own size back in buffer
516 // if not enough space, allocate temporary buffer and increase the
517 // size estimator for the next event
518 // 2) fill the index grid
519 // 3) make appropriate gaps between the partition cluster blocks
520 // 4) copy clusters into the partitions and update descriptors
524 int AliHLTTPCDataPublisherComponent::AliRawClusterContainer::CopyBlockDescriptors(AliHLTComponentBlockDataList& target) const
526 // fill block descriptors of extracted partition cluster blocks to target list
527 target.insert(target.begin(), fDescriptors.begin(), fDescriptors.end());
528 return fDescriptors.size();
531 AliHLTTPCDataPublisherComponent::AliRawClusterContainer::iterator& AliHLTTPCDataPublisherComponent::AliRawClusterContainer::BeginPartitionClusterBlock(int count, AliHLTUInt32_t specification)
533 /// iterator of partition clusters block of specification
534 return ClusterIterator(count, AliHLTTPCDefinitions::RemainingClustersCompressedDataType(), specification, fCurrentBlock);
537 AliHLTTPCDataPublisherComponent::AliRawClusterContainer::iterator& AliHLTTPCDataPublisherComponent::AliRawClusterContainer::BeginTrackModelClusterBlock(int count)
539 /// iterator of track model clusters
540 return ClusterIterator(count, AliHLTTPCDefinitions::ClusterTracksCompressedDataType(), 0x23000500, fTrackModelClusters);
543 AliHLTTPCDataPublisherComponent::AliRawClusterContainer::iterator& AliHLTTPCDataPublisherComponent::AliRawClusterContainer::ClusterIterator(int /*count*/, AliHLTComponentDataType dt, AliHLTUInt32_t specification, AliHLTTPCRawClusterData* &pData)
545 /// iterator of partition clusters block of specification
547 fIterator.~iterator();
549 fTrackModelClusters=NULL;
550 fTrackModelClusterMap.clear();
551 fBlockClusterCount=0;
552 AliHLTUInt32_t filled=0;
553 for (AliHLTComponentBlockDataList::const_iterator desc=fDescriptors.begin();
554 desc!=fDescriptors.end(); desc++) {
556 if (desc->fSpecification==specification &&
557 desc->fDataType==dt) {
558 HLTFatal("partition cluster block with data type %s and specification 0x%08x has been already processed",
559 AliHLTComponent::DataType2Text(dt).c_str(), specification);
564 // insert an empty data block which is than updated later
565 AliHLTComponentBlockData bd;
566 AliHLTComponent::FillBlockData(bd);
571 bd.fSpecification=specification;
572 fDescriptors.push_back(bd);
574 // initialize only the header, during filling the cluster count of the header
575 // and the block size will be incremented
576 AliHLTUInt32_t blocksize=sizeof(AliHLTTPCRawClusterData);
577 if (filled+blocksize>(unsigned)fBufferSize || fpBuffer==NULL) {
578 new (&fIterator) iterator;
581 pData=reinterpret_cast<AliHLTTPCRawClusterData*>(fpBuffer+filled);
584 fDescriptors.back().fSize=blocksize;
585 new (&fIterator) iterator(this);
589 AliHLTTPCRawCluster* AliHLTTPCDataPublisherComponent::AliRawClusterContainer::NextCluster(int slice, int partition)
591 /// increment to next cluster
592 fTotalClusterCount++;
593 fBlockClusterCount++;
594 if (!fCurrentBlock && !fTrackModelClusters)
596 if (fDescriptors.size()==0)
598 AliHLTTPCRawClusterData* data=fCurrentBlock?fCurrentBlock:fTrackModelClusters;
599 if (int(fDescriptors.back().fOffset+fDescriptors.back().fSize+sizeof(AliHLTTPCRawCluster))>=fBufferSize) {
604 fDescriptors.back().fSize+=sizeof(AliHLTTPCRawCluster);
605 if (fTrackModelClusters)
606 fTrackModelClusterMap.push_back(AliHLTTPCSpacePointData::GetID(slice, partition, fBlockClusterCount));
607 return data->fClusters+(data->fCount-1);
610 void AliHLTTPCDataPublisherComponent::AliRawClusterContainer::Clear(Option_t * /*option*/)
614 fTotalClusterCount=0;
615 fBlockClusterCount=0;
619 fTrackModelClusters=NULL;
620 fTrackModelClusterMap.clear();
621 fDescriptors.clear();
625 void AliHLTTPCDataPublisherComponent::AliRawClusterContainer::Print(Option_t */*option*/) const
630 AliHLTTPCDataPublisherComponent::AliRawClusterContainer::iterator& AliHLTTPCDataPublisherComponent::AliRawClusterContainer::iterator::Next(int slice, int partition)
632 // increment iterator
634 fCluster=fContainer->NextCluster(slice, partition);
635 if (fCluster) memset(fCluster, 0, sizeof(AliHLTTPCRawCluster));