New calibration classes (A.Colla)
[u/mrichter/AliRoot.git] / STEER / AliRunDataOrganizedFile.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 /* $Id$ */
17
18 ///////////////////////////////////////////////////////////////////////////////
19 //                                                                           //
20 // access class to a DB file inside an organized directory structure         //
21 // (DBFolder/detector/dbType/detSpecType)                                    //
22 //                                                                           //
23 ///////////////////////////////////////////////////////////////////////////////
24
25
26 #include <TFile.h>
27 #include <TKey.h>
28 #include <TROOT.h>
29 #include <TSystem.h>
30 #include <TObjArray.h>
31 #include <TObjString.h>
32 #include <TRegexp.h>
33
34 #include "AliLog.h"
35 #include "AliRunData.h"
36 #include "AliSelectionMetaData.h"
37 #include "AliRunDataOrganizedFile.h"
38
39
40 ClassImp(AliRunDataOrganizedFile)
41
42 //_____________________________________________________________________________
43 AliRunDataOrganizedFile::AliRunDataOrganizedFile(const char* DBFolder) :
44   AliRunDataStorage(),
45   fDBFolder(DBFolder)
46 {
47 // constructor
48   TString buffer(fDBFolder);
49   gSystem->ExpandPathName(buffer);
50   if(!gSystem->OpenDirectory(buffer)){
51     AliError(Form("Path %s not a directory",fDBFolder.Data()));
52   }
53 }
54
55 //_____________________________________________________________________________
56 AliRunDataOrganizedFile::~AliRunDataOrganizedFile()
57 {
58 // destructor
59
60   if (fDBFolder) fDBFolder="";
61 }
62
63 //_____________________________________________________________________________
64 AliRunDataOrganizedFile::AliRunDataOrganizedFile(const AliRunDataOrganizedFile& /*db*/) :
65   AliRunDataStorage(),
66   fDBFolder("")
67 {
68 // copy constructor
69
70   AliFatal("not implemented");
71 }
72
73 //_____________________________________________________________________________
74 AliRunDataOrganizedFile& AliRunDataOrganizedFile::operator = (const AliRunDataOrganizedFile& /*db*/)
75 {
76 // assignment operator
77
78  AliFatal("not implemented");
79  return *this;
80 }
81
82 //_____________________________________________________________________________
83 AliRunData* AliRunDataOrganizedFile::GetEntry(AliSelectionMetaData& selMetaData, Int_t runNumber)
84 {
85 // get an object from the data base   
86
87  TDirectory* saveDir = gDirectory;
88
89 // Find the right file in the directory
90
91   TObjArray *objarr = FindDataBaseFile(selMetaData, runNumber);
92   if(!objarr || objarr->GetEntries()==0) return NULL;
93   if(objarr->GetEntries()>1) 
94   AliWarning("Warning: more than 1 file match requirements, I will open the first found!");
95    
96 // Open the file
97
98  TObjString *objstr= (TObjString*) objarr->At(0); // there should be only one item
99  TString fileName(objstr->GetName());
100  TFile *dbFile = new TFile(fileName.Data(),"READ");
101  if (!dbFile || !dbFile->IsOpen()) {
102    AliError(Form("could not open file %s", fileName.Data()));
103    return NULL;
104  }
105    
106 // get the only AliRunData object from the file
107 // I suppose that the object in the file is a AliRunData entry with
108 // name="DetSpecType" (set in SelectionMetaData)
109
110  dbFile->cd();
111
112  AliRunData *entry = (AliRunData*) dbFile->Get(selMetaData.GetDetSpecType());
113  
114  if(!entry || !entry->InheritsFrom(AliRunData::Class())) {
115    AliError(Form("No entry named %s found!",selMetaData.GetDetSpecType())); 
116    dbFile->Close(); delete dbFile;  
117    if (saveDir) saveDir->cd(); else gROOT->cd();
118    return NULL;
119  }
120   
121 // now set the run range and version got from the filename 
122 // to the object's metadata!  
123   
124  TString fileNameShort=fileName;
125  fileNameShort.Remove(0,fileNameShort.Last('/')+1);
126  int numbers[3]={-1,-1,-1}; // numbers[0]=firstRun, numbers[1]=lastRun, numbers[2]=Version
127  GetNumbers(fileNameShort, numbers);
128  entry->SetRunRange(numbers[0],numbers[1]);
129  entry->SetVersion(numbers[2]);
130   
131 // close file, return retieved entry
132
133  dbFile->Close(); delete dbFile;  
134  if (saveDir) saveDir->cd(); else gROOT->cd();
135    
136  if(selMetaData.GetVersion() > -1 && numbers[2] != selMetaData.GetVersion()) 
137      AliWarning(Form("Warning: selected version (%d) not found, got version %d instead",
138             selMetaData.GetVersion(),numbers[2]));
139  return entry;
140   
141 }
142
143
144 //_____________________________________________________________________________
145 Bool_t AliRunDataOrganizedFile::PutEntry(AliRunData* entry)
146 {
147 // puts an object into the database
148
149 // AliRunData entry is composed by the object and its MetaData
150 // this method takes the metaData, reads the name, runRange and Version
151 // creates the directory structure and the file name
152 // looks for runs with same or overlapping runrange, if exist increment version
153 // (therefore version should not be put in the metadata)
154 // if the runrange is different (but overlapping) from a preceding version, a warning message
155 // is issued. 
156 // sets the runrange and version in the object metadata = -1 (to avoid inconsistencies)
157 // open the filem, write the entry in the file.
158 // Note: the key name of the entry is "DetSpecType"
159 // return result 
160    
161  if(!entry) return kFALSE;
162  TDirectory* saveDir = gDirectory;
163   
164  Int_t firstRun=entry->GetObjectMetaData().GetFirstRun();
165  Int_t lastRun=entry->GetObjectMetaData().GetLastRun();
166  if(firstRun<0 || lastRun<0 || lastRun<firstRun) {
167    AliError(Form("Run range not set or not valid: %d - %d !", firstRun, lastRun));
168    return kFALSE;
169  }
170
171  TString name(entry->GetObjectMetaData().GetName()); 
172   
173  while(name.EndsWith("/")) name.Remove(name.Last('/')); 
174  while(name.BeginsWith("/")) name.Remove(name.First('/'),1);
175
176  TString detSpecType(name(name.Last('/')+1, name.Length()-name.Last('/')));
177  
178  TString buffer(fDBFolder);
179  gSystem->ExpandPathName(buffer);
180  while(buffer.EndsWith("/")) buffer.Remove(buffer.Last('/'));
181  
182  void *dir=0;
183  Int_t index = -1;
184  name+='/'; // name=detector/dbType/detSpecType/
185
186  while ((index = name.Index("/")) >= 0) {
187    TString dirName(name(0, index));
188    buffer+='/'; buffer+=dirName;
189    dir=gSystem->OpenDirectory(buffer);
190    if (!dir) {
191     AliWarning(Form("Directory %s does not exist! It will be created...",buffer.Data()));
192     TString command = "mkdir "+ buffer;
193     gSystem->Exec(command.Data());
194    }
195    name.Remove(0, index+1);
196  } 
197  
198  TString strfName="Run";
199  
200  TString levelContent="";
201  Int_t maxVersion=-1, run1=-1, run2=-1;
202  int numbers[3]={-1,-1,-1}; // numbers[0]=firstRun, numbers[1]=lastRun, numbers[2]=Version
203  while(levelContent=gSystem->GetDirEntry(dir)){
204    if(levelContent=="." || levelContent=="..") continue; if(levelContent=="") break;
205    if(levelContent.Contains(strfName)){
206      GetNumbers(levelContent, numbers);
207      if((firstRun>=numbers[0] && firstRun<=numbers[1]) ||
208         (lastRun>=numbers[0] && lastRun<=numbers[1]) ||
209         (firstRun<=numbers[0] && lastRun>=numbers[1])) {// overlap!     
210         if(numbers[2]>maxVersion) {
211            maxVersion=numbers[2];
212            run1=numbers[0]; run2=numbers[1];
213         }
214      }
215    }
216  }
217  
218  if((run1!=-1 && run2!=-1) && (firstRun!=run1 || lastRun!=run2)) 
219     AliWarning(Form("Run range modified w.r.t. preceding version (%d, %d)",run1, run2));
220     
221  
222  if(firstRun==lastRun) {
223    strfName+=firstRun;
224  }else{
225    strfName+=firstRun; strfName+="-"; strfName+=lastRun;
226  }
227  strfName+="_v"; strfName+=maxVersion+1; strfName+=".root";
228  buffer+='/'; buffer+=strfName;
229  
230  // opening file
231  TFile *dbFile = new TFile(buffer.Data(),"NEW");
232  if(!dbFile || !dbFile->IsWritable()){
233    AliError(Form("The data base file is not writable. "
234                   "The object %s was not inserted", entry->GetName()));
235    return kFALSE;
236  }
237  
238  dbFile->cd();
239
240  entry->SetRunRange(-1,-1); entry->SetVersion(-1);
241  
242  // write object
243   Bool_t result = (entry->Write(detSpecType) != 0);
244   if (saveDir) saveDir->cd(); else gROOT->cd();
245   dbFile->Close(); delete dbFile;
246   
247   if(result) {
248     AliInfo(Form("Run object %s",entry->GetName()));
249     AliInfo(Form("was successfully written into file %s !",buffer.Data()));
250   }
251   
252   return result;
253 }
254
255 /*****************************************************************************/ 
256
257 TObjArray* AliRunDataOrganizedFile::FindDataBaseFile(AliSelectionMetaData& selMetaData, Int_t runNumber){
258 // Find DataBase file name in a local directory. The filename must be in the form: Run#run1-#run2_v#version.root
259 // TRegexp allowed: selMetaData's name can be for example: "detector/*" !!
260
261  TObjArray *fileNameColl=new TObjArray();
262
263  TString buffer(fDBFolder);
264  if(!(buffer.EndsWith("/"))) buffer+="/";
265  gSystem->ExpandPathName(buffer);
266   
267  TString bufftInit=buffer; // buffInit="$ALICE_ROOT/DB/
268  TString levelContent="";
269  
270  TString detector(selMetaData.GetDetector());
271  TString dbType(selMetaData.GetDBType());
272  TString detSpecType(selMetaData.GetDetSpecType());
273  int selVersion = selMetaData.GetVersion();
274
275  void *dirLevInit = gSystem->OpenDirectory(buffer);
276  while(levelContent=gSystem->GetDirEntry(dirLevInit)){ // lev0! In Detector directory (ZDC, TPC...)!!
277
278    if(levelContent=="." || levelContent=="..") continue; if(levelContent=="") break;
279    if(!(detector=="*") && !levelContent.Contains(TRegexp(detector)) ) continue;
280
281    buffer=bufftInit+levelContent; buffer+='/'; // buffer="$ALICE_ROOT/DB/detector/
282    TString bufft0=buffer; // bufft0="$ALICE_ROOT/DB/detector/
283
284    void *dirLev0 = gSystem->OpenDirectory(buffer);
285    while(levelContent=gSystem->GetDirEntry(dirLev0)){ // lev1! dbType directory (Calib, Align)!!
286
287      if(levelContent=="." || levelContent=="..") continue; if(levelContent=="") break;
288      if(!(dbType=="*") && !levelContent.Contains(TRegexp(dbType))) continue; 
289
290      buffer=bufft0+levelContent;buffer+='/'; // buffer="$ALICE_ROOT/DB/detector/dbType/
291      TString bufft1=buffer; // bufft1="$ALICE_ROOT/DB/detector/dbType/
292
293      void *dirLev1 = gSystem->OpenDirectory(buffer);
294      while(levelContent=gSystem->GetDirEntry(dirLev1)){ // lev2! detSpecType directory (Pedestals, gain....)!!
295
296        if(levelContent=="." || levelContent=="..") continue; if(levelContent=="") break;
297        if(!(detSpecType=="*") && !levelContent.Contains(TRegexp(detSpecType))) continue; 
298
299        buffer=bufft1+levelContent;buffer+='/'; // buffer="$ALICE_ROOT/DB/detector/dbType/detSpecType/
300        TString bufft2=buffer; // bufft2="$ALICE_ROOT/DB/detector/dbType/detSpecType/
301
302        void *dirLev2 = gSystem->OpenDirectory(buffer);
303        int oldVers=-1;
304        TObjString *str=0;
305        while(levelContent=gSystem->GetDirEntry(dirLev2)){ // lev3! Run directory (Run#XXX-#YYY_v#ZZ.root)!!
306
307          if(levelContent=="." || levelContent=="..") continue; if(levelContent=="") break;
308          if(!levelContent.BeginsWith("Run")) continue;
309          
310          int numbers[3]={-1,-1,-1}; // numbers[0]=firstRun, numbers[1]=lastRun, numbers[2]=Version 
311          GetNumbers(levelContent,numbers);
312          if(numbers[0]<0 || numbers[1]<0 || numbers[2]<0 ) continue; // wrong run filename format!
313          if(numbers[0]>runNumber ||  numbers[1]<runNumber) continue; // data not valid for run number
314
315          if((selVersion == -1 || numbers[2] <= selVersion) && numbers[2] >= oldVers) {
316            buffer=bufft2+levelContent;
317            str=new TObjString(buffer.Data());
318            oldVers=numbers[2];
319            if(numbers[2]==selVersion) break;
320            }
321          } // end loop on runs       
322        if(str) fileNameColl->Add(str);
323        } // end loop in lev1
324      } // end loop in lev0
325    } // end loop in levInit
326
327  AliInfo(Form("Found %d entries matching requirements", fileNameColl->GetEntriesFast()));
328  ToAliInfo(fileNameColl->ls());
329  return fileNameColl;
330 }
331
332 //_____________________________________________________________________________
333
334 void AliRunDataOrganizedFile::GetNumbers(const TString strName, int *numArray)
335 {
336 // Gets the numbers (#Run1, #Run2, #Version) from the filename: Run#Run1-#Run2_v#Version.root 
337
338  int indexMinus=strName.Last('-');
339  int indexUScore=strName.Last('_');
340  int indexPoint=strName.Last('.');
341  
342  if(indexUScore<0 || indexPoint<0 )
343     {AliError(Form("Check sintax %s",strName.Data())); return;}
344
345  if(indexMinus<0){ // only 1 Run number!
346    TString cRun=strName(3,indexUScore-3);
347    if(!(cRun.IsDigit()))
348       {AliError(Form("%s not a digit! Check sintax %s",cRun.Data(),strName.Data())); return;}
349    numArray[0] = (int) strtol(cRun.Data(),0,10);
350    numArray[1] = numArray[0];
351  }else{
352    TString cFirstRun = strName(3,indexMinus-3);  
353    TString cLastRun = strName(indexMinus+1,indexUScore-(indexMinus+1));  
354    if(!(cFirstRun.IsDigit()) || !(cLastRun.IsDigit()))
355       {AliError(Form("%s or %s are not digit! Check sintax %s",
356          cFirstRun.Data(), cLastRun.Data(), strName.Data())); return;}
357    numArray[0] = (int) strtol(cFirstRun.Data(),0,10);
358    numArray[1] = (int) strtol(cLastRun.Data(),0,10);
359  }
360  TString cVersion = strName(indexUScore+2,indexPoint-(indexUScore+2));
361  if(!(cVersion.IsDigit())){
362    AliError(Form("%s not a digit! Check sintax %s",cVersion.Data(),strName.Data())); return;}
363  numArray[2] = (int) strtol(cVersion.Data(),0,10);
364
365  return;
366 }