Run number is stored as a file <run#> among the DDL files. AliRawReaderFile looks...
[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   fType(7),
55   fRunNb(0),
56   fDetectorPattern(0),
57   fTimestamp(0)
58 {
59 // create an object to read digits from the given event
60 // in the current directory
61
62   fDirectory = OpenDirectory();
63   OpenNextFile();
64   fHeader = new AliRawDataHeader;
65
66   fId[0] = fId[1] = 0;
67   fTriggerPattern[0] = fTriggerPattern[1] = 0;
68 }
69
70 AliRawReaderFile::AliRawReaderFile(const char* dirName, Int_t eventNumber) :
71   fEventIndex(eventNumber),
72   fDirName(dirName),
73   fDirectory(NULL),
74   fStream(NULL),
75   fEquipmentId(-1),
76   fBuffer(NULL),
77   fBufferSize(0),
78   fEquipmentSize(0),
79   fDDLIndex(NULL),
80   fDDLCurrent(-1),
81   fType(7),
82   fRunNb(0),
83   fDetectorPattern(0),
84   fTimestamp(0)
85 {
86 // create an object to read digits from the given directory
87
88   fDirectory = OpenDirectory();
89   OpenNextFile();
90   fHeader = new AliRawDataHeader;
91
92   fId[0] = fId[1] = 0;
93   fTriggerPattern[0] = fTriggerPattern[1] = 0;
94 }
95
96 AliRawReaderFile::~AliRawReaderFile()
97 {
98 // close the input file
99
100   if (fDirectory) gSystem->FreeDirectory(fDirectory);
101   if (fStream) {
102 #if defined(__HP_aCC) || defined(__DECCXX)
103     if (fStream->rdbuf()->is_open()) fStream->close();
104 #else
105     if (fStream->is_open()) fStream->close();
106 #endif
107     delete fStream;
108   }
109   if (fHeader) delete fHeader;
110   if (fBuffer) delete[] fBuffer;
111   if (fDDLIndex) delete fDDLIndex; fDDLIndex=NULL;
112 }
113
114 void AliRawReaderFile::RequireHeader(Bool_t required)
115 {
116   // Reading of raw data in case of missing
117   // raw data header is not implemented for
118   // this class
119   if (!required) {
120     Warning("AliRawReaderFile","Reading of raw data without raw data header!");
121     if (fHeader) delete fHeader;
122     fHeader = NULL;
123   }
124   else {
125     if (!fHeader) fHeader = new AliRawDataHeader;
126   }
127
128   AliRawReader::RequireHeader(required);
129 }
130
131 TString AliRawReaderFile::GetDirName() const
132 {
133 // return the current directory name
134
135   TString dirName(fDirName);
136   if (fEventIndex >= 0) {
137     dirName += "/raw";
138     dirName += fEventIndex;
139   }
140   return dirName;
141 }
142
143 void* AliRawReaderFile::OpenDirectory()
144 {
145 // open and return the directory
146
147   TString dirName = GetDirName();
148   void* directory = gSystem->OpenDirectory(dirName);
149   if (!directory) {
150     Error("OpenDirectory", "could not open directory %s", dirName.Data());
151   }
152   return directory;
153 }
154
155 Bool_t AliRawReaderFile::CreateFileIndex()
156 {
157 // scan the files of the directory and create index of all DDL files
158 // returns kFALSE if no DDL files available
159   Bool_t result=kFALSE;
160   fDDLCurrent=-1;
161   if (fDDLIndex) return fDDLIndex->GetSize()>0;
162   if (!fDirectory) return kFALSE;
163   fDDLIndex=new TArrayC(0);
164   if (!fDDLIndex) return kFALSE;
165   TString entry;
166   while (entry = gSystem->GetDirEntry(fDirectory)) {
167     const char* filename=entry.Data();
168     if (!filename || entry.IsNull()) break;
169     if (entry.BeginsWith("run")) {
170       entry.ReplaceAll("run","");
171       fRunNb = entry.Atoi();
172       continue;
173     }
174     if (!entry.EndsWith(".ddl")) continue;
175     result=kTRUE;
176     entry.Remove(0, entry.Last('_')+1);
177     entry.Remove(entry.Length()-4);
178     Int_t equipmentId = atoi(entry.Data());
179     Int_t ddlIndex = -1;
180     fDetectorPattern |= (1 << AliDAQ::DetectorIDFromDdlID(equipmentId,ddlIndex));
181     if (fDDLIndex->GetSize()<=equipmentId) {
182       fDDLIndex->Set(equipmentId+1);
183     }
184     char* array=(char*)fDDLIndex->GetArray();
185     array[equipmentId]=1;
186   }
187
188   return result;
189 }
190
191 Bool_t AliRawReaderFile::OpenNextFile()
192 {
193 // open the next file
194 // returns kFALSE if the current file is the last one
195
196   if (!fDDLIndex && !CreateFileIndex()) return kFALSE;
197   if (fSelectMinEquipmentId>=0 && fSelectMinEquipmentId>fEquipmentId)
198     fDDLCurrent=fSelectMinEquipmentId-1;
199
200   if (fStream) {
201 #if defined(__HP_aCC) || defined(__DECCXX)
202     if (fStream->rdbuf()->is_open()) fStream->close();
203 #else
204     if (fStream->is_open()) fStream->close();
205 #endif
206     delete fStream;
207     fStream = NULL;
208     fEquipmentId = -1;
209     fEquipmentSize = 0;
210   }
211
212   if (!fDirectory) return kFALSE;
213   while (++fDDLCurrent<(fDDLIndex->GetSize()) && 
214          (fDDLCurrent<=fSelectMaxEquipmentId || fSelectMaxEquipmentId<0)) {
215     if (fDDLIndex->At(fDDLCurrent)==0) continue;
216     Int_t dummy=0;
217     TString entry;
218     entry.Form("%s_%d.ddl", AliDAQ::DetectorNameFromDdlID(fDDLCurrent, dummy), fDDLCurrent);
219     char* fileName = gSystem->ConcatFileName(GetDirName(), entry);
220     if (!fileName) continue;
221     // read the timestamp
222     FileStat_t buf;
223     if (gSystem->GetPathInfo(fileName,buf) == 0) {
224       fTimestamp = buf.fMtime;
225     }
226 #ifndef __DECCXX 
227     fStream = new fstream(fileName, ios::binary|ios::in);
228 #else
229     fStream = new fstream(fileName, ios::in);
230 #endif
231     delete [] fileName;
232     break;
233   }
234
235   if (!fStream) return kFALSE;
236   fEquipmentId = fDDLCurrent;
237 #if defined(__HP_aCC) || defined(__DECCXX)
238   return (fStream->rdbuf()->is_open());
239 #else
240   return (fStream->is_open());
241 #endif
242 }
243
244
245 Bool_t AliRawReaderFile::ReadHeader()
246 {
247 // read a data header at the current stream position
248 // returns kFALSE if the mini header could not be read
249
250   if (!fStream && !OpenNextFile()) return kFALSE;
251   do {
252     if (fCount > 0) fStream->seekg(Int_t(fStream->tellg()) + fCount);
253     if (fHeader) {
254       while (!fStream->read((char*) fHeader, sizeof(AliRawDataHeader))) {
255         if (!OpenNextFile()) return kFALSE;
256       }
257     }
258     else {
259       if (fStream->eof())
260         if (!OpenNextFile()) return kFALSE;
261     }
262     if (fHeader && fHeader->fSize != 0xFFFFFFFF) {
263       fCount = fHeader->fSize - sizeof(AliRawDataHeader);
264     } else {
265       UInt_t currentPos = fStream->tellg();
266       fStream->seekg(0, ios::end);
267       fCount = UInt_t(fStream->tellg()) - currentPos;
268       fStream->seekg(currentPos);
269     }
270     fEquipmentSize = fCount;
271     if (fHeader) fEquipmentSize += sizeof(AliRawDataHeader);
272   } while (!IsSelected());
273   return kTRUE;
274 }
275
276 Bool_t AliRawReaderFile::ReadNextData(UChar_t*& data)
277 {
278 // reads the next payload at the current stream position
279 // returns kFALSE if the data could not be read
280
281   while (fCount == 0) {
282     if (!ReadHeader()) return kFALSE;
283   }
284   if (fBufferSize < fCount) {
285     if (fBuffer) delete[] fBuffer;
286     fBufferSize = Int_t(fCount*1.2);
287     fBuffer = new UChar_t[fBufferSize];
288   }
289   if (!fStream->read((char*) fBuffer, fCount)) {
290     Error("ReadNext", "could not read data!");
291     return kFALSE;
292   }
293   fCount = 0;
294
295   data = fBuffer;
296   return kTRUE;
297 }
298
299 Bool_t AliRawReaderFile::ReadNext(UChar_t* data, Int_t size)
300 {
301 // reads the next block of data at the current stream position
302 // returns kFALSE if the data could not be read
303
304   if (!fStream->read((char*) data, size)) {
305     Error("ReadNext", "could not read data!");
306     return kFALSE;
307   }
308   fCount -= size;
309   return kTRUE;
310 }
311
312
313 Bool_t AliRawReaderFile::Reset()
314 {
315 // reset the current stream position to the first DDL file of the curevent
316
317   void* directory = OpenDirectory();
318   if (!directory) return kFALSE;
319
320   if (fStream) {
321 #if defined(__HP_aCC) || defined(__DECCXX)
322     if (fStream->rdbuf()->is_open()) fStream->close();
323 #else
324     if (fStream->is_open()) fStream->close();
325 #endif
326     delete fStream;
327     fStream = NULL;
328   }
329
330   if (fDirectory) gSystem->FreeDirectory(fDirectory);
331   fDirectory = directory;
332
333   // Matthias 05.06.2008
334   // do not open the next file. That might collide with a subsequent
335   // SelectEquipment call as the 'file pointer' is already set.
336   // This is important for the indexing of the DDL files.
337   // ---------------------------------------------------------
338   // All ReadNext functions first require the fCount member to be
339   // non zero or call ReadHeader. That allows to postpone the call
340   // to OpenNextFile to the next invocation of ReadHeader.
341   // ReadHeader has been mofified according to that.
342   /*
343   OpenNextFile();
344   */
345   fEquipmentId=-1;
346   fDDLCurrent=-1;
347   fCount = 0;
348   return kTRUE;
349 }
350
351 Bool_t AliRawReaderFile::NextEvent()
352 {
353 // go to the next event directory
354
355   if (fDDLIndex) delete fDDLIndex;
356   fDDLIndex=NULL;
357   fDetectorPattern = 0;
358   if (fEventIndex < -1) return kFALSE;
359
360   do {
361     TString dirName = fDirName + "/raw";
362     dirName += (fEventIndex + 1);
363     void* directory = gSystem->OpenDirectory(dirName);
364     if (!directory) return kFALSE;
365     gSystem->FreeDirectory(directory);
366
367     fEventIndex++;
368     Reset();
369   } while (!IsEventSelected());
370
371   // Read the header of the first payload
372   // in order to fill the 'fake' event header
373   if (ReadHeader() && fHeader) {
374     fId[0] = ((fHeader->GetEventID2() >> 20) & 0xf);
375     fId[1] = (fHeader->GetEventID1() & 0xfff) | ((fHeader->GetEventID2() & 0xfffff) << 12);
376     fTriggerPattern[0] = (fHeader->GetTriggerClasses() & 0xffffffff);
377     fTriggerPattern[1] = ((fHeader->GetTriggerClasses() >> 32) & 0x3ffff);
378   }
379   else {
380     Warning("AliRawReaderFile","Can not read CDH header! The event header fields will be empty!");
381   }
382   Reset();
383
384   fEventNumber++;
385
386   return kTRUE;
387 }
388
389 Bool_t AliRawReaderFile::RewindEvents()
390 {
391 // reset the event counter
392
393   if (fEventIndex >= 0)  fEventIndex = -1;
394   fEventNumber = -1;
395   return Reset();
396 }