Make the Scan method public
[u/mrichter/AliRoot.git] / MUON / AliMUONRawStreamTriggerHP.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 /// \class AliMUONRawStreamTriggerHP
20 ///
21 /// Implementation of a streamer interface to the high performance trigger decoder.
22 /// This is the raw stream class which interfaces between the high performance
23 /// core decoder for MUON trigger chambers and the AliRawReader class.
24 /// To gain the most out of the decoder, the Next() method should be used,
25 /// for example:
26 /// \code
27 ///   AliMUONRawStreamTriggerHP* rawStream;  // assume initialised
28 ///   const AliMUONRawStreamTriggerHP::AliLocalStruct* localStruct;
29 ///   while ((localStruct = rawStream->Next()) != NULL)
30 ///   {
31 ///      // Do something with localStruct here.
32 ///   }
33 /// \endcode
34 ///
35 /// This decoder tries to implement as similar an interface as possible to
36 /// AliMUONRawStreamTrigger where possible. However certain constructs which
37 /// would slow us down too much are avoided.
38 ///
39 /// \author Artur Szostak <artursz@iafrica.com>
40
41 #include "AliMUONRawStreamTriggerHP.h"
42 #include "AliMUONDarcHeader.h"
43 #include "AliMUONRegHeader.h"
44 #include "AliMUONLocalStruct.h"
45 #include "AliMUONDDLTrigger.h"
46 #include "AliRawReader.h"
47 #include "AliLog.h"
48 #include <cassert>
49 #include <iostream>
50 using std::cout;
51 using std::endl;
52 using std::hex;
53 using std::dec;
54
55 /// \cond CLASSIMP
56 ClassImp(AliMUONRawStreamTriggerHP)
57 /// \endcond
58
59 const Int_t AliMUONRawStreamTriggerHP::fgkMaxDDL = 2;
60 bool AliMUONRawStreamTriggerHP::AliLocalStruct::fgOverrideId = true;
61
62 const AliMUONRegionalHeaderStruct
63 AliMUONRawStreamTriggerHP::AliDecoderEventHandler::fgkEmptyHeader = {
64         AliMUONTriggerDDLDecoder<AliDecoderEventHandler>::RegionalErrorWord(),
65         0,
66         {0, 0},
67         0
68 };
69
70
71 AliMUONRawStreamTriggerHP::AliMUONRawStreamTriggerHP() :
72         AliMUONVRawStreamTrigger(),
73         fDecoder(),
74         fDDL(0),
75         fBufferSize(8192),
76         fBuffer(new UChar_t[8192]),
77         fkCurrentLocalStruct(NULL),
78         fHadError(kFALSE),
79         fDone(kFALSE),
80         fDDLObject(NULL),
81         fTotalNumberOfDarcEoWErrors(0),
82         fTotalNumberOfGlobalEoWErrors(0),
83         fTotalNumberOfRegEoWErrors(0),
84         fTotalNumberOfLocalEoWErrors(0)
85 {
86         ///
87         /// Default constructor.
88         ///
89         
90         fDecoder.ExitOnError(false);
91
92         fDecoder.GetHandler().SetMaxStructs(
93                         fDecoder.MaxRegionals(),
94                         fDecoder.MaxLocals()
95                 );
96
97         fDecoder.GetHandler().SetRawStream(this);
98 }
99
100
101 AliMUONRawStreamTriggerHP::AliMUONRawStreamTriggerHP(AliRawReader* rawReader) :
102         AliMUONVRawStreamTrigger(rawReader),
103         fDecoder(),
104         fDDL(0),
105         fBufferSize(8192),
106         fBuffer(new UChar_t[8192]),
107         fkCurrentLocalStruct(NULL),
108         fHadError(kFALSE),
109         fDone(kFALSE),
110         fDDLObject(NULL),
111         fTotalNumberOfDarcEoWErrors(0),
112         fTotalNumberOfGlobalEoWErrors(0),
113         fTotalNumberOfRegEoWErrors(0),
114         fTotalNumberOfLocalEoWErrors(0)
115 {
116         ///
117         /// Constructor with AliRawReader as argument.
118         ///
119         
120         fDecoder.ExitOnError(false);
121
122         fDecoder.GetHandler().SetMaxStructs(
123                         fDecoder.MaxRegionals(),
124                         fDecoder.MaxLocals()
125                 );
126         
127         fDecoder.GetHandler().SetRawStream(this);
128 }
129
130
131 AliMUONRawStreamTriggerHP::~AliMUONRawStreamTriggerHP()
132 {
133         ///
134         /// Default destructor which cleans up the memory allocated.
135         ///
136         
137         if (fBuffer != NULL)
138         {
139                 delete [] fBuffer;
140         }
141         if (fDDLObject != NULL)
142         {
143                 delete fDDLObject;
144         }
145 }
146
147
148 void AliMUONRawStreamTriggerHP::First()
149 {
150         /// Initialise or reset the iterator.
151         /// The first DDL will be found and decoded.
152         
153         assert( GetReader() != NULL );
154         
155         fDDL = 0;
156         fDone = kFALSE;
157         NextDDL();
158         fTotalNumberOfDarcEoWErrors = 0;
159         fTotalNumberOfGlobalEoWErrors = 0;
160         fTotalNumberOfRegEoWErrors = 0;
161         fTotalNumberOfLocalEoWErrors = 0;
162 }
163
164
165 Bool_t AliMUONRawStreamTriggerHP::NextDDL()
166 {
167         /// Read in the next trigger DDL and decode the payload with the
168         /// high performance decoder.
169         /// \return kTRUE if the next DDL was successfully read and kFALSE
170         ///    otherwise.
171
172         assert( GetReader() != NULL );
173         
174         // The temporary object if generated in GetDDLTracker, is now stale,
175         // so delete it.
176         if (fDDLObject != NULL)
177         {
178                 delete fDDLObject;
179                 fDDLObject = NULL;
180         }
181         
182         fkCurrentLocalStruct = NULL;
183         
184         while (fDDL < GetMaxDDL())
185         {
186                 GetReader()->Reset();
187                 GetReader()->Select("MUONTRG", fDDL, fDDL);  // Select the DDL file to be read.
188                 if (GetReader()->ReadHeader()) break;
189                 AliDebug(3, Form("Skipping DDL %d which does not seem to be there", fDDL+1));
190                 fDDL++;
191         }
192
193         // If we reach the end of the DDL list for this event then reset the
194         // DDL counter, mark the iteration as done and exit.
195         if (fDDL >= GetMaxDDL())
196         {
197                 fDDL = 0;
198                 fDone = kTRUE;
199                 return kFALSE;
200         }
201         else
202         {
203                 fDone = kFALSE;
204         }
205
206         AliDebug(3, Form("DDL Number %d\n", fDDL));
207         
208         Int_t dataSize = GetReader()->GetDataSize(); // in bytes
209         // Check if we have enough buffer space already in fBuffer. If we do then
210         // just continue reading otherwise we need to resize the buffer.
211         if (fBufferSize < dataSize)
212         {
213                 if (fBuffer != NULL)
214                 {
215                         delete [] fBuffer;
216                         fBuffer = NULL;
217                         fBufferSize = 0;
218                 }
219                 try
220                 {
221                         fBuffer = new UChar_t[dataSize];
222                         fBufferSize = dataSize;
223                 }
224                 catch (const std::bad_alloc&)
225                 {
226                         AliError("Could not allocate more buffer space. Cannot decode DDL.");
227                         return kFALSE;
228                 }
229         }
230         
231         if (not GetReader()->ReadNext(fBuffer, dataSize))
232         {
233                 return kFALSE;
234         }
235         
236 #ifndef R__BYTESWAP
237         Swap(reinterpret_cast<UInt_t*>(fBuffer), dataSize / sizeof(UInt_t)); // Swap needed for mac power pc.
238 #endif
239         
240         fDDL++; // Remember to increment index to next DDL before the calls to
241                 // fDecoder.Decode since the callback methods of the decoder might
242                 // use AliMUONRawStreamTriggerHP::GetDDL()
243         
244         // Check if this is a scalar event.
245         bool scalerEvent = (GetReader()->GetDataHeader()->GetL1TriggerMessage() & 0x1) == 0x1;
246         
247         bool result = false;
248         try
249         {
250                 // Since we might allocate memory inside OnNewBuffer in the event
251                 // handler we need to trap any memory allocation exception to be robust.
252                 result = fDecoder.Decode(fBuffer, dataSize, scalerEvent);
253                 fHadError = (result == true ? kFALSE : kTRUE);
254                 fTotalNumberOfDarcEoWErrors += fDecoder.GetHandler().GetDarcEoWErrors();
255                 fTotalNumberOfGlobalEoWErrors += fDecoder.GetHandler().GetGlobalEoWErrors();
256                 fTotalNumberOfRegEoWErrors += fDecoder.GetHandler().GetRegEoWErrors();
257                 fTotalNumberOfLocalEoWErrors += fDecoder.GetHandler().GetLocalEoWErrors();
258         }
259         catch (const std::bad_alloc&)
260         {
261                 AliError("Could not allocate more buffer space. Cannot decode DDL.");
262                 return kFALSE;
263         }
264
265         // Update the current local structure pointer.
266         fkCurrentLocalStruct = fDecoder.GetHandler().FirstLocalStruct();
267
268         return kTRUE;
269 }
270
271
272 Bool_t AliMUONRawStreamTriggerHP::IsDone() const
273 {
274         /// Indicates whether the iteration is finished or not.
275         /// \return kTRUE if we already read all the digits and kFALSE if not.
276         
277         return fDone;
278 }
279
280
281 Bool_t AliMUONRawStreamTriggerHP::Next(
282                 UChar_t& id,   UChar_t& dec,     Bool_t& trigY,
283                 UChar_t& yPos, UChar_t& sXDev,   UChar_t& xDev,
284                 UChar_t& xPos, Bool_t& triggerY, Bool_t& triggerX,
285                 TArrayS& xPattern, TArrayS& yPattern
286         )
287 {
288         /// Advance one step in the iteration. Returns kFALSE if finished.
289         /// If kTRUE is returned then the output parameters are filled with
290         /// the values found in the next local trigger circuit structure.
291         
292         const AliLocalStruct* localStruct = Next();
293         if (localStruct == NULL) return kFALSE;
294         
295         id    = localStruct->GetId();
296         dec   = localStruct->GetDec();
297         trigY = localStruct->GetTrigY();
298         yPos  = localStruct->GetYPos();
299         sXDev = localStruct->GetSXDev();
300         xDev  = localStruct->GetXDev();
301         xPos  = localStruct->GetXPos();
302         
303         triggerX = localStruct->GetTriggerX();
304         triggerY = localStruct->GetTriggerY();
305         
306         localStruct->GetXPattern(xPattern);
307         localStruct->GetYPattern(yPattern);
308
309         return kTRUE;
310 }
311
312
313 AliMUONDDLTrigger* AliMUONRawStreamTriggerHP::GetDDLTrigger() const
314 {
315         /// Construct and return a pointer to the DDL payload object.
316         /// \return Pointer to internally constructed AliMUONDDLTrigger object.
317         ///         The object is owned by this class and should not be deleted
318         ///         by the caller.
319         ///
320         /// \note This method should not be used just to gain access to the DDL
321         /// payload, unless there is a good reason to have the AliMUONDDLTrigger
322         /// object. For example, if you want to modify the data and then save it
323         /// to another DDL stream. Otherwise it can be an order of magnitude
324         /// faster to access the DDL headers and data with the GetHeaders,
325         /// GetRegionalHeader and GetLocalStruct methods for example.
326         /// Refer to the MUONRawStreamTrigger.C macro to see how to use the fast
327         /// decoder interface optimally.
328         
329         if (fDDLObject != NULL) return fDDLObject;
330         
331         fDDLObject = new AliMUONDDLTrigger;
332         
333         // Copy over all DARC, global headers and scalars.
334         AliMUONDarcHeader* darcHeader = fDDLObject->GetDarcHeader();
335         const AliHeader* hdr = GetHeaders();
336         UInt_t word = hdr->GetDarcHeader();
337         memcpy(darcHeader->GetHeader(), &word, sizeof(word));
338         if (hdr->GetDarcScalars() != NULL)
339         {
340                 memcpy(darcHeader->GetDarcScalers(), hdr->GetDarcScalars(), sizeof(AliMUONDarcScalarsStruct));
341         }
342         memcpy(darcHeader->GetGlobalInput(), hdr->GetGlobalHeader(), sizeof(AliMUONGlobalHeaderStruct));
343         if (hdr->GetGlobalScalars() != NULL)
344         {
345                 memcpy(darcHeader->GetGlobalScalers(), hdr->GetGlobalScalars(), sizeof(AliMUONGlobalScalarsStruct));
346         }
347         
348         for (Int_t iReg = 0; iReg < (Int_t)GetRegionalHeaderCount(); iReg++)
349         {
350                 AliMUONRegHeader regHeader;
351                 AliMUONLocalStruct localStruct;
352                 
353                 const AliRegionalHeader* rh = GetRegionalHeader(iReg);
354                 // Copy local structure and scalars and add everything into DDL object.
355                 memcpy(regHeader.GetHeader(), rh->GetHeader(), sizeof(AliMUONRegionalHeaderStruct));
356                 if (rh->GetScalars() != NULL)
357                 {
358                         memcpy(regHeader.GetScalers(), rh->GetScalars(), sizeof(AliMUONRegionalScalarsStruct));
359                 }
360                 fDDLObject->AddRegHeader(regHeader);
361                 
362                 const AliLocalStruct* lstruct = rh->GetFirstLocalStruct();
363                 while (lstruct != NULL)
364                 {
365                         // Copy local structure and scalars and add everything into DDL object.
366                         memcpy(localStruct.GetData(), lstruct->GetData(), sizeof(AliMUONLocalInfoStruct));
367                         if (lstruct->GetScalars() != NULL)
368                         {
369                                 memcpy(localStruct.GetScalers(), lstruct->GetScalars(), sizeof(AliMUONLocalScalarsStruct));
370                         }
371                         if (AliMUONRawStreamTriggerHP::AliLocalStruct::GetOverrideIdFlag() == true)
372                         {
373                                 // Since the override ID flag is set, we need to replace the
374                                 // ID in the structure with the calculated one returned by GetId().
375                                 AliMUONLocalInfoStruct* strptr = reinterpret_cast<AliMUONLocalInfoStruct*>( localStruct.GetData() );
376                                 UInt_t triggerBits = strptr->fTriggerBits;
377                                 triggerBits &= ~(0xF << 19);
378                                 strptr->fTriggerBits = triggerBits | ((lstruct->GetId() & 0xF) << 19);
379                         }
380                         fDDLObject->AddLocStruct(localStruct, iReg);
381                         lstruct = lstruct->Next();
382                 }
383         }
384         
385         return fDDLObject;
386 }
387
388
389 void AliMUONRawStreamTriggerHP::SetMaxReg(Int_t reg)
390 {
391         /// Set the maximum allowed number of regional cards in the DDL.
392         
393         fDecoder.MaxRegionals( (UInt_t) reg );
394         
395         fDecoder.GetHandler().SetMaxStructs(
396                         fDecoder.MaxRegionals(),
397                         fDecoder.MaxLocals()
398                 );
399 }
400
401
402 void AliMUONRawStreamTriggerHP::SetMaxLoc(Int_t loc)
403 {
404         /// Sets the maximum number of local cards in the DDL.
405         
406         fDecoder.MaxLocals( (UInt_t) loc );
407         
408         fDecoder.GetHandler().SetMaxStructs(
409                         fDecoder.MaxRegionals(),
410                         fDecoder.MaxLocals()
411                 );
412 }
413
414 ///////////////////////////////////////////////////////////////////////////////
415
416 void AliMUONRawStreamTriggerHP::AliHeader::Print() const
417 {
418         /// Print DARC header, global header and global scalars to screen.
419         
420         cout << "===== DARC info =====" << endl;
421         cout << "Header bits : 0x" << hex << fDarcHeader << dec << endl;
422         if (fDarcScalars != NULL)
423         {
424                 cout << "L0R :   " << fDarcScalars->fL0R << " (0x"
425                         << hex << fDarcScalars->fL0R << dec << ")" << endl;
426                 cout << "L1P :   " << fDarcScalars->fL1P << " (0x"
427                         << hex << fDarcScalars->fL1P << dec << ")" << endl;
428                 cout << "L1S :   " << fDarcScalars->fL1S << " (0x"
429                         << hex << fDarcScalars->fL1S << dec << ")" << endl;
430                 cout << "L2A :   " << fDarcScalars->fL2A << " (0x"
431                         << hex << fDarcScalars->fL2A << dec << ")" << endl;
432                 cout << "L2R :   " << fDarcScalars->fL2R << " (0x"
433                         << hex << fDarcScalars->fL2R << dec << ")" << endl;
434                 cout << "Clock : " << fDarcScalars->fClk << " (0x"
435                         << hex << fDarcScalars->fClk << dec << ")" << endl;
436                 cout << "Hold :  " << fDarcScalars->fHold << " (0x"
437                         << hex << fDarcScalars->fHold << dec << ")" << endl;
438                 cout << "Spare : " << fDarcScalars->fSpare << " (0x"
439                         << hex << fDarcScalars->fSpare << dec << ")" << endl;
440         }
441         else
442         {
443                 cout << "Scalars == NULL" << endl;
444         }
445         
446         cout << "===== Global info =====" << endl;
447         for (int i = 0; i < 4; i++)
448         {
449                 cout << "Input[" << i << "] : " << fGlobalHeader->fInput[i] << " (0x"
450                         << hex << fGlobalHeader->fInput[i] << dec << ")" << endl;
451         }
452         cout << "Output :    " << fGlobalHeader->fOutput << " (0x"
453                 << hex << fGlobalHeader->fOutput << dec << ")" << endl;
454         if (fGlobalScalars != NULL)
455         {
456                 cout << "L0 :         " << fGlobalScalars->fL0 << " (0x"
457                         << hex << fGlobalScalars->fL0 << dec << ")" << endl;
458                 cout << "Clock :     " << fGlobalScalars->fClk << " (0x"
459                         << hex << fGlobalScalars->fClk << dec << ")" << endl;
460                 for (int j = 0; j < 4; j++)
461                 {
462                         cout << "Scaler[" << j << "] : " << fGlobalScalars->fScaler[j] << " (0x"
463                                 << hex << fGlobalScalars->fScaler[j] << dec << ")" << endl;
464                 }
465                 cout << "Hold :      " << fGlobalScalars->fHold << " (0x"
466                         << hex << fGlobalScalars->fHold << dec << ")" << endl;
467                 cout << "Spare :     " << fGlobalScalars->fSpare << " (0x"
468                         << hex << fGlobalScalars->fSpare << dec << ")" << endl;
469         }
470         else
471         {
472                 cout << "Scalars == NULL" << endl;
473         }
474 }
475
476 void AliMUONRawStreamTriggerHP::AliRegionalHeader::Print() const
477 {
478         /// Print the regional header and scalars to screen.
479         
480         cout << "===== Regional card info =====" << endl;
481         cout << "DarcWord : " << fHeader->fDarcWord << " (0x"
482                 << hex << fHeader->fDarcWord << dec << ")" << endl;
483         cout << "Word :     " << fHeader->fWord << " (0x"
484                 << hex << fHeader->fWord << dec << ")" << endl;
485         cout << "Input[0] : " << fHeader->fInput[0] << " (0x"
486                 << hex << fHeader->fInput[0] << dec << ")" << endl;
487         cout << "Input[1] : " << fHeader->fInput[1] << " (0x"
488                 << hex << fHeader->fInput[1] << dec << ")" << endl;
489         cout << "L0/Mask :  " << fHeader->fL0CountAndMask << " (0x"
490                 << hex << fHeader->fL0CountAndMask << dec << ")" << endl;
491         if (fScalars != NULL)
492         {
493                 cout << "Clock :     " << fScalars->fClk << " (0x"
494                         << hex << fScalars->fClk << dec << ")" << endl;
495                 for (int i = 0; i < 8; i++)
496                 {
497                         cout << "Scaler[" << i << "] : " << fScalars->fScaler[i] << " (0x"
498                                 << hex << fScalars->fScaler[i] << dec << ")" << endl;
499                 }
500                 cout << "Hold :      " << fScalars->fHold << " (0x"
501                         << hex << fScalars->fHold << dec << ")" << endl;
502         }
503         else
504         {
505                 cout << "Scalars == NULL" << endl;
506         }
507 }
508
509 void AliMUONRawStreamTriggerHP::AliLocalStruct::Print() const
510 {
511         /// Print local trigger structure and scalars to screen.
512         
513         cout << "===== Local card info =====" << endl;
514         cout << "X2X1 :         " << fLocalStruct->fX2X1 << " (0x"
515                 << hex << fLocalStruct->fX2X1 << dec << ")" << endl;
516         cout << "X4X3 :         " << fLocalStruct->fX4X3 << " (0x"
517                 << hex << fLocalStruct->fX4X3 << dec << ")" << endl;
518         cout << "Y2Y1 :         " << fLocalStruct->fY2Y1 << " (0x"
519                 << hex << fLocalStruct->fY2Y1 << dec << ")" << endl;
520         cout << "Y4Y3 :         " << fLocalStruct->fY4Y3 << " (0x"
521                 << hex << fLocalStruct->fY4Y3 << dec << ")" << endl;
522         cout << "Trigger bits : " << fLocalStruct->fTriggerBits << " (0x"
523                 << hex << fLocalStruct->fTriggerBits << dec << ")" << endl;
524         if (fScalars != NULL)
525         {
526                 cout << "L0 :           " << fScalars->fL0 << " (0x"
527                         << hex << fScalars->fL0 << dec << ")" << endl;
528                 cout << "Hold :         " << fScalars->fHold << " (0x"
529                         << hex << fScalars->fHold << dec << ")" << endl;
530                 cout << "Clock :        " << fScalars->fClk << " (0x"
531                         << hex << fScalars->fClk << dec << ")" << endl;
532                 cout << "LPtNTrig :     " << fScalars->fLPtNTrig << " (0x"
533                         << hex << fScalars->fLPtNTrig << dec << ")" << endl;
534                 cout << "HPtNTrig :     " << fScalars->fHPtNTrig << " (0x"
535                         << hex << fScalars->fHPtNTrig << dec << ")" << endl;
536                 cout << "LPtRTrig :     " << fScalars->fLPtRTrig << " (0x"
537                         << hex << fScalars->fLPtRTrig << dec << ")" << endl;
538                 cout << "HPtRTrig :     " << fScalars->fHPtRTrig << " (0x"
539                         << hex << fScalars->fHPtRTrig << dec << ")" << endl;
540                 cout << "LPtLTrig :     " << fScalars->fLPtLTrig << " (0x"
541                         << hex << fScalars->fLPtLTrig << dec << ")" << endl;
542                 cout << "HPtLTrig :     " << fScalars->fHPtLTrig << " (0x"
543                         << hex << fScalars->fHPtLTrig << dec << ")" << endl;
544                 cout << "LPtSTrig :     " << fScalars->fLPtSTrig << " (0x"
545                         << hex << fScalars->fLPtSTrig << dec << ")" << endl;
546                 cout << "HPtSTrig :     " << fScalars->fHPtSTrig << " (0x"
547                         << hex << fScalars->fHPtSTrig << dec << ")" << endl;
548                 for (int i = 0; i < 8*4; i++)
549                 {
550                         cout << "Scaler[" << i << "] :  " << fScalars->fScaler[i] << " (0x"
551                                 << hex << fScalars->fScaler[i] << dec << ")" << endl;
552                 }
553                 cout << "EOS :          " << fScalars->fEOS << " (0x"
554                         << hex << fScalars->fEOS << dec << ")" << endl;
555                 cout << "Reset :        " << fScalars->fReset << " (0x"
556                         << hex << fScalars->fReset << dec << ")" << endl;
557         }
558         else
559         {
560                 cout << "Scalars == NULL" << endl;
561         }
562 }
563
564 ///////////////////////////////////////////////////////////////////////////////
565
566 AliMUONRawStreamTriggerHP::AliDecoderEventHandler::AliDecoderEventHandler() :
567         fRawStream(NULL),
568         fBufferStart(NULL),
569         fDarcHeader(0),
570         fDarcScalars(NULL),
571         fHeaders(),
572         fRegionalsCount(0),
573         fRegionals(NULL),
574         fLocals(NULL),
575         fEndOfLocals(NULL),
576         fCurrentRegional(NULL),
577         fCurrentLocal(NULL),
578         fDarcEoWErrors(0),
579         fGlobalEoWErrors(0),
580         fRegEoWErrors(0),
581         fLocalEoWErrors(0),
582         fWarnings(kTRUE)
583 {
584         /// Default constructor
585 }
586
587
588 AliMUONRawStreamTriggerHP::AliDecoderEventHandler::~AliDecoderEventHandler()
589 {
590         /// Default destructor cleans up the allocated memory.
591         
592         if (fRegionals != NULL) delete [] fRegionals;
593         if (fLocals != NULL) delete [] fLocals;
594 }
595
596
597 void AliMUONRawStreamTriggerHP::AliDecoderEventHandler::SetMaxStructs(
598                 UInt_t maxRegionals, UInt_t maxLocals
599         )
600 {
601         /// Sets the maximum number of structures allowed.
602         
603         // Start by clearing the current arrays.
604         if (fRegionals != NULL)
605         {
606                 delete [] fRegionals;
607                 fRegionals = NULL;
608         }
609         if (fLocals != NULL)
610         {
611                 delete [] fLocals;
612                 fLocals = NULL;
613                 fEndOfLocals = NULL;
614         }
615         fCurrentRegional = NULL;
616         fCurrentLocal = NULL;
617         
618         // Allocate new memory.
619         fRegionals = new AliRegionalHeader[maxRegionals];
620         fLocals = new AliLocalStruct[maxRegionals*maxLocals];
621         fEndOfLocals = fLocals;
622         
623         fRegionalsCount = maxRegionals;
624 }
625
626
627 void AliMUONRawStreamTriggerHP::AliDecoderEventHandler::OnNewBuffer(
628                 const void* buffer, UInt_t /*bufferSize*/
629         )
630 {
631         /// This is called by the high performance decoder when a new DDL payload
632         /// is about to be decoded.
633
634         assert( fRawStream != NULL );
635         
636         // remember the start of the buffer to be used in OnError.
637         fBufferStart = buffer;
638
639         // Reset error counters.
640         fDarcEoWErrors = 0;
641         fGlobalEoWErrors = 0;
642         fRegEoWErrors = 0;
643         fLocalEoWErrors = 0;
644         
645         // Reset the current local structure pointer which will be used to track
646         // where we need to fill fLocals. We have to subtract one space because we
647         // will increment the pointer the first time in the OnLocalStruct method.
648         fCurrentLocal = fLocals-1;
649         
650         fCurrentRegional = NULL;
651         
652         // Reset and link up all the regional structures together.
653         for (UInt_t i = 0; i+1 < fRegionalsCount; i++)
654         {
655                 fRegionals[i] = AliRegionalHeader(fLocals, &fgkEmptyHeader, NULL);
656                 fRegionals[i].SetNext(&fRegionals[i+1]);
657         }
658         // Reset the last structure.
659         fRegionals[fRegionalsCount-1] = AliRegionalHeader(fLocals, &fgkEmptyHeader, NULL);
660 }
661
662
663 void AliMUONRawStreamTriggerHP::AliDecoderEventHandler::OnError(
664                 ErrorCode error, const void* location
665         )
666 {
667         /// This is called by the high performance decoder when a error occurs
668         /// when trying to decode the DDL payload. This indicates corruption in
669         /// the data. This method converts the error code to a descriptive message
670         /// and logs this with the raw reader.
671         /// \param error  The error code indicating the problem.
672         /// \param location  A pointer to the location within the DDL payload buffer
673         ///              being decoded where the problem with the data was found.
674
675         assert( fRawStream != NULL );
676         assert( fRawStream->GetReader() != NULL );
677         
678         Char_t* message = NULL;
679         //UInt_t word = 0;
680
681         switch (error)
682         {
683         case kWrongEventType:
684                 message = Form("Wrong event type obtained from the Darc header, take the one of CDH");
685                 break;
686                 
687         case kBadEndOfDarc:
688                 fDarcEoWErrors++;
689                 message = Form(
690                         "Wrong end of Darc word %x instead of %x\n",
691                         *reinterpret_cast<const UInt_t*>(location),
692                         AliMUONTriggerDDLDecoder<AliMUONTriggerDDLDecoderEventHandler>::EndOfDarcWord()
693                 );
694                 fRawStream->GetReader()->AddMajorErrorLog(kDarcEoWErr, message);
695                 break;
696                 
697         case kBadEndOfGlobal:
698                 fGlobalEoWErrors++;
699                 message = Form(
700                         "Wrong end of Global word %x instead of %x\n",
701                         *reinterpret_cast<const UInt_t*>(location),
702                         AliMUONTriggerDDLDecoder<AliMUONTriggerDDLDecoderEventHandler>::EndOfGlobalWord()
703                 );
704                 fRawStream->GetReader()->AddMajorErrorLog(kGlobalEoWErr, message);
705                 break;
706                 
707         case kBadEndOfRegional:
708                 fRegEoWErrors++;
709                 message = Form(
710                         "Wrong end of Regional word %x instead of %x\n",
711                         *reinterpret_cast<const UInt_t*>(location),
712                         AliMUONTriggerDDLDecoder<AliMUONTriggerDDLDecoderEventHandler>::EndOfRegionalWord()
713                 );
714                 fRawStream->GetReader()->AddMajorErrorLog(kRegEoWErr, message);
715                 break;
716                 
717         case kBadEndOfLocal:
718                 fLocalEoWErrors++;
719                 message = Form(
720                         "Wrong end of Local word %x instead of %x\n",
721                         *reinterpret_cast<const UInt_t*>(location),
722                         AliMUONTriggerDDLDecoder<AliMUONTriggerDDLDecoderEventHandler>::EndOfLocalWord()
723                 );
724                 fRawStream->GetReader()->AddMajorErrorLog(kLocalEoWErr, message);
725                 break;
726                 
727         default:
728                 message = Form(
729                         "%s (At byte %lu in DDL.)",
730                         ErrorCodeToMessage(error),
731                         (unsigned long)location - (unsigned long)fBufferStart + sizeof(AliRawDataHeader)
732                 );
733                 fRawStream->GetReader()->AddMajorErrorLog(error, message);
734                 break;
735         }
736
737         if (fWarnings)
738         {
739                 AliWarningGeneral(
740                                 "AliMUONRawStreamTriggerHP::AliDecoderEventHandler",
741                                 message
742                         );
743         }
744 }
745