support of LDC events (no GDC super event)
[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 (!TEST_SYSTEM_ATTRIBUTE(fEvent->eventTypeAttribute, 
328                                    ATTR_SUPER_EVENT)) {
329           fSubEvent = fEvent;   // no super event
330         } else if (fSubEvent) {
331           fSubEvent = (eventHeaderStruct*) (((UChar_t*)fSubEvent) + 
332                                             fSubEvent->eventSize);
333         } else {
334           fSubEvent = (eventHeaderStruct*) (((UChar_t*)fEvent) + 
335                                             fEvent->eventHeadSize);
336         }
337
338         // check the magic word of the sub event
339         if (fSubEvent->eventMagic != EVENT_MAGIC_NUMBER) {
340           Error("ReadHeader", "wrong magic number in sub event!\n"
341                 " run: %d  event: %d %d  LDC: %d  GDC: %d\n", 
342                 fSubEvent->eventRunNb, 
343                 fSubEvent->eventId[0], fSubEvent->eventId[1],
344                 fSubEvent->eventLdcId, fSubEvent->eventGdcId);
345           fErrorCode = kErrMagic;
346           return kFALSE;
347         }
348
349         // continue if no data in the subevent
350         if (fSubEvent->eventSize == fSubEvent->eventHeadSize) {
351           fPosition = fEnd = ((UChar_t*)fSubEvent) + fSubEvent->eventSize;
352           fCount = 0;
353           continue;
354         }
355
356         fEquipment = (equipmentHeaderStruct*)
357           (((UChar_t*)fSubEvent) + fSubEvent->eventHeadSize);
358
359       } else {
360         fEquipment = (equipmentHeaderStruct*) fEnd;
361       }
362
363       fCount = 0;
364       fPosition = ((UChar_t*)fEquipment) + sizeof(equipmentHeaderStruct);
365       if (fSubEvent->eventVersion <= 0x00030002) {
366         fEnd = fPosition + fEquipment->equipmentSize;
367       } else {
368         fEnd = ((UChar_t*)fEquipment) + fEquipment->equipmentSize;
369       }
370     }
371
372     // continue with the next sub event if no data left in the payload
373     if (fPosition >= fEnd) continue;
374
375     if (fRequireHeader) {
376       // check that there are enough bytes left for the data header
377       if (fPosition + sizeof(AliRawDataHeader) > fEnd) {
378         Error("ReadHeader", "could not read data header data!");
379         Warning("ReadHeader", "skipping %d bytes\n"
380                 " run: %d  event: %d %d  LDC: %d  GDC: %d\n", 
381                 fEnd - fPosition, fSubEvent->eventRunNb, 
382                 fSubEvent->eventId[0], fSubEvent->eventId[1],
383                 fSubEvent->eventLdcId, fSubEvent->eventGdcId);
384         fCount = 0;
385         fPosition = fEnd;
386         fErrorCode = kErrNoDataHeader;
387         continue;
388       }
389
390       // "read" the data header
391       fHeader = (AliRawDataHeader*) fPosition;
392       fPosition += sizeof(AliRawDataHeader);
393     }
394
395     if (fHeader && (fHeader->fSize != 0xFFFFFFFF)) {
396       fCount = fHeader->fSize - sizeof(AliRawDataHeader);
397
398       // check consistency of data size in the header and in the sub event
399       if (fPosition + fCount > fEnd) {
400         Error("ReadHeader", "size in data header exceeds event size!");
401         Warning("ReadHeader", "skipping %d bytes\n"
402                 " run: %d  event: %d %d  LDC: %d  GDC: %d\n", 
403                 fEnd - fPosition, fSubEvent->eventRunNb, 
404                 fSubEvent->eventId[0], fSubEvent->eventId[1],
405                 fSubEvent->eventLdcId, fSubEvent->eventGdcId);
406         fCount = 0;
407         fPosition = fEnd;
408         fErrorCode = kErrSize;
409         continue;
410       }
411
412     } else {
413       fCount = fEnd - fPosition;
414     }
415
416   } while (!fEquipment || !IsSelected());
417
418   return kTRUE;
419 #else
420   return kFALSE;
421 #endif
422 }
423
424 Bool_t AliRawReaderDate::ReadNextData(UChar_t*& data)
425 {
426 // reads the next payload at the current position
427 // returns kFALSE if the data could not be read
428
429   fErrorCode = 0;
430   while (fCount == 0) {
431     if (!ReadHeader()) return kFALSE;
432   }
433   data = fPosition;
434   fPosition += fCount;  
435   fCount = 0;
436   return kTRUE;
437 }
438
439 Bool_t AliRawReaderDate::ReadNext(UChar_t* data, Int_t size)
440 {
441 // reads the next block of data at the current position
442 // returns kFALSE if the data could not be read
443
444   fErrorCode = 0;
445   if (fPosition + size > fEnd) {
446     Error("ReadNext", "could not read data!");
447     fErrorCode = kErrOutOfBounds;
448     return kFALSE;
449   }
450   memcpy(data, fPosition, size);
451   fPosition += size;
452   fCount -= size;
453   return kTRUE;
454 }
455
456
457 Bool_t AliRawReaderDate::Reset()
458 {
459 // reset the current position to the beginning of the event
460
461 #ifdef ALI_DATE
462   fSubEvent = NULL;
463 #endif
464   fCount = 0;
465   fPosition = fEnd = NULL;
466   return kTRUE;
467 }
468
469
470 Bool_t AliRawReaderDate::NextEvent()
471 {
472 // go to the next event in the date file
473
474 #ifdef ALI_DATE
475   if (!fFile) return kFALSE;
476
477   eventHeaderStruct header;
478   UInt_t headerSize = sizeof(eventHeaderStruct);
479   if (fEvent) delete[] fEvent;
480   fEvent = &header;
481
482   while (fread(&header, 1, headerSize, fFile) == headerSize) {
483     if (!IsEventSelected()) {
484       fseek(fFile, header.eventSize-headerSize, SEEK_CUR);
485       continue;
486     }
487     UChar_t* buffer = new UChar_t[header.eventSize];
488     fseek(fFile, -headerSize, SEEK_CUR);
489     if (fread(buffer, 1, header.eventSize, fFile) != header.eventSize) {
490       Error("NextEvent", "could not read event from file");
491       delete[] buffer;
492       break;
493     }
494     fEvent = (eventHeaderStruct*) buffer;
495     return kTRUE;
496   };
497
498   fEvent = NULL;
499 #endif
500
501   return kFALSE;
502 }
503
504 Bool_t AliRawReaderDate::RewindEvents()
505 {
506 // go back to the beginning of the date file
507
508   if (!fFile) return kFALSE;
509
510   fseek(fFile, 0, SEEK_SET);
511   return Reset();
512 }
513
514
515 Int_t AliRawReaderDate::CheckData() const
516 {
517 // check the consistency of the data
518
519 #ifdef ALI_DATE
520   if (!fEvent) return 0;
521   // check whether there are sub events
522   if (fEvent->eventSize <= fEvent->eventHeadSize) return 0;
523
524   eventHeaderStruct* subEvent = NULL;
525   UChar_t* position = 0;
526   UChar_t* end = 0;
527   Int_t result = 0;
528
529   while (kTRUE) {
530     // get the first or the next sub event if at the end of a sub event
531     if (!subEvent || (position >= end)) {
532
533       // check for end of event data
534       if (position >= ((UChar_t*)fEvent)+fEvent->eventSize) return result;
535       if (!TEST_SYSTEM_ATTRIBUTE(fEvent->eventTypeAttribute, 
536                                  ATTR_SUPER_EVENT)) {
537         subEvent = fEvent;   // no super event
538       } else if (subEvent) {
539         subEvent = (eventHeaderStruct*) (((UChar_t*)subEvent) + 
540                                          subEvent->eventSize);
541       } else {
542         subEvent = (eventHeaderStruct*) (((UChar_t*)fEvent) + 
543                                          fEvent->eventHeadSize);
544       }
545
546       // check the magic word of the sub event
547       if (subEvent->eventMagic != EVENT_MAGIC_NUMBER) {
548         result |= kErrMagic;
549         return result;
550       }
551
552       position = ((UChar_t*)subEvent) + subEvent->eventHeadSize + 
553         sizeof(equipmentHeaderStruct);
554       end = ((UChar_t*)subEvent) + subEvent->eventSize;
555     }
556
557     // continue with the next sub event if no data left in the payload
558     if (position >= end) continue;
559
560     // check that there are enough bytes left for the data header
561     if (position + sizeof(AliRawDataHeader) > end) {
562       result |= kErrNoDataHeader;
563       position = end;
564       continue;
565     }
566
567     // check consistency of data size in the data header and in the sub event
568     AliRawDataHeader* header = (AliRawDataHeader*) position;
569     if (header->fSize != 0xFFFFFFFF) {
570       if (position + header->fSize > end) {
571         result |= kErrSize;
572         position = end;
573       } else {
574         position += header->fSize;
575       }
576     } else {
577       position = end;
578     }
579   };
580
581 #endif
582   return 0;
583 }