Line data Source code
1 : // $Id$
2 : /**************************************************************************
3 : * This file is property of and copyright by the ALICE HLT Project *
4 : * ALICE Experiment at CERN, All rights reserved. *
5 : * *
6 : * Primary Authors: Artur Szostak <artursz@iafrica.com> *
7 : * for The ALICE HLT Project. *
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 AliHLTTPCDataCheckerComponent.cxx
19 : /// @author Artur Szostak <artursz@iafrica.com>
20 : /// @date 9 Aug 2010
21 : /// @brief Implementation of the AliHLTTPCDataCheckerComponent class.
22 : ///
23 : /// The AliHLTTPCDataCheckerComponent is used to perform data sanity and integrity
24 : /// checks on the TPC data. This component should be used for testing and debugging.
25 :
26 : #include "AliHLTTPCDataCheckerComponent.h"
27 : #include "AliHLTTPCDefinitions.h"
28 : #include "AliTPCRawStreamV3.h"
29 : #include "AliRawReaderMemory.h"
30 : #include <vector>
31 : #include <cstring>
32 : #include <cassert>
33 :
34 6 : ClassImp(AliHLTTPCDataCheckerComponent)
35 :
36 :
37 3 : AliHLTTPCDataCheckerComponent::AliHLTTPCDataCheckerComponent() :
38 3 : fRawStream(NULL),
39 3 : fRawReader(NULL),
40 3 : fForwardBadBlocks(false),
41 3 : fForwardGoodBlocks(false),
42 3 : fIgnoreType(false),
43 3 : fIgnoreOrigin(false),
44 3 : fIgnoreSpec(false),
45 3 : fHandleAllEvents(false)
46 15 : {
47 : // Default constructor.
48 6 : }
49 :
50 :
51 : AliHLTTPCDataCheckerComponent::~AliHLTTPCDataCheckerComponent()
52 18 : {
53 : // Default destructor.
54 :
55 3 : if (fRawStream != NULL) delete fRawStream;
56 3 : if (fRawReader != NULL) delete fRawReader;
57 9 : }
58 :
59 :
60 : const char* AliHLTTPCDataCheckerComponent::GetComponentID()
61 : {
62 : // Returns the component ID.
63 444 : return "TPCDataChecker";
64 : }
65 :
66 :
67 : void AliHLTTPCDataCheckerComponent::GetInputDataTypes(AliHLTComponentDataTypeList& list)
68 : {
69 : // Returns the list of input data types that are handled.
70 0 : list.push_back(kAliHLTAnyDataType | kAliHLTDataOriginTPC);
71 0 : }
72 :
73 :
74 : AliHLTComponentDataType AliHLTTPCDataCheckerComponent::GetOutputDataType()
75 : {
76 : // Returns kAliHLTMultipleDataType.
77 0 : return kAliHLTMultipleDataType;
78 : }
79 :
80 :
81 : int AliHLTTPCDataCheckerComponent::GetOutputDataTypes(AliHLTComponentDataTypeList& list)
82 : {
83 : // Returns the list of output data block types generated.
84 0 : list.push_back(kAliHLTAnyDataType);
85 0 : return int(list.size());
86 : }
87 :
88 :
89 : void AliHLTTPCDataCheckerComponent::GetOutputDataSize(unsigned long& constBase, double& inputMultiplier)
90 : {
91 : // Returns the buffer size requirements.
92 0 : constBase = 0;
93 0 : inputMultiplier = 0;
94 0 : }
95 :
96 :
97 : AliHLTComponent* AliHLTTPCDataCheckerComponent::Spawn()
98 : {
99 : // Creates a new instance of the component.
100 0 : return new AliHLTTPCDataCheckerComponent;
101 0 : }
102 :
103 :
104 : Int_t AliHLTTPCDataCheckerComponent::DoInit(int argc, const char** argv)
105 : {
106 : // Initialises the data checker component from the command line.
107 :
108 0 : HLTInfo("Starting TPC data checker component.");
109 :
110 0 : fForwardBadBlocks = true;
111 0 : fForwardGoodBlocks = true;
112 0 : fIgnoreType = false;
113 0 : fIgnoreOrigin = false;
114 0 : fIgnoreSpec = false;
115 0 : fHandleAllEvents = false;
116 :
117 0 : for (int i = 0; i < argc; ++i)
118 : {
119 0 : if (strcmp(argv[i], "-filter") == 0)
120 : {
121 0 : if (i+1 < argc)
122 : {
123 0 : if (strcmp(argv[i+1], "forwardbad") == 0)
124 : {
125 0 : fForwardBadBlocks = true;
126 0 : fForwardGoodBlocks = false;
127 : ++i;
128 0 : }
129 0 : else if (strcmp(argv[i+1], "forwardgood") == 0)
130 : {
131 0 : fForwardBadBlocks = false;
132 0 : fForwardGoodBlocks = true;
133 : ++i;
134 0 : }
135 : }
136 0 : fForwardBadBlocks = true;
137 0 : fForwardGoodBlocks = false;
138 0 : continue;
139 : }
140 :
141 0 : if (strcmp(argv[i], "-ignoretype") == 0)
142 : {
143 0 : fIgnoreType = true;
144 0 : continue;
145 : }
146 :
147 0 : if (strcmp(argv[i], "-ignoreorigin") == 0)
148 : {
149 0 : fIgnoreOrigin = true;
150 0 : continue;
151 : }
152 :
153 0 : if (strcmp(argv[i], "-ignorespec") == 0)
154 : {
155 0 : fIgnoreSpec = true;
156 0 : continue;
157 : }
158 :
159 0 : if (strcmp(argv[i], "-handle-all-events") == 0)
160 : {
161 0 : fHandleAllEvents = true;
162 0 : continue;
163 : }
164 :
165 0 : HLTError("Unknown option '%s'.", argv[i]);
166 0 : return -EINVAL;
167 : } // for loop
168 :
169 0 : if (fRawReader == NULL)
170 : {
171 0 : fRawReader = new AliRawReaderMemory();
172 0 : if (fRawReader == NULL)
173 : {
174 0 : HLTError("Could not allocate new AliRawReaderMemory object.");
175 0 : return -ENOMEM;
176 : }
177 : }
178 0 : if (fRawStream == NULL)
179 : {
180 0 : fRawStream = new AliTPCRawStreamV3(fRawReader);
181 0 : if (fRawStream == NULL)
182 : {
183 0 : HLTError("Could not allocate new AliTPCRawStreamV3 object.");
184 0 : return -ENOMEM;
185 : }
186 0 : fRawStream->SelectRawData("TPC");
187 0 : }
188 :
189 0 : return 0;
190 0 : }
191 :
192 :
193 : Int_t AliHLTTPCDataCheckerComponent::DoDeinit()
194 : {
195 : // Cleans up the data checker component.
196 0 : HLTInfo("Stopping TPC data checker component.");
197 0 : if (fRawReader != NULL)
198 : {
199 0 : fRawReader->ClearBuffers();
200 0 : fRawReader->Reset();
201 0 : }
202 0 : if (fRawStream != NULL)
203 : {
204 0 : fRawStream->Reset();
205 0 : }
206 0 : return 0;
207 : }
208 :
209 :
210 : int AliHLTTPCDataCheckerComponent::DoEvent(
211 : const AliHLTComponentEventData& evtData,
212 : const AliHLTComponentBlockData* blocks,
213 : AliHLTComponentTriggerData& /*trigData*/,
214 : AliHLTUInt8_t* /*outputPtr*/,
215 : AliHLTUInt32_t& size,
216 : AliHLTComponentBlockDataList& /*outputBlocks*/
217 : )
218 : {
219 : // Check all the input data blocks.
220 :
221 0 : if (fRawReader == NULL)
222 : {
223 0 : HLTError("The raw reader is not set.");
224 0 : size = 0;
225 0 : return -ENOENT;
226 : }
227 0 : if (fRawStream == NULL)
228 : {
229 0 : HLTError("The TPC raw stream is not set.");
230 0 : size = 0;
231 0 : return -ENOENT;
232 : }
233 :
234 0 : if (not IsDataEvent() and not fHandleAllEvents)
235 : {
236 : // Forward all data blocks if we are not supposed to handle this event.
237 0 : for (AliHLTUInt32_t n = 0; n < evtData.fBlockCnt; ++n)
238 : {
239 0 : Forward(blocks + n);
240 : }
241 0 : size = 0;
242 0 : return 0;
243 : }
244 :
245 0 : AliHLTEventID_t event = evtData.fEventID;
246 0 : AliHLTComponentDataType anyPrivateType = AliHLTComponentDataTypeInitializer(
247 : kAliHLTAnyDataType, kAliHLTDataOriginPrivate
248 : );
249 :
250 : // Setup the markers indicating the bad blocks.
251 0 : std::vector<bool> badBlock(evtData.fBlockCnt, false);
252 :
253 0 : for (AliHLTUInt32_t n = 0; n < evtData.fBlockCnt; ++n)
254 : {
255 : // Skip private data blocks from the framework.
256 0 : if (blocks[n].fDataType == anyPrivateType) continue;
257 :
258 0 : char ddltype[kAliHLTComponentDataTypefIDsize] = kAliHLTDDLRawDataTypeID;
259 0 : if (memcmp(&(blocks[n].fDataType.fID), &ddltype, sizeof(ddltype)) == 0)
260 : {
261 0 : badBlock[n] = not CheckRawDataBlock(event, n, blocks + n);
262 0 : }
263 0 : else if (not fIgnoreType)
264 : {
265 0 : HLTError("Received raw data block %d in event %lld that we do not know how to handle."
266 : " The data block has data type '%s' and specification 0x%8.8X.",
267 : n, event, DataType2Text(blocks[n].fDataType).c_str(), blocks[n].fSpecification
268 : );
269 : }
270 0 : }
271 :
272 : // Forward the different blocks.
273 0 : for (AliHLTUInt32_t n = 0; n < evtData.fBlockCnt; ++n)
274 : {
275 0 : if (badBlock[n] and fForwardBadBlocks)
276 : {
277 : //int result = Forward(blocks + n);
278 0 : int result = Forward(blocks + n);
279 0 : if (result != 0)
280 : {
281 0 : size = 0;
282 0 : return result;
283 : }
284 0 : }
285 0 : if (not badBlock[n] and fForwardGoodBlocks)
286 : {
287 0 : int result = Forward(blocks + n);
288 0 : if (result != 0)
289 : {
290 0 : size = 0;
291 0 : return result;
292 : }
293 0 : }
294 : }
295 :
296 0 : size = 0;
297 0 : return 0;
298 0 : }
299 :
300 :
301 : bool AliHLTTPCDataCheckerComponent::CheckRawDataBlock(
302 : AliHLTEventID_t event, AliHLTUInt32_t index,
303 : const AliHLTComponentBlockData* block
304 : )
305 : {
306 : // Checks TPC raw DDL data blocks.
307 :
308 0 : assert(fRawReader != NULL);
309 0 : assert(fRawStream != NULL);
310 :
311 : // Check the origin field of the data block.
312 0 : if (not fIgnoreOrigin and
313 0 : memcmp(&(block->fDataType.fOrigin), &kAliHLTDataOriginTPC, sizeof(kAliHLTDataOriginTPC)) != 0
314 : )
315 : {
316 0 : char origin[kAliHLTComponentDataTypefOriginSize+1];
317 0 : char expectedOrigin[kAliHLTComponentDataTypefOriginSize+1];
318 0 : memcpy(&origin, &(block->fDataType.fOrigin), kAliHLTComponentDataTypefOriginSize);
319 0 : memcpy(&expectedOrigin, &(kAliHLTDataOriginTPC), kAliHLTComponentDataTypefOriginSize);
320 0 : origin[kAliHLTComponentDataTypefOriginSize] = '\0'; // remember the NULL character for the ANSI string.
321 0 : expectedOrigin[kAliHLTComponentDataTypefOriginSize] = '\0';
322 0 : HLTError("Received raw DDL data block %d in event %lld which has an origin '%s', but expected '%s'.",
323 : index, event, origin, expectedOrigin
324 : );
325 : return false;
326 0 : }
327 :
328 : // Decode and check the specification bits.
329 0 : AliHLTUInt8_t slice = AliHLTTPCDefinitions::GetMinSliceNr(block->fSpecification);
330 0 : AliHLTUInt8_t patch = AliHLTTPCDefinitions::GetMinPatchNr(block->fSpecification);
331 0 : Int_t ddlid = AliHLTTPCDefinitions::SlicePatchToDDLId(slice, patch);
332 0 : if (slice != AliHLTTPCDefinitions::GetMaxSliceNr(block->fSpecification))
333 : {
334 0 : HLTError("Received raw DDL data block %d in event %lld which has a"
335 : " different minimum and maximum slice number (%d verse %d).",
336 : index, event, int(slice), int(AliHLTTPCDefinitions::GetMaxSliceNr(block->fSpecification))
337 : );
338 0 : return false;
339 : }
340 0 : if (patch != AliHLTTPCDefinitions::GetMaxPatchNr(block->fSpecification))
341 : {
342 0 : HLTError("Received raw DDL data block %d in event %lld which has a"
343 : " different minimum and maximum patch number (%d verse %d).",
344 : index, event, int(patch), int(AliHLTTPCDefinitions::GetMaxPatchNr(block->fSpecification))
345 : );
346 0 : return false;
347 : }
348 0 : if (ddlid == -1)
349 : {
350 0 : HLTError("Received raw DDL data block %d in event %lld which has an"
351 : " invalid specification 0x%8.8X. Cannot decode the DDL ID number.",
352 : index, event, block->fSpecification
353 : );
354 0 : return false;
355 : }
356 :
357 : // Now try decode the DDL data. Do it in a try catch block in case
358 : // the decoder segfaults. We want to know about this and log it.
359 : bool result = false;
360 : try
361 : {
362 0 : fRawReader->ClearBuffers();
363 0 : fRawReader->Reset();
364 0 : fRawStream->Reset();
365 0 : fRawReader->AddBuffer(reinterpret_cast<UChar_t*>(block->fPtr), block->fSize, ddlid);
366 0 : if (fRawStream->NextDDL())
367 : {
368 0 : while (fRawStream->NextChannel())
369 : {
370 0 : while (fRawStream->NextBunch())
371 : {
372 0 : Int_t bunchLength = fRawStream->GetBunchLength();
373 0 : const UShort_t* bunchData = fRawStream->GetSignals();
374 0 : for (Int_t i = 0; i < bunchLength; ++i)
375 : {
376 : // Check that the 10 bit signal is within range.
377 0 : if (bunchData[i] >= 1024)
378 : {
379 0 : HLTWarning("Data signal %d in sector %d row %d pad %d is a strange value %d,"
380 : " for data block %d (DDL ID = %d) in event %lld.",
381 : i, fRawStream->GetSector(), fRawStream->GetRow(),
382 : fRawStream->GetPad(), bunchData[i], index, ddlid, event
383 : );
384 : }
385 : }
386 : }
387 : }
388 : result = true;
389 0 : }
390 : else
391 : {
392 0 : HLTError("Cannot decode the raw DDL data (DDL ID = %d) from"
393 : " data block %d in event %lld.",
394 : ddlid, index, event
395 : );
396 : }
397 0 : }
398 : catch (...)
399 : {
400 0 : HLTFatal("Caught an exception when processing raw DDL data (DDL ID = %d)"
401 : " from data block %d in event %lld.",
402 : ddlid, index, event
403 : );
404 0 : throw;
405 0 : }
406 0 : return result;
407 0 : }
408 :
|