]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/TPCLib/AliHLTTPCDataCheckerComponent.cxx
adding pointer protection
[u/mrichter/AliRoot.git] / HLT / TPCLib / AliHLTTPCDataCheckerComponent.cxx
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 ClassImp(AliHLTTPCDataCheckerComponent)
35
36
37 AliHLTTPCDataCheckerComponent::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
51 AliHLTTPCDataCheckerComponent::~AliHLTTPCDataCheckerComponent()
52 {
53         // Default destructor.
54         
55         if (fRawStream != NULL) delete fRawStream;
56         if (fRawReader != NULL) delete fRawReader;
57 }
58
59
60 const char* AliHLTTPCDataCheckerComponent::GetComponentID()
61 {
62         // Returns the component ID.
63         return "TPCDataChecker";
64 }
65
66
67 void 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
74 AliHLTComponentDataType AliHLTTPCDataCheckerComponent::GetOutputDataType()
75 {
76         // Returns kAliHLTMultipleDataType.
77         return kAliHLTMultipleDataType;
78 }
79
80
81 int 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
89 void AliHLTTPCDataCheckerComponent::GetOutputDataSize(unsigned long& constBase, double& inputMultiplier)
90 {
91         // Returns the buffer size requirements.
92         constBase = 0;
93         inputMultiplier = 0;
94 }
95
96
97 AliHLTComponent* AliHLTTPCDataCheckerComponent::Spawn()
98 {
99         // Creates a new instance of the component.
100         return new AliHLTTPCDataCheckerComponent;
101 }
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         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
193 Int_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
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         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         AliHLTComponentDataType anyPrivateType = AliHLTComponentDataTypeInitializer(
247                         kAliHLTAnyDataType, kAliHLTDataOriginPrivate
248                 );
249         
250         // Setup the markers indicating the bad blocks.
251         std::vector<bool> badBlock(evtData.fBlockCnt, false);
252         
253         for (AliHLTUInt32_t n = 0; n < evtData.fBlockCnt; ++n)
254         {
255                 // Skip private data blocks from the framework.
256                 if (blocks[n].fDataType == anyPrivateType) continue;
257                 
258                 char ddltype[kAliHLTComponentDataTypefIDsize] = kAliHLTDDLRawDataTypeID;
259                 if (memcmp(&(blocks[n].fDataType.fID), &ddltype, sizeof(ddltype)) == 0)
260                 {
261                         badBlock[n] = not CheckRawDataBlock(event, n, blocks + n);
262                 }
263                 else if (not fIgnoreType)
264                 {
265                         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         }
271         
272         // Forward the different blocks.
273         for (AliHLTUInt32_t n = 0; n < evtData.fBlockCnt; ++n)
274         {
275                 if (badBlock[n] and fForwardBadBlocks)
276                 {
277                         //int result = Forward(blocks + n);
278                         int result = Forward(blocks + n);
279                         if (result != 0)
280                         {
281                                 size = 0;
282                                 return result;
283                         }
284                 }
285                 if (not badBlock[n] and fForwardGoodBlocks)
286                 {
287                         int result = Forward(blocks + n);
288                         if (result != 0)
289                         {
290                                 size = 0;
291                                 return result;
292                         }
293                 }
294         }
295         
296         size = 0;
297         return 0;
298 }
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         assert(fRawReader != NULL);
309         assert(fRawStream != NULL);
310         
311         // Check the origin field of the data block.
312         if (not fIgnoreOrigin and
313             memcmp(&(block->fDataType.fOrigin), &kAliHLTDataOriginTPC, sizeof(kAliHLTDataOriginTPC)) != 0
314            )
315         {
316                 char origin[kAliHLTComponentDataTypefOriginSize+1];
317                 char expectedOrigin[kAliHLTComponentDataTypefOriginSize+1];
318                 memcpy(&origin, &(block->fDataType.fOrigin), kAliHLTComponentDataTypefOriginSize);
319                 memcpy(&expectedOrigin, &(kAliHLTDataOriginTPC), kAliHLTComponentDataTypefOriginSize);
320                 origin[kAliHLTComponentDataTypefOriginSize] = '\0'; // remember the NULL character for the ANSI string.
321                 expectedOrigin[kAliHLTComponentDataTypefOriginSize] = '\0';
322                 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         }
327         
328         // Decode and check the specification bits.
329         AliHLTUInt8_t slice = AliHLTTPCDefinitions::GetMinSliceNr(block->fSpecification);
330         AliHLTUInt8_t patch = AliHLTTPCDefinitions::GetMinPatchNr(block->fSpecification);
331         Int_t ddlid = AliHLTTPCDefinitions::SlicePatchToDDLId(slice, patch);
332         if (slice != AliHLTTPCDefinitions::GetMaxSliceNr(block->fSpecification))
333         {
334                 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                 return false;
339         }
340         if (patch != AliHLTTPCDefinitions::GetMaxPatchNr(block->fSpecification))
341         {
342                 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                 return false;
347         }
348         if (ddlid == -1)
349         {
350                 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                 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                 fRawReader->ClearBuffers();
363                 fRawReader->Reset();
364                 fRawStream->Reset();
365                 fRawReader->AddBuffer(reinterpret_cast<UChar_t*>(block->fPtr), block->fSize, ddlid);
366                 if (fRawStream->NextDDL())
367                 {
368                         while (fRawStream->NextChannel())
369                         {
370                                 while (fRawStream->NextBunch())
371                                 {
372                                         Int_t bunchLength = fRawStream->GetBunchLength();
373                                         const UShort_t* bunchData = fRawStream->GetSignals();
374                                         for (Int_t i = 0; i < bunchLength; ++i)
375                                         {
376                                                 // Check that the 10 bit signal is within range.
377                                                 if (bunchData[i] >= 1024)
378                                                 {
379                                                         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                 }
390                 else
391                 {
392                         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         }
398         catch (...)
399         {
400                 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                 throw;
405         }
406         return result;
407 }
408