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