508cd71aa59774457c76c7cf0d93ea2397d4a472
[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 "AliRawEvent.h"
34 #include "AliRawEventHeader.h"
35 #include "AliMDC.h"
36
37 #include "AliRawDB.h"
38
39
40 ClassImp(AliRawDB)
41
42
43 //______________________________________________________________________________
44 AliRawDB::AliRawDB(AliRawEvent *event, Double_t maxsize, Int_t compress,
45                    Bool_t create)
46 {
47    // Create a new raw DB containing at most maxsize bytes.
48
49    fEvent    = event;
50    fMaxSize  = maxsize;
51    fCompress = compress;
52
53    // Consistency check with DATE header file
54 #ifdef ALI_DATE
55    if (fEvent->GetHeader()->HeaderSize() != EVENT_HEAD_BASE_SIZE) {
56       Error("AliRawDB", "inconsistency between DATE and AliRawEvent headers");
57       MakeZombie();
58       return;
59    }
60 #endif
61
62    if (create) {
63       if (!Create())
64          MakeZombie();
65    }
66 }
67
68 //______________________________________________________________________________
69 AliRawDB::AliRawDB(const AliRawDB& rawDB): TObject(rawDB)
70 {
71 // copy constructor
72
73   Fatal("AliRawDB", "copy constructor not implemented");
74 }
75
76 //______________________________________________________________________________
77 AliRawDB& AliRawDB::operator = (const AliRawDB& /*rawDB*/)
78 {
79 // assignment operator
80
81   Fatal("operator =", "assignment operator not implemented");
82   return *this;
83 }
84
85 //______________________________________________________________________________
86 Bool_t AliRawDB::FSHasSpace(const char *fs) const
87 {
88    // Check for at least fMaxSize bytes of free space on the file system.
89    // If the space is not available return kFALSE, kTRUE otherwise.
90
91    Long_t id, bsize, blocks, bfree;
92
93    if (gSystem->GetFsInfo(fs, &id, &bsize, &blocks, &bfree) == 1) {
94       Error("FSHasSpace", "could not stat file system %s", fs);
95       return kFALSE;
96    }
97
98    // Leave 5 percent of diskspace free
99    Double_t avail = Double_t(bfree) * 0.95;
100    if (avail*bsize > fMaxSize)
101       return kTRUE;
102
103    Warning("FSHasSpace", "no space on file system %s", fs);
104    return kFALSE;
105 }
106
107 //______________________________________________________________________________
108 const char *AliRawDB::GetFileName() const
109 {
110    // Return filename based on hostname and date and time. This will make
111    // each file unique. Also makes sure (via FSHasSpace()) that there is
112    // enough space on the file system to store the file. Returns 0 in
113    // case of error or interrupt signal.
114
115    static TString fname;
116    static Bool_t  fstoggle = kFALSE;
117
118    TString fs = fstoggle ? AliMDC::RawDBFS(1) : AliMDC::RawDBFS(0);
119    TDatime dt;
120
121    TString hostname = gSystem->HostName();
122    Int_t pos;
123    if ((pos = hostname.Index(".")) != kNPOS)
124       hostname.Remove(pos);
125
126    if (!FSHasSpace(fs)) {
127       while (1) {
128          fstoggle = !fstoggle;
129          fs = fstoggle ? AliMDC::RawDBFS(1) : AliMDC::RawDBFS(0);
130          if (FSHasSpace(fs)) break;
131          Info("GetFileName", "sleeping 30 seconds before retrying...");
132          gSystem->Sleep(30000);   // sleep for 30 seconds
133          if (AliMDC::Instance() && AliMDC::Instance()->StopLoop())
134             return 0;
135       }
136    }
137
138    fname = fs + "/" + hostname + "_";
139    fname += dt.GetDate();
140    fname += "_";
141    fname += dt.GetTime();
142    fname += ".root";
143
144    fstoggle = !fstoggle;
145
146    return fname;
147 }
148
149 //______________________________________________________________________________
150 Bool_t AliRawDB::Create()
151 {
152    // Create a new raw DB.
153
154    const Int_t kMaxRetry = 200;
155    const Int_t kMaxSleep = 1;      // seconds
156    const Int_t kMaxSleepLong = 10; // seconds
157    Int_t retry = 0;
158
159 again:
160    if (AliMDC::Instance() && AliMDC::Instance()->StopLoop())
161       return kFALSE;
162
163    const char *fname = GetFileName();
164    if (!fname) {
165       Error("Create", "error getting raw DB file name");
166       return kFALSE;
167    }
168
169    retry++;
170
171    fRawDB = TFile::Open(fname, GetOpenOption(),
172                         Form("ALICE MDC%d raw DB", AliMDC::kMDC), fCompress,
173                         GetNetopt());
174    if (!fRawDB) {
175       if (retry < kMaxRetry) {
176          Warning("Create", "failure to open file, sleeping %d %s before retrying...",
177                  kMaxSleep, kMaxSleep==1 ? "second" : "seconds");
178          gSystem->Sleep(kMaxSleep*1000);
179          goto again;
180       }
181       Error("Create", "failure to open file %s after %d tries", fname, kMaxRetry);
182       return kFALSE;
183    }
184    if (retry > 1)
185       Warning("Create", "succeeded to open file after %d retries", retry);
186
187    if (fRawDB->IsZombie()) {
188       if (fRawDB->GetErrno() == ENOSPC ||
189           fRawDB->GetErrno() == 1018   ||   // SECOMERR
190           fRawDB->GetErrno() == 1027) {     // SESYSERR
191          fRawDB->ResetErrno();
192          delete fRawDB;
193          Warning("Create", "file is a zombie (no space), sleeping %d %s before retrying...",
194                  kMaxSleepLong, kMaxSleepLong==1 ? "second" : "seconds");
195          gSystem->Sleep(kMaxSleepLong*1000);   // sleep 10 seconds before retrying
196          goto again;
197       }
198       Error("Create", "file %s is zombie", fname);
199       fRawDB->ResetErrno();
200       delete fRawDB;
201       fRawDB = 0;
202       if (retry < kMaxRetry) {
203          Warning("Create", "file is a zombie, sleeping %d %s before retrying...",
204                  kMaxSleep, kMaxSleep==1 ? "second" : "seconds");
205          gSystem->Sleep(kMaxSleep*1000);
206          goto again;
207       }
208       Error("Create", "failure to open file %s after %d tries", fname, kMaxRetry);
209       return kFALSE;
210    }
211
212    // Create raw data TTree
213    MakeTree();
214
215    return kTRUE;
216 }
217
218 //______________________________________________________________________________
219 void AliRawDB::MakeTree()
220 {
221    // Create ROOT Tree object container.
222
223    fTree = new TTree("RAW", Form("ALICE MDC%d raw data tree", AliMDC::kMDC));
224    fTree->SetAutoSave(2000000000);  // autosave when 2 Gbyte written
225
226    Int_t bufsize = 256000;
227    // splitting 29.6 MB/s, no splitting 35.3 MB/s on P4 2GHz 15k SCSI
228    //Int_t split   = 1;
229    Int_t split   = 0;
230    fTree->Branch("rawevent", "AliRawEvent", &fEvent, bufsize, split);
231 }
232
233 //______________________________________________________________________________
234 void AliRawDB::Close()
235 {
236    // Close raw DB.
237
238    if (!fRawDB) return;
239
240    fRawDB->cd();
241
242    // Write the tree.
243    fTree->Write();
244
245    // Close DB, this also deletes the fTree
246    fRawDB->Close();
247
248    if (AliMDC::DeleteFiles()) {
249       gSystem->Unlink(fRawDB->GetName());
250       delete fRawDB;
251       fRawDB = 0;
252       return;
253    }
254
255    // Create semaphore to say this file is finished
256    Int_t tfd = ::creat(Form("%s.done", fRawDB->GetName()), 0644);
257    close(tfd);
258
259    delete fRawDB;
260    fRawDB = 0;
261 }
262
263 //______________________________________________________________________________
264 Bool_t AliRawDB::NextFile()
265 {
266    // Close te current file and open a new one.
267    // Returns kFALSE in case opening failed.
268
269    Close();
270
271    if (!Create()) return kFALSE;
272    return kTRUE;
273 }
274
275 //______________________________________________________________________________
276 Float_t AliRawDB::GetCompressionFactor() const
277 {
278    // Return compression factor.
279
280    if (fTree->GetZipBytes() == 0.)
281       return 1.0;
282    else
283       return fTree->GetTotBytes()/fTree->GetZipBytes();
284 }