Fix for 64-bit platforms
[u/mrichter/AliRoot.git] / RAW / AliRawDB.cxx
CommitLineData
a197a4ce 1// @(#)alimdc:$Name$:$Id$
2// Author: Fons Rademakers 26/11/99
3
4/**************************************************************************
5 * Copyright(c) 1998-2003, ALICE Experiment at CERN, All rights reserved. *
6 * *
7 * Author: The ALICE Off-line Project. *
8 * Contributors are mentioned in the code where appropriate. *
9 * *
10 * Permission to use, copy, modify and distribute this software and its *
11 * documentation strictly for non-commercial purposes is hereby granted *
12 * without fee, provided that the above copyright notice appears in all *
13 * copies and that both the copyright notice and this permission notice *
14 * appear in the supporting documentation. The authors make no claims *
15 * about the suitability of this software for any purpose. It is *
16 * provided "as is" without express or implied warranty. *
17 **************************************************************************/
18
19//////////////////////////////////////////////////////////////////////////
20// //
21// AliRawDB //
22// //
23//////////////////////////////////////////////////////////////////////////
24
25#include <errno.h>
a1377739 26#include <Riostream.h>
a197a4ce 27
e6694ae0 28#if ROOT_VERSION_CODE >= ROOT_VERSION(5,15,0)
29#include <TBufferFile.h>
30#else
31#include <TBuffer.h>
32#endif
33
a197a4ce 34#include <TSystem.h>
d21e9888 35#include <TKey.h>
a197a4ce 36
5d315e4d 37#include <TObjString.h>
38
52f36b9b 39#include "AliESD.h"
a197a4ce 40#include "AliRawEvent.h"
6605cb7a 41#include "AliRawDataArray.h"
f2dc6b20 42#include "AliRawEventHeaderBase.h"
6605cb7a 43#include "AliRawEquipment.h"
44#include "AliRawEquipmentHeader.h"
b7d09bb3 45#include "AliStats.h"
a109e73e 46
a197a4ce 47#include "AliRawDB.h"
48
49
50ClassImp(AliRawDB)
51
ee8f2a6c 52const char *AliRawDB::fgkAliRootTag = "$Name$";
a197a4ce 53
54//______________________________________________________________________________
a109e73e 55AliRawDB::AliRawDB(AliRawEvent *event,
a109e73e 56 AliESD *esd,
e10815f1 57 Int_t compress,
58 const char* fileName) :
59 fRawDB(NULL),
60 fTree(NULL),
61 fEvent(event),
62 fESDTree(NULL),
63 fESD(esd),
64 fCompress(compress),
65 fMaxSize(-1),
66 fFS1(""),
67 fFS2(""),
68 fDeleteFiles(kFALSE),
19359f9c 69 fStop(kFALSE)
a197a4ce 70{
e10815f1 71 // Create a new raw DB
a197a4ce 72
6605cb7a 73 for (Int_t iDet = 0; iDet < AliDAQ::kNDetectors; iDet++)
74 fDetRawData[iDet] = new AliRawDataArray(AliDAQ::NumberOfDdls(iDet));
75
76 fDetRawData[AliDAQ::kNDetectors] = new AliRawDataArray(100);
77
e10815f1 78 if (fileName) {
79 if (!Create(fileName))
a197a4ce 80 MakeZombie();
81 }
82}
83
6605cb7a 84
85//______________________________________________________________________________
86AliRawDB::~AliRawDB() {
87 // Destructor
88
89 if(Close()==-1) Error("~AliRawDB", "cannot close output file!");
90
91 for (Int_t iDet = 0; iDet < (AliDAQ::kNDetectors + 1); iDet++)
92 delete fDetRawData[iDet];
93}
94
a197a4ce 95//______________________________________________________________________________
a197a4ce 96Bool_t AliRawDB::FSHasSpace(const char *fs) const
97{
98 // Check for at least fMaxSize bytes of free space on the file system.
99 // If the space is not available return kFALSE, kTRUE otherwise.
100
101 Long_t id, bsize, blocks, bfree;
102
103 if (gSystem->GetFsInfo(fs, &id, &bsize, &blocks, &bfree) == 1) {
104 Error("FSHasSpace", "could not stat file system %s", fs);
105 return kFALSE;
106 }
107
108 // Leave 5 percent of diskspace free
109 Double_t avail = Double_t(bfree) * 0.95;
110 if (avail*bsize > fMaxSize)
111 return kTRUE;
112
113 Warning("FSHasSpace", "no space on file system %s", fs);
114 return kFALSE;
115}
116
117//______________________________________________________________________________
118const char *AliRawDB::GetFileName() const
119{
120 // Return filename based on hostname and date and time. This will make
121 // each file unique. Also makes sure (via FSHasSpace()) that there is
122 // enough space on the file system to store the file. Returns 0 in
123 // case of error or interrupt signal.
124
125 static TString fname;
126 static Bool_t fstoggle = kFALSE;
127
e10815f1 128 TString fs = fstoggle ? fFS2 : fFS1;
a197a4ce 129 TDatime dt;
130
131 TString hostname = gSystem->HostName();
132 Int_t pos;
133 if ((pos = hostname.Index(".")) != kNPOS)
134 hostname.Remove(pos);
135
136 if (!FSHasSpace(fs)) {
137 while (1) {
138 fstoggle = !fstoggle;
e10815f1 139 fs = fstoggle ? fFS2 : fFS1;
a197a4ce 140 if (FSHasSpace(fs)) break;
141 Info("GetFileName", "sleeping 30 seconds before retrying...");
142 gSystem->Sleep(30000); // sleep for 30 seconds
e10815f1 143 if (fStop) return 0;
a197a4ce 144 }
145 }
146
147 fname = fs + "/" + hostname + "_";
148 fname += dt.GetDate();
149 fname += "_";
150 fname += dt.GetTime();
151 fname += ".root";
152
153 fstoggle = !fstoggle;
154
155 return fname;
156}
157
158//______________________________________________________________________________
e10815f1 159void AliRawDB::SetFS(const char* fs1, const char* fs2)
160{
161// set the file system location
162
163 fFS1 = fs1;
164 if (fs1 && !fFS1.Contains(":")) {
165 gSystem->ResetErrno();
166 gSystem->MakeDirectory(fs1);
167 if (gSystem->GetErrno() && gSystem->GetErrno() != EEXIST) {
168 SysError("SetFS", "mkdir %s", fs1);
169 }
170 }
171
172 fFS2 = fs2;
173 if (fs2) {
174 gSystem->ResetErrno();
175 gSystem->MakeDirectory(fs2);
176 if (gSystem->GetErrno() && gSystem->GetErrno() != EEXIST) {
177 SysError("SetFS", "mkdir %s", fs2);
178 }
179 }
180}
181
182//______________________________________________________________________________
183Bool_t AliRawDB::Create(const char* fileName)
a197a4ce 184{
185 // Create a new raw DB.
186
f07ec911 187 const Int_t kMaxRetry = 1;
a197a4ce 188 const Int_t kMaxSleep = 1; // seconds
189 const Int_t kMaxSleepLong = 10; // seconds
190 Int_t retry = 0;
191
192again:
e10815f1 193 if (fStop) return kFALSE;
a197a4ce 194
e10815f1 195 const char *fname = fileName;
196 if (!fname) fname = GetFileName();
a197a4ce 197 if (!fname) {
198 Error("Create", "error getting raw DB file name");
199 return kFALSE;
200 }
201
202 retry++;
203
204 fRawDB = TFile::Open(fname, GetOpenOption(),
ee8f2a6c 205 Form("ALICE raw-data file (%s)", GetAliRootTag()), fCompress,
f07ec911 206 GetNetopt());
a197a4ce 207 if (!fRawDB) {
208 if (retry < kMaxRetry) {
209 Warning("Create", "failure to open file, sleeping %d %s before retrying...",
210 kMaxSleep, kMaxSleep==1 ? "second" : "seconds");
211 gSystem->Sleep(kMaxSleep*1000);
212 goto again;
213 }
214 Error("Create", "failure to open file %s after %d tries", fname, kMaxRetry);
215 return kFALSE;
216 }
217 if (retry > 1)
218 Warning("Create", "succeeded to open file after %d retries", retry);
219
220 if (fRawDB->IsZombie()) {
221 if (fRawDB->GetErrno() == ENOSPC ||
222 fRawDB->GetErrno() == 1018 || // SECOMERR
223 fRawDB->GetErrno() == 1027) { // SESYSERR
224 fRawDB->ResetErrno();
225 delete fRawDB;
226 Warning("Create", "file is a zombie (no space), sleeping %d %s before retrying...",
227 kMaxSleepLong, kMaxSleepLong==1 ? "second" : "seconds");
228 gSystem->Sleep(kMaxSleepLong*1000); // sleep 10 seconds before retrying
229 goto again;
230 }
231 Error("Create", "file %s is zombie", fname);
232 fRawDB->ResetErrno();
233 delete fRawDB;
234 fRawDB = 0;
235 if (retry < kMaxRetry) {
236 Warning("Create", "file is a zombie, sleeping %d %s before retrying...",
237 kMaxSleep, kMaxSleep==1 ? "second" : "seconds");
238 gSystem->Sleep(kMaxSleep*1000);
239 goto again;
240 }
241 Error("Create", "failure to open file %s after %d tries", fname, kMaxRetry);
242 return kFALSE;
243 }
244
245 // Create raw data TTree
246 MakeTree();
247
248 return kTRUE;
249}
250
251//______________________________________________________________________________
252void AliRawDB::MakeTree()
253{
254 // Create ROOT Tree object container.
255
ee8f2a6c 256 fTree = new TTree("RAW", Form("ALICE raw-data tree (%s)", GetAliRootTag()));
a197a4ce 257 fTree->SetAutoSave(2000000000); // autosave when 2 Gbyte written
258
6605cb7a 259 fTree->BranchRef();
260
a197a4ce 261 Int_t bufsize = 256000;
262 // splitting 29.6 MB/s, no splitting 35.3 MB/s on P4 2GHz 15k SCSI
263 //Int_t split = 1;
264 Int_t split = 0;
265 fTree->Branch("rawevent", "AliRawEvent", &fEvent, bufsize, split);
a109e73e 266
6605cb7a 267 // Make brach for each sub-detector
268 for (Int_t iDet = 0; iDet < AliDAQ::kNDetectors; iDet++) {
269 fTree->Branch(AliDAQ::DetectorName(iDet),"AliRawDataArray",
270 &fDetRawData[iDet],bufsize,split);
271 }
272 // Make special branch for unrecognized raw-data payloads
273 fTree->Branch("Common","AliRawDataArray",
274 &fDetRawData[AliDAQ::kNDetectors],bufsize,split);
275
a109e73e 276 // Create tree which will contain the HLT ESD information
277
e10815f1 278 if (fESD) {
ee8f2a6c 279 fESDTree = new TTree("esdTree", Form("ALICE HLT ESD tree (%s)", GetAliRootTag()));
e10815f1 280 fESDTree->SetAutoSave(2000000000); // autosave when 2 Gbyte written
5f42007f 281 split = 0;
e10815f1 282 fESDTree->Branch("ESD", "AliESD", &fESD, bufsize, split);
283 }
a109e73e 284
a197a4ce 285}
286
287//______________________________________________________________________________
f07ec911 288Int_t AliRawDB::Close()
a197a4ce 289{
290 // Close raw DB.
f07ec911 291 if (!fRawDB) return 0;
a197a4ce 292
f07ec911 293 if (!fRawDB->IsOpen()) return 0;
a197a4ce 294
295 fRawDB->cd();
296
297 // Write the tree.
f07ec911 298 Bool_t error = kFALSE;
299 if (fTree->Write() == 0)
300 error = kTRUE;
301 if (fESDTree)
302 if (fESDTree->Write() == 0)
303 error = kTRUE;
a197a4ce 304
305 // Close DB, this also deletes the fTree
306 fRawDB->Close();
307
f07ec911 308 Int_t filesize = fRawDB->GetEND();
309
e10815f1 310 if (fDeleteFiles) {
a197a4ce 311 gSystem->Unlink(fRawDB->GetName());
312 delete fRawDB;
313 fRawDB = 0;
f07ec911 314 if(!error)
315 return filesize;
316 else
317 return -1;
a197a4ce 318 }
319
a197a4ce 320 delete fRawDB;
321 fRawDB = 0;
f07ec911 322 if(!error)
323 return filesize;
324 else
325 return -1;
a197a4ce 326}
327
328//______________________________________________________________________________
e10815f1 329Int_t AliRawDB::Fill()
330{
331 // Fill the trees and return the number of written bytes
332
6605cb7a 333 for (Int_t iDet = 0; iDet < (AliDAQ::kNDetectors + 1); iDet++)
334 fDetRawData[iDet]->ClearData();
335
336 // Move the raw-data payloads to the corresponding branches
337 for(Int_t iSubEvent = 0; iSubEvent < fEvent->GetNSubEvents(); iSubEvent++) {
338 AliRawEvent *subEvent = fEvent->GetSubEvent(iSubEvent);
339 for(Int_t iEquipment = 0; iEquipment < subEvent->GetNEquipments(); iEquipment++) {
340 AliRawEquipment *equipment = subEvent->GetEquipment(iEquipment);
341 UInt_t eqId = equipment->GetEquipmentHeader()->GetId();
342 Int_t ddlIndex;
343 Int_t iDet = AliDAQ::DetectorIDFromDdlID(eqId,ddlIndex);
344 if (iDet < 0 || iDet > AliDAQ::kNDetectors)
345 iDet = AliDAQ::kNDetectors;
346 equipment->SetRawDataRef(fDetRawData[iDet]);
347 }
348 }
349
e10815f1 350 Double_t bytes = fRawDB->GetBytesWritten();
f07ec911 351 Bool_t error = kFALSE;
352 if (fTree->Fill() == -1)
353 error = kTRUE;
354 if (fESDTree)
355 if (fESDTree->Fill() == -1)
356 error = kTRUE;
357 if(!error)
358 return Int_t(fRawDB->GetBytesWritten() - bytes);
359 else
360 return -1;
e10815f1 361}
362
363//______________________________________________________________________________
d21e9888 364Int_t AliRawDB::GetTotalSize()
365{
366 // Return the total size of the trees
367 Int_t total = 0;
368
369 {
370 Int_t skey = 0;
371 TDirectory *dir = fTree->GetDirectory();
372 if (dir) {
373 TKey *key = dir->GetKey(fTree->GetName());
374 if (key) skey = key->GetKeylen();
375 }
08359abe 376 total += skey + fTree->GetZipBytes();
d21e9888 377 }
378
379 if(fESDTree)
380 {
381 Int_t skey = 0;
382 TDirectory *dir = fESDTree->GetDirectory();
383 if (dir) {
384 TKey *key = dir->GetKey(fESDTree->GetName());
385 if (key) skey = key->GetKeylen();
386 }
08359abe 387 total += skey + fESDTree->GetZipBytes();
d21e9888 388 }
389
390 return total;
391}
392
393//______________________________________________________________________________
b7d09bb3 394void AliRawDB::WriteStats(AliStats* stats)
395{
396 // Write stats to raw DB, local run DB and global MySQL DB.
397
f2dc6b20 398 AliRawEventHeaderBase &header = *GetEvent()->GetHeader();
b7d09bb3 399
400 // Write stats into RawDB
401 TDirectory *ds = gDirectory;
402 GetDB()->cd();
403 stats->SetEvents(GetEvents());
ad594815 404 stats->SetLastId(header.GetP("Id")[0]);
b7d09bb3 405 stats->SetFileSize(GetBytesWritten());
406 stats->SetCompressionFactor(GetCompressionFactor());
407 stats->SetEndTime();
408 stats->Write("stats");
409 ds->cd();
410}
411
412//______________________________________________________________________________
e10815f1 413Bool_t AliRawDB::NextFile(const char* fileName)
a197a4ce 414{
415 // Close te current file and open a new one.
416 // Returns kFALSE in case opening failed.
417
418 Close();
419
e10815f1 420 if (!Create(fileName)) return kFALSE;
a197a4ce 421 return kTRUE;
422}
423
424//______________________________________________________________________________
425Float_t AliRawDB::GetCompressionFactor() const
426{
427 // Return compression factor.
428
429 if (fTree->GetZipBytes() == 0.)
430 return 1.0;
431 else
432 return fTree->GetTotBytes()/fTree->GetZipBytes();
433}
ee8f2a6c 434
435//______________________________________________________________________________
436const char *AliRawDB::GetAliRootTag()
437{
438 // Return the aliroot tag (version)
439 // used to generate the raw data file.
440 // Stored in the raw-data file title.
441
442 TString version = fgkAliRootTag;
443 version.Remove(TString::kBoth,'$');
444 version.ReplaceAll("Name","AliRoot version");
445
446 return version.Data();
447}
5d315e4d 448
449//______________________________________________________________________________
19359f9c 450Bool_t AliRawDB::WriteGuidFile(const char *guidFileFolder)
5d315e4d 451{
452 // Write the guid file
19359f9c 453 // in the specified folder or
454 // in the folder where the raw data
455 // file is.
5d315e4d 456
457 TString guidFileName;
19359f9c 458 if (guidFileFolder) {
459 guidFileName = guidFileFolder;
5d315e4d 460
461 TString pathStr = fRawDB->GetName();
462 TObjArray *pathArr = pathStr.Tokenize('/');
463 guidFileName.Append("/");
464 guidFileName.Append(((TObjString *)pathArr->Last())->String());
465 pathArr->Delete();
466 delete pathArr;
467 }
468 else
469 guidFileName = fRawDB->GetName();
470
471 guidFileName += ".guid";
472
473 ofstream fguid(guidFileName.Data());
19359f9c 474 if (!fguid.is_open()) {
475 Error("WriteGuidFile", "failure to open guid file %s", guidFileName.Data());
476 return kFALSE;
477 }
5d315e4d 478 TString guid = fRawDB->GetUUID().AsString();
479 fguid << "guid: \t" << guid.Data();
480 fguid.close();
19359f9c 481
482 return kTRUE;
5d315e4d 483}