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