]> git.uio.no Git - u/mrichter/AliRoot.git/blob - MUON/AliMUONTrackerDDLDecoder.h
SelectCollisionCandidates added for the task
[u/mrichter/AliRoot.git] / MUON / AliMUONTrackerDDLDecoder.h
1 #ifndef ALIMUONTRACKERDDLDECODER_H
2 #define ALIMUONTRACKERDDLDECODER_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   AliMUONTrackerDDLDecoder.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 tracking stations.
26 ///
27 /// This file implementes the AliMUONTrackerDDLDecoder class, which contains
28 /// the core logic for decoding the payload in DDL streams coming from the muon
29 /// spectrometer's tracking chambers in a very efficient manner.
30 ///
31 /// This implementation is derived from work done by Christian Finck for the
32 /// AliMUONPayloadTracker.
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 <string.h>
41 #include "AliMUONTrackerDDLDecoderEventHandler.h"
42
43 /// \ingroup raw
44 /// \class AliMUONTrackerDDLDecoder
45 /// \brief A high performance decoder class for MUON tracking DDL data.
46 ///
47 /// This class implements a high performance decoder for decoding DDL payload
48 /// data coming from the muon spectrometers tracking chambers.
49 /// It has been implemented using the event driven paradigm with templates,
50 /// which allows us to minimise the number of method calls made in the inner
51 /// loops of the algorithm and minimise the memory footprint. At least for
52 /// optimised production compilations.
53 /// The decoder class only contains the basic decoding and error checking logic.
54 /// It calls methods such as OnNewBlock, OnNewBusPatch, OnData etc in
55 /// the event handler during the decoding to return the decoded data.
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 AliMUONTrackerDDLDecoderEventHandler
60 /// and overriding the callback methods like so:
61 /// \code
62 ///  class MyCustomHandler : public AliMUONTrackerDDLDecoderEventHandler
63 ///  {
64 ///  public:
65 ///     void OnData(UInt_t data, bool parityError)
66 ///     {
67 ///       // I can do something with 'data' here and check if there was
68 ///       // a parity error with 'parityError'.
69 ///     }
70 ///  };
71 /// \endcode
72 ///
73 /// Once the custom handler is written then the decoder is instantiated as
74 /// shown below, to use your new custom handler. Also to start decoding one needs
75 /// to call the Decode() method of the decoder.
76 /// \code
77 ///  AliMUONTrackerDDLDecoder<MyCustomHandler> myDecoder;
78 ///  muDecoder.Decoder(buffer, bufferSize);
79 /// \endcode
80 ///
81 /// Note that this class was written as a template on purpose. To maximise the
82 /// compilers chance to make optimisations and inline the code we must use a template.
83 /// Depending on exactly what you do inside your handler, the decoder could be
84 /// significantly slower if run time polymorphism was used, i.e. making the class
85 /// AliMUONTrackerDDLDecoderEventHandler abstract and using virtual methods.
86 ///
87 /// There has been a change to the data format that the real detector generates.
88 /// Two trailer words are added to the end of the DDL payload which indicated
89 /// the end of data. The decoder is initialised by default to automatically
90 /// check for these and deal with it correctly, if they exist or not.
91 /// However, if you want to override this behaviour then set the flag
92 /// fAutoDetectTrailer to false with AutoDetectTrailer(false). Then if you have
93 /// data with the old data format you should set fCheckForTrailer to false with
94 /// CheckForTrailer(false), otherwise for real data it should be
95 /// fCheckForTrailer = true. Only when fAutoDetectTrailer is true will the
96 /// fCheckForTrailer flag be ignored and no warnings will be generated for an
97 /// incorrect data format.
98 ///
99 /// \author Artur Szostak <artursz@iafrica.com>
100
101 template <class EventHandler>
102 class AliMUONTrackerDDLDecoder
103 {
104 public:
105
106         /// Default contructor.
107         AliMUONTrackerDDLDecoder() :
108                 fExitOnError(true), fTryRecover(false),
109                 fSendDataOnParityError(false), fHadError(false),
110                 fAutoDetectTrailer(true), fCheckForTrailer(true),
111                 fMaxBlocks(2), fMaxDSPs(5), fMaxBusPatches(5), fHandler()
112         {}
113         
114         /// Constant method to return the event handler instance.
115         const EventHandler& GetHandler() const { return fHandler; }
116         
117         /// Returns the event handler instance.
118         EventHandler& GetHandler() { return fHandler; }
119         
120         /// Returns the "exit on error" flag.
121         /// i.e. should the decoder stop on the very first error found.
122         bool ExitOnError() const { return fExitOnError; }
123         
124         /// Sets the "exit on error" flag.
125         /// i.e. should the decoder stop on the very first error found.
126         void ExitOnError(bool value) { fExitOnError = value; }
127         
128         /// Returns the "try to recover from errors" flag.
129         /// i.e. should the decoder try to recover from errors found in the
130         /// payload headers or trailers.
131         bool TryRecover() const { return fTryRecover; }
132         
133         /// Sets the "try to recover from errors" flag.
134         /// i.e. should the decoder try to recover from errors found in the
135         /// payload headers or trailers.
136         void TryRecover(bool value) { fTryRecover = value; }
137         
138         /// Returns the flag indicating if the raw data words in the bus patches
139         /// that failed their parity tests (i.e. parity error / bit flip in the
140         /// raw data word) will be sent to the event handler anyway through OnData.
141         bool SendDataOnParityError() const { return fSendDataOnParityError; }
142         
143         /// Sets the flag indicating if the raw data words in the bus patches
144         /// that failed their parity tests (i.e. parity error / bit flip in the
145         /// raw data word) will be sent to the event handler anyway through OnData.
146         void SendDataOnParityError(bool value) { fSendDataOnParityError = value; }
147         
148         /// Returns the maximum block count expected in the DDL payload.
149         UInt_t MaxBlocks() const { return fMaxBlocks; }
150         
151         /// Sets the maximum block count expected in the DDL payload.
152         void MaxBlocks(UInt_t n) { fMaxBlocks = n; }
153         
154         /// Returns the maximum DSP header count expected in any given block
155         /// structure within the DDL payload.
156         UInt_t MaxDSPs() const { return fMaxDSPs; }
157         
158         /// Sets the maximum DSP header count expected in any given block structure
159         /// within the DDL payload.
160         void MaxDSPs(UInt_t n) { fMaxDSPs = n; }
161         
162         /// Returns the maximum number of bus patches expected in any given DSP
163         /// structure within the DDL payload.
164         UInt_t MaxBusPatches() const { return fMaxBusPatches; }
165         
166         /// Sets the maximum number of bus patches expected in any given DSP
167         /// structure within the DDL payload.
168         void MaxBusPatches(UInt_t n) { fMaxBusPatches = n; }
169         
170         /// Returns the value of the auto-detect trailer flag.
171         bool AutoDetectTrailer() const { return fAutoDetectTrailer; }
172         
173         /// Sets the value of the auto-detect trailer flag.
174         void AutoDetectTrailer(bool value) { fAutoDetectTrailer = value; }
175         
176         /// Returns the value of the flag to check for the end of DDL trailer.
177         bool CheckForTrailer() const { return fCheckForTrailer; }
178         
179         /// Sets the value of the flag to check for the end of DDL trailer.
180         void CheckForTrailer(bool value) { fCheckForTrailer = value; }
181         
182         /// This method decodes the DDL payload contained in the buffer.
183         bool Decode(const void* buffer, UInt_t bufferSize);
184         
185         /// First try fix data corruption and then decode the DDL payload.
186         bool Decode(void* buffer, UInt_t bufferSize);
187         
188         /// Returns the block marker key.
189         static UInt_t BlockDataKeyWord() { return fgkBlockDataKey; }
190         
191         /// Returns the DSP marker key.
192         static UInt_t DspDataKeyWord() { return fgkDSPDataKey; }
193         
194         /// Returns the bus patch marker key.
195         static UInt_t BusPatchDataKeyWord() { return fgkBusPatchDataKey; }
196         
197         /// Returns the expected padding word value.
198         static UInt_t PaddingWord() { return fgkPaddingWord; }
199         
200         /// Returns the expected end of DDL marker.
201         static UInt_t EndOfDDLWord() { return fgkEndOfDDL; }
202         
203 private:
204
205         bool fExitOnError; ///< Indicates if we should exit on the very first error.
206         bool fTryRecover; ///< Indicates if we should try recover from a corrupt structure header or DDL trailer.
207         bool fSendDataOnParityError; ///< If set to true then we issue a OnData() event even if the data word had a parity error.
208         bool fHadError; ///< Indicates if we had an error decoding the data.
209         bool fAutoDetectTrailer; ///< Indicates if we should automatically check for the end of DDL trailer (Default = true).
210         bool fCheckForTrailer; ///< Indicates if we should check for the end of DDL trailer (Default = true). This flag is ignored if fAutoDetectTrailer is true.
211         UInt_t fMaxBlocks; ///< Maximum number of block structures allowed in a DDL stream.
212         UInt_t fMaxDSPs; ///< Maximum number of DSP structures allowed in a DDL stream.
213         UInt_t fMaxBusPatches; ///< Maximum number of bus patch structures allowed in a DDL stream.
214         EventHandler fHandler; ///< The event handler which deals with parsing events.
215
216         void DecodeBuffer(const UChar_t* start, const UChar_t* end);
217         
218         bool DecodeBlockData(
219                         const AliMUONBlockHeaderStruct* blockHeader,
220                         const UChar_t* start, const UChar_t* end
221                 );
222
223         bool DecodeDSPData(const UChar_t* start, const UChar_t* end);
224         
225         bool DecodeBusPatchData(const UChar_t* start, const UChar_t* end);
226
227         /// Possible results that can be returned by the TryRecoverStruct method.
228         enum RecoverResult
229         {
230                 kRecoverFailed,        ///< The recovery failed. Cannot continue parsing.
231                 kStructRecovered,      ///< Indicates that we recovered from a corrupt structure header and can continue processing the given structure.
232                 kContinueToNextStruct  ///< Must continue parsing the next structure and ignore the current one.
233         };
234
235         RecoverResult TryRecoverStruct(
236                         UInt_t expectedKey,
237                         UInt_t headerSize,
238                         UInt_t totalLength,
239                         UInt_t length,
240                         const UChar_t* structStart,
241                         const UChar_t* bufferEnd,
242                         const UChar_t*& dataEnd,
243                         const UChar_t*& structEnd,
244                         const UChar_t*& current
245                 );
246         
247         const UChar_t* FindKey(
248                         UInt_t key, const UChar_t* start, const UChar_t* end
249                 );
250         
251         bool ParityIsOk(UInt_t data);
252         
253         static const UInt_t fgkBlockDataKey;     ///< The key word expected to identify block structure headers.
254         static const UInt_t fgkDSPDataKey;       ///< The key word expected to identify DSP structure headers.
255         static const UInt_t fgkBusPatchDataKey;  ///< The key word expected to identify bus patch headers.
256         static const UInt_t fgkPaddingWord;      ///< The expected format of the padding word in the DDL payload.
257         static const UInt_t fgkEndOfDDL;         ///< The end of DDL trailer word.
258 };
259
260 //_____________________________________________________________________________
261
262 // The following are the structure header keys which are used to identify the kind
263 // of structure header we are dealing with: block, DSP or bus patch header.
264 template <class EventHandler>
265 const UInt_t AliMUONTrackerDDLDecoder<EventHandler>::fgkBlockDataKey = 0xFC0000FC;
266 template <class EventHandler>
267 const UInt_t AliMUONTrackerDDLDecoder<EventHandler>::fgkDSPDataKey = 0xF000000F;
268 template <class EventHandler>
269 const UInt_t AliMUONTrackerDDLDecoder<EventHandler>::fgkBusPatchDataKey = 0xB000000B;
270 template <class EventHandler>
271 const UInt_t AliMUONTrackerDDLDecoder<EventHandler>::fgkPaddingWord = 0xBEEFFACE;
272 template <class EventHandler>
273 const UInt_t AliMUONTrackerDDLDecoder<EventHandler>::fgkEndOfDDL = 0xD000000D;
274
275
276 template <class EventHandler>
277 bool AliMUONTrackerDDLDecoder<EventHandler>::Decode(const void* buffer, UInt_t bufferSize)
278 {
279         /// This method should be called to actually decode the DDL payload
280         /// contained in a memory buffer. The payload should be for a muon tracking
281         /// chamber DDL stream.
282         /// As the decoder progresses it will make method calls to the event handler
283         /// instance (which can be accessed with the GetHandler() method) to indicate
284         /// the start of the new block, DSP and bus patch headers. For every raw
285         /// data word the OnData method of the event handler is called.
286         ///
287         /// If an error occurs during the parse because the data is corrupt then
288         /// the OnError method is called indicating what the problem was.
289         /// Decoding will stop at this point unless the fExitOnError flag is set
290         /// to false. Also raw data words which contain a parity error are only
291         /// sent to the event handler with OnData if the fSendDataOnParityError
292         /// flag is set to true. There is also an optional flag fTryRecover which
293         /// can enable logic which will attempt to recover the header structures found
294         /// in the DDL payload if they are found to be inconsistent (assumed corrupt).
295         /// fTryRecover set to true will also enable recovery from a corrupt
296         /// DDL trailer marking the end of DDL payload.
297         ///
298         /// \param buffer  This is the pointer to the start of the memory buffer
299         ///     containing the DDL payload. Remember that this must be the start of
300         ///     the payload and not the DDL stream. That is, this pointer should be
301         ///     equal to: DDL start pointer + 8 * sizeof(UInt_t).
302         /// \param bufferSize  This is the pointer to the first byte just past the
303         ///     end of the block structure.
304         /// \return Returns false if there was any problem with decoding the data,
305         ///     and true otherwise. Note: the data may have been partially decoded
306         ///     even if false was returned, which would be indicated by at least one
307         ///     call to the event handlers OnData method.
308         
309         assert( buffer != NULL );
310         
311         fHadError = false;
312         
313         // We are basically implementing something like a recursive decent parser.
314         // So start by marking the start of buffer position and end of buffer.
315         const UChar_t* start = reinterpret_cast<const UChar_t*>(buffer);
316         const UChar_t* end = start + bufferSize;
317         
318         fHandler.OnNewBuffer(buffer, bufferSize);
319         DecodeBuffer(start, end);
320         fHandler.OnEndOfBuffer(buffer, bufferSize);
321         return not fHadError;
322 }
323
324
325 template <class EventHandler>
326 bool AliMUONTrackerDDLDecoder<EventHandler>::Decode(void* buffer, UInt_t bufferSize)
327 {
328         /// This decoding method performs a special checks to see if the DDL
329         /// corruption is fixable and then fixes the buffer by modifying it directly.
330         /// The fixes only apply if the fTryRecover flag is enabled.
331         /// \note buffer might be modified.
332         
333         assert( buffer != NULL );
334         if (fTryRecover)
335         {
336                 ///////////////////////////////////////////////////////
337                 // Trick to recover B off data Runs : 119041, 119047, 119055, 119057
338                 // A. Baldisseri May 2010
339                 // Check if 16 32-bit words from a buspatch have been inserted
340                 // incorrectly immediately at the beginning of the DDL payload.
341                 UChar_t* bufferChar = reinterpret_cast<UChar_t*>(buffer);
342                 UInt_t* bufferInt = reinterpret_cast<UInt_t*>(buffer);
343                 if (bufferSize > 18*4 // is the buffer large enough to check the header.
344                     and bufferInt[0] != fgkBlockDataKey and bufferInt[16] == fgkBlockDataKey // was the header incorrectly moved.
345                     and bufferSize > bufferInt[17]*4 + sizeof(AliMUONBlockHeaderStruct) // is the buffer large enough for the second block header.
346                     and bufferInt[bufferInt[17]] == fgkBlockDataKey  // Check that the second header is in the correct location.
347                     and bufferInt[17] == bufferInt[18] + 8  // Make sure that both lengths are correct.
348                     and (bufferInt[17] + bufferInt[bufferInt[17]+1]+2)*4 == bufferSize // Check that both blocks will have the correct size if we make the fix.
349                    )
350                 {
351                         UChar_t tmpbuf[16*4];
352                         memcpy(tmpbuf, bufferChar, 16*4);
353                         size_t sizeToMove = bufferInt[17]*4-16*4;
354                         memmove(bufferChar, bufferChar+16*4, sizeToMove);
355                         memcpy(bufferChar + sizeToMove, tmpbuf, 16*4);
356                 }
357         }
358         return Decode(reinterpret_cast<const void*>(buffer), bufferSize);
359 }
360
361
362 template <class EventHandler>
363 void AliMUONTrackerDDLDecoder<EventHandler>::DecodeBuffer(
364                 const UChar_t* start, const UChar_t* end
365         )
366 {
367         /// This method decodes the buffer's payload data. It unpacks the block
368         /// structures contained inside and then for each block it calls the
369         /// OnNewBlock method for the event handler to signal the start of each new
370         /// block structure. OnEndOfBlock is called once each block is processed.
371         /// \param start  This is the pointer to the start of the buffer.
372         /// \param end  This is the pointer to the first byte just past the
373         ///             end of the buffer.
374         /// fHadError is set to true if there were any errors decoding the buffer
375         /// and the OnError method of the callback event handler is called for
376         /// each error.
377         
378         const UChar_t* current = start;
379         const UInt_t* bufferStart = reinterpret_cast<const UInt_t*>(start);
380         const UInt_t* bufferEnd = reinterpret_cast<const UInt_t*>(end);
381         bool problemWithTrailer = false;
382         
383         // The DDL payload normally has a 2 word trailer which contains the end of
384         // DDL markers 0xD000000D. But this is not the case for older simulated
385         // data so if we are auto-detecting the trailer then we need to carefully
386         // check if these words are there or not.
387         const UChar_t* endOfBlocks = end;
388         const UInt_t* trailerWords = reinterpret_cast<const UInt_t*>(end) - 2;
389         if (fAutoDetectTrailer)
390         {
391                 if (trailerWords >= bufferStart and trailerWords < bufferEnd
392                     and *trailerWords == fgkEndOfDDL and *(trailerWords+1) == fgkEndOfDDL
393                    )
394                 {
395                         // Found the trailer so reposition the end of blocks marker.
396                         endOfBlocks = reinterpret_cast<const UChar_t*>(trailerWords);
397                 }
398                 // else assume we are dealing with the older data format.
399         }
400         else if (fCheckForTrailer)
401         {
402                 if (trailerWords >= bufferStart and trailerWords < bufferEnd
403                     and *trailerWords == fgkEndOfDDL and *(trailerWords+1) == fgkEndOfDDL
404                    )
405                 {
406                         // Found the trailer so reposition the end of blocks marker.
407                         endOfBlocks = reinterpret_cast<const UChar_t*>(trailerWords);
408                 }
409                 else
410                 {
411                         if (trailerWords+1 >= bufferStart and trailerWords+1 < bufferEnd and *(trailerWords+1) == fgkEndOfDDL)
412                                 fHandler.OnError(EventHandler::kTooFewDDLTrailerWords, trailerWords+1);
413                         else if (trailerWords >= bufferStart and trailerWords < bufferEnd and *(trailerWords) == fgkEndOfDDL)
414                                 fHandler.OnError(EventHandler::kTooFewDDLTrailerWords, trailerWords);
415                         else
416                                 fHandler.OnError(EventHandler::kNoDDLTrailerWords, end);
417         
418                         // Stop the decoding if so requested by the user, otherwise
419                         // remember about the error so that we return false from the
420                         // Decode() method and continue decoding.
421                         fHadError = true;
422                         if (fExitOnError) return;
423                         
424                         // Mark that there was a problem with the trailer so that
425                         // for subsequent errors we try to deal with this better.
426                         problemWithTrailer = true;
427                         
428                         // We can also try figure out how many trailer words there
429                         // actually are and move the end of blocks marker back.
430                         
431                         if (fTryRecover)
432                         {
433                                 trailerWords = bufferEnd;
434                                 // There should only be a max of 2 trailer words.
435                                 if (trailerWords-2 >= bufferStart and trailerWords-2 < bufferEnd and *(trailerWords-2) == fgkEndOfDDL)
436                                         trailerWords -= 2;
437                                 else if (trailerWords-1 >= bufferStart and trailerWords-1 < bufferEnd and *(trailerWords-1) == fgkEndOfDDL)
438                                         trailerWords -= 1;
439                                 endOfBlocks = reinterpret_cast<const UChar_t*>(trailerWords);
440                         }
441                 }
442         }
443
444         UInt_t blockCount = 0; // Indicates the number of blocks decoded.
445         while (current < endOfBlocks)
446         {
447                 // Mark the start of the block structure.
448                 const UChar_t* blockStart = current;
449                 
450                 // Get the block header, move the current pointer just past the end
451                 // of the header and check that we have not overflowed the buffer.
452                 const AliMUONBlockHeaderStruct* blockHeader
453                         = reinterpret_cast<const AliMUONBlockHeaderStruct*>(blockStart);
454                 current += sizeof(AliMUONBlockHeaderStruct);
455                 if (current > endOfBlocks or current < start)
456                 {
457                         // If we overflowed the pointer and already had an error then
458                         // we are clearly lost so just stop decoding before we segfault.
459                         if (current < start and fHadError) return;
460                         
461                         // We first check if we actually hit the end of DDL markers
462                         // If we did then either we did not/could not recover from
463                         // a corrupt trailer or we did not detect a correct trailer
464                         // in auto-detect mode.
465                         trailerWords = reinterpret_cast<const UInt_t*>(blockHeader);
466                         // The "trailerWords+1 <= bufferEnd" checks that we are
467                         // not reading beyond the end of the buffer.
468                         if (trailerWords+1 <= bufferEnd and *trailerWords == fgkEndOfDDL)
469                         {
470                                 // If we aready knew the trailer was corrupt then just
471                                 // return because the error was already announced.
472                                 if (problemWithTrailer) return;
473                                 
474                                 if (fAutoDetectTrailer)
475                                 {
476                                         // If we got here then there is at least one correct trailer
477                                         // word, but since we did not detect a correct trailer then
478                                         // there must be only one. Announce the error and exit.
479                                         fHandler.OnError(EventHandler::kTooFewDDLTrailerWords, trailerWords);
480                                         fHadError = true;
481                                         return;
482                                 }
483                         }
484                         
485                         // So we only got part of a block header at the very end
486                         // of the buffer. Nothing to do but report the error and exit.
487                         if (blockCount == fMaxBlocks)
488                                 // Special case where we got all the blocks we
489                                 // expected, so the remaining data must be rubbish.
490                                 fHandler.OnError(EventHandler::kBufferTooBig, blockHeader);
491                         else
492                                 fHandler.OnError(EventHandler::kNoBlockHeader, blockHeader);
493                         fHadError = true;
494                         return;
495                 }
496                 
497                 // The header fits the buffer so we can mark the data start and
498                 // read from the header to find the end of data and block pointers.
499                 const UChar_t* dataStart = current;
500                 current += blockHeader->fLength * sizeof(UInt_t);
501                 const UChar_t* dataEnd = current;
502                 const UChar_t* blockEnd = blockStart
503                         + blockHeader->fTotalLength * sizeof(UInt_t);
504                 
505                 // Now we need to check for the following things:
506                 // 1) Is the end of block or end of data pointer outside the buffer
507                 //    boundaries.
508                 // 2) Are the values for these pointers the same.
509                 // 3) Is the expected data key in the header present.
510                 // If any of the above fail then we know there is a problem with
511                 // the block header. It must be corrupted somehow.
512                 if (blockHeader->fDataKey != fgkBlockDataKey
513                     or dataEnd > endOfBlocks or dataEnd < start
514                     or blockEnd > endOfBlocks or blockEnd < start
515                     or dataEnd != blockEnd)
516                 {
517                         // So let us see what exactly is wrong and report this.
518                         if (blockCount == fMaxBlocks)
519                         {
520                                 // Special case where we got all the blocks we
521                                 // expected, so the remaining data must be rubbish.
522                                 // Don't even bother trying to recover the data.
523                                 fHandler.OnError(EventHandler::kBufferTooBig, blockHeader);
524                                 fHadError = true;
525                                 return;
526                         }
527                         if (blockHeader->fDataKey != fgkBlockDataKey)
528                                 fHandler.OnError(EventHandler::kBadBlockKey, &blockHeader->fDataKey);
529                         if (blockEnd > endOfBlocks or blockEnd < start)
530                                 fHandler.OnError(EventHandler::kBadBlockLength, &blockHeader->fLength);
531                         if (dataEnd > endOfBlocks or dataEnd < start)
532                                 fHandler.OnError(EventHandler::kBadBlockTotalLength, &blockHeader->fTotalLength);
533                         if (dataEnd != blockEnd)
534                                 fHandler.OnError(EventHandler::kBlockLengthMismatch, blockHeader);
535                         
536                         // Stop the decoding if so requested by the user, otherwise
537                         // remember about the error so that we return false from the
538                         // Decode() method and continue decoding.
539                         fHadError = true;
540                         if (fExitOnError) return;
541                         
542                         // Try to recover from the corrupt header.
543                         RecoverResult result = TryRecoverStruct(
544                                         fgkBlockDataKey, sizeof(AliMUONBlockHeaderStruct),
545                                         blockHeader->fTotalLength, blockHeader->fLength,
546                                         blockStart, endOfBlocks, dataEnd, blockEnd, current
547                                 );
548                         if (result == kContinueToNextStruct)
549                                 continue; // Try the next block at 'current'.
550                         if (result == kRecoverFailed) return;
551                 }
552                 
553                 // At this point we certainly have a valid block header, so we
554                 // need to check if we have more blocks than we expected. If not
555                 // then we can indicate we have another block and decode its data.
556                 if (++blockCount > fMaxBlocks)
557                 {
558                         fHandler.OnError(EventHandler::kTooManyBlocks, current);
559                         
560                         // In this case we stop the decoding because clearly
561                         // something is seriously wrong with the data if we are
562                         // getting more blocks than expected.
563                         fHadError = true;
564                         return;
565                 }
566                 
567                 fHandler.OnNewBlock(blockHeader, dataStart);
568                 if (not DecodeBlockData(blockHeader, dataStart, dataEnd))
569                 {
570                         // At this point we had a problem decoding the block structure's
571                         // data. Thus we should stop further decoding if so requested by
572                         // the user. Note the fHadError flag is already marked inside
573                         // DecodeBlockData.
574                         if (fExitOnError)
575                         {
576                                 fHandler.OnEndOfBlock(blockHeader, dataStart);
577                                 return;
578                         }
579                 }
580                 fHandler.OnEndOfBlock(blockHeader, dataStart);
581         }
582 }
583
584
585 template <class EventHandler>
586 bool AliMUONTrackerDDLDecoder<EventHandler>::DecodeBlockData(
587                 const AliMUONBlockHeaderStruct* blockHeader,
588                 const UChar_t* start, const UChar_t* end
589         )
590 {
591         /// This method decodes a block structure's data payload. It unpacks the
592         /// DSP structures contained inside and then for each DSP it calls the
593         /// OnNewDSP method for the event handler to signal the start of each new
594         /// DSP structure.
595         /// \param blockHeader
596         /// \param start  This is the pointer to the start of the block
597         ///               structure's data.
598         /// \param end  This is the pointer to the first byte just past the
599         ///             end of the block structure.
600         /// \return If the block structure's data was decoded without errors
601         ///      or we could recover from the errors, then true is returned.
602         ///      False is returned otherwise.
603         
604         const UChar_t* current = start;
605         
606         UInt_t dspCount = 0; // Indicates the number of DSPs decoded.
607         while (current < end)
608         {
609                 // Mark the start of the DSP structure.
610                 const UChar_t* dspStart = current;
611                 
612                 // Get the DSP header, move the current pointer just past the end
613                 // of the header and check that we have not overflowed the buffer.
614                 const AliMUONDSPHeaderStruct* dspHeader
615                         = reinterpret_cast<const AliMUONDSPHeaderStruct*>(dspStart);
616                 current += sizeof(AliMUONDSPHeaderStruct);
617                 if (current > end or current < start)
618                 {
619                         // If we overflowed the pointer and already had an error then
620                         // we are clearly lost so just stop decoding before we segfault.
621                         if (current < start and fHadError) return false;
622                         
623                         // So we only got part of a DSP header at the very end of
624                         // the block structure buffer. Nothing to do but report the
625                         // error and exit. Set fHadError in case of further decoding.
626                         fHandler.OnError(EventHandler::kNoDSPHeader, dspHeader);
627                         fHadError = true;
628                         return false;
629                 }
630                 
631                 // The header fits the buffer so we can mark the data start and
632                 // read from the header to find the end of data and DSP pointers.
633                 const UChar_t* dataStart = current;
634                 current += dspHeader->fLength * sizeof(UInt_t);
635                 const UChar_t* dataEnd = current;
636                 const UChar_t* dspEnd = dspStart + dspHeader->fTotalLength * sizeof(UInt_t);
637                 
638                 // Now we need to check for the following things:
639                 // 1) Is the end of DSP or end of data pointer outside the buffer
640                 //    boundaries.
641                 // 2) Are the values for these pointers the same.
642                 // 3) Is the expected data key in the header present.
643                 // If any of the above fail then we know there is a problem with
644                 // the DSP header. It must be corrupted somehow.
645                 if (dspHeader->fDataKey != fgkDSPDataKey
646                     or dataEnd > end or dataEnd < start
647                     or dspEnd > end or dspEnd < start
648                     or dataEnd != dspEnd)
649                 {
650                         // So let us see what exactly is wrong and report this.
651                         if (dspHeader->fDataKey != fgkDSPDataKey)
652                                 fHandler.OnError(EventHandler::kBadDSPKey, &dspHeader->fDataKey);
653                         if (dspEnd > end or dspEnd < start)
654                                 fHandler.OnError(EventHandler::kBadDSPLength, &dspHeader->fLength);
655                         if (dataEnd > end or dataEnd < start)
656                                 fHandler.OnError(EventHandler::kBadDSPTotalLength, &dspHeader->fTotalLength);
657                         if (dataEnd != dspEnd)
658                                 fHandler.OnError(EventHandler::kDSPLengthMismatch, dspHeader);
659                         
660                         // Indicate we had and error and stop the decoding if so
661                         // requested by the user.
662                         fHadError = true;
663                         if (fExitOnError) return false;
664                         
665                         // Try to recover from the corrupt header.
666                         RecoverResult result = TryRecoverStruct(
667                                         fgkDSPDataKey, sizeof(AliMUONDSPHeaderStruct),
668                                         dspHeader->fTotalLength, dspHeader->fLength,
669                                         dspStart, end, dataEnd, dspEnd, current
670                                 );
671                         if (result == kContinueToNextStruct)
672                                 continue; // Try the next DSP at 'current'.
673                         if (result == kRecoverFailed) return false;
674                 }
675                 
676                 // At this point we certainly have a valid DSP header, so we
677                 // need to check if we have more DSPs than we expected. If not
678                 // then we can indicate we have another DSP and decode its data.
679                 if (++dspCount > fMaxDSPs)
680                 {
681                         fHandler.OnError(EventHandler::kTooManyDSPs, current);
682                         
683                         // In this case we stop further decoding of the block
684                         // structure data because clearly something is seriously
685                         // wrong if we are getting more DSPs than expected.
686                         // Indicate that we had an error so the Decode() method
687                         // returns false.
688                         fHadError = true;
689                         return false;
690                 }
691                 
692                 fHandler.OnNewDSP(dspHeader, dataStart);
693                 
694                 // Check the error word in the header.
695                 if (dspHeader->fErrorWord != 0x0)
696                 {
697                         if (dspHeader->fErrorWord == (0x000000B1 | blockHeader->fDSPId)
698                             or dspHeader->fErrorWord == (0x00000091 | blockHeader->fDSPId)
699                            )
700                         {
701                                 // An event with a glitch in the readout has been detected.
702                                 // It means that somewhere a 1 byte word has been randomly
703                                 // inserted and all the readout sequence is shifted until
704                                 // the next event.
705                                 fHandler.OnError(EventHandler::kGlitchFound, &dspHeader->fErrorWord);
706                         }
707                         else if ((dspHeader->fErrorWord & 0x0000FFF0) == 0x220)
708                         {
709                                 // Detected a TOKEN_LOST error which can affect the dead time in the DAQ.
710                                 fHandler.OnError(EventHandler::kTokenLost, &dspHeader->fErrorWord);
711                         }
712                         else
713                         {
714                                 // The DSP error code is non-zero but has an unknown code.
715                                 fHandler.OnError(EventHandler::kUnknownDspError, &dspHeader->fErrorWord);
716                         }
717                         
718                         fHadError = true;
719                         if (fExitOnError)
720                         {
721                                 fHandler.OnEndOfDSP(dspHeader, dataStart);
722                                 return false;
723                         }
724                         
725                         // Try recover by finding the very next DSP and continue
726                         // decoding from there. Note: to achieve all we have to do
727                         // is continue to the next iteration, because the logic
728                         // will land up calling the FindKey method within the
729                         // TryRecoverStruct method above.
730                         if (fTryRecover) continue;
731                 }
732                 
733                 // Check if we are padding. If we are, then the bus patch data is
734                 // actually 4 bytes smaller and the last word is a padding word.
735                 if (dspHeader->fPaddingWord == 1)
736                 {
737                         dataEnd -= sizeof(UInt_t);
738                         
739                         // Check the pad word is correct.
740                         const UInt_t* padWord = reinterpret_cast<const UInt_t*>(dataEnd);
741                         if (*padWord != fgkPaddingWord)
742                         {
743                                 fHandler.OnError(EventHandler::kBadPaddingWord, padWord);
744                                 fHadError = true;
745                                 if (fExitOnError)
746                                 {
747                                         fHandler.OnEndOfDSP(dspHeader, dataStart);
748                                         return false;
749                                 }
750                         }
751                 }
752                 
753                 if (not DecodeDSPData(dataStart, dataEnd))
754                 {
755                         // At this point we had a problem decoding the DSP structure's
756                         // data, thus we should stop further decoding if so requested by
757                         // the user. Note the fHadError flag is already marked inside
758                         // DecodeDSPData.
759                         if (fExitOnError)
760                         {
761                                 fHandler.OnEndOfDSP(dspHeader, dataStart);
762                                 return false;
763                         }
764                 }
765                 fHandler.OnEndOfDSP(dspHeader, dataStart);
766         }
767         
768         return true;
769 }
770
771
772 template <class EventHandler>
773 bool AliMUONTrackerDDLDecoder<EventHandler>::DecodeDSPData(
774                 const UChar_t* start, const UChar_t* end
775         )
776 {
777         /// This method decodes a DSP structure's data payload. It finds all the
778         /// bus patches found inside and for each it calls the OnNewBusPatch method
779         /// for the event handler to signal the start of each new bus patch.
780         /// \param start  This is the pointer to the start of the DSP structure's data.
781         /// \param end  This is the pointer to the first byte just past the
782         ///             end of the DSP structure.
783         /// \return If the DSP structure's data was decoded without errors
784         ///      or we could recover from the errors, then true is returned.
785         ///      False is returned otherwise.
786         
787         const UChar_t* current = start;
788         
789         UInt_t busPatchCount = 0; // Indicates the number of bus patches decoded.
790         while (current < end)
791         {
792                 // Mark the start of the bus patch structure.
793                 const UChar_t* busPatchStart = current;
794                 
795                 // Get the bus patch header, move the current pointer just past
796                 // the end of the header and check that we have not overflowed
797                 // the buffer.
798                 const AliMUONBusPatchHeaderStruct* busPatchHeader
799                         = reinterpret_cast<const AliMUONBusPatchHeaderStruct*>(busPatchStart);
800                 current += sizeof(AliMUONBusPatchHeaderStruct);
801                 if (current > end or current < start)
802                 {
803                         // If we overflowed the pointer and already had an error then
804                         // we are clearly lost so just stop decoding before we segfault.
805                         if (current < start and fHadError) return false;
806                         
807                         // So we only got part of a bus patch header at the very
808                         // end of the DSP structure buffer. Nothing to do but
809                         // report the error and exit. Set fHadError in case of
810                         // further decoding.
811                         fHandler.OnError(EventHandler::kNoBusPatchHeader, busPatchHeader);
812                         fHadError = true;
813                         return false;
814                 }
815                 
816                 // The header fits the buffer so we can mark the data start and
817                 // read from the header to find the end of data and bus patch
818                 // structure pointers.
819                 const UChar_t* dataStart = current;
820                 current += busPatchHeader->fLength * sizeof(UInt_t);
821                 const UChar_t* dataEnd = current;
822                 const UChar_t* busPatchEnd = busPatchStart
823                         + busPatchHeader->fTotalLength * sizeof(UInt_t);
824                 
825                 // Now we need to check for the following things:
826                 // 1) Is the end of bus patch structure or end of data pointer
827                 //    outside the buffer boundaries.
828                 // 2) Are the values for these pointers the same.
829                 // 3) Is the expected data key in the header present.
830                 // If any of the above fail then we know there is a problem with
831                 // the bus patch header. It must be corrupted somehow.
832                 if (busPatchHeader->fDataKey != fgkBusPatchDataKey
833                     or dataEnd > end or dataEnd < start
834                     or busPatchEnd > end or busPatchEnd < start
835                     or dataEnd != busPatchEnd)
836                 {
837                         // So let us see what exactly is wrong and report this.
838                         if (busPatchHeader->fDataKey != fgkBusPatchDataKey)
839                                 fHandler.OnError(EventHandler::kBadBusPatchKey, &busPatchHeader->fDataKey);
840                         if (busPatchEnd > end or busPatchEnd < start)
841                                 fHandler.OnError(EventHandler::kBadBusPatchLength, &busPatchHeader->fLength);
842                         if (dataEnd > end or dataEnd < start)
843                                 fHandler.OnError(EventHandler::kBadBusPatchTotalLength, &busPatchHeader->fTotalLength);
844                         if (dataEnd != busPatchEnd)
845                                 fHandler.OnError(EventHandler::kBusPatchLengthMismatch, busPatchHeader);
846                         
847                         // Indicate we had and error and stop the decoding if so
848                         // requested by the user.
849                         fHadError = true;
850                         if (fExitOnError) return false;
851                         
852                         // Try to recover from the corrupt header.
853                         RecoverResult result = TryRecoverStruct(
854                                         fgkBusPatchDataKey, sizeof(AliMUONBusPatchHeaderStruct),
855                                         busPatchHeader->fTotalLength, busPatchHeader->fLength,
856                                         busPatchStart, end, dataEnd, busPatchEnd, current
857                                 );
858                         if (result == kContinueToNextStruct)
859                                 continue; // Try the next bus patch at 'current'.
860                         if (result == kRecoverFailed) return false;
861                 }
862                 
863                 // At this point we certainly have a valid bus patch header, so
864                 // we need to check if we have more bus patches than we expected.
865                 // If not then we can indicate we have another bus patch and
866                 // decode its data.
867                 if (++busPatchCount > fMaxBusPatches)
868                 {
869                         fHandler.OnError(EventHandler::kTooManyBusPatches, current);
870                         
871                         // In this case we stop further decoding of the DSP
872                         // structure's data because clearly something is seriously
873                         // wrong if we are getting more bus patches than expected.
874                         // Indicate that we had an error so the Decode() method
875                         // returns false.
876                         fHadError = true;
877                         return false;
878                 }
879                 
880                 fHandler.OnNewBusPatch(busPatchHeader, dataStart);
881                 if (not DecodeBusPatchData(dataStart, dataEnd))
882                 {
883                         // At this point we had a problem decoding the bus patch data,
884                         // thus we should stop further decoding if so requested by the
885                         // user. Note the fHadError flag is already marked inside
886                         // DecodeBusPatchData.
887                         if (fExitOnError)
888                         {
889                                 fHandler.OnEndOfBusPatch(busPatchHeader, dataStart);
890                                 return false;
891                         }
892                 }
893                 fHandler.OnEndOfBusPatch(busPatchHeader, dataStart);
894         }
895         
896         return true;
897 }
898
899
900 template <class EventHandler>
901 bool AliMUONTrackerDDLDecoder<EventHandler>::DecodeBusPatchData(
902                 const UChar_t* start, const UChar_t* end
903         )
904 {
905         /// This method decodes a single bus patch's data payload.
906         /// It will check the parity of the raw data words and send them
907         /// to the event handler instance with calls to OnData.
908         /// \param start  This is the pointer to the start of the bus patch
909         ///               structure's data.
910         /// \param end  This is the pointer to the first byte just past the
911         ///             end of the bus patch structure.
912         /// \return If the bus patch's data was decoded without errors
913         ///      or we could recover from the errors, then true is returned.
914         ///      False is returned otherwise.
915
916         // Assert that 'end' is always larger than start by n*sizeof(UInt_t)
917         // where n is a positive integer. This should be the case because we
918         // always add multiples of sizeof(UInt_t) to the 'current' pointer in
919         // all the DecodeXYZ methods.
920         assert( UInt_t(end - start) % 4 == 0 );
921         
922         // Now step through all the data words and issue OnData events.
923         // We also need to check parity and signal OnError if it is not valid
924         // for any of the data words.
925         const UInt_t* data = reinterpret_cast<const UInt_t*>(start);
926         const UInt_t* dataEnd = reinterpret_cast<const UInt_t*>(end);
927         for (; data < dataEnd; data++)
928         {
929                 if (ParityIsOk(*data))
930                 {
931                         fHandler.OnData(*data, false);
932                 }
933                 else
934                 {
935                         // Indicate we had a parity error and exit immediately
936                         // if the user so requested.
937                         fHandler.OnError(EventHandler::kParityError, data);
938                         fHadError = true;
939                         if (fExitOnError) return false;
940                         
941                         if (fSendDataOnParityError)
942                                 fHandler.OnData(*data, true);
943                 }
944         }
945         
946         return true;
947 }
948
949
950 template <class EventHandler>
951 typename AliMUONTrackerDDLDecoder<EventHandler>::RecoverResult
952 AliMUONTrackerDDLDecoder<EventHandler>::TryRecoverStruct(
953                 UInt_t expectedKey,
954                 UInt_t headerSize,
955                 UInt_t totalLength,
956                 UInt_t length,
957                 const UChar_t* structStart,
958                 const UChar_t* bufferEnd,
959                 const UChar_t*& dataEnd,
960                 const UChar_t*& structEnd,
961                 const UChar_t*& current
962         )
963 {
964         /// This method attempts to recover from a corrupt structure header by
965         /// figuring out which of the structure size indicators is correct.
966         /// This is possible because each header has some redundant information.
967         /// The recovery procedure is only attempted if fTryRecover was set to
968         /// true. If the recovery procedure is successful then this method will
969         /// also update the pointers indicating the start of data, end of structure
970         /// and current parsing position with the correct values.
971         ///
972         /// [in]  \param expectedKey This is the expected block key for the header
973         ///           currently being processed.
974         /// [in]  \param headerSize  The expected header size as given by the sizeof
975         ///           operator for example.
976         /// [in]  \param totalLength The total length as given by the fTotalLength
977         ///           field in the current header being handled.
978         /// [in]  \param length  The data length as given by the fLength field
979         ///           in the current header being handled.
980         /// [in]  \param structStart A pointer to the start of the structure header.
981         /// [in]  \param bufferEnd A pointer to the first byte just past the end
982         ///           of the buffer. This could be the pointer to the first byte
983         ///           just past the end of the parent structure if we are dealing
984         ///           with a DSP structure or bus patch. The parent structure for
985         ///           the DSP is a block structure and for a bus patch it is a DSP.
986         /// [out] \param dataEnd This is the pointer to the first byte just past
987         ///           the end of the structure being processed. It should be equal to
988         ///           structStart + sizeof(structure header) + fLength, where fLength
989         ///           is the field found in the structure's header itself. This value
990         ///           will be corrected and updated if we could recover from the
991         ///           corruption in the header.
992         /// [out] \param structEnd A pointer to the first byte just past the end of
993         ///           the structure. This value should be set equal to
994         ///           structStart + fTotalLength * sizeof(UInt_t), where fTotalLength
995         ///           is the field found in the structure's header itself. This value
996         ///           will be corrected and updated if we could recover from the
997         ///           corruption in the header.
998         /// [out] \param current This is the pointer to the current location in
999         ///           the DDL payload being parsed. It should in principle point
1000         ///           to the start of the structures data. This value will be
1001         ///           corrected and updated if we could recover from the corruption
1002         ///           in the header.
1003         ///
1004         /// \return Returns the result of the recovery attempt, which can be one
1005         ///    of the following:
1006         ///      kRecoverFailed - The recovery failed completely so the caller
1007         ///           cannot continue parsing any more structures. If the failure
1008         ///           is within a DSP then one could still continue parsing
1009         ///           from the next block. Similarly for bus patches, parsing could
1010         ///           continue from the next DSP structure.
1011         ///      kStructRecovered - Indicates that we recovered from a corrupt
1012         ///           structure header and can continue processing the data of the
1013         ///           structure in question.
1014         ///      kContinueToNextStruct - Either fTryRecover was set to false or we
1015         ///           could not recover from the corrupt header but we did find the
1016         ///           start of another header matching the expected key so parsing
1017         ///           can continue from the updated current position.
1018
1019         // Check if the user wants us to try and recover from a corrupt header.
1020         if (not fTryRecover) return kContinueToNextStruct;
1021         
1022         // If the user wants us to try recover, then try to recover what the
1023         // correct values for dataEnd, structEnd and current were supposed to be.
1024         // The recovery procedure is as follows: We have 4 conditions for a correct
1025         // header:
1026         //   1) The header key is what we expect.
1027         //   2) The totalLength equals length + headerSize.
1028         //   3) The word at dataEnd contains a valid key. (implies length is
1029         //      correct.)
1030         //   4) The word at structEnd contains a valid key. (implies totalLength
1031         //      is correct.)
1032         // If any 2 of these conditions hold then we know that only one of the
1033         // header fields is corrupt and we have enough information to reconstruct
1034         // the third field. Note that if conditions 3 and 4 are true then this
1035         // implies 2 is also true. (not necessarily the other way around though.)
1036         // The valid key mentioned above at dataEnd and structEnd should be:
1037         //   a) A bus patch key, DSP key or end of buffer if expectedKey indicates
1038         //      a buspatch.
1039         //   b) A DSP key, block structure key or end of buffer if expectedKey
1040         //      indicates a DSP.
1041         //   c) A block structure key or end of buffer if expectedKey indicates
1042         //      a DSP.
1043         const UInt_t* headerKey = reinterpret_cast<const UInt_t*>(structStart);
1044         bool headerKeyOk = (expectedKey == *headerKey);
1045         
1046         bool lengthsMatch = (totalLength*4 == length*4 + headerSize);
1047         
1048         bool lengthIsCorrect = false;
1049         bool totalLengthIsCorrect = false;
1050         const UInt_t* keyAtDataEnd = reinterpret_cast<const UInt_t*>(dataEnd);
1051         const UInt_t* keyAtStructEnd = reinterpret_cast<const UInt_t*>(structEnd);
1052         
1053
1054         if ( expectedKey == fgkBlockDataKey )
1055         {
1056                 if (dataEnd == bufferEnd)
1057                 {
1058                         // Are we at the end of the buffer?
1059                         lengthIsCorrect = true;
1060                 }
1061                 else
1062                 {
1063                         // Must check that we can read another 4 bytes before
1064                         // checking the key at dataEnd.
1065                         if (dataEnd + sizeof(UInt_t) <= bufferEnd and dataEnd + sizeof(UInt_t) > structStart)
1066                         {
1067                                 if (*keyAtDataEnd == fgkBlockDataKey)
1068                                         lengthIsCorrect = true;
1069                         }
1070                 }
1071                 
1072                 if (structEnd == bufferEnd)
1073                 {
1074                         // Are we at the end of the buffer?
1075                         totalLengthIsCorrect = true;
1076                 }
1077                 else
1078                 {
1079                         // Must check that we can read another 4 bytes before
1080                         // checking the key at structEnd.
1081                         if (structEnd + sizeof(UInt_t) <= bufferEnd and structEnd + sizeof(UInt_t) > structStart)
1082                         {
1083                                 if (*keyAtStructEnd == fgkBlockDataKey)
1084                                         totalLengthIsCorrect = true;
1085                         }
1086                 }
1087         }        
1088                         
1089         else if ( expectedKey == fgkDSPDataKey )
1090         {
1091                 if (dataEnd == bufferEnd)
1092                 {
1093                         // Are we at the end of the buffer?
1094                         lengthIsCorrect = true;
1095                 }
1096                 else
1097                 {
1098                         // Must check that we can read another 4 bytes before
1099                         // checking the key at dataEnd.
1100                         if (dataEnd + sizeof(UInt_t) <= bufferEnd and dataEnd + sizeof(UInt_t) > structStart)
1101                         {
1102                                 if (*keyAtDataEnd == fgkBlockDataKey
1103                                     or *keyAtDataEnd == fgkDSPDataKey)
1104                                         lengthIsCorrect = true;
1105                         }
1106                 }
1107                 
1108                 if (structEnd == bufferEnd)
1109                 {
1110                         // Are we at the end of the buffer?
1111                         totalLengthIsCorrect = true;
1112                 }
1113                 else
1114                 {
1115                         // Must check that we can read another 4 bytes before
1116                         // checking the key at structEnd.
1117                         if (structEnd + sizeof(UInt_t) <= bufferEnd and structEnd + sizeof(UInt_t) > structStart)
1118                         {
1119                                 if (*keyAtStructEnd == fgkBlockDataKey
1120                                     or *keyAtStructEnd == fgkDSPDataKey)
1121                                         totalLengthIsCorrect = true;
1122                         }
1123                 }
1124         }        
1125         else if ( expectedKey == fgkBusPatchDataKey )
1126         {
1127                 if (dataEnd == bufferEnd)
1128                 {
1129                         // Are we at the end of the buffer?
1130                         lengthIsCorrect = true;
1131                 }
1132                 else
1133                 {
1134                         // Must check that we can read another 4 bytes before
1135                         // checking the key at dataEnd.
1136                         if (dataEnd + sizeof(UInt_t) <= bufferEnd and dataEnd + sizeof(UInt_t) > structStart)
1137                         {
1138                                 if (*keyAtDataEnd == fgkDSPDataKey
1139                                     or *keyAtDataEnd == fgkBusPatchDataKey)
1140                                         lengthIsCorrect = true;
1141                         }
1142                 }
1143                 
1144                 if (structEnd == bufferEnd)
1145                 {
1146                         // Are we at the end of the buffer?
1147                         totalLengthIsCorrect = true;
1148                 }
1149                 else
1150                 {
1151                         // Must check that we can read another 4 bytes before
1152                         // checking the key at structEnd.
1153                         if (structEnd + sizeof(UInt_t) <= bufferEnd and structEnd + sizeof(UInt_t) > structStart)
1154                         {
1155                                 if (*keyAtStructEnd == fgkDSPDataKey
1156                                     or *keyAtStructEnd == fgkBusPatchDataKey)
1157                                         totalLengthIsCorrect = true;
1158                         }
1159                 }
1160         }
1161         
1162         if (headerKeyOk and lengthIsCorrect)
1163         {
1164                 // totalLength was wrong, dataEnd is correct.
1165                 structEnd = dataEnd;
1166                 current = dataEnd;
1167                 return kStructRecovered;
1168         }
1169         if (headerKeyOk and totalLengthIsCorrect)
1170         {
1171                 // Length was wrong, structEnd is correct.
1172                 dataEnd = structEnd;
1173                 current = structEnd;
1174                 return kStructRecovered;
1175         }
1176         if (lengthsMatch and lengthIsCorrect and totalLengthIsCorrect)
1177         {
1178                 // The header's key was wrong but the lengths and pointers are OK.
1179                 return kStructRecovered;
1180         }
1181         
1182         // Could not recover the header from the available information, so find
1183         // the next key in the stream that is the same as the currently expected
1184         // one and continue decoding from there.
1185         const UChar_t* location = FindKey(
1186                         expectedKey, structStart + sizeof(UInt_t), bufferEnd
1187                 );
1188         if (location != NULL)
1189         {
1190                 current = location;
1191                 return kContinueToNextStruct;
1192         }
1193
1194         return kRecoverFailed;
1195 }
1196
1197
1198 template <class EventHandler>
1199 const UChar_t* AliMUONTrackerDDLDecoder<EventHandler>::FindKey(
1200                 UInt_t key, const UChar_t* start, const UChar_t* end
1201         )
1202 {
1203         /// Searches for the first occurrence of the key value in the buffer marked by
1204         /// 'start' and 'end'. 'start' should point to the start of the buffer and 'end'
1205         /// should point to 'start + bufferSize', i.e. just past the last byte of the
1206         /// buffer. If the key was found then the pointer to that location is returned
1207         /// otherwise NULL is returned.
1208         
1209         if (end + sizeof(UInt_t) < start) return NULL;  // check for pointer overflow.
1210         const UChar_t* current = start;
1211         while (current + sizeof(UInt_t) <= end)
1212         {
1213                 UInt_t data = * reinterpret_cast<const UInt_t*>(current);
1214                 if (data == key) return current;
1215                 current++;
1216         }
1217         return NULL;
1218 }
1219
1220
1221 template <class EventHandler>
1222 bool AliMUONTrackerDDLDecoder<EventHandler>::ParityIsOk(UInt_t data)
1223 {
1224         /// Optimised parity check addapted from:
1225         /// http://graphics.stanford.edu/~seander/bithacks.html#ParityParallel
1226         
1227         // parity of the 32 bits must be zero if the last bit is equal
1228         // to the parity of the first 31 bits.
1229         // Reason: the parity bit xor the parity of the first 31 bits must give
1230         // zero, unless there was a bit error.
1231         data ^= data >> 16;
1232         data ^= data >> 8;
1233         data ^= data >> 4;
1234         data &= 0xf;
1235         data = ((0x6996 >> data) & 1);
1236         return data == 0;
1237 }
1238
1239 #endif // ALIMUONTRACKERDDLDECODER_H