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