Line data Source code
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>
26 : #include <Riostream.h>
27 : #include <RVersion.h>
28 :
29 : #if ROOT_VERSION_CODE >= ROOT_VERSION(5,15,0)
30 : #include <TBufferFile.h>
31 : #else
32 : #include <TBuffer.h>
33 : #endif
34 :
35 : #include <TSystem.h>
36 : #include <TKey.h>
37 :
38 : #include <TObjString.h>
39 :
40 : #include <TBranch.h>
41 :
42 : #include "AliESDEvent.h"
43 : #include "AliRawEventV2.h"
44 : #include "AliRawDataArrayV2.h"
45 : #include "AliRawEventHeaderBase.h"
46 : #include "AliRawEquipmentHeader.h"
47 :
48 : #include "AliRawDB.h"
49 :
50 : using std::ofstream;
51 :
52 2 : ClassImp(AliRawDB)
53 :
54 : const char *AliRawDB::fgkAliRootTag = "$Rev$";
55 :
56 : // Split TPC into 18 branches in order to avoid problems with big memory
57 : // consumption in case of TPC events w/o zero-suppression
58 : Int_t AliRawDB::fgkDetBranches[AliDAQ::kNDetectors+1] = {
59 : 1, /* 1 ITSSPD */
60 : 1, /* 2 ITSSDD */
61 : 1, /* 3 ITSSSD */
62 : 18, /* 4 TPC */
63 : 1, /* 5 TRD */
64 : 1, /* 6 TOF */
65 : 1, /* 7 HMPID */
66 : 1, /* 8 PHOS */
67 : 1, /* 9 CPV */
68 : 1, /* 10 PMD */
69 : 1, /* 11 MUONTRK */
70 : 1, /* 12 MUONTRG */
71 : 1, /* 13 FMD */
72 : 1, /* 14 T0 */
73 : 1, /* 15 VZERO */
74 : 1, /* 16 ZDC */
75 : 1, /* 17 ACORDE */
76 : 1, /* 18 TRG */
77 : 1, /* 19 EMCAL */
78 : 1, /* 20 DAQ_TEST */
79 : 1, /* 21 EMPTY */
80 : 1, /* 22 AD */
81 : 1, /* 23 MFT */
82 : 1, /* 24 FIT */
83 : 10,/* 25 HLT */
84 : 1 /* 26 --- */
85 : };
86 :
87 : //______________________________________________________________________________
88 1 : AliRawDB::AliRawDB(AliRawEventV2 *event,
89 : AliESDEvent *esd,
90 : Int_t compress,
91 : const char* fileName,
92 : Int_t basketsize, Long64_t autoflush) :
93 1 : fRawDB(NULL),
94 1 : fTree(NULL),
95 1 : fEvent(event),
96 1 : fESDTree(NULL),
97 1 : fESD(esd),
98 1 : fCompress(compress),
99 1 : fBasketSize(basketsize),
100 1 : fAutoFlush(autoflush),
101 1 : fMaxSize(-1),
102 1 : fFS1(""),
103 1 : fFS2(""),
104 1 : fDeleteFiles(kFALSE),
105 1 : fStop(kFALSE)
106 5 : {
107 : // Create a new raw DB
108 :
109 52 : for (Int_t iDet = 0; iDet < AliDAQ::kNDetectors; iDet++) {
110 50 : fDetRawData[iDet] = new AliRawDataArrayV2*[fgkDetBranches[iDet]];
111 50 : Int_t nDDLsPerBranch = AliDAQ::NumberOfDdls(iDet)/fgkDetBranches[iDet];
112 152 : for (Int_t iBranch = 0; iBranch < fgkDetBranches[iDet]; iBranch++)
113 153 : fDetRawData[iDet][iBranch] = new AliRawDataArrayV2(nDDLsPerBranch);
114 : }
115 :
116 2 : fDetRawData[AliDAQ::kNDetectors] = new AliRawDataArrayV2*[fgkDetBranches[AliDAQ::kNDetectors]];
117 4 : for (Int_t iBranch = 0; iBranch < fgkDetBranches[AliDAQ::kNDetectors]; iBranch++)
118 3 : fDetRawData[AliDAQ::kNDetectors][iBranch] = new AliRawDataArrayV2(100);
119 :
120 1 : if (fileName) {
121 0 : if (!Create(fileName))
122 0 : MakeZombie();
123 : }
124 2 : }
125 :
126 :
127 : //______________________________________________________________________________
128 6 : AliRawDB::~AliRawDB() {
129 : // Destructor
130 :
131 2 : if(Close()==-1) Error("~AliRawDB", "cannot close output file!");
132 :
133 54 : for (Int_t iDet = 0; iDet < (AliDAQ::kNDetectors + 1); iDet++) {
134 156 : for (Int_t iBranch = 0; iBranch < fgkDetBranches[iDet]; iBranch++)
135 104 : delete fDetRawData[iDet][iBranch];
136 52 : delete [] fDetRawData[iDet];
137 : }
138 3 : }
139 :
140 : //______________________________________________________________________________
141 : Bool_t AliRawDB::FSHasSpace(const char *fs) const
142 : {
143 : // Check for at least fMaxSize bytes of free space on the file system.
144 : // If the space is not available return kFALSE, kTRUE otherwise.
145 :
146 2 : Long_t id, bsize, blocks, bfree;
147 :
148 1 : if (gSystem->GetFsInfo(fs, &id, &bsize, &blocks, &bfree) == 1) {
149 0 : Error("FSHasSpace", "could not stat file system %s", fs);
150 0 : return kFALSE;
151 : }
152 :
153 : // Leave 5 percent of diskspace free
154 1 : Double_t avail = Double_t(bfree) * 0.95;
155 1 : if (avail*bsize > fMaxSize)
156 1 : return kTRUE;
157 :
158 0 : Warning("FSHasSpace", "no space on file system %s", fs);
159 0 : return kFALSE;
160 1 : }
161 :
162 : //______________________________________________________________________________
163 : const char *AliRawDB::GetFileName() const
164 : {
165 : // Return filename based on hostname and date and time. This will make
166 : // each file unique. Also makes sure (via FSHasSpace()) that there is
167 : // enough space on the file system to store the file. Returns 0 in
168 : // case of error or interrupt signal.
169 :
170 5 : static TString fname;
171 : static Bool_t fstoggle = kFALSE;
172 :
173 1 : TString fs = fstoggle ? fFS2 : fFS1;
174 1 : TDatime dt;
175 :
176 2 : TString hostname = gSystem->HostName();
177 : Int_t pos;
178 2 : if ((pos = hostname.Index(".")) != kNPOS)
179 1 : hostname.Remove(pos);
180 :
181 3 : if (!FSHasSpace(fs)) {
182 : while (1) {
183 0 : fstoggle = !fstoggle;
184 0 : fs = fstoggle ? fFS2 : fFS1;
185 0 : if (FSHasSpace(fs)) break;
186 0 : Info("GetFileName", "sleeping 30 seconds before retrying...");
187 0 : gSystem->Sleep(30000); // sleep for 30 seconds
188 0 : if (fStop) return 0;
189 : }
190 : }
191 :
192 5 : fname = fs + "/" + hostname + "_";
193 2 : fname += dt.GetDate();
194 1 : fname += "_";
195 2 : fname += dt.GetTime();
196 1 : fname += ".root";
197 :
198 1 : fstoggle = !fstoggle;
199 :
200 2 : return fname;
201 1 : }
202 :
203 : //______________________________________________________________________________
204 : void AliRawDB::SetFS(const char* fs1, const char* fs2)
205 : {
206 : // set the file system location
207 :
208 2 : fFS1 = fs1;
209 2 : if (fs1 && !fFS1.Contains(":")) {
210 1 : gSystem->ResetErrno();
211 1 : gSystem->MakeDirectory(fs1);
212 2 : if (gSystem->GetErrno() && gSystem->GetErrno() != EEXIST) {
213 0 : SysError("SetFS", "mkdir %s", fs1);
214 0 : }
215 : }
216 :
217 1 : fFS2 = fs2;
218 1 : if (fs2) {
219 1 : gSystem->ResetErrno();
220 1 : gSystem->MakeDirectory(fs2);
221 2 : if (gSystem->GetErrno() && gSystem->GetErrno() != EEXIST) {
222 0 : SysError("SetFS", "mkdir %s", fs2);
223 0 : }
224 : }
225 1 : }
226 :
227 : //______________________________________________________________________________
228 : Bool_t AliRawDB::Create(const char* fileName)
229 : {
230 : // Create a new raw DB.
231 :
232 : const Int_t kMaxRetry = 1;
233 : const Int_t kMaxSleep = 1; // seconds
234 : const Int_t kMaxSleepLong = 10; // seconds
235 2 : Int_t retry = 0;
236 :
237 : again:
238 1 : if (fStop) return kFALSE;
239 :
240 : const char *fname = fileName;
241 2 : if (!fname) fname = GetFileName();
242 1 : if (!fname) {
243 0 : Error("Create", "error getting raw DB file name");
244 0 : return kFALSE;
245 : }
246 :
247 1 : retry++;
248 :
249 2 : fRawDB = TFile::Open(fname, GetOpenOption(),
250 1 : Form("ALICE raw-data file (%s)", GetAliRootTag()), fCompress,
251 1 : GetNetopt());
252 1 : if (!fRawDB) {
253 0 : if (retry < kMaxRetry) {
254 0 : Warning("Create", "failure to open file, sleeping %d %s before retrying...",
255 : kMaxSleep, kMaxSleep==1 ? "second" : "seconds");
256 0 : gSystem->Sleep(kMaxSleep*1000);
257 0 : goto again;
258 : }
259 0 : Error("Create", "failure to open file %s after %d tries", fname, kMaxRetry);
260 0 : return kFALSE;
261 : }
262 1 : if (retry > 1)
263 0 : Warning("Create", "succeeded to open file after %d retries", retry);
264 :
265 1 : if (fRawDB->IsZombie()) {
266 0 : if (fRawDB->GetErrno() == ENOSPC ||
267 0 : fRawDB->GetErrno() == 1018 || // SECOMERR
268 0 : fRawDB->GetErrno() == 1027) { // SESYSERR
269 0 : fRawDB->ResetErrno();
270 0 : delete fRawDB;
271 0 : Warning("Create", "file is a zombie (no space), sleeping %d %s before retrying...",
272 : kMaxSleepLong, kMaxSleepLong==1 ? "second" : "seconds");
273 0 : gSystem->Sleep(kMaxSleepLong*1000); // sleep 10 seconds before retrying
274 0 : goto again;
275 : }
276 0 : Error("Create", "file %s is zombie", fname);
277 0 : fRawDB->ResetErrno();
278 0 : delete fRawDB;
279 0 : fRawDB = 0;
280 0 : if (retry < kMaxRetry) {
281 0 : Warning("Create", "file is a zombie, sleeping %d %s before retrying...",
282 : kMaxSleep, kMaxSleep==1 ? "second" : "seconds");
283 0 : gSystem->Sleep(kMaxSleep*1000);
284 0 : goto again;
285 : }
286 0 : Error("Create", "failure to open file %s after %d tries", fname, kMaxRetry);
287 0 : return kFALSE;
288 : }
289 :
290 1 : return kTRUE;
291 1 : }
292 :
293 : static void BranchResetBit(TBranch *b)
294 : {
295 : // Reset MapObject on this branch and all the sub-branches
296 :
297 688 : b->ResetBit( kBranchObject | kBranchAny ); // Or in newer ROOT: b->ResetBit( kMapObject )
298 344 : TIter next( b->GetListOfBranches() );
299 : TBranch *sub = 0;
300 1614 : while ( (sub = (TBranch*)next() ) ) {
301 291 : BranchResetBit( sub );
302 : }
303 344 : }
304 :
305 : //______________________________________________________________________________
306 : void AliRawDB::MakeTree()
307 : {
308 : // Create ROOT Tree object container.
309 :
310 5 : fTree = new TTree("RAW", Form("ALICE raw-data tree (%s)", GetAliRootTag()));
311 1 : fTree->SetAutoSave(21000000000LL); // autosave when 21 Gbyte written
312 1 : fTree->SetAutoFlush(fAutoFlush);
313 :
314 1 : fTree->BranchRef();
315 :
316 : Int_t split = 99;
317 1 : TBranch *b = fTree->Branch("rawevent", "AliRawEventV2", &fEvent, fBasketSize, split);
318 1 : BranchResetBit(b);
319 :
320 : // Make brach for each sub-detector
321 52 : for (Int_t iDet = 0; iDet < AliDAQ::kNDetectors; iDet++) {
322 152 : for (Int_t iBranch = 0; iBranch < fgkDetBranches[iDet]; iBranch++) {
323 102 : b = fTree->Branch(Form("%s%d",AliDAQ::DetectorName(iDet),iBranch),"AliRawDataArrayV2",
324 51 : &fDetRawData[iDet][iBranch],fBasketSize,split);
325 51 : BranchResetBit(b);
326 : }
327 : }
328 : // Make special branch for unrecognized raw-data payloads
329 4 : for (Int_t iBranch = 0; iBranch < fgkDetBranches[AliDAQ::kNDetectors]; iBranch++) {
330 2 : b = fTree->Branch(Form("Common%d",iBranch),"AliRawDataArrayV2",
331 1 : &fDetRawData[AliDAQ::kNDetectors][iBranch],fBasketSize,split);
332 1 : BranchResetBit(b);
333 : }
334 :
335 : // Create tree which will contain the HLT ESD information
336 :
337 1 : if (fESD) {
338 0 : fESDTree = new TTree("esdTree", Form("ALICE HLT ESD tree (%s)", GetAliRootTag()));
339 0 : fESDTree->SetAutoSave(21000000000LL); // autosave when 21 Gbyte written
340 0 : fESDTree->SetAutoFlush(fAutoFlush);
341 : split = 0;
342 0 : fESDTree->Branch("ESD", "AliESDEvent", &fESD, fBasketSize, split);
343 0 : }
344 :
345 1 : }
346 :
347 : //______________________________________________________________________________
348 : Long64_t AliRawDB::Close()
349 : {
350 : // Close raw DB.
351 5 : if (!fRawDB) return 0;
352 :
353 1 : if (!fRawDB->IsOpen()) return 0;
354 :
355 1 : fRawDB->cd();
356 :
357 : // Write the tree.
358 : Bool_t error = kFALSE;
359 1 : if (fTree)
360 1 : if (fTree->Write() == 0)
361 0 : error = kTRUE;
362 1 : if (fESDTree)
363 0 : if (fESDTree->Write() == 0)
364 0 : error = kTRUE;
365 :
366 : // Close DB, this also deletes the fTree
367 1 : fRawDB->Close();
368 :
369 1 : fTree = NULL;
370 :
371 1 : Long64_t filesize = fRawDB->GetEND();
372 :
373 1 : if (fDeleteFiles) {
374 0 : gSystem->Unlink(fRawDB->GetName());
375 0 : delete fRawDB;
376 0 : fRawDB = 0;
377 0 : if(!error)
378 0 : return filesize;
379 : else
380 0 : return -1;
381 : }
382 :
383 2 : delete fRawDB;
384 1 : fRawDB = 0;
385 1 : if(!error)
386 1 : return filesize;
387 : else
388 0 : return -1;
389 2 : }
390 :
391 : //______________________________________________________________________________
392 : Int_t AliRawDB::Fill()
393 : {
394 : // Fill the trees and return the number of written bytes
395 :
396 : // Create raw data TTree if it not yet done
397 9 : if (!fTree) MakeTree();
398 :
399 4 : Double_t bytes = fRawDB->GetBytesWritten();
400 : Bool_t error = kFALSE;
401 4 : if (fTree->Fill() == -1)
402 0 : error = kTRUE;
403 4 : if (fESDTree)
404 0 : if (fESDTree->Fill() == -1)
405 0 : error = kTRUE;
406 4 : if(!error)
407 4 : return Int_t(fRawDB->GetBytesWritten() - bytes);
408 : else
409 0 : return -1;
410 4 : }
411 :
412 : //______________________________________________________________________________
413 : Long64_t AliRawDB::GetTotalSize()
414 : {
415 : // Return the total size of the trees
416 : Long64_t total = 0;
417 :
418 8 : if (fTree) {
419 : Int_t skey = 0;
420 3 : TDirectory *dir = fTree->GetDirectory();
421 3 : if (dir) {
422 3 : TKey *key = dir->GetKey(fTree->GetName());
423 3 : if (key) skey = key->GetKeylen();
424 3 : }
425 3 : total += (Long64_t)skey + fTree->GetZipBytes();
426 3 : }
427 :
428 4 : if(fESDTree)
429 : {
430 : Int_t skey = 0;
431 0 : TDirectory *dir = fESDTree->GetDirectory();
432 0 : if (dir) {
433 0 : TKey *key = dir->GetKey(fESDTree->GetName());
434 0 : if (key) skey = key->GetKeylen();
435 0 : }
436 0 : total += (Long64_t)skey + fESDTree->GetZipBytes();
437 0 : }
438 :
439 4 : return total;
440 : }
441 :
442 : //______________________________________________________________________________
443 : Long64_t AliRawDB::AutoSave()
444 : {
445 : // Auto-save the raw-data and
446 : // esd (if any) trees
447 :
448 0 : Long64_t nbytes = fTree->AutoSave();
449 :
450 0 : if (fESDTree) nbytes += fESDTree->AutoSave();
451 :
452 0 : return nbytes;
453 : }
454 :
455 : //______________________________________________________________________________
456 : Bool_t AliRawDB::NextFile(const char* fileName)
457 : {
458 : // Close te current file and open a new one.
459 : // Returns kFALSE in case opening failed.
460 :
461 0 : Close();
462 :
463 0 : if (!Create(fileName)) return kFALSE;
464 0 : return kTRUE;
465 0 : }
466 :
467 : //______________________________________________________________________________
468 : Float_t AliRawDB::GetCompressionFactor() const
469 : {
470 : // Return compression factor.
471 :
472 0 : if (fTree->GetZipBytes() == 0.)
473 0 : return 1.0;
474 : else
475 0 : return fTree->GetTotBytes()/fTree->GetZipBytes();
476 0 : }
477 :
478 : //______________________________________________________________________________
479 : const char *AliRawDB::GetAliRootTag()
480 : {
481 : // Return the aliroot tag (version)
482 : // used to generate the raw data file.
483 : // Stored in the raw-data file title.
484 :
485 11 : static TString version = fgkAliRootTag;
486 4 : version.Remove(TString::kBoth,'$');
487 4 : version.ReplaceAll("Rev","AliRoot version");
488 :
489 4 : return version.Data();
490 0 : }
491 :
492 : //______________________________________________________________________________
493 : Bool_t AliRawDB::WriteGuidFile(TString &guidFileFolder)
494 : {
495 : // Write the guid file
496 : // in the specified folder or
497 : // in the folder where the raw data
498 : // file is.
499 :
500 2 : TString guidFileName;
501 2 : if (!guidFileFolder.IsNull()) {
502 0 : guidFileName = guidFileFolder;
503 :
504 0 : TString pathStr = fRawDB->GetName();
505 0 : TObjArray *pathArr = pathStr.Tokenize('/');
506 0 : guidFileName.Append("/");
507 0 : guidFileName.Append(((TObjString *)pathArr->Last())->String());
508 0 : pathArr->Delete();
509 0 : delete pathArr;
510 0 : }
511 : else
512 2 : guidFileName = fRawDB->GetName();
513 :
514 1 : guidFileName += ".guid";
515 :
516 2 : ofstream fguid(guidFileName.Data());
517 2 : if (!fguid.is_open()) {
518 0 : Error("WriteGuidFile", "failure to open guid file %s", guidFileName.Data());
519 0 : return kFALSE;
520 : }
521 3 : TString guid = fRawDB->GetUUID().AsString();
522 3 : fguid << "guid: \t" << guid.Data();
523 1 : fguid.close();
524 :
525 : return kTRUE;
526 2 : }
527 :
528 :
529 : //______________________________________________________________________________
530 : void AliRawDB::Reset()
531 : {
532 : // Clear the raw-data arrays
533 : // Should be done before processing the raw-data event
534 :
535 220 : for (Int_t iDet = 0; iDet < (AliDAQ::kNDetectors + 1); iDet++)
536 624 : for (Int_t iBranch = 0; iBranch < fgkDetBranches[iDet]; iBranch++)
537 208 : fDetRawData[iDet][iBranch]->ClearData();
538 4 : }
539 :
540 : //______________________________________________________________________________
541 : AliRawDataArrayV2 *AliRawDB::GetRawDataArray(UInt_t eqSize, UInt_t eqId) const
542 : {
543 : // Return the corresponding raw-datra array (branch)
544 : // depending on the equipment ID
545 :
546 : Int_t iDet = AliDAQ::kNDetectors;
547 : Int_t iBranch = 0; // can we split somehow the unrecognized data??? For the moment - no
548 3242 : if(eqSize) {
549 1621 : Int_t ddlIndex = -1;
550 1621 : iDet = AliDAQ::DetectorIDFromDdlID(eqId,ddlIndex);
551 1621 : if (iDet < 0 || iDet >= AliDAQ::kNDetectors)
552 0 : iDet = AliDAQ::kNDetectors;
553 : else
554 1621 : iBranch = (ddlIndex * fgkDetBranches[iDet])/AliDAQ::NumberOfDdls(iDet);
555 1621 : }
556 :
557 1621 : return fDetRawData[iDet][iBranch];
558 : }
559 :
|