Fix for the false error message about an invalid equipment ID. It was coming in case...
[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 = "$Rev$";
53
54 // Split TPC into 9 branches in order to avoid problems with big memory
55 // consumption in case of TPC events w/o zero-suppression
56 Int_t AliRawDB::fgkDetBranches[AliDAQ::kNDetectors+1] = {1,1,1,18,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,10,1};
57
58 //______________________________________________________________________________
59 AliRawDB::AliRawDB(AliRawEvent *event,
60                    AliESDEvent *esd, 
61                    Int_t compress,
62                    const char* fileName) :
63   fRawDB(NULL),
64   fTree(NULL),
65   fEvent(event),
66   fESDTree(NULL),
67   fESD(esd),
68   fCompress(compress),
69   fMaxSize(-1),
70   fFS1(""),
71   fFS2(""),
72   fDeleteFiles(kFALSE),
73   fStop(kFALSE)
74 {
75    // Create a new raw DB
76
77   for (Int_t iDet = 0; iDet < AliDAQ::kNDetectors; iDet++) {
78     fDetRawData[iDet] = new AliRawDataArray*[fgkDetBranches[iDet]];
79     Int_t nDDLsPerBranch = AliDAQ::NumberOfDdls(iDet)/fgkDetBranches[iDet];
80     for (Int_t iBranch = 0; iBranch < fgkDetBranches[iDet]; iBranch++)
81       fDetRawData[iDet][iBranch] = new AliRawDataArray(nDDLsPerBranch);
82   }
83
84   fDetRawData[AliDAQ::kNDetectors] = new AliRawDataArray*[fgkDetBranches[AliDAQ::kNDetectors]];
85   for (Int_t iBranch = 0; iBranch < fgkDetBranches[AliDAQ::kNDetectors]; iBranch++)
86     fDetRawData[AliDAQ::kNDetectors][iBranch] = new AliRawDataArray(100);
87
88    if (fileName) {
89       if (!Create(fileName))
90          MakeZombie();
91    }
92 }
93
94
95 //______________________________________________________________________________
96 AliRawDB::~AliRawDB() {
97   // Destructor
98
99   if(Close()==-1) Error("~AliRawDB", "cannot close output file!");
100
101   for (Int_t iDet = 0; iDet < (AliDAQ::kNDetectors + 1); iDet++) {
102     for (Int_t iBranch = 0; iBranch < fgkDetBranches[iDet]; iBranch++)
103       delete fDetRawData[iDet][iBranch];
104     delete [] fDetRawData[iDet];
105   }
106 }
107
108 //______________________________________________________________________________
109 Bool_t AliRawDB::FSHasSpace(const char *fs) const
110 {
111    // Check for at least fMaxSize bytes of free space on the file system.
112    // If the space is not available return kFALSE, kTRUE otherwise.
113
114    Long_t id, bsize, blocks, bfree;
115
116    if (gSystem->GetFsInfo(fs, &id, &bsize, &blocks, &bfree) == 1) {
117       Error("FSHasSpace", "could not stat file system %s", fs);
118       return kFALSE;
119    }
120
121    // Leave 5 percent of diskspace free
122    Double_t avail = Double_t(bfree) * 0.95;
123    if (avail*bsize > fMaxSize)
124       return kTRUE;
125
126    Warning("FSHasSpace", "no space on file system %s", fs);
127    return kFALSE;
128 }
129
130 //______________________________________________________________________________
131 const char *AliRawDB::GetFileName() const
132 {
133    // Return filename based on hostname and date and time. This will make
134    // each file unique. Also makes sure (via FSHasSpace()) that there is
135    // enough space on the file system to store the file. Returns 0 in
136    // case of error or interrupt signal.
137
138    static TString fname;
139    static Bool_t  fstoggle = kFALSE;
140
141    TString fs = fstoggle ? fFS2 : fFS1;
142    TDatime dt;
143
144    TString hostname = gSystem->HostName();
145    Int_t pos;
146    if ((pos = hostname.Index(".")) != kNPOS)
147       hostname.Remove(pos);
148
149    if (!FSHasSpace(fs)) {
150       while (1) {
151          fstoggle = !fstoggle;
152          fs = fstoggle ? fFS2 : fFS1;
153          if (FSHasSpace(fs)) break;
154          Info("GetFileName", "sleeping 30 seconds before retrying...");
155          gSystem->Sleep(30000);   // sleep for 30 seconds
156          if (fStop) return 0;
157       }
158    }
159
160    fname = fs + "/" + hostname + "_";
161    fname += dt.GetDate();
162    fname += "_";
163    fname += dt.GetTime();
164    fname += ".root";
165
166    fstoggle = !fstoggle;
167
168    return fname;
169 }
170
171 //______________________________________________________________________________
172 void AliRawDB::SetFS(const char* fs1, const char* fs2)
173 {
174 // set the file system location
175
176   fFS1 = fs1;
177   if (fs1 && !fFS1.Contains(":")) {
178     gSystem->ResetErrno();
179     gSystem->MakeDirectory(fs1);
180     if (gSystem->GetErrno() && gSystem->GetErrno() != EEXIST) {
181       SysError("SetFS", "mkdir %s", fs1);
182     }
183   }
184
185   fFS2 = fs2;
186   if (fs2) {
187     gSystem->ResetErrno();
188     gSystem->MakeDirectory(fs2);
189     if (gSystem->GetErrno() && gSystem->GetErrno() != EEXIST) {
190       SysError("SetFS", "mkdir %s", fs2);
191     }
192   }
193 }
194
195 //______________________________________________________________________________
196 Bool_t AliRawDB::Create(const char* fileName)
197 {
198    // Create a new raw DB.
199
200    const Int_t kMaxRetry = 1;
201    const Int_t kMaxSleep = 1;      // seconds
202    const Int_t kMaxSleepLong = 10; // seconds
203    Int_t retry = 0;
204
205 again:
206    if (fStop) return kFALSE;
207
208    const char *fname = fileName;
209    if (!fname) fname = GetFileName();
210    if (!fname) {
211       Error("Create", "error getting raw DB file name");
212       return kFALSE;
213    }
214
215    retry++;
216
217    fRawDB = TFile::Open(fname, GetOpenOption(),
218                         Form("ALICE raw-data file (%s)", GetAliRootTag()), fCompress,
219                         GetNetopt());
220    if (!fRawDB) {
221       if (retry < kMaxRetry) {
222          Warning("Create", "failure to open file, sleeping %d %s before retrying...",
223                  kMaxSleep, kMaxSleep==1 ? "second" : "seconds");
224          gSystem->Sleep(kMaxSleep*1000);
225          goto again;
226       }
227       Error("Create", "failure to open file %s after %d tries", fname, kMaxRetry);
228       return kFALSE;
229    }
230    if (retry > 1)
231       Warning("Create", "succeeded to open file after %d retries", retry);
232
233    if (fRawDB->IsZombie()) {
234       if (fRawDB->GetErrno() == ENOSPC ||
235           fRawDB->GetErrno() == 1018   ||   // SECOMERR
236           fRawDB->GetErrno() == 1027) {     // SESYSERR
237          fRawDB->ResetErrno();
238          delete fRawDB;
239          Warning("Create", "file is a zombie (no space), sleeping %d %s before retrying...",
240                  kMaxSleepLong, kMaxSleepLong==1 ? "second" : "seconds");
241          gSystem->Sleep(kMaxSleepLong*1000);   // sleep 10 seconds before retrying
242          goto again;
243       }
244       Error("Create", "file %s is zombie", fname);
245       fRawDB->ResetErrno();
246       delete fRawDB;
247       fRawDB = 0;
248       if (retry < kMaxRetry) {
249          Warning("Create", "file is a zombie, sleeping %d %s before retrying...",
250                  kMaxSleep, kMaxSleep==1 ? "second" : "seconds");
251          gSystem->Sleep(kMaxSleep*1000);
252          goto again;
253       }
254       Error("Create", "failure to open file %s after %d tries", fname, kMaxRetry);
255       return kFALSE;
256    }
257
258    // Create raw data TTree
259    MakeTree();
260
261    return kTRUE;
262 }
263
264 //______________________________________________________________________________
265 void AliRawDB::MakeTree()
266 {
267    // Create ROOT Tree object container.
268
269    fTree = new TTree("RAW", Form("ALICE raw-data tree (%s)", GetAliRootTag()));
270    fTree->SetAutoSave(21000000000LL);  // autosave when 21 Gbyte written
271
272    fTree->BranchRef();
273
274    Int_t bufsize = 256000;
275    // splitting 29.6 MB/s, no splitting 35.3 MB/s on P4 2GHz 15k SCSI
276    //Int_t split   = 1;
277    Int_t split   = 0;
278    fTree->Branch("rawevent", "AliRawEvent", &fEvent, bufsize, split);
279
280    // Make brach for each sub-detector
281    for (Int_t iDet = 0; iDet < AliDAQ::kNDetectors; iDet++) {
282      for (Int_t iBranch = 0; iBranch < fgkDetBranches[iDet]; iBranch++)
283        fTree->Branch(Form("%s%d",AliDAQ::DetectorName(iDet),iBranch),"AliRawDataArray",
284                      &fDetRawData[iDet][iBranch],bufsize,split);
285    }
286    // Make special branch for unrecognized raw-data payloads
287    for (Int_t iBranch = 0; iBranch < fgkDetBranches[AliDAQ::kNDetectors]; iBranch++)
288      fTree->Branch(Form("Common%d",iBranch),"AliRawDataArray",
289                    &fDetRawData[AliDAQ::kNDetectors][iBranch],bufsize,split);
290
291    // Create tree which will contain the HLT ESD information
292
293    if (fESD) {
294      fESDTree = new TTree("esdTree", Form("ALICE HLT ESD tree (%s)", GetAliRootTag()));
295      fESDTree->SetAutoSave(21000000000LL);  // autosave when 21 Gbyte written
296      split   = 0;
297      fESDTree->Branch("ESD", "AliESDEvent", &fESD, bufsize, split);
298    }
299
300 }
301
302 //______________________________________________________________________________
303 Long64_t AliRawDB::Close()
304 {
305    // Close raw DB.
306    if (!fRawDB) return 0;
307
308    if (!fRawDB->IsOpen()) return 0;
309
310    fRawDB->cd();
311
312    // Write the tree.
313    Bool_t error = kFALSE;
314    if (fTree->Write() == 0)
315      error = kTRUE;
316    if (fESDTree)
317      if (fESDTree->Write() == 0)
318        error = kTRUE;
319
320    // Close DB, this also deletes the fTree
321    fRawDB->Close();
322
323    Long64_t filesize = fRawDB->GetEND();
324
325    if (fDeleteFiles) {
326       gSystem->Unlink(fRawDB->GetName());
327       delete fRawDB;
328       fRawDB = 0;
329       if(!error)
330         return filesize;
331       else
332         return -1;
333    }
334
335    delete fRawDB;
336    fRawDB = 0;
337    if(!error)
338      return filesize;
339    else
340      return -1;
341 }
342
343 //______________________________________________________________________________
344 Int_t AliRawDB::Fill()
345 {
346    // Fill the trees and return the number of written bytes
347
348   for (Int_t iDet = 0; iDet < (AliDAQ::kNDetectors + 1); iDet++)
349     for (Int_t iBranch = 0; iBranch < fgkDetBranches[iDet]; iBranch++)
350       fDetRawData[iDet][iBranch]->ClearData();
351
352    // Move the raw-data payloads to the corresponding branches
353   for(Int_t iSubEvent = 0; iSubEvent < fEvent->GetNSubEvents(); iSubEvent++) {
354     AliRawEvent *subEvent = fEvent->GetSubEvent(iSubEvent);
355     for(Int_t iEquipment = 0; iEquipment < subEvent->GetNEquipments(); iEquipment++) {
356       AliRawEquipment *equipment = subEvent->GetEquipment(iEquipment);
357       Int_t iDet = AliDAQ::kNDetectors;
358       Int_t iBranch = 0; // can we split somehow the unrecognized data??? For the moment - no
359       if(equipment->GetEquipmentHeader()->GetEquipmentSize()) {
360         UInt_t eqId = equipment->GetEquipmentHeader()->GetId();
361         Int_t ddlIndex = -1;
362         iDet = AliDAQ::DetectorIDFromDdlID(eqId,ddlIndex);
363         if (iDet < 0 || iDet >= AliDAQ::kNDetectors)
364           iDet = AliDAQ::kNDetectors;
365         else
366           iBranch = (ddlIndex * fgkDetBranches[iDet])/AliDAQ::NumberOfDdls(iDet);
367       }
368       equipment->SetRawDataRef(fDetRawData[iDet][iBranch]);
369     }
370   }
371
372    Double_t bytes = fRawDB->GetBytesWritten();
373    Bool_t error = kFALSE;
374    if (fTree->Fill() == -1)
375      error = kTRUE;
376    if (fESDTree) 
377      if (fESDTree->Fill() == -1)
378        error = kTRUE;
379    if(!error)
380      return Int_t(fRawDB->GetBytesWritten() - bytes);
381    else
382      return -1;
383 }
384
385 //______________________________________________________________________________
386 Long64_t AliRawDB::GetTotalSize()
387 {
388    // Return the total size of the trees
389   Long64_t total = 0;
390
391   {
392     Int_t skey = 0;
393     TDirectory *dir = fTree->GetDirectory();
394     if (dir) {
395       TKey *key = dir->GetKey(fTree->GetName());
396       if (key) skey = key->GetKeylen();
397     }
398     total += (Long64_t)skey + fTree->GetZipBytes();
399   }
400
401   if(fESDTree)
402     {
403       Int_t skey = 0;
404       TDirectory *dir = fESDTree->GetDirectory();
405       if (dir) {
406         TKey *key = dir->GetKey(fESDTree->GetName());
407         if (key) skey = key->GetKeylen();
408       }
409       total += (Long64_t)skey + fESDTree->GetZipBytes();
410     }
411
412   return total;
413 }
414
415 //______________________________________________________________________________
416 Long64_t AliRawDB::AutoSave()
417 {
418   // Auto-save the raw-data and
419   // esd (if any) trees
420
421   Long64_t nbytes = fTree->AutoSave();
422
423   if (fESDTree) nbytes += fESDTree->AutoSave();
424
425   return nbytes;
426 }
427
428 //______________________________________________________________________________
429 void AliRawDB::WriteStats(AliStats* stats)
430 {
431    // Write stats to raw DB, local run DB and global MySQL DB.
432
433    AliRawEventHeaderBase &header = *GetEvent()->GetHeader();
434
435    // Write stats into RawDB
436    TDirectory *ds = gDirectory;
437    GetDB()->cd();
438    stats->SetEvents(GetEvents());
439    stats->SetLastId(header.GetP("Id")[0]);
440    stats->SetFileSize(GetBytesWritten());
441    stats->SetCompressionFactor(GetCompressionFactor());
442    stats->SetEndTime();
443    stats->Write("stats");
444    ds->cd();
445 }
446
447 //______________________________________________________________________________
448 Bool_t AliRawDB::NextFile(const char* fileName)
449 {
450    // Close te current file and open a new one.
451    // Returns kFALSE in case opening failed.
452
453    Close();
454
455    if (!Create(fileName)) return kFALSE;
456    return kTRUE;
457 }
458
459 //______________________________________________________________________________
460 Float_t AliRawDB::GetCompressionFactor() const
461 {
462    // Return compression factor.
463
464    if (fTree->GetZipBytes() == 0.)
465       return 1.0;
466    else
467       return fTree->GetTotBytes()/fTree->GetZipBytes();
468 }
469
470 //______________________________________________________________________________
471 const char *AliRawDB::GetAliRootTag()
472 {
473   // Return the aliroot tag (version)
474   // used to generate the raw data file.
475   // Stored in the raw-data file title.
476
477   static TString version = fgkAliRootTag;
478   version.Remove(TString::kBoth,'$');
479   version.ReplaceAll("Rev","AliRoot version");
480
481   return version.Data();
482 }
483
484 //______________________________________________________________________________
485 Bool_t AliRawDB::WriteGuidFile(TString &guidFileFolder)
486 {
487   // Write the guid file
488   // in the specified folder or
489   // in the folder where the raw data
490   // file is.
491
492    TString guidFileName;
493    if (!guidFileFolder.IsNull()) {
494      guidFileName = guidFileFolder;
495
496      TString pathStr = fRawDB->GetName();
497      TObjArray *pathArr = pathStr.Tokenize('/');
498      guidFileName.Append("/");
499      guidFileName.Append(((TObjString *)pathArr->Last())->String());
500      pathArr->Delete();
501      delete pathArr;
502    }
503    else
504      guidFileName = fRawDB->GetName();
505
506    guidFileName += ".guid";
507
508    ofstream fguid(guidFileName.Data());
509    if (!fguid.is_open()) {
510      Error("WriteGuidFile", "failure to open guid file %s", guidFileName.Data());
511      return kFALSE;
512    }
513    TString guid = fRawDB->GetUUID().AsString();
514    fguid << "guid: \t" << guid.Data();
515    fguid.close();
516
517    return kTRUE;
518 }