]> git.uio.no Git - u/mrichter/AliRoot.git/blob - MUON/AliMUONRawStreamTrackerHP.cxx
Sergey: bug fix with storing cluster id's
[u/mrichter/AliRoot.git] / MUON / AliMUONRawStreamTrackerHP.cxx
1 /**************************************************************************
2  * This file is property of and copyright by the ALICE HLT Project        *
3  * All rights reserved.                                                   *
4  *                                                                        *
5  * Primary Authors:                                                       *
6  *   Artur Szostak <artursz@iafrica.com>                                  *
7  *                                                                        *
8  * Permission to use, copy, modify and distribute this software and its   *
9  * documentation strictly for non-commercial purposes is hereby granted   *
10  * without fee, provided that the above copyright notice appears in all   *
11  * copies and that both the copyright notice and this permission notice   *
12  * appear in the supporting documentation. The authors make no claims     *
13  * about the suitability of this software for any purpose. It is          *
14  * provided "as is" without express or implied warranty.                  *
15  **************************************************************************/
16
17 /* $Id$*/
18
19 ///
20 /// \file   AliMUONRawStreamTrackerHP.cxx
21 /// \author Artur Szostak <artursz@iafrica.com>
22 /// \date   29-11-2007
23 /// \brief  Implementation of the the high performance decoder AliMUONRawStreamTrackerHP.
24 ///
25
26 //-----------------------------------------------------------------------------
27 /// \ingroup raw
28 /// \class AliMUONRawStreamTrackerHP
29 /// \brief A high performance stream decoder for muon tracking DDL streams.
30 ///
31 /// This is the raw stream class which interfaces between the high performance
32 /// core decoder and the AliRawReader class.
33 /// To gain the most out of the decoder, the Next() method which returns batches
34 /// of decoded digit / channel information should be used. That is:
35 /// \code
36 ///   const AliBusPatch* Next();
37 /// \endcode
38 ///
39 /// This decoder tries to implement as similar an interface as possible to
40 /// AliMUONRawStreamTracker where possible. However certain constructs which
41 /// would slow us down too much are avoided.
42 ///
43 /// \author Artur Szostak <artursz@iafrica.com>
44 //-----------------------------------------------------------------------------
45
46 #include "AliMUONRawStreamTrackerHP.h"
47 #include "AliMUONTrackerDDLDecoder.h"
48 #include "AliMUONDspHeader.h"
49 #include "AliMUONBlockHeader.h"
50 #include "AliMUONBusStruct.h"
51 #include "AliMUONDDLTracker.h"
52 #include "AliMUONLogger.h"
53 #include "AliRawReader.h"
54 #include "AliLog.h"
55 #include "AliDAQ.h"
56 #include <cassert>
57 #include <iostream>
58 using std::cout;
59 using std::endl;
60 using std::hex;
61 using std::dec;
62
63 /// \cond CLASSIMP
64 ClassImp(AliMUONRawStreamTrackerHP)
65 /// \endcond
66
67 const Int_t AliMUONRawStreamTrackerHP::fgkMaxDDL = 20;
68
69 AliMUONRawStreamTrackerHP::AliMUONRawStreamTrackerHP() :
70         TObject(),
71         fRawReader(NULL),
72         fLogger(NULL),
73         fDetailLevel(kMediumErrorDetail),
74         fEnableMUONErrorLogger(kFALSE),
75         fEnableRawReaderErrorLogger(kFALSE),
76         fWarnings(kTRUE),
77         fDecoder(),
78         fDDL(0),
79         fBufferSize(8192),
80         fBuffer(new UChar_t[8192]),
81         fkCurrentBusPatch(NULL),
82         fkCurrentData(NULL),
83         fkEndOfData(NULL),
84         fHadError(kFALSE),
85         fDone(kFALSE),
86         fDDLObject(NULL),
87         fTotalNumberOfGlitchErrors(0),
88         fTotalNumberOfParityErrors(0),
89         fTotalNumberOfPaddingErrors(0),
90         fTotalNumberOfTokenLostErrors(0)
91 {
92         ///
93         /// Default constructor.
94         ///
95         
96         // Must set this flag to get all information about parity errors though
97         // the OnData method. OnError gets them either way.
98         fDecoder.ExitOnError(false);
99         fDecoder.SendDataOnParityError(true);
100
101         fDecoder.GetHandler().SetMaxStructs(
102                         fDecoder.MaxBlocks(),
103                         fDecoder.MaxDSPs(),
104                         fDecoder.MaxBusPatches()
105                 );
106         
107         fDecoder.GetHandler().SetRawStream(this);
108 }
109
110
111 AliMUONRawStreamTrackerHP::AliMUONRawStreamTrackerHP(AliRawReader* rawReader) :
112         TObject(),
113         fRawReader(rawReader),
114         fLogger(NULL),
115         fDetailLevel(kMediumErrorDetail),
116         fEnableMUONErrorLogger(kFALSE),
117         fEnableRawReaderErrorLogger(kFALSE),
118         fWarnings(kTRUE),
119         fDecoder(),
120         fDDL(0),
121         fBufferSize(8192),
122         fBuffer(new UChar_t[8192]),
123         fkCurrentBusPatch(NULL),
124         fkCurrentData(NULL),
125         fkEndOfData(NULL),
126         fHadError(kFALSE),
127         fDone(kFALSE),
128         fDDLObject(NULL),
129         fTotalNumberOfGlitchErrors(0),
130         fTotalNumberOfParityErrors(0),
131         fTotalNumberOfPaddingErrors(0),
132         fTotalNumberOfTokenLostErrors(0)
133 {
134         ///
135         /// Constructor with AliRawReader as argument.
136         ///
137         
138         // Must set this flag to get all information about parity errors though
139         // the OnData method. OnError gets them either way.
140         fDecoder.ExitOnError(false);
141         fDecoder.SendDataOnParityError(true);
142
143         fDecoder.GetHandler().SetMaxStructs(
144                         fDecoder.MaxBlocks(),
145                         fDecoder.MaxDSPs(),
146                         fDecoder.MaxBusPatches()
147                 );
148         
149         fDecoder.GetHandler().SetRawStream(this);
150 }
151
152
153 AliMUONRawStreamTrackerHP::~AliMUONRawStreamTrackerHP()
154 {
155         ///
156         /// Default destructor.
157         ///
158         
159         if (fBuffer != NULL)
160         {
161                 delete [] fBuffer;
162         }
163         if (fDDLObject != NULL)
164         {
165                 delete fDDLObject;
166         }
167 }
168
169
170 void AliMUONRawStreamTrackerHP::First()
171 {
172         /// Initialise or reset the iterator.
173         /// The first DDL will be found and decoded.
174         
175         assert( GetReader() != NULL );
176         
177         fDDL = 0;
178         fDone = kFALSE;
179         NextDDL();
180         fTotalNumberOfGlitchErrors = 0;
181         fTotalNumberOfPaddingErrors = 0;
182         fTotalNumberOfParityErrors = 0;
183         fTotalNumberOfTokenLostErrors = 0;
184 }
185
186
187 Bool_t AliMUONRawStreamTrackerHP::NextDDL()
188 {
189         /// Reading the next tracker DDL and decode the payload with the 
190         /// high performance decoder.
191         /// \return kTRUE if the next DDL was successfully read and kFALSE otherwise.
192
193         assert( GetReader() != NULL );
194         
195         // The temporary object if generated in GetDDLTracker, is now stale,
196         // so delete it.
197         if (fDDLObject != NULL)
198         {
199                 delete fDDLObject;
200                 fDDLObject = NULL;
201         }
202         
203         // Better to reset these pointers.
204         fkCurrentBusPatch = NULL;
205         fkCurrentData = NULL;
206         fkEndOfData = NULL;
207         
208         while (fDDL < GetMaxDDL())
209         {
210                 GetReader()->Reset();
211                 GetReader()->Select("MUONTRK", fDDL, fDDL);  // Select the DDL file to be read.
212                 if (GetReader()->ReadHeader()) break;
213                 AliDebug(3, Form("Skipping DDL %d which does not seem to be there", fDDL+1));
214                 fDDL++;
215         }
216
217         // If we reach the end of the DDL list for this event then reset the
218         // DDL counter, mark the iteration as done and exit.
219         if (fDDL >= GetMaxDDL())
220         {
221                 fDDL = 0;
222                 fDone = kTRUE;
223                 return kFALSE;
224         }
225         else
226         {
227                 fDone = kFALSE;
228         }
229
230         AliDebug(3, Form("DDL Number %d\n", fDDL));
231         
232         Int_t dataSize = GetReader()->GetDataSize(); // in bytes
233         // Check if we have enough buffer space already in fBuffer. If we do then
234         // just continue reading otherwise we need to resize the buffer.
235         if (fBufferSize < dataSize)
236         {
237                 if (fBuffer != NULL)
238                 {
239                         delete [] fBuffer;
240                         fBuffer = NULL;
241                         fBufferSize = 0;
242                 }
243                 try
244                 {
245                         fBuffer = new UChar_t[dataSize];
246                         fBufferSize = dataSize;
247                 }
248                 catch (const std::bad_alloc&)
249                 {
250                         AliError("Could not allocate more buffer space. Cannot decode DDL.");
251                         return kFALSE;
252                 }
253         }
254         
255         if (not GetReader()->ReadNext(fBuffer, dataSize))
256         {
257                 return kFALSE;
258         }
259         
260 #ifndef R__BYTESWAP
261         Swap(reinterpret_cast<UInt_t*>(fBuffer), dataSize / sizeof(UInt_t)); // Swap needed for mac power pc.
262 #endif
263         
264         bool result = false;
265         try
266         {
267                 // Since we might allocate memory inside OnNewBuffer in the event
268                 // handler we need to trap any memory allocation exception to be robust.
269                 result = fDecoder.Decode(fBuffer, dataSize);
270                 fHadError = (result == true ? kFALSE : kTRUE);
271                 fTotalNumberOfGlitchErrors += fDecoder.GetHandler().GlitchErrorCount();
272                 fTotalNumberOfParityErrors += fDecoder.GetHandler().ParityErrorCount();
273                 fTotalNumberOfPaddingErrors += fDecoder.GetHandler().PaddingErrorCount();
274                 fTotalNumberOfTokenLostErrors += fDecoder.GetHandler().TokenLostCount();
275         }
276         catch (const std::bad_alloc&)
277         {
278                 AliError("Could not allocate more buffer space. Cannot decode DDL.");
279                 return kFALSE;
280         }
281
282         // Update the current bus patch pointers.
283         fkCurrentBusPatch = fDecoder.GetHandler().FirstBusPatch();
284         if (fkCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch())
285         {
286                 fkCurrentData = fkCurrentBusPatch->GetData();
287                 fkEndOfData = fkCurrentData + fkCurrentBusPatch->GetDataCount();
288         }
289         else
290         {
291                 // If the DDL did not have any bus patches then mark both fCurrentData
292                 // and fEndOfData as NULL so that in Next() we are forced to find the
293                 // first non empty DDL.
294                 fkCurrentData = fkEndOfData = NULL;
295         }
296
297         fDDL++; // Remember to increment index to next DDL.
298         return kTRUE;
299 }
300
301
302 Bool_t AliMUONRawStreamTrackerHP::IsDone() const
303 {
304         /// Indicates whether the iteration is finished or not.
305         /// \return kTRUE if we already read all the digits and kFALSE if not.
306         
307         return fDone;
308 }
309
310
311 Bool_t AliMUONRawStreamTrackerHP::Next(Int_t& busPatchId, 
312                                        UShort_t& manuId, 
313                                        UChar_t& manuChannel,
314                                        UShort_t& adc, 
315                                        Bool_t skipParityErrors)
316 {
317         /// Advance one step in the iteration. Returns false if finished.
318         /// [out] \param busPatchId  This is filled with the bus patch ID of the digit.
319         /// [out] \param manuId      This is filled with the MANU ID of the digit.
320         /// [out] \param manuChannel This is filled with the MANU channel ID of the digit.
321         /// [out] \param adc         This is filled with the ADC signal value of the digit.
322         /// [in] \param skipParityErrors If this is kTRUE, we'll skip the buspatches that
323         ///                              have some parity errors
324         /// \return kTRUE if we read another digit and kFALSE if we have read all the
325         ///    digits already, i.e. at the end of the iteration.
326         
327         if (fkCurrentData == NULL) return kFALSE;
328         
329 retry:
330         // Check if we still have data to be returned for the current bus patch.
331         if (fkCurrentData != fkEndOfData)
332         {
333                 busPatchId = fkCurrentBusPatch->GetBusPatchId();
334                 AliMUONTrackerDDLDecoderEventHandler::UnpackADC(*fkCurrentData, manuId, manuChannel, adc);
335                 fkCurrentData++;
336                 return kTRUE;
337         }
338         else
339         {
340                 // We hit the end of the current bus patch so check if we have any more
341                 // bus patches to process for the current DDL. If we do, then increment
342                 // the current bus patch, make sure it is not the last one and then try
343                 // reading the first element again.
344                 if (fkCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch())
345                 {
346                         fkCurrentBusPatch++;
347                         if (fkCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch())
348                         {
349                                 fkCurrentData = fkCurrentBusPatch->GetData();
350                                 fkEndOfData = fkCurrentData + fkCurrentBusPatch->GetDataCount();
351                                 if ( skipParityErrors )
352                                 {
353                                         Bool_t ok(kTRUE);
354                                         for ( Int_t i = 0; i < fkCurrentBusPatch->GetLength() && ok; ++ i )
355                                         {
356                                                 ok = fkCurrentBusPatch->IsParityOk(i);
357                                         }
358                                         if (!ok) fkCurrentData = fkEndOfData;
359                                 }
360                                 goto retry;
361                         }
362                 }
363
364                 // This was the last bus patch in the DDL so read in the next one and
365                 // try reading the first data element again.
366                 // Note: fCurrentBusPatch is set inside NextDDL().
367                 if (NextDDL()) goto retry;
368         }
369         return kFALSE;
370 }
371
372
373 AliMUONDDLTracker* AliMUONRawStreamTrackerHP::GetDDLTracker() const
374 {
375         /// Construct and return a pointer to the DDL payload object.
376         /// \return Pointer to internally constructed AliMUONDDLTracker object.
377         ///         The object is owned by this class and should not be deleted
378         ///         by the caller.
379         ///
380         /// \note This method should not be used just to gain access to the DDL
381         /// payload, unless there is a good reason to have the AliMUONDDLTracker
382         /// object. For example, if you want to modify the data and then save it
383         /// to another DDL stream. Otherwise it can be an order of magnitude
384         /// faster to access the DDL headers and data with the GetBlockHeader,
385         /// GetDspHeader and GetBusPatch methods for example.
386         /// Refer to the MUONRawStreamTracker.C macro to see how to use the fast
387         /// decoder interface optimally.
388         
389         if (fDDLObject != NULL) return fDDLObject;
390         
391         fDDLObject = new AliMUONDDLTracker;
392         for (Int_t iBlock = 0; iBlock < (Int_t)GetBlockCount(); iBlock++)
393         {
394                 AliMUONBlockHeader blockHeader;
395                 AliMUONDspHeader dspHeader;
396                 AliMUONBusStruct busPatch;
397                 
398                 const AliBlockHeader* bh = GetBlockHeader(iBlock);
399                 // Copy block header and add it to the DDL object.
400                 memcpy(blockHeader.GetHeader(), bh->GetHeader(), sizeof(AliMUONBlockHeaderStruct));
401                 fDDLObject->AddBlkHeader(blockHeader);
402                 
403                 for (Int_t iDsp = 0; iDsp < (Int_t)bh->GetDspCount(); iDsp++)
404                 {
405                         const AliDspHeader* dh = bh->GetDspHeader(iDsp);
406                         // Copy DSP header and add it to the DDL object.
407                         memcpy(dspHeader.GetHeader(), dh->GetHeader(), sizeof(AliMUONDSPHeaderStruct));
408                         fDDLObject->AddDspHeader(dspHeader, iBlock);
409                         
410                         const AliBusPatch* bp = dh->GetFirstBusPatch();
411                         while (bp != NULL)
412                         {
413                                 // Copy bus patch header, data and add everything into DDL object.
414                                 memcpy(busPatch.GetHeader(), bp->GetHeader(), sizeof(AliMUONBusPatchHeaderStruct));
415                                 busPatch.SetAlloc(bp->GetLength());
416                                 memcpy(busPatch.GetData(), bp->GetData(), bp->GetDataCount()*sizeof(UInt_t));
417                                 busPatch.SetBlockId(iBlock);
418                                 busPatch.SetDspId(iDsp);
419                                 fDDLObject->AddBusPatch(busPatch, iBlock, iDsp);
420                                 bp = bp->Next();
421                         }
422                 }
423         }
424         
425         return fDDLObject;
426 }
427
428
429 void AliMUONRawStreamTrackerHP::SetMaxBlock(Int_t blk)
430 {
431         /// Set maximum number of blocks per DDL allowed.
432         fDecoder.MaxBlocks( (UInt_t) blk );
433         
434         fDecoder.GetHandler().SetMaxStructs(
435                         fDecoder.MaxBlocks(),
436                         fDecoder.MaxDSPs(),
437                         fDecoder.MaxBusPatches()
438                 );
439 }
440
441
442 void AliMUONRawStreamTrackerHP::SetMaxDsp(Int_t dsp)
443 {
444         /// Set maximum number of Dsp per block allowed.
445         fDecoder.MaxDSPs( (UInt_t) dsp );
446         
447         fDecoder.GetHandler().SetMaxStructs(
448                         fDecoder.MaxBlocks(),
449                         fDecoder.MaxDSPs(),
450                         fDecoder.MaxBusPatches()
451                 );
452 }
453
454
455 void AliMUONRawStreamTrackerHP::SetMaxBus(Int_t bus)
456 {
457         /// Set maximum number of Buspatch per Dsp allowed.
458         fDecoder.MaxBusPatches( (UInt_t) bus );
459         
460         fDecoder.GetHandler().SetMaxStructs(
461                         fDecoder.MaxBlocks(),
462                         fDecoder.MaxDSPs(),
463                         fDecoder.MaxBusPatches()
464                 );
465 }
466
467 ///////////////////////////////////////////////////////////////////////////////
468
469 void AliMUONRawStreamTrackerHP::AliBlockHeader::Print() const
470 {
471         /// Print header to screen.
472         
473         cout << "CRT info"        << endl;
474         if (fHeader == NULL)
475         {
476                 cout << "Header is NULL" << endl;
477                 return;
478         }
479         cout << "DataKey: 0x"     << hex << fHeader->fDataKey << dec << endl;
480         cout << "TotalLength: "   << fHeader->fTotalLength << endl;
481         cout << "Length: "        << fHeader->fLength << endl;
482         cout << "DspId: "         << fHeader->fDSPId << endl;
483         cout << "L0Trigger: "     << fHeader->fL0Trigger << endl;
484         cout << "MiniEventId: "   << fHeader->fMiniEventId<< endl; 
485         cout << "EventId1: "      << fHeader->fEventId1 << endl;
486         cout << "EventId2: "      << fHeader->fEventId2 << endl;
487 }
488
489
490 void AliMUONRawStreamTrackerHP::AliDspHeader::Print() const
491 {
492         /// Print header to screen.
493         
494         cout << "FRT info"        << endl;
495         if (fHeader == NULL)
496         {
497                 cout << "Header is NULL" << endl;
498                 return;
499         }
500         cout << "DataKey: 0x"     << hex << fHeader->fDataKey << dec << endl;
501         cout << "TotalLength: "   << fHeader->fTotalLength << endl;
502         cout << "Length : "       << fHeader->fLength << endl;
503         cout << "DspId: "         << fHeader->fDSPId << endl;
504         cout << "BlkL1ATrigger: " << fHeader->fBlkL1ATrigger << endl;
505         cout << "MiniEventId: "   << fHeader->fMiniEventId << endl;
506         cout << "L1ATrigger: "    << fHeader->fL1ATrigger << endl;
507         cout << "L1RTrigger: "    << fHeader->fL1RTrigger << endl;
508         cout << "PaddingWord: "   << fHeader->fPaddingWord << endl;
509         cout << "ErrorWord: "     << fHeader->fErrorWord << endl;
510 }
511
512
513 void AliMUONRawStreamTrackerHP::AliBusPatch::Print(const Option_t* opt) const
514 {
515         /// Print header to screen.
516         cout << "Bus patch info" << endl;
517         if (fHeader == NULL)
518         {
519                 cout << "Header is NULL" << endl;
520                 return;
521         }
522         cout << "DataKey: 0x"    << hex << fHeader->fDataKey << dec << endl;
523         cout << "fTotalLength: " << fHeader->fTotalLength << endl;
524         cout << "fLength: "      << fHeader->fLength << endl;
525         cout << "fBusPatchId: "  << fHeader->fBusPatchId << endl;
526
527         if (TString(opt).Contains("all"))
528         {
529                 for (UInt_t i = 0; i < fHeader->fLength; ++i)
530                         cout << "Data["<< i << "] = " << fData[i] << endl;
531         }
532 }
533
534 ///////////////////////////////////////////////////////////////////////////////
535
536 AliMUONRawStreamTrackerHP::AliDecoderEventHandler::AliDecoderEventHandler() :
537         fRawStream(NULL),
538         fBufferStart(NULL),
539         fBlockCount(0),
540         fBlocks(NULL),
541         fDSPs(NULL),
542         fBusPatches(NULL),
543         fEndOfBusPatches(NULL),
544         fMaxChannels(8192),
545         fParityOk(new Bool_t[8192]),
546         fCurrentBlock(NULL),
547         fCurrentDSP(NULL),
548         fCurrentBusPatch(NULL),
549         fCurrentParityOkFlag(NULL),
550         fParityErrors(0),
551         fGlitchErrors(0),
552         fPaddingErrors(0),
553         fTokenLostErrors(0),
554         fMaxBlocks(),
555         fMaxDsps(),
556         fMaxBusPatches()
557 {
558         /// Default constructor initialises the internal parity flags buffer to
559         /// store 8192 elements. This array will grow dynamically if needed.
560 }
561
562
563 AliMUONRawStreamTrackerHP::AliDecoderEventHandler::~AliDecoderEventHandler()
564 {
565         /// Default destructor cleans up the allocated memory.
566         
567         if (fParityOk != NULL) delete [] fParityOk;
568         if (fBlocks != NULL) delete [] fBlocks;
569         if (fDSPs != NULL) delete [] fDSPs;
570         if (fBusPatches != NULL) delete [] fBusPatches;
571 }
572
573
574 void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::SetMaxStructs(
575                 UInt_t maxBlocks, UInt_t maxDsps, UInt_t maxBusPatches
576         )
577 {
578         /// Sets the maximum number of structures allowed.
579         
580         // Start by clearing the current arrays.
581         if (fBlocks != NULL)
582         {
583                 delete [] fBlocks;
584                 fBlocks = NULL;
585         }
586         if (fDSPs != NULL)
587         {
588                 delete [] fDSPs;
589                 fDSPs = NULL;
590         }
591         if (fBusPatches != NULL)
592         {
593                 delete [] fBusPatches;
594                 fBusPatches = NULL;
595         }
596         fCurrentBlock = NULL;
597         fCurrentDSP = NULL;
598         fCurrentBusPatch = NULL;
599         
600         // Allocate new memory.
601         fBlocks = new AliBlockHeader[maxBlocks];
602         fDSPs = new AliDspHeader[maxBlocks*maxDsps];
603         fBusPatches = new AliBusPatch[maxBlocks*maxDsps*maxBusPatches];
604         fEndOfBusPatches = fBusPatches;
605
606         fMaxBlocks = maxBlocks;
607         fMaxDsps = maxDsps;
608         fMaxBusPatches = maxBusPatches;
609 }
610
611
612 void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::OnNewBuffer(
613                 const void* buffer, UInt_t bufferSize
614         )
615 {
616         /// This is called by the high performance decoder when a new DDL payload
617         /// is about to be decoded.
618         /// \param buffer  The pointer to the buffer storing the DDL payload.
619         /// \param bufferSize  The size of the buffer in bytes.
620
621         // remember the start of the buffer to be used in OnError.
622         fBufferStart = buffer;
623
624         // Reset error counters.
625         fParityErrors = 0;
626         fGlitchErrors = 0;
627         fPaddingErrors = 0;
628         fTokenLostErrors = 0;
629
630         // Check if we will have enough space in the fParityOk array.
631         // If we do not then we need to resize the array.
632         // bufferSize / sizeof(UInt_t) will be a safe over estimate of the
633         // number of channels that we will find.
634         UInt_t maxChannelsPossible = bufferSize / sizeof(UInt_t);
635         if (maxChannelsPossible > fMaxChannels)
636         {
637                 if (fParityOk != NULL)
638                 {
639                         delete [] fParityOk;
640                         fParityOk = NULL;
641                         fMaxChannels = 0;
642                 }
643                 fParityOk = new Bool_t[maxChannelsPossible];
644                 fMaxChannels = maxChannelsPossible;
645         }
646         
647         // Reset the current pointers which will be used to track where we need to
648         // fill fBlocks, fDSPs, fBusPatches and the parity flag. We have to subtract
649         // one space because we will increment the pointer the first time in the
650         // OnNewXZY methods.
651         fCurrentBlock = fBlocks-1;
652         fCurrentDSP = fDSPs-1;
653         fCurrentBusPatch = fBusPatches-1;
654         fCurrentParityOkFlag = fParityOk-1;
655         fBlockCount = 0;
656 }
657
658
659 void AliMUONRawStreamTrackerHP::Swap(UInt_t* buffer, Int_t size) const
660 {
661         // swap from little to big endian
662         
663         typedef struct {
664                 UInt_t b1:8; ///< first byte word
665                 UInt_t b2:8; ///< second byte word
666                 UInt_t b3:8; ///< third byte word
667                 UInt_t b4:8; ///< fourth byte word
668         } RawWord;
669         
670         RawWord* word, temp;
671         word = (RawWord*) buffer;
672         
673         for (Int_t i = 0; i < size; i++)
674         {
675                 temp = *(((RawWord*)buffer)+i);
676                 word->b1 = temp.b4;
677                 word->b2 = temp.b3;
678                 word->b3 = temp.b2;
679                 word->b4 = temp.b1;
680                 word++;
681         }
682 }
683
684
685 void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::OnError(
686                 ErrorCode error, const void* location
687         )
688 {
689         /// This is called by the high performance decoder when a error occurs
690         /// when trying to decode the DDL payload. This indicates corruption in
691         /// the data. This method converts the error code to a descriptive message
692         /// and logs this with the logger object.
693         /// \param error  The error code indicating the problem.
694         /// \param location  A pointer to the location within the DDL payload buffer
695         ///              being decoded where the problem with the data was found.
696         
697         assert(fRawStream != NULL);
698         
699         const char* message = NULL;
700         UInt_t word = 0;
701         bool logAsMajorError = true;
702         
703         // Build the detailed part of the error message if high detail selected.
704         const char* detail = "";
705         if (fRawStream->GetLoggingDetailLevel() == kHighErrorDetail)
706         {
707                 bool blockPtrOk = fBlockCount > 0;
708                 bool dspPtrOk = blockPtrOk ? fCurrentBlock->GetDspCount() > 0 : false;
709                 bool buspatchPtrOk = dspPtrOk ? fCurrentDSP->GetBusPatchCount() > 0 : false;
710                 // We subtract 1 from the current numbers of blocks, DSPs
711                 // and bus patches to get the iBlock, iDsp and iBus indices.
712                 detail = Form(
713                         "At byte %d in DDL %d, event %d, iBlock %d, iDsp %d [DSP ID: %d (0x%X)],"
714                         " iBus %d [bus patch ID: %d (0x%X)].",
715                         (unsigned long)location - (unsigned long)fBufferStart + sizeof(AliRawDataHeader),
716                         AliDAQ::DdlID("MUONTRK", fRawStream->GetDDL()),
717                         fRawStream->GetReader()->GetEventIndex(),
718                         int(fBlockCount)-1,
719                         blockPtrOk ? int(fCurrentBlock->GetDspCount())-1 : -1,
720                         blockPtrOk ? fCurrentBlock->GetDspId() : -1,
721                         blockPtrOk ? fCurrentBlock->GetDspId() : -1,
722                         dspPtrOk ? int(fCurrentDSP->GetBusPatchCount())-1 : -1,
723                         buspatchPtrOk ? fCurrentBusPatch->GetBusPatchId() : -1,
724                         buspatchPtrOk ? fCurrentBusPatch->GetBusPatchId() : -1
725                 );
726         }
727         
728         // Build the log message.
729         switch (error)
730         {
731         case kGlitchFound:
732                 fGlitchErrors++;
733                 switch (fRawStream->GetLoggingDetailLevel())
734                 {
735                 case kLowErrorDetail:
736                         message = "Glitch error detected.";
737                         break;
738                 case kMediumErrorDetail:
739                         message = Form(
740                                 "Glitch error detected in DSP %d (0x%X), skipping event.",
741                                 fCurrentBlock->GetDspId(), fCurrentBlock->GetDspId()
742                         );
743                         break;
744                 case kHighErrorDetail:
745                 default:
746                         message = Form("%s %s", ErrorCodeToMessage(error), detail);
747                         break;
748                 }
749                 logAsMajorError = true;
750                 break;
751
752         case kBadPaddingWord:
753                 fPaddingErrors++;
754                 switch (fRawStream->GetLoggingDetailLevel())
755                 {
756                 case kLowErrorDetail:
757                         message = "Padding word error detected.";
758                         break;
759                 case kMediumErrorDetail:
760                         // We subtract 1 from the current numbers of blocks, DSPs
761                         // and bus patches to get the indices.
762                         message = Form(
763                                 "Padding word error for iBlock %d, iDsp %d, iBus %d.",
764                                 fBlockCount-1,
765                                 fCurrentBlock->GetDspCount()-1,
766                                 fCurrentDSP->GetBusPatchCount()-1
767                         );
768                         break;
769                 case kHighErrorDetail:
770                 default:
771                         message = Form("%s %s", ErrorCodeToMessage(error), detail);
772                         break;
773                 }
774                 logAsMajorError = false;
775                 break;
776
777         case kParityError:
778                 fParityErrors++;
779                 switch (fRawStream->GetLoggingDetailLevel())
780                 {
781                 case kLowErrorDetail:
782                         message = "Parity error detected.";
783                         break;
784                 case kMediumErrorDetail:
785                         message = Form(
786                                 "Parity error in buspatch %d (0x%X).",
787                                 fCurrentBusPatch->GetBusPatchId(),
788                                 fCurrentBusPatch->GetBusPatchId()
789                         );
790                         break;
791                 case kHighErrorDetail:
792                 default:
793                         // location points to the incorrect data word and
794                         // fCurrentBusPatch->GetData() returns a pointer to the start of
795                         // bus patches data, so the difference divided by 4 gives the 32
796                         // bit word number.
797                         word = ((unsigned long)location - (unsigned long)fCurrentBusPatch->GetData())
798                                 / sizeof(UInt_t);
799                         message = Form(
800                                 "Parity error in word %d for manuId %d and channel %d in buspatch %d. %s",
801                                 word,
802                                 fCurrentBusPatch->GetManuId(word),
803                                 fCurrentBusPatch->GetChannelId(word),
804                                 fCurrentBusPatch->GetBusPatchId(),
805                                 detail
806                         );
807                         break;
808                 }
809                 logAsMajorError = false;
810                 break;
811                 
812         case kTokenLost:
813                 fTokenLostErrors++;
814                 switch (fRawStream->GetLoggingDetailLevel())
815                 {
816                 case kLowErrorDetail:
817                         message = "Lost token error detected.";
818                         break;
819                 case kMediumErrorDetail:
820                         word = *reinterpret_cast<const UInt_t*>(location);
821                         message = Form(
822                                 "Lost token error detected in DSP 0x%X of DDL %d and code %d.",
823         ((word & 0xFFFF0000) >> 16),
824         fRawStream->GetDDL(),
825                                 (word & 0xF)
826                         );
827                         break;
828                 case kHighErrorDetail:
829                 default:
830                         word = *reinterpret_cast<const UInt_t*>(location);
831                         message = Form(
832                                 "Lost token error detected with address 0x%X and code %d. %s",
833                                 ((word & 0xFFFF0000) >> 16),
834                                 (word & 0xF),
835                                 detail
836                         );
837                         message = Form("Lost token error detected. %s.", detail);
838                         break;
839                 }
840                 logAsMajorError = false;
841                 break;
842
843         default:
844                 switch (fRawStream->GetLoggingDetailLevel())
845                 {
846                 case kLowErrorDetail:
847                         message = ErrorCodeToMessage(error);
848                         break;
849                 case kMediumErrorDetail:
850                         message = Form(
851                                 "%s (At byte %d)",
852                                 ErrorCodeToMessage(error),
853                                 (unsigned long)location - (unsigned long)fBufferStart + sizeof(AliRawDataHeader)
854                         );
855                         break;
856                 case kHighErrorDetail:
857                 default:
858                         message = Form(
859                                 "%s Error code: %d (%s). %s",
860                                 ErrorCodeToMessage(error),
861                                 error, ErrorCodeToString(error),
862                                 detail
863                         );
864                         break;
865                 }
866                 logAsMajorError = true;
867                 break;
868         }
869         
870         // Now log the error message depending on the logging flags set.
871         if (fRawStream->IsRawReaderErrorLoggerEnabled())
872         {
873                 if (logAsMajorError)
874                         fRawStream->GetReader()->AddMajorErrorLog(Int_t(error), message);
875                 else
876                         fRawStream->GetReader()->AddMinorErrorLog(Int_t(error), message);
877         }
878         if (fRawStream->IsMUONErrorLoggerEnabled())
879         {
880                 AliMUONLogger* logger = fRawStream->GetMUONErrorLogger();
881                 if (logger != NULL)
882                 {
883                         logger->Log(message);
884                 }
885                 else
886                 {
887                         AliErrorGeneral(
888                                 "AliMUONRawStreamTrackerHP::AliDecoderEventHandler",
889                                 "Enabled logging to AliMUONLogger, but the logger object"
890                                 " was not set with SetMUONErrorLogger()."
891                         );
892                 }
893         }
894         if (fRawStream->IsWarningsEnabled())
895         {
896                 AliWarningGeneral(
897                                 "AliMUONRawStreamTrackerHP::AliDecoderEventHandler",
898                                 message
899                         );
900         }
901 }
902