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