LCOV - code coverage report
Current view: top level - MUON/MUONraw - AliMUONTrackerDDLDecoderEventHandler.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 9 74 12.2 %
Date: 2016-06-14 17:26:59 Functions: 6 15 40.0 %

          Line data    Source code
       1             : #ifndef ALIMUONTRACKERDDLDECODEREVENTHANDLER_H
       2             : #define ALIMUONTRACKERDDLDECODEREVENTHANDLER_H
       3             : /**************************************************************************
       4             :  * This file is property of and copyright by the ALICE HLT Project        *
       5             :  * All rights reserved.                                                   *
       6             :  *                                                                        *
       7             :  * Primary Authors:                                                       *
       8             :  *   Artur Szostak <artursz@iafrica.com>                                  *
       9             :  *                                                                        *
      10             :  * Permission to use, copy, modify and distribute this software and its   *
      11             :  * documentation strictly for non-commercial purposes is hereby granted   *
      12             :  * without fee, provided that the above copyright notice appears in all   *
      13             :  * copies and that both the copyright notice and this permission notice   *
      14             :  * appear in the supporting documentation. The authors make no claims     *
      15             :  * about the suitability of this software for any purpose. It is          *
      16             :  * provided "as is" without express or implied warranty.                  *
      17             :  **************************************************************************/
      18             : 
      19             : /* $Id$ */
      20             : 
      21             : ///
      22             : /// \file   AliMUONTrackerDDLDecoderEventHandler.h
      23             : /// \author Artur Szostak <artursz@iafrica.com>
      24             : /// \date   28-11-2007
      25             : /// \brief  Implementation of a high performance DDL decoder event handler 
      26             : /// for the muon tracking stations.
      27             : ///
      28             : 
      29             : #include <cassert>
      30             : #include <ostream>
      31             : #include <Rtypes.h>
      32             : 
      33             : 
      34             : // We use C binding for the structures because C is more uniform with its application
      35             : // binary interface (ABI) between compilers.
      36             : extern "C"
      37             : {
      38             : 
      39             : // The following structures are the headers found in the DDL payload from the
      40             : // muon tracking chambers. The specification is defined in ALICE-INT-2005-012
      41             : // (https://edms.cern.ch/file/591904/1/ALICE-INT-2005-012.pdf)
      42             : 
      43             : /// The block header structure of the Tracker DDL payload.
      44             : struct AliMUONBlockHeaderStruct
      45             : {
      46             :         UInt_t     fDataKey;        ///< Data key word for CRT header 
      47             :         UInt_t     fTotalLength;    ///< total length of block structure (w/o padding word)
      48             :         UInt_t     fLength;         ///< length of raw data
      49             :         UInt_t     fDSPId;          ///< DSP id
      50             :         UInt_t     fL0Trigger;      ///< L0 trigger word
      51             :         UInt_t     fMiniEventId;    ///< Bunch Crossing for mini-event id (see TDR chapter 8)
      52             :         UInt_t     fEventId1;       ///< Event Id in bunch crossing
      53             :         UInt_t     fEventId2;       ///< Event Id in orbit number
      54             : };
      55             : 
      56             : /// The DSP header structure of the Tracker DDL payload.
      57             : struct AliMUONDSPHeaderStruct
      58             : {
      59             :         UInt_t     fDataKey;          ///< Data key word for FRT header 
      60             :         UInt_t     fTotalLength;      ///< total length of block structure
      61             :         UInt_t     fLength;           ///< length of raw data
      62             :         UInt_t     fDSPId;            ///< DSP id
      63             :         UInt_t     fBlkL1ATrigger;    ///< L1 accept in Block Structure (CRT)
      64             :         UInt_t     fMiniEventId;      ///< Mini Event Id in bunch crossing 
      65             :         UInt_t     fL1ATrigger;       ///< Number of L1 accept in DSP Structure (FRT)
      66             :         UInt_t     fL1RTrigger;       ///< Number of L1 reject in DSP Structure (FRT)
      67             :         UInt_t     fPaddingWord;      ///< padding dummy word for 64 bits transfer
      68             :         UInt_t     fErrorWord;        ///< Error word
      69             : };
      70             : 
      71             : /// The bus patch header structure of the Tracker DDL payload.
      72             : struct AliMUONBusPatchHeaderStruct
      73             : {
      74             :         UInt_t     fDataKey;       ///< Data key word for bus patch header 
      75             :         UInt_t     fTotalLength;   ///< total length of bus patch structure
      76             :         UInt_t     fLength;        ///< length of raw data
      77             :         UInt_t     fBusPatchId;    ///< bus patch id
      78             : };
      79             : 
      80             : } // extern "C"
      81             : 
      82             : 
      83             : /// \ingroup raw
      84             : /// \class AliMUONTrackerDDLDecoderEventHandler
      85             : /// \brief Callback event handler class for the AliMUONTrackerDDLDecoder.
      86             : ///
      87             : /// This class is the base class defining what methods the event handler for the
      88             : /// high performance decoder should have. This handler actually does nothing.
      89             : /// The user of this decoder will have to derive from this class a custom event
      90             : /// handler that actually does something within the callback methods OnNewBusPatch,
      91             : /// OnData, OnError etc...
      92             : ///
      93             : /// \author Artur Szostak <artursz@iafrica.com>
      94             : 
      95          24 : class AliMUONTrackerDDLDecoderEventHandler
      96             : {
      97             : public:
      98             : 
      99             :         /// The only reason for a virtual destructor is to make -Weffc++ shutup.
     100             :         /// This should not really be here since we do not need or use virtual methods.
     101          16 :         virtual ~AliMUONTrackerDDLDecoderEventHandler() {}
     102             : 
     103             :         /// All the possible error codes for the parsing.
     104             :         enum ErrorCode
     105             :         {
     106             :                 kNoError = 0,                  /// Decoding was successful.
     107             :                 // Offset our error codes to stay clear of any common codes in AliMUONRawStreamTracker:
     108             :                 kBufferTooBig = 10,            /// The DDL raw data is larger than indicated by the headers; extra bytes are probably just garbage.
     109             :                 kTooManyBlocks = 11,           /// Too many block structures found.
     110             :                 kTooManyDSPs = 12,             /// Too many DSP structures found in the block.
     111             :                 kTooManyBusPatches = 13,       /// Too many bus patch structures found in the DSP structure.
     112             :                 kNoBlockHeader = 14,           /// Missing a block header.
     113             :                 kBadBlockKey = 15,             /// The block header key word does not contain the correct value.
     114             :                 kBadBlockLength = 16,          /// The block length field points past the end of the raw data size.
     115             :                 kBadBlockTotalLength = 17,     /// The total block length field points past the end of the raw data size.
     116             :                 kBlockLengthMismatch = 18,     /// The block length and total length fields do not correspond. One or both of these values is incorrect.
     117             :                 kNoDSPHeader = 19,             /// Missing a DSP header.
     118             :                 kBadDSPKey = 20,               /// The DSP header key word does not contain the correct value.
     119             :                 kBadDSPLength = 21,            /// The DSP structure length field points past the end of the block structure.
     120             :                 kBadDSPTotalLength = 22,       /// The total DSP structure length field points past the end of the block structure.
     121             :                 kDSPLengthMismatch = 23,       /// The DSP structure length and total length fields do not correspond. One or both of these values is incorrect.
     122             :                 kNoBusPatchHeader = 24,        /// Missing a bus patch header.
     123             :                 kBadBusPatchKey = 25,          /// The bus patch header key word does not contain the correct value.
     124             :                 kBadBusPatchLength = 26,       /// The bus patch length field points past the end of the DSP structure.
     125             :                 kBadBusPatchTotalLength = 27,  /// The total bus patch length field points past the end of the DSP structure.
     126             :                 kBusPatchLengthMismatch = 28,  /// The bus patch length and total length fields do not correspond. One or both of these values is incorrect.
     127             :                 kNoDDLTrailerWords = 29,       /// No end of DDL markers found in the trailer words.
     128             :                 kTooFewDDLTrailerWords = 30,   /// Only one end of DDL marker trailer word found but expected two.
     129             :                 kUnknownDspError = 31,         /// The DSP error code is non-zero but of an unrecognised format.
     130             :                 kTokenLost = 32,               /// The DSP contains a token lost error code that can affect the deadtime.
     131             :                 // match up error codes with AliMUONRawStreamTracker:
     132             :                 kGlitchFound = 1,              /// Found a glitch. This means a 1 byte word has been randomly inserted into the raw data by mistake.
     133             :                 kBadPaddingWord = 2,           /// The padding word does not contain the correct value.
     134             :                 kParityError = 3               /// Found a parity error in the data word.
     135             :         };
     136             : 
     137             :         // The following methods should be overridden for specific processing to
     138             :         // take place in your event handler.
     139             : 
     140             :         /// The OnNewBuffer method will be called whenever a new buffer containing
     141             :         /// a DDL payload is about to be processed.
     142             :         /// The default behaviour of this method is to do nothing.
     143             :         /// - param const void*  The pointer to the start of the memory buffer storing
     144             :         ///                the DDL payload.
     145             :         /// - param UInt_t The size in bytes of the memory buffer.
     146           0 :         void OnNewBuffer(const void* /*buffer*/, UInt_t /*bufferSize*/) {}
     147             :         
     148             :         /// The OnEndOfBuffer method will be called whenever the buffer containing
     149             :         /// a DDL payload has been processed. For each OnNewBuffer method call a
     150             :         /// symmetric call to OnEndOfBuffer is made at the end of processing (after
     151             :         /// the last call to OnData)
     152             :         /// The default behaviour of this method is to do nothing.
     153             :         /// - param const void*  The pointer to the start of the memory buffer storing
     154             :         ///                the DDL payload.
     155             :         /// - param UInt_t The size in bytes of the memory buffer.
     156           0 :         void OnEndOfBuffer(const void* /*buffer*/, UInt_t /*bufferSize*/) {}
     157             :         
     158             :         /// OnNewBlock is called whenever a new block header is found in the payload.
     159             :         /// The default behaviour of this method is to do nothing.
     160             :         /// - param const AliMUONBlockHeaderStruct* This is a pointer to the block header
     161             :         ///                as found in the DDL payload.
     162             :         /// - param const void* This is a pointer to the start of the block's contents.
     163             :         /// Note: both pointers point into the memory buffer being parsed, so the
     164             :         /// contents must not be modified. On the other hand this is very efficient
     165             :         /// because no memory copying is required.
     166           0 :         void OnNewBlock(const AliMUONBlockHeaderStruct* /*header*/, const void* /*data*/) {}
     167             :         
     168             :         /// OnEndOfBlock is called whenever a block has been processed. Symmetric
     169             :         /// calls are made to OnEndOfBlock after each call to OnNewBlock. This happens
     170             :         /// once all DSP structures contained inside the current block have been
     171             :         /// processed.
     172             :         /// The default behaviour of this method is to do nothing.
     173             :         /// - param const AliMUONBlockHeaderStruct* This is a pointer to the processed
     174             :         ///                block header as found in the DDL payload.
     175             :         /// - param const void* This is a pointer to the start of the block's contents.
     176             :         /// Note: both pointers point into the memory buffer being parsed, so the
     177             :         /// contents must not be modified. On the other hand this is very efficient
     178             :         /// because no memory copying is required.
     179         320 :         void OnEndOfBlock(const AliMUONBlockHeaderStruct* /*header*/, const void* /*data*/) {}
     180             :         
     181             :         /// OnNewDSP is called whenever a new DSP header is found in the payload.
     182             :         /// Every DSP header received by a call to OnNewDSP is associated to the
     183             :         /// block header received in the most recent call to OnNewBlock.
     184             :         /// The default behaviour of this method is to do nothing.
     185             :         /// - param const AliMUONDSPHeaderStruct*  This is a pointer to the DSP header
     186             :         ///                as found in the DDL payload.
     187             :         /// - param const void*  This is a pointer to the start of the DSP's contents.
     188             :         /// Note: both pointers point into the memory buffer being parsed, so the
     189             :         /// contents must not be modified. On the other hand this is very efficient
     190             :         /// because no memory copying is required.
     191           0 :         void OnNewDSP(const AliMUONDSPHeaderStruct* /*header*/, const void* /*data*/) {}
     192             :         
     193             :         /// OnEndOfDSP is called whenever a DSP header has already been processed.
     194             :         /// For every call to OnNewDSP a symmetric call to OnEndOfDSP is made once
     195             :         /// all the bus patch structured contained in the DSP are processed.
     196             :         /// The default behaviour of this method is to do nothing.
     197             :         /// - param const AliMUONDSPHeaderStruct*  This is a pointer to the already
     198             :         ///                processed DSP header as found in the DDL payload.
     199             :         /// - param const void*  This is a pointer to the start of the DSP's contents.
     200             :         /// Note: both pointers point into the memory buffer being parsed, so the
     201             :         /// contents must not be modified. On the other hand this is very efficient
     202             :         /// because no memory copying is required.
     203        1472 :         void OnEndOfDSP(const AliMUONDSPHeaderStruct* /*header*/, const void* /*data*/) {}
     204             :         
     205             :         /// OnNewBusPatch is called whenever a new bus patch header is found in
     206             :         /// the payload. Every bus patch received by a call to OnNewBusPatch is
     207             :         /// associated to the DSP header received in the most recent call to OnNewDSP.
     208             :         /// The default behaviour of this method is to do nothing.
     209             :         /// - param const AliMUONBusPatchHeaderStruct*  This is a pointer to the bus patch
     210             :         ///                header as found in the DDL payload.
     211             :         /// - param const void*  This is a pointer to the start of the bus patch's contents,
     212             :         ///              specifically the raw data words.
     213             :         /// Note: both pointers point into the memory buffer being parsed, so the
     214             :         /// contents must not be modified. On the other hand this is very efficient
     215             :         /// because no memory copying is required.
     216           0 :         void OnNewBusPatch(const AliMUONBusPatchHeaderStruct* /*header*/, const void* /*data*/) {}
     217             :         
     218             :         /// OnEndOfBusPatch is called whenever a bus patch has been processed.
     219             :         /// For every call to OnNewBusPatch a symmetric call to OnEndOfBusPatch is
     220             :         /// made once the bus patch is completely processed (no more OnData calls).
     221             :         /// The default behaviour of this method is to do nothing.
     222             :         /// - param const AliMUONBusPatchHeaderStruct*  This is a pointer to the already
     223             :         ///                processed bus patch header, as found in the DDL payload.
     224             :         /// - param const void*  This is a pointer to the start of the bus patch's contents,
     225             :         ///              specifically the raw data words.
     226             :         /// Note: both pointers point into the memory buffer being parsed so the
     227             :         /// contents must not be modified. On the other hand this is very efficient
     228             :         /// because no memory copying is required.
     229        7104 :         void OnEndOfBusPatch(const AliMUONBusPatchHeaderStruct* /*header*/, const void* /*data*/) {}
     230             :         
     231             :         /// OnData is called for every raw data word found within a bus patch.
     232             :         /// Every data ward received by a call to OnData is associated to the bus patch
     233             :         /// header received in the most recent call to OnNewBusPatch.
     234             :         /// The default behaviour of this method is to do nothing.
     235             :         /// - param UInt_t  This is the raw data word as found within the bus patch payload.
     236             :         /// - param bool  Flag indicating if the raw data word had a parity error.
     237             :         ///       This will always be set to false if fSendDataOnParityError in the
     238             :         ///       AliMUONTrackerDDLDecoder class was set to false.
     239             :         void OnData(UInt_t /*data*/, bool /*parityError*/) {}
     240             :         
     241             :         /// Whenever a parsing error of the DDL payload is encountered because of
     242             :         /// corruption of the raw data (eg. bit flips) the OnError method is called
     243             :         /// immediately at the point this error is discovered.
     244             :         /// The default behaviour of this method is to do nothing.
     245             :         /// - param ErrorCode  This is an error code indicating the kind of problem
     246             :         ///               encountered with the DDL payload.
     247             :         /// - param const void*  This is a pointer into the DDL payload memory buffer
     248             :         ///         indicating the exact location where the parsing error happened
     249             :         ///         or i.e. the location of the corruption.
     250             :         /// Note that a relative offset in bytes from the start of the memory buffer
     251             :         /// can be calculated by: storing the buffer pointer received in OnNewBuffer
     252             :         /// earlier in fBufferStart for example, and then the offset is given by:
     253             :         ///   offset = (unsigned long)location - (unsigned long)fBufferStart;
     254             :         void OnError(ErrorCode /*error*/, const void* /*location*/) {}
     255             :         
     256             :         /// This is a utility method which will unpack the MANU ID, channel ID and
     257             :         /// ADC signal value from a raw data word. It should normally be used in
     258             :         /// OnData() to unpack these fields.
     259             :         /// [in]  \param data  This is the raw data word found in the DDL payload.
     260             :         /// [out] \param manuId    This is filled with the unpacked MANU ID.
     261             :         /// [out] \param channelId This is filled with the unpacked MANU channel ID.
     262             :         /// [out] \param adc       This is filled with the unpacked ADC signal.
     263             :         static void UnpackADC(
     264             :                         UInt_t data,
     265             :                         UShort_t& manuId, UChar_t& channelId, UShort_t& adc
     266             :                 )
     267             :         {
     268        1416 :                 manuId = (UShort_t)(data >> 18) & 0x7FF;
     269         708 :                 channelId = (Char_t)(data >> 12) & 0x3F;
     270         708 :                 adc = (UShort_t)(data & 0xFFF);
     271         708 :         }
     272             :         
     273             :         /// This is a utility method which converts an error code to a string
     274             :         /// representation for printing purposes.
     275             :         /// \param code  The error code as received in OnError for example.
     276             :         /// \return  An ANSI string containing the name of the error code symbol.
     277             :         static const char* ErrorCodeToString(ErrorCode code);
     278             :         
     279             :         /// This is a utility method which converts an error code to user friendly
     280             :         /// descriptive message useful for printing to the screen.
     281             :         /// \param code  The error code as received in OnError for example.
     282             :         /// \return  An ANSI string containing a descriptive message of the error.
     283             :         static const char* ErrorCodeToMessage(ErrorCode code);
     284             : };
     285             : 
     286             : //_____________________________________________________________________________
     287             : 
     288             : inline const char* AliMUONTrackerDDLDecoderEventHandler::ErrorCodeToString(ErrorCode code)
     289             : {
     290             :         /// This is a utility method which converts an error code to a string
     291             :         /// representation for printing purposes.
     292             :         /// \param code  The error code as received in OnError for example.
     293             :         /// \return  An ANSI string containing the name of the error code symbol.
     294             :         
     295           0 :         switch (code)
     296             :         {
     297           0 :         case kNoError: return "kNoError";
     298           0 :         case kBufferTooBig: return "kBufferTooBig";
     299           0 :         case kTooManyBlocks: return "kTooManyBlocks";
     300           0 :         case kTooManyDSPs: return "kTooManyDSPs";
     301           0 :         case kTooManyBusPatches: return "kTooManyBusPatches";
     302           0 :         case kNoBlockHeader: return "kNoBlockHeader";
     303           0 :         case kBadBlockKey: return "kBadBlockKey";
     304           0 :         case kBadBlockLength: return "kBadBlockLength";
     305           0 :         case kBadBlockTotalLength: return "kBadBlockTotalLength";
     306           0 :         case kBlockLengthMismatch: return "kBlockLengthMismatch";
     307           0 :         case kNoDSPHeader: return "kNoDSPHeader";
     308           0 :         case kBadDSPKey: return "kBadDSPKey";
     309           0 :         case kBadDSPLength: return "kBadDSPLength";
     310           0 :         case kBadDSPTotalLength: return "kBadDSPTotalLength";
     311           0 :         case kDSPLengthMismatch: return "kDSPLengthMismatch";
     312           0 :         case kNoBusPatchHeader: return "kNoBusPatchHeader";
     313           0 :         case kBadBusPatchKey: return "kBadBusPatchKey";
     314           0 :         case kBadBusPatchLength: return "kBadBusPatchLength";
     315           0 :         case kBadBusPatchTotalLength: return "kBadBusPatchTotalLength";
     316           0 :         case kBusPatchLengthMismatch: return "kBusPatchLengthMismatch";
     317           0 :         case kNoDDLTrailerWords: return "kNoDDLTrailerWords";
     318           0 :         case kTooFewDDLTrailerWords: return "kTooFewDDLTrailerWords";
     319           0 :         case kUnknownDspError: return "kUnknownDspError";
     320           0 :         case kTokenLost: return "kTokenLost";
     321           0 :         case kGlitchFound: return "kGlitchFound";
     322           0 :         case kBadPaddingWord: return "kBadPaddingWord";
     323           0 :         case kParityError: return "kParityError";
     324           0 :         default: return "INVALID";
     325             :         }
     326           0 : }
     327             : 
     328             : 
     329             : inline const char* AliMUONTrackerDDLDecoderEventHandler::ErrorCodeToMessage(ErrorCode code)
     330             : {
     331             :         /// This is a utility method which converts an error code to user friendly
     332             :         /// descriptive message useful for printing to the screen.
     333             :         /// \param code  The error code as received in OnError for example.
     334             :         /// \return  An ANSI string containing a descriptive message of the error.
     335             :         
     336           0 :         switch (code)
     337             :         {
     338             :         case kNoError:
     339           0 :                 return "Decoding was successful.";
     340             :         case kBufferTooBig:
     341           0 :                 return "The DDL raw data is larger than indicated by the headers;"
     342             :                        " extra bytes are probably just garbage.";
     343             :         case kTooManyBlocks:
     344           0 :                 return "Too many block structures found.";
     345             :         case kTooManyDSPs:
     346           0 :                 return "Too many DSP structures found in the block.";
     347             :         case kTooManyBusPatches:
     348           0 :                 return "Too many bus patch structures found in the DSP structure.";
     349             :         case kNoBlockHeader:
     350           0 :                 return "Missing a block header.";
     351             :         case kBadBlockKey:
     352           0 :                 return "The block header key word does not contain the correct value.";
     353             :         case kBadBlockLength:
     354           0 :                 return "The block length field points past the end of the raw data size.";
     355             :         case kBadBlockTotalLength:
     356           0 :                 return "The total block length field points past the end of the"
     357             :                        " raw data size.";
     358             :         case kBlockLengthMismatch:
     359           0 :                 return "The block length and total length fields do not correspond."
     360             :                        " One or both of these values is incorrect.";
     361             :         case kNoDSPHeader:
     362           0 :                 return "Missing a DSP header.";
     363             :         case kBadDSPKey:
     364           0 :                 return "The DSP header key word does not contain the correct value.";
     365             :         case kBadDSPLength:
     366           0 :                 return "The DSP structure length field points past the end of the"
     367             :                        " block structure.";
     368             :         case kBadDSPTotalLength:
     369           0 :                 return "The total DSP structure length field points past the end of"
     370             :                        " the block structure.";
     371             :         case kDSPLengthMismatch:
     372           0 :                 return "The DSP structure length and total length fields do not"
     373             :                        " correspond. One or both of these values is incorrect.";
     374             :         case kNoBusPatchHeader:
     375           0 :                 return "Missing a bus patch header.";
     376             :         case kBadBusPatchKey:
     377           0 :                 return "The bus patch header key word does not contain the correct value.";
     378             :         case kBadBusPatchLength:
     379           0 :                 return "The bus patch length field points past the end of the"
     380             :                        " DSP structure.";
     381             :         case kBadBusPatchTotalLength:
     382           0 :                 return "The total bus patch length field points past the end of"
     383             :                        " the DSP structure.";
     384             :         case kBusPatchLengthMismatch:
     385           0 :                 return "The bus patch length and total length fields do not correspond."
     386             :                        " One or both of these values is incorrect.";
     387             :         case kNoDDLTrailerWords:
     388           0 :                 return "No end of DDL data key found in the trailer words.";
     389             :         case kTooFewDDLTrailerWords:
     390           0 :                 return "Only one end of DDL data key word found in the trailer but expected two.";
     391             :         case kUnknownDspError:
     392           0 :                 return "The DSP error code is non-zero but of an unrecognised format.";
     393             :         case kTokenLost:
     394           0 :                 return "The DSP contains a token lost error code that can affect the deadtime.";
     395             :         case kGlitchFound:
     396           0 :                 return "Found a glitch. This means a 1 byte word has been randomly"
     397             :                        " inserted into the raw data by mistake.";
     398             :         case kBadPaddingWord:
     399           0 :                 return "The padding word does not contain the correct value.";
     400             :         case kParityError:
     401           0 :                 return "Found a parity error in the data word.";
     402             :         default:
     403           0 :                 return "Unknown error code!";
     404             :         }
     405           0 : }
     406             : 
     407             : 
     408             : inline std::ostream& operator << (std::ostream& os, AliMUONTrackerDDLDecoderEventHandler::ErrorCode code)
     409             : {
     410             :         /// This is the stream operator for std::ostream classes to be able to
     411             :         /// easily write the error messages associated with the error codes generated
     412             :         /// by the decoder to 'cout' or 'cerr' for example.
     413             :         
     414             :         os << AliMUONTrackerDDLDecoderEventHandler::ErrorCodeToMessage(code);
     415             :         return os;
     416             : }
     417             : 
     418             : #endif // ALIMUONTRACKERDDLDECODEREVENTHANDLER_H
     419             : 

Generated by: LCOV version 1.11