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