Adding first version of data checking component for TPC.
[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         
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
295 bool 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