New versions of GDC and CDH raw data headers. Some CDH getters are added
[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, -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
203 Int_t AliRawReaderDateV3::GetEquipmentSize() const
204 {
205 // get the size of the equipment
206
207   if (!fSubEvent) return 0;
208   return fSubEvent->size;
209 }
210
211 Int_t AliRawReaderDateV3::GetEquipmentType() const
212 {
213 // get the type from the equipment header
214
215   return 0;
216 }
217
218 Int_t AliRawReaderDateV3::GetEquipmentId() const
219 {
220 // get the ID from the equipment header
221
222   return 0;
223 }
224
225 const UInt_t* AliRawReaderDateV3::GetEquipmentAttributes() const
226 {
227 // get the attributes from the equipment header
228
229   return 0;
230 }
231
232 Int_t AliRawReaderDateV3::GetEquipmentElementSize() const
233 {
234 // get the basic element size from the equipment header
235
236   return 0;
237 }
238
239 Int_t AliRawReaderDateV3::GetEquipmentHeaderSize() const
240 {
241 // get the size of the equipment header
242
243   return 0;
244 }
245
246 Bool_t AliRawReaderDateV3::ReadHeader()
247 {
248 // read a data header at the current position
249 // returns kFALSE if the data header could not be read
250
251   fErrorCode = 0;
252
253   fHeader = NULL;
254   if (!fEvent) return kFALSE;
255   // check whether there are sub events
256   if (fEvent->size <= Int_t(fEvent->headLen)) return kFALSE;
257
258   do {
259     // skip payload (if event was not selected)
260     if (fCount > 0) fPosition += fCount;
261
262     // check for end of event data
263     if (fPosition >= ((UChar_t*)fEvent)+fEvent->size) return kFALSE;
264     if ((fEvent->detectorId[2] & 0x8000) != 0x8000) {
265       fSubEvent = fEvent;   // no super event
266     } else if (fSubEvent) {
267       fSubEvent = (eventHeaderStruct*) (((UChar_t*)fSubEvent) + 
268                                         fSubEvent->size);
269     } else {
270       fSubEvent = (eventHeaderStruct*) (((UChar_t*)fEvent) + 
271                                         fEvent->headLen);
272     }
273
274     // check the magic word of the sub event
275     if (fSubEvent->magic != EVENT_MAGIC_NUMBER) {
276       Error("ReadHeader", "wrong magic number in sub event!\n"
277             " run: %d  event: %d\n", 
278             fSubEvent->runNb, fSubEvent->nbInRun);
279       fErrorCode = kErrMagic;
280       return kFALSE;
281     }
282
283     // continue if no data in the subevent
284     if (fSubEvent->size == Int_t(fSubEvent->headLen)) {
285       fPosition = fEnd = ((UChar_t*)fSubEvent) + fSubEvent->size;
286       fCount = 0;
287       continue;
288     }
289
290     fCount = 0;
291     fPosition = ((UChar_t*)fSubEvent) + sizeof(eventHeaderStruct);
292     fEnd = ((UChar_t*)fSubEvent) + fSubEvent->size;
293
294     // continue with the next sub event if no data left in the payload
295     if (fPosition >= fEnd) continue;
296
297     if (fRequireHeader) {
298       // check that there are enough bytes left for the data header
299       if (fPosition + sizeof(AliRawDataHeader) > fEnd) {
300         Error("ReadHeader", "could not read data header data!");
301         Warning("ReadHeader", "skipping %d bytes\n"
302                 " run: %d  event: %d\n", 
303                 fEnd - fPosition, fSubEvent->runNb, fSubEvent->nbInRun);
304         fCount = 0;
305         fPosition = fEnd;
306         fErrorCode = kErrNoDataHeader;
307         continue;
308       }
309
310       // "read" the data header
311       fHeader = (AliRawDataHeader*) fPosition;
312       if ((fPosition + fHeader->fSize) != fEnd) {
313         Warning("ReadHeader",
314                 "raw data size found in the header is wrong (%d != %d)! Using the equipment size instead !",
315                 fHeader->fSize, fEnd - fPosition);
316         fHeader->fSize = fEnd - fPosition;
317       }
318       fPosition += sizeof(AliRawDataHeader);
319     }
320
321     if (fHeader && (fHeader->fSize != 0xFFFFFFFF)) {
322       fCount = fHeader->fSize - sizeof(AliRawDataHeader);
323
324       // check consistency of data size in the header and in the sub event
325       if (fPosition + fCount > fEnd) {
326         Error("ReadHeader", "size in data header exceeds event size!");
327         Warning("ReadHeader", "skipping %d bytes\n"
328                 " run: %d  event: %d\n", 
329                 fEnd - fPosition, fSubEvent->runNb, fSubEvent->nbInRun);
330         fCount = 0;
331         fPosition = fEnd;
332         fErrorCode = kErrSize;
333         continue;
334       }
335
336     } else {
337       fCount = fEnd - fPosition;
338     }
339
340   } while (!IsSelected());
341
342   return kTRUE;
343 }
344
345 Bool_t AliRawReaderDateV3::ReadNextData(UChar_t*& data)
346 {
347 // reads the next payload at the current position
348 // returns kFALSE if the data could not be read
349
350   fErrorCode = 0;
351   while (fCount == 0) {
352     if (!ReadHeader()) return kFALSE;
353   }
354   data = fPosition;
355   fPosition += fCount;  
356   fCount = 0;
357   return kTRUE;
358 }
359
360 Bool_t AliRawReaderDateV3::ReadNext(UChar_t* data, Int_t size)
361 {
362 // reads the next block of data at the current position
363 // returns kFALSE if the data could not be read
364
365   fErrorCode = 0;
366   if (fPosition + size > fEnd) {
367     Error("ReadNext", "could not read data!");
368     fErrorCode = kErrOutOfBounds;
369     return kFALSE;
370   }
371   memcpy(data, fPosition, size);
372   fPosition += size;
373   fCount -= size;
374   return kTRUE;
375 }
376
377
378 Bool_t AliRawReaderDateV3::Reset()
379 {
380 // reset the current position to the beginning of the event
381
382   fSubEvent = NULL;
383   fCount = 0;
384   fPosition = fEnd = NULL;
385   return kTRUE;
386 }
387
388
389 Bool_t AliRawReaderDateV3::NextEvent()
390 {
391 // go to the next event in the date file
392
393   if (!fFile) return kFALSE;
394
395   Reset();
396   eventHeaderStruct header;
397   UInt_t headerSize = sizeof(eventHeaderStruct);
398   if (fEvent) delete[] fEvent;
399   fEvent = &header;
400
401   while (fread(&header, 1, headerSize, fFile) == headerSize) {
402     if (!IsEventSelected()) {
403       fseek(fFile, header.size-headerSize, SEEK_CUR);
404       continue;
405     }
406     UChar_t* buffer = new UChar_t[header.size];
407     fseek(fFile, -headerSize, SEEK_CUR);
408     if (Int_t(fread(buffer, 1, header.size, fFile)) != header.size) {
409       Error("NextEvent", "could not read event from file");
410       delete[] buffer;
411       break;
412     }
413     fEvent = (eventHeaderStruct*) buffer;
414     return kTRUE;
415   };
416
417   fEvent = NULL;
418   return kFALSE;
419 }
420
421 Bool_t AliRawReaderDateV3::RewindEvents()
422 {
423 // go back to the beginning of the date file
424
425   if (!fFile) return kFALSE;
426
427   fseek(fFile, 0, SEEK_SET);
428   return Reset();
429 }
430
431
432 Int_t AliRawReaderDateV3::CheckData() const
433 {
434 // check the consistency of the data
435
436   if (!fEvent) return 0;
437   // check whether there are sub events
438   if (fEvent->size <= Int_t(fEvent->headLen)) return 0;
439
440   eventHeaderStruct* subEvent = NULL;
441   UChar_t* position = 0;
442   UChar_t* end = 0;
443   Int_t result = 0;
444
445   while (kTRUE) {
446     // check for end of event data
447     if (position >= ((UChar_t*)fEvent)+fEvent->size) return result;
448     if ((fEvent->detectorId[2] & 0x8000) != 0x8000) {
449       subEvent = fEvent;   // no super event
450     } else if (subEvent) {
451       subEvent = (eventHeaderStruct*) (((UChar_t*)subEvent) + 
452                                        subEvent->size);
453     } else {
454       subEvent = (eventHeaderStruct*) (((UChar_t*)fEvent) + 
455                                        fEvent->headLen);
456     }
457
458     // check the magic word of the sub event
459     if (subEvent->magic != EVENT_MAGIC_NUMBER) {
460       result |= kErrMagic;
461       return result;
462     }
463
464     position = ((UChar_t*)subEvent) + subEvent->headLen;
465     end = ((UChar_t*)subEvent) + subEvent->size;
466
467     // continue with the next sub event if no data left in the payload
468     if (position >= end) continue;
469
470     if (fRequireHeader) {
471       // check that there are enough bytes left for the data header
472       if (position + sizeof(AliRawDataHeader) > end) {
473         result |= kErrNoDataHeader;
474         position = end;
475         continue;
476       }
477
478       // check consistency of data size in the data header and in the sub event
479       AliRawDataHeader* header = (AliRawDataHeader*) position;
480       if ((position + header->fSize) != end) {
481         Warning("ReadHeader",
482                 "raw data size found in the header is wrong (%d != %d)! Using the equipment size instead !",
483                 header->fSize, end - position);
484         header->fSize = end - position;
485         result |= kErrSize;
486       }
487     }
488     position = end;
489   };
490
491   return 0;
492 }