]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/MUON/utils/dHLTdumpraw.cxx
39874a1a74692897d9be561fcd87194edd644ec9
[u/mrichter/AliRoot.git] / HLT / MUON / utils / dHLTdumpraw.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-2007, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author:                                                                *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 /* $Id$ */
17
18 /**
19  * @file   dHLTdumpraw.cxx
20  * @author Artur Szostak <artursz@iafrica.com>,
21  *         Seforo Mohlalisi <seforomohlalisi@yahoo.co.uk>
22  * @date   1 July 2007
23  * @brief  Command line utility to dump dHLT's internal raw data blocks.
24  */
25
26 // We define NDEBUG for the AliHLTMUONDataBlockReader.h header file since this
27 // program by definition handles corrupt data. So we do not need the assertions
28 // in the AliHLTMUONDataBlockReader class to be checked.
29 #ifndef NDEBUG
30 #define NDEBUG
31 #endif
32 #include "AliHLTMUONDataBlockReader.h"
33 #if defined(DEBUG) && defined(NDEBUG)
34 #undef NDEBUG
35 #endif
36
37 #include "AliHLTMUONUtils.h"
38 #include "AliHLTMUONConstants.h"
39 #include "Rtypes.h"
40 #include "AliRawDataHeader.h"
41 #include "AliMUONTrackerDDLDecoder.h"
42 #include "AliMUONTriggerDDLDecoder.h"
43 #include "AliHLTSystem.h"
44 #include "AliHLTConfiguration.h"
45 #include "AliLog.h"
46 #include "TClassTable.h"
47 #include "TString.h"
48 #include "TRegexp.h"
49
50 #include <cstring>
51 #include <cstdlib>
52 #include <cstdio>
53 #include <cassert>
54 #include <new>
55 #include <fstream>
56
57 #include <iostream>
58 using std::cout;
59 using std::cerr;
60 using std::endl;
61 using std::showbase;
62 using std::noshowbase;
63 using std::hex;
64 using std::dec;
65
66 #include <iomanip>
67 using std::setw;
68 using std::left;
69 using std::right;
70 using std::internal;
71
72
73 #define CMDLINE_ERROR 1
74 #define PARSE_ERROR 2
75 #define SYSTEM_ERROR 3
76 #define FATAL_ERROR 4
77 #define HLTSYSTEM_ERROR 5
78
79
80 // Adding enum types for extending AliHLTMUONDataBlockType with the
81 // raw DDL data types.
82 enum AliHLTMUONDDLRawDataType
83 {
84         kTrackerDDLRawData = 10,
85         kTriggerDDLRawData = 11
86 };
87
88
89 void PrintRubbishData(AliHLTUInt32_t offset, const char* padByte, AliHLTUInt32_t padCount)
90 {
91         if (padCount == 0) return;
92         
93         cerr << "ERROR: Found the following unexpected rubbish data at the"
94                 " end of the data block:" << endl;
95         cerr << "Byte #\tValue\tCharacter" << endl;
96         for (AliHLTUInt32_t i = 0; i < padCount; i++)
97         {
98                 short value = short(padByte[i]) & 0xFF;
99                 char character = padByte[i];
100                 cerr << offset + i + 1 << "\t"
101                         << noshowbase << hex << "0x" << value << dec << "\t"
102                         << character << endl;
103         }
104 }
105
106
107 template <typename FieldType>
108 int CheckHeaderField(
109                 FieldType& field, const char* buffer, unsigned long bufferSize,
110                 bool continueParse
111         )
112 {
113         const char* fieldptr = reinterpret_cast<const char*>(&field);
114         const char* endptr = buffer + bufferSize;
115         AliHLTUInt32_t bufferRemaining = endptr > fieldptr ? endptr - fieldptr : 0;
116         
117         if (bufferRemaining < sizeof(field))
118         {
119                 cout << "..." << endl; // We may be half way through printing a line so end it.
120                 cerr << "ERROR: The data block is too short. The header is corrupt." << endl;
121                 if (continueParse)
122                 {
123                         AliHLTUInt32_t offset = fieldptr - buffer;
124                         PrintRubbishData(offset, fieldptr, bufferRemaining);
125                 }
126                 return PARSE_ERROR;
127         }
128         return EXIT_SUCCESS;
129 }
130
131
132 template <typename FieldType>
133 int CheckField(
134                 FieldType& field, const char* buffer, unsigned long bufferSize,
135                 bool continueParse
136         )
137 {
138         const char* fieldptr = reinterpret_cast<const char*>(&field);
139         const char* endptr = buffer + bufferSize;
140         AliHLTUInt32_t bufferRemaining = endptr > fieldptr ? endptr - fieldptr : 0;
141         
142         if (bufferRemaining < sizeof(field))
143         {
144                 cout << "..." << endl; // We may be half way through printing a line so end it.
145                 cerr << "ERROR: The data block is too short. The data is corrupt." << endl;
146                 if (continueParse)
147                 {
148                         AliHLTUInt32_t offset = fieldptr - buffer;
149                         PrintRubbishData(offset, fieldptr, bufferRemaining);
150                 }
151                 return PARSE_ERROR;
152         }
153         return EXIT_SUCCESS;
154 }
155
156
157 template <typename BlockType>
158 int CheckCommonHeader(
159                 BlockType& block, const char* /*buffer*/, unsigned long bufferSize,
160                 bool continueParse
161         )
162 {
163         int result = EXIT_SUCCESS;
164
165         // Check the fRecordWidth field in the common header.
166         if (block.CommonBlockHeader().fRecordWidth !=
167                 sizeof(typename BlockType::ElementType))
168         {
169                 cerr << "ERROR: The record width found in the header is incorrect."
170                         " Found a record width of "
171                         << block.CommonBlockHeader().fRecordWidth << " bytes, but expected"
172                         " a value of " << sizeof(typename BlockType::ElementType)
173                         << " bytes." << endl;
174                 result = PARSE_ERROR;
175                 if (not continueParse) return result;
176         }
177         
178         if (not block.BufferSizeOk())
179         {
180                 cerr << "ERROR: The size of the file is incorrect. It is "
181                         << bufferSize << " bytes big, but according"
182                         " to the data block header it should be " << block.BytesUsed()
183                         << " bytes." << endl;
184                 result = PARSE_ERROR;
185                 if (not continueParse) return result;
186         }
187         
188         return result;
189 }
190
191
192 template <typename BlockType>
193 AliHLTUInt32_t CalculateNEntries(BlockType& block, unsigned long bufferSize)
194 {
195         // Calculate how many entries we can display. If the buffer size is correct
196         // we just use the number of entries the block specifies. Otherwise we need
197         // to calculate it from the buffer size.
198         AliHLTUInt32_t nentries;
199         if (block.BytesUsed() == bufferSize)
200         {
201                 nentries = block.Nentries();
202         }
203         else
204         {
205                 AliHLTInt32_t dataSize = bufferSize
206                         - sizeof(typename BlockType::HeaderType);
207                 nentries = dataSize / sizeof(typename BlockType::ElementType);
208                 if (dataSize % sizeof(typename BlockType::ElementType) > 0)
209                         nentries++;
210         }
211         return nentries;
212 }
213
214
215 namespace
216 {
217         /**
218          * Common methods for DDL decoder event handlers.
219          */
220         class AliDecoderHandler
221         {
222         public:
223                 AliDecoderHandler() :
224                         fBufferStart(NULL),
225                         fDumpStart(NULL),
226                         fDumpData(false)
227                 {
228                 }
229                 
230                 virtual ~AliDecoderHandler() {}
231                 
232         protected:
233                 
234                 // Do not allow copying of this class.
235                 AliDecoderHandler(const AliDecoderHandler& obj);
236                 AliDecoderHandler& operator = (const AliDecoderHandler& obj);
237                 
238                 void HandleError(
239                                 const char* errorMessage, int errorCode,
240                                 const char* errorCodeString, const void* location
241                         )
242                 {
243                         unsigned long offset = (unsigned long)location - (unsigned long)fBufferStart
244                                 + sizeof(AliRawDataHeader);
245                         
246                         cerr << "ERROR: " << errorMessage
247                                 << " [Error code = " << errorCode << " ("
248                                 << errorCodeString << "), at byte "
249                                 << offset << " (" << noshowbase << hex << "0x"
250                                 << offset << dec << ")]" << endl;
251                         
252                         if (fDumpStart == NULL) fDumpStart = location;
253                         fDumpData = true;
254                 }
255         
256                 void TryDumpCorruptData(const void* dumpEnd)
257                 {
258                         if (dumpEnd < fDumpStart) return;
259                         if (not fDumpData) return;
260                         
261                         unsigned long startOffset = (unsigned long)fDumpStart - (unsigned long)fBufferStart
262                                 + sizeof(AliRawDataHeader);
263                         unsigned long endOffset = (unsigned long)dumpEnd - (unsigned long)fBufferStart
264                                 + sizeof(AliRawDataHeader);
265                         if (endOffset - startOffset > 264)
266                         {
267                                 endOffset = startOffset + 264;
268                                 dumpEnd = reinterpret_cast<const char*>(fBufferStart) + endOffset;
269                         }
270                         cerr << "Dumping corrupt data words from byte " << startOffset
271                                 << " (" << noshowbase << hex << "0x" << startOffset
272                                 << dec << "), to byte " << endOffset << " (" << noshowbase
273                                 << hex << "0x" << endOffset << dec << "):" << endl;
274                         const UInt_t* start = reinterpret_cast<const UInt_t*>(fDumpStart);
275                         const UInt_t* end = reinterpret_cast<const UInt_t*>(dumpEnd);
276                         cerr << "     Start byte     | Data words" << endl;
277                         for (const UInt_t* current = start; current < end; current++)
278                         {
279                                 unsigned long currentByte = (unsigned long)current
280                                         - (unsigned long)fBufferStart + sizeof(AliRawDataHeader);
281                                 cerr << right << setw(9) << dec << currentByte << setw(0)
282                                         << " 0x" << left << setw(7) << noshowbase << hex
283                                         << currentByte << setw(0) << right << " | ";
284                                 char fillChar = cerr.fill();
285                                 cerr.fill('0');
286                                 for (int i = 0; i < 4 and current < end; i++, current++)
287                                 {
288                                         cerr << noshowbase << hex << "0x" << setw(8)
289                                                 << (*current) << setw(0) << dec << " ";
290                                 }
291                                 cerr.fill(fillChar);
292                                 cerr << endl;
293                         }
294                         fDumpStart = NULL;
295                         fDumpData = false;
296                 }
297                 
298                 const void* fBufferStart;  ///< Start location of buffer.
299                 const void* fDumpStart;  ///< Start location of corrupt data to dump.
300                 bool fDumpData;  ///< Flag indicating if fDumpStart points to corrupt data and should be dumped.
301         };
302
303         /**
304          * Event handler for the tracker DDL decoder.
305          * It simply prints the structure to standard output.
306          */
307         class AliTrackerDecoderHandler :
308                 public AliMUONTrackerDDLDecoderEventHandler, public AliDecoderHandler
309         {
310         public:
311                 AliTrackerDecoderHandler() :
312                         AliMUONTrackerDDLDecoderEventHandler(),
313                         AliDecoderHandler()
314                 {}
315                 
316                 virtual ~AliTrackerDecoderHandler() {}
317         
318                 void OnNewBuffer(const void* buffer, UInt_t /*bufferSize*/)
319                 {
320                         fBufferStart = buffer;
321                 }
322                 
323                 void OnEndOfBuffer(const void* buffer, UInt_t bufferSize)
324                 {
325                         const char* bufferEnd =
326                                 reinterpret_cast<const char*>(buffer) + bufferSize;
327                         TryDumpCorruptData(bufferEnd);
328                 }
329                 
330                 void OnNewBlock(const AliMUONBlockHeaderStruct* header, const void* /*data*/)
331                 {
332                         TryDumpCorruptData(header);
333                         
334                         //TODO print nicely.
335                         cout << "block: " << header << endl;
336                 }
337                 
338                 void OnNewDSP(const AliMUONDSPHeaderStruct* header, const void* /*data*/)
339                 {
340                         TryDumpCorruptData(header);
341                         
342                         //TODO print nicely.
343                         cout << "DSP: " << header << endl;
344                 }
345                 
346                 void OnNewBusPatch(const AliMUONBusPatchHeaderStruct* header, const void* /*data*/)
347                 {
348                         TryDumpCorruptData(header);
349                         
350                         //TODO print nicely.
351                         cout << "buspatch: " << header << endl;
352                 }
353                 
354                 void OnData(UInt_t data, bool parityError)
355                 {
356                         if (parityError)
357                         {
358                                 // TODO complete
359                                 cerr << "Raw data word with parity error" << data << endl;
360                         }
361                         else
362                         {
363                                 //TODO print nicely.
364                                 cout << "data word: 0x" << hex << data << dec << endl;
365                         }
366                 }
367                 
368                 void OnError(ErrorCode error, const void* location)
369                 {
370                         TryDumpCorruptData(location);
371                         HandleError(
372                                 ErrorCodeToMessage(error), error,
373                                 ErrorCodeToString(error), location
374                         );
375                 }
376         };
377
378         /**
379          * Event handler for the trigger DDL decoder.
380          * It simply prints the structure to standard output.
381          */
382         class AliTriggerDecoderHandler :
383                 public AliMUONTriggerDDLDecoderEventHandler, public AliDecoderHandler
384         {
385         public:
386                 AliTriggerDecoderHandler() :
387                         AliMUONTriggerDDLDecoderEventHandler(),
388                         AliDecoderHandler()
389                 {}
390                 
391                 virtual ~AliTriggerDecoderHandler() {}
392         
393                 void OnNewBuffer(const void* buffer, UInt_t /*bufferSize*/)
394                 {
395                         fBufferStart = buffer;
396                 }
397                 
398                 void OnEndOfBuffer(const void* buffer, UInt_t bufferSize)
399                 {
400                         const char* bufferEnd =
401                                 reinterpret_cast<const char*>(buffer) + bufferSize;
402                         TryDumpCorruptData(bufferEnd);
403                 }
404                 
405                 void OnDarcHeader(
406                                 UInt_t header,
407                                 const AliMUONDarcScalarsStruct* scalars,
408                                 const void* data
409                         )
410                 {
411                         if (scalars != NULL)
412                                 TryDumpCorruptData(scalars);
413                         else
414                                 TryDumpCorruptData(data);
415                         
416                         //TODO print nicely.
417                         cout << "DARC header: " << header << endl;
418                 }
419                 
420                 void OnGlobalHeader(
421                                 const AliMUONGlobalHeaderStruct* header,
422                                 const AliMUONGlobalScalarsStruct* /*scalars*/,
423                                 const void* /*data*/
424                         )
425                 {
426                         TryDumpCorruptData(header);
427                         
428                         //TODO print nicely.
429                         cout << "global header: " << header << endl;
430                 }
431                 
432                 void OnNewRegionalStruct(
433                                 const AliMUONRegionalHeaderStruct* regionalStruct,
434                                 const AliMUONRegionalScalarsStruct* /*scalars*/,
435                                 const void* /*data*/
436                         )
437                 {
438                         TryDumpCorruptData(regionalStruct);
439                         
440                         //TODO print nicely.
441                         cout << "regional struct: " << regionalStruct << endl;
442                 }
443                 
444                 void OnLocalStruct(
445                                 const AliMUONLocalInfoStruct* localStruct,
446                                 const AliMUONLocalScalarsStruct* /*scalars*/
447                         )
448                 {
449                         TryDumpCorruptData(localStruct);
450                         
451                         //TODO print nicely.
452                         cout << "local struct: " << localStruct << endl;
453                 }
454                 
455                 void OnError(ErrorCode error, const void* location)
456                 {
457                         TryDumpCorruptData(location);
458                         HandleError(
459                                 ErrorCodeToMessage(error), error,
460                                 ErrorCodeToString(error), location
461                         );
462                 }
463         };
464
465 } // end of namespace
466
467
468 int DumpTrackerDDLRawStream(
469                 const char* buffer, unsigned long bufferSize,
470                 bool continueParse
471         )
472 {
473         // TODO dump the CDH header.
474
475         // Setup the decoder for the DDL payload.
476         AliMUONTrackerDDLDecoder<AliTrackerDecoderHandler> decoder;
477         decoder.ExitOnError(not continueParse);
478         decoder.SendDataOnParityError(false);
479         decoder.TryRecover(false);
480         decoder.AutoDetectTrailer(true);
481         decoder.CheckForTrailer(true);
482         const char* payload = buffer + sizeof(AliRawDataHeader);
483         UInt_t payloadSize = bufferSize - sizeof(AliRawDataHeader);
484         if (decoder.Decode(payload, payloadSize))
485         {
486                 return EXIT_SUCCESS;
487         }
488         else
489         {
490                 return PARSE_ERROR;
491         }
492 }
493
494
495 int DumpTriggerDDLRawStream(
496                 const char* buffer, unsigned long bufferSize,
497                 bool continueParse
498         )
499 {
500         // TODO dump the CDH header.
501         
502         const AliRawDataHeader* header =
503                 reinterpret_cast<const AliRawDataHeader*>(buffer);
504         bool scalarEvent = header->GetL1TriggerMessage() == 0x1;
505         
506         AliMUONTriggerDDLDecoder<AliTriggerDecoderHandler> decoder;
507         decoder.ExitOnError(not continueParse);
508         decoder.TryRecover(false);
509         decoder.AutoDetectScalars(false);
510         const char* payload = buffer + sizeof(AliRawDataHeader);
511         UInt_t payloadSize = bufferSize - sizeof(AliRawDataHeader);
512         if (decoder.Decode(payload, payloadSize, scalarEvent))
513         {
514                 return EXIT_SUCCESS;
515         }
516         else
517         {
518                 return PARSE_ERROR;
519         }
520 }
521
522
523 int DumpRecHitStruct(
524                 const char* buffer, unsigned long bufferSize,
525                 const AliHLTMUONRecHitStruct* hit,
526                 bool continueParse
527         )
528 {
529         // Step through the fields trying to print them.
530         // At each step check if we have not overflowed the buffer. If we have
531         // not, then we can print the field, otherwise we print the left over
532         // bytes assumed to be corrupted rubbish.
533         int result = CheckField(hit->fX, buffer, bufferSize, continueParse);
534         if (result != EXIT_SUCCESS) return result;
535         cout << setw(13) << left << hit->fX << setw(0);
536
537         result = CheckField(hit->fY, buffer, bufferSize, continueParse);
538         if (result != EXIT_SUCCESS) return result;
539         cout << setw(13) << left << hit->fY << setw(0);
540
541         result = CheckField(hit->fZ, buffer, bufferSize, continueParse);
542         if (result != EXIT_SUCCESS) return result;
543         cout << hit->fZ << setw(0) << endl;
544
545         return result;
546 }
547
548
549 int DumpRecHitsBlock(
550                 const char* buffer, unsigned long bufferSize,
551                 bool continueParse
552         )
553 {
554         int result = EXIT_SUCCESS;
555         AliHLTMUONRecHitsBlockReader block(buffer, bufferSize);
556         
557         result = CheckCommonHeader(block, buffer, bufferSize, continueParse);
558         if (result != EXIT_SUCCESS and not continueParse) return result;
559         
560         AliHLTUInt32_t nentries = CalculateNEntries(block, bufferSize);
561         
562         // Print the data block record entries.
563         cout << " X (cm)     | Y (cm)     | Z (cm)" << endl;
564         cout << "---------------------------------------" << endl;
565         const AliHLTMUONRecHitStruct* entry = block.GetArray();
566         for(AliHLTUInt32_t i = 0; i < nentries; i++)
567         {
568                 int subResult = DumpRecHitStruct(buffer, bufferSize, entry++, continueParse);
569                 if (subResult != EXIT_SUCCESS) return subResult;
570         }
571         
572         return result;
573 }
574
575
576 int DumpTriggerRecordStruct(
577                 const char* buffer, unsigned long bufferSize,
578                 const AliHLTMUONTriggerRecordStruct* record,
579                 bool continueParse
580         )
581 {
582         // Step through the fields trying to print them.
583         // At each step check if we have not overflowed the buffer. If we have
584         // not, then we can print the field, otherwise we print the left over
585         // bytes assumed to be corrupted rubbish.
586         int result = CheckField(record->fId, buffer, bufferSize, continueParse);
587         if (result != EXIT_SUCCESS) return result;
588         cout << "Trigger Record ID: " << record->fId <<endl;
589         
590         result = CheckField(record->fFlags, buffer, bufferSize, continueParse);
591         if (result != EXIT_SUCCESS) return result;
592         cout << "Flags: " << showbase << hex << record->fFlags << dec;
593                 
594         // Print the individual trigger bits.
595         AliHLTMUONParticleSign sign;
596         bool hitset[4];
597         AliHLTMUONUtils::UnpackTriggerRecordFlags(record->fFlags, sign, hitset);
598         cout << " [Sign: " << sign << ", Hits set on chambers: ";
599         bool first = true;
600         for (AliHLTUInt32_t i = 0; i < 4; i++)
601         {
602                 if (hitset[i])
603                 {
604                         cout << (first ? "" : ", ") << i+11;
605                         first = false;
606                 }
607         }
608         cout << (first ? "none]" : "]") << endl;
609
610         result = CheckField(record->fPx, buffer, bufferSize, continueParse);
611         if (result != EXIT_SUCCESS) return result;
612         cout << "Momentum: (px = " << record->fPx << ", ";
613
614         result = CheckField(record->fPy, buffer, bufferSize, continueParse);
615         if (result != EXIT_SUCCESS) return result;
616         cout << "py = " << record->fPy << ", ";
617
618         result = CheckField(record->fPz, buffer, bufferSize, continueParse);
619         if (result != EXIT_SUCCESS) return result;
620         cout << "pz = " << record->fPz << ") GeV/c"<<endl;
621         
622         cout << "Track hits:" << endl;
623         cout << "Chamber | X (cm)     | Y (cm)     | Z (cm)" << endl;
624         cout << "------------------------------------------------" << endl;
625         const AliHLTMUONRecHitStruct* hit = &record->fHit[0];
626         for(AliHLTUInt32_t ch = 0; ch < 4; ch++)
627         {
628                 cout << setw(10) << left << ch + 11 << setw(0);
629                 result = DumpRecHitStruct(buffer, bufferSize, hit++, continueParse);
630                 if (result != EXIT_SUCCESS) return result;
631         }
632
633         return result;
634
635 }
636
637
638 int DumpTriggerRecordsBlock(
639                 const char* buffer, unsigned long bufferSize,
640                 bool continueParse
641         )
642 {
643         AliHLTMUONTriggerRecordsBlockReader block(buffer, bufferSize);
644         
645         int result = CheckCommonHeader(block, buffer, bufferSize, continueParse);
646         if (result != EXIT_SUCCESS and not continueParse) return result;
647         
648         AliHLTUInt32_t nentries = CalculateNEntries(block, bufferSize);
649         
650         // Print the data block record entries.
651         const AliHLTMUONTriggerRecordStruct* entry = block.GetArray();
652         for(AliHLTUInt32_t i = 0; i < nentries; i++)
653         {
654                 cout << "============================== Trigger Record number " << i+1
655                         << " of " << nentries << " ==============================" << endl;
656                 int subResult = DumpTriggerRecordStruct(buffer, bufferSize, entry++, continueParse);
657                 if (subResult != EXIT_SUCCESS) return subResult;
658         }
659         
660         return EXIT_SUCCESS;
661 }
662
663
664 int DumpTrigRecInfoStruct(
665                 const char* buffer, unsigned long bufferSize,
666                 const AliHLTMUONTrigRecInfoStruct* debuginfo,
667                 bool continueParse
668         )
669 {
670         // Step through the fields trying to print them.
671         // At each step check if we have not overflowed the buffer. If we have
672         // not, then we can print the field, otherwise we print the left over
673         // bytes assumed to be corrupted rubbish.
674         int result = CheckField(debuginfo->fTrigRecId, buffer, bufferSize, continueParse);
675         if (result != EXIT_SUCCESS) return result;
676         cout << setw(22) << left << debuginfo->fTrigRecId << setw(0);
677
678         result = CheckField(debuginfo->fDetElemId, buffer, bufferSize, continueParse);
679         if (result != EXIT_SUCCESS) return result;
680         cout << setw(20) << left << debuginfo->fDetElemId << setw(0);
681         
682         result = CheckField(debuginfo->fZmiddle, buffer, bufferSize, continueParse);
683         if(result != EXIT_SUCCESS) return result;
684         cout << setw(30) << left << debuginfo->fZmiddle << setw(0);
685
686         result = CheckField(debuginfo->fBl, buffer, bufferSize, continueParse);
687         if (result != EXIT_SUCCESS) return result;
688         cout <<debuginfo->fBl << setw(0) << endl;
689
690         return result;
691 }
692
693
694 int DumpTrigRecsDebugBlock(
695                 const char* buffer, unsigned long bufferSize,
696                 bool continueParse
697         )
698 {
699         AliHLTMUONTrigRecsDebugBlockReader block(buffer, bufferSize);
700         
701         int result = CheckCommonHeader(block, buffer, bufferSize, continueParse);
702         if (result != EXIT_SUCCESS and not continueParse) return result;
703         
704         AliHLTUInt32_t nentries = CalculateNEntries(block, bufferSize);
705         
706         // Print the data block record entries.
707         cout << "Trigger Record ID  | Detector ID  | Momentum X Component (Gev/c) | Integrated Magnetic Field (T.m)" << endl;
708         cout << "--------------------------------------------------------------------------------------------------" << endl;
709         const AliHLTMUONTrigRecInfoStruct* entry = block.GetArray();
710         for(AliHLTUInt32_t i = 0; i < nentries; i++)
711         {
712                 int subResult = DumpTrigRecInfoStruct(buffer, bufferSize, entry++, continueParse);
713                 if (subResult != EXIT_SUCCESS) return subResult;
714         }
715         
716         return EXIT_SUCCESS;
717 }
718
719
720 int DumpTriggerChannelStruct(
721                 const char* buffer, unsigned long bufferSize,
722                 const AliHLTMUONTriggerChannelStruct* triggerchannel,
723                 bool continueParse
724         )
725 {
726         // Step through the fields trying to print them.
727         // At each step check if we have not overflowed the buffer. If we have
728         // not, then we can print the field, otherwise we print the left over
729         // bytes assumed to be corrupted rubbish.
730         int result = CheckField(triggerchannel->fTrigRecId, buffer, bufferSize, continueParse);
731         if (result != EXIT_SUCCESS) return result;
732         cout << setw(25) << left << triggerchannel->fTrigRecId << setw(0);
733
734         result = CheckField(triggerchannel->fChamber, buffer, bufferSize, continueParse);
735         if (result != EXIT_SUCCESS) return result;
736         cout << setw(13) << left << triggerchannel->fChamber << setw(0);
737
738         result = CheckField(triggerchannel->fSignal, buffer, bufferSize, continueParse);
739         if (result != EXIT_SUCCESS) return result;
740         cout << setw(10) << left << triggerchannel->fSignal << setw(0);
741
742         result = CheckField(triggerchannel->fRawDataWord, buffer, bufferSize, continueParse);
743         if(result != EXIT_SUCCESS) return result;
744         cout << showbase << hex << triggerchannel->fRawDataWord << dec << setw(0) << endl;
745         return result;
746 }
747
748
749 int DumpTriggerChannelsBlock(
750                 const char* buffer, unsigned long bufferSize,
751                 bool continueParse
752         )
753 {
754         int result = EXIT_SUCCESS;
755         AliHLTMUONTriggerChannelsBlockReader block(buffer, bufferSize);
756         
757         result = CheckCommonHeader(block, buffer, bufferSize, continueParse);
758         if (result != EXIT_SUCCESS and not continueParse) return result;
759         
760         AliHLTUInt32_t nentries = CalculateNEntries(block, bufferSize);
761         
762         // Print the data block record entries.
763         cout << " Trigger Record ID   | Chamber    | Signal   | Raw Data Word " << endl;
764         cout << "--------------------------------------------------------------" << endl;
765         const AliHLTMUONTriggerChannelStruct* entry = block.GetArray();
766         for(AliHLTUInt32_t i = 0; i < nentries; i++)
767         {
768                 int subResult = DumpTriggerChannelStruct(buffer, bufferSize, entry++, continueParse);
769                 if (subResult != EXIT_SUCCESS) return subResult;
770         }
771
772         return result;
773 }
774
775
776 int DumpClusterStruct(
777                 const char* buffer, unsigned long bufferSize,
778                 const AliHLTMUONClusterStruct* cluster,
779                 bool continueParse
780         )
781 {
782         // Step through the fields trying to print them.
783         // At each step check if we have not overflowed the buffer. If we have
784         // not, then we can print the field, otherwise we print the left over
785         // bytes assumed to be corrupted rubbish.
786         int result = CheckField(cluster->fId, buffer, bufferSize, continueParse);
787         if (result != EXIT_SUCCESS) return result;
788         cout << "cluster->fId: " << cluster->fId << "\t";
789
790         result = CheckField(cluster->fDetElemId, buffer, bufferSize, continueParse);
791         if (result != EXIT_SUCCESS) return result;
792         cout << "cluster->fDetElemId: " << cluster->fDetElemId << "\t";
793
794         result = CheckField(cluster->fNchannels, buffer, bufferSize, continueParse);
795         if(result != EXIT_SUCCESS) return result;
796         cout << "cluster->fNchannels: " << cluster->fNchannels <<endl;
797
798         cout << " Corresponding Hit: "<< endl;
799         cout << " X (cm)     | Y (cm)     | Z (cm)" << endl;
800         cout << "---------------------------------------" << endl;
801         const AliHLTMUONRecHitStruct * hit = & cluster->fHit;
802         result = DumpRecHitStruct(buffer, bufferSize, hit, continueParse);
803
804         return result;
805 }
806
807
808 int DumpClustersBlock(
809                 const char* buffer, unsigned long bufferSize,
810                 bool continueParse
811         )
812 {
813         int result = EXIT_SUCCESS;
814         AliHLTMUONClustersBlockReader block(buffer, bufferSize);
815         
816         result = CheckCommonHeader(block, buffer, bufferSize, continueParse);
817         if (result != EXIT_SUCCESS and not continueParse) return result;
818         
819         AliHLTUInt32_t nentries = CalculateNEntries(block, bufferSize);
820         
821         // Print the data block record entries.
822         const AliHLTMUONClusterStruct* entry = block.GetArray();
823         for(AliHLTUInt32_t i = 0; i < nentries; i++)
824         {
825                 cout << " ===================================================== Cluster Number "
826                         << i+1 << "==================================================" << endl; 
827                 int subResult = DumpClusterStruct(buffer, bufferSize, entry++, continueParse);
828                 if (subResult != EXIT_SUCCESS) return subResult;
829         }       
830
831         return result;
832 }
833
834
835 int DumpChannelStruct(
836                 const char* buffer, unsigned long bufferSize,
837                 const AliHLTMUONChannelStruct* channel,
838                 bool continueParse
839         )
840 {
841         // Step through the fields trying to print them.
842         // At each step check if we have not overflowed the buffer. If we have
843         // not, then we can print the field, otherwise we print the left over
844         // bytes assumed to be corrupted rubbish.
845         int result = CheckField(channel->fClusterId, buffer, bufferSize, continueParse);
846         if (result != EXIT_SUCCESS) return result;
847         cout << setw(16) << left << channel->fClusterId << setw(0);
848
849         result = CheckField(channel->fBusPatch, buffer, bufferSize, continueParse);
850         if (result != EXIT_SUCCESS) return result;
851         cout << setw(16) << left << channel->fBusPatch << setw(0);
852
853         result = CheckField(channel->fManu, buffer, bufferSize, continueParse);
854         if (result != EXIT_SUCCESS) return result;
855         cout << setw(16) << left << channel->fManu << setw(0);
856
857         result = CheckField(channel->fChannelAddress, buffer, bufferSize, continueParse);
858         if (result != EXIT_SUCCESS) return result;
859         cout << setw(16) << left << channel->fChannelAddress << setw(0);
860
861         result = CheckField(channel->fSignal, buffer, bufferSize, continueParse);
862         if(result != EXIT_SUCCESS) return result;
863         cout << setw(16) << left << channel->fSignal << setw(0);
864
865         result = CheckField(channel->fRawDataWord, buffer, bufferSize, continueParse);
866         if(result != EXIT_SUCCESS) return result;
867         cout << showbase << hex << channel->fRawDataWord << dec << setw(0) <<endl;
868
869         return result;
870 }
871
872
873 int DumpChannelsBlock(
874                 const char* buffer, unsigned long bufferSize,
875                 bool continueParse
876         )
877 {
878         int result = EXIT_SUCCESS;
879         AliHLTMUONChannelsBlockReader block(buffer, bufferSize);
880         
881         result = CheckCommonHeader(block, buffer, bufferSize, continueParse);
882         if (result != EXIT_SUCCESS and not continueParse) return result;
883         
884         AliHLTUInt32_t nentries = CalculateNEntries(block, bufferSize);
885         
886         // Print the data block record entries.
887         cout << "Cluster Id    | Bus Patch     | Manu Address  | Channel Addr  | Signal Value  | Raw Data Word " << endl;
888         cout << "----------------------------------------------------------------------------------------------" << endl;
889         const AliHLTMUONChannelStruct* entry = block.GetArray();
890         for(AliHLTUInt32_t i = 0; i < nentries; i++)
891         { 
892                 int subResult = DumpChannelStruct(buffer, bufferSize, entry++, continueParse);
893                 if (subResult != EXIT_SUCCESS) return subResult;
894         }
895         return EXIT_SUCCESS;
896 }
897
898
899 int DumpMansoTrackStruct(
900                 const char* buffer, unsigned long bufferSize,
901                 const AliHLTMUONMansoTrackStruct* track,
902                 bool continueParse
903         )
904 {
905         // Step through the fields trying to print them.
906         // At each step check if we have not overflowed the buffer. If we have
907         // not, then we can print the field, otherwise we print the left over
908         // bytes assumed to be corrupted rubbish.
909         int result = CheckField(track->fId, buffer, bufferSize, continueParse);
910         if (result != EXIT_SUCCESS) return result;
911         cout << "Track ID: " << track->fId << "\t";
912
913         result = CheckField(track->fTrigRec, buffer, bufferSize, continueParse);
914         if (result != EXIT_SUCCESS) return result;
915         cout << "Trigger Record ID: " << track->fTrigRec << endl;
916         
917         result = CheckField(track->fFlags, buffer, bufferSize, continueParse);
918         if (result != EXIT_SUCCESS) return result;
919         cout << "Flags: " << showbase << hex << track->fFlags << dec;
920         
921         // Print the individual trigger bits.
922         AliHLTMUONParticleSign sign;
923         bool hitset[4];
924         AliHLTMUONUtils::UnpackMansoTrackFlags(track->fFlags, sign, hitset);
925         cout << " [Sign: " << sign << ", Hits set on chambers: ";
926         bool first = true;
927         for (AliHLTUInt32_t i = 0; i < 4; i++)
928         {
929                 if (hitset[i])
930                 {
931                         cout << (first ? "" : ", ") << i+7;
932                         first = false;
933                 }
934         }
935         cout << (first ? "none]" : "]") << endl;
936
937         result = CheckField(track->fPx, buffer, bufferSize, continueParse);
938         if (result != EXIT_SUCCESS) return result;
939         cout << "Momentum: (px = " << track->fPx << ", ";
940
941         result = CheckField(track->fPy, buffer, bufferSize, continueParse);
942         if (result != EXIT_SUCCESS) return result;
943         cout << "py = " << track->fPy << ", ";
944
945         result = CheckField(track->fPz, buffer, bufferSize, continueParse);
946         if (result != EXIT_SUCCESS) return result;
947         cout << "pz = " << track->fPz << ") GeV/c\t";
948
949         result = CheckField(track->fChi2, buffer, bufferSize, continueParse);
950         if (result != EXIT_SUCCESS) return result;
951         cout << "Chi squared fit: " << track->fChi2 << endl;
952         
953         cout << "Track hits:" << endl;
954         cout << "Chamber | X (cm)     | Y (cm)     | Z (cm)" << endl;
955         cout << "------------------------------------------------" << endl;
956         const AliHLTMUONRecHitStruct* hit = &track->fHit[0];
957         for(AliHLTUInt32_t ch = 0; ch < 4; ch++)
958         {
959                 cout << setw(10) << left << ch + 7 << setw(0);
960                 result = DumpRecHitStruct(buffer, bufferSize, hit++, continueParse);
961                 if (result != EXIT_SUCCESS) return result;
962         }
963
964         return result;
965 }
966
967
968 int DumpMansoTracksBlock(
969                 const char* buffer, unsigned long bufferSize,
970                 bool continueParse
971         )
972 {
973         int result = EXIT_SUCCESS;
974         AliHLTMUONMansoTracksBlockReader block(buffer, bufferSize);
975         
976         result = CheckCommonHeader(block, buffer, bufferSize, continueParse);
977         if (result != EXIT_SUCCESS and not continueParse) return result;
978         
979         AliHLTUInt32_t nentries = CalculateNEntries(block, bufferSize);
980         
981         // Print the data block record entries.
982         const AliHLTMUONMansoTrackStruct* entry = block.GetArray();
983         for(AliHLTUInt32_t i = 0; i < nentries; i++)
984         {
985                 cout << "============================== Manso track number " << i+1
986                         << " of " << nentries << " ==============================" << endl;
987                 int subResult = DumpMansoTrackStruct(buffer, bufferSize, entry++, continueParse);
988                 if (subResult != EXIT_SUCCESS) return subResult;
989         }
990         
991         return result;
992 }
993
994
995 int DumpMansoRoIStruct(
996                 const char* buffer, unsigned long bufferSize,
997                 const AliHLTMUONMansoRoIStruct* roi,
998                 bool continueParse
999         )
1000 {
1001         // Step through the fields trying to print them.
1002         // At each step check if we have not overflowed the buffer. If we have
1003         // not, then we can print the field, otherwise we print the left over
1004         // bytes assumed to be corrupted rubbish.
1005         int result = CheckField(roi->fX, buffer, bufferSize, continueParse);
1006         if (result != EXIT_SUCCESS) return result;
1007         cout << setw(13) << left << roi->fX << setw(0);
1008
1009         result = CheckField(roi->fY, buffer, bufferSize, continueParse);
1010         if (result != EXIT_SUCCESS) return result;
1011         cout << setw(13) << left << roi->fY << setw(0);
1012
1013         result = CheckField(roi->fZ, buffer, bufferSize, continueParse);
1014         if (result != EXIT_SUCCESS) return result;
1015         cout << setw(13) << left << roi->fZ << setw(0);
1016
1017         result = CheckField(roi->fRadius, buffer, bufferSize, continueParse);
1018         if (result != EXIT_SUCCESS) return result;
1019         cout << roi->fRadius << setw(0) << endl;
1020
1021         return result;
1022 }
1023
1024
1025 int DumpMansoCandidateStruct(
1026                 const char* buffer, unsigned long bufferSize,
1027                 const AliHLTMUONMansoCandidateStruct* candidate,
1028                 bool continueParse
1029         )
1030 {
1031         int result = DumpMansoTrackStruct(buffer, bufferSize, &candidate->fTrack, continueParse);
1032         if (result != EXIT_SUCCESS) return result;
1033         
1034         cout << "Regions of interest:" << endl;
1035         cout << "Chamber | X (cm)     | Y (cm)     | Z (cm)     | Radius (cm)" << endl;
1036         cout << "-------------------------------------------------------------" << endl;
1037         const AliHLTMUONMansoRoIStruct* roi = &candidate->fRoI[0];
1038         for(AliHLTUInt32_t ch = 0; ch < 4; ch++)
1039         {
1040                 cout << setw(10) << ch + 7;
1041                 result = DumpMansoRoIStruct(buffer, bufferSize, roi++, continueParse);
1042                 if (result != EXIT_SUCCESS) return result;
1043         }
1044         return result;
1045 }
1046
1047
1048 int DumpMansoCandidatesBlock(
1049                 const char* buffer, unsigned long bufferSize,
1050                 bool continueParse
1051         )
1052 {
1053         int result = EXIT_SUCCESS;
1054         AliHLTMUONMansoCandidatesBlockReader block(buffer, bufferSize);
1055         
1056         result = CheckCommonHeader(block, buffer, bufferSize, continueParse);
1057         if (result != EXIT_SUCCESS and not continueParse) return result;
1058         
1059         AliHLTUInt32_t nentries = CalculateNEntries(block, bufferSize);
1060         
1061         // Print the data block record entries.
1062         const AliHLTMUONMansoCandidateStruct* entry = block.GetArray();
1063         for(AliHLTUInt32_t i = 0; i < nentries; i++)
1064         {
1065                 cout << "=========================== Manso track candidate number " << i+1
1066                         << " of " << nentries << " ===========================" << endl;
1067                 int subResult = DumpMansoCandidateStruct(buffer, bufferSize, entry++, continueParse);
1068                 if (subResult != EXIT_SUCCESS) return subResult;
1069         }
1070         
1071         return result;
1072 }
1073
1074
1075 int DumpSinglesDecisionBlockHeader(
1076                 const char* buffer, unsigned long bufferSize,
1077                 const AliHLTMUONSinglesDecisionBlockStruct* header,
1078                 bool continueParse
1079         )
1080 {
1081         // Step through the header fields trying to print them.
1082         // At each step check if we have not overflowed the buffer, if we have
1083         // not then we can print the field, otherwise we print the left over
1084         // bytes assumed to be corrupted rubbish.
1085         int result = CheckHeaderField(header->fNlowPt, buffer, bufferSize, continueParse);
1086         if (result != EXIT_SUCCESS) return result;
1087         cout << " Number of low pt triggers: " << header->fNlowPt << endl;
1088         
1089         result = CheckHeaderField(header->fNhighPt, buffer, bufferSize, continueParse);
1090         if (result != EXIT_SUCCESS) return result;
1091         cout << "Number of high pt triggers: " << header->fNhighPt << endl;
1092
1093         return result;
1094 }
1095
1096
1097 int DumpTrackDecisionStruct(
1098                 const char* buffer, unsigned long bufferSize,
1099                 const AliHLTMUONTrackDecisionStruct* decision,
1100                 bool continueParse
1101         )
1102 {
1103         // Step through the fields trying to print them.
1104         // At each step check if we have not overflowed the buffer. If we have
1105         // not, then we can print the field, otherwise we print the left over
1106         // bytes assumed to be corrupted rubbish.
1107         int result = CheckField(decision->fTrackId, buffer, bufferSize, continueParse);
1108         if (result != EXIT_SUCCESS) return result;
1109         cout << setw(13) << left << decision->fTrackId << setw(0);
1110         
1111         result = CheckField(decision->fTriggerBits, buffer, bufferSize, continueParse);
1112         if (result != EXIT_SUCCESS) return result;
1113         cout << setw(12) << left << showbase << hex << decision->fTriggerBits
1114                 << setw(0) << dec;
1115                 
1116         // Print the individual trigger bits.
1117         bool highPt, lowPt;
1118         AliHLTMUONUtils::UnpackTrackDecisionBits(decision->fTriggerBits, highPt, lowPt);
1119         cout << setw(7) << left << (highPt ? "yes" : "no");
1120         cout << setw(8) << left << (lowPt ? "yes" : "no");
1121         
1122         result = CheckField(decision->fPt, buffer, bufferSize, continueParse);
1123         if (result != EXIT_SUCCESS) return result;
1124         cout << setw(0) << decision->fPt << endl;
1125
1126         return result;
1127 }
1128
1129
1130 int DumpSinglesDecisionBlock(
1131                 const char* buffer, unsigned long bufferSize,
1132                 bool continueParse
1133         )
1134 {
1135         int result = EXIT_SUCCESS;
1136         AliHLTMUONSinglesDecisionBlockReader block(buffer, bufferSize);
1137         
1138         result = CheckCommonHeader(block, buffer, bufferSize, continueParse);
1139         if (result != EXIT_SUCCESS and not continueParse) return result;
1140         
1141         // Dump the rest of the block header.
1142         const AliHLTMUONSinglesDecisionBlockStruct* header = &block.BlockHeader();
1143         int subResult = DumpSinglesDecisionBlockHeader(buffer, bufferSize, header, continueParse);
1144         if (subResult != EXIT_SUCCESS) return subResult;
1145         
1146         AliHLTUInt32_t nentries = CalculateNEntries(block, bufferSize);
1147         
1148         // Print the data block record entries.
1149         cout << "           |        Trigger Bits      |" << endl;
1150         cout << "Track ID   | Raw         HighPt LowPt | pT" << endl;
1151         cout << "----------------------------------------------------" << endl;
1152         const AliHLTMUONTrackDecisionStruct* entry = block.GetArray();
1153         for(AliHLTUInt32_t i = 0; i < nentries; i++)
1154         {
1155                 subResult = DumpTrackDecisionStruct(buffer, bufferSize, entry++, continueParse);
1156                 if (subResult != EXIT_SUCCESS) return subResult;
1157         }
1158         
1159         return result;
1160 }
1161
1162
1163 int DumpPairsDecisionBlockHeader(
1164                 const char* buffer, unsigned long bufferSize,
1165                 const AliHLTMUONPairsDecisionBlockStruct* header,
1166                 bool continueParse
1167         )
1168 {
1169         // Step through the header fields trying to print them.
1170         // At each step check if we have not overflowed the buffer, if we have
1171         // not then we can print the field, otherwise we print the left over
1172         // bytes assumed to be corrupted rubbish.
1173         int result = CheckHeaderField(header->fNunlikeAnyPt, buffer, bufferSize, continueParse);
1174         if (result != EXIT_SUCCESS) return result;
1175         cout << "      Number of unlike all pt triggers: " << header->fNunlikeAnyPt << endl;
1176         
1177         result = CheckHeaderField(header->fNunlikeLowPt, buffer, bufferSize, continueParse);
1178         if (result != EXIT_SUCCESS) return result;
1179         cout << "      Number of unlike low pt triggers: " << header->fNunlikeLowPt << endl;
1180         
1181         result = CheckHeaderField(header->fNunlikeHighPt, buffer, bufferSize, continueParse);
1182         if (result != EXIT_SUCCESS) return result;
1183         cout << "     Number of unlike high pt triggers: " << header->fNunlikeHighPt << endl;
1184         
1185         result = CheckHeaderField(header->fNlikeAnyPt, buffer, bufferSize, continueParse);
1186         if (result != EXIT_SUCCESS) return result;
1187         cout << "        Number of like any pt triggers: " << header->fNlikeAnyPt << endl;
1188         
1189         result = CheckHeaderField(header->fNlikeLowPt, buffer, bufferSize, continueParse);
1190         if (result != EXIT_SUCCESS) return result;
1191         cout << "        Number of like low pt triggers: " << header->fNlikeLowPt << endl;
1192         
1193         result = CheckHeaderField(header->fNlikeHighPt, buffer, bufferSize, continueParse);
1194         if (result != EXIT_SUCCESS) return result;
1195         cout << "       Number of like high pt triggers: " << header->fNlikeHighPt << endl;
1196         
1197         result = CheckHeaderField(header->fNmassAny, buffer, bufferSize, continueParse);
1198         if (result != EXIT_SUCCESS) return result;
1199         cout << " Number of all invariant mass triggers: " << header->fNmassAny << endl;
1200         
1201         result = CheckHeaderField(header->fNmassLow, buffer, bufferSize, continueParse);
1202         if (result != EXIT_SUCCESS) return result;
1203         cout << " Number of low invariant mass triggers: " << header->fNmassLow << endl;
1204         
1205         result = CheckHeaderField(header->fNmassHigh, buffer, bufferSize, continueParse);
1206         if (result != EXIT_SUCCESS) return result;
1207         cout << "Number of high invariant mass triggers: " << header->fNmassHigh << endl;
1208         
1209         return result;
1210 }
1211
1212
1213 int DumpPairDecisionStruct(
1214                 const char* buffer, unsigned long bufferSize,
1215                 const AliHLTMUONPairDecisionStruct* decision,
1216                 bool continueParse
1217         )
1218 {
1219         // Step through the fields trying to print them.
1220         // At each step check if we have not overflowed the buffer. If we have
1221         // not, then we can print the field, otherwise we print the left over
1222         // bytes assumed to be corrupted rubbish.
1223         int result = CheckField(decision->fTrackAId, buffer, bufferSize, continueParse);
1224         if (result != EXIT_SUCCESS) return result;
1225         cout << setw(13) << left << decision->fTrackAId << setw(0);
1226         
1227         result = CheckField(decision->fTrackBId, buffer, bufferSize, continueParse);
1228         if (result != EXIT_SUCCESS) return result;
1229         cout << setw(13) << left << decision->fTrackBId << setw(0);
1230         
1231         result = CheckField(decision->fTriggerBits, buffer, bufferSize, continueParse);
1232         if (result != EXIT_SUCCESS) return result;
1233         cout << setw(12) << left << showbase << hex << decision->fTriggerBits
1234                 << setw(0) << dec;
1235                 
1236         // Print the individual trigger bits.
1237         bool highMass, lowMass, unlike;
1238         AliHLTUInt8_t highPtCount, lowPtCount;
1239         AliHLTMUONUtils::UnpackPairDecisionBits(
1240                         decision->fTriggerBits,
1241                         highMass, lowMass, unlike, highPtCount, lowPtCount
1242                 );
1243         cout << setw(7) << left << (highMass ? "yes" : "no");
1244         cout << setw(7) << left << (lowMass ? "yes" : "no");
1245         cout << setw(7) << left << (unlike ? "yes" : "no");
1246         cout << setw(6) << left << AliHLTUInt16_t(highPtCount);
1247         cout << setw(8) << left << AliHLTUInt16_t(lowPtCount);
1248         cout << setw(0);
1249         
1250         result = CheckField(decision->fInvMass, buffer, bufferSize, continueParse);
1251         if (result != EXIT_SUCCESS) return result;
1252         cout << decision->fInvMass << endl;
1253         
1254         return EXIT_SUCCESS;
1255 }
1256
1257
1258 int DumpPairsDecisionBlock(
1259                 const char* buffer, unsigned long bufferSize,
1260                 bool continueParse
1261         )
1262 {
1263         int result = EXIT_SUCCESS;
1264         AliHLTMUONPairsDecisionBlockReader block(buffer, bufferSize);
1265         
1266         result = CheckCommonHeader(block, buffer, bufferSize, continueParse);
1267         if (result != EXIT_SUCCESS and not continueParse) return result;
1268         
1269         // Dump the rest of the block header.
1270         const AliHLTMUONPairsDecisionBlockStruct* header = &block.BlockHeader();
1271         int subResult = DumpPairsDecisionBlockHeader(buffer, bufferSize, header, continueParse);
1272         if (subResult != EXIT_SUCCESS) return subResult;
1273         
1274         AliHLTUInt32_t nentries = CalculateNEntries(block, bufferSize);
1275         
1276         // Print the data block record entries.
1277         cout << "           |            |                Trigger Bits                  |" << endl;
1278         cout << "Track A ID | Track B ID | Raw         HiMass LoMass Unlike HiPt# LoPt# | Invariant mass" << endl;
1279         cout << "----------------------------------------------------------------------------------------" << endl;
1280         const AliHLTMUONPairDecisionStruct* entry = block.GetArray();
1281         for(AliHLTUInt32_t i = 0; i < nentries; i++)
1282         {
1283                 subResult = DumpPairDecisionStruct(buffer, bufferSize, entry++, continueParse);
1284                 if (subResult != EXIT_SUCCESS) return subResult;
1285         }
1286         
1287         return result;
1288 }
1289
1290
1291 int DumpCommonHeader(
1292                 const char* buffer, unsigned long bufferSize,
1293                 const AliHLTMUONDataBlockHeader* header, bool continueParse
1294         )
1295 {
1296         // Step through the header fields trying to print them.
1297         // At each step check if we have not overflowed the buffer, if we have
1298         // not then we can print the field, otherwise we print the left over
1299         // bytes assumed to be corrupted rubbish.
1300         int result = CheckHeaderField(header->fType, buffer, bufferSize, continueParse);
1301         if (result != EXIT_SUCCESS) return result;
1302         AliHLTMUONDataBlockType type = AliHLTMUONDataBlockType(header->fType);
1303         cout << "       Block type: " << type << endl;
1304         
1305         result = CheckHeaderField(header->fRecordWidth, buffer, bufferSize, continueParse);
1306         if (result != EXIT_SUCCESS) return result;
1307         cout << "     Record width: " << header->fRecordWidth << endl;
1308         
1309         result = CheckHeaderField(header->fNrecords, buffer, bufferSize, continueParse);
1310         if (result != EXIT_SUCCESS) return result;
1311         cout << "Number of entries: " << header->fNrecords << endl;
1312         
1313         return result;
1314 }
1315
1316 /**
1317  * Method to look for a certain data word key in the buffer.
1318  * \param buffer  The start location in the buffer to search.
1319  * \param end  The end of the buffer.
1320  * \returns  the pointer position just past the word found or
1321  *     NULL if the word was not found in the buffer.
1322  */
1323 const char* FindDataWord(const char* buffer, const char* end, UInt_t word)
1324 {
1325         for (const char* current = buffer; (current+1) <= end; current += sizeof(UInt_t))
1326         {
1327                 const UInt_t* currentWord = reinterpret_cast<const UInt_t*>(current);
1328                 if (*currentWord == word) return current + sizeof(UInt_t);
1329         }
1330         return NULL;
1331 }
1332
1333 /**
1334  * Method to check if the data buffer is really a raw DDL stream.
1335  * \returns  kUnknownDataBlock if this does not look like a raw DDL stream.
1336  *     kTrackerDDLRawData if this looks like a raw DDL stream from the tracker.
1337  *     kTriggerDDLRawData if this looks like a raw DDL stream from the trigger.
1338  */
1339 int CheckIfDDLStream(const char* buffer, unsigned long bufferSize)
1340 {
1341         if (bufferSize < sizeof(AliRawDataHeader)) return kUnknownDataBlock;
1342         
1343         const AliRawDataHeader* cdhHeader =
1344                 reinterpret_cast<const AliRawDataHeader*>(buffer);
1345         
1346         // Keep scores of indicators / tests that show this is a raw DDL stream
1347         // either from the trigger or tracker. We will decide if the stream is
1348         // indeed a raw DDL stream if the largest of the two scores is above a
1349         // minimum threshold.
1350         int trackerScore = 0;
1351         int triggerScore = 0;
1352         
1353         if (cdhHeader->fSize == UInt_t(-1) or cdhHeader->fSize == bufferSize)
1354         {
1355                 trackerScore++;
1356                 triggerScore++;
1357         }
1358         
1359         if (cdhHeader->GetVersion() == 2)
1360         {
1361                 trackerScore++;
1362                 triggerScore++;
1363         }
1364         
1365         const char* payload = buffer + sizeof(AliRawDataHeader);
1366         const char* payloadEnd = buffer + bufferSize;
1367         
1368         typedef AliMUONTrackerDDLDecoder<AliMUONTrackerDDLDecoderEventHandler> AliTrkDecoder;
1369         typedef AliMUONTriggerDDLDecoder<AliMUONTriggerDDLDecoderEventHandler> AliTrgDecoder;
1370         
1371         // See if the DDL data has a payload with data word keys as expected by
1372         // AliMUONTrackerDDLDecoder.
1373         const char* current = payload;
1374         while ( (current = FindDataWord(current, payloadEnd, AliTrkDecoder::BlockDataKeyWord())) != NULL )
1375         {
1376                 trackerScore++;
1377         }
1378         current = payload;
1379         while ( (current = FindDataWord(current, payloadEnd, AliTrkDecoder::DspDataKeyWord())) != NULL )
1380         {
1381                 trackerScore++;
1382         }
1383         current = payload;
1384         while ( (current = FindDataWord(current, payloadEnd, AliTrkDecoder::BusPatchDataKeyWord())) != NULL )
1385         {
1386                 trackerScore++;
1387         }
1388         current = payload;
1389         while ( (current = FindDataWord(current, payloadEnd, AliTrkDecoder::EndOfDDLWord())) != NULL )
1390         {
1391                 trackerScore++;
1392         }
1393         
1394         // See if the DDL data has a payload with data word keys as expected by
1395         // AliMUONTriggerDDLDecoder.
1396         current = payload;
1397         while ( (current = FindDataWord(current, payloadEnd, AliTrgDecoder::EndOfDarcWord())) != NULL )
1398         {
1399                 triggerScore++;
1400         }
1401         current = payload;
1402         while ( (current = FindDataWord(current, payloadEnd, AliTrgDecoder::EndOfGlobalWord())) != NULL )
1403         {
1404                 triggerScore++;
1405         }
1406         current = payload;
1407         while ( (current = FindDataWord(current, payloadEnd, AliTrgDecoder::EndOfRegionalWord())) != NULL )
1408         {
1409                 triggerScore++;
1410         }
1411         current = payload;
1412         while ( (current = FindDataWord(current, payloadEnd, AliTrgDecoder::EndOfLocalWord())) != NULL )
1413         {
1414                 triggerScore++;
1415         }
1416         
1417         if (triggerScore > trackerScore)
1418         {
1419                 if (triggerScore >= 6) return kTriggerDDLRawData;
1420         }
1421         else
1422         {
1423                 if (trackerScore >= 6) return kTrackerDDLRawData;
1424         }
1425         return kUnknownDataBlock;
1426 }
1427
1428 /**
1429  * Parses the buffer and prints the contents to screen.
1430  * [in] \param buffer  The pointer to the buffer to parse.
1431  * [in] \param bufferSize  The size of the buffer in bytes.
1432  * [in] \param continueParse  If specified then the we try to continue parsing the
1433  *           buffer as much as possible.
1434  * [in/out] \param type  Initialy this should indicate the type of the data block
1435  *           or kUnknownDataBlock if not known. On exit it will be filled with
1436  *           the type of the data block as discovered by this routine if type
1437  *           initially contained kUnknownDataBlock.
1438  * \returns  The error code indicating the problem. EXIT_SUCCESS is returned
1439  *           on success.
1440  */
1441 int ParseBuffer(
1442                 const char* buffer, unsigned long bufferSize,
1443                 bool continueParse, int& type
1444         )
1445 {
1446         assert( buffer != NULL );
1447         int result = EXIT_SUCCESS;
1448         int subResult = EXIT_FAILURE;
1449         
1450         // If the -type|-t option was not used in the command line then we need to
1451         // figure out what type of data block this is from the data itself.
1452         bool ddlStream = false;
1453         if (type == kUnknownDataBlock)
1454         {
1455                 // First check if this is a raw DDL stream, if not then assume it is
1456                 // some kind of internal dHLT raw data block.
1457                 int streamType = CheckIfDDLStream(buffer, bufferSize);
1458                 if (streamType == kTrackerDDLRawData or streamType == kTriggerDDLRawData)
1459                 {
1460                         type = streamType;
1461                         ddlStream = true;
1462                 }
1463         }
1464         else if (type == kTrackerDDLRawData or type == kTriggerDDLRawData)
1465         {
1466                 ddlStream = true;
1467         }
1468         
1469         if (not ddlStream)
1470         {
1471                 if (bufferSize < sizeof(AliHLTMUONDataBlockHeader))
1472                 {
1473                         cerr << "ERROR: The size of the file is too small to contain a"
1474                                 " valid data block." << endl;
1475                         result = PARSE_ERROR;
1476                         if (not continueParse) return result;
1477                 }
1478                 const AliHLTMUONDataBlockHeader* header =
1479                         reinterpret_cast<const AliHLTMUONDataBlockHeader*>(buffer);
1480         
1481                 subResult = DumpCommonHeader(buffer, bufferSize, header, continueParse);
1482                 if (subResult != EXIT_SUCCESS) return subResult;
1483         
1484                 
1485                 // Check if the block type in the header corresponds to the type given
1486                 // by the '-type' command line parameter. If they do not then print an
1487                 // error or big fat warning message and force interpretation of the data
1488                 // block with the type given by '-type'.
1489                 AliHLTMUONDataBlockType headerType = AliHLTMUONDataBlockType(header->fType);
1490                 
1491                 if (type == kUnknownDataBlock)
1492                 {
1493                         // -type not used in the command line so just use what is given
1494                         // by the data block header.
1495                         type = headerType;
1496                 }
1497                 else if (type != headerType)
1498                 {
1499                         cerr << "WARNING: The data block header indicates a type"
1500                                 " different from what was specified on the command line."
1501                                 " The data could be corrupt."
1502                                 << endl;
1503                         cerr << "WARNING: The type value in the file is "
1504                                 << showbase << hex << header->fType
1505                                 << " (" << headerType << "), but on the command line it is "
1506                                 << showbase << hex << int(type) << dec
1507                                 << " (" << type << ")."
1508                                 << endl;
1509                         cerr << "WARNING: Will force the interpretation of the data block"
1510                                 " with a type of " << type << "." << endl;
1511                 }
1512         }
1513         
1514         // Now we know what type the data block is supposed to be, so we can
1515         // dump it to screen with the appropriate dump routine.
1516         switch (type)
1517         {
1518         case kTrackerDDLRawData:
1519                 subResult = DumpTrackerDDLRawStream(buffer, bufferSize, continueParse);
1520                 if (subResult != EXIT_SUCCESS) result = subResult;
1521                 break;
1522         case kTriggerDDLRawData:
1523                 subResult = DumpTriggerDDLRawStream(buffer, bufferSize, continueParse);
1524                 if (subResult != EXIT_SUCCESS) result = subResult;
1525                 break;
1526         case kTriggerRecordsDataBlock:
1527                 subResult = DumpTriggerRecordsBlock(buffer, bufferSize, continueParse);
1528                 if (subResult != EXIT_SUCCESS) result = subResult;
1529                 break;
1530         case kTrigRecsDebugDataBlock:
1531                 subResult = DumpTrigRecsDebugBlock(buffer, bufferSize, continueParse);
1532                 if (subResult != EXIT_SUCCESS) result = subResult;
1533                 break;
1534         case kTriggerChannelsDataBlock:
1535                 subResult = DumpTriggerChannelsBlock(buffer, bufferSize, continueParse);
1536                 if (subResult != EXIT_SUCCESS) result = subResult;
1537                 break;
1538         case kRecHitsDataBlock:
1539                 subResult = DumpRecHitsBlock(buffer, bufferSize, continueParse);
1540                 if (subResult != EXIT_SUCCESS) result = subResult;
1541                 break;
1542         case kClustersDataBlock:
1543                 subResult = DumpClustersBlock(buffer, bufferSize, continueParse);
1544                 if (subResult != EXIT_SUCCESS) result = subResult;
1545                 break;
1546         case kChannelsDataBlock:
1547                 return DumpChannelsBlock(buffer, bufferSize, continueParse);
1548                 if (subResult != EXIT_SUCCESS) result = subResult;
1549                 break;
1550         case kMansoTracksDataBlock:
1551                 subResult = DumpMansoTracksBlock(buffer, bufferSize, continueParse);
1552                 if (subResult != EXIT_SUCCESS) result = subResult;
1553                 break;
1554         case kMansoCandidatesDataBlock:
1555                 subResult = DumpMansoCandidatesBlock(buffer, bufferSize, continueParse);
1556                 if (subResult != EXIT_SUCCESS) result = subResult;
1557                 break;
1558         case kSinglesDecisionDataBlock:
1559                 subResult = DumpSinglesDecisionBlock(buffer, bufferSize, continueParse);
1560                 if (subResult != EXIT_SUCCESS) result = subResult;
1561                 break;
1562         case kPairsDecisionDataBlock:
1563                 return DumpPairsDecisionBlock(buffer, bufferSize, continueParse);
1564                 if (subResult != EXIT_SUCCESS) result = subResult;
1565                 break;
1566         default :
1567                 cout << "ERROR: Unknown data block type. Found a type number of "
1568                         << showbase << hex << int(type) << dec
1569                         << " (" << int(type) << ")." << endl;
1570                 result = PARSE_ERROR;
1571         }
1572         
1573         return result;
1574 }
1575
1576 /**
1577  * Convert the type code to a string.
1578  */
1579 const char* TypeToString(int type)
1580 {
1581         if (type == kTrackerDDLRawData or type == kTriggerDDLRawData)
1582         {
1583                 static char str[kAliHLTComponentDataTypefIDsize+1];
1584                 AliHLTComponentDataType t = AliHLTMUONConstants::DDLRawDataType();
1585                 memcpy(&str, &t.fID, kAliHLTComponentDataTypefIDsize);
1586                 // Must insert the NULL character to make this an ANSI C string.
1587                 str[kAliHLTComponentDataTypefIDsize] = '\0';
1588                 return &str[0];
1589         }
1590         else
1591         {
1592                 return AliHLTMUONUtils::DataBlockTypeToString(AliHLTMUONDataBlockType(type));
1593         }
1594 }
1595
1596 /**
1597  * Find the data specification from the filename and return it in string format.
1598  */
1599 const char* TryDecodeDataSpec(const char* filename)
1600 {
1601         TString name = filename;
1602         
1603         TRegexp re1("MUONTR[GK]_[0123456789]+\\.ddl$");
1604         Ssiz_t length = 0;
1605         Ssiz_t pos = re1.Index(name, &length);
1606         if (pos != kNPOS)
1607         {
1608                 TString substr;
1609                 for (Ssiz_t i = 0; i < length; i++)
1610                         substr += name[pos+i];
1611                 TRegexp re("[0123456789]+");
1612                 pos = re.Index(substr, &length);
1613                 TString num;
1614                 for (Ssiz_t i = 0; i < length; i++)
1615                         num += substr[pos+i];
1616                 AliHLTUInt32_t spec = AliHLTMUONUtils::EquipIdToSpec(num.Atoi());
1617                 static char strbuf[32];
1618                 sprintf(&strbuf[0], "0x%8.8X", spec);
1619                 return &strbuf[0];
1620         }
1621         
1622         TRegexp re2("_MUON\\:.+_0x[0123456789abscefABCDEF]+\\.dat$");
1623         pos = re2.Index(name, &length);
1624         if (pos != kNPOS)
1625         {
1626                 TString substr;
1627                 for (Ssiz_t i = 0; i < length; i++)
1628                         substr += name[pos+i];
1629                 TRegexp re("0x[0123456789abscefABCDEF]+");
1630                 pos = re.Index(substr, &length);
1631                 TString num;
1632                 for (Ssiz_t i = 0; i < length; i++)
1633                         num += substr[pos+i];
1634                 static TString result = num;
1635                 return result.Data();
1636         }
1637         
1638         return NULL;
1639 }
1640
1641 /**
1642  * Performs basic data integrity checks of the data block using the
1643  * AliHLTMUONDataCheckerComponent.
1644  * [in] \param sys  The HLT system framework.
1645  * [in] \param filename  The name of the file containing the data block to check.
1646  * [in] \param type  Must indicate the type of the data block.
1647  * [in] \param dataspec The data specification of the data block. NULL if none.
1648  * [in] \param maxLogging  If set to true then full logging is turned on for AliHLTSystem.
1649  * \returns  The error code indicating the problem. EXIT_SUCCESS is returned
1650  *           on success.
1651  */
1652 int CheckDataIntegrity(
1653                 AliHLTSystem& sys, const char* filename, int type,
1654                 const char* dataspec, bool maxLogging
1655         )
1656 {
1657         if (maxLogging)
1658         {
1659                 AliLog::SetGlobalLogLevel(AliLog::kMaxType);
1660                 sys.SetGlobalLoggingLevel(kHLTLogAll);
1661         }
1662         else
1663         {
1664                 AliLog::SetGlobalLogLevel(AliLog::kWarning);
1665                 int level = kHLTLogWarning | kHLTLogError | kHLTLogFatal;
1666                 sys.SetGlobalLoggingLevel(AliHLTComponentLogSeverity(level));
1667         }
1668         
1669         // Check if required libraries are there and load them if not.
1670         if (gClassTable->GetID("AliHLTAgentUtil") < 0)
1671         {
1672                 sys.LoadComponentLibraries("libAliHLTUtil.so");
1673         }
1674         if (gClassTable->GetID("AliHLTMUONAgent") < 0)
1675         {
1676                 sys.LoadComponentLibraries("libAliHLTMUON.so");
1677         }
1678         
1679         // Setup the component parameter lists and then the components.
1680         TString dcparams = "-return_error -warn_on_unexpected_block -no_global_check";
1681         TString fpparams = "-datatype '";
1682         fpparams += TypeToString(type);
1683         fpparams += "' 'MUON'";
1684         if (dataspec != NULL)
1685         {
1686                 fpparams += " -dataspec ";
1687                 fpparams += dataspec;
1688         }
1689         else
1690         {
1691                 const char* spec = TryDecodeDataSpec(filename);
1692                 if (spec != NULL)
1693                 {
1694                         fpparams += " -dataspec ";
1695                         fpparams += spec;
1696                 }
1697                 else
1698                 {
1699                         dcparams += " -ignorespec";
1700                 }
1701         }
1702         fpparams += " -datafile ";
1703         fpparams += filename;
1704         TString fpname = "filePublisher_";
1705         fpname += filename;
1706         TString dcname = "checker_";
1707         dcname += filename;
1708         
1709         if (maxLogging)
1710         {
1711                 cout << "DEBUG: Using the following flags for FilePublisher: \""
1712                         << fpparams.Data() << "\""<< endl;
1713                 cout << "DEBUG: Using the following flags for "
1714                         << AliHLTMUONConstants::DataCheckerComponentId()
1715                         << ": \"" << dcparams.Data() << "\""<< endl;
1716         }
1717         
1718         AliHLTConfiguration(fpname.Data(), "FilePublisher", NULL, fpparams.Data());
1719         AliHLTConfiguration checker(
1720                         dcname.Data(), AliHLTMUONConstants::DataCheckerComponentId(),
1721                         fpname.Data(), dcparams.Data()
1722                 );
1723         
1724         // Build and run the HLT tasks.
1725         if (sys.BuildTaskList(dcname.Data()) != 0) return HLTSYSTEM_ERROR;
1726         if (maxLogging) sys.PrintTaskList();
1727         if (sys.Run() != 1) return HLTSYSTEM_ERROR;
1728         
1729         // Now clean up.
1730         if (sys.CleanTaskList() != 0) return HLTSYSTEM_ERROR;
1731
1732         return EXIT_SUCCESS;
1733 }
1734
1735
1736 /**
1737  * The caller is responsible for freeing memory allocated for buffer with a call
1738  * to delete [] buffer.
1739  */
1740 int ReadFile(const char* filename, char*& buffer, unsigned long& bufferSize)
1741 {
1742         assert( filename != NULL );
1743         
1744         // Open the file and find its size.
1745         fstream file;
1746         file.open(filename, ios::in);
1747         if (not file)
1748         {
1749                 cerr << "ERROR: Could not open the file: " << filename << endl;
1750                 return SYSTEM_ERROR;
1751         }
1752         file.seekg(0, ios::end);
1753         if (not file)
1754         {
1755                 cerr << "ERROR: Could not seek in the file: " << filename << endl;
1756                 return SYSTEM_ERROR;
1757         }
1758         bufferSize = file.tellg();
1759         if (not file)
1760         {
1761                 cerr << "ERROR: Could not get file size for the file: " <<
1762                         filename << endl;
1763                 return SYSTEM_ERROR;
1764         }
1765         file.seekg(0, ios::beg);
1766         if (not file)
1767         {
1768                 cerr << "ERROR: Could not seek in the file: " << filename << endl;
1769                 return SYSTEM_ERROR;
1770         }
1771         
1772         // Allocate the memory for the file.
1773         try
1774         {
1775                 buffer = new char[bufferSize];
1776         }
1777         catch (const std::bad_alloc&)
1778         {
1779                 cerr << "ERROR: Out of memory. Tried to allocate " << bufferSize
1780                         << " bytes." << endl;
1781                 return SYSTEM_ERROR;
1782         }
1783         
1784         file.read(buffer, bufferSize);
1785         if (not file)
1786         {
1787                 delete [] buffer;
1788                 buffer = NULL;
1789                 bufferSize = 0;
1790                 cerr << "ERROR: Could not read from file: " << filename << endl;
1791                 return SYSTEM_ERROR;
1792         }
1793         
1794         file.close();
1795         if (not file)
1796         {
1797                 delete [] buffer;
1798                 buffer = NULL;
1799                 bufferSize = 0;
1800                 cerr << "ERROR: Could not close the file: " << filename << endl;
1801                 return SYSTEM_ERROR;
1802         }
1803         
1804         return EXIT_SUCCESS;
1805 }
1806
1807 /**
1808  * Prints the command line usage of this program to standard error.
1809  */
1810 void PrintUsage(bool asError = true)
1811 {
1812         std::ostream& os = asError ? cerr : cout;
1813         os << "Usage: dHLTdumpraw [-help|-h] [-continue|-c] [-type|-t <typename>] [-check|-k]" << endl;
1814         os << "         [-debug|-d] [-dataspec|-s <number>] <filename> [<filename> ...]" << endl;
1815         os << "Where <filename> is the name of a file containing a raw data block." << endl;
1816         os << "Options:" << endl;
1817         os << " -help | -h" << endl;
1818         os << "       Displays this message." << endl;
1819         os << " -continue | -c" << endl;
1820         os << "       If specified, the program will try to continue parsing the data block" << endl;
1821         os << "       as much as possible rather than stopping at the first error." << endl;
1822         os << " -type | -t <typename>" << endl;
1823         os << "       Forces the contents of the subsequent files specified on the command" << endl;
1824         os << "       line to be interpreted as a specific type of data block." << endl;
1825         os << "       Where <typename> can be one of:" << endl;
1826         os << "         rawtracker - raw DDL stream from tracker chambers." << endl;
1827         os << "         rawtrigger - raw DDL stream from trigger chambers." << endl;
1828         os << "         trigrecs - trigger records data." << endl;
1829         os << "         trigrecsdebug - debugging information about trigger records." << endl;
1830         os << "         trigchannels - channel debugging in." << endl;
1831         os << "         rechits - reconstructed hits data." << endl;
1832         os << "         channels - channel debugging information from hit reconstruction." << endl;
1833         os << "         clusters - cluster debugging information from hit reconstruction." << endl;
1834         os << "         mansotracks - partial tracks from Manso algorithm." << endl;
1835         os << "         mansocandidates - track candidates considered in the Manso algorithm." << endl;
1836         os << "         singlesdecision - trigger decisions for single tracks." << endl;
1837         os << "         pairsdecision - trigger decisions for track pairs." << endl;
1838         os << "         autodetect - the type of the data block will be automatically" << endl;
1839         os << "                      detected." << endl;
1840         os << " -check | -k" << endl;
1841         os << "       If specified then data integrity checks are performed on the raw data." << endl;
1842         os << "       Warnings and errors are printed as problems are found with the data, but" << endl;
1843         os << "       the data will still be converted into ROOT objects as best as possible." << endl;
1844         os << " -debug | -d" << endl;
1845         os << "       If specified, then the all debug messages are printed by the AliHLTSystem." << endl;
1846         os << "       This is only useful if experiencing problems with the -check|-k option." << endl;
1847         os << " -dataspec | -s <number>" << endl;
1848         os << "       When specified, then <number> is used as the data specification for the" << endl;
1849         os << "       data file that follows. This option is only useful with the -check|-k option." << endl;
1850 }
1851
1852 /**
1853  * Parses the command line.
1854  * @param argc  Number of arguments as given in main().
1855  * @param argv  Array of arguments as given in main().
1856  * @param filenames  Pointer to buffer storing file name strings.
1857  * @param filetypes  Array that receives the type of the data block expected, i.e.
1858  *                   the value of the -type flag for the corresponding file.
1859  * @param dataspecs  Data specifications to use for the data files.
1860  * @param numOfFiles  Receives the number of file name strings that were found
1861  *                    and added to 'filenames'.
1862  * @param continueParse  Set to true if the user requested to continue to parse
1863  *                      after errors.
1864  * @param checkData  Set to true if data integrity checking was requested.
1865  * @param maxLogging  Set to true if maximal logging was requested.
1866  * @return  A status flag suitable for returning from main(), containing either
1867  *          EXIT_SUCCESS or CMDLINE_ERROR.
1868  */
1869 int ParseCommandLine(
1870                 int argc,
1871                 const char** argv,
1872                 const char** filenames,
1873                 int* filetypes,
1874                 const char** dataspecs,
1875                 int& numOfFiles,
1876                 bool& continueParse,
1877                 bool& checkData,
1878                 bool& maxLogging
1879         )
1880 {
1881         numOfFiles = 0;
1882         continueParse = false;
1883         maxLogging = false;
1884         checkData = false;
1885         int currentType = kUnknownDataBlock;
1886         const char* currentDataSpec = NULL;
1887
1888         // Parse the command line.
1889         for (int i = 1; i < argc; i++)
1890         {
1891                 if (strcmp(argv[i], "-help") == 0 or strcmp(argv[i], "-h") == 0)
1892                 {
1893                         PrintUsage(false);
1894                         return EXIT_SUCCESS;
1895                 }
1896                 else if (strcmp(argv[i], "-continue") == 0 or strcmp(argv[i], "-c") == 0)
1897                 {
1898                         continueParse = true;
1899                 }
1900                 else if (strcmp(argv[i], "-type") == 0 or strcmp(argv[i], "-t") == 0)
1901                 {
1902                         if (++i >= argc)
1903                         {
1904                                 cerr << "ERROR: Missing a type specifier." << endl << endl;
1905                                 PrintUsage();
1906                                 return CMDLINE_ERROR;
1907                         }
1908                         // Now we need to parse the typename in the command line.
1909                         if (strcmp(argv[i], "autodetect") == 0)
1910                         {
1911                                 currentType = kUnknownDataBlock;
1912                         }
1913                         else if (strcmp(argv[i], "rawtracker") == 0)
1914                         {
1915                                 currentType = kTrackerDDLRawData;
1916                         }
1917                         else if (strcmp(argv[i], "rawtrigger") == 0)
1918                         {
1919                                 currentType = kTriggerDDLRawData;
1920                         }
1921                         else
1922                         {
1923                                 currentType = AliHLTMUONUtils::ParseCommandLineTypeString(argv[i]);
1924                                 if (currentType == kUnknownDataBlock)
1925                                 {
1926                                         cerr << "ERROR: Invalid type name '" << argv[i]
1927                                                 << "' specified for argument " << argv[i-1]
1928                                                 << "." << endl << endl;
1929                                         PrintUsage();
1930                                         return CMDLINE_ERROR;
1931                                 }
1932                         }
1933                 }
1934                 else if (strcmp(argv[i], "-debug") == 0 or strcmp(argv[i], "-d") == 0)
1935                 {
1936                         maxLogging = true;
1937                 }
1938                 else if (strcmp(argv[i], "-check") == 0 or strcmp(argv[i], "-k") == 0)
1939                 {
1940                         checkData = true;
1941                 }
1942                 else if (strcmp(argv[i], "-dataspec") == 0 or strcmp(argv[i], "-s") == 0)
1943                 {
1944                         if (++i >= argc)
1945                         {
1946                                 cerr << "ERROR: Missing a specification number." << endl << endl;
1947                                 PrintUsage();
1948                                 return CMDLINE_ERROR;
1949                         }
1950                         
1951                         char* errPos = NULL;
1952                         unsigned long num = strtoul(argv[i], &errPos, 0);
1953                         if (errPos == NULL or *errPos != '\0')
1954                         {
1955                                 cerr << "ERROR: Cannot convert '%s' to a data specification number."
1956                                         << argv[i] << endl;
1957                                 return CMDLINE_ERROR;
1958                         }
1959                         if (not AliHLTMUONUtils::IsSpecValid(num))
1960                         {
1961                                 cerr << "ERROR: The data specification number is not a valid format."
1962                                         << endl;
1963                                 return CMDLINE_ERROR;
1964                         }
1965                         currentDataSpec = argv[i];
1966                 }
1967                 else
1968                 {
1969                         assert( numOfFiles < argc );
1970                         filenames[numOfFiles] = argv[i];
1971                         filetypes[numOfFiles] = currentType;
1972                         dataspecs[numOfFiles] = currentDataSpec;
1973                         currentDataSpec = NULL;  // Reset because '-dataspec' option is only valid for one file.
1974                         numOfFiles++;
1975                 }
1976         }
1977         
1978         // Now check that we have at least one filename and all the flags we need.
1979         if (numOfFiles == 0)
1980         {
1981                 cerr << "ERROR: Missing a file name. You must specify at least one file to process."
1982                         << endl << endl;
1983                 PrintUsage();
1984                 return CMDLINE_ERROR;
1985         }
1986         
1987         return EXIT_SUCCESS;
1988 }
1989
1990
1991 int main(int argc, const char** argv)
1992 {
1993         // Test endianess of this machine during runtime and print warning if it is not
1994         // little endian.
1995         union
1996         {
1997                 int dword;
1998                 char byte[4];
1999         } endianTest;
2000         endianTest.dword = 0x1;
2001         if (endianTest.byte[0] != 0x1)
2002         {
2003                 cerr << "!!!! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !!!!!" << endl;
2004                 cerr << "!!!! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !!!!!" << endl;
2005                 cerr << "!!                                                                     !!" << endl;
2006                 cerr << "!! This is not a little endian machine, but dHLT raw data is normally  !!" << endl;
2007                 cerr << "!! generated in little endian format. Unless you are looking at localy !!" << endl;
2008                 cerr << "!! created simulated data, then this program will not show you correct !!" << endl;
2009                 cerr << "!! output.                                                             !!" << endl;
2010                 cerr << "!!                                                                     !!" << endl;
2011                 cerr << "!!!! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !!!!!" << endl;
2012                 cerr << "!!!! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !!!!!" << endl;
2013                 cerr << endl;
2014         }
2015
2016
2017         int numOfFiles = 0;
2018         bool continueParse = false;
2019         bool checkData = false;
2020         bool maxLogging = false;
2021         int returnCode = EXIT_SUCCESS;
2022         char* buffer = NULL;
2023         const char** filename = NULL;
2024         int* filetype = NULL;
2025         const char** dataspec = NULL;
2026
2027         try
2028         {
2029                 // Reduce logging now to get rid of informationals from AliHLTSystem constructor.
2030                 AliLog::SetGlobalLogLevel(AliLog::kWarning);
2031                 AliHLTSystem sys;
2032         
2033                 // There will be at least 'argc' number of filenames.
2034                 typedef const char* AnsiString;
2035                 filename = new AnsiString[argc];
2036                 filetype = new int[argc];
2037                 dataspec = new AnsiString[argc];
2038                 
2039                 returnCode = ParseCommandLine(
2040                                 argc, argv, filename, filetype, dataspec, numOfFiles,
2041                                 continueParse, checkData, maxLogging
2042                         );
2043
2044                 if (returnCode == EXIT_SUCCESS)
2045                 {
2046                         for (int i = 0; i < numOfFiles; i++)
2047                         {
2048                                 unsigned long bufferSize = 0;
2049                                 returnCode = ReadFile(filename[i], buffer, bufferSize);
2050                                 if (returnCode != EXIT_SUCCESS) break;
2051                                 if (numOfFiles > 1)
2052                                 {
2053                                         cout << "########## Start of dump for file: "
2054                                                 << filename[i] << " ##########" << endl;
2055                                 }
2056                                 int result = ParseBuffer(buffer, bufferSize, continueParse, filetype[i]);
2057                                 if (buffer != NULL) delete [] buffer;
2058                                 if (result != EXIT_SUCCESS)
2059                                 {
2060                                         returnCode = result;
2061                                         if (not continueParse) break;
2062                                 }
2063                                 if (checkData)
2064                                 {
2065                                         result = CheckDataIntegrity(
2066                                                         sys, filename[i], filetype[i],
2067                                                         dataspec[i], maxLogging
2068                                                 );
2069                                         if (result != EXIT_SUCCESS)
2070                                         {
2071                                                 returnCode = result;
2072                                                 if (not continueParse) break;
2073                                         }
2074                                 }
2075                                 if (numOfFiles > 1)
2076                                 {
2077                                         cout << "##########   End of dump for file: " <<
2078                                                 filename[i] << " ##########" << endl;
2079                                 }
2080                         }
2081                 }
2082                 
2083                 delete [] filename;
2084                 delete [] filetype;
2085                 delete [] dataspec;
2086         }
2087         catch (...)
2088         {
2089                 cerr << "FATAL ERROR: An unknown exception occurred!" << endl << endl;
2090                 returnCode = FATAL_ERROR;
2091                 if (buffer != NULL) delete [] buffer;
2092                 if (filename != NULL) delete [] filename;
2093                 if (filetype != NULL) delete [] filetype;
2094                 if (dataspec != NULL) delete [] dataspec;
2095         }
2096         
2097         return returnCode;
2098 }