check of data consistency
[u/mrichter/AliRoot.git] / RAW / AliRawReaderRoot.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 ///////////////////////////////////////////////////////////////////////////////
17 //
18 // This is a class for reading a raw data from a root file and providing
19 // information about digits
20 //
21 ///////////////////////////////////////////////////////////////////////////////
22
23 #include "AliRawReaderRoot.h"
24 #include "AliRawEvent.h"
25
26
27 ClassImp(AliRawReaderRoot)
28
29
30 AliRawReaderRoot::AliRawReaderRoot(const char* fileName, Int_t eventNumber)
31 {
32 // create an object to read digits from the given input file for the
33 // event with the given number
34
35   TDirectory* dir = gDirectory;
36   fFile = TFile::Open(fileName);
37   dir->cd();
38   if (!fFile || !fFile->IsOpen()) {
39     Error("AliRawReaderRoot", "could not open file %s", fileName);
40     return;
41   }
42   TTree* tree = (TTree*) fFile->Get("RAW");
43   if (!tree) {
44     Error("AliRawReaderRoot", "no raw data tree found");
45     return;
46   }
47   TBranch* branch = tree->GetBranch("rawevent");
48   if (!branch) {
49     Error("AliRawReaderRoot", "no raw data branch found");
50     return;
51   }
52
53   fEvent = new AliRawEvent;
54   branch->SetAddress(&fEvent);
55   if (branch->GetEntry(eventNumber) <= 0) {
56     Error("AliRawReaderRoot", "no event with number %d found", eventNumber);
57     return;
58   }
59   
60   fSubEventIndex = 0;
61   fSubEvent = NULL;
62   fRawData = NULL;
63   fMiniHeader = NULL;
64
65   fCount = 0;
66   fPosition = fEnd = NULL;
67 }
68
69 AliRawReaderRoot::AliRawReaderRoot(AliRawEvent* event)
70 {
71 // create an object to read digits from the given raw event
72
73   fFile = NULL;
74   fEvent = event;
75   
76   fSubEventIndex = 0;
77   fSubEvent = NULL;
78   fRawData = NULL;
79   fMiniHeader = NULL;
80
81   fCount = 0;
82   fPosition = fEnd = NULL;
83 }
84
85 AliRawReaderRoot::AliRawReaderRoot(const AliRawReaderRoot& rawReader) :
86   AliRawReader(rawReader)
87 {
88 // copy constructor
89
90   fFile = NULL;
91   fEvent = rawReader.fEvent;
92   
93   fSubEventIndex = rawReader.fSubEventIndex;
94   fSubEvent = rawReader.fSubEvent;
95   fRawData = rawReader.fRawData;
96   fMiniHeader = rawReader.fMiniHeader;
97
98   fCount = rawReader.fCount;
99   fPosition = rawReader.fPosition;
100   fEnd = rawReader.fEnd;
101 }
102
103 AliRawReaderRoot& AliRawReaderRoot::operator = (const AliRawReaderRoot& 
104                                                 rawReader)
105 {
106 // assignment operator
107
108   this->~AliRawReaderRoot();
109   new(this) AliRawReaderRoot(rawReader);
110   return *this;
111 }
112
113 AliRawReaderRoot::~AliRawReaderRoot()
114 {
115 // delete objects and close root file
116
117   if (fFile) {
118     if (fEvent) delete fEvent;
119     fFile->Close();
120     delete fFile;
121   }
122 }
123
124
125 UInt_t AliRawReaderRoot::GetType() const
126 {
127 // get the type from the event header
128
129   if (!fEvent) return 0;
130   return fEvent->GetHeader()->GetType();
131 }
132
133 UInt_t AliRawReaderRoot::GetRunNumber() const
134 {
135 // get the run number from the event header
136
137   if (!fEvent) return 0;
138   return fEvent->GetHeader()->GetRunNumber();
139 }
140
141 const UInt_t* AliRawReaderRoot::GetEventId() const
142 {
143 // get the event id from the event header
144
145   if (!fEvent) return NULL;
146   return fEvent->GetHeader()->GetId();
147 }
148
149 const UInt_t* AliRawReaderRoot::GetTriggerPattern() const
150 {
151 // get the trigger pattern from the event header
152
153   if (!fEvent) return NULL;
154   return fEvent->GetHeader()->GetTriggerPattern();
155 }
156
157 const UInt_t* AliRawReaderRoot::GetDetectorPattern() const
158 {
159 // get the detector pattern from the event header
160
161   if (!fEvent) return NULL;
162   return fEvent->GetHeader()->GetDetectorPattern();
163 }
164
165 const UInt_t* AliRawReaderRoot::GetAttributes() const
166 {
167 // get the type attributes from the event header
168
169   if (!fEvent) return NULL;
170   return fEvent->GetHeader()->GetTypeAttribute();
171 }
172
173 UInt_t AliRawReaderRoot::GetGDCId() const
174 {
175 // get the GDC Id from the event header
176
177   if (!fEvent) return 0;
178   return fEvent->GetHeader()->GetGDCId();
179 }
180
181
182 Bool_t AliRawReaderRoot::ReadMiniHeader()
183 {
184 // read a mini header at the current position
185 // returns kFALSE if the mini header could not be read
186
187   fErrorCode = 0;
188   if (!fEvent) return kFALSE;
189
190   do {
191     // skip payload (if event was not selected)
192     if (fCount > 0) fPosition += fCount;
193
194     // get the first or the next sub event if at the end of a sub event
195     if (!fSubEvent || (fPosition >= fEnd)) {
196
197       // check for end of event data
198       if (fSubEventIndex >= fEvent->GetNSubEvents()) return kFALSE;
199       fSubEvent = fEvent->GetSubEvent(fSubEventIndex++);
200
201       // check the magic word of the sub event
202       if (!fSubEvent->GetHeader()->IsValid()) {
203         Error("ReadMiniHeader", "wrong magic number in sub event!");
204         fSubEvent->GetHeader()->Dump();
205         fErrorCode = kErrMagic;
206         return kFALSE;
207       }
208
209       fRawData = fSubEvent->GetRawData();
210       fCount = 0;
211       fPosition = (UChar_t*) fRawData->GetBuffer();
212       fEnd = ((UChar_t*) fRawData->GetBuffer()) + fRawData->GetSize();
213     }
214
215     // continue with the next sub event if no data left in the payload
216     if (fPosition >= fEnd) continue;
217
218     // check that there are enough bytes left for the mini header
219     if (fPosition + sizeof(AliMiniHeader) > fEnd) {
220       Error("ReadMiniHeader", "could not read mini header data!");
221       Warning("ReadMiniHeader", "skipping %d bytes", fEnd - fPosition);
222       fSubEvent->GetHeader()->Dump();
223       fCount = 0;
224       fPosition = fEnd;
225       fErrorCode = kErrNoMiniHeader;
226       continue;
227     }
228
229     // "read" and check the mini header
230     fMiniHeader = (AliMiniHeader*) fPosition;
231     fPosition += sizeof(AliMiniHeader);
232     if (!CheckMiniHeader()) {
233       Error("ReadMiniHeader", "wrong magic word in mini header!");
234       Warning("ReadMiniHeader", "skipping %d bytes", fEnd - fPosition);
235       fSubEvent->GetHeader()->Dump();
236       fCount = 0;
237       fPosition = fEnd;
238       fErrorCode = kErrMiniMagic;
239       continue;
240     }
241     fCount = fMiniHeader->fSize;
242
243     // check consistency of data size in the mini header and in the sub event
244     if (fPosition + fCount > fEnd) {  
245       Error("ReadMiniHeader", "size in mini header exceeds event size!");
246       Warning("ReadMiniHeader", "skipping %d bytes", fEnd - fPosition);
247       fSubEvent->GetHeader()->Dump();
248       fCount = 0;
249       fPosition = fEnd;
250       fErrorCode = kErrSize;
251       continue;
252     }
253
254   } while (!IsSelected());
255
256   return kTRUE;
257 }
258
259 Bool_t AliRawReaderRoot::ReadNextData(UChar_t*& data)
260 {
261 // reads the next payload at the current position
262 // returns kFALSE if the data could not be read
263
264   fErrorCode = 0;
265   while (fCount == 0) {
266     if (!ReadMiniHeader()) return kFALSE;
267   }
268   data = fPosition;
269   fPosition += fCount;  
270   fCount = 0;
271   return kTRUE;
272 }
273
274 Bool_t AliRawReaderRoot::ReadNext(UChar_t* data, Int_t size)
275 {
276 // reads the next block of data at the current position
277 // returns kFALSE if the data could not be read
278
279   fErrorCode = 0;
280   if (fPosition + size > fEnd) {
281     Error("ReadNext", "could not read data!");
282     fErrorCode = kErrOutOfBounds;
283     return kFALSE;
284   }
285   memcpy(data, fPosition, size);
286   fPosition += size;
287   fCount -= size;
288   return kTRUE;
289 }
290
291
292 Bool_t AliRawReaderRoot::Reset()
293 {
294 // reset the current position to the beginning of the event
295
296   fSubEventIndex = 0;
297   fSubEvent = NULL;
298   fRawData = NULL;
299   fMiniHeader = NULL;
300
301   fCount = 0;
302   fPosition = fEnd = NULL;
303   return kTRUE;
304 }
305
306
307 Int_t AliRawReaderRoot::CheckData() const
308 {
309 // check the consistency of the data
310
311   if (!fEvent) return 0;
312
313   AliRawEvent* subEvent = NULL;
314   Int_t subEventIndex = 0;
315   UChar_t* position = 0;
316   UChar_t* end = 0;
317
318   while (kTRUE) {
319     // get the first or the next sub event if at the end of a sub event
320     if (!subEvent || (position >= end)) {
321
322       // check for end of event data
323       if (subEventIndex >= fEvent->GetNSubEvents()) return 0;
324       subEvent = fEvent->GetSubEvent(subEventIndex++);
325
326       // check the magic word of the sub event
327       if (!fSubEvent->GetHeader()->IsValid()) return kErrMagic;
328
329       AliRawData* rawData = subEvent->GetRawData();
330       position = (UChar_t*) rawData->GetBuffer();
331       end = ((UChar_t*) rawData->GetBuffer()) + rawData->GetSize();
332     }
333
334     // continue with the next sub event if no data left in the payload
335     if (position >= end) continue;
336
337     // check that there are enough bytes left for the mini header
338     if (position + sizeof(AliMiniHeader) > end) return kErrNoMiniHeader;
339
340     // "read" and check the mini header
341     AliMiniHeader* miniHeader = (AliMiniHeader*) position;
342     position += sizeof(AliMiniHeader);
343     if (!CheckMiniHeader(miniHeader)) return kErrMiniMagic;
344
345     // check consistency of data size in the mini header and in the sub event
346     if (position + miniHeader->fSize > end) return kErrSize;
347     position += miniHeader->fSize;
348   };
349 }