3 ///**************************************************************************
4 ///* This file is property of and copyright by the *
5 ///* ALICE Experiment at CERN, All rights reserved. *
7 ///* Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no> *
9 ///* Permission to use, copy, modify and distribute this software and its *
10 ///* documentation strictly for non-commercial purposes is hereby granted *
11 ///* without fee, provided that the above copyright notice appears in all *
12 ///* copies and that both the copyright notice and this permission notice *
13 ///* appear in the supporting documentation. The authors make no claims *
14 ///* about the suitability of this software for any purpose. It is *
15 ///* provided "as is" without express or implied warranty. *
16 ///**************************************************************************/
18 /// @file AliHLTRawReaderPublisherComponent.cxx
19 /// @author Matthias Richter
21 /// @brief Publisher component for raw data blocks through the AliRawReader
22 /// of the offline environment
24 #include "AliHLTRawReaderPublisherComponent.h"
25 #include "AliRawReader.h"
28 #include "AliHLTCDHWrapper.h"
33 /** ROOT macro for the implementation of ROOT specific class methods */
34 ClassImp(AliHLTRawReaderPublisherComponent)
36 AliHLTRawReaderPublisherComponent::AliHLTRawReaderPublisherComponent()
43 fDataType(kAliHLTVoidDataType),
44 fSpecification(kAliHLTVoidDataSpec),
50 AliHLTRawReaderPublisherComponent::~AliHLTRawReaderPublisherComponent()
55 const char* AliHLTRawReaderPublisherComponent::GetComponentID()
57 /// inherited from AliHLTComponent: id of the component
58 return "AliRawReaderPublisher";
61 AliHLTComponentDataType AliHLTRawReaderPublisherComponent::GetOutputDataType()
63 /// inherited from AliHLTComponent: output data type of the component.
67 void AliHLTRawReaderPublisherComponent::GetOutputDataSize( unsigned long& constBase, double& inputMultiplier )
69 /// inherited from AliHLTComponent: output data size estimator
74 AliHLTComponent* AliHLTRawReaderPublisherComponent::Spawn()
76 /// inherited from AliHLTComponent: spawn function.
77 return new AliHLTRawReaderPublisherComponent;
80 int AliHLTRawReaderPublisherComponent::DoInit( int argc, const char** argv )
82 /// inherited from AliHLTComponent: component initialisation and argument scan.
86 if (argc && (iResult = ConfigureFromArgumentString(argc, argv)) < 0)
89 if (!fDetector.IsNull()) {
92 if ((ddloffset=AliDAQ::DdlIDOffset(fDetector))<0 ||
93 (ddlcount=AliDAQ::NumberOfDdls(fDetector))<0) {
96 if (fMinEquId<0) fMinEquId=ddloffset;
97 else fMinEquId+=ddloffset;
99 if (fMaxEquId<0 || fMaxEquId>ddlcount) fMaxEquId=ddloffset+ddlcount-1;
100 else fMaxEquId+=ddloffset;
103 if (fMinEquId>fMaxEquId) fMaxEquId=fMinEquId;
106 AliErrorStream() << "equipment id required, use \'-equipmentid\' or \'-detector\' option" << endl;
110 AliHLTUInt32_t dummy;
111 if (fMinEquId!=fMaxEquId && GetSpecificationFromEquipmentId(0, dummy)==-ENOSYS) {
112 AliWarningStream() << "publication of multiple equipment ids needs implementation of a child and function GetSpecificationFromEquipmentId to set correct specifications" << endl;
116 if (GetRawReader()!=NULL) {
118 AliErrorStream() << "RawReader instance needed" << endl;
125 int AliHLTRawReaderPublisherComponent::DoDeinit()
127 /// inherited from AliHLTComponent: component cleanup
132 int AliHLTRawReaderPublisherComponent::ScanConfigurationArgument(int argc, const char** argv)
134 /// inherited from AliHLTComponent: argument scan
135 if (argc<1) return 0;
138 TString argument=argv[i];
142 if (argument.CompareTo("-detector")==0) {
143 if ((bMissingParam=(++i>=argc))) break;
147 // -equipmentid, -minid
148 } else if (argument.CompareTo("-equipmentid")==0 ||
149 argument.CompareTo("-minid")==0) {
150 if ((bMissingParam=(++i>=argc))) break;
151 TString parameter(argv[i]);
152 parameter.Remove(TString::kLeading, ' '); // remove all blanks
153 if (parameter.IsDigit()) {
154 fMinEquId=(AliHLTUInt32_t)parameter.Atoi();
157 HLTError("wrong parameter for argument %s, number expected", argument.Data());
162 } else if (argument.CompareTo("-maxid")==0) {
163 if ((bMissingParam=(++i>=argc))) break;
164 TString parameter(argv[i]);
165 parameter.Remove(TString::kLeading, ' '); // remove all blanks
166 if (parameter.IsDigit()) {
167 fMaxEquId=(AliHLTUInt32_t)parameter.Atoi();
170 HLTError("wrong parameter for argument %s, number expected", argument.Data());
175 } else if (argument.CompareTo("-verbose")==0) {
180 } else if (argument.CompareTo("-silent")==0) {
185 } else if (argument.CompareTo("-skipempty")==0) {
190 } else if (argument.CompareTo("-datatype")==0) {
191 if ((bMissingParam=(++i>=argc))) break;
192 memcpy(&fDataType.fID, argv[i], TMath::Min(kAliHLTComponentDataTypefIDsize, (Int_t)strlen(argv[i])));
193 if ((bMissingParam=(++i>=argc))) break;
194 memcpy(&fDataType.fOrigin, argv[i], TMath::Min(kAliHLTComponentDataTypefOriginSize, (Int_t)strlen(argv[i])));
198 } else if (argument.CompareTo("-dataspec")==0) {
199 if ((bMissingParam=(++i>=argc))) break;
200 TString parameter(argv[i]);
201 parameter.Remove(TString::kLeading, ' '); // remove all blanks
202 if (parameter.IsDigit()) {
203 fSpecification=(AliHLTUInt32_t)parameter.Atoi();
204 } else if (parameter.BeginsWith("0x") &&
205 parameter.Replace(0,2,"",0).IsHex()) {
206 sscanf(parameter.Data(),"%x", &fSpecification);
208 HLTError("wrong parameter for argument %s, number expected", argument.Data());
213 } while (0); // using do-while only to have break available
215 HLTError("missing parameter for argument %s", argument.Data());
222 int AliHLTRawReaderPublisherComponent::GetEvent(const AliHLTComponentEventData& /*evtData*/,
223 AliHLTComponentTriggerData& /*trigData*/,
224 AliHLTUInt8_t* outputPtr,
225 AliHLTUInt32_t& size,
226 vector<AliHLTComponentBlockData>& outputBlocks)
228 /// inherited from AliHLTDataSource: get the event
230 AliHLTUInt32_t capacity=size;
233 // process data events only
234 if (!IsDataEvent()) return 0;
236 unsigned int offset=0;
237 assert(outputPtr!=NULL || size==0);
238 AliRawReader* pRawReader=GetRawReader();
241 pRawReader->SelectEquipment(-1, fMinEquId, fMaxEquId);
243 AliInfo(Form("get event from RawReader %p equipment id range [%d,%d]", pRawReader, fMinEquId, fMaxEquId));
245 AliDebug(0, Form("get event from RawReader %p equipment id range [%d,%d]", pRawReader, fMinEquId, fMaxEquId));
247 list<int> processedIds;
248 UChar_t headerVersion=0;
249 while (pRawReader->ReadHeader() && (iResult>=0 || iResult==-ENOSPC)) {
250 const AliRawDataHeader* pHeaderV2=pRawReader->GetDataHeader();
251 const AliRawDataHeaderV3* pHeaderV3=pRawReader->GetDataHeaderV3();
252 AliHLTCDHWrapper pHeader;
255 } else if (pHeaderV3) {
258 HLTError("can not get data header from RawReader, skipping data block ...");
261 // store header version for empty blocks later on
262 // any found header will suffice
263 headerVersion=pHeader.GetVersion();
264 unsigned int headerSize=pHeader.GetHeaderSize();
265 unsigned int readSize=pRawReader->GetDataSize()+headerSize;
266 int id=pRawReader->GetEquipmentId();
267 if (fMinEquId>id || fMaxEquId<id) {
268 AliError(Form("id %d returned from RawReader is outside range [%d,%d]", id, fMinEquId, fMaxEquId));
271 processedIds.push_back(id);
272 bool isSelected=IsSelected(id);
274 AliInfo(Form("got header for id %d, size %d, %s", id, readSize, isSelected?"selected":"discarded"));
276 AliDebug(0, Form("got header for id %d, size %d", id, readSize));
278 if (!isSelected) continue;
279 if (readSize+offset<=capacity) {
280 memcpy(outputPtr+offset, pHeader.GetHeader(), headerSize);
281 if (readSize>headerSize) {
282 if (!pRawReader->ReadNext(outputPtr+offset+headerSize, readSize-headerSize)) {
283 AliError(Form("error reading %d bytes from RawReader %p", readSize-headerSize, pRawReader));
288 AliHLTComponentBlockData bd;
292 bd.fDataType = fDataType;
293 if (fSpecification == kAliHLTVoidDataSpec) {
294 GetSpecificationFromEquipmentId(id, bd.fSpecification);
296 bd.fSpecification=fSpecification;
298 outputBlocks.push_back( bd );
300 // we keep the loop going in order to collect the full size
301 fMaxSize=offset+readSize;
306 if (!fSkipEmpty && processedIds.size()!=size_t(fMaxEquId-fMinEquId+1)) {
307 // add further empty data blocks
308 AliHLTCDHWrapper header;
309 AliRawDataHeader headerV2;
310 AliRawDataHeaderV3 headerV3;
311 if(headerVersion==2){
312 headerV2.fSize=sizeof(AliRawDataHeader);
313 const UInt_t* triggermask=pRawReader->GetTriggerPattern();
315 headerV2.fTriggerClassLow=triggermask[0];
316 headerV2.fROILowTriggerClassHigh=triggermask[1];
319 } else { //assuming V3 even if no header at all was found above
321 AliWarning("No data header found! Creating dummy header for empty blocks assuming CDH v3.");
323 headerV3.fSize=sizeof(AliRawDataHeaderV3);
324 const UInt_t* triggermask=pRawReader->GetTriggerPattern();
326 headerV3.fTriggerClassLow=triggermask[0];
327 headerV3.fTriggerClassesMiddleLow=triggermask[1] & 0x3FFFF;
328 headerV3.fTriggerClassesMiddleHigh= (triggermask[1]>>18) | (triggermask[2]<<14);
329 headerV3.fROILowTriggerClassHigh=(triggermask[2]>>18) | (triggermask[3]<<14);
333 unsigned int headerSize=header.GetHeaderSize();
335 list<int>::iterator curr=processedIds.begin();
336 for (int id=fMinEquId; id<=fMaxEquId; id++) {
337 if (curr!=processedIds.end() && *curr<=id) {
340 if (headerSize<=capacity-offset) {
341 HLTInfo("add empty data block for equipment id %d", id);
342 memcpy(outputPtr+offset, header.GetHeader(), headerSize);
343 AliHLTComponentBlockData bd;
346 bd.fSize = headerSize;
347 bd.fDataType = fDataType;
348 if (fSpecification == kAliHLTVoidDataSpec) {
349 GetSpecificationFromEquipmentId(id, bd.fSpecification);
351 bd.fSpecification=fSpecification;
353 outputBlocks.push_back( bd );
355 // we keep the loop going in order to collect the full size
356 fMaxSize=offset+headerSize;
363 if (offset<=capacity) {
366 outputBlocks.clear();
369 AliErrorStream() << "RawReader uninitialized" << endl;
375 int AliHLTRawReaderPublisherComponent::GetSpecificationFromEquipmentId(int id, AliHLTUInt32_t& specification) const {
376 /// get the data specification from the equipment id
377 /// default method just returns the equipment id
378 return specification=id;