]> git.uio.no Git - u/mrichter/AliRoot.git/blob - MUON/AliMUONRawStreamTrackerHP.cxx
aa82a6ee5768d75ed94eb3fae0a5134dba4d1f92
[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 "AliRawReader.h"
53 #include "AliLog.h"
54 #include <cassert>
55 #include <iostream>
56 using std::cout;
57 using std::endl;
58 using std::hex;
59 using std::dec;
60
61 /// \cond CLASSIMP
62 ClassImp(AliMUONRawStreamTrackerHP)
63 /// \endcond
64
65 const Int_t AliMUONRawStreamTrackerHP::fgkMaxDDL = 20;
66
67 AliMUONRawStreamTrackerHP::AliMUONRawStreamTrackerHP() :
68         TObject(),
69         fEnableErrorLogger(kFALSE),
70         fDecoder(),
71         fDDL(0),
72         fBufferSize(8192),
73         fBuffer(new UChar_t[8192]),
74         fkCurrentBusPatch(NULL),
75         fkCurrentData(NULL),
76         fkEndOfData(NULL),
77         fHadError(kFALSE),
78         fDone(kFALSE),
79         fDDLObject(NULL),
80         fTotalNumberOfGlitchErrors(0),
81         fTotalNumberOfParityErrors(0),
82         fTotalNumberOfPaddingErrors(0),
83         fTotalNumberOfTokenLostErrors(0)
84 {
85         ///
86         /// Default constructor.
87         ///
88         
89         // Must set this flag to get all information about parity errors though
90         // the OnData method. OnError gets them either way.
91         fDecoder.ExitOnError(false);
92         fDecoder.SendDataOnParityError(true);
93
94         fDecoder.GetHandler().SetMaxStructs(
95                         fDecoder.MaxBlocks(),
96                         fDecoder.MaxDSPs(),
97                         fDecoder.MaxBusPatches()
98                 );
99 }
100
101
102 AliMUONRawStreamTrackerHP::AliMUONRawStreamTrackerHP(AliRawReader* rawReader) :
103         TObject(),
104         fEnableErrorLogger(kFALSE),
105         fDecoder(),
106         fDDL(0),
107         fBufferSize(8192),
108         fBuffer(new UChar_t[8192]),
109         fkCurrentBusPatch(NULL),
110         fkCurrentData(NULL),
111         fkEndOfData(NULL),
112         fHadError(kFALSE),
113         fDone(kFALSE),
114         fDDLObject(NULL),
115         fTotalNumberOfGlitchErrors(0),
116         fTotalNumberOfParityErrors(0),
117         fTotalNumberOfPaddingErrors(0),
118         fTotalNumberOfTokenLostErrors(0)
119 {
120         ///
121         /// Constructor with AliRawReader as argument.
122         ///
123         
124         // Must set this flag to get all information about parity errors though
125         // the OnData method. OnError gets them either way.
126         fDecoder.ExitOnError(false);
127         fDecoder.SendDataOnParityError(true);
128
129         fDecoder.GetHandler().SetMaxStructs(
130                         fDecoder.MaxBlocks(),
131                         fDecoder.MaxDSPs(),
132                         fDecoder.MaxBusPatches()
133                 );
134         
135         fDecoder.GetHandler().SetReader(rawReader);
136 }
137
138
139 AliMUONRawStreamTrackerHP::~AliMUONRawStreamTrackerHP()
140 {
141         ///
142         /// Default destructor.
143         ///
144         
145         if (fBuffer != NULL)
146         {
147                 delete [] fBuffer;
148         }
149         if (fDDLObject != NULL)
150         {
151                 delete fDDLObject;
152         }
153 }
154
155
156 void AliMUONRawStreamTrackerHP::First()
157 {
158         /// Initialise or reset the iterator.
159         /// The first DDL will be found and decoded.
160         
161         assert( GetReader() != NULL );
162         
163         fDDL = 0;
164         fDone = kFALSE;
165         NextDDL();
166         fTotalNumberOfGlitchErrors = 0;
167         fTotalNumberOfPaddingErrors = 0;
168         fTotalNumberOfParityErrors = 0;
169         fTotalNumberOfTokenLostErrors = 0;
170 }
171
172
173 Bool_t AliMUONRawStreamTrackerHP::NextDDL()
174 {
175         /// Reading the next tracker DDL and decode the payload with the 
176         /// high performance decoder.
177         /// \return kTRUE if the next DDL was successfully read and kFALSE otherwise.
178
179         assert( GetReader() != NULL );
180         
181         // The temporary object if generated in GetDDLTracker, is now stale,
182         // so delete it.
183         if (fDDLObject != NULL)
184         {
185                 delete fDDLObject;
186                 fDDLObject = NULL;
187         }
188         
189         // Better to reset these pointers.
190         fkCurrentBusPatch = NULL;
191         fkCurrentData = NULL;
192         fkEndOfData = NULL;
193         
194         while (fDDL < GetMaxDDL())
195         {
196                 GetReader()->Reset();
197                 GetReader()->Select("MUONTRK", fDDL, fDDL);  // Select the DDL file to be read.
198                 if (GetReader()->ReadHeader()) break;
199                 AliDebug(3, Form("Skipping DDL %d which does not seem to be there", fDDL+1));
200                 fDDL++;
201         }
202
203         // If we reach the end of the DDL list for this event then reset the
204         // DDL counter, mark the iteration as done and exit.
205         if (fDDL >= GetMaxDDL())
206         {
207                 fDDL = 0;
208                 fDone = kTRUE;
209                 return kFALSE;
210         }
211         else
212         {
213                 fDone = kFALSE;
214         }
215
216         AliDebug(3, Form("DDL Number %d\n", fDDL));
217         
218         Int_t dataSize = GetReader()->GetDataSize(); // in bytes
219         // Check if we have enough buffer space already in fBuffer. If we do then
220         // just continue reading otherwise we need to resize the buffer.
221         if (fBufferSize < dataSize)
222         {
223                 if (fBuffer != NULL)
224                 {
225                         delete [] fBuffer;
226                         fBuffer = NULL;
227                         fBufferSize = 0;
228                 }
229                 try
230                 {
231                         fBuffer = new UChar_t[dataSize];
232                         fBufferSize = dataSize;
233                 }
234                 catch (const std::bad_alloc&)
235                 {
236                         AliError("Could not allocate more buffer space. Cannot decode DDL.");
237                         return kFALSE;
238                 }
239         }
240         
241         if (not GetReader()->ReadNext(fBuffer, dataSize))
242         {
243                 return kFALSE;
244         }
245         
246 #ifndef R__BYTESWAP
247         Swap(reinterpret_cast<UInt_t*>(fBuffer), dataSize / sizeof(UInt_t)); // Swap needed for mac power pc.
248 #endif
249         
250         bool result = false;
251         try
252         {
253                 // Since we might allocate memory inside OnNewBuffer in the event
254                 // handler we need to trap any memory allocation exception to be robust.
255                 result = fDecoder.Decode(fBuffer, dataSize);
256                 fHadError = (result == true ? kFALSE : kTRUE);
257                 fTotalNumberOfGlitchErrors += fDecoder.GetHandler().GlitchErrorCount();
258                 fTotalNumberOfParityErrors += fDecoder.GetHandler().ParityErrorCount();
259                 fTotalNumberOfPaddingErrors += fDecoder.GetHandler().PaddingErrorCount();
260                 fTotalNumberOfTokenLostErrors += fDecoder.GetHandler().TokenLostCount();
261         }
262         catch (const std::bad_alloc&)
263         {
264                 AliError("Could not allocate more buffer space. Cannot decode DDL.");
265                 return kFALSE;
266         }
267
268         // Update the current bus patch pointers.
269         fkCurrentBusPatch = fDecoder.GetHandler().FirstBusPatch();
270         if (fkCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch())
271         {
272                 fkCurrentData = fkCurrentBusPatch->GetData();
273                 fkEndOfData = fkCurrentData + fkCurrentBusPatch->GetDataCount();
274         }
275         else
276         {
277                 // If the DDL did not have any bus patches then mark both fCurrentData
278                 // and fEndOfData as NULL so that in Next() we are forced to find the
279                 // first non empty DDL.
280                 fkCurrentData = fkEndOfData = NULL;
281         }
282
283         fDDL++; // Remember to increment index to next DDL.
284         return kTRUE;
285 }
286
287
288 Bool_t AliMUONRawStreamTrackerHP::IsDone() const
289 {
290         /// Indicates whether the iteration is finished or not.
291         /// \return kTRUE if we already read all the digits and kFALSE if not.
292         
293         return fDone;
294 }
295
296
297 Bool_t AliMUONRawStreamTrackerHP::Next(Int_t& busPatchId, 
298                                        UShort_t& manuId, 
299                                        UChar_t& manuChannel,
300                                        UShort_t& adc, 
301                                        Bool_t skipParityErrors)
302 {
303         /// Advance one step in the iteration. Returns false if finished.
304         /// [out] \param busPatchId  This is filled with the bus patch ID of the digit.
305         /// [out] \param manuId      This is filled with the MANU ID of the digit.
306         /// [out] \param manuChannel This is filled with the MANU channel ID of the digit.
307         /// [out] \param adc         This is filled with the ADC signal value of the digit.
308         /// [in] \param skipParityErrors If this is kTRUE, we'll skip the buspatches that
309         ///                              have some parity errors
310         /// \return kTRUE if we read another digit and kFALSE if we have read all the
311         ///    digits already, i.e. at the end of the iteration.
312         
313         if (fkCurrentData == NULL) return kFALSE;
314         
315 retry:
316         // Check if we still have data to be returned for the current bus patch.
317         if (fkCurrentData != fkEndOfData)
318         {
319                 busPatchId = fkCurrentBusPatch->GetBusPatchId();
320                 AliMUONTrackerDDLDecoderEventHandler::UnpackADC(*fkCurrentData, manuId, manuChannel, adc);
321                 fkCurrentData++;
322                 return kTRUE;
323         }
324         else
325         {
326                 // We hit the end of the current bus patch so check if we have any more
327                 // bus patches to process for the current DDL. If we do, then increment
328                 // the current bus patch, make sure it is not the last one and then try
329                 // reading the first element again.
330                 if (fkCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch())
331                 {
332                         fkCurrentBusPatch++;
333                         if (fkCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch())
334                         {
335                                 fkCurrentData = fkCurrentBusPatch->GetData();
336                                 fkEndOfData = fkCurrentData + fkCurrentBusPatch->GetDataCount();
337                                 if ( skipParityErrors )
338                                 {
339                                         Bool_t ok(kTRUE);
340                                         for ( Int_t i = 0; i < fkCurrentBusPatch->GetLength() && ok; ++ i )
341                                         {
342                                                 ok = fkCurrentBusPatch->IsParityOk(i);
343                                         }
344                                         if (!ok) fkCurrentData = fkEndOfData;
345                                 }
346                                 goto retry;
347                         }
348                 }
349
350                 // This was the last bus patch in the DDL so read in the next one and
351                 // try reading the first data element again.
352                 // Note: fCurrentBusPatch is set inside NextDDL().
353                 if (NextDDL()) goto retry;
354         }
355         return kFALSE;
356 }
357
358
359 AliMUONDDLTracker* AliMUONRawStreamTrackerHP::GetDDLTracker() const
360 {
361         /// Construct and return a pointer to the DDL payload object.
362         /// \return Pointer to internally constructed AliMUONDDLTracker object.
363         ///         The object is owned by this class and should not be deleted
364         ///         by the caller.
365         ///
366         /// \note This method should not be used just to gain access to the DDL
367         /// payload, unless there is a good reason to have the AliMUONDDLTracker
368         /// object. For example, if you want to modify the data and then save it
369         /// to another DDL stream. Otherwise it can be an order of magnitude
370         /// faster to access the DDL headers and data with the GetBlockHeader,
371         /// GetDspHeader and GetBusPatch methods for example.
372         /// Refer to the MUONRawStreamTracker.C macro to see how to use the fast
373         /// decoder interface optimally.
374         
375         if (fDDLObject != NULL) return fDDLObject;
376         
377         fDDLObject = new AliMUONDDLTracker;
378         for (Int_t iBlock = 0; iBlock < (Int_t)GetBlockCount(); iBlock++)
379         {
380                 AliMUONBlockHeader blockHeader;
381                 AliMUONDspHeader dspHeader;
382                 AliMUONBusStruct busPatch;
383                 
384                 const AliBlockHeader* bh = GetBlockHeader(iBlock);
385                 // Copy block header and add it to the DDL object.
386                 memcpy(blockHeader.GetHeader(), bh->GetHeader(), sizeof(AliMUONBlockHeaderStruct));
387                 fDDLObject->AddBlkHeader(blockHeader);
388                 
389                 for (Int_t iDsp = 0; iDsp < (Int_t)bh->GetDspCount(); iDsp++)
390                 {
391                         const AliDspHeader* dh = bh->GetDspHeader(iDsp);
392                         // Copy DSP header and add it to the DDL object.
393                         memcpy(dspHeader.GetHeader(), dh->GetHeader(), sizeof(AliMUONDSPHeaderStruct));
394                         fDDLObject->AddDspHeader(dspHeader, iBlock);
395                         
396                         const AliBusPatch* bp = dh->GetFirstBusPatch();
397                         while (bp != NULL)
398                         {
399                                 // Copy bus patch header, data and add everything into DDL object.
400                                 memcpy(busPatch.GetHeader(), bp->GetHeader(), sizeof(AliMUONBusPatchHeaderStruct));
401                                 busPatch.SetAlloc(bp->GetLength());
402                                 memcpy(busPatch.GetData(), bp->GetData(), bp->GetDataCount()*sizeof(UInt_t));
403                                 busPatch.SetBlockId(iBlock);
404                                 busPatch.SetDspId(iDsp);
405                                 fDDLObject->AddBusPatch(busPatch, iBlock, iDsp);
406                                 bp = bp->Next();
407                         }
408                 }
409         }
410         
411         return fDDLObject;
412 }
413
414
415 void AliMUONRawStreamTrackerHP::SetMaxBlock(Int_t blk)
416 {
417         /// Set maximum number of blocks per DDL allowed.
418         fDecoder.MaxBlocks( (UInt_t) blk );
419         
420         fDecoder.GetHandler().SetMaxStructs(
421                         fDecoder.MaxBlocks(),
422                         fDecoder.MaxDSPs(),
423                         fDecoder.MaxBusPatches()
424                 );
425 }
426
427
428 void AliMUONRawStreamTrackerHP::SetMaxDsp(Int_t dsp)
429 {
430         /// Set maximum number of Dsp per block allowed.
431         fDecoder.MaxDSPs( (UInt_t) dsp );
432         
433         fDecoder.GetHandler().SetMaxStructs(
434                         fDecoder.MaxBlocks(),
435                         fDecoder.MaxDSPs(),
436                         fDecoder.MaxBusPatches()
437                 );
438 }
439
440
441 void AliMUONRawStreamTrackerHP::SetMaxBus(Int_t bus)
442 {
443         /// Set maximum number of Buspatch per Dsp allowed.
444         fDecoder.MaxBusPatches( (UInt_t) bus );
445         
446         fDecoder.GetHandler().SetMaxStructs(
447                         fDecoder.MaxBlocks(),
448                         fDecoder.MaxDSPs(),
449                         fDecoder.MaxBusPatches()
450                 );
451 }
452
453 AliRawReader* AliMUONRawStreamTrackerHP::GetReader()
454 {
455   return fDecoder.GetHandler().GetReader();
456 }
457
458 void AliMUONRawStreamTrackerHP::SetReader(AliRawReader* reader)
459 {
460   fDecoder.GetHandler().SetReader(reader);
461 }
462
463 ///////////////////////////////////////////////////////////////////////////////
464
465 void AliMUONRawStreamTrackerHP::AliBlockHeader::Print() const
466 {
467         /// Print header to screen.
468         
469         cout << "CRT info"        << endl;
470         if (fHeader == NULL)
471         {
472                 cout << "Header is NULL" << endl;
473                 return;
474         }
475         cout << "DataKey: 0x"     << hex << fHeader->fDataKey << dec << endl;
476         cout << "TotalLength: "   << fHeader->fTotalLength << endl;
477         cout << "Length: "        << fHeader->fLength << endl;
478         cout << "DspId: "         << fHeader->fDSPId << endl;
479         cout << "L0Trigger: "     << fHeader->fL0Trigger << endl;
480         cout << "MiniEventId: "   << fHeader->fMiniEventId<< endl; 
481         cout << "EventId1: "      << fHeader->fEventId1 << endl;
482         cout << "EventId2: "      << fHeader->fEventId2 << endl;
483 }
484
485
486 void AliMUONRawStreamTrackerHP::AliDspHeader::Print() const
487 {
488         /// Print header to screen.
489         
490         cout << "FRT info"        << endl;
491         if (fHeader == NULL)
492         {
493                 cout << "Header is NULL" << endl;
494                 return;
495         }
496         cout << "DataKey: 0x"     << hex << fHeader->fDataKey << dec << endl;
497         cout << "TotalLength: "   << fHeader->fTotalLength << endl;
498         cout << "Length : "       << fHeader->fLength << endl;
499         cout << "DspId: "         << fHeader->fDSPId << endl;
500         cout << "BlkL1ATrigger: " << fHeader->fBlkL1ATrigger << endl;
501         cout << "MiniEventId: "   << fHeader->fMiniEventId << endl;
502         cout << "L1ATrigger: "    << fHeader->fL1ATrigger << endl;
503         cout << "L1RTrigger: "    << fHeader->fL1RTrigger << endl;
504         cout << "PaddingWord: "   << fHeader->fPaddingWord << endl;
505         cout << "ErrorWord: "     << fHeader->fErrorWord << endl;
506 }
507
508
509 void AliMUONRawStreamTrackerHP::AliBusPatch::Print(const Option_t* opt) const
510 {
511         /// Print header to screen.
512         cout << "Bus patch info" << endl;
513         if (fHeader == NULL)
514         {
515                 cout << "Header is NULL" << endl;
516                 return;
517         }
518         cout << "DataKey: 0x"    << hex << fHeader->fDataKey << dec << endl;
519         cout << "fTotalLength: " << fHeader->fTotalLength << endl;
520         cout << "fLength: "      << fHeader->fLength << endl;
521         cout << "fBusPatchId: "  << fHeader->fBusPatchId << endl;
522
523         if (TString(opt).Contains("all"))
524         {
525                 for (UInt_t i = 0; i < fHeader->fLength; ++i)
526                         cout << "Data["<< i << "] = " << fData[i] << endl;
527         }
528 }
529
530 ///////////////////////////////////////////////////////////////////////////////
531
532 AliMUONRawStreamTrackerHP::AliDecoderEventHandler::AliDecoderEventHandler() :
533         fRawReader(0x0),
534         fBufferStart(NULL),
535         fBlockCount(0),
536         fBlocks(NULL),
537         fDSPs(NULL),
538         fBusPatches(NULL),
539         fEndOfBusPatches(NULL),
540         fMaxChannels(8192),
541         fParityOk(new Bool_t[8192]),
542         fCurrentBlock(NULL),
543         fCurrentDSP(NULL),
544         fCurrentBusPatch(NULL),
545         fCurrentParityOkFlag(NULL),
546         fParityErrors(0),
547         fGlitchErrors(0),
548         fPaddingErrors(0),
549         fTokenLostErrors(0),
550         fWarnings(kTRUE),
551         fMaxBlocks(),
552         fMaxDsps(),
553         fMaxBusPatches()
554 {
555         /// Default constructor initialises the internal parity flags buffer to
556         /// store 8192 elements. This array will grow dynamically if needed.
557 }
558
559
560 AliMUONRawStreamTrackerHP::AliDecoderEventHandler::~AliDecoderEventHandler()
561 {
562         /// Default destructor cleans up the allocated memory.
563         
564         if (fParityOk != NULL) delete [] fParityOk;
565         if (fBlocks != NULL) delete [] fBlocks;
566         if (fDSPs != NULL) delete [] fDSPs;
567         if (fBusPatches != NULL) delete [] fBusPatches;
568 }
569
570
571 void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::SetMaxStructs(
572                 UInt_t maxBlocks, UInt_t maxDsps, UInt_t maxBusPatches
573         )
574 {
575         /// Sets the maximum number of structures allowed.
576         
577         // Start by clearing the current arrays.
578         if (fBlocks != NULL)
579         {
580                 delete [] fBlocks;
581                 fBlocks = NULL;
582         }
583         if (fDSPs != NULL)
584         {
585                 delete [] fDSPs;
586                 fDSPs = NULL;
587         }
588         if (fBusPatches != NULL)
589         {
590                 delete [] fBusPatches;
591                 fBusPatches = NULL;
592         }
593         fCurrentBlock = NULL;
594         fCurrentDSP = NULL;
595         fCurrentBusPatch = NULL;
596         
597         // Allocate new memory.
598         fBlocks = new AliBlockHeader[maxBlocks];
599         fDSPs = new AliDspHeader[maxBlocks*maxDsps];
600         fBusPatches = new AliBusPatch[maxBlocks*maxDsps*maxBusPatches];
601         fEndOfBusPatches = fBusPatches;
602
603         fMaxBlocks = maxBlocks;
604         fMaxDsps = maxDsps;
605         fMaxBusPatches = maxBusPatches;
606 }
607
608
609 void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::OnNewBuffer(
610                 const void* buffer, UInt_t bufferSize
611         )
612 {
613         /// This is called by the high performance decoder when a new DDL payload
614         /// is about to be decoded.
615         /// \param buffer  The pointer to the buffer storing the DDL payload.
616         /// \param bufferSize  The size of the buffer in bytes.
617
618         // remember the start of the buffer to be used in OnError.
619         fBufferStart = buffer;
620
621         // Reset error counters.
622         fParityErrors = 0;
623         fGlitchErrors = 0;
624         fPaddingErrors = 0;
625         fTokenLostErrors = 0;
626
627         // Check if we will have enough space in the fParityOk array.
628         // If we do not then we need to resize the array.
629         // bufferSize / sizeof(UInt_t) will be a safe over estimate of the
630         // number of channels that we will find.
631         UInt_t maxChannelsPossible = bufferSize / sizeof(UInt_t);
632         if (maxChannelsPossible > fMaxChannels)
633         {
634                 if (fParityOk != NULL)
635                 {
636                         delete [] fParityOk;
637                         fParityOk = NULL;
638                         fMaxChannels = 0;
639                 }
640                 fParityOk = new Bool_t[maxChannelsPossible];
641                 fMaxChannels = maxChannelsPossible;
642         }
643         
644         // Reset the current pointers which will be used to track where we need to
645         // fill fBlocks, fDSPs, fBusPatches and the parity flag. We have to subtract
646         // one space because we will increment the pointer the first time in the
647         // OnNewXZY methods.
648         fCurrentBlock = fBlocks-1;
649         fCurrentDSP = fDSPs-1;
650         fCurrentBusPatch = fBusPatches-1;
651         fCurrentParityOkFlag = fParityOk-1;
652         fBlockCount = 0;
653 }
654
655
656 void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::OnError(
657                 ErrorCode error, const void* location
658         )
659 {
660         /// This is called by the high performance decoder when a error occurs
661         /// when trying to decode the DDL payload. This indicates corruption in
662         /// the data. This method converts the error code to a descriptive message
663         /// and logs this with the raw reader.
664         /// \param error  The error code indicating the problem.
665         /// \param location  A pointer to the location within the DDL payload buffer
666         ///              being decoded where the problem with the data was found.
667
668         assert( fRawReader != NULL );
669         
670         Char_t* message = NULL;
671         UInt_t word = 0;
672
673         switch (error)
674         {
675         case kGlitchFound:
676                 fGlitchErrors++;
677                 message = Form(
678                         "Glitch error detected in DSP %d (0x%X), skipping event ",
679                         fCurrentBlock->GetDspId(), fCurrentBlock->GetDspId()
680                 );
681                 fRawReader->AddMajorErrorLog(error, message);
682                 break;
683
684         case kBadPaddingWord:
685                 fPaddingErrors++;
686                 // We subtract 1 from the current numbers of blocks, DSPs
687                 // and bus patches to get the indices.
688                 message = Form(
689                         "Padding word error for iBlock %d, iDsp %d, iBus %d\n", 
690                         fBlockCount-1,
691                         fCurrentBlock->GetDspCount()-1,
692                         fCurrentDSP->GetBusPatchCount()-1
693                 );
694                 fRawReader->AddMinorErrorLog(error, message);
695                 break;
696
697         case kParityError:
698                 fParityErrors++;
699                 // location points to the incorrect data word and
700                 // fCurrentBusPatch->GetData() returns a pointer to the start of
701                 // bus patches data, so the difference divided by 4 gives the 32
702                 // bit word number.
703                 word = ((unsigned long)location - (unsigned long)fCurrentBusPatch->GetData())
704                                 / sizeof(UInt_t);
705                 message = Form(
706                         "Parity error in word %d for manuId %d and channel %d in buspatch %d\n", 
707                         word,
708                         fCurrentBusPatch->GetManuId(word),
709                         fCurrentBusPatch->GetChannelId(word),
710                         fCurrentBusPatch->GetBusPatchId()
711                 );
712                 fRawReader->AddMinorErrorLog(error, message);
713                 break;
714                 
715         case kTokenLost:
716                 fTokenLostErrors++;
717                 word = *reinterpret_cast<const UInt_t*>(location);
718                 message = Form(
719                         "Lost token error detected in DSP %d (0x%X) with address 0x%X and code %d.",
720                         fCurrentBlock->GetDspId(), fCurrentBlock->GetDspId(),
721                         ((word & 0xFFFF0000) >> 16),
722                         (word & 0xF)
723                 );
724                 fRawReader->AddMinorErrorLog(error, message);
725                 break;
726
727         default:
728                 message = Form(
729                         "%s (At byte %d in DDL.)",
730                         ErrorCodeToMessage(error),
731                         (unsigned long)location - (unsigned long)fBufferStart + sizeof(AliRawDataHeader)
732                 );
733                 fRawReader->AddMajorErrorLog(error, message);
734                 break;
735         }
736
737         if (fWarnings)
738         {
739                 AliWarningGeneral(
740                                 "AliMUONRawStreamTrackerHP::AliDecoderEventHandler",
741                                 message
742                         );
743         }
744 }
745