]> git.uio.no Git - u/mrichter/AliRoot.git/blob - STEER/CDB/AliCDBLocal.cxx
MFT track shit tool added
[u/mrichter/AliRoot.git] / STEER / CDB / AliCDBLocal.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 /////////////////////////////////////////////////////////////////////////////////////////////////
17 //                                                                                             //
18 // AliCDBLocal                                                                                 //
19 // access class to a DataBase in a local storage                                               //
20 //                                                                                             //
21 /////////////////////////////////////////////////////////////////////////////////////////////////
22
23 #include <cstdlib>
24 #include <stdexcept>
25 #include <fstream>
26
27 #include <TSystem.h>
28 #include <TObjString.h>
29 #include <TRegexp.h>
30 #include <TFile.h>
31 #include <TKey.h>
32
33 #include "AliCDBLocal.h"
34 #include "AliCDBEntry.h"
35 #include "AliLog.h"
36 using namespace std;
37
38 ClassImp(AliCDBLocal)
39
40 //_____________________________________________________________________________
41 AliCDBLocal::AliCDBLocal(const char* baseDir):
42   fBaseDirectory(baseDir) 
43 {
44   // constructor
45
46   AliDebug(1, Form("fBaseDirectory = %s",fBaseDirectory.Data()));
47
48   // check baseDire: trying to cd to baseDir; if it does not exist, create it
49   void* dir = gSystem->OpenDirectory(baseDir);
50   if (dir == NULL) {
51     if (gSystem->mkdir(baseDir, kTRUE)) {
52        AliError(Form("Can't open directory <%s>!", baseDir)); //!!!!!!!! to be commented out for testing
53     }
54
55   } else {
56     AliDebug(2,Form("Folder <%s> found",fBaseDirectory.Data()));
57     gSystem->FreeDirectory(dir);
58   }
59   fType="local";
60   fBaseFolder = fBaseDirectory;
61 }
62
63 //_____________________________________________________________________________
64 AliCDBLocal::~AliCDBLocal() {
65 // destructor
66
67 }
68
69
70 //_____________________________________________________________________________
71 Bool_t AliCDBLocal::FilenameToId(const char* filename, AliCDBRunRange& runRange,
72     Int_t& version, Int_t& subVersion) {
73   // build AliCDBId from filename numbers
74
75   Ssiz_t mSize;
76
77   // valid filename: Run#firstRun_#lastRun_v#version_s#subVersion.root
78   TRegexp keyPattern("^Run[0-9]+_[0-9]+_v[0-9]+_s[0-9]+.root$");
79   keyPattern.Index(filename, &mSize);
80   if (!mSize) {
81     AliDebug(2, Form("Bad filename <%s>.", filename));
82     return kFALSE;
83   }
84
85   TString idString(filename);
86   idString.Resize(idString.Length() - sizeof(".root") + 1);
87
88   TObjArray* strArray = (TObjArray*) idString.Tokenize("_");
89
90   TString firstRunString(((TObjString*) strArray->At(0))->GetString());
91   runRange.SetFirstRun(atoi(firstRunString.Data() + 3));
92   runRange.SetLastRun(atoi(((TObjString*) strArray->At(1))->GetString()));
93
94   TString verString(((TObjString*) strArray->At(2))->GetString());
95   version = atoi(verString.Data() + 1);
96
97   TString subVerString(((TObjString*) strArray->At(3))->GetString());
98   subVersion = atoi(subVerString.Data() + 1);
99
100   delete strArray;
101
102   return kTRUE;
103 }
104
105
106 //_____________________________________________________________________________
107 Bool_t AliCDBLocal::IdToFilename(const AliCDBId& id, TString& filename) const {
108 // build file name from AliCDBId data (run range, version, subVersion)
109
110   AliDebug(1, Form("fBaseDirectory = %s",fBaseDirectory.Data()));
111
112   if (!id.GetAliCDBRunRange().IsValid()) {
113     AliDebug(2,Form("Invalid run range <%d, %d>.", 
114           id.GetFirstRun(), id.GetLastRun()));
115     return kFALSE;
116   }
117
118   if (id.GetVersion() < 0) {
119     AliDebug(2,Form("Invalid version <%d>.", id.GetVersion()));
120     return kFALSE;
121   }
122
123   if (id.GetSubVersion() < 0) {
124     AliDebug(2,Form("Invalid subversion <%d>.", id.GetSubVersion()));
125     return kFALSE;
126   }
127
128   filename = Form("Run%d_%d_v%d_s%d.root", id.GetFirstRun(), id.GetLastRun(),
129       id.GetVersion(), id.GetSubVersion());
130
131   filename.Prepend(fBaseDirectory +'/' + id.GetPath() + '/');
132
133   return kTRUE;
134 }
135
136 //_____________________________________________________________________________
137 Bool_t AliCDBLocal::PrepareId(AliCDBId& id) {
138 // prepare id (version, subVersion) of the object that will be stored (called by PutEntry)
139
140   TString dirName = Form("%s/%s", fBaseDirectory.Data(), id.GetPath().Data());
141
142   // go to the path; if directory does not exist, create it
143   void* dirPtr = gSystem->OpenDirectory(dirName);
144   if (!dirPtr) {
145     gSystem->mkdir(dirName, kTRUE);
146     dirPtr = gSystem->OpenDirectory(dirName);
147
148     if (!dirPtr) {
149       AliError(Form("Can't create directory <%s>!", 
150             dirName.Data()));
151       return kFALSE;
152     }
153   }
154
155   const char* filename;
156   AliCDBRunRange aRunRange; // the runRange got from filename
157   AliCDBRunRange lastRunRange(-1,-1); // highest runRange found
158   Int_t aVersion, aSubVersion; // the version subVersion got from filename
159   Int_t lastVersion = 0, lastSubVersion = -1; // highest version and subVersion found
160
161   if (!id.HasVersion()) { // version not specified: look for highest version & subVersion
162
163     while ((filename = gSystem->GetDirEntry(dirPtr))) { // loop on the files
164
165       TString aString(filename);
166       if (aString == "." || aString == "..") continue;
167
168       if (!FilenameToId(filename, aRunRange, aVersion, 
169             aSubVersion)) {
170         AliDebug(2,Form(
171               "Bad filename <%s>! I'll skip it.", 
172               filename));
173         continue;
174       }
175
176       if (!aRunRange.Overlaps(id.GetAliCDBRunRange())) continue;
177       if(aVersion < lastVersion) continue;
178       if(aVersion > lastVersion) lastSubVersion = -1;
179       if(aSubVersion < lastSubVersion) continue;
180       lastVersion = aVersion;
181       lastSubVersion = aSubVersion;
182       lastRunRange = aRunRange;
183     }
184
185     id.SetVersion(lastVersion);
186     id.SetSubVersion(lastSubVersion + 1);
187
188   } else { // version specified, look for highest subVersion only
189
190     while ((filename = gSystem->GetDirEntry(dirPtr))) { // loop on the files
191
192       TString aString(filename);
193       if (aString == "." || aString == "..") {
194         continue;
195       }
196
197       if (!FilenameToId(filename, aRunRange, aVersion, 
198             aSubVersion)) {
199         AliDebug(2,Form(
200               "Bad filename <%s>!I'll skip it.",
201               filename));       
202         continue;
203       }
204
205       if (aRunRange.Overlaps(id.GetAliCDBRunRange()) 
206           && aVersion == id.GetVersion()
207           && aSubVersion > lastSubVersion) {
208         lastSubVersion = aSubVersion;
209         lastRunRange = aRunRange;
210       }
211
212     }
213
214     id.SetSubVersion(lastSubVersion + 1);
215   }
216
217   gSystem->FreeDirectory(dirPtr);
218
219   TString lastStorage = id.GetLastStorage();
220   if(lastStorage.Contains(TString("grid"), TString::kIgnoreCase) &&
221       id.GetSubVersion() > 0 ){
222     AliError(Form("Grid to Local Storage error! local object with version v%d_s%d found:",id.GetVersion(), id.GetSubVersion()-1));
223     AliError(Form("This object has been already transferred from Grid (check v%d_s0)!",id.GetVersion()));
224     return kFALSE;
225   }
226
227   if(lastStorage.Contains(TString("new"), TString::kIgnoreCase) &&
228       id.GetSubVersion() > 0 ){
229     AliDebug(2, Form("A NEW object is being stored with version v%d_s%d",
230           id.GetVersion(),id.GetSubVersion()));
231     AliDebug(2, Form("and it will hide previously stored object with v%d_s%d!",
232           id.GetVersion(),id.GetSubVersion()-1));
233   }
234
235   if(!lastRunRange.IsAnyRange() && !(lastRunRange.IsEqual(& id.GetAliCDBRunRange()))) 
236     AliWarning(Form("Run range modified w.r.t. previous version (Run%d_%d_v%d_s%d)",
237           lastRunRange.GetFirstRun(), lastRunRange.GetLastRun(), 
238           id.GetVersion(), id.GetSubVersion()-1));
239
240   return kTRUE;
241 }
242
243
244 //_____________________________________________________________________________
245 AliCDBId* AliCDBLocal::GetId(const AliCDBId& query) {
246   // look for filename matching query (called by GetEntryId)
247
248   // if querying for fRun and not specifying a version, look in the fValidFileIds list
249   if(!AliCDBManager::Instance()->GetCvmfsOcdbTag().IsNull() && query.GetFirstRun() == fRun && !query.HasVersion()) {
250   //if(query.GetFirstRun() == fRun && !query.HasVersion()) {
251     // get id from fValidFileIds
252     TIter iter(&fValidFileIds);
253
254     AliCDBId *anIdPtr=0;
255     AliCDBId* result=0;
256
257     while((anIdPtr = dynamic_cast<AliCDBId*> (iter.Next()))){
258       if(anIdPtr->GetPath() == query.GetPath()){
259         result = new AliCDBId(*anIdPtr);
260         break;
261       }
262     }
263     return result;
264   }
265
266   // otherwise browse in the local filesystem CDB storage
267   TString dirName = Form("%s/%s", fBaseDirectory.Data(), query.GetPath().Data());
268
269   void* dirPtr = gSystem->OpenDirectory(dirName);
270   if (!dirPtr) {
271     AliDebug(2,Form("Directory <%s> not found", (query.GetPath()).Data()));
272     AliDebug(2,Form("in DB folder %s", fBaseDirectory.Data()));
273     return NULL;
274   }
275
276   const char* filename;
277   AliCDBId *result = new AliCDBId();
278   result->SetPath(query.GetPath());
279
280   AliCDBRunRange aRunRange; // the runRange got from filename
281   Int_t aVersion, aSubVersion; // the version and subVersion got from filename
282
283   if (!query.HasVersion()) { // neither version and subversion specified -> look for highest version and subVersion
284
285     while ((filename = gSystem->GetDirEntry(dirPtr))) { // loop on files
286
287       TString aString(filename);
288       if (aString.BeginsWith('.')) continue;
289
290       if (!FilenameToId(filename, aRunRange, aVersion, aSubVersion)) continue;
291       // aRunRange, aVersion, aSubVersion filled from filename
292
293       if (!aRunRange.Comprises(query.GetAliCDBRunRange())) continue;
294       // aRunRange contains requested run!
295
296       AliDebug(1,Form("Filename %s matches\n",filename));
297
298       if (result->GetVersion() < aVersion) {
299         result->SetVersion(aVersion);
300         result->SetSubVersion(aSubVersion);
301
302         result->SetFirstRun(
303             aRunRange.GetFirstRun());
304         result->SetLastRun(
305             aRunRange.GetLastRun());
306
307       } else if (result->GetVersion() == aVersion
308           && result->GetSubVersion()
309           < aSubVersion) {
310
311         result->SetSubVersion(aSubVersion);
312
313         result->SetFirstRun(
314             aRunRange.GetFirstRun());
315         result->SetLastRun(
316             aRunRange.GetLastRun());
317       } else if (result->GetVersion() == aVersion
318           && result->GetSubVersion() == aSubVersion){
319         AliError(Form("More than one object valid for run %d, version %d_%d!",
320               query.GetFirstRun(), aVersion, aSubVersion));
321         gSystem->FreeDirectory(dirPtr);
322         delete result;
323         return NULL;
324       }
325     }
326
327   } else if (!query.HasSubVersion()) { // version specified but not subversion -> look for highest subVersion
328     result->SetVersion(query.GetVersion());
329
330     while ((filename = gSystem->GetDirEntry(dirPtr))) { // loop on files
331
332       TString aString(filename);
333       if (aString.BeginsWith('.')) continue;
334
335       if (!FilenameToId(filename, aRunRange, aVersion, aSubVersion)) continue;
336       // aRunRange, aVersion, aSubVersion filled from filename
337
338       if (!aRunRange.Comprises(query.GetAliCDBRunRange())) continue; 
339       // aRunRange contains requested run!
340
341       if(query.GetVersion() != aVersion) continue;
342       // aVersion is requested version!
343
344       if(result->GetSubVersion() == aSubVersion){
345         AliError(Form("More than one object valid for run %d, version %d_%d!",
346               query.GetFirstRun(), aVersion, aSubVersion));
347         gSystem->FreeDirectory(dirPtr);
348         delete result;
349         return NULL;
350       }
351       if( result->GetSubVersion() < aSubVersion) {
352
353         result->SetSubVersion(aSubVersion);
354
355         result->SetFirstRun(
356             aRunRange.GetFirstRun());
357         result->SetLastRun(
358             aRunRange.GetLastRun());
359       } 
360     }
361
362   } else { // both version and subversion specified
363
364     //AliCDBId dataId(queryId.GetAliCDBPath(), -1, -1, -1, -1);
365     //Bool_t result;
366     while ((filename = gSystem->GetDirEntry(dirPtr))) { // loop on files
367
368       TString aString(filename);
369       if (aString.BeginsWith('.')) continue;
370
371       if (!FilenameToId(filename, aRunRange, aVersion, aSubVersion)){
372         AliDebug(5, Form("Could not make id from file: %s", filename));
373         continue;
374       }
375       // aRunRange, aVersion, aSubVersion filled from filename
376
377       if (!aRunRange.Comprises(query.GetAliCDBRunRange())) continue;
378       // aRunRange contains requested run!
379
380       if(query.GetVersion() != aVersion || query.GetSubVersion() != aSubVersion){
381           continue;
382       }
383       // aVersion and aSubVersion are requested version and subVersion!
384
385       result->SetVersion(aVersion);
386       result->SetSubVersion(aSubVersion);
387       result->SetFirstRun(aRunRange.GetFirstRun());
388       result->SetLastRun(aRunRange.GetLastRun());
389       break;
390     }
391   }
392
393   gSystem->FreeDirectory(dirPtr);
394
395   return result;
396 }
397
398 //_____________________________________________________________________________
399 AliCDBEntry* AliCDBLocal::GetEntry(const AliCDBId& queryId) {
400 // get AliCDBEntry from the storage (the CDB file matching the query is
401 // selected by GetEntryId and the contained AliCDBid is passed here)
402
403   AliCDBId* dataId = GetEntryId(queryId);
404
405   TString errMessage(TString::Format("No valid CDB object found! request was: %s", queryId.ToString().Data()));
406   if (!dataId || !dataId->IsSpecified()){
407     AliError(Form("No file found matching this id!"));
408     throw std::runtime_error(errMessage.Data());
409     return NULL;
410   }
411
412   TString filename;
413   if (!IdToFilename(*dataId, filename)) {
414     AliError(Form("Bad data ID encountered!"));
415     delete dataId;
416     throw std::runtime_error(errMessage.Data());
417     return NULL;
418   }
419
420   TFile file(filename, "READ"); // open file
421   if (!file.IsOpen()) {
422     AliError(Form("Can't open file <%s>!", filename.Data()));
423     delete dataId;
424     throw std::runtime_error(errMessage.Data());
425     return NULL;
426   }
427
428   // get the only AliCDBEntry object from the file
429   // the object in the file is an AliCDBEntry entry named "AliCDBEntry"
430
431   AliCDBEntry* anEntry = dynamic_cast<AliCDBEntry*> (file.Get("AliCDBEntry"));
432   if (!anEntry) {
433     AliError(Form("Bad storage data: No AliCDBEntry in file!"));
434     file.Close();
435     delete dataId;
436     throw std::runtime_error(errMessage.Data());
437     return NULL;
438   }
439
440   AliCDBId& entryId = anEntry->GetId();
441
442   // The object's Id are not reset during storage
443   // If object's Id runRange or version do not match with filename,
444   // it means that someone renamed file by hand. In this case a warning msg is issued.
445
446   anEntry-> SetLastStorage("local");
447
448   if(!entryId.IsEqual(dataId)){
449     AliWarning(Form("Mismatch between file name and object's Id!"));
450     AliWarning(Form("File name: %s", dataId->ToString().Data()));
451     AliWarning(Form("Object's Id: %s", entryId.ToString().Data()));
452   }
453
454   // Check whether entry contains a TTree. In case load the tree in memory!
455   LoadTreeFromFile(anEntry);
456
457   // close file, return retrieved entry
458   file.Close();
459   delete dataId;
460
461   return anEntry;
462 }
463
464 //_____________________________________________________________________________
465 AliCDBId* AliCDBLocal::GetEntryId(const AliCDBId& queryId) {
466 // get AliCDBId from the storage
467 // Via GetId, select the CDB file matching the query and return
468 // the contained AliCDBId
469
470   AliCDBId* dataId = 0;
471
472   // look for a filename matching query requests (path, runRange, version, subVersion)
473   if (!queryId.HasVersion()) {
474     // if version is not specified, first check the selection criteria list
475     AliCDBId selectedId(queryId);
476     GetSelection(&selectedId);
477     dataId = GetId(selectedId);
478   } else {
479     dataId = GetId(queryId);
480   }
481
482   if (dataId && !dataId->IsSpecified()) {
483     delete dataId;
484     return NULL;
485   }
486
487   return dataId;
488 }
489
490 //_____________________________________________________________________________
491 void AliCDBLocal::GetEntriesForLevel0(const char* level0,
492     const AliCDBId& queryId, TList* result) {
493   // multiple request (AliCDBStorage::GetAll)
494
495   TString level0Dir = Form("%s/%s", fBaseDirectory.Data(), level0);
496
497   void* level0DirPtr = gSystem->OpenDirectory(level0Dir);
498   if (!level0DirPtr) {
499     AliDebug(2,Form("Can't open level0 directory <%s>!",
500           level0Dir.Data()));
501     return;
502   }
503
504   const char* level1;
505   Long_t flag=0;
506   while ((level1 = gSystem->GetDirEntry(level0DirPtr))) {
507
508     TString level1Str(level1);
509     // skip directories starting with a dot (".svn" and similar in old svn working copies)
510     if (level1Str.BeginsWith('.')) {
511       continue;
512     }
513
514     TString fullPath = Form("%s/%s",level0Dir.Data(), level1); 
515
516     Int_t res=gSystem->GetPathInfo(fullPath.Data(), 0, (Long64_t*) 0, &flag, 0);
517
518     if(res){
519       AliDebug(2, Form("Error reading entry %s !",level1Str.Data()));
520       continue;
521     }
522     if(!(flag&2)) continue; // bit 1 of flag = directory!
523
524     if (queryId.GetAliCDBPath().Level1Comprises(level1)) {
525       GetEntriesForLevel1(level0, level1, queryId, result);
526     }
527   }
528
529   gSystem->FreeDirectory(level0DirPtr);
530 }
531
532 //_____________________________________________________________________________
533 void AliCDBLocal::GetEntriesForLevel1(const char* level0, const char* level1,
534     const AliCDBId& queryId, TList* result) {
535   // multiple request (AliCDBStorage::GetAll)
536
537   TString level1Dir = Form("%s/%s/%s", fBaseDirectory.Data(), level0,level1);
538
539   void* level1DirPtr = gSystem->OpenDirectory(level1Dir);
540   if (!level1DirPtr) {
541     AliDebug(2,Form("Can't open level1 directory <%s>!",
542           level1Dir.Data()));
543     return;
544   }
545
546   const char* level2;
547   Long_t flag=0;
548   while ((level2 = gSystem->GetDirEntry(level1DirPtr))) {
549
550     TString level2Str(level2);
551     // skip directories starting with a dot (".svn" and similar in old svn working copies)
552     if (level2Str.BeginsWith('.')) {
553       continue;
554     }
555
556     TString fullPath = Form("%s/%s",level1Dir.Data(), level2); 
557
558     Int_t res=gSystem->GetPathInfo(fullPath.Data(), 0, (Long64_t*) 0, &flag, 0);
559
560     if(res){
561       AliDebug(2, Form("Error reading entry %s !",level2Str.Data()));
562       continue;
563     }
564     if(!(flag&2)) continue; // skip if not a directory
565
566     if (queryId.GetAliCDBPath().Level2Comprises(level2)) {
567
568       AliCDBPath entryPath(level0, level1, level2);
569
570       AliCDBId entryId(entryPath, queryId.GetAliCDBRunRange(),
571           queryId.GetVersion(), queryId.GetSubVersion());
572
573       // check filenames to see if any includes queryId.GetAliCDBRunRange()
574       void* level2DirPtr = gSystem->OpenDirectory(fullPath);
575       if (!level2DirPtr) {
576         AliDebug(2,Form("Can't open level2 directory <%s>!", fullPath.Data()));
577         return;
578       }
579       const char* level3;
580       Long_t file_flag=0;
581       while ((level3 = gSystem->GetDirEntry(level2DirPtr))) {
582         TString fileName(level3);
583         TString fullFileName = Form("%s/%s", fullPath.Data(), level3); 
584
585         Int_t file_res=gSystem->GetPathInfo(fullFileName.Data(), 0, (Long64_t*) 0, &file_flag, 0);
586
587         if(file_res){
588           AliDebug(2, Form("Error reading entry %s !",level2Str.Data()));
589           continue;
590         }
591         if(file_flag)
592           continue; // it is not a regular file!
593
594         // skip if result already contains an entry for this path
595         Bool_t alreadyLoaded = kFALSE;
596         Int_t nEntries = result->GetEntries();
597         for(int i=0; i<nEntries; i++){
598           AliCDBEntry *lEntry = (AliCDBEntry*) result->At(i);
599           AliCDBId lId = lEntry->GetId();
600           TString lPath = lId.GetPath();
601           if(lPath.EqualTo(entryPath.GetPath())){
602             alreadyLoaded = kTRUE;
603             break;
604           }
605         }
606         if (alreadyLoaded) continue;
607
608         //skip filenames not matching the regex below
609         TRegexp re("^Run[0-9]+_[0-9]+_");
610         if(!fileName.Contains(re))
611           continue;
612         // Extract first- and last-run and version and subversion.
613         // This allows to avoid quering for a calibration path if we did not find a filename with
614         // run-range including the one specified in the query and
615         // with version, subversion matching the query
616         TString fn = fileName( 3, fileName.Length()-3 );
617         TString firstRunStr = fn( 0, fn.First('_') );
618         fn.Remove( 0, firstRunStr.Length()+1 );
619         TString lastRunStr = fn( 0, fn.First('_') );
620         fn.Remove( 0, lastRunStr.Length()+1 );
621         TString versionStr = fn( 1, fn.First('_')-1 );
622         fn.Remove( 0, versionStr.Length()+2 );
623         TString subvStr = fn(1, fn.First('.')-1);
624         Int_t firstRun = firstRunStr.Atoi();
625         Int_t lastRun  = lastRunStr.Atoi();
626         AliCDBRunRange rr(firstRun,lastRun);
627         Int_t version = versionStr.Atoi();
628         Int_t subVersion = subvStr.Atoi();
629
630         AliCDBEntry* anEntry = 0;
631         Bool_t versionOK = kTRUE, subVersionOK = kTRUE;
632         if ( queryId.HasVersion() && version!=queryId.GetVersion())
633           versionOK = kFALSE;
634         if ( queryId.HasSubVersion() && subVersion!=queryId.GetSubVersion())
635           subVersionOK = kFALSE;
636         if (rr.Comprises(queryId.GetAliCDBRunRange()) && versionOK && subVersionOK )
637         {
638           anEntry = GetEntry(entryId);
639           result->Add(anEntry);
640         }
641       }
642     }
643   }
644
645   gSystem->FreeDirectory(level1DirPtr);
646 }
647
648 //_____________________________________________________________________________
649 TList* AliCDBLocal::GetEntries(const AliCDBId& queryId) {
650 // multiple request (AliCDBStorage::GetAll)
651
652   TList* result = new TList();
653   result->SetOwner();
654
655   // if querying for fRun and not specifying a version, look in the fValidFileIds list
656   if(queryId.GetFirstRun() == fRun && !queryId.HasVersion()) {
657     // get id from fValidFileIds
658     TIter *iter = new TIter(&fValidFileIds);
659     TObjArray selectedIds;
660     selectedIds.SetOwner(1);
661
662     // loop on list of valid Ids to select the right version to get.
663     // According to query and to the selection criteria list, version can be the highest or exact
664     AliCDBId* anIdPtr=0;
665     AliCDBId* dataId=0;
666     AliCDBPath queryPath = queryId.GetAliCDBPath();
667     while((anIdPtr = dynamic_cast<AliCDBId*> (iter->Next()))){
668       AliCDBPath thisCDBPath = anIdPtr->GetAliCDBPath();
669       if(!(queryPath.Comprises(thisCDBPath))){
670         continue;
671       }
672
673       AliCDBId thisId(*anIdPtr);
674       dataId = GetId(thisId);
675       if(dataId)
676         selectedIds.Add(dataId);
677     }
678
679     delete iter; iter=0;
680
681     // selectedIds contains the Ids of the files matching all requests of query!
682     // All the objects are now ready to be retrieved
683     iter = new TIter(&selectedIds);
684     while((anIdPtr = dynamic_cast<AliCDBId*> (iter->Next()))){
685       AliCDBEntry* anEntry = GetEntry(*anIdPtr);
686       if(anEntry) result->Add(anEntry);
687     }
688     delete iter; iter=0;
689     return result;
690   }
691
692   void* storageDirPtr = gSystem->OpenDirectory(fBaseDirectory);
693   if (!storageDirPtr) {
694     AliDebug(2,Form("Can't open storage directory <%s>",
695           fBaseDirectory.Data()));
696     return NULL;
697   }
698
699   const char* level0;
700   Long_t flag=0;
701   while ((level0 = gSystem->GetDirEntry(storageDirPtr))) {
702
703     TString level0Str(level0);
704     // skip directories starting with a dot (".svn" and similar in old svn working copies)
705     if (level0Str.BeginsWith('.')) {
706       continue;
707     }
708
709     TString fullPath = Form("%s/%s",fBaseDirectory.Data(), level0); 
710
711     Int_t res=gSystem->GetPathInfo(fullPath.Data(), 0, (Long64_t*) 0, &flag, 0);
712
713     if(res){
714       AliDebug(2, Form("Error reading entry %s !",level0Str.Data()));
715       continue;
716     }
717
718     if(!(flag&2)) continue; // bit 1 of flag = directory!                               
719
720     if (queryId.GetAliCDBPath().Level0Comprises(level0)) {
721       GetEntriesForLevel0(level0, queryId, result);
722     }
723   }
724
725   gSystem->FreeDirectory(storageDirPtr);
726
727   return result;        
728 }
729
730 //_____________________________________________________________________________
731 Bool_t AliCDBLocal::PutEntry(AliCDBEntry* entry, const char* mirrors) {
732 // put an AliCDBEntry object into the database
733
734   AliCDBId& id = entry->GetId();
735
736   // set version and subVersion for the entry to be stored
737   if (!PrepareId(id)) return kFALSE;
738
739
740   // build filename from entry's id
741   TString filename="";
742   if (!IdToFilename(id, filename)) {
743
744     AliDebug(2,Form("Bad ID encountered! Subnormal error!"));
745     return kFALSE;
746   }
747
748   TString mirrorsString(mirrors);
749   if(!mirrorsString.IsNull())
750     AliWarning("AliCDBLocal storage cannot take mirror SEs into account. They will be ignored.");
751
752   // open file
753   TFile file(filename, "CREATE");
754   if (!file.IsOpen()) {
755     AliError(Form("Can't open file <%s>!", filename.Data()));
756     return kFALSE;
757   }
758
759   //SetTreeToFile(entry, &file);
760
761   entry->SetVersion(id.GetVersion());
762   entry->SetSubVersion(id.GetSubVersion());
763
764   // write object (key name: "AliCDBEntry")
765   Bool_t result = file.WriteTObject(entry, "AliCDBEntry");
766   if (!result) AliDebug(2,Form("Can't write entry to file: %s", filename.Data()));
767
768   file.Close();
769   if(result) {
770     if(!(id.GetPath().Contains("SHUTTLE/STATUS")))
771       AliInfo(Form("CDB object stored into file %s",filename.Data()));
772   }
773
774   return result;
775 }
776
777 //_____________________________________________________________________________
778 TList* AliCDBLocal::GetIdListFromFile(const char* fileName){
779
780   TString fullFileName(fileName);
781   fullFileName.Prepend(fBaseDirectory+'/');
782   TFile *file = TFile::Open(fullFileName);
783   if (!file) {
784     AliError(Form("Can't open selection file <%s>!", fullFileName.Data()));
785     return NULL;
786   }
787   file->cd();
788
789   TList *list = new TList();
790   list->SetOwner();
791   int i=0;
792   TString keycycle;
793
794   AliCDBId *id;
795   while(1){
796     i++;
797     keycycle = "AliCDBId;";
798     keycycle+=i;
799
800     id = (AliCDBId*) file->Get(keycycle);
801     if(!id) break;
802     list->AddFirst(id);
803   }
804   file->Close(); delete file; file=0;   
805   return list;
806 }
807
808 //_____________________________________________________________________________
809 Bool_t AliCDBLocal::Contains(const char* path) const{
810 // check for path in storage's fBaseDirectory
811
812   TString dirName = Form("%s/%s", fBaseDirectory.Data(), path);
813   Bool_t result=kFALSE;
814
815   void* dirPtr = gSystem->OpenDirectory(dirName); 
816   if (dirPtr) result=kTRUE;
817   gSystem->FreeDirectory(dirPtr);
818
819   return result;
820 }
821
822 //_____________________________________________________________________________
823 void AliCDBLocal::QueryValidFiles() {
824 // Query the CDB for files valid for AliCDBStorage::fRun.
825 // Fills list fValidFileIds with AliCDBId objects extracted from CDB files
826 // present in the local storage.
827 // If fVersion was not set, fValidFileIds is filled with highest versions.
828 // In the CVMFS case, the fValidFileIds is filled from the file containing
829 // the filepaths corresponding to the highest versions for the give OCDB tag
830 // by launching the script which extracts the last versions for the given run.
831 //
832
833   if(fVersion != -1) AliWarning ("Version parameter is not used by local storage query!");
834   if(fMetaDataFilter) {
835     AliWarning ("CDB meta data parameters are not used by local storage query!");
836     delete fMetaDataFilter; fMetaDataFilter=0;
837   }
838
839   // Check if in CVMFS case
840   TString cvmfsOcdbTag(gSystem->Getenv("OCDB_PATH"));
841   if (!cvmfsOcdbTag.IsNull()) {
842     QueryValidCVMFSFiles(cvmfsOcdbTag);
843     return;
844   }
845
846   void* storageDirPtr = gSystem->OpenDirectory(fBaseDirectory);
847
848   const char* level0;
849   while ((level0 = gSystem->GetDirEntry(storageDirPtr))) {
850
851     TString level0Str(level0);
852     if (level0Str.BeginsWith(".")) {
853       continue;
854     }
855
856     if (fPathFilter.Level0Comprises(level0)) {
857       TString level0Dir = Form("%s/%s",fBaseDirectory.Data(),level0);
858       void* level0DirPtr = gSystem->OpenDirectory(level0Dir);
859       const char* level1;
860       while ((level1 = gSystem->GetDirEntry(level0DirPtr))) {
861
862         TString level1Str(level1);
863         if (level1Str.BeginsWith(".")) {
864           continue;
865         }
866
867         if (fPathFilter.Level1Comprises(level1)) {
868           TString level1Dir = Form("%s/%s/%s",
869               fBaseDirectory.Data(),level0,level1);
870
871           void* level1DirPtr = gSystem->OpenDirectory(level1Dir);
872           const char* level2;
873           while ((level2 = gSystem->GetDirEntry(level1DirPtr))) {
874
875             TString level2Str(level2);
876             if (level2Str.BeginsWith(".")) {
877               continue;
878             }
879
880             if (fPathFilter.Level2Comprises(level2)) {
881               TString dirName = Form("%s/%s/%s/%s", fBaseDirectory.Data(), level0, level1, level2);
882
883               void* dirPtr = gSystem->OpenDirectory(dirName);
884
885               const char* filename;
886
887               AliCDBRunRange aRunRange; // the runRange got from filename
888               AliCDBRunRange hvRunRange; // the runRange of the highest version valid file
889               Int_t aVersion, aSubVersion; // the version and subVersion got from filename
890               Int_t highestV=-1, highestSubV=-1; // the highest version and subVersion for this calibration type
891
892               while ((filename = gSystem->GetDirEntry(dirPtr))) { // loop on files
893
894                 TString aString(filename);
895                 if (aString.BeginsWith(".")) continue;
896
897                 if (!FilenameToId(filename, aRunRange, aVersion, aSubVersion)) {
898                   continue;
899                 }
900
901                 AliCDBRunRange runrg(fRun, fRun);
902                 if (!aRunRange.Comprises(runrg))
903                   continue;
904
905                 // check to keep the highest version/subversion (in case of more than one)
906                 if (aVersion > highestV) {
907                   highestV = aVersion;
908                   highestSubV = aSubVersion;
909                   hvRunRange = aRunRange;
910                 } else if (aVersion == highestV) {
911                   if (aSubVersion > highestSubV) {
912                     highestSubV = aSubVersion;
913                     hvRunRange = aRunRange;
914                   }
915                 }
916               }
917               if(highestV >= 0){
918                 AliCDBPath validPath(level0, level1, level2);
919                 AliCDBId *validId = new AliCDBId(validPath, hvRunRange, highestV, highestSubV);
920                 fValidFileIds.AddLast(validId);
921               }
922
923               gSystem->FreeDirectory(dirPtr);
924             }
925           }
926           gSystem->FreeDirectory(level1DirPtr);
927         }
928       }
929       gSystem->FreeDirectory(level0DirPtr);
930     }
931   }
932   gSystem->FreeDirectory(storageDirPtr);
933
934 }
935
936 //_____________________________________________________________________________
937 void AliCDBLocal::QueryValidCVMFSFiles(TString& cvmfsOcdbTag) {
938 // Called in the CVMFS case to fill the fValidFileIds from the file containing
939 // the filepaths corresponding to the highest versions for the given OCDB tag
940 // by launching the script which extracts the last versions for the given run.
941 //
942
943   TString command = cvmfsOcdbTag;
944   AliDebug(3, Form("Getting valid files from CVMFS-OCDB tag \"%s\"", cvmfsOcdbTag.Data()));
945   // CVMFS-OCDB tag. This is the file $OCDB_PATH/catalogue/20??.list.gz
946   // containing all CDB file paths (for the given AR tag)
947   cvmfsOcdbTag.Strip(TString::kTrailing, '/');
948   cvmfsOcdbTag.Append("/");
949   gSystem->ExpandPathName(cvmfsOcdbTag);
950   if ( gSystem->AccessPathName(cvmfsOcdbTag) )
951     AliFatal(Form("cvmfs OCDB set to an invalid path: %s", cvmfsOcdbTag.Data()));
952
953   // The file containing the list of valid files for the current run has to be generated
954   // by running the (shell+awk) script on the CVMFS OCDB tag file.
955
956   // the script in cvmfs to extract CDB filepaths for the given run has the following fullpath
957   // w.r.t. $OCDB_PATH: bin/OCDBperRun.sh
958   command = command.Strip(TString::kTrailing, '/');
959   command.Append("/bin/getOCDBFilesPerRun.sh "); 
960   command += cvmfsOcdbTag;
961   // from URI define the last two levels of the path of the cvmfs ocdb tag (e.g. data/2012.list.gz)
962   TString uri(GetURI());
963   uri.Remove(TString::kTrailing, '/');
964   TObjArray * osArr = uri.Tokenize('/');
965   TObjString* mcdata_os = dynamic_cast<TObjString*>(osArr->At(osArr->GetEntries()-3));
966   TObjString* yeartype_os = 0;
967   TString mcdata = mcdata_os->GetString();
968   if( mcdata == TString("data")) {
969     yeartype_os = dynamic_cast<TObjString*>(osArr->At(osArr->GetEntries()-2));
970   } else {
971     mcdata_os = dynamic_cast<TObjString*>(osArr->At(osArr->GetEntries()-2));
972     yeartype_os = dynamic_cast<TObjString*>(osArr->At(osArr->GetEntries()-1));
973   }
974   mcdata = mcdata_os->GetString();
975   TString yeartype = yeartype_os->GetString();
976   command += mcdata;
977   command += '/';
978   command += yeartype;
979   command += ".list.gz cvmfs ";
980   command += TString::Itoa(fRun,10);
981   command += ' ';
982   command += TString::Itoa(fRun,10);
983   command += " -y > ";
984   TString runValidFile(gSystem->WorkingDirectory());
985   runValidFile += '/';
986   runValidFile += mcdata;
987   runValidFile += '_';
988   runValidFile += yeartype;
989   runValidFile += '_';
990   runValidFile += TString::Itoa(fRun,10);
991   command += runValidFile;
992   AliDebug(3, Form("Running command: \"%s\"",command.Data()));
993   Int_t result = gSystem->Exec(command.Data());
994   if(result != 0) {
995     AliError(Form("Was not able to execute \"%s\"", command.Data()));
996   }
997
998   // We expect the file with valid paths for this run to be generated in the current directory
999   // and to be named as the CVMFS OCDB tag, without .gz, with '_runnumber' appended
1000   // Fill fValidFileIds from file
1001   std::ifstream file (runValidFile.Data());
1002   if (!file.is_open()) {
1003     AliFatal(Form("Error opening file \"%s\"!", runValidFile.Data()));
1004   }
1005   TString filepath;
1006   while (filepath.ReadLine(file)) {
1007     // skip line in case it is not a root file path
1008     if(! filepath.EndsWith(".root")) {
1009       continue;
1010     }
1011     //extract three-level path and basename
1012     TObjArray *tokens = filepath.Tokenize('/');
1013     if (tokens->GetEntries() < 5) {
1014       AliError(Form("\"%s\" is not a valid cvmfs path for an OCDB object", filepath.Data()));
1015       continue;
1016     }
1017     TObjString *baseNameOstr = (TObjString*) tokens->At(tokens->GetEntries()-1);
1018     TString baseName(baseNameOstr->String());
1019     TObjString *l0oStr = (TObjString*) tokens->At(tokens->GetEntries()-4);
1020     TObjString *l1oStr = (TObjString*) tokens->At(tokens->GetEntries()-3);
1021     TObjString *l2oStr = (TObjString*) tokens->At(tokens->GetEntries()-2);
1022     TString l0(l0oStr->String());
1023     TString l1(l1oStr->String());
1024     TString l2(l2oStr->String());
1025     TString threeLevels = l0 + '/' + l1 + '/' + l2;
1026
1027     AliCDBPath validPath(threeLevels);
1028     //use basename and three-level path to create Id
1029     AliCDBRunRange aRunRange; // the runRange got from filename
1030     Int_t aVersion, aSubVersion; // the version and subVersion got from filename
1031     if ( !FilenameToId(baseName, aRunRange, aVersion, aSubVersion) )
1032       AliError( Form("Could not create a valid CDB id from path: \"%s\"", filepath.Data()) );
1033
1034     AliCDBRunRange runrg(fRun,fRun);
1035     if (!aRunRange.Comprises(runrg)) continue; // should never happen (would mean awk script wrong output)
1036     // aRunRange contains requested run!
1037     AliCDBId *validId = new AliCDBId(validPath,aRunRange,aVersion,aSubVersion);
1038     fValidFileIds.AddLast(validId);
1039   }
1040
1041   file.close();
1042   return;
1043 }
1044
1045 /////////////////////////////////////////////////////////////////////////////////////////////////
1046 //                                                                                             //
1047 // AliCDBLocal factory                                                                         //
1048 //                                                                                             //
1049 /////////////////////////////////////////////////////////////////////////////////////////////////
1050
1051 ClassImp(AliCDBLocalFactory)
1052
1053 //_____________________________________________________________________________
1054 Bool_t AliCDBLocalFactory::Validate(const char* dbString) {
1055 // check if the string is valid local URI
1056
1057   TRegexp dbPatternLocal("^local://.+$");
1058
1059   return (TString(dbString).Contains(dbPatternLocal) || TString(dbString).BeginsWith("snapshot://folder="));
1060 }
1061
1062 //_____________________________________________________________________________
1063 AliCDBParam* AliCDBLocalFactory::CreateParameter(const char* dbString) {
1064 // create AliCDBLocalParam class from the URI string
1065
1066   if (!Validate(dbString)) {
1067     return NULL;
1068   }
1069
1070   TString checkSS(dbString);
1071   if(checkSS.BeginsWith("snapshot://"))
1072   {
1073     TString snapshotPath("OCDB");
1074     snapshotPath.Prepend(TString(gSystem->WorkingDirectory()) + '/');
1075     checkSS.Remove(0,checkSS.First(':')+3);
1076     return new AliCDBLocalParam(snapshotPath,checkSS);
1077   }
1078
1079   // if the string argument is not a snapshot URI, than it is a plain local URI
1080   TString pathname(dbString + sizeof("local://") - 1);
1081
1082   if(gSystem->ExpandPathName(pathname))
1083     return NULL;
1084
1085   if (pathname[0] != '/') {
1086     pathname.Prepend(TString(gSystem->WorkingDirectory()) + '/');
1087   }
1088   //pathname.Prepend("local://");
1089
1090   return new AliCDBLocalParam(pathname);
1091 }
1092
1093 //_____________________________________________________________________________
1094 AliCDBStorage* AliCDBLocalFactory::Create(const AliCDBParam* param) {
1095 // create AliCDBLocal storage instance from parameters
1096
1097   if (AliCDBLocalParam::Class() == param->IsA()) {
1098
1099     const AliCDBLocalParam* localParam = 
1100       (const AliCDBLocalParam*) param;
1101
1102     return new AliCDBLocal(localParam->GetPath());
1103   }
1104
1105   return NULL;
1106 }
1107 //_____________________________________________________________________________
1108 void AliCDBLocal::SetRetry(Int_t /* nretry */, Int_t /* initsec */) {
1109
1110   // Function to set the exponential retry for putting entries in the OCDB
1111
1112   AliInfo("This function sets the exponential retry for putting entries in the OCDB - to be used ONLY for AliCDBGrid --> returning without doing anything");
1113   return;
1114
1115
1116
1117
1118 /////////////////////////////////////////////////////////////////////////////////////////////////
1119 //                                                                                             //
1120 // AliCDBLocal Parameter class                                                                 //                                          //
1121 //                                                                                             //
1122 /////////////////////////////////////////////////////////////////////////////////////////////////
1123
1124 ClassImp(AliCDBLocalParam)
1125
1126   //_____________________________________________________________________________
1127   AliCDBLocalParam::AliCDBLocalParam():
1128     AliCDBParam(),
1129     fDBPath()
1130 {
1131   // default constructor
1132
1133 }
1134
1135 //_____________________________________________________________________________
1136 AliCDBLocalParam::AliCDBLocalParam(const char* dbPath):
1137   AliCDBParam(),
1138   fDBPath(dbPath)
1139 {
1140   // constructor
1141
1142   SetType("local");
1143   SetURI(TString("local://") + dbPath);
1144 }
1145
1146 //_____________________________________________________________________________
1147 AliCDBLocalParam::AliCDBLocalParam(const char* dbPath, const char* uri):
1148   AliCDBParam(),
1149   fDBPath(dbPath)
1150 {
1151   // constructor
1152
1153   SetType("local");
1154   SetURI(TString("alien://") + uri);
1155 }
1156
1157 //_____________________________________________________________________________
1158 AliCDBLocalParam::~AliCDBLocalParam() {
1159   // destructor
1160
1161 }
1162
1163 //_____________________________________________________________________________
1164 AliCDBParam* AliCDBLocalParam::CloneParam() const {
1165   // clone parameter
1166
1167   return new AliCDBLocalParam(fDBPath);
1168 }
1169
1170 //_____________________________________________________________________________
1171 ULong_t AliCDBLocalParam::Hash() const {
1172   // return Hash function
1173
1174   return fDBPath.Hash();
1175 }
1176
1177 //_____________________________________________________________________________
1178 Bool_t AliCDBLocalParam::IsEqual(const TObject* obj) const {
1179   // check if this object is equal to AliCDBParam obj
1180
1181   if (this == obj) {
1182     return kTRUE;
1183   }
1184
1185   if (AliCDBLocalParam::Class() != obj->IsA()) {
1186     return kFALSE;
1187   }
1188
1189   AliCDBLocalParam* other = (AliCDBLocalParam*) obj;
1190
1191   return fDBPath == other->fDBPath;
1192 }
1193