]>
Commit | Line | Data |
---|---|---|
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 | ClassImp(AliHLTRawReaderPublisherComponent) | |
35 | ||
36 | AliHLTRawReaderPublisherComponent::AliHLTRawReaderPublisherComponent() | |
37 | : | |
38 | fMaxSize(5000000), | |
39 | fDetector(), | |
40 | fMinEquId(-1), | |
41 | fMaxEquId(-1), | |
42 | fVerbosity(0), | |
43 | fDataType(kAliHLTVoidDataType), | |
44 | fSpecification(kAliHLTVoidDataSpec), | |
45 | fSkipEmpty(kFALSE) | |
46 | { | |
47 | // constructor | |
48 | } | |
49 | ||
50 | AliHLTRawReaderPublisherComponent::~AliHLTRawReaderPublisherComponent() | |
51 | { | |
52 | // destructor | |
53 | } | |
54 | ||
55 | const char* AliHLTRawReaderPublisherComponent::GetComponentID() | |
56 | { | |
57 | /// inherited from AliHLTComponent: id of the component | |
58 | return "AliRawReaderPublisher"; | |
59 | } | |
60 | ||
61 | AliHLTComponentDataType AliHLTRawReaderPublisherComponent::GetOutputDataType() | |
62 | { | |
63 | /// inherited from AliHLTComponent: output data type of the component. | |
64 | return fDataType; | |
65 | } | |
66 | ||
67 | void AliHLTRawReaderPublisherComponent::GetOutputDataSize( unsigned long& constBase, double& inputMultiplier ) | |
68 | { | |
69 | /// inherited from AliHLTComponent: output data size estimator | |
70 | constBase=fMaxSize; | |
71 | inputMultiplier=1; | |
72 | } | |
73 | ||
74 | AliHLTComponent* AliHLTRawReaderPublisherComponent::Spawn() | |
75 | { | |
76 | /// inherited from AliHLTComponent: spawn function. | |
77 | return new AliHLTRawReaderPublisherComponent; | |
78 | } | |
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 | if (argc && (iResult = ConfigureFromArgumentString(argc, argv)) < 0) | |
87 | return iResult; | |
88 | ||
89 | if (!fDetector.IsNull()) { | |
90 | int ddloffset=-1; | |
91 | int ddlcount=-1; | |
92 | if ((ddloffset=AliDAQ::DdlIDOffset(fDetector))<0 || | |
93 | (ddlcount=AliDAQ::NumberOfDdls(fDetector))<0) { | |
94 | return -EINVAL; | |
95 | } | |
96 | if (fMinEquId<0) fMinEquId=ddloffset; | |
97 | else fMinEquId+=ddloffset; | |
98 | ||
99 | if (fMaxEquId<0 || fMaxEquId>ddlcount) fMaxEquId=ddloffset+ddlcount-1; | |
100 | else fMaxEquId+=ddloffset; | |
101 | } | |
102 | ||
103 | if (fMinEquId>fMaxEquId) fMaxEquId=fMinEquId; | |
104 | ||
105 | if (fMinEquId<0) { | |
106 | AliErrorStream() << "equipment id required, use \'-equipmentid\' or \'-detector\' option" << endl; | |
107 | return -EINVAL; | |
108 | } | |
109 | ||
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; | |
113 | //return -EINVAL; | |
114 | } | |
115 | ||
116 | if (GetRawReader()!=NULL) { | |
117 | } else { | |
118 | AliErrorStream() << "RawReader instance needed" << endl; | |
119 | return -EINVAL; | |
120 | } | |
121 | ||
122 | return iResult; | |
123 | } | |
124 | ||
125 | int AliHLTRawReaderPublisherComponent::DoDeinit() | |
126 | { | |
127 | /// inherited from AliHLTComponent: component cleanup | |
128 | int iResult=0; | |
129 | return iResult; | |
130 | } | |
131 | ||
132 | int AliHLTRawReaderPublisherComponent::ScanConfigurationArgument(int argc, const char** argv) | |
133 | { | |
134 | /// inherited from AliHLTComponent: argument scan | |
135 | if (argc<1) return 0; | |
136 | int bMissingParam=0; | |
137 | int i=0; | |
138 | TString argument=argv[i]; | |
139 | ||
140 | do { | |
141 | // -detector | |
142 | if (argument.CompareTo("-detector")==0) { | |
143 | if ((bMissingParam=(++i>=argc))) break; | |
144 | fDetector=argv[i]; | |
145 | return 2; | |
146 | ||
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(); | |
155 | return 2; | |
156 | } else { | |
157 | HLTError("wrong parameter for argument %s, number expected", argument.Data()); | |
158 | return -EINVAL; | |
159 | } | |
160 | ||
161 | // -maxid | |
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(); | |
168 | return 2; | |
169 | } else { | |
170 | HLTError("wrong parameter for argument %s, number expected", argument.Data()); | |
171 | return -EINVAL; | |
172 | } | |
173 | ||
174 | // -verbose | |
175 | } else if (argument.CompareTo("-verbose")==0) { | |
176 | fVerbosity++; | |
177 | return 1; | |
178 | ||
179 | // -silent | |
180 | } else if (argument.CompareTo("-silent")==0) { | |
181 | fVerbosity=0; | |
182 | return 1; | |
183 | ||
184 | // -skipempty | |
185 | } else if (argument.CompareTo("-skipempty")==0) { | |
186 | fSkipEmpty=kTRUE; | |
187 | return 1; | |
188 | ||
189 | // -datatype | |
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]))); | |
195 | return 3; | |
196 | ||
197 | // -dataspec | |
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); | |
207 | } else { | |
208 | HLTError("wrong parameter for argument %s, number expected", argument.Data()); | |
209 | return -EINVAL; | |
210 | } | |
211 | return 2; | |
212 | } | |
213 | } while (0); // using do-while only to have break available | |
214 | if (bMissingParam) { | |
215 | HLTError("missing parameter for argument %s", argument.Data()); | |
216 | return -EINVAL; | |
217 | } | |
218 | ||
219 | return -EPROTO; | |
220 | } | |
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 | AliHLTUInt32_t capacity=size; | |
231 | size=0; | |
232 | ||
233 | // process data events only | |
234 | if (!IsDataEvent()) return 0; | |
235 | ||
236 | unsigned int offset=0; | |
237 | assert(outputPtr!=NULL || size==0); | |
238 | AliRawReader* pRawReader=GetRawReader(); | |
239 | if (pRawReader) { | |
240 | pRawReader->Reset(); | |
241 | pRawReader->SelectEquipment(-1, fMinEquId, fMaxEquId); | |
242 | if (fVerbosity>1) { | |
243 | AliInfo(Form("get event from RawReader %p equipment id range [%d,%d]", pRawReader, fMinEquId, fMaxEquId)); | |
244 | } else { | |
245 | AliDebug(0, Form("get event from RawReader %p equipment id range [%d,%d]", pRawReader, fMinEquId, fMaxEquId)); | |
246 | } | |
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; | |
253 | if(pHeaderV2) { | |
254 | pHeader=pHeaderV2; | |
255 | } else if (pHeaderV3) { | |
256 | pHeader=pHeaderV3; | |
257 | } else { | |
258 | HLTError("can not get data header from RawReader, skipping data block ..."); | |
259 | continue; | |
260 | } | |
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)); | |
269 | continue; | |
270 | } | |
271 | processedIds.push_back(id); | |
272 | bool isSelected=IsSelected(id); | |
273 | if (fVerbosity>0) { | |
274 | AliInfo(Form("got header for id %d, size %d, %s", id, readSize, isSelected?"selected":"discarded")); | |
275 | } else { | |
276 | AliDebug(0, Form("got header for id %d, size %d", id, readSize)); | |
277 | } | |
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)); | |
284 | iResult=-ENODATA; | |
285 | break; | |
286 | } | |
287 | } | |
288 | AliHLTComponentBlockData bd; | |
289 | FillBlockData( bd ); | |
290 | bd.fOffset = offset; | |
291 | bd.fSize = readSize; | |
292 | bd.fDataType = fDataType; | |
293 | if (fSpecification == kAliHLTVoidDataSpec) { | |
294 | GetSpecificationFromEquipmentId(id, bd.fSpecification); | |
295 | } else { | |
296 | bd.fSpecification=fSpecification; | |
297 | } | |
298 | outputBlocks.push_back( bd ); | |
299 | } else { | |
300 | // we keep the loop going in order to collect the full size | |
301 | fMaxSize=offset+readSize; | |
302 | iResult=-ENOSPC; | |
303 | } | |
304 | offset+=readSize; | |
305 | } | |
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(); | |
314 | if (triggermask) { | |
315 | headerV2.fTriggerClassLow=triggermask[0]; | |
316 | headerV2.fROILowTriggerClassHigh=triggermask[1]; | |
317 | } | |
318 | header=&headerV2; | |
319 | } else { //assuming V3 even if no header at all was found above | |
320 | headerV3.fSize=sizeof(AliRawDataHeaderV3); | |
321 | const UInt_t* triggermask=pRawReader->GetTriggerPattern(); | |
322 | if (triggermask) { | |
323 | headerV3.fTriggerClassLow=triggermask[0]; | |
324 | headerV3.fTriggerClassesMiddleLow=triggermask[1] & 0x3FFFF; | |
325 | headerV3.fTriggerClassesMiddleHigh= (triggermask[1]>>18) | (triggermask[2]<<14); | |
326 | headerV3.fROILowTriggerClassHigh=(triggermask[2]>>18) | (triggermask[3]<<14); | |
327 | } | |
328 | header=&headerV3; | |
329 | } | |
330 | unsigned int headerSize=header.GetHeaderSize(); | |
331 | processedIds.sort(); | |
332 | list<int>::iterator curr=processedIds.begin(); | |
333 | for (int id=fMinEquId; id<=fMaxEquId; id++) { | |
334 | if (curr!=processedIds.end() && *curr<=id) { | |
335 | curr++; | |
336 | } else { | |
337 | if (headerSize<=capacity-offset) { | |
338 | HLTInfo("add empty data block for equipment id %d", id); | |
339 | memcpy(outputPtr+offset, header.GetHeader(), headerSize); | |
340 | AliHLTComponentBlockData bd; | |
341 | FillBlockData( bd ); | |
342 | bd.fOffset = offset; | |
343 | bd.fSize = headerSize; | |
344 | bd.fDataType = fDataType; | |
345 | if (fSpecification == kAliHLTVoidDataSpec) { | |
346 | GetSpecificationFromEquipmentId(id, bd.fSpecification); | |
347 | } else { | |
348 | bd.fSpecification=fSpecification; | |
349 | } | |
350 | outputBlocks.push_back( bd ); | |
351 | } else { | |
352 | // we keep the loop going in order to collect the full size | |
353 | fMaxSize=offset+headerSize; | |
354 | iResult=-ENOSPC; | |
355 | } | |
356 | offset+=headerSize; | |
357 | } | |
358 | } | |
359 | } | |
360 | if (offset<=capacity) { | |
361 | size=offset; | |
362 | } else { | |
363 | outputBlocks.clear(); | |
364 | } | |
365 | } else { | |
366 | AliErrorStream() << "RawReader uninitialized" << endl; | |
367 | iResult=-EFAULT; | |
368 | } | |
369 | return iResult; | |
370 | } | |
371 | ||
372 | int AliHLTRawReaderPublisherComponent::GetSpecificationFromEquipmentId(int id, AliHLTUInt32_t& specification) const { | |
373 | /// get the data specification from the equipment id | |
374 | /// default method just returns the equipment id | |
375 | return specification=id; | |
376 | } |