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