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