Bug fix. alimdc was ignoring the setting of the basket size, so it was always 32k
[u/mrichter/AliRoot.git] / RAW / AliRawReaderDateV3.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 /* $Id$ */
17
18 ///////////////////////////////////////////////////////////////////////////////
19 ///
20 /// This is a class for reading raw data from a date file or event (version 3).
21 ///
22 /// The AliRawReaderDateV3 is constructed either with a pointer to a
23 /// date event or with a file name and an event number.
24 ///
25 ///////////////////////////////////////////////////////////////////////////////
26
27 #include "AliRawReaderDateV3.h"
28
29 struct eventHeaderStruct { 
30   Int_t  size;          /* size of event in Bytes  */
31   UInt_t magic;         /* magic number used for consistency check */
32   UInt_t type;          /* event type */
33   UInt_t headLen;       /* size of header in bytes */
34   UInt_t runNb;         /* run number */
35   UInt_t burstNb;       /* burst number */
36   UInt_t nbInRun;       /* event number in run */
37   UInt_t nbInBurst;     /* event number in burst */
38   UInt_t triggerNb;     /* trigger number for this detector */
39   UInt_t fileSeqNb;     /* file sequence number for multifiles run */
40   UInt_t detectorId[3]; /* detector identification */
41   UInt_t time;          /* time in seconds since 0.00 GMT 1.1.1970 */
42   UInt_t usec;          /* microseconds */
43   UInt_t errorCode;
44   UInt_t deadTime;
45   UInt_t deadTimeusec;
46   UInt_t typeAttribute[2]; /* event type id mask */
47 };
48
49 #define EVENT_MAGIC_NUMBER         ((UInt_t)0xDA1E5AFE)
50
51
52 ClassImp(AliRawReaderDateV3)
53
54
55 AliRawReaderDateV3::AliRawReaderDateV3(void* event) :
56   fFile(NULL),
57   fEvent(NULL),
58   fSubEvent(NULL),
59   fPosition(NULL),
60   fEnd(NULL)
61 {
62 // create an object to read digits from the given date event
63
64   fEvent = (eventHeaderStruct*) event;
65 }
66
67 AliRawReaderDateV3::AliRawReaderDateV3(const char* fileName, 
68                                        Int_t eventNumber) :
69   fFile(NULL),
70   fEvent(NULL),
71   fSubEvent(NULL),
72   fPosition(NULL),
73   fEnd(NULL)
74 {
75 // create an object to read digits from the given date event
76
77   fFile = fopen(fileName, "rb");
78   if (!fFile) {
79     Error("AliRawReaderDateV3", "could not open file %s", fileName);
80     return;
81   }
82   if (eventNumber < 0) return;
83
84   eventHeaderStruct header;
85   UInt_t headerSize = sizeof(eventHeaderStruct);
86   while (fread(&header, 1, headerSize, fFile) == headerSize) {
87     if (eventNumber == 0) {
88       UChar_t* buffer = new UChar_t[header.size];
89       fseek(fFile, -(long)headerSize, SEEK_CUR);
90       if (Int_t(fread(buffer, 1, header.size, fFile)) != header.size) break;
91       fEvent = (eventHeaderStruct*) buffer;
92       break;
93     }
94     fseek(fFile, header.size-headerSize, SEEK_CUR);
95     eventNumber--;
96   }
97 }
98
99 AliRawReaderDateV3::AliRawReaderDateV3(const AliRawReaderDateV3& rawReader) :
100   AliRawReader(rawReader),
101   fFile(rawReader.fFile),
102   fEvent(rawReader.fEvent),
103   fSubEvent(rawReader.fSubEvent),
104   fPosition(rawReader.fPosition),
105   fEnd(rawReader.fEnd)
106
107 {
108 // copy constructor
109
110   Fatal("AliRawReaderDateV3", "copy constructor not implemented");
111 }
112
113 AliRawReaderDateV3& AliRawReaderDateV3::operator = (const AliRawReaderDateV3& 
114                                                 /*rawReader*/)
115 {
116 // assignment operator
117
118   Fatal("operator =", "assignment operator not implemented");
119   return *this;
120 }
121
122 AliRawReaderDateV3::~AliRawReaderDateV3()
123 {
124 // destructor
125
126   if (fFile) {
127     delete[] fEvent;
128     fclose(fFile);
129   }
130 }
131
132
133 UInt_t AliRawReaderDateV3::GetType() const
134 {
135 // get the type from the event header
136
137   if (!fEvent) return 0;
138   return fEvent->type;
139 }
140
141 UInt_t AliRawReaderDateV3::GetRunNumber() const
142 {
143 // get the run number from the event header
144
145   if (!fEvent) return 0;
146   return fEvent->runNb;
147 }
148
149 const UInt_t* AliRawReaderDateV3::GetEventId() const
150 {
151 // get the event id from the event header
152
153   if (!fEvent) return NULL;
154   return &(fEvent->nbInRun);
155 }
156
157 const UInt_t* AliRawReaderDateV3::GetTriggerPattern() const
158 {
159 // get the trigger pattern from the event header
160
161   return NULL;
162 }
163
164 const UInt_t* AliRawReaderDateV3::GetDetectorPattern() const
165 {
166 // get the detector pattern from the event header
167
168   if (!fEvent) return NULL;
169   return fEvent->detectorId;
170 }
171
172 const UInt_t* AliRawReaderDateV3::GetAttributes() const
173 {
174 // get the type attributes from the event header
175
176   if (!fEvent) return NULL;
177   return fEvent->typeAttribute;
178 }
179
180 const UInt_t* AliRawReaderDateV3::GetSubEventAttributes() const
181 {
182 // get the type attributes from the sub event header
183
184   if (!fSubEvent) return NULL;
185   return fSubEvent->typeAttribute;
186 }
187
188 UInt_t AliRawReaderDateV3::GetLDCId() const
189 {
190 // get the LDC Id from the event header
191
192   return UInt_t(-1);
193 }
194
195 UInt_t AliRawReaderDateV3::GetGDCId() const
196 {
197 // get the GDC Id from the event header
198
199   return UInt_t(-1);
200 }
201
202 UInt_t AliRawReaderDateV3::GetTimestamp() const
203 {
204 // get the timestamp from the event header
205
206   if (!fEvent) return 0;
207   return fEvent->time;
208 }
209
210 Int_t AliRawReaderDateV3::GetEquipmentSize() const
211 {
212 // get the size of the equipment
213
214   if (!fSubEvent) return 0;
215   return fSubEvent->size;
216 }
217
218 Int_t AliRawReaderDateV3::GetEquipmentType() const
219 {
220 // get the type from the equipment header
221
222   return 0;
223 }
224
225 Int_t AliRawReaderDateV3::GetEquipmentId() const
226 {
227 // get the ID from the equipment header
228
229   return 0;
230 }
231
232 const UInt_t* AliRawReaderDateV3::GetEquipmentAttributes() const
233 {
234 // get the attributes from the equipment header
235
236   return 0;
237 }
238
239 Int_t AliRawReaderDateV3::GetEquipmentElementSize() const
240 {
241 // get the basic element size from the equipment header
242
243   return 0;
244 }
245
246 Int_t AliRawReaderDateV3::GetEquipmentHeaderSize() const
247 {
248 // get the size of the equipment header
249
250   return 0;
251 }
252
253 Bool_t AliRawReaderDateV3::ReadHeader()
254 {
255 // read a data header at the current position
256 // returns kFALSE if the data header could not be read
257
258   fErrorCode = 0;
259
260   fHeader = NULL;
261   if (!fEvent) return kFALSE;
262   // check whether there are sub events
263   if (fEvent->size <= Int_t(fEvent->headLen)) return kFALSE;
264
265   do {
266     // skip payload (if event was not selected)
267     if (fCount > 0) fPosition += fCount;
268
269     // check for end of event data
270     if (fPosition >= ((UChar_t*)fEvent)+fEvent->size) return kFALSE;
271     if ((fEvent->detectorId[2] & 0x8000) != 0x8000) {
272       fSubEvent = fEvent;   // no super event
273     } else if (fSubEvent) {
274       fSubEvent = (eventHeaderStruct*) (((UChar_t*)fSubEvent) + 
275                                         fSubEvent->size);
276     } else {
277       fSubEvent = (eventHeaderStruct*) (((UChar_t*)fEvent) + 
278                                         fEvent->headLen);
279     }
280
281     // check the magic word of the sub event
282     if (fSubEvent->magic != EVENT_MAGIC_NUMBER) {
283       Error("ReadHeader", "wrong magic number in sub event!\n"
284             " run: %d  event: %d\n", 
285             fSubEvent->runNb, fSubEvent->nbInRun);
286       fErrorCode = kErrMagic;
287       return kFALSE;
288     }
289
290     // continue if no data in the subevent
291     if (fSubEvent->size == Int_t(fSubEvent->headLen)) {
292       fPosition = fEnd = ((UChar_t*)fSubEvent) + fSubEvent->size;
293       fCount = 0;
294       continue;
295     }
296
297     fCount = 0;
298     fPosition = ((UChar_t*)fSubEvent) + sizeof(eventHeaderStruct);
299     fEnd = ((UChar_t*)fSubEvent) + fSubEvent->size;
300
301     // continue with the next sub event if no data left in the payload
302     if (fPosition >= fEnd) continue;
303
304     if (fRequireHeader) {
305       // check that there are enough bytes left for the data header
306       if (fPosition + sizeof(AliRawDataHeader) > fEnd) {
307         Error("ReadHeader", "could not read data header data!");
308         Warning("ReadHeader", "skipping %d bytes\n"
309                 " run: %d  event: %d\n", 
310                 fEnd - fPosition, fSubEvent->runNb, fSubEvent->nbInRun);
311         fCount = 0;
312         fPosition = fEnd;
313         fErrorCode = kErrNoDataHeader;
314         continue;
315       }
316
317       // "read" the data header
318       fHeader = (AliRawDataHeader*) fPosition;
319       if ((fPosition + fHeader->fSize) != fEnd) {
320         if (fHeader->fSize != 0xFFFFFFFF)
321           Warning("ReadHeader",
322                   "raw data size found in the header is wrong (%d != %d)! Using the equipment size instead !",
323                   fHeader->fSize, fEnd - fPosition);
324         fHeader->fSize = fEnd - fPosition;
325       }
326       fPosition += sizeof(AliRawDataHeader);
327     }
328
329     if (fHeader && (fHeader->fSize != 0xFFFFFFFF)) {
330       fCount = fHeader->fSize - sizeof(AliRawDataHeader);
331
332       // check consistency of data size in the header and in the sub event
333       if (fPosition + fCount > fEnd) {
334         Error("ReadHeader", "size in data header exceeds event size!");
335         Warning("ReadHeader", "skipping %d bytes\n"
336                 " run: %d  event: %d\n", 
337                 fEnd - fPosition, fSubEvent->runNb, fSubEvent->nbInRun);
338         fCount = 0;
339         fPosition = fEnd;
340         fErrorCode = kErrSize;
341         continue;
342       }
343
344     } else {
345       fCount = fEnd - fPosition;
346     }
347
348   } while (!IsSelected());
349
350   return kTRUE;
351 }
352
353 Bool_t AliRawReaderDateV3::ReadNextData(UChar_t*& data)
354 {
355 // reads the next payload at the current position
356 // returns kFALSE if the data could not be read
357
358   fErrorCode = 0;
359   while (fCount == 0) {
360     if (!ReadHeader()) return kFALSE;
361   }
362   data = fPosition;
363   fPosition += fCount;  
364   fCount = 0;
365   return kTRUE;
366 }
367
368 Bool_t AliRawReaderDateV3::ReadNext(UChar_t* data, Int_t size)
369 {
370 // reads the next block of data at the current position
371 // returns kFALSE if the data could not be read
372
373   fErrorCode = 0;
374   if (fPosition + size > fEnd) {
375     Error("ReadNext", "could not read data!");
376     fErrorCode = kErrOutOfBounds;
377     return kFALSE;
378   }
379   memcpy(data, fPosition, size);
380   fPosition += size;
381   fCount -= size;
382   return kTRUE;
383 }
384
385
386 Bool_t AliRawReaderDateV3::Reset()
387 {
388 // reset the current position to the beginning of the event
389
390   fSubEvent = NULL;
391   fCount = 0;
392   fPosition = fEnd = NULL;
393   return kTRUE;
394 }
395
396
397 Bool_t AliRawReaderDateV3::NextEvent()
398 {
399 // go to the next event in the date file
400
401   if (!fFile) return kFALSE;
402
403   Reset();
404   eventHeaderStruct header;
405   UInt_t headerSize = sizeof(eventHeaderStruct);
406   if (fEvent) delete[] fEvent;
407   fEvent = &header;
408
409   while (fread(&header, 1, headerSize, fFile) == headerSize) {
410     if (!IsEventSelected()) {
411       fseek(fFile, header.size-headerSize, SEEK_CUR);
412       continue;
413     }
414     UChar_t* buffer = new UChar_t[header.size];
415     fseek(fFile, -(long)headerSize, SEEK_CUR);
416     if (Int_t(fread(buffer, 1, header.size, fFile)) != header.size) {
417       Error("NextEvent", "could not read event from file");
418       delete[] buffer;
419       break;
420     }
421     fEvent = (eventHeaderStruct*) buffer;
422     fEventNumber++;
423     return kTRUE;
424   };
425
426   fEvent = NULL;
427   return kFALSE;
428 }
429
430 Bool_t AliRawReaderDateV3::RewindEvents()
431 {
432 // go back to the beginning of the date file
433
434   if (!fFile) return kFALSE;
435
436   fseek(fFile, 0, SEEK_SET);
437   fEventNumber = -1;
438   return Reset();
439 }
440
441
442 Int_t AliRawReaderDateV3::CheckData() const
443 {
444 // check the consistency of the data
445
446   if (!fEvent) return 0;
447   // check whether there are sub events
448   if (fEvent->size <= Int_t(fEvent->headLen)) return 0;
449
450   eventHeaderStruct* subEvent = NULL;
451   UChar_t* position = 0;
452   UChar_t* end = 0;
453   Int_t result = 0;
454
455   while (kTRUE) {
456     // check for end of event data
457     if (position >= ((UChar_t*)fEvent)+fEvent->size) return result;
458     if ((fEvent->detectorId[2] & 0x8000) != 0x8000) {
459       subEvent = fEvent;   // no super event
460     } else if (subEvent) {
461       subEvent = (eventHeaderStruct*) (((UChar_t*)subEvent) + 
462                                        subEvent->size);
463     } else {
464       subEvent = (eventHeaderStruct*) (((UChar_t*)fEvent) + 
465                                        fEvent->headLen);
466     }
467
468     // check the magic word of the sub event
469     if (subEvent->magic != EVENT_MAGIC_NUMBER) {
470       result |= kErrMagic;
471       return result;
472     }
473
474     position = ((UChar_t*)subEvent) + subEvent->headLen;
475     end = ((UChar_t*)subEvent) + subEvent->size;
476
477     // continue with the next sub event if no data left in the payload
478     if (position >= end) continue;
479
480     if (fRequireHeader) {
481       // check that there are enough bytes left for the data header
482       if (position + sizeof(AliRawDataHeader) > end) {
483         result |= kErrNoDataHeader;
484         position = end;
485         continue;
486       }
487
488       // check consistency of data size in the data header and in the sub event
489       AliRawDataHeader* header = (AliRawDataHeader*) position;
490       if ((position + header->fSize) != end) {
491         if (header->fSize != 0xFFFFFFFF)
492           Warning("ReadHeader",
493                   "raw data size found in the header is wrong (%d != %d)! Using the equipment size instead !",
494                   header->fSize, end - position);
495         header->fSize = end - position;
496         result |= kErrSize;
497       }
498     }
499     position = end;
500   };
501
502   return 0;
503 }