]> git.uio.no Git - u/mrichter/AliRoot.git/blob - RAW/AliRawReaderFile.cxx
Protection against infinite loop in case of raw-data payload w/o CDH. This fix is...
[u/mrichter/AliRoot.git] / RAW / AliRawReaderFile.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 files.
21 ///
22 /// The files of one event are expected to be in one directory. The name 
23 /// of the directory is "raw" + the event number. Each file contains
24 /// the raw data (with data header) of one DDL. The convention for the
25 /// file names is "DET_#DDL.ddl". "DET" is the name of the detector and
26 /// "#DDL" is the unique equipment ID.
27 ///
28 /// The constructor of AliRawReaderFile takes the event number or the
29 /// directory name as argument.
30 /// 
31 ///////////////////////////////////////////////////////////////////////////////
32
33 #include <cstdlib>
34 #include "AliRawReaderFile.h"
35 #include "AliDAQ.h"
36 #include <TSystem.h>
37 #include <TArrayC.h>
38
39
40 ClassImp(AliRawReaderFile)
41
42
43 AliRawReaderFile::AliRawReaderFile(Int_t eventNumber) :
44   fEventIndex(eventNumber),
45   fDirName("."),
46   fDirectory(NULL),
47   fStream(NULL),
48   fEquipmentId(-1),
49   fBuffer(NULL),
50   fBufferSize(0),
51   fEquipmentSize(0),
52   fDDLIndex(NULL),
53   fDDLCurrent(-1)
54 {
55 // create an object to read digits from the given event
56 // in the current directory
57
58   fDirectory = OpenDirectory();
59   OpenNextFile();
60   fHeader = new AliRawDataHeader;
61 }
62
63 AliRawReaderFile::AliRawReaderFile(const char* dirName, Int_t eventNumber) :
64   fEventIndex(eventNumber),
65   fDirName(dirName),
66   fDirectory(NULL),
67   fStream(NULL),
68   fEquipmentId(-1),
69   fBuffer(NULL),
70   fBufferSize(0),
71   fEquipmentSize(0),
72   fDDLIndex(NULL),
73   fDDLCurrent(-1)
74 {
75 // create an object to read digits from the given directory
76
77   fDirectory = OpenDirectory();
78   OpenNextFile();
79   fHeader = new AliRawDataHeader;
80 }
81
82 AliRawReaderFile::~AliRawReaderFile()
83 {
84 // close the input file
85
86   if (fDirectory) gSystem->FreeDirectory(fDirectory);
87   if (fStream) {
88 #if defined(__HP_aCC) || defined(__DECCXX)
89     if (fStream->rdbuf()->is_open()) fStream->close();
90 #else
91     if (fStream->is_open()) fStream->close();
92 #endif
93     delete fStream;
94   }
95   if (fHeader) delete fHeader;
96   if (fBuffer) delete[] fBuffer;
97   if (fDDLIndex) delete fDDLIndex; fDDLIndex=NULL;
98 }
99
100 void AliRawReaderFile::RequireHeader(Bool_t required)
101 {
102   // Reading of raw data in case of missing
103   // raw data header is not implemented for
104   // this class
105   if (!required) {
106     Warning("AliRawReaderFile","Reading of raw data without raw data header!");
107     if (fHeader) delete fHeader;
108     fHeader = NULL;
109   }
110   else {
111     if (!fHeader) fHeader = new AliRawDataHeader;
112   }
113
114   AliRawReader::RequireHeader(required);
115 }
116
117 TString AliRawReaderFile::GetDirName() const
118 {
119 // return the current directory name
120
121   TString dirName(fDirName);
122   if (fEventIndex >= 0) {
123     dirName += "/raw";
124     dirName += fEventIndex;
125   }
126   return dirName;
127 }
128
129 void* AliRawReaderFile::OpenDirectory()
130 {
131 // open and return the directory
132
133   TString dirName = GetDirName();
134   void* directory = gSystem->OpenDirectory(dirName);
135   if (!directory) {
136     Error("OpenDirectory", "could not open directory %s", dirName.Data());
137   }
138   return directory;
139 }
140
141 Bool_t AliRawReaderFile::CreateFileIndex()
142 {
143 // scan the files of the directory and create index of all DDL files
144 // returns kFALSE if no DDL files available
145   Bool_t result=kFALSE;
146   fDDLCurrent=-1;
147   if (fDDLIndex) return fDDLIndex->GetSize()>0;
148   if (!fDirectory) return kFALSE;
149   fDDLIndex=new TArrayC(0);
150   if (!fDDLIndex) return kFALSE;
151   TString entry;
152   while (entry = gSystem->GetDirEntry(fDirectory)) {
153     const char* filename=entry.Data();
154     if (!filename || entry.IsNull()) break;
155     if (!entry.EndsWith(".ddl")) continue;
156     result=kTRUE;
157     entry.Remove(0, entry.Last('_')+1);
158     entry.Remove(entry.Length()-4);
159     Int_t equipmentId = atoi(entry.Data());
160     if (fDDLIndex->GetSize()<=equipmentId) {
161       fDDLIndex->Set(equipmentId+1);
162     }
163     char* array=(char*)fDDLIndex->GetArray();
164     array[equipmentId]=1;
165   }
166
167   return result;
168 }
169
170 Bool_t AliRawReaderFile::OpenNextFile()
171 {
172 // open the next file
173 // returns kFALSE if the current file is the last one
174
175   if (!fDDLIndex && !CreateFileIndex()) return kFALSE;
176   if (fSelectMinEquipmentId>=0 && fSelectMinEquipmentId>fEquipmentId)
177     fDDLCurrent=fSelectMinEquipmentId-1;
178
179   if (fStream) {
180 #if defined(__HP_aCC) || defined(__DECCXX)
181     if (fStream->rdbuf()->is_open()) fStream->close();
182 #else
183     if (fStream->is_open()) fStream->close();
184 #endif
185     delete fStream;
186     fStream = NULL;
187     fEquipmentId = -1;
188     fEquipmentSize = 0;
189   }
190
191   if (!fDirectory) return kFALSE;
192   while (++fDDLCurrent<(fDDLIndex->GetSize()) && 
193          (fDDLCurrent<=fSelectMaxEquipmentId || fSelectMaxEquipmentId<0)) {
194     if (fDDLIndex->At(fDDLCurrent)==0) continue;
195     Int_t dummy=0;
196     TString entry;
197     entry.Form("%s_%d.ddl", AliDAQ::DetectorNameFromDdlID(fDDLCurrent, dummy), fDDLCurrent);
198     char* fileName = gSystem->ConcatFileName(GetDirName(), entry);
199     if (!fileName) continue;
200 #ifndef __DECCXX 
201     fStream = new fstream(fileName, ios::binary|ios::in);
202 #else
203     fStream = new fstream(fileName, ios::in);
204 #endif
205     delete [] fileName;
206     break;
207   }
208
209   if (!fStream) return kFALSE;
210   fEquipmentId = fDDLCurrent;
211 #if defined(__HP_aCC) || defined(__DECCXX)
212   return (fStream->rdbuf()->is_open());
213 #else
214   return (fStream->is_open());
215 #endif
216 }
217
218
219 Bool_t AliRawReaderFile::ReadHeader()
220 {
221 // read a data header at the current stream position
222 // returns kFALSE if the mini header could not be read
223
224   if (!fStream && !OpenNextFile()) return kFALSE;
225   do {
226     if (fCount > 0) fStream->seekg(Int_t(fStream->tellg()) + fCount);
227     if (fHeader) {
228       while (!fStream->read((char*) fHeader, sizeof(AliRawDataHeader))) {
229         if (!OpenNextFile()) return kFALSE;
230       }
231     }
232     else {
233       if (fStream->eof())
234         if (!OpenNextFile()) return kFALSE;
235     }
236     if (fHeader && fHeader->fSize != 0xFFFFFFFF) {
237       fCount = fHeader->fSize - sizeof(AliRawDataHeader);
238     } else {
239       UInt_t currentPos = fStream->tellg();
240       fStream->seekg(0, ios::end);
241       fCount = UInt_t(fStream->tellg()) - currentPos;
242       fStream->seekg(currentPos);
243     }
244     fEquipmentSize = fCount;
245     if (fHeader) fEquipmentSize += sizeof(AliRawDataHeader);
246   } while (!IsSelected());
247   return kTRUE;
248 }
249
250 Bool_t AliRawReaderFile::ReadNextData(UChar_t*& data)
251 {
252 // reads the next payload at the current stream position
253 // returns kFALSE if the data could not be read
254
255   while (fCount == 0) {
256     if (!ReadHeader()) return kFALSE;
257   }
258   if (fBufferSize < fCount) {
259     if (fBuffer) delete[] fBuffer;
260     fBufferSize = Int_t(fCount*1.2);
261     fBuffer = new UChar_t[fBufferSize];
262   }
263   if (!fStream->read((char*) fBuffer, fCount)) {
264     Error("ReadNext", "could not read data!");
265     return kFALSE;
266   }
267   fCount = 0;
268
269   data = fBuffer;
270   return kTRUE;
271 }
272
273 Bool_t AliRawReaderFile::ReadNext(UChar_t* data, Int_t size)
274 {
275 // reads the next block of data at the current stream position
276 // returns kFALSE if the data could not be read
277
278   if (!fStream->read((char*) data, size)) {
279     Error("ReadNext", "could not read data!");
280     return kFALSE;
281   }
282   fCount -= size;
283   return kTRUE;
284 }
285
286
287 Bool_t AliRawReaderFile::Reset()
288 {
289 // reset the current stream position to the first DDL file of the curevent
290
291   void* directory = OpenDirectory();
292   if (!directory) return kFALSE;
293
294   if (fStream) {
295 #if defined(__HP_aCC) || defined(__DECCXX)
296     if (fStream->rdbuf()->is_open()) fStream->close();
297 #else
298     if (fStream->is_open()) fStream->close();
299 #endif
300     delete fStream;
301     fStream = NULL;
302   }
303
304   if (fDirectory) gSystem->FreeDirectory(fDirectory);
305   fDirectory = directory;
306
307   // Matthias 05.06.2008
308   // do not open the next file. That might collide with a subsequent
309   // SelectEquipment call as the 'file pointer' is already set.
310   // This is important for the indexing of the DDL files.
311   // ---------------------------------------------------------
312   // All ReadNext functions first require the fCount member to be
313   // non zero or call ReadHeader. That allows to postpone the call
314   // to OpenNextFile to the next invocation of ReadHeader.
315   // ReadHeader has been mofified according to that.
316   /*
317   OpenNextFile();
318   */
319   fEquipmentId=-1;
320   fDDLCurrent=-1;
321   fCount = 0;
322   return kTRUE;
323 }
324
325 Bool_t AliRawReaderFile::NextEvent()
326 {
327 // go to the next event directory
328
329   if (fDDLIndex) delete fDDLIndex;
330   fDDLIndex=NULL;
331   if (fEventIndex < -1) return kFALSE;
332
333   do {
334     TString dirName = fDirName + "/raw";
335     dirName += (fEventIndex + 1);
336     void* directory = gSystem->OpenDirectory(dirName);
337     if (!directory) return kFALSE;
338     gSystem->FreeDirectory(directory);
339
340     fEventIndex++;
341     Reset();
342   } while (!IsEventSelected());
343
344   fEventNumber++;
345
346   return kTRUE;
347 }
348
349 Bool_t AliRawReaderFile::RewindEvents()
350 {
351 // reset the event counter
352
353   if (fEventIndex >= 0)  fEventIndex = -1;
354   fEventNumber = -1;
355   return Reset();
356 }