]>
Commit | Line | Data |
---|---|---|
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 | } |