Cleaning up warnings and making some changes to memory handling to be more robust...
[u/mrichter/AliRoot.git] / HLT / MUON / OnlineAnalysis / AliHLTMUONTriggerReconstructorComponent.cxx
1 /**************************************************************************
2  * This file is property of and copyright by the ALICE HLT Project        *
3  * All rights reserved.                                                   *
4  *                                                                        *
5  * Primary Authors:                                                       *
6  *   Indranil Das <indra.das@saha.ac.in>                                  *
7  *   Artur Szostak <artursz@iafrica.com>                                  *
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 /* $Id$ */
19
20 ///
21 /// @file   AliHLTMUONTriggerReconstructorComponent.cxx
22 /// @author Indranil Das <indra.das@saha.ac.in>, Artur Szostak <artursz@iafrica.com>
23 /// @date
24 /// @brief  Implementation of the trigger DDL reconstructor component.
25 ///
26
27 #include "AliHLTMUONTriggerReconstructorComponent.h"
28 #include "AliHLTMUONTriggerReconstructor.h"
29 #include "AliHLTMUONHitReconstructor.h"
30 #include "AliHLTMUONConstants.h"
31 #include "AliHLTMUONUtils.h"
32 #include "AliHLTMUONDataBlockWriter.h"
33 #include <cstdlib>
34 #include <cerrno>
35 #include <cassert>
36 #include <fstream>
37
38 ClassImp(AliHLTMUONTriggerReconstructorComponent)
39
40
41 AliHLTMUONTriggerReconstructorComponent::AliHLTMUONTriggerReconstructorComponent() :
42         AliHLTProcessor(),
43         fTrigRec(NULL),
44         fDDL(-1),
45         fWarnForUnexpecedBlock(false),
46         fSuppressPartialTrigs(false)
47 {
48         ///
49         /// Default constructor.
50         ///
51 }
52
53
54 AliHLTMUONTriggerReconstructorComponent::~AliHLTMUONTriggerReconstructorComponent()
55 {
56         ///
57         /// Default destructor.
58         ///
59         
60         if (fTrigRec != NULL) delete fTrigRec;
61 }
62
63
64 const char* AliHLTMUONTriggerReconstructorComponent::GetComponentID()
65 {
66         ///
67         /// Inherited from AliHLTComponent. Returns the component ID.
68         ///
69         
70         return AliHLTMUONConstants::TriggerReconstructorId();
71 }
72
73
74 void AliHLTMUONTriggerReconstructorComponent::GetInputDataTypes( std::vector<AliHLTComponentDataType>& list)
75 {
76         ///
77         /// Inherited from AliHLTProcessor. Returns the list of expected input data types.
78         ///
79         
80         list.clear();
81         list.push_back( AliHLTMUONConstants::DDLRawDataType() );
82 }
83
84
85 AliHLTComponentDataType AliHLTMUONTriggerReconstructorComponent::GetOutputDataType()
86 {
87         ///
88         /// Inherited from AliHLTComponent. Returns the output data type.
89         ///
90         
91         return AliHLTMUONConstants::TriggerRecordsBlockDataType();
92 }
93
94
95 void AliHLTMUONTriggerReconstructorComponent::GetOutputDataSize(
96                 unsigned long& constBase, double& inputMultiplier
97         )
98 {
99         ///
100         /// Inherited from AliHLTComponent. Returns an estimate of the expected output data size.
101         ///
102         
103         constBase = sizeof(AliHLTMUONTriggerRecordsBlockWriter::HeaderType);
104         inputMultiplier = 4;
105 }
106
107
108 AliHLTComponent* AliHLTMUONTriggerReconstructorComponent::Spawn()
109 {
110         ///
111         /// Inherited from AliHLTComponent. Creates a new object instance.
112         ///
113         
114         return new AliHLTMUONTriggerReconstructorComponent;
115 }
116
117
118 int AliHLTMUONTriggerReconstructorComponent::DoInit(int argc, const char** argv)
119 {
120         ///
121         /// Inherited from AliHLTComponent.
122         /// Parses the command line parameters and initialises the component.
123         ///
124         
125         // perform initialization.
126         
127         HLTInfo("Initialising dHLT trigger reconstructor component.");
128         
129         // Make sure to cleanup fTrigRec if it is still there for some reason.
130         if (fTrigRec != NULL)
131         {
132                 delete fTrigRec;
133                 fTrigRec = NULL;
134         }
135         
136         try
137         {
138                 fTrigRec = new AliHLTMUONTriggerReconstructor();
139         }
140         catch (const std::bad_alloc&)
141         {
142                 HLTError("Could not allocate more memory for the trigger reconstructor component.");
143                 return -ENOMEM;
144         }
145         
146         fDDL = -1;
147         fWarnForUnexpecedBlock = false;
148         fSuppressPartialTrigs = false;
149         
150         const char* lutFileName = NULL;
151         
152         for (int i = 0; i < argc; i++)
153         {
154                 if (strcmp( argv[i], "-lut" ) == 0)
155                 {
156                         if ( argc <= i+1 )
157                         {
158                                 HLTError("LookupTable filename not specified." );
159                                 // Make sure to delete fTrigRec to avoid partial initialisation.
160                                 delete fTrigRec;
161                                 fTrigRec = NULL;
162                                 return -EINVAL;
163                         }
164                         
165                         lutFileName = argv[i+1];
166                         
167                         i++;
168                         continue;
169                 }
170                 
171                 if (strcmp( argv[i], "-ddl" ) == 0)
172                 {
173                         if ( argc <= i+1 )
174                         {
175                                 HLTError("DDL number not specified." );
176                                 // Make sure to delete fTrigRec to avoid partial initialisation.
177                                 delete fTrigRec;
178                                 fTrigRec = NULL;
179                                 return -EINVAL;
180                         }
181                 
182                         char* cpErr = NULL;
183                         unsigned long num = strtoul(argv[i+1], &cpErr, 0);
184                         if (cpErr == NULL or *cpErr != '\0')
185                         {
186                                 HLTError("Cannot convert '%s' to a DDL Number.", argv[i+1] );\
187                                 // Make sure to delete fTrigRec to avoid partial initialisation.
188                                 delete fTrigRec;
189                                 fTrigRec = NULL;
190                                 return -EINVAL;
191                         }
192                         if (num < 21 or 22 < num)
193                         {
194                                 HLTError("The DDL number must be in the range [21..22].");
195                                 // Make sure to delete fTrigRec to avoid partial initialisation.
196                                 delete fTrigRec;
197                                 fTrigRec = NULL;
198                                 return -EINVAL;
199                         }
200                         fDDL = num - 1; // Convert to DDL number in the range 0..21
201                         
202                         i++;
203                         continue;
204                 }
205                         
206                 if (strcmp( argv[i], "-warn_on_unexpected_block" ) == 0)
207                 {
208                         fWarnForUnexpecedBlock = true;
209                         continue;
210                 }
211                         
212                 if (strcmp( argv[i], "-suppress_partial_triggers" ) == 0)
213                 {
214                         fSuppressPartialTrigs = true;
215                         continue;
216                 }
217                 
218                 HLTError("Unknown option '%s'.", argv[i] );
219                 // Make sure to delete fTrigRec to avoid partial initialisation.
220                 delete fTrigRec;
221                 fTrigRec = NULL;
222                 return -EINVAL;
223                         
224         } // for loop
225         
226         if (fDDL == -1)
227         {
228                 HLTWarning("DDL number not specified. Cannot check if incomming data is valid.");
229         }
230         
231         if (lutFileName != NULL)
232         {
233                 if (not ReadLookUpTable(lutFileName))
234                 {
235                         HLTError("Failed to read lut from file.");
236                         // Make sure to delete fTrigRec to avoid partial initialisation.
237                         delete fTrigRec;
238                         fTrigRec = NULL;
239                         return -ENOENT;
240                 }
241         }
242         else
243         {
244                 HLTWarning("The lookup table has not been specified. Output results will be invalid.");
245         }
246         
247         return 0;
248 }
249
250
251 int AliHLTMUONTriggerReconstructorComponent::DoDeinit()
252 {
253         ///
254         /// Inherited from AliHLTComponent. Performs a cleanup of the component.
255         ///
256         
257         HLTInfo("Deinitialising dHLT trigger reconstructor component.");
258
259         if (fTrigRec != NULL)
260         {
261                 delete fTrigRec;
262                 fTrigRec = NULL;
263         }
264         return 0;
265 }
266
267
268 int AliHLTMUONTriggerReconstructorComponent::DoEvent(
269                 const AliHLTComponentEventData& evtData,
270                 const AliHLTComponentBlockData* blocks,
271                 AliHLTComponentTriggerData& /*trigData*/,
272                 AliHLTUInt8_t* outputPtr,
273                 AliHLTUInt32_t& size,
274                 std::vector<AliHLTComponentBlockData>& outputBlocks
275         )
276 {
277         ///
278         /// Inherited from AliHLTProcessor. Processes the new event data.
279         ///
280         
281         // Process an event
282         unsigned long totalSize = 0; // Amount of memory currently consumed in bytes.
283
284         HLTDebug("Processing event %llu with %u input data blocks.",
285                 evtData.fEventID, evtData.fBlockCnt
286         );
287         
288         // Loop over all input blocks in the event and run the trigger DDL
289         // reconstruction algorithm on the raw data.
290         for (AliHLTUInt32_t n = 0; n < evtData.fBlockCnt; n++)
291         {
292 #ifdef __DEBUG
293                 char id[kAliHLTComponentDataTypefIDsize+1];
294                 for (int i = 0; i < kAliHLTComponentDataTypefIDsize; i++)
295                         id[i] = blocks[n].fDataType.fID[i];
296                 id[kAliHLTComponentDataTypefIDsize] = '\0';
297                 char origin[kAliHLTComponentDataTypefOriginSize+1];
298                 for (int i = 0; i < kAliHLTComponentDataTypefOriginSize; i++)
299                         origin[i] = blocks[n].fDataType.fOrigin[i];
300                 origin[kAliHLTComponentDataTypefOriginSize] = '\0';
301 #endif // __DEBUG
302                 HLTDebug("Handling block: %u, with fDataType.fID = '%s',"
303                           " fDataType.fID = '%s', fPtr = %p and fSize = %u bytes.",
304                         n, static_cast<char*>(id), static_cast<char*>(origin),
305                         blocks[n].fPtr, blocks[n].fSize
306                 );
307
308                 if (blocks[n].fDataType != AliHLTMUONConstants::DDLRawDataType()
309                     or not AliHLTMUONUtils::IsTriggerDDL(blocks[n].fSpecification)
310                    )
311                 {
312                         // Log a message indicating that we got a data block that we
313                         // do not know how to handle.
314                         char id[kAliHLTComponentDataTypefIDsize+1];
315                         for (int i = 0; i < kAliHLTComponentDataTypefIDsize; i++)
316                                 id[i] = blocks[n].fDataType.fID[i];
317                         id[kAliHLTComponentDataTypefIDsize] = '\0';
318                         char origin[kAliHLTComponentDataTypefOriginSize+1];
319                         for (int i = 0; i < kAliHLTComponentDataTypefOriginSize; i++)
320                                 origin[i] = blocks[n].fDataType.fOrigin[i];
321                         origin[kAliHLTComponentDataTypefOriginSize] = '\0';
322                         
323                         if (fWarnForUnexpecedBlock)
324                                 HLTWarning("Received a data block of a type we cannot handle: '%s' origin: '%s' spec: 0x%X",
325                                         static_cast<char*>(id), static_cast<char*>(origin), blocks[n].fSpecification
326                                 );
327                         else
328                                 HLTDebug("Received a data block of a type we cannot handle: '%s' origin: '%s' spec: 0x%X",
329                                         static_cast<char*>(id), static_cast<char*>(origin), blocks[n].fSpecification
330                                 );
331                         
332                         continue;
333                 }
334                 
335                 if (fDDL != -1)
336                 {
337                         bool ddl[22];
338                         AliHLTMUONUtils::UnpackSpecBits(blocks[n].fSpecification, ddl);
339                         if (not ddl[fDDL])
340                         {
341                                 HLTWarning("Received raw data from an unexpected DDL.");
342                         }
343                 }
344                 
345                 // Create a new output data block and initialise the header.
346                 AliHLTMUONTriggerRecordsBlockWriter block(outputPtr+totalSize, size-totalSize);
347                 if (not block.InitCommonHeader())
348                 {
349                         HLTError("There is not enough space in the output buffer for the new data block.",
350                                  " We require at least %ufTrigRec->GetkDDLHeaderSize() bytes, but have %u bytes left.",
351                                 sizeof(AliHLTMUONTriggerRecordsBlockWriter::HeaderType),
352                                 block.BufferSize()
353                         );
354                         break;
355                 }
356
357                 AliHLTUInt32_t totalDDLSize = blocks[n].fSize / sizeof(AliHLTUInt32_t);
358                 AliHLTUInt32_t ddlRawDataSize = totalDDLSize - 8;
359                 AliHLTUInt32_t* buffer = reinterpret_cast<AliHLTUInt32_t*>(blocks[n].fPtr) + 8;
360                 AliHLTUInt32_t nofTrigRec = block.MaxNumberOfEntries();
361
362                 bool runOk = fTrigRec->Run(
363                                 buffer, ddlRawDataSize,
364                                 block.GetArray(), nofTrigRec,
365                                 fSuppressPartialTrigs
366                         );
367                 if (not runOk)
368                 {
369                         HLTError("Error while processing of trigger DDL reconstruction algorithm.");
370                         size = totalSize; // Must tell the framework how much buffer space was used.
371                         return -EIO;
372                 }
373                 
374                 // nofTrigRec should now contain the number of triggers actually found
375                 // and filled into the output data block, so we can set this number.
376                 assert( nofTrigRec <= block.MaxNumberOfEntries() );
377                 block.SetNumberOfEntries(nofTrigRec);
378                 
379                 HLTDebug("Number of trigger records found is %d", nofTrigRec);
380                 
381                 // Fill a block data structure for our output block.
382                 AliHLTComponentBlockData bd;
383                 FillBlockData(bd);
384                 bd.fPtr = outputPtr;
385                 // This block's start (offset) is after all other blocks written so far.
386                 bd.fOffset = totalSize;
387                 bd.fSize = block.BytesUsed();
388                 bd.fDataType = AliHLTMUONConstants::TriggerRecordsBlockDataType();
389                 bd.fSpecification = blocks[n].fSpecification;
390                 outputBlocks.push_back(bd);
391                 
392                 HLTDebug("Created a new output data block at fPtr = %p,"
393                           " with fOffset = %u (0x%.X) and fSize = %u bytes.", 
394                         bd.fPtr, bd.fOffset, bd.fOffset, bd.fSize
395                 );
396                 
397                 // Increase the total amount of data written so far to our output memory.
398                 totalSize += block.BytesUsed();
399         }
400         
401         // Finally we set the total size of output memory we consumed.
402         size = totalSize;
403         return 0;
404 }
405
406
407 bool AliHLTMUONTriggerReconstructorComponent::ReadLookUpTable(const char* lutpath)
408 {
409         ///
410         /// Read in the lookup table from file.
411         ///
412         
413         assert(fTrigRec != NULL);
414
415         fstream file;
416         file.open(lutpath, fstream::binary | fstream::in);
417         if (not file)
418         {
419                 HLTError("Could not open file: %s", lutpath);
420                 return false;
421         }
422         
423         file.read(reinterpret_cast<char*>(fTrigRec->LookupTableBuffer()), fTrigRec->LookupTableSize());
424         if (file.eof())
425         {
426                 HLTError("The file %s was too short to contain a valid lookup table for this component.", lutpath);
427                 file.close();
428                 return false;
429         }
430         if (file.bad())
431         {
432                 HLTError("Could not read from file: %s", lutpath);
433                 file.close();
434                 return false;
435         }
436         
437         file.close();
438         return true;
439 }