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