]> git.uio.no Git - u/mrichter/AliRoot.git/blob - RAW/AliRawDB.cxx
Put index into track's name instead of its label.
[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 #include <Riostream.h>
27
28 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,15,0)
29 #include <TBufferFile.h>
30 #else
31 #include <TBuffer.h>
32 #endif
33
34 #include <TSystem.h>
35 #include <TKey.h>
36
37 #include <TObjString.h>
38
39 #include "AliESDEvent.h"
40 #include "AliRawEvent.h"
41 #include "AliRawDataArray.h"
42 #include "AliRawEventHeaderBase.h"
43 #include "AliRawEquipment.h"
44 #include "AliRawEquipmentHeader.h"
45 #include "AliStats.h"
46
47 #include "AliRawDB.h"
48
49
50 ClassImp(AliRawDB)
51
52 const char *AliRawDB::fgkAliRootTag = "$Name$";
53
54 //______________________________________________________________________________
55 AliRawDB::AliRawDB(AliRawEvent *event,
56                    AliESDEvent *esd, 
57                    Int_t compress,
58                    const char* fileName) :
59   fRawDB(NULL),
60   fTree(NULL),
61   fEvent(event),
62   fESDTree(NULL),
63   fESD(esd),
64   fCompress(compress),
65   fMaxSize(-1),
66   fFS1(""),
67   fFS2(""),
68   fDeleteFiles(kFALSE),
69   fStop(kFALSE)
70 {
71    // Create a new raw DB
72
73   for (Int_t iDet = 0; iDet < AliDAQ::kNDetectors; iDet++)
74     fDetRawData[iDet] = new AliRawDataArray(AliDAQ::NumberOfDdls(iDet));
75
76   fDetRawData[AliDAQ::kNDetectors] = new AliRawDataArray(100);
77
78    if (fileName) {
79       if (!Create(fileName))
80          MakeZombie();
81    }
82 }
83
84
85 //______________________________________________________________________________
86 AliRawDB::~AliRawDB() {
87   // Destructor
88
89   if(Close()==-1) Error("~AliRawDB", "cannot close output file!");
90
91   for (Int_t iDet = 0; iDet < (AliDAQ::kNDetectors + 1); iDet++)
92     delete fDetRawData[iDet];
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 ? fFS2 : fFS1;
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 ? fFS2 : fFS1;
140          if (FSHasSpace(fs)) break;
141          Info("GetFileName", "sleeping 30 seconds before retrying...");
142          gSystem->Sleep(30000);   // sleep for 30 seconds
143          if (fStop) 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 void AliRawDB::SetFS(const char* fs1, const char* fs2)
160 {
161 // set the file system location
162
163   fFS1 = fs1;
164   if (fs1 && !fFS1.Contains(":")) {
165     gSystem->ResetErrno();
166     gSystem->MakeDirectory(fs1);
167     if (gSystem->GetErrno() && gSystem->GetErrno() != EEXIST) {
168       SysError("SetFS", "mkdir %s", fs1);
169     }
170   }
171
172   fFS2 = fs2;
173   if (fs2) {
174     gSystem->ResetErrno();
175     gSystem->MakeDirectory(fs2);
176     if (gSystem->GetErrno() && gSystem->GetErrno() != EEXIST) {
177       SysError("SetFS", "mkdir %s", fs2);
178     }
179   }
180 }
181
182 //______________________________________________________________________________
183 Bool_t AliRawDB::Create(const char* fileName)
184 {
185    // Create a new raw DB.
186
187    const Int_t kMaxRetry = 1;
188    const Int_t kMaxSleep = 1;      // seconds
189    const Int_t kMaxSleepLong = 10; // seconds
190    Int_t retry = 0;
191
192 again:
193    if (fStop) return kFALSE;
194
195    const char *fname = fileName;
196    if (!fname) fname = GetFileName();
197    if (!fname) {
198       Error("Create", "error getting raw DB file name");
199       return kFALSE;
200    }
201
202    retry++;
203
204    fRawDB = TFile::Open(fname, GetOpenOption(),
205                         Form("ALICE raw-data file (%s)", GetAliRootTag()), fCompress,
206                         GetNetopt());
207    if (!fRawDB) {
208       if (retry < kMaxRetry) {
209          Warning("Create", "failure to open file, sleeping %d %s before retrying...",
210                  kMaxSleep, kMaxSleep==1 ? "second" : "seconds");
211          gSystem->Sleep(kMaxSleep*1000);
212          goto again;
213       }
214       Error("Create", "failure to open file %s after %d tries", fname, kMaxRetry);
215       return kFALSE;
216    }
217    if (retry > 1)
218       Warning("Create", "succeeded to open file after %d retries", retry);
219
220    if (fRawDB->IsZombie()) {
221       if (fRawDB->GetErrno() == ENOSPC ||
222           fRawDB->GetErrno() == 1018   ||   // SECOMERR
223           fRawDB->GetErrno() == 1027) {     // SESYSERR
224          fRawDB->ResetErrno();
225          delete fRawDB;
226          Warning("Create", "file is a zombie (no space), sleeping %d %s before retrying...",
227                  kMaxSleepLong, kMaxSleepLong==1 ? "second" : "seconds");
228          gSystem->Sleep(kMaxSleepLong*1000);   // sleep 10 seconds before retrying
229          goto again;
230       }
231       Error("Create", "file %s is zombie", fname);
232       fRawDB->ResetErrno();
233       delete fRawDB;
234       fRawDB = 0;
235       if (retry < kMaxRetry) {
236          Warning("Create", "file is a zombie, sleeping %d %s before retrying...",
237                  kMaxSleep, kMaxSleep==1 ? "second" : "seconds");
238          gSystem->Sleep(kMaxSleep*1000);
239          goto again;
240       }
241       Error("Create", "failure to open file %s after %d tries", fname, kMaxRetry);
242       return kFALSE;
243    }
244
245    // Create raw data TTree
246    MakeTree();
247
248    return kTRUE;
249 }
250
251 //______________________________________________________________________________
252 void AliRawDB::MakeTree()
253 {
254    // Create ROOT Tree object container.
255
256    fTree = new TTree("RAW", Form("ALICE raw-data tree (%s)", GetAliRootTag()));
257    fTree->SetAutoSave(2000000000);  // autosave when 2 Gbyte written
258
259    fTree->BranchRef();
260
261    Int_t bufsize = 256000;
262    // splitting 29.6 MB/s, no splitting 35.3 MB/s on P4 2GHz 15k SCSI
263    //Int_t split   = 1;
264    Int_t split   = 0;
265    fTree->Branch("rawevent", "AliRawEvent", &fEvent, bufsize, split);
266
267    // Make brach for each sub-detector
268    for (Int_t iDet = 0; iDet < AliDAQ::kNDetectors; iDet++) {
269      fTree->Branch(AliDAQ::DetectorName(iDet),"AliRawDataArray",
270                    &fDetRawData[iDet],bufsize,split);
271    }
272    // Make special branch for unrecognized raw-data payloads
273    fTree->Branch("Common","AliRawDataArray",
274                    &fDetRawData[AliDAQ::kNDetectors],bufsize,split);
275
276    // Create tree which will contain the HLT ESD information
277
278    if (fESD) {
279      fESDTree = new TTree("esdTree", Form("ALICE HLT ESD tree (%s)", GetAliRootTag()));
280      fESDTree->SetAutoSave(2000000000);  // autosave when 2 Gbyte written
281      split   = 0;
282      fESDTree->Branch("ESD", "AliESDEvent", &fESD, bufsize, split);
283    }
284
285 }
286
287 //______________________________________________________________________________
288 Int_t AliRawDB::Close()
289 {
290    // Close raw DB.
291    if (!fRawDB) return 0;
292
293    if (!fRawDB->IsOpen()) return 0;
294
295    fRawDB->cd();
296
297    // Write the tree.
298    Bool_t error = kFALSE;
299    if (fTree->Write() == 0)
300      error = kTRUE;
301    if (fESDTree)
302      if (fESDTree->Write() == 0)
303        error = kTRUE;
304
305    // Close DB, this also deletes the fTree
306    fRawDB->Close();
307
308    Int_t filesize = fRawDB->GetEND();
309
310    if (fDeleteFiles) {
311       gSystem->Unlink(fRawDB->GetName());
312       delete fRawDB;
313       fRawDB = 0;
314       if(!error)
315         return filesize;
316       else
317         return -1;
318    }
319
320    delete fRawDB;
321    fRawDB = 0;
322    if(!error)
323      return filesize;
324    else
325      return -1;
326 }
327
328 //______________________________________________________________________________
329 Int_t AliRawDB::Fill()
330 {
331    // Fill the trees and return the number of written bytes
332
333   for (Int_t iDet = 0; iDet < (AliDAQ::kNDetectors + 1); iDet++)
334     fDetRawData[iDet]->ClearData();
335
336    // Move the raw-data payloads to the corresponding branches
337   for(Int_t iSubEvent = 0; iSubEvent < fEvent->GetNSubEvents(); iSubEvent++) {
338     AliRawEvent *subEvent = fEvent->GetSubEvent(iSubEvent);
339     for(Int_t iEquipment = 0; iEquipment < subEvent->GetNEquipments(); iEquipment++) {
340       AliRawEquipment *equipment = subEvent->GetEquipment(iEquipment);
341       UInt_t eqId = equipment->GetEquipmentHeader()->GetId();
342       Int_t ddlIndex;
343       Int_t iDet = AliDAQ::DetectorIDFromDdlID(eqId,ddlIndex);
344       if (iDet < 0 || iDet > AliDAQ::kNDetectors)
345         iDet = AliDAQ::kNDetectors;
346       equipment->SetRawDataRef(fDetRawData[iDet]);
347     }
348   }
349
350    Double_t bytes = fRawDB->GetBytesWritten();
351    Bool_t error = kFALSE;
352    if (fTree->Fill() == -1)
353      error = kTRUE;
354    if (fESDTree) 
355      if (fESDTree->Fill() == -1)
356        error = kTRUE;
357    if(!error)
358      return Int_t(fRawDB->GetBytesWritten() - bytes);
359    else
360      return -1;
361 }
362
363 //______________________________________________________________________________
364 Int_t AliRawDB::GetTotalSize()
365 {
366    // Return the total size of the trees
367   Int_t total = 0;
368
369   {
370     Int_t skey = 0;
371     TDirectory *dir = fTree->GetDirectory();
372     if (dir) {
373       TKey *key = dir->GetKey(fTree->GetName());
374       if (key) skey = key->GetKeylen();
375     }
376     total += skey + fTree->GetZipBytes();
377   }
378
379   if(fESDTree)
380     {
381       Int_t skey = 0;
382       TDirectory *dir = fESDTree->GetDirectory();
383       if (dir) {
384         TKey *key = dir->GetKey(fESDTree->GetName());
385         if (key) skey = key->GetKeylen();
386       }
387       total += skey + fESDTree->GetZipBytes();
388     }
389
390   return total;
391 }
392
393 //______________________________________________________________________________
394 void AliRawDB::WriteStats(AliStats* stats)
395 {
396    // Write stats to raw DB, local run DB and global MySQL DB.
397
398    AliRawEventHeaderBase &header = *GetEvent()->GetHeader();
399
400    // Write stats into RawDB
401    TDirectory *ds = gDirectory;
402    GetDB()->cd();
403    stats->SetEvents(GetEvents());
404    stats->SetLastId(header.GetP("Id")[0]);
405    stats->SetFileSize(GetBytesWritten());
406    stats->SetCompressionFactor(GetCompressionFactor());
407    stats->SetEndTime();
408    stats->Write("stats");
409    ds->cd();
410 }
411
412 //______________________________________________________________________________
413 Bool_t AliRawDB::NextFile(const char* fileName)
414 {
415    // Close te current file and open a new one.
416    // Returns kFALSE in case opening failed.
417
418    Close();
419
420    if (!Create(fileName)) return kFALSE;
421    return kTRUE;
422 }
423
424 //______________________________________________________________________________
425 Float_t AliRawDB::GetCompressionFactor() const
426 {
427    // Return compression factor.
428
429    if (fTree->GetZipBytes() == 0.)
430       return 1.0;
431    else
432       return fTree->GetTotBytes()/fTree->GetZipBytes();
433 }
434
435 //______________________________________________________________________________
436 const char *AliRawDB::GetAliRootTag()
437 {
438   // Return the aliroot tag (version)
439   // used to generate the raw data file.
440   // Stored in the raw-data file title.
441
442   TString version = fgkAliRootTag;
443   version.Remove(TString::kBoth,'$');
444   version.ReplaceAll("Name","AliRoot version");
445
446   return version.Data();
447 }
448
449 //______________________________________________________________________________
450 Bool_t AliRawDB::WriteGuidFile(TString &guidFileFolder)
451 {
452   // Write the guid file
453   // in the specified folder or
454   // in the folder where the raw data
455   // file is.
456
457    TString guidFileName;
458    if (!guidFileFolder.IsNull()) {
459      guidFileName = guidFileFolder;
460
461      TString pathStr = fRawDB->GetName();
462      TObjArray *pathArr = pathStr.Tokenize('/');
463      guidFileName.Append("/");
464      guidFileName.Append(((TObjString *)pathArr->Last())->String());
465      pathArr->Delete();
466      delete pathArr;
467    }
468    else
469      guidFileName = fRawDB->GetName();
470
471    guidFileName += ".guid";
472
473    ofstream fguid(guidFileName.Data());
474    if (!fguid.is_open()) {
475      Error("WriteGuidFile", "failure to open guid file %s", guidFileName.Data());
476      return kFALSE;
477    }
478    TString guid = fRawDB->GetUUID().AsString();
479    fguid << "guid: \t" << guid.Data();
480    fguid.close();
481
482    return kTRUE;
483 }