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