]> git.uio.no Git - u/mrichter/AliRoot.git/blob - RAW/AliRawDB.cxx
Adding libMUONshuttle which is needed by libMUONrec
[u/mrichter/AliRoot.git] / RAW / AliRawDB.cxx
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
28 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,15,0)
29 #include <TBufferFile.h>
30 #else
31 #include <TBuffer.h>
32 #endif
33
34 #include <TSystem.h>
35 #include <TKey.h>
36
37 #include <TObjString.h>
38
39 #include "AliESD.h"
40 #include "AliRawEvent.h"
41 #include "AliRawEventHeaderBase.h"
42 #include "AliStats.h"
43
44 #include "AliRawDB.h"
45
46
47 ClassImp(AliRawDB)
48
49 const char *AliRawDB::fgkAliRootTag = "$Name$";
50
51 //______________________________________________________________________________
52 AliRawDB::AliRawDB(AliRawEvent *event,
53                    AliESD *esd, 
54                    Int_t compress,
55                    const char* fileName) :
56   fRawDB(NULL),
57   fTree(NULL),
58   fEvent(event),
59   fESDTree(NULL),
60   fESD(esd),
61   fCompress(compress),
62   fMaxSize(-1),
63   fFS1(""),
64   fFS2(""),
65   fDeleteFiles(kFALSE),
66   fStop(kFALSE),
67   fGuidFileFolder(NULL)
68 {
69    // Create a new raw DB
70
71    if (fileName) {
72       if (!Create(fileName))
73          MakeZombie();
74    }
75 }
76
77 //______________________________________________________________________________
78 Bool_t AliRawDB::FSHasSpace(const char *fs) const
79 {
80    // Check for at least fMaxSize bytes of free space on the file system.
81    // If the space is not available return kFALSE, kTRUE otherwise.
82
83    Long_t id, bsize, blocks, bfree;
84
85    if (gSystem->GetFsInfo(fs, &id, &bsize, &blocks, &bfree) == 1) {
86       Error("FSHasSpace", "could not stat file system %s", fs);
87       return kFALSE;
88    }
89
90    // Leave 5 percent of diskspace free
91    Double_t avail = Double_t(bfree) * 0.95;
92    if (avail*bsize > fMaxSize)
93       return kTRUE;
94
95    Warning("FSHasSpace", "no space on file system %s", fs);
96    return kFALSE;
97 }
98
99 //______________________________________________________________________________
100 const char *AliRawDB::GetFileName() const
101 {
102    // Return filename based on hostname and date and time. This will make
103    // each file unique. Also makes sure (via FSHasSpace()) that there is
104    // enough space on the file system to store the file. Returns 0 in
105    // case of error or interrupt signal.
106
107    static TString fname;
108    static Bool_t  fstoggle = kFALSE;
109
110    TString fs = fstoggle ? fFS2 : fFS1;
111    TDatime dt;
112
113    TString hostname = gSystem->HostName();
114    Int_t pos;
115    if ((pos = hostname.Index(".")) != kNPOS)
116       hostname.Remove(pos);
117
118    if (!FSHasSpace(fs)) {
119       while (1) {
120          fstoggle = !fstoggle;
121          fs = fstoggle ? fFS2 : fFS1;
122          if (FSHasSpace(fs)) break;
123          Info("GetFileName", "sleeping 30 seconds before retrying...");
124          gSystem->Sleep(30000);   // sleep for 30 seconds
125          if (fStop) return 0;
126       }
127    }
128
129    fname = fs + "/" + hostname + "_";
130    fname += dt.GetDate();
131    fname += "_";
132    fname += dt.GetTime();
133    fname += ".root";
134
135    fstoggle = !fstoggle;
136
137    return fname;
138 }
139
140 //______________________________________________________________________________
141 void AliRawDB::SetFS(const char* fs1, const char* fs2)
142 {
143 // set the file system location
144
145   fFS1 = fs1;
146   if (fs1 && !fFS1.Contains(":")) {
147     gSystem->ResetErrno();
148     gSystem->MakeDirectory(fs1);
149     if (gSystem->GetErrno() && gSystem->GetErrno() != EEXIST) {
150       SysError("SetFS", "mkdir %s", fs1);
151     }
152   }
153
154   fFS2 = fs2;
155   if (fs2) {
156     gSystem->ResetErrno();
157     gSystem->MakeDirectory(fs2);
158     if (gSystem->GetErrno() && gSystem->GetErrno() != EEXIST) {
159       SysError("SetFS", "mkdir %s", fs2);
160     }
161   }
162 }
163
164 //______________________________________________________________________________
165 Bool_t AliRawDB::Create(const char* fileName)
166 {
167    // Create a new raw DB.
168
169    const Int_t kMaxRetry = 1;
170    const Int_t kMaxSleep = 1;      // seconds
171    const Int_t kMaxSleepLong = 10; // seconds
172    Int_t retry = 0;
173
174 again:
175    if (fStop) return kFALSE;
176
177    const char *fname = fileName;
178    if (!fname) fname = GetFileName();
179    if (!fname) {
180       Error("Create", "error getting raw DB file name");
181       return kFALSE;
182    }
183
184    retry++;
185
186    fRawDB = TFile::Open(fname, GetOpenOption(),
187                         Form("ALICE raw-data file (%s)", GetAliRootTag()), fCompress,
188                         GetNetopt());
189    if (!fRawDB) {
190       if (retry < kMaxRetry) {
191          Warning("Create", "failure to open file, sleeping %d %s before retrying...",
192                  kMaxSleep, kMaxSleep==1 ? "second" : "seconds");
193          gSystem->Sleep(kMaxSleep*1000);
194          goto again;
195       }
196       Error("Create", "failure to open file %s after %d tries", fname, kMaxRetry);
197       return kFALSE;
198    }
199    if (retry > 1)
200       Warning("Create", "succeeded to open file after %d retries", retry);
201
202    if (fRawDB->IsZombie()) {
203       if (fRawDB->GetErrno() == ENOSPC ||
204           fRawDB->GetErrno() == 1018   ||   // SECOMERR
205           fRawDB->GetErrno() == 1027) {     // SESYSERR
206          fRawDB->ResetErrno();
207          delete fRawDB;
208          Warning("Create", "file is a zombie (no space), sleeping %d %s before retrying...",
209                  kMaxSleepLong, kMaxSleepLong==1 ? "second" : "seconds");
210          gSystem->Sleep(kMaxSleepLong*1000);   // sleep 10 seconds before retrying
211          goto again;
212       }
213       Error("Create", "file %s is zombie", fname);
214       fRawDB->ResetErrno();
215       delete fRawDB;
216       fRawDB = 0;
217       if (retry < kMaxRetry) {
218          Warning("Create", "file is a zombie, sleeping %d %s before retrying...",
219                  kMaxSleep, kMaxSleep==1 ? "second" : "seconds");
220          gSystem->Sleep(kMaxSleep*1000);
221          goto again;
222       }
223       Error("Create", "failure to open file %s after %d tries", fname, kMaxRetry);
224       return kFALSE;
225    }
226
227    // Create raw data TTree
228    MakeTree();
229
230    return kTRUE;
231 }
232
233 //______________________________________________________________________________
234 void AliRawDB::MakeTree()
235 {
236    // Create ROOT Tree object container.
237
238    fTree = new TTree("RAW", Form("ALICE raw-data tree (%s)", GetAliRootTag()));
239    fTree->SetAutoSave(2000000000);  // autosave when 2 Gbyte written
240
241    Int_t bufsize = 256000;
242    // splitting 29.6 MB/s, no splitting 35.3 MB/s on P4 2GHz 15k SCSI
243    //Int_t split   = 1;
244    Int_t split   = 0;
245    fTree->Branch("rawevent", "AliRawEvent", &fEvent, bufsize, split);
246
247    // Create tree which will contain the HLT ESD information
248
249    if (fESD) {
250      fESDTree = new TTree("esdTree", Form("ALICE HLT ESD tree (%s)", GetAliRootTag()));
251      fESDTree->SetAutoSave(2000000000);  // autosave when 2 Gbyte written
252      split   = 0;
253      fESDTree->Branch("ESD", "AliESD", &fESD, bufsize, split);
254    }
255
256 }
257
258 //______________________________________________________________________________
259 Int_t AliRawDB::Close()
260 {
261    // Close raw DB.
262    if (!fRawDB) return 0;
263
264    if (!fRawDB->IsOpen()) return 0;
265
266    fRawDB->cd();
267
268    // Write the tree.
269    Bool_t error = kFALSE;
270    if (fTree->Write() == 0)
271      error = kTRUE;
272    if (fESDTree)
273      if (fESDTree->Write() == 0)
274        error = kTRUE;
275
276    // Close DB, this also deletes the fTree
277    fRawDB->Close();
278
279    Int_t filesize = fRawDB->GetEND();
280
281    if (fDeleteFiles) {
282       gSystem->Unlink(fRawDB->GetName());
283       delete fRawDB;
284       fRawDB = 0;
285       if(!error)
286         return filesize;
287       else
288         return -1;
289    }
290
291    // Write a text file with file GUID
292    // in the specified folder
293    WriteGuidFile();
294
295    delete fRawDB;
296    fRawDB = 0;
297    if(!error)
298      return filesize;
299    else
300      return -1;
301 }
302
303 //______________________________________________________________________________
304 Int_t AliRawDB::Fill()
305 {
306    // Fill the trees and return the number of written bytes
307
308    Double_t bytes = fRawDB->GetBytesWritten();
309    Bool_t error = kFALSE;
310    if (fTree->Fill() == -1)
311      error = kTRUE;
312    if (fESDTree) 
313      if (fESDTree->Fill() == -1)
314        error = kTRUE;
315    if(!error)
316      return Int_t(fRawDB->GetBytesWritten() - bytes);
317    else
318      return -1;
319 }
320
321 //______________________________________________________________________________
322 Int_t AliRawDB::GetTotalSize()
323 {
324    // Return the total size of the trees
325   Int_t total = 0;
326
327   {
328     Int_t skey = 0;
329     TDirectory *dir = fTree->GetDirectory();
330     if (dir) {
331       TKey *key = dir->GetKey(fTree->GetName());
332       if (key) skey = key->GetKeylen();
333     }
334     total += skey;
335     if (fTree->GetZipBytes() > 0) total += fTree->GetTotBytes();
336 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,15,0)
337     TBufferFile b(TBuffer::kWrite,10000);
338 #else
339     TBuffer b(TBuffer::kWrite,10000);
340 #endif
341     TTree::Class()->WriteBuffer(b,fTree);
342     total += b.Length();
343   }
344
345   if(fESDTree)
346     {
347       Int_t skey = 0;
348       TDirectory *dir = fESDTree->GetDirectory();
349       if (dir) {
350         TKey *key = dir->GetKey(fESDTree->GetName());
351         if (key) skey = key->GetKeylen();
352       }
353       total += skey;
354       if (fESDTree->GetZipBytes() > 0) total += fESDTree->GetTotBytes();
355 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,15,0)
356       TBufferFile b(TBuffer::kWrite,10000);
357 #else
358       TBuffer b(TBuffer::kWrite,10000);
359 #endif
360       TTree::Class()->WriteBuffer(b,fESDTree);
361       total += b.Length();
362     }
363
364   return total;
365 }
366
367 //______________________________________________________________________________
368 void AliRawDB::WriteStats(AliStats* stats)
369 {
370    // Write stats to raw DB, local run DB and global MySQL DB.
371
372    AliRawEventHeaderBase &header = *GetEvent()->GetHeader();
373
374    // Write stats into RawDB
375    TDirectory *ds = gDirectory;
376    GetDB()->cd();
377    stats->SetEvents(GetEvents());
378    stats->SetLastId(header.GetP("Id")[0]);
379    stats->SetFileSize(GetBytesWritten());
380    stats->SetCompressionFactor(GetCompressionFactor());
381    stats->SetEndTime();
382    stats->Write("stats");
383    ds->cd();
384 }
385
386 //______________________________________________________________________________
387 Bool_t AliRawDB::NextFile(const char* fileName)
388 {
389    // Close te current file and open a new one.
390    // Returns kFALSE in case opening failed.
391
392    Close();
393
394    if (!Create(fileName)) return kFALSE;
395    return kTRUE;
396 }
397
398 //______________________________________________________________________________
399 Float_t AliRawDB::GetCompressionFactor() const
400 {
401    // Return compression factor.
402
403    if (fTree->GetZipBytes() == 0.)
404       return 1.0;
405    else
406       return fTree->GetTotBytes()/fTree->GetZipBytes();
407 }
408
409 //______________________________________________________________________________
410 const char *AliRawDB::GetAliRootTag()
411 {
412   // Return the aliroot tag (version)
413   // used to generate the raw data file.
414   // Stored in the raw-data file title.
415
416   TString version = fgkAliRootTag;
417   version.Remove(TString::kBoth,'$');
418   version.ReplaceAll("Name","AliRoot version");
419
420   return version.Data();
421 }
422
423 //______________________________________________________________________________
424 void AliRawDB::WriteGuidFile()
425 {
426   // Write the guid file
427   // in the specified folder
428
429    TString guidFileName;
430    if (fGuidFileFolder) {
431      guidFileName = fGuidFileFolder;
432
433      TString pathStr = fRawDB->GetName();
434      TObjArray *pathArr = pathStr.Tokenize('/');
435      guidFileName.Append("/");
436      guidFileName.Append(((TObjString *)pathArr->Last())->String());
437      pathArr->Delete();
438      delete pathArr;
439    }
440    else
441      guidFileName = fRawDB->GetName();
442
443    guidFileName += ".guid";
444
445    ofstream fguid(guidFileName.Data());
446    TString guid = fRawDB->GetUUID().AsString();
447    fguid << "guid: \t" << guid.Data();
448    fguid.close();
449 }