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