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