1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
18 ///////////////////////////////////////////////////////////////////////////////
20 /// This is a class for reading raw data from a date file or event.
22 /// The AliRawReaderDate is constructed either with a pointer to a
23 /// date event or with a file name and an event number.
25 ///////////////////////////////////////////////////////////////////////////////
27 #include "AliRawReaderDate.h"
30 ClassImp(AliRawReaderDate)
33 AliRawReaderDate::AliRawReaderDate(void* event, Bool_t owner) :
42 // create an object to read digits from the given date event
44 fEvent = (eventHeaderStruct*) event;
47 AliRawReaderDate::AliRawReaderDate(const char* fileName, Int_t eventNumber) :
56 // create an object to read digits from the given date event
58 fFile = fopen(fileName, "rb");
60 Error("AliRawReaderDate", "could not open file %s", fileName);
64 if (eventNumber < 0) return;
66 eventHeaderStruct header;
67 UInt_t headerSize = sizeof(eventHeaderStruct);
68 while (fread(&header, 1, headerSize, fFile) == headerSize) {
69 if (eventNumber == 0) {
70 UChar_t* buffer = new UChar_t[header.eventSize];
71 fseek(fFile, -(long)headerSize, SEEK_CUR);
72 if (fread(buffer, 1, header.eventSize, fFile) != header.eventSize) break;
73 fEvent = (eventHeaderStruct*) buffer;
76 fseek(fFile, header.eventSize-headerSize, SEEK_CUR);
82 AliRawReaderDate::~AliRawReaderDate()
86 if (fEvent && fOwner) delete[] fEvent;
93 UInt_t AliRawReaderDate::GetType() const
95 // get the type from the event header
97 if (!fEvent) return 0;
98 return fEvent->eventType;
101 UInt_t AliRawReaderDate::GetRunNumber() const
103 // get the run number from the event header
105 if (!fEvent) return 0;
106 return fEvent->eventRunNb;
109 const UInt_t* AliRawReaderDate::GetEventId() const
111 // get the event id from the event header
113 if (!fEvent) return NULL;
114 return fEvent->eventId;
117 const UInt_t* AliRawReaderDate::GetTriggerPattern() const
119 // get the trigger pattern from the event header
121 if (!fEvent) return NULL;
122 return fEvent->eventTriggerPattern;
125 const UInt_t* AliRawReaderDate::GetDetectorPattern() const
127 // get the detector pattern from the event header
129 if (!fEvent) return NULL;
130 return fEvent->eventDetectorPattern;
133 const UInt_t* AliRawReaderDate::GetAttributes() const
135 // get the type attributes from the event header
137 if (!fEvent) return NULL;
138 return fEvent->eventTypeAttribute;
141 const UInt_t* AliRawReaderDate::GetSubEventAttributes() const
143 // get the type attributes from the sub event header
145 if (!fSubEvent) return NULL;
146 return fSubEvent->eventTypeAttribute;
149 UInt_t AliRawReaderDate::GetLDCId() const
151 // get the LDC Id from the event header
153 if (!fSubEvent) return 0;
154 return fSubEvent->eventLdcId;
157 UInt_t AliRawReaderDate::GetGDCId() const
159 // get the GDC Id from the event header
161 if (!fEvent) return 0;
162 return fEvent->eventGdcId;
165 UInt_t AliRawReaderDate::GetTimestamp() const
167 // get the timestamp from the event header
169 if (!fEvent) return 0;
170 return fEvent->eventTimestamp;
173 Int_t AliRawReaderDate::GetEquipmentSize() const
175 // get the size of the equipment (including the header)
177 if (!fEquipment) return 0;
178 if (fSubEvent->eventVersion <= 0x00030001) {
179 return fEquipment->equipmentSize + sizeof(equipmentHeaderStruct);
181 return fEquipment->equipmentSize;
185 Int_t AliRawReaderDate::GetEquipmentType() const
187 // get the type from the equipment header
189 if (!fEquipment) return -1;
190 return fEquipment->equipmentType;
193 Int_t AliRawReaderDate::GetEquipmentId() const
195 // get the ID from the equipment header
197 if (!fEquipment) return -1;
198 return fEquipment->equipmentId;
201 const UInt_t* AliRawReaderDate::GetEquipmentAttributes() const
203 // get the attributes from the equipment header
205 if (!fEquipment) return NULL;
206 return fEquipment->equipmentTypeAttribute;
209 Int_t AliRawReaderDate::GetEquipmentElementSize() const
211 // get the basic element size from the equipment header
213 if (!fEquipment) return 0;
214 return fEquipment->equipmentBasicElementSize;
217 Int_t AliRawReaderDate::GetEquipmentHeaderSize() const
219 // Get the equipment header size
220 // 28 bytes by default
221 return sizeof(equipmentHeaderStruct);
224 Bool_t AliRawReaderDate::ReadHeader()
226 // read a data header at the current position
227 // returns kFALSE if the data header could not be read
232 if (!fEvent) return kFALSE;
233 // check whether there are sub events
234 if (fEvent->eventSize <= fEvent->eventHeadSize) return kFALSE;
237 // skip payload (if event was not selected)
238 if (fCount > 0) fPosition += fCount;
240 // get the first or the next equipment if at the end of an equipment
241 if (!fEquipment || (fPosition >= fEnd)) {
244 // get the first or the next sub event if at the end of a sub event
246 (fPosition >= ((UChar_t*)fSubEvent) + fSubEvent->eventSize)) {
248 // check for end of event data
249 if (fPosition >= ((UChar_t*)fEvent)+fEvent->eventSize) return kFALSE;
250 if (!TEST_SYSTEM_ATTRIBUTE(fEvent->eventTypeAttribute,
252 fSubEvent = fEvent; // no super event
253 } else if (fSubEvent) {
254 fSubEvent = (eventHeaderStruct*) (((UChar_t*)fSubEvent) +
255 fSubEvent->eventSize);
257 fSubEvent = (eventHeaderStruct*) (((UChar_t*)fEvent) +
258 fEvent->eventHeadSize);
261 // check the magic word of the sub event
262 if (fSubEvent->eventMagic != EVENT_MAGIC_NUMBER) {
263 Error("ReadHeader", "wrong magic number in sub event!\n"
264 " run: %d event: %d %d LDC: %d GDC: %d\n",
265 fSubEvent->eventRunNb,
266 fSubEvent->eventId[0], fSubEvent->eventId[1],
267 fSubEvent->eventLdcId, fSubEvent->eventGdcId);
268 fErrorCode = kErrMagic;
272 // continue if no data in the subevent
273 if (fSubEvent->eventSize == fSubEvent->eventHeadSize) {
274 fPosition = fEnd = ((UChar_t*)fSubEvent) + fSubEvent->eventSize;
279 fEquipment = (equipmentHeaderStruct*)
280 (((UChar_t*)fSubEvent) + fSubEvent->eventHeadSize);
283 fEquipment = (equipmentHeaderStruct*) fEnd;
287 fPosition = ((UChar_t*)fEquipment) + sizeof(equipmentHeaderStruct);
288 if (fSubEvent->eventVersion <= 0x00030001) {
289 fEnd = fPosition + fEquipment->equipmentSize;
291 fEnd = ((UChar_t*)fEquipment) + fEquipment->equipmentSize;
295 // continue with the next sub event if no data left in the payload
296 if (fPosition >= fEnd) continue;
298 if (fRequireHeader) {
299 // check that there are enough bytes left for the data header
300 if (fPosition + sizeof(AliRawDataHeader) > fEnd) {
301 Error("ReadHeader", "could not read data header data!");
302 Warning("ReadHeader", "skipping %ld bytes\n"
303 " run: %d event: %d %d LDC: %d GDC: %d\n",
304 fEnd - fPosition, fSubEvent->eventRunNb,
305 fSubEvent->eventId[0], fSubEvent->eventId[1],
306 fSubEvent->eventLdcId, fSubEvent->eventGdcId);
309 fErrorCode = kErrNoDataHeader;
313 // "read" the data header
314 fHeader = (AliRawDataHeader*) fPosition;
315 // Now check the version of the header
317 if (fHeader) version=fHeader->GetVersion();
320 if ((fPosition + fHeader->fSize) != fEnd) {
321 if ((fHeader->fSize != 0xFFFFFFFF) &&
322 (fEquipment->equipmentId != 4352))
323 Warning("ReadHeader",
324 "raw data size found in the header is wrong (%d != %ld)! Using the equipment size instead !",
325 fHeader->fSize, fEnd - fPosition);
326 fHeader->fSize = fEnd - fPosition;
328 fPosition += sizeof(AliRawDataHeader);
330 } else if (version==3) {
331 fHeaderV3 = (AliRawDataHeaderV3*) fPosition;
332 if ((fPosition + fHeaderV3->fSize) != fEnd) {
333 if ((fHeaderV3->fSize != 0xFFFFFFFF) &&
334 (fEquipment->equipmentId != 4352))
335 Warning("ReadHeader",
336 "raw data size found in the header is wrong (%d != %ld)! Using the equipment size instead !",
337 fHeaderV3->fSize, fEnd - fPosition);
338 fHeaderV3->fSize = fEnd - fPosition;
340 fPosition += sizeof(AliRawDataHeaderV3);
345 if (fHeader && (fHeader->fSize != 0xFFFFFFFF)) {
346 fCount = fHeader->fSize - sizeof(AliRawDataHeader);
348 // check consistency of data size in the header and in the sub event
349 if (fPosition + fCount > fEnd) {
350 Error("ReadHeader", "size in data header exceeds event size!");
351 Warning("ReadHeader", "skipping %ld bytes\n"
352 " run: %d event: %d %d LDC: %d GDC: %d\n",
353 fEnd - fPosition, fSubEvent->eventRunNb,
354 fSubEvent->eventId[0], fSubEvent->eventId[1],
355 fSubEvent->eventLdcId, fSubEvent->eventGdcId);
358 fErrorCode = kErrSize;
362 } else if (fHeaderV3 && (fHeaderV3->fSize != 0xFFFFFFFF)) {
363 fCount = fHeaderV3->fSize - sizeof(AliRawDataHeaderV3);
365 // check consistency of data size in the header and in the sub event
366 if (fPosition + fCount > fEnd) {
367 Error("ReadHeader", "size in data header exceeds event size!");
368 Warning("ReadHeader", "skipping %ld bytes\n"
369 " run: %d event: %d %d LDC: %d GDC: %d\n",
370 fEnd - fPosition, fSubEvent->eventRunNb,
371 fSubEvent->eventId[0], fSubEvent->eventId[1],
372 fSubEvent->eventLdcId, fSubEvent->eventGdcId);
375 fErrorCode = kErrSize;
380 fCount = fEnd - fPosition;
383 } while (!fEquipment || !IsSelected());
388 Bool_t AliRawReaderDate::ReadNextData(UChar_t*& data)
390 // reads the next payload at the current position
391 // returns kFALSE if the data could not be read
394 while (fCount == 0) {
395 if (!ReadHeader()) return kFALSE;
403 Bool_t AliRawReaderDate::ReadNext(UChar_t* data, Int_t size)
405 // reads the next block of data at the current position
406 // returns kFALSE if the data could not be read
409 if (fPosition + size > fEnd) {
410 Error("ReadNext", "could not read data!");
411 fErrorCode = kErrOutOfBounds;
414 memcpy(data, fPosition, size);
421 Bool_t AliRawReaderDate::Reset()
423 // reset the current position to the beginning of the event
428 fPosition = fEnd = NULL;
435 Bool_t AliRawReaderDate::NextEvent()
437 // go to the next event in the date file
440 if (fEventNumber < 0 && fEvent) {
449 eventHeaderStruct header;
450 UInt_t headerSize = sizeof(eventHeaderStruct);
451 if (fEvent) delete[] fEvent;
454 while (fread(&header, 1, headerSize, fFile) == headerSize) {
455 if (!IsEventSelected()) {
456 fseek(fFile, header.eventSize-headerSize, SEEK_CUR);
459 UChar_t* buffer = new UChar_t[header.eventSize];
460 fseek(fFile, -(long)headerSize, SEEK_CUR);
461 if (fread(buffer, 1, header.eventSize, fFile) != header.eventSize) {
462 Error("NextEvent", "could not read event from file");
466 fEvent = (eventHeaderStruct*) buffer;
476 Bool_t AliRawReaderDate::RewindEvents()
478 // go back to the beginning of the date file
481 fseek(fFile, 0, SEEK_SET);
488 Int_t AliRawReaderDate::CheckData() const
490 // check the consistency of the data
492 if (!fEvent) return 0;
493 // check whether there are sub events
494 if (fEvent->eventSize <= fEvent->eventHeadSize) return 0;
496 eventHeaderStruct* subEvent = NULL;
497 UChar_t* position = 0;
502 // get the first or the next sub event if at the end of a sub event
503 if (!subEvent || (position >= end)) {
505 // check for end of event data
506 if (position >= ((UChar_t*)fEvent)+fEvent->eventSize) return result;
507 if (!TEST_SYSTEM_ATTRIBUTE(fEvent->eventTypeAttribute,
509 subEvent = fEvent; // no super event
510 } else if (subEvent) {
511 subEvent = (eventHeaderStruct*) (((UChar_t*)subEvent) +
512 subEvent->eventSize);
514 subEvent = (eventHeaderStruct*) (((UChar_t*)fEvent) +
515 fEvent->eventHeadSize);
518 // check the magic word of the sub event
519 if (subEvent->eventMagic != EVENT_MAGIC_NUMBER) {
524 position = ((UChar_t*)subEvent) + subEvent->eventHeadSize +
525 sizeof(equipmentHeaderStruct);
526 end = ((UChar_t*)subEvent) + subEvent->eventSize;
529 // continue with the next sub event if no data left in the payload
530 if (position >= end) continue;
532 if (fRequireHeader) {
533 // check that there are enough bytes left for the data header
534 if (position + sizeof(AliRawDataHeader) > end) {
535 result |= kErrNoDataHeader;
540 // Here we have to check if we have header v2 or v3
541 // check consistency of data size in the data header and in the sub event
542 AliRawDataHeader* header = (AliRawDataHeader*) position;
543 UChar_t version = header->GetVersion();
545 if ((position + header->fSize) != end) {
546 if (header->fSize != 0xFFFFFFFF)
548 "raw data size found in the header V2 is wrong (%d != %ld)! Using the equipment size instead !",
549 header->fSize, end - position);
550 header->fSize = end - position;
554 else if (version==3) {
555 AliRawDataHeaderV3 * headerV3 = (AliRawDataHeaderV3*) position;
556 if ((position + headerV3->fSize) != end) {
557 if (headerV3->fSize != 0xFFFFFFFF)
559 "raw data size found in the header V3 is wrong (%d != %ld)! Using the equipment size instead !",
560 headerV3->fSize, end - position);
561 headerV3->fSize = end - position;
573 AliRawReader* AliRawReaderDate::CloneSingleEvent() const
575 // Clones the current event and
576 // creates raw-reader for the cloned event
577 // Can be used in order to make asynchronious
578 // access to the current raw data within
579 // several threads (online event display/reco)
582 UInt_t evSize = fEvent->eventSize;
584 UChar_t *newEvent = new UChar_t[evSize];
585 memcpy(newEvent,fEvent,evSize);
586 return new AliRawReaderDate((void *)newEvent,kTRUE);