LCOV - code coverage report
Current view: top level - MUON/MUONraw - AliMUONTriggerDDLDecoder.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 89 255 34.9 %
Date: 2016-06-14 17:26:59 Functions: 21 67 31.3 %

          Line data    Source code
       1             : #ifndef ALIMUONTRIGGERDDLDECODER_H
       2             : #define ALIMUONTRIGGERDDLDECODER_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   AliMUONTriggerDDLDecoder.h
      23             : /// \author Artur Szostak <artursz@iafrica.com>
      24             : /// \date   28-11-2007
      25             : /// \brief  Implementation of a high performance DDL decoder for the muon trigger.
      26             : ///
      27             : /// This file implementes the AliMUONTriggerDDLDecoder class, which contains
      28             : /// the core logic for decoding the payload in DDL streams comming from the muon
      29             : /// spectrometer's hardware trigger in a very efficient manner.
      30             : ///
      31             : /// This implementation is derived from work done by Christian Finck for the
      32             : /// AliMUONPayloadTrigger class.
      33             : ///
      34             : /// Note to maintainers: Please remember that this file is used by the online
      35             : /// dHLT system. As an online system, the dHLT requires the fastest code possible
      36             : /// in the decoders to satisfy its timing constraints. The performance impact
      37             : /// must be checked before any proposed modification is made to this file.
      38             : ///
      39             : 
      40             : #include "AliMUONTriggerDDLDecoderEventHandler.h"
      41             : 
      42             : /// \ingroup raw
      43             : /// \class AliMUONTriggerDDLDecoder
      44             : /// \brief A high performance decoder class for MUON trigger DDL data.
      45             : ///
      46             : /// This class implements a high performance decoder for decoding DDL payload
      47             : /// data coming from the muon spectrometers trigger stations.
      48             : /// It has been implemented using the event driven paradigm with templates,
      49             : /// which allows us to minimise the number of method calls made in the inner
      50             : /// loops of the algorithm and minimise the memory footprint.
      51             : /// At least for optimised production compilations.
      52             : /// The decoder class only contains the basic decoding and error checking logic.
      53             : /// It calls methods such as OnNewBuffer, OnDarcHeader, OnNewRegionalStruct,
      54             : /// OnLocalStruct etc in the event handler during the decoding to return the
      55             : /// decoded data and headers.
      56             : /// The event handler class is nothing more than a callback interface to deliver
      57             : /// the next chunks of decoded data.
      58             : /// To actually do something with the data, one needs to implement a custom
      59             : /// event handler (callback) class by inheriting from AliMUONTriggerDDLDecoderEventHandler
      60             : /// and overriding the callback methods like so:
      61             : /// \code
      62             : ///  class MyCustomHandler : public AliMUONTriggerDDLDecoderEventHandler
      63             : ///  {
      64             : ///  public:
      65             : ///     void OnLocalStruct(const AliMUONLocalInfoStruct* localStruct,
      66             : ///                        const AliMUONLocalScalarsStruct* scalars)
      67             : ///     {
      68             : ///       // I can do something with the data in 'localStruct' here.
      69             : ///       // and the 'scalars' if they are not NULL.
      70             : ///     }
      71             : ///  };
      72             : /// \endcode
      73             : ///
      74             : /// Once the custom handler is written then the decoder is instantiated as
      75             : /// shown below, to use your new custom handler. Also to start decoding one needs
      76             : /// to call the Decode() method of the decoder.
      77             : /// \code
      78             : ///  AliMUONTriggerDDLDecoder<MyCustomHandler> myDecoder;
      79             : ///  muDecoder.Decoder(buffer, bufferSize);
      80             : /// \endcode
      81             : ///
      82             : /// Note that this class was written as a template on purpose. To maximise the
      83             : /// compilers chance to make optimisations and inline the code we must use a template.
      84             : /// Depending on exactly what you do inside your handler, the decoder could be
      85             : /// significantly slower if run time polymorphism was used, i.e. making the class
      86             : /// AliMUONTriggerDDLDecoderEventHandler abstract and using virtual methods.
      87             : ///
      88             : template <class EventHandler>
      89          32 : class AliMUONTriggerDDLDecoder
      90             : {
      91             : public:
      92             : 
      93             :         /// Default contructor.
      94             :         AliMUONTriggerDDLDecoder() :
      95          24 :                 fExitOnError(true), fTryRecover(false),
      96          12 :                 fAutoDetectScalars(false), fHadError(false),
      97          12 :                 fNoRegionals(0), fMaxRegionals(8), fMaxLocals(16),
      98          12 :                 fHandler()
      99          36 :         {}
     100             :         
     101             :         /// Constant method to return the event handler instance.
     102         160 :         const EventHandler& GetHandler() const { return fHandler; }
     103             :         
     104             :         /// Returns the event handler instance.
     105         116 :         EventHandler& GetHandler() { return fHandler; }
     106             :         
     107             :         /// Returns the "exit on error" flag.
     108             :         /// i.e. should the decoder stop on the very first error found.
     109             :         bool ExitOnError() const { return fExitOnError; }
     110             :         
     111             :         /// Sets the "exit on error" flag.
     112             :         /// i.e. should the decoder stop on the very first error found.
     113          12 :         void ExitOnError(bool value) { fExitOnError = value; }
     114             :         
     115             :         /// Returns the "try to recover from errors" flag.
     116             :         /// i.e. should the decoder try to recover from errors found in the
     117             :         /// payload headers.
     118           0 :         bool TryRecover() const { return fTryRecover; }
     119             :         
     120             :         /// Sets the "try to recover from errors" flag.
     121             :         /// i.e. should the decoder try to recover from errors found in the
     122             :         /// payload headers.
     123           3 :         void TryRecover(bool value) { fTryRecover = value; }
     124             :         
     125             :         /// Returns the flag indicating if we should check for the scalars of
     126             :         /// software triggers automatically or not.
     127             :         bool AutoDetectScalars() const { return fAutoDetectScalars; }
     128             :         
     129             :         /// Sets the flag indicating if we should check for the scalars of
     130             :         /// software triggers automatically or not. If set to true then the
     131             :         /// scalarEvent parameter of the Decode method is ignored.
     132           3 :         void AutoDetectScalars(bool value) { fAutoDetectScalars = value; }
     133             :         
     134             :         /// Returns the maximum regional structure count expected in the DDL payload.
     135          18 :         UInt_t MaxRegionals() const { return fMaxRegionals; }
     136             :         
     137             :         /// Sets the maximum regional structure count expected in the DDL payload.
     138           0 :         void MaxRegionals(UInt_t n) { fMaxRegionals = n; }
     139             :         
     140             :         /// Returns the number of regional structures we actually attempted to decode.
     141             :         UInt_t RegionalsDecoded() const { return fNoRegionals; }
     142             :         
     143             :         /// Returns the maximum local structure count expected in any given regional
     144             :         /// card structure within the DDL payload.
     145        1954 :         UInt_t MaxLocals() const { return fMaxLocals; }
     146             :         
     147             :         /// Sets the maximum local structure count expected in any given regional
     148             :         /// card structure within the DDL payload.
     149           0 :         void MaxLocals(UInt_t n) { fMaxLocals = n; }
     150             :         
     151             :         /// This method decodes the DDL payload contained in the buffer.
     152             :         bool Decode(const void* buffer, UInt_t bufferSize, bool scalarEvent = false);
     153             :         
     154             :         /// Returns the end of DARC marker key.
     155           0 :         static UInt_t EndOfDarcWord() { return fgkEndOfDarc; }
     156             :         
     157             :         /// Returns the end of global header marker key.
     158           0 :         static UInt_t EndOfGlobalWord() { return fgkEndOfGlobal; }
     159             :         
     160             :         /// Returns the end of regional structure marker key.
     161           0 :         static UInt_t EndOfRegionalWord() { return fgkEndOfReg; }
     162             :         
     163             :         /// Returns the regional error word.
     164          18 :         static UInt_t RegionalErrorWord() { return fgkErrorWord; }
     165             :         
     166             :         /// Returns the end of local structure marker key.
     167           0 :         static UInt_t EndOfLocalWord() { return fgkEndOfLocal; }
     168             :         
     169             :         /// Returns the local card disable word.
     170             :         static UInt_t LocalDisableWord() { return fgkDisableWord; }
     171             :         
     172             :         /// Returns value of default DARC type.
     173           0 :         static UInt_t DarcDefaultType() { return fgkDarcDefaultType; }
     174             :         
     175             :         /// Returns value of Vadorh DARC type.
     176           0 :         static UInt_t DarcVadorhType()  { return fgkDarcVadorhType; }
     177             :         
     178             : private:
     179             : 
     180             :         bool fExitOnError; ///< Indicates if we should exit on the very first error.
     181             :         bool fTryRecover; ///< Indicates if we should try recover from a corrupt structures.
     182             :         bool fAutoDetectScalars; ///< Flag to indicate if we should auto-detect if there are scalars in the data.
     183             :         bool fHadError; ///< Indicates if we had an error decoding the data.
     184             :         UInt_t fNoRegionals; ///< The number of regional card structures actually decoded.
     185             :         UInt_t fMaxRegionals; ///< Maximum number of regional card structures allowed in a DDL stream.
     186             :         UInt_t fMaxLocals; ///< Maximum number of local card structures per regional structure allowed in a DDL stream.
     187             :         EventHandler fHandler; ///< The event handler which deals with the generated parsing events.
     188             : 
     189             :         void DecodeBuffer(const UChar_t* start, const UChar_t* end, bool scalarEvent);
     190             :         void DecodeRegionalStructs(const UChar_t* start, const UChar_t* end, bool scalarEvent);
     191             :         const UChar_t* DecodeLocalStructs(const UChar_t* start, const UChar_t* end, bool scalarEvent);
     192             :         
     193             :         const UChar_t* FindKey(
     194             :                         UInt_t key, const UChar_t* start, const UChar_t* end
     195             :                 );
     196             : 
     197             :         static const UInt_t fgkEndOfDarc;   ///< Indicates the end of the DARC header.
     198             :         static const UInt_t fgkEndOfGlobal; ///< Indicates the end of the global header just after the DARC header.
     199             :         static const UInt_t fgkEndOfReg;    ///< Indicates the end of a regional card structure.
     200             :         static const UInt_t fgkErrorWord;   ///< The error word when a regional board is missing.
     201             :         static const UInt_t fgkEndOfLocal;  ///< Indicates the end of a local card structure.
     202             :         static const UInt_t fgkDisableWord; ///< Word used to fill "empty" slots.
     203             :         static const UInt_t fgkDarcDefaultType;   ///< default type for DARC def.
     204             :         static const UInt_t fgkDarcVadorhType;    ///< default type for DARC vadorh
     205             : };
     206             : 
     207             : //_____________________________________________________________________________
     208             : 
     209             : // The following are the structure key words which are used to demarcate (identify
     210             : // the end) of the structures within the raw trigger data.
     211             : template <class EventHandler>
     212             : const UInt_t AliMUONTriggerDDLDecoder<EventHandler>::fgkEndOfDarc    = 0xDEADFACE;
     213             : template <class EventHandler>
     214             : const UInt_t AliMUONTriggerDDLDecoder<EventHandler>::fgkEndOfGlobal  = 0xDEADBEEF;
     215             : template <class EventHandler>
     216             : const UInt_t AliMUONTriggerDDLDecoder<EventHandler>::fgkEndOfReg     = 0xBEEFFACE;
     217             : template <class EventHandler>
     218             : const UInt_t AliMUONTriggerDDLDecoder<EventHandler>::fgkErrorWord    = 0xCAFEDEAD;
     219             : template <class EventHandler>
     220             : const UInt_t AliMUONTriggerDDLDecoder<EventHandler>::fgkEndOfLocal   = 0xCAFEFADE;
     221             : template <class EventHandler>
     222             : const UInt_t AliMUONTriggerDDLDecoder<EventHandler>::fgkDisableWord  = 0x10CADEAD;
     223             : template <class EventHandler>
     224             : const UInt_t AliMUONTriggerDDLDecoder<EventHandler>::fgkDarcDefaultType = 0x6;
     225             : template <class EventHandler>
     226             : const UInt_t AliMUONTriggerDDLDecoder<EventHandler>::fgkDarcVadorhType  = 0x4;
     227             : 
     228             : 
     229             : template <class EventHandler>
     230             : bool AliMUONTriggerDDLDecoder<EventHandler>::Decode(
     231             :                 const void* buffer, UInt_t bufferSize, bool scalarEvent
     232             :         )
     233             : {
     234             :         /// This method should be called to actually decode the DDL payload
     235             :         /// contained in a memory buffer. The payload should be in the muon trigger
     236             :         /// system DDL stream format otherwise it will be recognised as corrupt.
     237             :         /// As the decoder progresses it will make method calls to the event handler
     238             :         /// instance (which can be accessed with the GetHandler() method) to indicate
     239             :         /// the start of the DARC header, global header, new regional structures and
     240             :         /// local card structures.
     241             :         ///
     242             :         /// If an error occurs during the parse, because the data is corrupt, then
     243             :         /// the OnError method is called indicating what the problem was.
     244             :         /// Decoding will stop at this point unless the fExitOnError flag is set
     245             :         /// to false. There is an optional flag fTryRecover which can enable logic
     246             :         /// which will attempt to recover from corruption of the data structures
     247             :         /// in the DDL payload, if they are found to be inconsistent (assumed corrupt).
     248             :         /// The recovery procedure simply involves trying to find in the DDL stream
     249             :         /// the location of the expected end of header/structure marker/key or the
     250             :         /// next expected key, and then continue decoding from there. This kind of
     251             :         /// recovery logic is (and should be) turned off by default and only
     252             :         /// enabled when trying to recover corrupted data.
     253             :         ///
     254             :         /// \param buffer  This is the pointer to the start of the memory buffer
     255             :         ///     containing the DDL payload. Remember that this must be the start of
     256             :         ///     the payload and not the DDL stream. That is, this pointer should be
     257             :         ///     equal to: DDL start pointer + 8 * sizeof(UInt_t).
     258             :         /// \param bufferSize  This is the pointer to the first byte just past the
     259             :         ///     end of the block structure.
     260             :         /// \param scalarEvent  Set to true if this DDL contains a scalar event
     261             :         ///     and false if it is a normal physics event. If the fAutoDetectScalars
     262             :         ///     flag is true then we ignore this parameter.
     263             :         /// \return Returns false if there was any problem with decoding the data,
     264             :         ///     and true otherwise. Note: the data may have been partially decoded
     265             :         ///     even if false was returned, which would be indicated by at least one
     266             :         ///     call to the event handler's OnLocalStruct or OnNewRegionalStruct methods.
     267             :         
     268           8 :         assert( buffer != NULL );
     269             :         
     270           8 :         fHadError = false;
     271             :         
     272             :         // We are basically implementing something like a recursive decent parser.
     273             :         // So start by marking the start of buffer position and end of buffer.
     274             :         const UChar_t* start = reinterpret_cast<const UChar_t*>(buffer);
     275           8 :         const UChar_t* end = start + bufferSize;
     276             :         
     277           8 :         fHandler.OnNewBuffer(buffer, bufferSize);
     278           8 :         DecodeBuffer(start, end, scalarEvent);
     279           8 :         fHandler.OnEndOfBuffer(buffer, bufferSize);
     280           8 :         return not fHadError;
     281             : }
     282             : 
     283             : 
     284             : template <class EventHandler>
     285             : void AliMUONTriggerDDLDecoder<EventHandler>::DecodeBuffer(
     286             :                 const UChar_t* start, const UChar_t* end, bool scalarEvent
     287             :         )
     288             : {
     289             :         /// This method does the work to decode the buffer's payload data. It
     290             :         /// unpacks the DARC header, the global header, then calls the
     291             :         /// DecodeRegionalStructs() method to decode the regional structures.
     292             :         /// For the DARC and global headers the methods OnDarcHeader and
     293             :         /// OnGlobalHeader of the event handler object are called respectively.
     294             :         /// \param start  This is the pointer to the start of the buffer to decode.
     295             :         /// \param end  This is the pointer to the first byte just past the
     296             :         ///             end of the buffer.
     297             :         /// \param scalarEvent  Set to true if this DDL contains a scalar event
     298             :         ///     and false if it is a normal physics event.
     299             :         ///
     300             :         /// fHadError is set to true if there were any errors decoding the buffer
     301             :         /// and the OnError method of the callback event handler is called for
     302             :         /// each error.
     303             :         
     304             :         const UChar_t* current = start;
     305             :         
     306             :         // Mark the DARC header, but check that we do not overrun the buffer.
     307           8 :         const UInt_t* darcHeader = reinterpret_cast<const UInt_t*>(current);
     308           8 :         current += sizeof(UInt_t);
     309          16 :         if (current > end or current < start)
     310             :         {
     311             :                 // Indicate we had an error and stop the decoding because we
     312             :                 // hit the end of the buffer already.
     313           0 :                 fHandler.OnError(EventHandler::kNoDarcHeader, darcHeader);
     314           0 :                 fHadError = true;
     315           0 :                 return;
     316             :         }
     317             :         
     318             :         // Check if we need to figure out if this is a scalar event.
     319             :         // If we do, then we do this by checking the event type in the DARC header
     320             :         // and double checking this by checking if the fgkEndOfDarc key is in the
     321             :         // expected location for a scalar event DDL payload.
     322           8 :         if (fAutoDetectScalars)
     323             :         {
     324           0 :                 const UInt_t* expectedEndOfDarc = reinterpret_cast<const UInt_t*>(
     325           0 :                                 current + sizeof(AliMUONDarcScalarsStruct)
     326             :                         );
     327             :                 
     328             :                 // First make sure not to read past the end of buffer. Then check
     329             :                 // the value of the event type in the DARC header.
     330             :                 // Physics events are indicated by the two trigger bits of the
     331             :                 // DARC header set to 01b. Everything else is a software trigger
     332             :                 // of some sort.
     333           0 :                 if (reinterpret_cast<const UChar_t*>(expectedEndOfDarc+1) <= end and
     334           0 :                     reinterpret_cast<const UChar_t*>(expectedEndOfDarc+1) > start and
     335           0 :                     EventHandler::GetDarcEventType(*darcHeader) != 0x1
     336           0 :                     and *expectedEndOfDarc == fgkEndOfDarc
     337             :                    )
     338             :                 {
     339             :                         scalarEvent = true;
     340           0 :                 }
     341             :                 else
     342             :                 {
     343             :                         scalarEvent = false;
     344             :                 }
     345           0 :         }
     346             :         
     347             :         // Detect how many regional blocks we expect. If we have no idea then
     348             :         // just use what the maximum setting is.
     349           8 :         UInt_t darkType = EventHandler::GetDarcType(*darcHeader);
     350           8 :         if (darkType == fgkDarcVadorhType)
     351             :         {
     352           0 :                 fNoRegionals = 1;
     353           0 :         }
     354           8 :         else if (darkType == fgkDarcDefaultType)
     355             :         {
     356           0 :                 fNoRegionals = 8;
     357           0 :         }
     358             :         else
     359             :         {
     360           8 :                 fNoRegionals = fMaxRegionals;
     361             :         }
     362             :         
     363             :         // Check if the DARC header indicates we expect more regionals than we
     364             :         // are allowed to decode according to our max regional structures count.
     365             :         // If we do then this is an error and we should indicate it and exit
     366             :         // if so requested by the user. Also we can fix the number of regionals
     367             :         // to expect if we are trying to recover from errors.
     368           8 :         if (fNoRegionals > fMaxRegionals)
     369             :         {
     370           0 :                 fHandler.OnError(EventHandler::kTooManyRegionals, darcHeader);
     371           0 :                 fHadError = true;
     372           0 :                 if (fExitOnError) return;
     373           0 :                 if (fTryRecover)
     374             :                 {
     375           0 :                         fNoRegionals = fMaxRegionals;
     376           0 :                 }
     377             :         }
     378             :         
     379             :         // Check that the DARC header indicates correctly if we are a scalar event or not.
     380           8 :         bool darcShowsScalar = (EventHandler::GetDarcEventType(*darcHeader) != 0x1);
     381           8 :         if (darcShowsScalar != scalarEvent)
     382             :         {
     383             :                 // Indicate we had an error and stop the decoding if so requested
     384             :                 // by the user.
     385           0 :                 fHandler.OnError(EventHandler::kWrongEventType, darcHeader);
     386           0 :                 fHadError = true;
     387           0 :                 if (fExitOnError) return;
     388             :         }
     389             :         
     390             :         // Decode the DARC scalars if this is a scalar event.
     391             :         const AliMUONDarcScalarsStruct* darcScalars = NULL;
     392           8 :         if (scalarEvent)
     393             :         {
     394           0 :                 darcScalars = reinterpret_cast<const AliMUONDarcScalarsStruct*>(current);
     395           0 :                 current += sizeof(AliMUONDarcScalarsStruct);
     396           0 :                 if (current > end or current < start)
     397             :                 {
     398             :                         // If we overflowed the pointer and already had an error then
     399             :                         // we are clearly lost so just stop decoding before we segfault.
     400           0 :                         if (current < start and fHadError) return;
     401             :                         
     402             :                         // Indicate we had an error and stop the decoding because we
     403             :                         // hit the end of the buffer already.
     404           0 :                         fHandler.OnError(EventHandler::kNoDarcScalars, darcScalars);
     405           0 :                         fHadError = true;
     406           0 :                         return;
     407             :                 }
     408             :         }
     409             :         
     410             :         // Now check that the end of DARC header marker is OK.
     411           8 :         const UInt_t* endOfDarc = reinterpret_cast<const UInt_t*>(current);
     412           8 :         current += sizeof(UInt_t);
     413          16 :         if (current > end or current < start)
     414             :         {
     415             :                 // If we overflowed the pointer and already had an error then
     416             :                 // we are clearly lost so just stop decoding before we segfault.
     417           0 :                 if (current < start and fHadError) return;
     418             :                 
     419             :                 // Indicate we had an error and stop the decoding because we
     420             :                 // hit the end of the buffer already.
     421           0 :                 fHandler.OnError(EventHandler::kNoEndOfDarc, endOfDarc);
     422           0 :                 fHadError = true;
     423           0 :                 return;
     424             :         }
     425           8 :         if (*endOfDarc != fgkEndOfDarc)
     426             :         {
     427             :                 // Indicate we had an error and stop the decoding if so requested
     428             :                 // by the user.
     429           0 :                 fHandler.OnError(EventHandler::kBadEndOfDarc, endOfDarc);
     430           0 :                 fHadError = true;
     431           0 :                 if (fExitOnError) return;
     432             :                 
     433             :                 // If the user requested for us to try and recover from structure
     434             :                 // errors then we need to try locate the key in the data stream
     435             :                 // and continue decoding from there.
     436           0 :                 if (fTryRecover)
     437             :                 {
     438           0 :                         const UChar_t* keypos = FindKey(fgkEndOfDarc,
     439           0 :                                         reinterpret_cast<const UChar_t*>(darcHeader),
     440             :                                         end
     441             :                                 );
     442           0 :                         if (keypos != NULL)
     443             :                         {
     444             :                                 // remember to continue decoding just past the key.
     445           0 :                                 current = keypos + sizeof(UInt_t);
     446           0 :                         }
     447           0 :                 }
     448             :         }
     449             :         
     450           8 :         fHandler.OnDarcHeader(*darcHeader, darcScalars, current);
     451             :         
     452             :         // Next, we mark the Global header and check that we do not overrun the buffer.
     453             :         const AliMUONGlobalHeaderStruct* globalHeader =
     454           8 :                 reinterpret_cast<const AliMUONGlobalHeaderStruct*>(current);
     455           8 :         current += sizeof(AliMUONGlobalHeaderStruct);
     456          16 :         if (current > end or current < start)
     457             :         {
     458             :                 // If we overflowed the pointer and already had an error then
     459             :                 // we are clearly lost so just stop decoding before we segfault.
     460           0 :                 if (current < start and fHadError) return;
     461             :                 
     462             :                 // Indicate we had an error and stop the decoding because we
     463             :                 // hit the end of the buffer already.
     464           0 :                 fHandler.OnError(EventHandler::kNoGlobalHeader, globalHeader);
     465           0 :                 fHadError = true;
     466           0 :                 return;
     467             :         }
     468             :         
     469             :         // Decode the global scalars if this is a scalar event.
     470             :         const AliMUONGlobalScalarsStruct* globalScalars = NULL;
     471           8 :         if (scalarEvent)
     472             :         {
     473           0 :                 globalScalars = reinterpret_cast<const AliMUONGlobalScalarsStruct*>(current);
     474           0 :                 current += sizeof(AliMUONGlobalScalarsStruct);
     475           0 :                 if (current > end or current < start)
     476             :                 {
     477             :                         // If we overflowed the pointer and already had an error then
     478             :                         // we are clearly lost so just stop decoding before we segfault.
     479           0 :                         if (current < start and fHadError) return;
     480             :                         
     481             :                         // Indicate we had an error and stop the decoding because we
     482             :                         // hit the end of the buffer already.
     483           0 :                         fHandler.OnError(EventHandler::kNoGlobalScalars, globalScalars);
     484           0 :                         fHadError = true;
     485           0 :                         return;
     486             :                 }
     487             :         }
     488             :         
     489             :         // Now check that the end of global header marker is OK.
     490           8 :         const UInt_t* endOfGlobal = reinterpret_cast<const UInt_t*>(current);
     491           8 :         current += sizeof(UInt_t);
     492          16 :         if (current > end or current < start)
     493             :         {
     494             :                 // If we overflowed the pointer and already had an error then
     495             :                 // we are clearly lost so just stop decoding before we segfault.
     496           0 :                 if (current < start and fHadError) return;
     497             :                 
     498             :                 // Indicate we had an error and stop the decoding because we
     499             :                 // hit the end of the buffer already.
     500           0 :                 fHandler.OnError(EventHandler::kNoEndOfGlobal, endOfGlobal);
     501           0 :                 fHadError = true;
     502           0 :                 return;
     503             :         }
     504           8 :         if (*endOfGlobal != fgkEndOfGlobal)
     505             :         {
     506             :                 // Indicate we had an error and stop the decoding if so requested
     507             :                 // by the user.
     508           0 :                 fHandler.OnError(EventHandler::kBadEndOfGlobal, endOfGlobal);
     509           0 :                 fHadError = true;
     510           0 :                 if (fExitOnError) return;
     511             :                 
     512             :                 // If the user requested for us to try and recover from structure
     513             :                 // errors then we need to try locate the key in the data stream
     514             :                 // and continue decoding from there.
     515           0 :                 if (fTryRecover)
     516             :                 {
     517           0 :                         const UChar_t* keypos = FindKey(fgkEndOfGlobal,
     518           0 :                                         reinterpret_cast<const UChar_t*>(globalHeader),
     519             :                                         end
     520             :                                 );
     521           0 :                         if (keypos != NULL)
     522             :                         {
     523             :                                 // remember to continue decoding just past the key.
     524           0 :                                 current = keypos + sizeof(UInt_t);
     525           0 :                         }
     526           0 :                 }
     527             :         }
     528             :         
     529           8 :         fHandler.OnGlobalHeader(globalHeader, globalScalars, current);
     530             :         
     531           8 :         DecodeRegionalStructs(current, end, scalarEvent);
     532          16 : }
     533             : 
     534             : 
     535             : template <class EventHandler>
     536             : void AliMUONTriggerDDLDecoder<EventHandler>::DecodeRegionalStructs(
     537             :                 const UChar_t* start, const UChar_t* end, bool scalarEvent
     538             :         )
     539             : {
     540             :         /// This method decodes the regional structures in the DDL data.
     541             :         /// For each regional header found, the OnNewRegionalStruct method of
     542             :         /// the event handler is called, to signal the start of each
     543             :         /// new regional structure. The DecodeLocalStructs() method is then
     544             :         /// called to decode the local trigger structures. Finally, a symmetrical
     545             :         /// call to OnEndOfRegionalStruct of the event handler is called to
     546             :         /// signal that the regional structure has been decoded.
     547             :         /// \param start  This is the pointer to the start of the buffer.
     548             :         /// \param end  This is the pointer to the first byte just past the
     549             :         ///             end of the buffer.
     550             :         /// \param scalarEvent  Set to true if this DDL contains a scalar event
     551             :         ///     and false if it is a normal physics event.
     552             :         ///
     553             :         /// fHadError is set to true if there were any errors decoding the buffer
     554             :         /// and the OnError method of the callback event handler is called for
     555             :         /// each error.
     556             :         
     557             :         const UChar_t* current = start;
     558             :         
     559         152 :         for (UInt_t iReg = 0; iReg < fNoRegionals; iReg++)
     560             :         {
     561             :                 const AliMUONRegionalHeaderStruct* regionalHeader =
     562          64 :                         reinterpret_cast<const AliMUONRegionalHeaderStruct*>(current);
     563          64 :                 current += sizeof(AliMUONRegionalHeaderStruct);
     564             :                 
     565         128 :                 if (current > end or current < start)
     566             :                 {
     567             :                         // If we overflowed the pointer and already had an error then
     568             :                         // we are clearly lost so just stop decoding before we segfault.
     569           0 :                         if (current < start and fHadError) return;
     570             :                         
     571             :                         // So we only got part of a regional header, nothing to do but
     572             :                         // report the error and exit.
     573           0 :                         fHandler.OnError(EventHandler::kNoRegionalHeader, regionalHeader);
     574           0 :                         fHadError = true;
     575           0 :                         return;
     576             :                 }
     577             :                 
     578             :                 // Skip empty regional board (not connected or with error reading).
     579          64 :                 if (regionalHeader->fDarcWord == fgkErrorWord)
     580             :                 {
     581             :                         //current += sizeof(AliMUONRegionalHeaderStruct);  // already done above
     582           0 :                         if (scalarEvent)
     583           0 :                                 current += sizeof(AliMUONRegionalScalarsStruct);
     584           0 :                         current += sizeof(UInt_t); // skip the end of regional structure key.
     585             :                         
     586             :                         // now also skip the local structure part:
     587           0 :                         current += fMaxLocals * sizeof(AliMUONLocalInfoStruct);
     588           0 :                         if (scalarEvent)
     589           0 :                                 current += fMaxLocals * sizeof(AliMUONLocalScalarsStruct);
     590           0 :                         current += fMaxLocals * sizeof(UInt_t); // skip all the end of local structure keys.
     591             :                         
     592           0 :                         continue;
     593             :                 }
     594             :                 
     595             :                 // Decode the regional scalar words if this is a scalar event.
     596             :                 const AliMUONRegionalScalarsStruct* regionalScalars = NULL;
     597          64 :                 if (scalarEvent)
     598             :                 {
     599           0 :                         regionalScalars = reinterpret_cast<const AliMUONRegionalScalarsStruct*>(current);
     600           0 :                         current += sizeof(AliMUONRegionalScalarsStruct);
     601           0 :                         if (current > end or current < start)
     602             :                         {
     603             :                                 // If we overflowed the pointer and already had an error then
     604             :                                 // we are clearly lost so just stop decoding before we segfault.
     605           0 :                                 if (current < start and fHadError) return;
     606             :                                 
     607             :                                 // Indicate we had an error and stop the decoding because we
     608             :                                 // hit the end of the buffer already.
     609           0 :                                 fHandler.OnError(EventHandler::kNoRegionalScalars, regionalScalars);
     610           0 :                                 fHadError = true;
     611           0 :                                 return;
     612             :                         }
     613             :                 }
     614             :                 
     615             :                 // Now check that the end of regional header marker is OK.
     616          64 :                 const UInt_t* endOfRegional = reinterpret_cast<const UInt_t*>(current);
     617          64 :                 current += sizeof(UInt_t);
     618         128 :                 if (current > end or current < start)
     619             :                 {
     620             :                         // If we overflowed the pointer and already had an error then
     621             :                         // we are clearly lost so just stop decoding before we segfault.
     622           0 :                         if (current < start and fHadError) return;
     623             :                         
     624             :                         // Indicate we had an error and stop the decoding because we
     625             :                         // hit the end of the buffer already.
     626           0 :                         fHandler.OnError(EventHandler::kNoEndOfRegional, endOfRegional);
     627           0 :                         fHadError = true;
     628           0 :                         return;
     629             :                 }
     630          64 :                 if (*endOfRegional != fgkEndOfReg)
     631             :                 {
     632             :                         // Indicate we had an error and stop the decoding if so requested
     633             :                         // by the user.
     634           0 :                         fHandler.OnError(EventHandler::kBadEndOfRegional, endOfRegional);
     635           0 :                         fHadError = true;
     636           0 :                         if (fExitOnError) return;
     637             :                         
     638             :                         // If the user requested for us to try and recover from structure
     639             :                         // errors then we need to try locate the key in the data stream
     640             :                         // and continue decoding from there.
     641           0 :                         if (fTryRecover)
     642             :                         {
     643           0 :                                 const UChar_t* keypos = FindKey(fgkEndOfReg,
     644           0 :                                                 reinterpret_cast<const UChar_t*>(regionalHeader),
     645             :                                                 end
     646             :                                         );
     647             :                                 
     648             :                                 // If the fgkEndOfReg key was found exactly one regional
     649             :                                 // structure later then we should not adjust the current
     650             :                                 // decoding position because it is more likely that the
     651             :                                 // end of regional structure key was just corrupt rather
     652             :                                 // than offset.
     653             :                                 // If we could not find another good key then just continue.
     654             :                                 size_t sizeOfRegional = sizeof(AliMUONRegionalHeaderStruct) + sizeof(UInt_t)
     655           0 :                                         + fMaxLocals * (sizeof(AliMUONLocalInfoStruct) + sizeof(UInt_t));
     656           0 :                                 if (scalarEvent)
     657             :                                 {
     658           0 :                                         sizeOfRegional += sizeof(AliMUONRegionalScalarsStruct)
     659           0 :                                                 + fMaxLocals * sizeof(AliMUONLocalScalarsStruct);
     660           0 :                                 }
     661             :                                 
     662           0 :                                 if (keypos != NULL and keypos != current + sizeOfRegional)
     663             :                                 {
     664           0 :                                         current = keypos + sizeof(UInt_t);
     665           0 :                                 }
     666           0 :                         }
     667             :                 }
     668             :                 
     669             :                 // Tell the handler that we have a new regional block and decode it.
     670             :                 // When done, tell the handler again.
     671             :                 // We call both versions of OnNewRegionalStruct so that user event
     672             :                 // handlers can implement the one they prefer to use.
     673             :                 const UChar_t* startOfLocals = current;
     674          64 :                 fHandler.OnNewRegionalStruct(regionalHeader, regionalScalars, startOfLocals);
     675          64 :                 fHandler.OnNewRegionalStructV2(iReg, regionalHeader, regionalScalars, startOfLocals);
     676          64 :                 current = DecodeLocalStructs(current, end, scalarEvent);
     677          64 :                 fHandler.OnEndOfRegionalStruct(regionalHeader, regionalScalars, startOfLocals);
     678          64 :                 fHandler.OnEndOfRegionalStructV2(iReg, regionalHeader, regionalScalars, startOfLocals);
     679          64 :         }
     680             :         
     681             :         // Now just check that there is no extra rubbish at the end of the DDL.
     682           8 :         if (current != end)
     683             :         {
     684           0 :                 fHandler.OnError(EventHandler::kBufferTooBig, current);
     685           0 :                 fHadError = true;
     686           0 :         }
     687          16 : }
     688             : 
     689             : 
     690             : template <class EventHandler>
     691             : const UChar_t* AliMUONTriggerDDLDecoder<EventHandler>::DecodeLocalStructs(
     692             :                 const UChar_t* start, const UChar_t* end, bool scalarEvent
     693             :         )
     694             : {
     695             :         /// This method decodes the local structures in the DDL data for a
     696             :         /// single regional structure. For each local trigger structure found,
     697             :         /// the OnLocalStruct method of the event handler is called.
     698             :         /// \param start  This is the pointer to the start of the regional structure
     699             :         ///               payload (The pointer just past the regional header key).
     700             :         /// \param end  This is the pointer to the first byte just past the
     701             :         ///             end of the buffer.
     702             :         /// \param scalarEvent  Set to true if this DDL contains a scalar event
     703             :         ///     and false if it is a normal physics event.
     704             :         /// \returns  The position in the buffer where this method stopped decoding.
     705             :         ///
     706             :         /// fHadError is set to true if there were any errors decoding the buffer
     707             :         /// and the OnError method of the callback event handler is called for
     708             :         /// each error.
     709             :         
     710             :         const UChar_t* current = start;
     711             :         
     712        2240 :         for (UInt_t iLocal = 0; iLocal < fMaxLocals; iLocal++)
     713             :         {
     714             :                 const AliMUONLocalInfoStruct* localStruct =
     715        1024 :                         reinterpret_cast<const AliMUONLocalInfoStruct*>(current);
     716        1024 :                 current += sizeof(AliMUONLocalInfoStruct);
     717             :                 
     718        2048 :                 if (current > end or current < start)
     719             :                 {
     720             :                         // If we overflowed the pointer and already had an error then
     721             :                         // we are clearly lost so just stop decoding before we segfault.
     722           0 :                         if (current < start and fHadError) return end;
     723             :                         
     724             :                         // So we only got part of a local structure, nothing to do but
     725             :                         // report the error and exit.
     726           0 :                         fHandler.OnError(EventHandler::kNoLocalStruct, localStruct);
     727           0 :                         fHadError = true;
     728           0 :                         return end;
     729             :                 }
     730             :                 
     731             :                 // Skip empty local board if card not notified.
     732        1080 :                 if (localStruct->fX2X1 == fgkDisableWord and
     733          56 :                     localStruct->fX4X3 == fgkDisableWord and
     734          56 :                     localStruct->fY2Y1 == fgkDisableWord and
     735          56 :                     localStruct->fY4Y3 == fgkDisableWord and
     736          56 :                     localStruct->fTriggerBits == fgkDisableWord
     737             :                    )
     738             :                 {
     739             :                         //current += sizeof(AliMUONLocalInfoStruct); // already done above
     740          56 :                         if (scalarEvent)
     741           0 :                                 current += sizeof(AliMUONLocalScalarsStruct);
     742          56 :                         current += sizeof(UInt_t); // skip the end of local structure key.
     743          56 :                         continue;
     744             :                 }
     745             :                 
     746             :                 // Decode the regional scalar words if this is a scalar event.
     747             :                 const AliMUONLocalScalarsStruct* localScalars = NULL;
     748         968 :                 if (scalarEvent)
     749             :                 {
     750           0 :                         localScalars = reinterpret_cast<const AliMUONLocalScalarsStruct*>(current);
     751           0 :                         current += sizeof(AliMUONLocalScalarsStruct);
     752           0 :                         if (current > end or current < start)
     753             :                         {
     754             :                                 // If we overflowed the pointer and already had an error then
     755             :                                 // we are clearly lost so just stop decoding before we segfault.
     756           0 :                                 if (current < start and fHadError) return end;
     757             :                                 
     758             :                                 // Indicate we had an error and stop the decoding because we
     759             :                                 // hit the end of the buffer already.
     760           0 :                                 fHandler.OnError(EventHandler::kNoLocalScalars, localScalars);
     761           0 :                                 fHadError = true;
     762           0 :                                 return end;
     763             :                         }
     764             :                 }
     765             :                 
     766             :                 // Now check that the end of regional header marker is OK.
     767         968 :                 const UInt_t* endOfLocal = reinterpret_cast<const UInt_t*>(current);
     768         968 :                 current += sizeof(UInt_t);
     769        1936 :                 if (current > end or current < start)
     770             :                 {
     771             :                         // If we overflowed the pointer and already had an error then
     772             :                         // we are clearly lost so just stop decoding before we segfault.
     773           0 :                         if (current < start and fHadError) return end;
     774             :                         
     775             :                         // Indicate we had an error and stop the decoding because we
     776             :                         // hit the end of the buffer already. We can however signal that
     777             :                         // we got a local structure, because the buffer contains enough
     778             :                         // data to potencially contain the real data of the structure.
     779           0 :                         fHandler.OnError(EventHandler::kNoEndOfLocal, endOfLocal);
     780           0 :                         if (not fExitOnError)
     781             :                         {
     782           0 :                                 fHandler.OnLocalStruct(localStruct, localScalars);
     783           0 :                         }
     784           0 :                         fHadError = true;
     785           0 :                         return end;
     786             :                 }
     787         968 :                 if (*endOfLocal != fgkEndOfLocal)
     788             :                 {
     789             :                         // Indicate we had an error and stop the decoding if so requested
     790             :                         // by the user.
     791           0 :                         fHandler.OnError(EventHandler::kBadEndOfLocal, endOfLocal);
     792           0 :                         fHadError = true;
     793           0 :                         if (fExitOnError) return current;
     794             :                         
     795             :                         // If the user requested for us to try and recover from structure
     796             :                         // errors then we need to try locate the key in the data stream
     797             :                         // and continue decoding from there.
     798           0 :                         if (fTryRecover)
     799             :                         {
     800           0 :                                 const UChar_t* searchPos = reinterpret_cast<const UChar_t*>(localStruct);
     801           0 :                                 const UChar_t* firstLocalKey = FindKey(fgkEndOfLocal, searchPos, end);
     802           0 :                                 const UChar_t* firstRegionalKey = FindKey(fgkEndOfReg, searchPos, end);
     803             :                                 
     804             :                                 // If a regional key was found first, then give up on
     805             :                                 // anymore local structures from this regional block and
     806             :                                 // continue decoding from the next regional block.
     807             :                                 // Also if the fgkEndOfLocal key was found exactly one
     808             :                                 // local structure later then we should not adjust the
     809             :                                 // current decoding position because it is more likely that
     810             :                                 // the end of local structure key was just corrupt rather
     811             :                                 // than offset.
     812           0 :                                 if (firstLocalKey != NULL and firstRegionalKey != NULL)
     813             :                                 {
     814           0 :                                         if (firstLocalKey < firstRegionalKey)
     815             :                                         {
     816             :                                                 size_t sizeOflocalStruct = sizeof(AliMUONLocalInfoStruct) + sizeof(UInt_t);
     817           0 :                                                 if (scalarEvent)
     818           0 :                                                         sizeOflocalStruct += sizeof(AliMUONLocalScalarsStruct);
     819             :                                                 
     820           0 :                                                 if (firstLocalKey != current + sizeOflocalStruct)
     821           0 :                                                         current = firstLocalKey + sizeof(UInt_t);
     822             :                                         }
     823             :                                         else
     824             :                                         {
     825             :                                                 // Adjust back to the start of the regional header.
     826           0 :                                                 current = firstRegionalKey - sizeof(AliMUONRegionalHeaderStruct);
     827           0 :                                                 if (scalarEvent)
     828           0 :                                                         current -= sizeof(AliMUONRegionalScalarsStruct);
     829           0 :                                                 break;
     830             :                                         }
     831           0 :                                 }
     832             :                                 
     833             :                                 // If we could not find another good key then just continue.
     834           0 :                         }
     835             :                 }
     836             :                 
     837             :                 // Call both handlers for local structures so that the user decoder event
     838             :                 // handler class can implement the one it prefers to use.
     839         968 :                 fHandler.OnLocalStruct(localStruct, localScalars);
     840         968 :                 fHandler.OnLocalStructV2(iLocal, localStruct, localScalars);
     841         968 :         }
     842             :         
     843          64 :         return current;
     844          64 : }
     845             : 
     846             : 
     847             : template <class EventHandler>
     848             : const UChar_t* AliMUONTriggerDDLDecoder<EventHandler>::FindKey(
     849             :                 UInt_t key, const UChar_t* start, const UChar_t* end
     850             :         )
     851             : {
     852             :         /// Searches for the first occurrence of the key value in the buffer
     853             :         /// marked by 'start' and 'end'. 'start' should point to the start of
     854             :         /// the buffer and 'end' should point to 'start + bufferSize'.
     855             :         /// \param key  The 32 bit word to look for.
     856             :         /// \param start  The start location to begin the search at.
     857             :         /// \param end  The pointer to the first byte just past end of the
     858             :         ///             buffer to check.
     859             :         /// \returns  The location of the first occurance of key in the buffer,
     860             :         ///           otherwise NULL is returned if nothing was found.
     861             :  
     862           0 :         if (end + sizeof(UInt_t) < start) return NULL;  // check for pointer overflow.
     863             :         const UChar_t* current = start;
     864           0 :         while (current + sizeof(UInt_t) <= end)
     865             :         {
     866           0 :                 UInt_t data = * reinterpret_cast<const UInt_t*>(current);
     867           0 :                 if (data == key) return current;
     868           0 :                 current++;
     869           0 :         }
     870           0 :         return NULL;
     871           0 : }
     872             : 
     873             : #endif // ALIMUONTRIGGERDDLDECODER_H

Generated by: LCOV version 1.11