Line data Source code
1 : // $Id$
2 :
3 : ///**************************************************************************
4 : ///* This file is property of and copyright by the *
5 : ///* ALICE Experiment at CERN, All rights reserved. *
6 : ///* *
7 : ///* Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no> *
8 : ///* *
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 : ///**************************************************************************/
17 :
18 : /// @file AliHLTRawReaderPublisherComponent.cxx
19 : /// @author Matthias Richter
20 : /// @date
21 : /// @brief Publisher component for raw data blocks through the AliRawReader
22 : /// of the offline environment
23 :
24 : #include "AliHLTRawReaderPublisherComponent.h"
25 : #include "AliRawReader.h"
26 : #include "AliDAQ.h"
27 : #include "AliLog.h"
28 : #include "AliHLTCDHWrapper.h"
29 : #include <cerrno>
30 : #include <cassert>
31 : #include <list>
32 :
33 : /** ROOT macro for the implementation of ROOT specific class methods */
34 8 : ClassImp(AliHLTRawReaderPublisherComponent)
35 :
36 6 : AliHLTRawReaderPublisherComponent::AliHLTRawReaderPublisherComponent()
37 : :
38 6 : fMaxSize(5000000),
39 6 : fDetector(),
40 6 : fMinEquId(-1),
41 6 : fMaxEquId(-1),
42 6 : fVerbosity(0),
43 6 : fDataType(kAliHLTVoidDataType),
44 6 : fSpecification(kAliHLTVoidDataSpec),
45 6 : fSkipEmpty(kFALSE)
46 24 : {
47 : // constructor
48 9 : }
49 :
50 0 : AliHLTRawReaderPublisherComponent::~AliHLTRawReaderPublisherComponent()
51 24 : {
52 : // destructor
53 12 : }
54 :
55 : const char* AliHLTRawReaderPublisherComponent::GetComponentID()
56 : {
57 : /// inherited from AliHLTComponent: id of the component
58 690 : return "AliRawReaderPublisher";
59 : }
60 :
61 : AliHLTComponentDataType AliHLTRawReaderPublisherComponent::GetOutputDataType()
62 : {
63 : /// inherited from AliHLTComponent: output data type of the component.
64 0 : return fDataType;
65 : }
66 :
67 : void AliHLTRawReaderPublisherComponent::GetOutputDataSize( unsigned long& constBase, double& inputMultiplier )
68 : {
69 : /// inherited from AliHLTComponent: output data size estimator
70 0 : constBase=fMaxSize;
71 0 : inputMultiplier=1;
72 0 : }
73 :
74 : AliHLTComponent* AliHLTRawReaderPublisherComponent::Spawn()
75 : {
76 : /// inherited from AliHLTComponent: spawn function.
77 0 : return new AliHLTRawReaderPublisherComponent;
78 0 : }
79 :
80 : int AliHLTRawReaderPublisherComponent::DoInit( int argc, const char** argv )
81 : {
82 : /// inherited from AliHLTComponent: component initialisation and argument scan.
83 : int iResult=0;
84 :
85 : // scan arguments
86 0 : if (argc && (iResult = ConfigureFromArgumentString(argc, argv)) < 0)
87 0 : return iResult;
88 :
89 0 : if (!fDetector.IsNull()) {
90 : int ddloffset=-1;
91 : int ddlcount=-1;
92 0 : if ((ddloffset=AliDAQ::DdlIDOffset(fDetector))<0 ||
93 0 : (ddlcount=AliDAQ::NumberOfDdls(fDetector))<0) {
94 0 : return -EINVAL;
95 : }
96 0 : if (fMinEquId<0) fMinEquId=ddloffset;
97 0 : else fMinEquId+=ddloffset;
98 :
99 0 : if (fMaxEquId<0 || fMaxEquId>ddlcount) fMaxEquId=ddloffset+ddlcount-1;
100 0 : else fMaxEquId+=ddloffset;
101 0 : }
102 :
103 0 : if (fMinEquId>fMaxEquId) fMaxEquId=fMinEquId;
104 :
105 0 : if (fMinEquId<0) {
106 0 : AliErrorStream() << "equipment id required, use \'-equipmentid\' or \'-detector\' option" << endl;
107 0 : return -EINVAL;
108 : }
109 :
110 0 : AliHLTUInt32_t dummy;
111 0 : if (fMinEquId!=fMaxEquId && GetSpecificationFromEquipmentId(0, dummy)==-ENOSYS) {
112 0 : AliWarningStream() << "publication of multiple equipment ids needs implementation of a child and function GetSpecificationFromEquipmentId to set correct specifications" << endl;
113 : //return -EINVAL;
114 0 : }
115 :
116 0 : if (GetRawReader()!=NULL) {
117 : } else {
118 0 : AliErrorStream() << "RawReader instance needed" << endl;
119 0 : return -EINVAL;
120 : }
121 :
122 0 : return iResult;
123 0 : }
124 :
125 : int AliHLTRawReaderPublisherComponent::DoDeinit()
126 : {
127 : /// inherited from AliHLTComponent: component cleanup
128 : int iResult=0;
129 0 : return iResult;
130 : }
131 :
132 : int AliHLTRawReaderPublisherComponent::ScanConfigurationArgument(int argc, const char** argv)
133 : {
134 : /// inherited from AliHLTComponent: argument scan
135 0 : if (argc<1) return 0;
136 : int bMissingParam=0;
137 : int i=0;
138 0 : TString argument=argv[i];
139 :
140 : do {
141 : // -detector
142 0 : if (argument.CompareTo("-detector")==0) {
143 0 : if ((bMissingParam=(++i>=argc))) break;
144 0 : fDetector=argv[i];
145 0 : return 2;
146 :
147 : // -equipmentid, -minid
148 0 : } else if (argument.CompareTo("-equipmentid")==0 ||
149 0 : argument.CompareTo("-minid")==0) {
150 0 : if ((bMissingParam=(++i>=argc))) break;
151 0 : TString parameter(argv[i]);
152 0 : parameter.Remove(TString::kLeading, ' '); // remove all blanks
153 0 : if (parameter.IsDigit()) {
154 0 : fMinEquId=(AliHLTUInt32_t)parameter.Atoi();
155 0 : return 2;
156 : } else {
157 0 : HLTError("wrong parameter for argument %s, number expected", argument.Data());
158 0 : return -EINVAL;
159 : }
160 :
161 : // -maxid
162 0 : } else if (argument.CompareTo("-maxid")==0) {
163 0 : if ((bMissingParam=(++i>=argc))) break;
164 0 : TString parameter(argv[i]);
165 0 : parameter.Remove(TString::kLeading, ' '); // remove all blanks
166 0 : if (parameter.IsDigit()) {
167 0 : fMaxEquId=(AliHLTUInt32_t)parameter.Atoi();
168 0 : return 2;
169 : } else {
170 0 : HLTError("wrong parameter for argument %s, number expected", argument.Data());
171 0 : return -EINVAL;
172 : }
173 :
174 : // -verbose
175 0 : } else if (argument.CompareTo("-verbose")==0) {
176 0 : fVerbosity++;
177 0 : return 1;
178 :
179 : // -silent
180 0 : } else if (argument.CompareTo("-silent")==0) {
181 0 : fVerbosity=0;
182 0 : return 1;
183 :
184 : // -skipempty
185 0 : } else if (argument.CompareTo("-skipempty")==0) {
186 0 : fSkipEmpty=kTRUE;
187 0 : return 1;
188 :
189 : // -datatype
190 0 : } else if (argument.CompareTo("-datatype")==0) {
191 0 : if ((bMissingParam=(++i>=argc))) break;
192 0 : memcpy(&fDataType.fID, argv[i], TMath::Min(kAliHLTComponentDataTypefIDsize, (Int_t)strlen(argv[i])));
193 0 : if ((bMissingParam=(++i>=argc))) break;
194 0 : memcpy(&fDataType.fOrigin, argv[i], TMath::Min(kAliHLTComponentDataTypefOriginSize, (Int_t)strlen(argv[i])));
195 0 : return 3;
196 :
197 : // -dataspec
198 0 : } else if (argument.CompareTo("-dataspec")==0) {
199 0 : if ((bMissingParam=(++i>=argc))) break;
200 0 : TString parameter(argv[i]);
201 0 : parameter.Remove(TString::kLeading, ' '); // remove all blanks
202 0 : if (parameter.IsDigit()) {
203 0 : fSpecification=(AliHLTUInt32_t)parameter.Atoi();
204 0 : } else if (parameter.BeginsWith("0x") &&
205 0 : parameter.Replace(0,2,"",0).IsHex()) {
206 0 : sscanf(parameter.Data(),"%x", &fSpecification);
207 : } else {
208 0 : HLTError("wrong parameter for argument %s, number expected", argument.Data());
209 0 : return -EINVAL;
210 : }
211 0 : return 2;
212 0 : }
213 : } while (0); // using do-while only to have break available
214 0 : if (bMissingParam) {
215 0 : HLTError("missing parameter for argument %s", argument.Data());
216 0 : return -EINVAL;
217 : }
218 :
219 0 : return -EPROTO;
220 0 : }
221 :
222 : int AliHLTRawReaderPublisherComponent::GetEvent(const AliHLTComponentEventData& /*evtData*/,
223 : AliHLTComponentTriggerData& /*trigData*/,
224 : AliHLTUInt8_t* outputPtr,
225 : AliHLTUInt32_t& size,
226 : vector<AliHLTComponentBlockData>& outputBlocks)
227 : {
228 : /// inherited from AliHLTDataSource: get the event
229 : int iResult=0;
230 0 : AliHLTUInt32_t capacity=size;
231 0 : size=0;
232 :
233 : // process data events only
234 0 : if (!IsDataEvent()) return 0;
235 :
236 : unsigned int offset=0;
237 0 : assert(outputPtr!=NULL || size==0);
238 0 : AliRawReader* pRawReader=GetRawReader();
239 0 : if (pRawReader) {
240 0 : pRawReader->Reset();
241 0 : pRawReader->SelectEquipment(-1, fMinEquId, fMaxEquId);
242 0 : if (fVerbosity>1) {
243 0 : AliInfo(Form("get event from RawReader %p equipment id range [%d,%d]", pRawReader, fMinEquId, fMaxEquId));
244 0 : } else {
245 0 : AliDebug(0, Form("get event from RawReader %p equipment id range [%d,%d]", pRawReader, fMinEquId, fMaxEquId));
246 : }
247 0 : list<int> processedIds;
248 : UChar_t headerVersion=0;
249 0 : while (pRawReader->ReadHeader() && (iResult>=0 || iResult==-ENOSPC)) {
250 0 : const AliRawDataHeader* pHeaderV2=pRawReader->GetDataHeader();
251 0 : const AliRawDataHeaderV3* pHeaderV3=pRawReader->GetDataHeaderV3();
252 0 : AliHLTCDHWrapper pHeader;
253 0 : if(pHeaderV2) {
254 0 : pHeader=pHeaderV2;
255 0 : } else if (pHeaderV3) {
256 0 : pHeader=pHeaderV3;
257 : } else {
258 0 : HLTError("can not get data header from RawReader, skipping data block ...");
259 0 : continue;
260 : }
261 : // store header version for empty blocks later on
262 : // any found header will suffice
263 0 : headerVersion=pHeader.GetVersion();
264 0 : unsigned int headerSize=pHeader.GetHeaderSize();
265 0 : unsigned int readSize=pRawReader->GetDataSize()+headerSize;
266 0 : int id=pRawReader->GetEquipmentId();
267 0 : if (fMinEquId>id || fMaxEquId<id) {
268 0 : AliError(Form("id %d returned from RawReader is outside range [%d,%d]", id, fMinEquId, fMaxEquId));
269 0 : continue;
270 : }
271 0 : processedIds.push_back(id);
272 0 : bool isSelected=IsSelected(id);
273 0 : if (fVerbosity>0) {
274 0 : AliInfo(Form("got header for id %d, size %d, %s", id, readSize, isSelected?"selected":"discarded"));
275 : } else {
276 0 : AliDebug(0, Form("got header for id %d, size %d", id, readSize));
277 : }
278 0 : if (!isSelected) continue;
279 0 : if (readSize+offset<=capacity) {
280 0 : memcpy(outputPtr+offset, pHeader.GetHeader(), headerSize);
281 0 : if (readSize>headerSize) {
282 0 : if (!pRawReader->ReadNext(outputPtr+offset+headerSize, readSize-headerSize)) {
283 0 : AliError(Form("error reading %d bytes from RawReader %p", readSize-headerSize, pRawReader));
284 : iResult=-ENODATA;
285 0 : break;
286 : }
287 : }
288 0 : AliHLTComponentBlockData bd;
289 0 : FillBlockData( bd );
290 0 : bd.fOffset = offset;
291 0 : bd.fSize = readSize;
292 0 : bd.fDataType = fDataType;
293 0 : if (fSpecification == kAliHLTVoidDataSpec) {
294 0 : GetSpecificationFromEquipmentId(id, bd.fSpecification);
295 : } else {
296 0 : bd.fSpecification=fSpecification;
297 : }
298 0 : outputBlocks.push_back( bd );
299 0 : } else {
300 : // we keep the loop going in order to collect the full size
301 0 : fMaxSize=offset+readSize;
302 : iResult=-ENOSPC;
303 : }
304 : offset+=readSize;
305 0 : }
306 0 : if (!fSkipEmpty && processedIds.size()!=size_t(fMaxEquId-fMinEquId+1)) {
307 : // add further empty data blocks
308 0 : AliHLTCDHWrapper header;
309 0 : AliRawDataHeader headerV2;
310 0 : AliRawDataHeaderV3 headerV3;
311 0 : if(headerVersion==2){
312 0 : headerV2.fSize=sizeof(AliRawDataHeader);
313 0 : const UInt_t* triggermask=pRawReader->GetTriggerPattern();
314 0 : if (triggermask) {
315 0 : headerV2.fTriggerClassLow=triggermask[0];
316 0 : headerV2.fROILowTriggerClassHigh=triggermask[1];
317 0 : }
318 0 : header=&headerV2;
319 0 : } else { //assuming V3 even if no header at all was found above
320 0 : if(! headerVersion){
321 0 : AliWarning("No data header found! Creating dummy header for empty blocks assuming CDH v3.");
322 : }
323 0 : headerV3.fSize=sizeof(AliRawDataHeaderV3);
324 0 : const UInt_t* triggermask=pRawReader->GetTriggerPattern();
325 0 : if (triggermask) {
326 0 : headerV3.fTriggerClassLow=triggermask[0];
327 0 : headerV3.fTriggerClassesMiddleLow=triggermask[1] & 0x3FFFF;
328 0 : headerV3.fTriggerClassesMiddleHigh= (triggermask[1]>>18) | (triggermask[2]<<14);
329 0 : headerV3.fROILowTriggerClassHigh=(triggermask[2]>>18) | (triggermask[3]<<14);
330 0 : }
331 0 : header=&headerV3;
332 : }
333 0 : unsigned int headerSize=header.GetHeaderSize();
334 0 : processedIds.sort();
335 0 : list<int>::iterator curr=processedIds.begin();
336 0 : for (int id=fMinEquId; id<=fMaxEquId; id++) {
337 0 : if (curr!=processedIds.end() && *curr<=id) {
338 0 : curr++;
339 0 : } else {
340 0 : if (offset+headerSize<=capacity) {
341 0 : HLTInfo("add empty data block for equipment id %d", id);
342 0 : memcpy(outputPtr+offset, header.GetHeader(), headerSize);
343 0 : AliHLTComponentBlockData bd;
344 0 : FillBlockData( bd );
345 0 : bd.fOffset = offset;
346 0 : bd.fSize = headerSize;
347 0 : bd.fDataType = fDataType;
348 0 : if (fSpecification == kAliHLTVoidDataSpec) {
349 0 : GetSpecificationFromEquipmentId(id, bd.fSpecification);
350 : } else {
351 0 : bd.fSpecification=fSpecification;
352 : }
353 0 : outputBlocks.push_back( bd );
354 0 : } else {
355 : // we keep the loop going in order to collect the full size
356 0 : fMaxSize=offset+headerSize;
357 : iResult=-ENOSPC;
358 : }
359 : offset+=headerSize;
360 : }
361 : }
362 0 : }
363 0 : if (offset<=capacity) {
364 0 : size=offset;
365 0 : } else {
366 0 : outputBlocks.clear();
367 : }
368 0 : } else {
369 0 : AliErrorStream() << "RawReader uninitialized" << endl;
370 : iResult=-EFAULT;
371 : }
372 : return iResult;
373 0 : }
374 :
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 0 : return specification=id;
379 : }
|