]> git.uio.no Git - u/mrichter/AliRoot.git/blob - STEER/CDB/AliCDBLocal.cxx
6962b72be7d50f6435c058d60ed695778ace7304
[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("The data ID is undefined!"));
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. This allows to avoid quering for a calibration path
613         // if we did not find a filename with interesting run-range.
614         TString firstRunStr = fileName(3,fileName.First('_')-3);
615         TString lastRunStr  = fileName(fileName.First('_')+1,fileName.Length()-fileName.First('_')-2);
616         Int_t firstRun = firstRunStr.Atoi();
617         Int_t lastRun  = lastRunStr.Atoi();
618         AliCDBRunRange rr(firstRun,lastRun);
619
620         AliCDBEntry* anEntry = 0;
621         if (rr.Comprises(queryId.GetAliCDBRunRange()))
622           anEntry = GetEntry(entryId);
623         if (anEntry)
624           result->Add(anEntry);
625       }
626     }
627   }
628
629   gSystem->FreeDirectory(level1DirPtr);
630 }
631
632 //_____________________________________________________________________________
633 TList* AliCDBLocal::GetEntries(const AliCDBId& queryId) {
634 // multiple request (AliCDBStorage::GetAll)
635
636   TList* result = new TList();
637   result->SetOwner();
638
639   // if querying for fRun and not specifying a version, look in the fValidFileIds list
640   if(queryId.GetFirstRun() == fRun && !queryId.HasVersion()) {
641     // get id from fValidFileIds
642     TIter *iter = new TIter(&fValidFileIds);
643     TObjArray selectedIds;
644     selectedIds.SetOwner(1);
645
646     // loop on list of valid Ids to select the right version to get.
647     // According to query and to the selection criteria list, version can be the highest or exact
648     AliCDBId* anIdPtr=0;
649     AliCDBId* dataId=0;
650     AliCDBPath queryPath = queryId.GetAliCDBPath();
651     while((anIdPtr = dynamic_cast<AliCDBId*> (iter->Next()))){
652       AliCDBPath thisCDBPath = anIdPtr->GetAliCDBPath();
653       if(!(queryPath.Comprises(thisCDBPath))){
654         continue;
655       }
656
657       AliCDBId thisId(*anIdPtr);
658       dataId = GetId(thisId);
659       if(dataId)
660         selectedIds.Add(dataId);
661     }
662
663     delete iter; iter=0;
664
665     // selectedIds contains the Ids of the files matching all requests of query!
666     // All the objects are now ready to be retrieved
667     iter = new TIter(&selectedIds);
668     while((anIdPtr = dynamic_cast<AliCDBId*> (iter->Next()))){
669       AliCDBEntry* anEntry = GetEntry(*anIdPtr);
670       if(anEntry) result->Add(anEntry);
671     }
672     delete iter; iter=0;
673     return result;
674   }
675
676   void* storageDirPtr = gSystem->OpenDirectory(fBaseDirectory);
677   if (!storageDirPtr) {
678     AliDebug(2,Form("Can't open storage directory <%s>",
679           fBaseDirectory.Data()));
680     return NULL;
681   }
682
683   const char* level0;
684   Long_t flag=0;
685   while ((level0 = gSystem->GetDirEntry(storageDirPtr))) {
686
687     TString level0Str(level0);
688     // skip directories starting with a dot (".svn" and similar in old svn working copies)
689     if (level0Str.BeginsWith('.')) {
690       continue;
691     }
692
693     TString fullPath = Form("%s/%s",fBaseDirectory.Data(), level0); 
694
695     Int_t res=gSystem->GetPathInfo(fullPath.Data(), 0, (Long64_t*) 0, &flag, 0);
696
697     if(res){
698       AliDebug(2, Form("Error reading entry %s !",level0Str.Data()));
699       continue;
700     }
701
702     if(!(flag&2)) continue; // bit 1 of flag = directory!                               
703
704     if (queryId.GetAliCDBPath().Level0Comprises(level0)) {
705       GetEntriesForLevel0(level0, queryId, result);
706     }
707   }
708
709   gSystem->FreeDirectory(storageDirPtr);
710
711   return result;        
712 }
713
714 //_____________________________________________________________________________
715 Bool_t AliCDBLocal::PutEntry(AliCDBEntry* entry, const char* mirrors) {
716 // put an AliCDBEntry object into the database
717
718   AliCDBId& id = entry->GetId();
719
720   // set version and subVersion for the entry to be stored
721   if (!PrepareId(id)) return kFALSE;
722
723
724   // build filename from entry's id
725   TString filename="";
726   if (!IdToFilename(id, filename)) {
727
728     AliDebug(2,Form("Bad ID encountered! Subnormal error!"));
729     return kFALSE;
730   }
731
732   TString mirrorsString(mirrors);
733   if(!mirrorsString.IsNull())
734     AliWarning("AliCDBLocal storage cannot take mirror SEs into account. They will be ignored.");
735
736   // open file
737   TFile file(filename, "CREATE");
738   if (!file.IsOpen()) {
739     AliError(Form("Can't open file <%s>!", filename.Data()));
740     return kFALSE;
741   }
742
743   //SetTreeToFile(entry, &file);
744
745   entry->SetVersion(id.GetVersion());
746   entry->SetSubVersion(id.GetSubVersion());
747
748   // write object (key name: "AliCDBEntry")
749   Bool_t result = file.WriteTObject(entry, "AliCDBEntry");
750   if (!result) AliDebug(2,Form("Can't write entry to file: %s", filename.Data()));
751
752   file.Close();
753   if(result) {
754     if(!(id.GetPath().Contains("SHUTTLE/STATUS")))
755       AliInfo(Form("CDB object stored into file %s",filename.Data()));
756   }
757
758   return result;
759 }
760
761 //_____________________________________________________________________________
762 TList* AliCDBLocal::GetIdListFromFile(const char* fileName){
763
764   TString fullFileName(fileName);
765   fullFileName.Prepend(fBaseDirectory+'/');
766   TFile *file = TFile::Open(fullFileName);
767   if (!file) {
768     AliError(Form("Can't open selection file <%s>!", fullFileName.Data()));
769     return NULL;
770   }
771   file->cd();
772
773   TList *list = new TList();
774   list->SetOwner();
775   int i=0;
776   TString keycycle;
777
778   AliCDBId *id;
779   while(1){
780     i++;
781     keycycle = "AliCDBId;";
782     keycycle+=i;
783
784     id = (AliCDBId*) file->Get(keycycle);
785     if(!id) break;
786     list->AddFirst(id);
787   }
788   file->Close(); delete file; file=0;   
789   return list;
790 }
791
792 //_____________________________________________________________________________
793 Bool_t AliCDBLocal::Contains(const char* path) const{
794 // check for path in storage's fBaseDirectory
795
796   TString dirName = Form("%s/%s", fBaseDirectory.Data(), path);
797   Bool_t result=kFALSE;
798
799   void* dirPtr = gSystem->OpenDirectory(dirName); 
800   if (dirPtr) result=kTRUE;
801   gSystem->FreeDirectory(dirPtr);
802
803   return result;
804 }
805
806 //_____________________________________________________________________________
807 void AliCDBLocal::QueryValidFiles() {
808 // Query the CDB for files valid for AliCDBStorage::fRun.
809 // Fills list fValidFileIds with AliCDBId objects extracted from CDB files
810 // present in the local storage.
811 // If fVersion was not set, fValidFileIds is filled with highest versions.
812 // In the CVMFS case, the fValidFileIds is filled from the file containing
813 // the filepaths corresponding to the highest versions for the give OCDB tag
814 // by launching the script which extracts the last versions for the given run.
815 //
816
817   if(fVersion != -1) AliWarning ("Version parameter is not used by local storage query!");
818   if(fMetaDataFilter) {
819     AliWarning ("CDB meta data parameters are not used by local storage query!");
820     delete fMetaDataFilter; fMetaDataFilter=0;
821   }
822
823   // Check if in CVMFS case
824   TString cvmfsOcdbTag(gSystem->Getenv("OCDB_PATH"));
825   if (!cvmfsOcdbTag.IsNull()) {
826     QueryValidCVMFSFiles(cvmfsOcdbTag);
827     return;
828   }
829
830   void* storageDirPtr = gSystem->OpenDirectory(fBaseDirectory);
831
832   const char* level0;
833   while ((level0 = gSystem->GetDirEntry(storageDirPtr))) {
834
835     TString level0Str(level0);
836     if (level0Str.BeginsWith(".")) {
837       continue;
838     }
839
840     if (fPathFilter.Level0Comprises(level0)) {
841       TString level0Dir = Form("%s/%s",fBaseDirectory.Data(),level0);
842       void* level0DirPtr = gSystem->OpenDirectory(level0Dir);
843       const char* level1;
844       while ((level1 = gSystem->GetDirEntry(level0DirPtr))) {
845
846         TString level1Str(level1);
847         if (level1Str.BeginsWith(".")) {
848           continue;
849         }
850
851         if (fPathFilter.Level1Comprises(level1)) {
852           TString level1Dir = Form("%s/%s/%s",
853               fBaseDirectory.Data(),level0,level1);
854
855           void* level1DirPtr = gSystem->OpenDirectory(level1Dir);
856           const char* level2;
857           while ((level2 = gSystem->GetDirEntry(level1DirPtr))) {
858
859             TString level2Str(level2);
860             if (level2Str.BeginsWith(".")) {
861               continue;
862             }
863
864             if (fPathFilter.Level2Comprises(level2)) {
865               TString dirName = Form("%s/%s/%s/%s", fBaseDirectory.Data(), level0, level1, level2);
866
867               void* dirPtr = gSystem->OpenDirectory(dirName);
868
869               const char* filename;
870
871               AliCDBRunRange aRunRange; // the runRange got from filename
872               AliCDBRunRange hvRunRange; // the runRange of the highest version valid file
873               Int_t aVersion, aSubVersion; // the version and subVersion got from filename
874               Int_t highestV=-1, highestSubV=-1; // the highest version and subVersion for this calibration type
875
876               while ((filename = gSystem->GetDirEntry(dirPtr))) { // loop on files
877
878                 TString aString(filename);
879                 if (aString.BeginsWith(".")) continue;
880
881                 if (!FilenameToId(filename, aRunRange, aVersion, aSubVersion)) {
882                   continue;
883                 }
884
885                 AliCDBRunRange runrg(fRun, fRun);
886                 if (!aRunRange.Comprises(runrg))
887                   continue;
888
889                 // check to keep the highest version/subversion (in case of more than one)
890                 if (aVersion > highestV) {
891                   highestV = aVersion;
892                   highestSubV = aSubVersion;
893                   hvRunRange = aRunRange;
894                 } else {
895                   if (aSubVersion > highestSubV) {
896                     highestSubV = aSubVersion;
897                     hvRunRange = aRunRange;
898                   }
899                 }
900               }
901               if(highestV >= 0){
902                 AliCDBPath validPath(level0, level1, level2);
903                 AliCDBId *validId = new AliCDBId(validPath, hvRunRange, highestV, highestSubV);
904                 fValidFileIds.AddLast(validId);
905               }
906
907               gSystem->FreeDirectory(dirPtr);
908             }
909           }
910           gSystem->FreeDirectory(level1DirPtr);
911         }
912       }
913       gSystem->FreeDirectory(level0DirPtr);
914     }
915   }
916   gSystem->FreeDirectory(storageDirPtr);
917
918 }
919
920 //_____________________________________________________________________________
921 void AliCDBLocal::QueryValidCVMFSFiles(TString& cvmfsOcdbTag) {
922 // Called in the CVMFS case to fill the fValidFileIds from the file containing
923 // the filepaths corresponding to the highest versions for the given OCDB tag
924 // by launching the script which extracts the last versions for the given run.
925 //
926
927   TString command = cvmfsOcdbTag;
928   AliDebug(3, Form("Getting valid files from CVMFS-OCDB tag \"%s\"", cvmfsOcdbTag.Data()));
929   // CVMFS-OCDB tag. This is the file $OCDB_PATH/catalogue/20??.list.gz
930   // containing all CDB file paths (for the given AR tag)
931   cvmfsOcdbTag.Strip(TString::kTrailing, '/');
932   cvmfsOcdbTag.Append("/");
933   gSystem->ExpandPathName(cvmfsOcdbTag);
934   if ( gSystem->AccessPathName(cvmfsOcdbTag) )
935     AliFatal(Form("cvmfs OCDB set to an invalid path: %s", cvmfsOcdbTag.Data()));
936
937   // The file containing the list of valid files for the current run has to be generated
938   // by running the (shell+awk) script on the CVMFS OCDB tag file.
939
940   // the script in cvmfs to extract CDB filepaths for the given run has the following fullpath
941   // w.r.t. $OCDB_PATH: bin/OCDBperRun.sh
942   command = command.Strip(TString::kTrailing, '/');
943   command.Append("/bin/getOCDBFilesPerRun.sh "); 
944   command += cvmfsOcdbTag;
945   // from URI define the last two levels of the path of the cvmfs ocdb tag (e.g. data/2012.list.gz)
946   TString uri(GetURI());
947   uri.Remove(TString::kTrailing, '/');
948   TObjArray * osArr = uri.Tokenize('/');
949   TObjString* mcdata_os = dynamic_cast<TObjString*>(osArr->At(osArr->GetEntries()-3));
950   TObjString* yeartype_os = 0;
951   TString mcdata = mcdata_os->GetString();
952   if( mcdata == TString("data")) {
953     yeartype_os = dynamic_cast<TObjString*>(osArr->At(osArr->GetEntries()-2));
954   } else {
955     mcdata_os = dynamic_cast<TObjString*>(osArr->At(osArr->GetEntries()-2));
956     yeartype_os = dynamic_cast<TObjString*>(osArr->At(osArr->GetEntries()-1));
957   }
958   mcdata = mcdata_os->GetString();
959   TString yeartype = yeartype_os->GetString();
960   command += mcdata;
961   command += '/';
962   command += yeartype;
963   command += ".list.gz cvmfs ";
964   command += TString::Itoa(fRun,10);
965   command += ' ';
966   command += TString::Itoa(fRun,10);
967   command += " -y > ";
968   TString runValidFile(gSystem->WorkingDirectory());
969   runValidFile += '/';
970   runValidFile += mcdata;
971   runValidFile += '_';
972   runValidFile += yeartype;
973   runValidFile += '_';
974   runValidFile += TString::Itoa(fRun,10);
975   command += runValidFile;
976   AliDebug(3, Form("Running command: \"%s\"",command.Data()));
977   Int_t result = gSystem->Exec(command.Data());
978   if(result != 0) {
979     AliError(Form("Was not able to execute \"%s\"", command.Data()));
980   }
981
982   // We expect the file with valid paths for this run to be generated in the current directory
983   // and to be named as the CVMFS OCDB tag, without .gz, with '_runnumber' appended
984   // Fill fValidFileIds from file
985   std::ifstream file (runValidFile.Data());
986   if (!file.is_open()) {
987     AliFatal(Form("Error opening file \"%s\"!", runValidFile.Data()));
988   }
989   TString filepath;
990   while (filepath.ReadLine(file)) {
991     // skip line in case it is not a root file path
992     if(! filepath.EndsWith(".root")) {
993       continue;
994     }
995     //extract three-level path and basename
996     TObjArray *tokens = filepath.Tokenize('/');
997     if (tokens->GetEntries() < 5) {
998       AliError(Form("\"%s\" is not a valid cvmfs path for an OCDB object", filepath.Data()));
999       continue;
1000     }
1001     TObjString *baseNameOstr = (TObjString*) tokens->At(tokens->GetEntries()-1);
1002     TString baseName(baseNameOstr->String());
1003     TObjString *l0oStr = (TObjString*) tokens->At(tokens->GetEntries()-4);
1004     TObjString *l1oStr = (TObjString*) tokens->At(tokens->GetEntries()-3);
1005     TObjString *l2oStr = (TObjString*) tokens->At(tokens->GetEntries()-2);
1006     TString l0(l0oStr->String());
1007     TString l1(l1oStr->String());
1008     TString l2(l2oStr->String());
1009     TString threeLevels = l0 + '/' + l1 + '/' + l2;
1010
1011     AliCDBPath validPath(threeLevels);
1012     //use basename and three-level path to create Id
1013     AliCDBRunRange aRunRange; // the runRange got from filename
1014     Int_t aVersion, aSubVersion; // the version and subVersion got from filename
1015     if ( !FilenameToId(baseName, aRunRange, aVersion, aSubVersion) )
1016       AliError( Form("Could not create a valid CDB id from path: \"%s\"", filepath.Data()) );
1017
1018     AliCDBRunRange runrg(fRun,fRun);
1019     if (!aRunRange.Comprises(runrg)) continue; // should never happen (would mean awk script wrong output)
1020     // aRunRange contains requested run!
1021     AliCDBId *validId = new AliCDBId(validPath,aRunRange,aVersion,aSubVersion);
1022     fValidFileIds.AddLast(validId);
1023   }
1024
1025   file.close();
1026   return;
1027 }
1028
1029 /////////////////////////////////////////////////////////////////////////////////////////////////
1030 //                                                                                             //
1031 // AliCDBLocal factory                                                                         //
1032 //                                                                                             //
1033 /////////////////////////////////////////////////////////////////////////////////////////////////
1034
1035 ClassImp(AliCDBLocalFactory)
1036
1037 //_____________________________________________________________________________
1038 Bool_t AliCDBLocalFactory::Validate(const char* dbString) {
1039 // check if the string is valid local URI
1040
1041   TRegexp dbPatternLocal("^local://.+$");
1042
1043   return (TString(dbString).Contains(dbPatternLocal) || TString(dbString).BeginsWith("snapshot://folder="));
1044 }
1045
1046 //_____________________________________________________________________________
1047 AliCDBParam* AliCDBLocalFactory::CreateParameter(const char* dbString) {
1048 // create AliCDBLocalParam class from the URI string
1049
1050   if (!Validate(dbString)) {
1051     return NULL;
1052   }
1053
1054   TString checkSS(dbString);
1055   if(checkSS.BeginsWith("snapshot://"))
1056   {
1057     TString snapshotPath("OCDB");
1058     snapshotPath.Prepend(TString(gSystem->WorkingDirectory()) + '/');
1059     checkSS.Remove(0,checkSS.First(':')+3);
1060     return new AliCDBLocalParam(snapshotPath,checkSS);
1061   }
1062
1063   // if the string argument is not a snapshot URI, than it is a plain local URI
1064   TString pathname(dbString + sizeof("local://") - 1);
1065
1066   if(gSystem->ExpandPathName(pathname))
1067     return NULL;
1068
1069   if (pathname[0] != '/') {
1070     pathname.Prepend(TString(gSystem->WorkingDirectory()) + '/');
1071   }
1072   //pathname.Prepend("local://");
1073
1074   return new AliCDBLocalParam(pathname);
1075 }
1076
1077 //_____________________________________________________________________________
1078 AliCDBStorage* AliCDBLocalFactory::Create(const AliCDBParam* param) {
1079 // create AliCDBLocal storage instance from parameters
1080
1081   if (AliCDBLocalParam::Class() == param->IsA()) {
1082
1083     const AliCDBLocalParam* localParam = 
1084       (const AliCDBLocalParam*) param;
1085
1086     return new AliCDBLocal(localParam->GetPath());
1087   }
1088
1089   return NULL;
1090 }
1091 //_____________________________________________________________________________
1092 void AliCDBLocal::SetRetry(Int_t /* nretry */, Int_t /* initsec */) {
1093
1094   // Function to set the exponential retry for putting entries in the OCDB
1095
1096   AliInfo("This function sets the exponential retry for putting entries in the OCDB - to be used ONLY for AliCDBGrid --> returning without doing anything");
1097   return;
1098
1099
1100
1101
1102 /////////////////////////////////////////////////////////////////////////////////////////////////
1103 //                                                                                             //
1104 // AliCDBLocal Parameter class                                                                 //                                          //
1105 //                                                                                             //
1106 /////////////////////////////////////////////////////////////////////////////////////////////////
1107
1108 ClassImp(AliCDBLocalParam)
1109
1110   //_____________________________________________________________________________
1111   AliCDBLocalParam::AliCDBLocalParam():
1112     AliCDBParam(),
1113     fDBPath()
1114 {
1115   // default constructor
1116
1117 }
1118
1119 //_____________________________________________________________________________
1120 AliCDBLocalParam::AliCDBLocalParam(const char* dbPath):
1121   AliCDBParam(),
1122   fDBPath(dbPath)
1123 {
1124   // constructor
1125
1126   SetType("local");
1127   SetURI(TString("local://") + dbPath);
1128 }
1129
1130 //_____________________________________________________________________________
1131 AliCDBLocalParam::AliCDBLocalParam(const char* dbPath, const char* uri):
1132   AliCDBParam(),
1133   fDBPath(dbPath)
1134 {
1135   // constructor
1136
1137   SetType("local");
1138   SetURI(TString("alien://") + uri);
1139 }
1140
1141 //_____________________________________________________________________________
1142 AliCDBLocalParam::~AliCDBLocalParam() {
1143   // destructor
1144
1145 }
1146
1147 //_____________________________________________________________________________
1148 AliCDBParam* AliCDBLocalParam::CloneParam() const {
1149   // clone parameter
1150
1151   return new AliCDBLocalParam(fDBPath);
1152 }
1153
1154 //_____________________________________________________________________________
1155 ULong_t AliCDBLocalParam::Hash() const {
1156   // return Hash function
1157
1158   return fDBPath.Hash();
1159 }
1160
1161 //_____________________________________________________________________________
1162 Bool_t AliCDBLocalParam::IsEqual(const TObject* obj) const {
1163   // check if this object is equal to AliCDBParam obj
1164
1165   if (this == obj) {
1166     return kTRUE;
1167   }
1168
1169   if (AliCDBLocalParam::Class() != obj->IsA()) {
1170     return kFALSE;
1171   }
1172
1173   AliCDBLocalParam* other = (AliCDBLocalParam*) obj;
1174
1175   return fDBPath == other->fDBPath;
1176 }
1177