]> git.uio.no Git - u/mrichter/AliRoot.git/blob - MUON/AliMUONRawStreamTrackerHP.cxx
- Use new AliMpSlatMotifMap::Instance() function to instantiate
[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 ///   UInt_t Next(const AliChannelInfo*& channels);
37 /// \endcode
38 ///
39 /// \author Artur Szostak <artursz@iafrica.com>
40 //-----------------------------------------------------------------------------
41
42 #include "AliMUONRawStreamTrackerHP.h"
43 #include "AliRawReader.h"
44 #include "AliLog.h"
45 #include <cassert>
46
47 /// \cond CLASSIMP
48 ClassImp(AliMUONRawStreamTrackerHP)
49 /// \endcond
50
51
52 AliMUONRawStreamTrackerHP::AliMUONRawStreamTrackerHP() :
53         AliMUONVRawStreamTracker(),
54         fDecoder(),
55         fDDL(0),
56         fCurrentChannel(0),
57         fBufferSize(8192),
58         fBuffer(new UChar_t[8192]),
59         fHadError(kFALSE)
60 {
61         ///
62         /// Default constructor.
63         ///
64 }
65
66
67 AliMUONRawStreamTrackerHP::AliMUONRawStreamTrackerHP(AliRawReader* rawReader) :
68         AliMUONVRawStreamTracker(rawReader),
69         fDecoder(),
70         fDDL(0),
71         fCurrentChannel(0),
72         fBufferSize(8192),
73         fBuffer(new UChar_t[8192]),
74         fHadError(kFALSE)
75 {
76         ///
77         /// Constructor with AliRawReader as argument.
78         ///
79         
80         fDecoder.GetHandler().SetRawStream(this);
81 }
82
83
84 AliMUONRawStreamTrackerHP::~AliMUONRawStreamTrackerHP()
85 {
86         ///
87         /// Default destructor.
88         ///
89         
90         if (fBuffer != NULL)
91         {
92                 delete [] fBuffer;
93         }
94 }
95
96
97 void AliMUONRawStreamTrackerHP::First()
98 {
99         /// Initialise or reset the iterator.
100         /// The first DDL will be found and decoded.
101         
102         assert( GetReader() != NULL );
103         
104         fDDL = 0;
105         NextDDL();
106 }
107
108
109 Bool_t AliMUONRawStreamTrackerHP::NextDDL()
110 {
111         /// Reading the next tracker DDL and decode the payload with the 
112         /// high performance decoder.
113         /// \return kTRUE if the next DDL was successfully read and kFALSE otherwise.
114
115         assert( GetReader() != NULL );
116         
117         if (IsDone()) return kFALSE;
118         
119         do
120         {
121                 GetReader()->Reset();
122                 GetReader()->Select("MUONTRK", fDDL, fDDL);  // Select the DDL file to be read.
123                 if (GetReader()->ReadHeader()) break;
124                 AliDebug(3, Form("Skipping DDL %d which does not seem to be there", fDDL+1));
125                 fDDL++;
126         }
127         while (fDDL < GetMaxDDL());
128         
129         AliDebug(3, Form("DDL Number %d\n", fDDL));
130         
131         Int_t dataSize = GetReader()->GetDataSize(); // in bytes
132         // Check if we have enough buffer space already in fBuffer. If we do then
133         // just continue reading otherwise we need to resize the buffer.
134         if (fBufferSize < dataSize)
135         {
136                 if (fBuffer != NULL)
137                 {
138                         delete [] fBuffer;
139                         fBuffer = NULL;
140                         fBufferSize = 0;
141                 }
142                 try
143                 {
144                         fBuffer = new UChar_t[dataSize];
145                         fBufferSize = dataSize;
146                 }
147                 catch (const std::bad_alloc&)
148                 {
149                         AliError("Could not allocate more buffer space. Cannot decode DDL.");
150                         return kFALSE;
151                 }
152         }
153         
154         if (not GetReader()->ReadNext(fBuffer, dataSize))
155         {
156                 return kFALSE;
157         }
158         
159 #ifndef R__BYTESWAP
160         Swap(fBuffer, dataSize); // Swap needed for mac power pc.
161 #endif
162         
163         bool result = false;
164         try
165         {
166                 // Since we might allocate memory inside OnNewBuffer in the event
167                 // handler we need to trap any memory allocation exception to be robust.
168                 result = fDecoder.Decode(fBuffer, dataSize);
169         }
170         catch (const std::bad_alloc&)
171         {
172                 AliError("Could not allocate more buffer space. Cannot decode DDL.");
173                 return kFALSE;
174         }
175         
176         fCurrentChannel = 0;
177         fDDL++; // Remember to increment index to next DDL.
178         return result;
179 }
180
181
182 Bool_t AliMUONRawStreamTrackerHP::IsDone() const
183 {
184         /// Indicates whether the iteration is finished or not.
185         /// \return kTRUE if we already read all the digits and kFALSE if not.
186         
187         return fDDL == GetMaxDDL();
188 }
189
190
191 Bool_t AliMUONRawStreamTrackerHP::Next(
192                 Int_t& busPatchId, UShort_t& manuId, UChar_t& manuChannel,
193                 UShort_t& adc
194         )
195 {
196         /// Advance one step in the iteration. Returns false if finished.
197         /// [out] \param busPatchId  This is filled with the bus patch ID of the digit.
198         /// [out] \param manuId      This is filled with the MANU ID of the digit.
199         /// [out] \param manuChannel This is filled with the MANU channel ID of the digit.
200         /// [out] \param adc         This is filled with the ADC signal value of the digit.
201         /// \return kTRUE if we read another digit and kFALSE if we have read all the
202         ///    digits already, i.e. at the end of the iteration.
203         
204         if (fCurrentChannel < fDecoder.GetHandler().ChannelCount())
205         {
206                 const AliChannelInfo& channel = fDecoder.GetHandler().Channels()[fCurrentChannel];
207                 busPatchId = channel.BusPatchId();
208                 manuId = channel.ManuId();
209                 manuChannel = channel.ChannelId();
210                 adc = channel.ADC();
211                 fCurrentChannel++;
212                 return kTRUE;
213         }
214         else
215         {
216                 if (NextDDL())
217                 {
218                         if (fCurrentChannel < fDecoder.GetHandler().ChannelCount())
219                         {
220                                 const AliChannelInfo& channel = fDecoder.GetHandler().Channels()[fCurrentChannel];
221                                 busPatchId = channel.BusPatchId();
222                                 manuId = channel.ManuId();
223                                 manuChannel = channel.ChannelId();
224                                 adc = channel.ADC();
225                                 fCurrentChannel++;
226                                 return kTRUE;
227                         }
228                 }
229         }
230         return kFALSE;
231 }
232
233
234 UInt_t AliMUONRawStreamTrackerHP::Next(const AliChannelInfo*& channels)
235 {
236         /// Returns the next batch of decoded channel data.
237         /// [out] \param channels This is filled with a pointer to an array of
238         ///          channels / digits that were decoded. This method does not
239         ///          modify 'channels' if zero is returned.
240         /// \return The number of elements in the array pointed to by 'channels'
241         ///    is returned. If zero is returned then there are no more channels to read.
242         
243         // Check if we are already at the end of the channels array. If so then we
244         // need to fetch the next non empty DDL.
245         if (fCurrentChannel >= fDecoder.GetHandler().ChannelCount())
246         {
247                 do
248                 {
249                         if (not NextDDL()) return 0;
250                 }
251                 // Make sure to keep going even for empty DDL payloads:
252                 while (fDecoder.GetHandler().ChannelCount() == 0);
253         }
254         channels = fDecoder.GetHandler().Channels() + fCurrentChannel;
255         return fDecoder.GetHandler().ChannelCount() - fCurrentChannel;
256 }
257
258 ///////////////////////////////////////////////////////////////////////////////
259
260 AliMUONRawStreamTrackerHP::AliDecoderEventHandler::AliDecoderEventHandler() :
261         fBusPatchId(0),
262         fChannelCount(0),
263         fMaxChannels(8192),
264         fChannelBuffer(new AliChannelInfo[8192]),
265         fRawStream(NULL),
266         fBufferStart(NULL)
267 {
268         /// Default constructor initialises the internal buffer to store decoded
269         /// channel / digit data to 8192 elements.
270         /// This array will grow dynamically if needed.
271 }
272
273
274 AliMUONRawStreamTrackerHP::AliDecoderEventHandler::~AliDecoderEventHandler()
275 {
276         /// Default destructor cleans up the allocated memory.
277         
278         if (fChannelBuffer != NULL)
279         {
280                 delete [] fChannelBuffer;
281         }
282 }
283
284 void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::OnNewBuffer(
285                 const void* buffer, UInt_t bufferSize
286         )
287 {
288         /// This is called by the high performance decoder when a new DDL payload
289         /// is about to be decoded.
290         /// \param buffer  The pointer to the buffer storing the DDL payload.
291         /// \param bufferSize  The size of the buffer in bytes.
292
293         // remember the start of the buffer to be used in OnError.
294         fBufferStart = buffer;
295         
296         // Reset the number of channels found.
297         fChannelCount = 0;
298         
299         // Check if we will have enough space in the fChannelBuffer array.
300         // If we do not then we need to resize the array.
301         // bufferSize / sizeof(UInt_t) will be a safe over estimate of the
302         // number of channels that we will find.
303         UInt_t maxPossibleChannels = bufferSize / sizeof(UInt_t);
304         if (maxPossibleChannels > fMaxChannels)
305         {
306                 if (fChannelBuffer != NULL)
307                 {
308                         delete [] fChannelBuffer;
309                         fChannelBuffer = NULL;
310                         fMaxChannels = 0;
311                 }
312                 fChannelBuffer = new AliChannelInfo[maxPossibleChannels];
313                 fMaxChannels = maxPossibleChannels;
314         }
315 }
316
317
318 void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::OnNewBusPatch(
319                 const AliMUONBusPatchHeaderStruct* header, const void* /*data*/
320         )
321 {
322         /// This is called by the high performance decoder when a new bus patch
323         /// is found within the DDL payload. All we do is remember the bus patch ID.
324         /// \param header  The bus patch header structure.
325         /// \param data  The bus patch data (not used in this method).
326         
327         fBusPatchId = header->fBusPatchId;
328 }
329
330
331 void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::OnData(UInt_t data)
332 {
333         /// This is called by the high performance decoder when a new bus patch
334         /// is found within the DDL payload. All we do is remember the bus patch ID.
335         /// \param data  The bus patch data (not used in this method).
336         
337         assert( fChannelCount < fMaxChannels );
338         
339         UShort_t manuId; UChar_t channelId; UShort_t adc;
340         UnpackADC(data, manuId, channelId, adc);
341         fChannelBuffer[fChannelCount] = AliChannelInfo(fBusPatchId, manuId, channelId, adc);
342         fChannelCount++;
343 }
344
345
346 void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::OnError(
347                 ErrorCode error, const void* location
348         )
349 {
350         /// This is called by the high performance decoder when a error occurs
351         /// when trying to decode the DDL payload. This indicates corruption in
352         /// the data. This method converts the error code to a descriptive message
353         /// and log this with the raw reader.
354         /// \param error  The error code indicating the problem.
355         /// \param location  A pointer to the location within the DDL payload buffer
356         ///              being decoded where the problem with the data was found.
357
358         assert( fRawStream != NULL );
359         assert( fRawStream->GetReader() != NULL );
360         
361         const char* msg = ErrorCodeToMessage(error);
362         unsigned long pos = (unsigned long)location - (unsigned long)fBufferStart;
363         
364         switch (error)
365         {
366         case kBadPaddingWord:
367         case kParityError:
368                 fRawStream->GetReader()->AddMinorErrorLog(error, Form("%s [At byte: %d]", msg, pos));
369                 break;
370         default:
371                 fRawStream->GetReader()->AddMajorErrorLog(error, Form("%s [At byte: %d]", msg, pos));
372                 break;
373         }
374 }
375