bugfix
[u/mrichter/AliRoot.git] / RAW / AliRawReaderDate.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.
21 ///
22 /// The AliRawReaderDate 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 "AliRawReaderDate.h"
28 #ifdef ALI_DATE
29 #include "event.h"
30 #endif
31
32 ClassImp(AliRawReaderDate)
33
34
35 AliRawReaderDate::AliRawReaderDate(
36 #ifdef ALI_DATE
37                                    void* event
38 #else
39                                    void* /* event */
40 #endif
41                                    ) :
42   fRequireHeader(kTRUE),
43   fFile(NULL),
44   fEvent(NULL),
45   fSubEvent(NULL),
46   fEquipment(NULL),
47   fPosition(NULL),
48   fEnd(NULL)
49 {
50 // create an object to read digits from the given date event
51
52 #ifdef ALI_DATE
53   fEvent = (eventHeaderStruct*) event;
54 #else
55   Fatal("AliRawReaderDate", "this class was compiled without DATE");
56 #endif
57 }
58
59 AliRawReaderDate::AliRawReaderDate(
60 #ifdef ALI_DATE
61                                    const char* fileName, Int_t eventNumber
62 #else
63                                    const char* /*fileName*/, 
64                                    Int_t /*eventNumber*/
65 #endif
66                                    ) :
67   fRequireHeader(kTRUE),
68   fFile(NULL),
69   fEvent(NULL),
70   fSubEvent(NULL),
71   fEquipment(NULL),
72   fPosition(NULL),
73   fEnd(NULL)
74 {
75 // create an object to read digits from the given date event
76
77 #ifdef ALI_DATE
78   fFile = fopen(fileName, "rb");
79   if (!fFile) {
80     Error("AliRawReaderDate", "could not open file %s", fileName);
81     return;
82   }
83   if (eventNumber < 0) return;
84
85   eventHeaderStruct header;
86   UInt_t headerSize = sizeof(eventHeaderStruct);
87   while (fread(&header, 1, headerSize, fFile) == headerSize) {
88     if (eventNumber == 0) {
89       UChar_t* buffer = new UChar_t[header.eventSize];
90       fseek(fFile, -headerSize, SEEK_CUR);
91       if (fread(buffer, 1, header.eventSize, fFile) != header.eventSize) break;
92       fEvent = (eventHeaderStruct*) buffer;
93       break;
94     }
95     fseek(fFile, header.eventSize-headerSize, SEEK_CUR);
96     eventNumber--;
97   }
98
99 #else
100   Fatal("AliRawReaderDate", "this class was compiled without DATE");
101 #endif
102 }
103
104 AliRawReaderDate::AliRawReaderDate(const AliRawReaderDate& rawReader) :
105   AliRawReader(rawReader),
106   fRequireHeader(rawReader.fRequireHeader),
107   fFile(rawReader.fFile),
108   fEvent(rawReader.fEvent),
109   fSubEvent(rawReader.fSubEvent),
110   fEquipment(rawReader.fEquipment),
111   fPosition(rawReader.fPosition),
112   fEnd(rawReader.fEnd)
113
114 {
115 // copy constructor
116
117   Fatal("AliRawReaderDate", "copy constructor not implemented");
118 }
119
120 AliRawReaderDate& AliRawReaderDate::operator = (const AliRawReaderDate& 
121                                                 /*rawReader*/)
122 {
123 // assignment operator
124
125   Fatal("operator =", "assignment operator not implemented");
126   return *this;
127 }
128
129 AliRawReaderDate::~AliRawReaderDate()
130 {
131 // destructor
132
133 #ifdef ALI_DATE
134   if (fFile) {
135     delete[] fEvent;
136     fclose(fFile);
137   }
138 #endif
139 }
140
141
142 UInt_t AliRawReaderDate::GetType() const
143 {
144 // get the type from the event header
145
146 #ifdef ALI_DATE
147   if (!fEvent) return 0;
148   return fEvent->eventType;
149 #else
150   return 0;
151 #endif
152 }
153
154 UInt_t AliRawReaderDate::GetRunNumber() const
155 {
156 // get the run number from the event header
157
158 #ifdef ALI_DATE
159   if (!fEvent) return 0;
160   return fEvent->eventRunNb;
161 #else
162   return 0;
163 #endif
164 }
165
166 const UInt_t* AliRawReaderDate::GetEventId() const
167 {
168 // get the event id from the event header
169
170 #ifdef ALI_DATE
171   if (!fEvent) return NULL;
172   return fEvent->eventId;
173 #else
174   return NULL;
175 #endif
176 }
177
178 const UInt_t* AliRawReaderDate::GetTriggerPattern() const
179 {
180 // get the trigger pattern from the event header
181
182 #ifdef ALI_DATE
183   if (!fEvent) return NULL;
184   return fEvent->eventTriggerPattern;
185 #else
186   return NULL;
187 #endif
188 }
189
190 const UInt_t* AliRawReaderDate::GetDetectorPattern() const
191 {
192 // get the detector pattern from the event header
193
194 #ifdef ALI_DATE
195   if (!fEvent) return NULL;
196   return fEvent->eventDetectorPattern;
197 #else
198   return NULL;
199 #endif
200 }
201
202 const UInt_t* AliRawReaderDate::GetAttributes() const
203 {
204 // get the type attributes from the event header
205
206 #ifdef ALI_DATE
207   if (!fEvent) return NULL;
208   return fEvent->eventTypeAttribute;
209 #else
210   return NULL;
211 #endif
212 }
213
214 UInt_t AliRawReaderDate::GetLDCId() const
215 {
216 // get the LDC Id from the event header
217
218 #ifdef ALI_DATE
219   if (!fSubEvent) return 0;
220   return fSubEvent->eventLdcId;
221 #else
222   return 0;
223 #endif
224 }
225
226 UInt_t AliRawReaderDate::GetGDCId() const
227 {
228 // get the GDC Id from the event header
229
230 #ifdef ALI_DATE
231   if (!fEvent) return 0;
232   return fEvent->eventGdcId;
233 #else
234   return 0;
235 #endif
236 }
237
238
239 Int_t AliRawReaderDate::GetEquipmentSize() const
240 {
241 // get the size of the equipment
242
243 #ifdef ALI_DATE
244   if (!fEquipment) return 0;
245   return fEquipment->equipmentSize;
246 #else
247   return 0;
248 #endif
249 }
250
251 Int_t AliRawReaderDate::GetEquipmentType() const
252 {
253 // get the type from the equipment header
254
255 #ifdef ALI_DATE
256   if (!fEquipment) return -1;
257   return fEquipment->equipmentType;
258 #else
259   return 0;
260 #endif
261 }
262
263 Int_t AliRawReaderDate::GetEquipmentId() const
264 {
265 // get the ID from the equipment header
266
267 #ifdef ALI_DATE
268   if (!fEquipment) return -1;
269   return fEquipment->equipmentId;
270 #else
271   return 0;
272 #endif
273 }
274
275 const UInt_t* AliRawReaderDate::GetEquipmentAttributes() const
276 {
277 // get the attributes from the equipment header
278
279 #ifdef ALI_DATE
280   if (!fEquipment) return NULL;
281   return fEquipment->equipmentTypeAttribute;
282 #else
283   return 0;
284 #endif
285 }
286
287 Int_t AliRawReaderDate::GetEquipmentElementSize() const
288 {
289 // get the basic element size from the equipment header
290
291 #ifdef ALI_DATE
292   if (!fEquipment) return 0;
293   return fEquipment->equipmentBasicElementSize;
294 #else
295   return 0;
296 #endif
297 }
298
299
300 Bool_t AliRawReaderDate::ReadHeader()
301 {
302 // read a data header at the current position
303 // returns kFALSE if the data header could not be read
304
305   fErrorCode = 0;
306
307 #ifdef ALI_DATE
308   fHeader = NULL;
309   if (!fEvent) return kFALSE;
310   // check whether there are sub events
311   if (fEvent->eventSize <= fEvent->eventHeadSize) return kFALSE;
312
313   do {
314     // skip payload (if event was not selected)
315     if (fCount > 0) fPosition += fCount;
316
317     // get the first or the next equipment if at the end of an equipment
318     if (!fEquipment || (fPosition >= fEnd)) {
319       fEquipment = NULL;
320
321       // get the first or the next sub event if at the end of a sub event
322       if (!fSubEvent || 
323           (fPosition >= ((UChar_t*)fSubEvent) + fSubEvent->eventSize)) {
324
325         // check for end of event data
326         if (fPosition >= ((UChar_t*)fEvent)+fEvent->eventSize) return kFALSE;
327         if (fSubEvent) {
328           fSubEvent = (eventHeaderStruct*) (((UChar_t*)fSubEvent) + 
329                                             fSubEvent->eventSize);
330         } else {
331           fSubEvent = (eventHeaderStruct*) (((UChar_t*)fEvent) + 
332                                             fEvent->eventHeadSize);
333         }
334
335         // check the magic word of the sub event
336         if (fSubEvent->eventMagic != EVENT_MAGIC_NUMBER) {
337           Error("ReadHeader", "wrong magic number in sub event!\n"
338                 " run: %d  event: %d %d  LDC: %d  GDC: %d\n", 
339                 fSubEvent->eventRunNb, 
340                 fSubEvent->eventId[0], fSubEvent->eventId[1],
341                 fSubEvent->eventLdcId, fSubEvent->eventGdcId);
342           fErrorCode = kErrMagic;
343           return kFALSE;
344         }
345
346         // continue if no data in the subevent
347         if (fSubEvent->eventSize == fSubEvent->eventHeadSize) {
348           fPosition = fEnd = ((UChar_t*)fSubEvent) + fSubEvent->eventSize;
349           fCount = 0;
350           continue;
351         }
352
353         fEquipment = (equipmentHeaderStruct*)
354           (((UChar_t*)fSubEvent) + fSubEvent->eventHeadSize);
355
356       } else {
357         fEquipment = (equipmentHeaderStruct*) fEnd;
358       }
359
360       fCount = 0;
361       fPosition = ((UChar_t*)fEquipment) + sizeof(equipmentHeaderStruct);
362       if (fSubEvent->eventVersion <= 0x00030002) {
363         fEnd = fPosition + fEquipment->equipmentSize;
364       } else {
365         fEnd = ((UChar_t*)fEquipment) + fEquipment->equipmentSize;
366       }
367     }
368
369     // continue with the next sub event if no data left in the payload
370     if (fPosition >= fEnd) continue;
371
372     if (fRequireHeader) {
373       // check that there are enough bytes left for the data header
374       if (fPosition + sizeof(AliRawDataHeader) > fEnd) {
375         Error("ReadHeader", "could not read data header data!");
376         Warning("ReadHeader", "skipping %d bytes\n"
377                 " run: %d  event: %d %d  LDC: %d  GDC: %d\n", 
378                 fEnd - fPosition, fSubEvent->eventRunNb, 
379                 fSubEvent->eventId[0], fSubEvent->eventId[1],
380                 fSubEvent->eventLdcId, fSubEvent->eventGdcId);
381         fCount = 0;
382         fPosition = fEnd;
383         fErrorCode = kErrNoDataHeader;
384         continue;
385       }
386
387       // "read" the data header
388       fHeader = (AliRawDataHeader*) fPosition;
389       fPosition += sizeof(AliRawDataHeader);
390     }
391
392     if (fHeader && (fHeader->fSize != 0xFFFFFFFF)) {
393       fCount = fHeader->fSize - sizeof(AliRawDataHeader);
394
395       // check consistency of data size in the header and in the sub event
396       if (fPosition + fCount > fEnd) {
397         Error("ReadHeader", "size in data header exceeds event size!");
398         Warning("ReadHeader", "skipping %d bytes\n"
399                 " run: %d  event: %d %d  LDC: %d  GDC: %d\n", 
400                 fEnd - fPosition, fSubEvent->eventRunNb, 
401                 fSubEvent->eventId[0], fSubEvent->eventId[1],
402                 fSubEvent->eventLdcId, fSubEvent->eventGdcId);
403         fCount = 0;
404         fPosition = fEnd;
405         fErrorCode = kErrSize;
406         continue;
407       }
408
409     } else {
410       fCount = fEnd - fPosition;
411     }
412
413   } while (!fEquipment || !IsSelected());
414
415   return kTRUE;
416 #else
417   return kFALSE;
418 #endif
419 }
420
421 Bool_t AliRawReaderDate::ReadNextData(UChar_t*& data)
422 {
423 // reads the next payload at the current position
424 // returns kFALSE if the data could not be read
425
426   fErrorCode = 0;
427   while (fCount == 0) {
428     if (!ReadHeader()) return kFALSE;
429   }
430   data = fPosition;
431   fPosition += fCount;  
432   fCount = 0;
433   return kTRUE;
434 }
435
436 Bool_t AliRawReaderDate::ReadNext(UChar_t* data, Int_t size)
437 {
438 // reads the next block of data at the current position
439 // returns kFALSE if the data could not be read
440
441   fErrorCode = 0;
442   if (fPosition + size > fEnd) {
443     Error("ReadNext", "could not read data!");
444     fErrorCode = kErrOutOfBounds;
445     return kFALSE;
446   }
447   memcpy(data, fPosition, size);
448   fPosition += size;
449   fCount -= size;
450   return kTRUE;
451 }
452
453
454 Bool_t AliRawReaderDate::Reset()
455 {
456 // reset the current position to the beginning of the event
457
458 #ifdef ALI_DATE
459   fSubEvent = NULL;
460 #endif
461   fCount = 0;
462   fPosition = fEnd = NULL;
463   return kTRUE;
464 }
465
466
467 Bool_t AliRawReaderDate::NextEvent()
468 {
469 // go to the next event in the date file
470
471 #ifdef ALI_DATE
472   if (!fFile) return kFALSE;
473
474   eventHeaderStruct header;
475   UInt_t headerSize = sizeof(eventHeaderStruct);
476   if (fEvent) delete[] fEvent;
477   fEvent = &header;
478
479   while (fread(&header, 1, headerSize, fFile) == headerSize) {
480     if (!IsEventSelected()) {
481       fseek(fFile, header.eventSize-headerSize, SEEK_CUR);
482       continue;
483     }
484     UChar_t* buffer = new UChar_t[header.eventSize];
485     fseek(fFile, -headerSize, SEEK_CUR);
486     if (fread(buffer, 1, header.eventSize, fFile) != header.eventSize) {
487       Error("NextEvent", "could not read event from file");
488       delete[] buffer;
489       break;
490     }
491     fEvent = (eventHeaderStruct*) buffer;
492     return kTRUE;
493   };
494
495   fEvent = NULL;
496 #endif
497
498   return kFALSE;
499 }
500
501 Bool_t AliRawReaderDate::RewindEvents()
502 {
503 // go back to the beginning of the date file
504
505   if (!fFile) return kFALSE;
506
507   fseek(fFile, 0, SEEK_SET);
508   return Reset();
509 }
510
511
512 Int_t AliRawReaderDate::CheckData() const
513 {
514 // check the consistency of the data
515
516 #ifdef ALI_DATE
517   if (!fEvent) return 0;
518   // check whether there are sub events
519   if (fEvent->eventSize <= fEvent->eventHeadSize) return 0;
520
521   eventHeaderStruct* subEvent = NULL;
522   UChar_t* position = 0;
523   UChar_t* end = 0;
524   Int_t result = 0;
525
526   while (kTRUE) {
527     // get the first or the next sub event if at the end of a sub event
528     if (!subEvent || (position >= end)) {
529
530       // check for end of event data
531       if (position >= ((UChar_t*)fEvent)+fEvent->eventSize) return result;
532       if (subEvent) {
533         subEvent = (eventHeaderStruct*) (((UChar_t*)subEvent) + 
534                                          subEvent->eventSize);
535       } else {
536         subEvent = (eventHeaderStruct*) (((UChar_t*)fEvent) + 
537                                          fEvent->eventHeadSize);
538       }
539
540       // check the magic word of the sub event
541       if (subEvent->eventMagic != EVENT_MAGIC_NUMBER) {
542         result |= kErrMagic;
543         return result;
544       }
545
546       position = ((UChar_t*)subEvent) + subEvent->eventHeadSize + 
547         sizeof(equipmentHeaderStruct);
548       end = ((UChar_t*)subEvent) + subEvent->eventSize;
549     }
550
551     // continue with the next sub event if no data left in the payload
552     if (position >= end) continue;
553
554     // check that there are enough bytes left for the data header
555     if (position + sizeof(AliRawDataHeader) > end) {
556       result |= kErrNoDataHeader;
557       position = end;
558       continue;
559     }
560
561     // check consistency of data size in the data header and in the sub event
562     AliRawDataHeader* header = (AliRawDataHeader*) position;
563     if (header->fSize != 0xFFFFFFFF) {
564       if (position + header->fSize > end) {
565         result |= kErrSize;
566         position = end;
567       } else {
568         position += header->fSize;
569       }
570     } else {
571       position = end;
572     }
573   };
574
575 #endif
576   return 0;
577 }