28a128e5adfc010c244c1c8badb9c3a1cc56cc20
[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 "AliStats.h"
36 #include "AliMDC.h"
37
38 #ifdef USE_HLT
39 #include "AliESD.h"
40 #endif
41
42 #include "AliRawDB.h"
43
44
45 ClassImp(AliRawDB)
46
47
48 //______________________________________________________________________________
49 AliRawDB::AliRawDB(AliRawEvent *event,
50 #ifdef USE_HLT
51                    AliESD *esd, 
52 #endif
53                    Double_t maxsize, Int_t compress,
54                    Bool_t create)
55 {
56    // Create a new raw DB containing at most maxsize bytes.
57
58    fEvent    = event;
59    fESD      = esd;
60    fMaxSize  = maxsize;
61    fCompress = compress;
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 (create) {
73       if (!Create())
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 ? AliMDC::RawDBFS(1) : AliMDC::RawDBFS(0);
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 ? AliMDC::RawDBFS(1) : AliMDC::RawDBFS(0);
140          if (FSHasSpace(fs)) break;
141          Info("GetFileName", "sleeping 30 seconds before retrying...");
142          gSystem->Sleep(30000);   // sleep for 30 seconds
143          if (AliMDC::Instance() && AliMDC::Instance()->StopLoop())
144             return 0;
145       }
146    }
147
148    fname = fs + "/" + hostname + "_";
149    fname += dt.GetDate();
150    fname += "_";
151    fname += dt.GetTime();
152    fname += ".root";
153
154    fstoggle = !fstoggle;
155
156    return fname;
157 }
158
159 //______________________________________________________________________________
160 Bool_t AliRawDB::Create()
161 {
162    // Create a new raw DB.
163
164    const Int_t kMaxRetry = 200;
165    const Int_t kMaxSleep = 1;      // seconds
166    const Int_t kMaxSleepLong = 10; // seconds
167    Int_t retry = 0;
168
169 again:
170    if (AliMDC::Instance() && AliMDC::Instance()->StopLoop())
171       return kFALSE;
172
173    const char *fname = GetFileName();
174    if (!fname) {
175       Error("Create", "error getting raw DB file name");
176       return kFALSE;
177    }
178
179    retry++;
180
181    fRawDB = TFile::Open(fname, GetOpenOption(),
182                         Form("ALICE MDC%d raw DB", AliMDC::kMDC), fCompress,
183                         GetNetopt());
184    if (!fRawDB) {
185       if (retry < kMaxRetry) {
186          Warning("Create", "failure to open file, sleeping %d %s before retrying...",
187                  kMaxSleep, kMaxSleep==1 ? "second" : "seconds");
188          gSystem->Sleep(kMaxSleep*1000);
189          goto again;
190       }
191       Error("Create", "failure to open file %s after %d tries", fname, kMaxRetry);
192       return kFALSE;
193    }
194    if (retry > 1)
195       Warning("Create", "succeeded to open file after %d retries", retry);
196
197    if (fRawDB->IsZombie()) {
198       if (fRawDB->GetErrno() == ENOSPC ||
199           fRawDB->GetErrno() == 1018   ||   // SECOMERR
200           fRawDB->GetErrno() == 1027) {     // SESYSERR
201          fRawDB->ResetErrno();
202          delete fRawDB;
203          Warning("Create", "file is a zombie (no space), sleeping %d %s before retrying...",
204                  kMaxSleepLong, kMaxSleepLong==1 ? "second" : "seconds");
205          gSystem->Sleep(kMaxSleepLong*1000);   // sleep 10 seconds before retrying
206          goto again;
207       }
208       Error("Create", "file %s is zombie", fname);
209       fRawDB->ResetErrno();
210       delete fRawDB;
211       fRawDB = 0;
212       if (retry < kMaxRetry) {
213          Warning("Create", "file is a zombie, sleeping %d %s before retrying...",
214                  kMaxSleep, kMaxSleep==1 ? "second" : "seconds");
215          gSystem->Sleep(kMaxSleep*1000);
216          goto again;
217       }
218       Error("Create", "failure to open file %s after %d tries", fname, kMaxRetry);
219       return kFALSE;
220    }
221
222    // Create raw data TTree
223    MakeTree();
224
225    return kTRUE;
226 }
227
228 //______________________________________________________________________________
229 void AliRawDB::MakeTree()
230 {
231    // Create ROOT Tree object container.
232
233    fTree = new TTree("RAW", Form("ALICE MDC%d raw data tree", AliMDC::kMDC));
234    fTree->SetAutoSave(2000000000);  // autosave when 2 Gbyte written
235
236    Int_t bufsize = 256000;
237    // splitting 29.6 MB/s, no splitting 35.3 MB/s on P4 2GHz 15k SCSI
238    //Int_t split   = 1;
239    Int_t split   = 0;
240    fTree->Branch("rawevent", "AliRawEvent", &fEvent, bufsize, split);
241
242 #ifdef USE_HLT
243    // Create tree which will contain the HLT ESD information
244
245    fESDTree = new TTree("esdTree", Form("ALICE MDC%d HLT ESD tree", AliMDC::kMDC));
246    fESDTree->SetAutoSave(2000000000);  // autosave when 2 Gbyte written
247    split   = 99;
248    fESDTree->Branch("ESD", "AliESD", &fESD, bufsize, split);
249 #endif
250
251 }
252
253 //______________________________________________________________________________
254 void AliRawDB::Close()
255 {
256    // Close raw DB.
257
258    if (!fRawDB) return;
259
260    fRawDB->cd();
261
262    // Write the tree.
263    fTree->Write();
264    fESDTree->Write();
265
266    // Close DB, this also deletes the fTree
267    fRawDB->Close();
268
269    if (AliMDC::DeleteFiles()) {
270       gSystem->Unlink(fRawDB->GetName());
271       delete fRawDB;
272       fRawDB = 0;
273       return;
274    }
275
276    // Create semaphore to say this file is finished
277    Int_t tfd = ::creat(Form("%s.done", fRawDB->GetName()), 0644);
278    close(tfd);
279
280    delete fRawDB;
281    fRawDB = 0;
282 }
283
284 //______________________________________________________________________________
285 void AliRawDB::WriteStats(AliStats* stats)
286 {
287    // Write stats to raw DB, local run DB and global MySQL DB.
288
289    AliRawEventHeader &header = *GetEvent()->GetHeader();
290
291    // Write stats into RawDB
292    TDirectory *ds = gDirectory;
293    GetDB()->cd();
294    stats->SetEvents(GetEvents());
295    stats->SetLastId(header.GetRunNumber(), header.GetEventInRun());
296    stats->SetFileSize(GetBytesWritten());
297    stats->SetCompressionFactor(GetCompressionFactor());
298    stats->SetEndTime();
299    stats->Write("stats");
300    ds->cd();
301 }
302
303 //______________________________________________________________________________
304 Bool_t AliRawDB::NextFile()
305 {
306    // Close te current file and open a new one.
307    // Returns kFALSE in case opening failed.
308
309    Close();
310
311    if (!Create()) return kFALSE;
312    return kTRUE;
313 }
314
315 //______________________________________________________________________________
316 Float_t AliRawDB::GetCompressionFactor() const
317 {
318    // Return compression factor.
319
320    if (fTree->GetZipBytes() == 0.)
321       return 1.0;
322    else
323       return fTree->GetTotBytes()/fTree->GetZipBytes();
324 }