1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
18 /////////////////////////////////////////////////////////////////////////////////////////////////
20 // access class to a DB file inside an organized directory structure //
21 // file name = "DBFolder/detector/dbType/detSpecType/Run#firstRun-#lastRun _v#version.root" //
23 /////////////////////////////////////////////////////////////////////////////////////////////////
30 #include <TObjArray.h>
31 #include <TObjString.h>
35 #include "AliCDBLocal.h"
40 //_____________________________________________________________________________
41 AliCDBLocal::AliCDBLocal(const char* DBFolder) :
46 gSystem->ExpandPathName(fDBFolder);
48 if(!(dir=gSystem->OpenDirectory(fDBFolder))){
49 AliFatal(Form("Path %s not a directory",fDBFolder.Data()));
51 gSystem->FreeDirectory(dir);
53 while(fDBFolder.EndsWith("/")) fDBFolder.Remove(fDBFolder.Last('/'));
57 //_____________________________________________________________________________
58 AliCDBLocal::~AliCDBLocal()
64 //_____________________________________________________________________________
65 AliCDBLocal::AliCDBLocal(const AliCDBLocal& /*db*/) :
71 AliFatal("not implemented");
74 //_____________________________________________________________________________
75 AliCDBLocal& AliCDBLocal::operator = (const AliCDBLocal& /*db*/)
77 // assignment operator
79 AliFatal("not implemented");
83 //_____________________________________________________________________________
84 AliCDBEntry* AliCDBLocal::GetEntry(AliCDBMetaDataSelect& selMetaData, Int_t runNumber)
86 // get an object from the data base
88 TDirectory* saveDir = gDirectory;
90 // Find the right file in the directory
91 TString prefix="_v"; // development mode: fileName=Run#Run1-#Run2_v#Version.root
92 if(fStorageMode==kProduction) prefix="_Prod"; // production mode: fileName=Run#Run1-#Run2_Prod#Version.root
94 TString buffer(fDBFolder);
95 TString name(selMetaData.GetName());
96 buffer+=name; buffer+='/';
98 int selVersion = selMetaData.GetVersion();
100 void *dir = gSystem->OpenDirectory(buffer);
102 AliError(Form("Directory %s not found", name.Data()));
103 AliError(Form("in DB folder %s", fDBFolder.Data()));
108 TString levelContent="";
110 // in this array the "numbers" of the retrieved fileName (Run1, Run2, Version) are stored for later usage
111 int fileNumbers[3]={-1,-1,-1};
112 while(levelContent=gSystem->GetDirEntry(dir)){
114 if(levelContent=="." || levelContent=="..") continue; if(levelContent=="") break;
115 if(!levelContent.Contains("Run") || !levelContent.Contains(prefix)) continue;
117 int numbers[3]={-1,-1,-1}; // numbers[0]=firstRun, numbers[1]=lastRun, numbers[2]=Version
118 // gets the 3 "numbers" in the file name
119 if(!DecodeFileName(levelContent,numbers, prefix)) continue; // wrong run filename format
120 if(numbers[0]>runNumber || numbers[1]<runNumber) continue; // data not valid for run number
122 if(selVersion == -1) {
123 if(numbers[2] >= oldVers){
124 if(numbers[2] == oldVers){
125 // more than one file valid for the run -> error!
126 AliError(Form("More than one object valid for run %d, version %d!", runNumber, oldVers));
127 AliError(Form("No object will be returned!"));
128 gSystem->FreeDirectory(dir);
131 fileName=levelContent;
133 fileNumbers[0]=numbers[0]; fileNumbers[1]=numbers[1]; fileNumbers[2]=numbers[2];
136 if(numbers[2] == selVersion){
138 // filename was already assigned, this means there is more than one file valid for the run -> error!
139 AliError(Form("More than one object valid for run %d, version %d!", runNumber, selVersion));
140 AliError(Form("No object will be returned!"));
141 gSystem->FreeDirectory(dir);
144 fileName=levelContent;
145 fileNumbers[0]=numbers[0]; fileNumbers[1]=numbers[1]; fileNumbers[2]=numbers[2];
149 } // end loop on runs
151 gSystem->FreeDirectory(dir);
153 if(!buffer.EndsWith(".root")){
154 AliError(Form("No DB file matching criteria found!"));
158 TFile *DBFile = new TFile(buffer.Data(),"READ");
159 if(!DBFile || !DBFile->IsOpen()) {
160 AliError(Form("could not open file %s", buffer.Data()));
164 AliInfo(Form("File %s succesfully opened", buffer.Data()));
166 // get the only AliCDBEntry object from the file
167 // I assume that the object in the file is a AliCDBEntry entry with
168 // name="detSpecType" (set in CDBMetaDataSelect)
172 AliCDBEntry *entry = (AliCDBEntry*) DBFile->Get(selMetaData.GetDetSpecType());
174 if(!entry || !entry->InheritsFrom(AliCDBEntry::Class())) {
175 AliError(Form("No entry named %s found!",selMetaData.GetDetSpecType()));
176 DBFile->Close(); delete DBFile; DBFile=0;
177 if (saveDir) saveDir->cd(); else gROOT->cd();
182 // set the run range and version got from the filename
183 // to the object's metadata!
185 // entry->SetRunRange(fileNumbers[0],fileNumbers[1]);
186 // entry->SetVersion(fileNumbers[2]);
188 // Version 2: The object's metadata are not reset during storage
189 // If object's metadata runRange or version do not match with filename,
190 // it means that someone renamed file by hand. In this case a warning msg is issued.
191 Int_t objFirstRun=(entry->GetCDBMetaData()).GetFirstRun();
192 Int_t objLastRun=(entry->GetCDBMetaData()).GetLastRun();
193 Int_t objVersion=(entry->GetCDBMetaData()).GetVersion();
195 if(objFirstRun != fileNumbers[0] || objLastRun != fileNumbers[1] || objVersion != fileNumbers[2]){
196 AliWarning(Form("Either RunRange or Version in the object's metadata do noth match with fileName numbers:"));
197 AliWarning(Form("someone renamed file by hand!"));
200 // close file, return retieved entry
202 DBFile->Close(); delete DBFile; DBFile=0;
203 if (saveDir) saveDir->cd(); else gROOT->cd();
205 // if(selMetaData.GetVersion() > -1 && fileNumbers[2] != selMetaData.GetVersion())
206 // AliWarning(Form("Warning: selected version (%d) not found, got version %d instead",
207 // selMetaData.GetVersion(),fileNumbers[2]));
214 //_____________________________________________________________________________
215 Bool_t AliCDBLocal::PutEntry(AliCDBEntry* entry)
217 // puts an object into the database
219 // AliCDBEntry entry is composed by the object and its MetaData
220 // this method takes the metaData, reads the name, runRange and Version
221 // creates the directory structure and the file name
222 // looks for runs with same or overlapping runrange, if exist increment version
223 // (therefore version should not be put in the metadata)
224 // if the runrange is different (but overlapping) from a preceding version, a warning message
226 // sets the runrange and version in the object metadata = -1 (to avoid inconsistencies)
227 // open the filem, write the entry in the file.
228 // Note: the key name of the entry is "detSpecType"
231 if(!entry) return kFALSE;
232 TDirectory* saveDir = gDirectory;
234 Int_t firstRun=entry->GetCDBMetaData().GetFirstRun();
235 Int_t lastRun=entry->GetCDBMetaData().GetLastRun();
236 if(firstRun<0 || lastRun<0 || lastRun<firstRun) {
237 AliError(Form("Run range not set or not valid: %d - %d !", firstRun, lastRun));
241 TString name(entry->GetName());
244 TString detSpecType(name(name.Last('/')+1, name.Length()-name.Last('/')));
245 TString buffer(fDBFolder);
249 name+='/'; // name=detector/dbType/detSpecType/
251 while ((index = name.Index("/")) >= 0) {
252 TString dirName(name(0, index+1));
254 dir=gSystem->OpenDirectory(buffer);
256 AliWarning(Form("Directory %s does not exist! It will be created...",buffer.Data()));
257 gSystem->mkdir(buffer.Data());
259 name.Remove(0, index+1);
260 gSystem->FreeDirectory(dir);
263 dir = gSystem->OpenDirectory(buffer);
264 TString levelContent="";
265 Int_t maxVersion=-1, run1=-1, run2=-1;
266 int numbers[3]={-1,-1,-1}; // numbers[0]=firstRun, numbers[1]=lastRun, numbers[2]=Version
267 while(levelContent=gSystem->GetDirEntry(dir)){
268 if(levelContent=="." || levelContent=="..") continue; if(levelContent=="") break;
269 if(levelContent.Contains("Run")){
270 if(levelContent.Contains("_Prod")) continue; //skip "Production" links
271 if(!DecodeFileName(levelContent, numbers, "_v")) continue;
272 if((firstRun>=numbers[0] && firstRun<=numbers[1]) ||
273 (lastRun>=numbers[0] && lastRun<=numbers[1]) ||
274 (firstRun<=numbers[0] && lastRun>=numbers[1])) {// overlap!
275 if(numbers[2]>maxVersion) {
276 maxVersion=numbers[2];
277 run1=numbers[0]; run2=numbers[1];
282 gSystem->FreeDirectory(dir);
284 if((run1!=-1 && run2!=-1) && (firstRun!=run1 || lastRun!=run2))
285 AliWarning(Form("Run range modified w.r.t. preceding version (%d, %d)",run1, run2));
287 TString strfName=EncodeFileName(firstRun, lastRun, maxVersion+1);
291 TFile *DBFile = new TFile(buffer.Data(),"NEW");
292 if(!DBFile || !DBFile->IsWritable()){
293 AliError(Form("The data base file is not writable. "
294 "The object %s was not inserted", entry->GetName()));
295 if(!DBFile->IsWritable()) DBFile->Close(); DBFile->Delete(); delete DBFile; DBFile=0;
301 entry->SetVersion(maxVersion+1);
304 Bool_t result = (entry->Write(detSpecType) != 0);
305 if (saveDir) saveDir->cd(); else gROOT->cd();
306 DBFile->Close(); DBFile->Delete(); delete DBFile; DBFile=0;
308 AliInfo(Form("Run object %s",entry->GetName()));
309 AliInfo(Form("was successfully written into file %s",buffer.Data()));
316 /*****************************************************************************/
317 TObjArray* AliCDBLocal::FindDBFiles(const char* name, Int_t runNumber){
318 // Find DataBase file name in a local directory. The filename must be in the form: Run#run1-#run2_v#version.root
319 // TRegexp allowed: name can be for example: "detector/*" !!
321 TObjArray *FileNameColl=new TObjArray();
323 TString prefix="_v"; // development mode: fileName=Run#Run1-#Run2_v#Version.root
324 if(fStorageMode==kProduction) prefix="_Prod"; // production mode: fileName=Run#Run1-#Run2_Prod#Version.root
326 TString buffer(fDBFolder);
327 // gSystem->ExpandPathName(buffer);
329 TString bufftInit=buffer; // buffInit="$ALICE_ROOT/DB/
330 TString levelContent="";
332 AliCDBMetaDataSelect selMetaData(name);
334 TString detector(selMetaData.GetDetector());
335 TString dbType(selMetaData.GetDBType());
336 TString detSpecType(selMetaData.GetDetSpecType());
337 int selVersion = selMetaData.GetVersion();
339 void *dirLevInit = gSystem->OpenDirectory(buffer);
340 while(levelContent=gSystem->GetDirEntry(dirLevInit)){ // lev0! In detector directory (ZDC, TPC...)!!
342 if(levelContent=="." || levelContent=="..") continue; if(levelContent=="") break;
343 if(!(detector=="*") && !levelContent.Contains(TRegexp(detector)) ) continue;
345 buffer=bufftInit+levelContent; buffer+='/'; // buffer="$ALICE_ROOT/DB/detector/
346 TString bufft0=buffer; // bufft0="$ALICE_ROOT/DB/detector/
348 void *dirLev0 = gSystem->OpenDirectory(buffer);
349 while(levelContent=gSystem->GetDirEntry(dirLev0)){ // lev1! dbType directory (Calib, Align)!!
351 if(levelContent=="." || levelContent=="..") continue; if(levelContent=="") break;
352 if(!(dbType=="*") && !levelContent.Contains(TRegexp(dbType))) continue;
354 buffer=bufft0+levelContent;buffer+='/'; // buffer="$ALICE_ROOT/DB/detector/dbType/
355 TString bufft1=buffer; // bufft1="$ALICE_ROOT/DB/detector/dbType/
357 void *dirLev1 = gSystem->OpenDirectory(buffer);
358 while(levelContent=gSystem->GetDirEntry(dirLev1)){ // lev2! detSpecType directory (Pedestals, gain....)!!
360 if(levelContent=="." || levelContent=="..") continue; if(levelContent=="") break;
361 if(!(detSpecType=="*") && !levelContent.Contains(TRegexp(detSpecType))) continue;
363 buffer=bufft1+levelContent;buffer+='/'; // buffer="$ALICE_ROOT/DB/detector/dbType/detSpecType/
364 TString bufft2=buffer; // bufft2="$ALICE_ROOT/DB/detector/dbType/detSpecType/
366 void *dirLev2 = gSystem->OpenDirectory(buffer);
368 while(levelContent=gSystem->GetDirEntry(dirLev2)){ // lev3! Run directory (Run#XXX-#YYY_v#ZZ.root)!!
370 if(levelContent=="." || levelContent=="..") continue; if(levelContent=="") break;
371 if(!levelContent.BeginsWith("Run")) continue;
372 if(!levelContent.Contains(prefix)) continue;
374 int numbers[3]={-1,-1,-1}; // numbers[0]=firstRun, numbers[1]=lastRun, numbers[2]=Version
375 if(!DecodeFileName(levelContent,numbers, prefix)) continue; // wrong run filename format!
376 if(numbers[0]>runNumber || numbers[1]<runNumber) continue; // data not valid for run number
378 if(numbers[2]==selVersion) {
379 buffer=bufft2+levelContent;
380 str=new TObjString(buffer.Data());
381 FileNameColl->Add(str);
384 if(selVersion == -1) { // if version is not specified, collect all versions
385 buffer=bufft2+levelContent;
386 str=new TObjString(buffer.Data());
387 FileNameColl->Add(str);
389 } // end loop on runs
390 } // end loop in lev1
391 } // end loop in lev0
392 } // end loop in levInit
394 AliInfo(Form("Found %d entries matching requirements", FileNameColl->GetEntriesFast()));
395 ToAliInfo(FileNameColl->ls());
399 //_____________________________________________________________________________
400 void AliCDBLocal::TagForProduction(const AliCDBMetaDataSelect& selMetaData, UInt_t prodVers){
402 TString workingDir=gSystem->pwd();
403 //Build the file path
404 TString buffer(fDBFolder); //gSystem->ExpandPathName() already done in ctor
407 buffer+=selMetaData.GetName(); buffer+='/';
408 //gSystem->ExpandPathName(dirName);
410 if(!gSystem->cd(buffer))
411 {AliError(Form("Directory %s does not exist... check name!", buffer.Data())); gSystem->cd(workingDir.Data()); return;}
413 // if version is not specified (=-1), then tag the highest version (BE CAREFUL!!)
414 if(selMetaData.GetVersion() != -1){
416 fName = EncodeFileName(selMetaData.GetFirstRun(), selMetaData.GetLastRun(), selMetaData.GetVersion());
418 //look in directory for valid DB files, seek highest version
419 void *dir = gSystem->OpenDirectory(buffer);
420 TString levelContent="";
422 while(levelContent=gSystem->GetDirEntry(dir)){
424 if(levelContent=="." || levelContent=="..") continue; if(levelContent=="") break;
425 if(!levelContent.Contains("Run") || !levelContent.Contains("_v")) continue;
427 int numbers[3]={-1,-1,-1}; // numbers[0]=firstRun, numbers[1]=lastRun, numbers[2]=Version
428 // gets the 3 "numbers" in the file name
429 if(!DecodeFileName(levelContent,numbers, "_v")) continue; // wrong run filename format!
430 if(numbers[0] != selMetaData.GetFirstRun() || numbers[1] != selMetaData.GetLastRun()) continue;
431 if(numbers[2] >= oldVers) {
435 } // end loop on runs
438 //check that the flename exists
439 if(!gSystem->IsFileInIncludePath(fName.Data())){
440 AliError(Form("File name %s not found... check!", fName.Data()));
441 gSystem->cd(workingDir.Data());
445 // file exists: make symbolic link!
446 TString prodfName=EncodeFileName(selMetaData.GetFirstRun(), selMetaData.GetLastRun(), prodVers, "_Prod");
447 if(gSystem->Symlink(fName.Data(),prodfName.Data())<0){
448 AliError(Form("Link name already existing (%s): linkage failed!",prodfName.Data()));
450 AliError(Form("File %s tagged for production with symlink %s",fName.Data(), prodfName.Data()));
453 gSystem->cd(workingDir);
458 //_____________________________________________________________________________
459 Bool_t AliCDBLocal::DecodeFileName(const TString strName, int *numArray, TString prefix)
461 // Gets the numbers (#Run1, #Run2, #Version)
462 // from the filename: Run#Run1-#Run2_v#Version.root or Run#Run1-#Run2_Prod#prodVers.root
464 int indexMinus=strName.Last('-');
465 int indexUScore=strName.Last('_');
466 int indexPoint=strName.Last('.');
468 int nSkipChar=prefix.Length(); // prefix can be either "_v" or "_Prod" depending on fStorageMode
469 //if(prefix=="_v") {nSkipChar=2;} // development mode: _v# skip 2 characters
470 //else if(prefix=="_Prod") {nSkipChar=5;} // production mode: _Prod# skip 5 characters
472 if(indexUScore<0 || indexPoint<0 )
473 {AliDebug(2, Form("Check sintax %s",strName.Data())); return kFALSE;}
475 if(indexMinus<0){ // only 1 Run number!
476 TString cRun=strName(3,indexUScore-3);
477 if(!(cRun.IsDigit()))
478 {AliDebug(2, Form("%s not a digit! Check sintax %s",cRun.Data(),strName.Data())); return kFALSE;}
479 numArray[0] = (int) strtol(cRun.Data(),0,10);
480 numArray[1] = numArray[0];
482 TString cFirstRun = strName(3,indexMinus-3);
483 TString cLastRun = strName(indexMinus+1,indexUScore-(indexMinus+1));
484 if(!(cFirstRun.IsDigit()) || !(cLastRun.IsDigit()))
485 {AliDebug(2, Form("%s or %s are not digit! Check sintax %s",
486 cFirstRun.Data(), cLastRun.Data(), strName.Data())); return kFALSE;}
487 numArray[0] = (int) strtol(cFirstRun.Data(),0,10);
488 numArray[1] = (int) strtol(cLastRun.Data(),0,10);
490 // TString cVersion = strName(indexUScore+2,indexPoint-(indexUScore+2));
491 TString cVersion = strName(indexUScore+nSkipChar,indexPoint-(indexUScore+nSkipChar));
492 if(!(cVersion.IsDigit())){
493 AliDebug(2, Form("%s not a digit! Check sintax %s",cVersion.Data(),strName.Data())); return kFALSE;}
494 numArray[2] = (int) strtol(cVersion.Data(),0,10);
500 //_____________________________________________________________________________
501 TString AliCDBLocal::EncodeFileName(int firstRun, int lastRun, int version, TString prefix){
502 // Builds a file name of the form: Run#firstRun-#lastRun_v#Version.root
505 if(firstRun==lastRun) {
508 fName+=firstRun; fName+="-"; fName+=lastRun;
510 fName+=prefix; fName+=version; fName+=".root";