5f0fa08f6da4b18c8b4a65146f152c932d568b8d
[u/mrichter/AliRoot.git] / STEER / 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 <TSystem.h>
24 #include <TObjString.h>
25 #include <TRegexp.h>
26 #include <TFile.h>
27 #include <TKey.h>
28
29 #include "AliCDBLocal.h"
30 #include "AliCDBEntry.h"
31 #include "AliLog.h"
32
33 ClassImp(AliCDBLocal)
34
35 //_____________________________________________________________________________
36 AliCDBLocal::AliCDBLocal(const char* baseDir):
37 fBaseDirectory(baseDir) 
38 {
39 // constructor
40
41         // check baseDire: trying to cd to baseDir; if it does not exist, create it
42         void* dir = gSystem->OpenDirectory(baseDir);
43         if (dir == NULL) {
44                 if (gSystem->mkdir(baseDir, kTRUE)) {
45                         AliError(Form("Can't open directory <%s>!", baseDir));
46                 }
47
48         } else {
49                 AliDebug(2,Form("Folder <%s> found",fBaseDirectory.Data()));
50                 gSystem->FreeDirectory(dir);
51         }
52 }
53
54 //_____________________________________________________________________________
55 AliCDBLocal::~AliCDBLocal() {
56 // destructor
57
58 }
59
60
61 //_____________________________________________________________________________
62 Bool_t AliCDBLocal::FilenameToId(const char* filename, AliCDBRunRange& runRange,
63         Int_t& version, Int_t& subVersion) {
64 // build AliCDBId from filename numbers
65
66
67         Ssiz_t mSize;
68
69         // valid filename: Run#firstRun_#lastRun_v#version_s#subVersion.root
70         TRegexp keyPattern("^Run[0-9]+_[0-9]+_v[0-9]+_s[0-9]+.root$");
71         keyPattern.Index(filename, &mSize);
72         if (!mSize) {
73                 AliDebug(2, Form("Bad filename <%s>.", filename));
74                 return kFALSE;
75         }
76
77         TString idString(filename);
78         idString.Resize(idString.Length() - sizeof(".root") + 1);
79
80         TObjArray* strArray = (TObjArray*) idString.Tokenize("_");
81
82         TString firstRunString(((TObjString*) strArray->At(0))->GetString());
83         runRange.SetFirstRun(atoi(firstRunString.Data() + 3));
84         runRange.SetLastRun(atoi(((TObjString*) strArray->At(1))->GetString()));
85         
86         TString verString(((TObjString*) strArray->At(2))->GetString());
87         version = atoi(verString.Data() + 1);
88
89         TString subVerString(((TObjString*) strArray->At(3))->GetString());
90         subVersion = atoi(subVerString.Data() + 1);
91
92         delete strArray;
93
94         return kTRUE;
95 }
96
97
98 //_____________________________________________________________________________
99 Bool_t AliCDBLocal::IdToFilename(const AliCDBRunRange& runRange, Int_t version,
100         Int_t subVersion, TString& filename) {
101 // build file name from AliCDBId data (run range, version, subVersion)
102
103         if (!runRange.IsValid()) {
104                 AliDebug(2,Form("Invalid run range <%d, %d>.", 
105                         runRange.GetFirstRun(), runRange.GetLastRun()));
106                 return kFALSE;
107         }
108
109         if (version < 0) {
110                 AliDebug(2,Form("Invalid version <%d>.", version));
111                 return kFALSE;
112         }
113
114         if (subVersion < 0) {
115                 AliDebug(2,Form("Invalid subversion <%s>.", subVersion));
116                 return kFALSE;
117         }
118  
119         filename += "Run";
120         filename += runRange.GetFirstRun();
121         filename += "_";
122         filename += runRange.GetLastRun();
123         filename += "_v";
124         filename += version;
125         filename += "_s";
126         filename += subVersion;
127         filename += ".root";
128
129         return kTRUE;
130 }
131
132 //_____________________________________________________________________________
133 Bool_t AliCDBLocal::PrepareId(AliCDBId& id) {
134 // prepare id (version, subVersion) of the object that will be stored (called by PutEntry)
135
136         TString dirName;
137         dirName += fBaseDirectory;
138         dirName += '/';
139         dirName += id.GetPath();
140
141         // go to the path; if directory does not exist, create it
142         void* dirPtr = gSystem->OpenDirectory(dirName);
143         if (!dirPtr) {
144                 gSystem->mkdir(dirName, kTRUE);
145                 dirPtr = gSystem->OpenDirectory(dirName);
146
147                 if (!dirPtr) {
148                         AliError(Form("Can't create directory <%s>!", 
149                                         dirName.Data()));
150                         return kFALSE;
151                 }
152         }
153
154         const char* filename;
155         AliCDBRunRange aRunRange; // the runRange got from filename 
156         AliCDBRunRange lastRunRange(-1,-1); // highest runRange found
157         Int_t aVersion, aSubVersion; // the version subVersion got from filename
158         Int_t lastVersion = 0, lastSubVersion = -1; // highest version and subVersion found
159
160         if (!id.HasVersion()) { // version not specified: look for highest version & subVersion
161                                 
162                 while ((filename = gSystem->GetDirEntry(dirPtr))) { // loop on the files
163
164                         TString aString(filename);
165                         if (aString == "." || aString == "..") continue;
166         
167                         if (!FilenameToId(filename, aRunRange, aVersion, 
168                                 aSubVersion)) {
169                                 AliDebug(2,Form(
170                                         "Bad filename <%s>! I'll skip it.", 
171                                         filename));
172                                 continue;
173                         }
174                         
175                         if (!aRunRange.Overlaps(id.GetAliCDBRunRange())) continue;
176                         if(aVersion < lastVersion) continue;
177                         if(aVersion > lastVersion) lastSubVersion = -1;
178                         if(aSubVersion < lastSubVersion) continue;
179                         lastVersion = aVersion;
180                         lastSubVersion = aSubVersion;
181                         lastRunRange = aRunRange;
182                 }
183
184                 id.SetVersion(lastVersion);
185                 id.SetSubVersion(lastSubVersion + 1);
186
187         } else { // version specified, look for highest subVersion only
188                 
189                 while ((filename = gSystem->GetDirEntry(dirPtr))) { // loop on the files
190                         
191                         TString aString(filename);
192                         if (aString == "." || aString == "..") {
193                                 continue;
194                         }
195
196                         if (!FilenameToId(filename, aRunRange, aVersion, 
197                                 aSubVersion)) {
198                                 AliDebug(2,Form(
199                                         "Bad filename <%s>!I'll skip it.",
200                                         filename));     
201                                 continue;
202                         }
203
204                         if (aRunRange.Overlaps(id.GetAliCDBRunRange()) 
205                                 && aVersion == id.GetVersion()
206                                 && aSubVersion > lastSubVersion) {
207                                 lastSubVersion = aSubVersion;
208                                 lastRunRange = aRunRange;
209                         }
210         
211                 }
212                 
213                 id.SetSubVersion(lastSubVersion + 1);
214         }
215
216         gSystem->FreeDirectory(dirPtr);
217
218         TString lastStorage = id.GetLastStorage();
219         if(lastStorage.Contains(TString("grid"), TString::kIgnoreCase) &&
220            id.GetSubVersion() > 0 ){
221                 AliError(Form("Grid to Local Storage error! local object with version v%d_s%d found:",id.GetVersion(), id.GetSubVersion()-1));
222                 AliError(Form("This object has been already transferred from Grid (check v%d_s0)!",id.GetVersion()));
223                 return kFALSE;
224         }
225
226         if(lastStorage.Contains(TString("new"), TString::kIgnoreCase) &&
227            id.GetSubVersion() > 0 ){
228                 AliWarning(Form("A NEW object is being stored with version v%d_s%d",
229                                         id.GetVersion(),id.GetSubVersion()));
230                 AliWarning(Form("and it will hide previously stored object with v%d_s%d!",
231                                         id.GetVersion(),id.GetSubVersion()-1));
232         }
233
234         if(!lastRunRange.IsAnyRange() && !(lastRunRange.IsEqual(& id.GetAliCDBRunRange()))) 
235                 AliWarning(Form("Run range modified w.r.t. previous version (Run%d_%d_v%d_s%d)",
236                         lastRunRange.GetFirstRun(), lastRunRange.GetLastRun(), 
237                         id.GetVersion(), id.GetSubVersion()-1));
238
239         return kTRUE;
240 }
241
242 //_____________________________________________________________________________
243 Bool_t AliCDBLocal::GetId(const AliCDBId& query, AliCDBId& result) {
244 // look for filename matching query (called by GetEntry)
245
246         TString dirName;
247         dirName += fBaseDirectory;
248         dirName += '/';
249         dirName += query.GetPath(); // dirName = fDBPath/idPath
250
251         void* dirPtr = gSystem->OpenDirectory(dirName); 
252         if (!dirPtr) {
253                 AliError(Form("Directory <%s> not found", (query.GetPath()).Data()));
254                 AliError(Form("in DB folder %s", fBaseDirectory.Data()));
255                 return kFALSE;
256         }
257
258         const char* filename;   
259         
260         AliCDBRunRange aRunRange; // the runRange got from filename
261         Int_t aVersion, aSubVersion; // the version and subVersion got from filename
262
263         if (!query.HasVersion()) { // neither version and subversion specified -> look for highest version and subVersion
264                 
265                 while ((filename = gSystem->GetDirEntry(dirPtr))) { // loop on files
266                         
267                         TString aString(filename);
268                         if (aString == "." || aString == "..") continue;
269
270                         if (!FilenameToId(filename, aRunRange, aVersion, aSubVersion)) continue;
271                         // aRunRange, aVersion, aSubVersion filled from filename
272
273                         if (!aRunRange.Comprises(query.GetAliCDBRunRange())) continue;
274                         // aRunRange contains requested run!
275                         
276                         if (result.GetVersion() < aVersion) {
277                                 result.SetVersion(aVersion);
278                                 result.SetSubVersion(aSubVersion);
279
280                                 result.SetFirstRun(
281                                         aRunRange.GetFirstRun());
282                                 result.SetLastRun(
283                                         aRunRange.GetLastRun());
284
285                         } else if (result.GetVersion() == aVersion 
286                                 && result.GetSubVersion() 
287                                         < aSubVersion) {
288
289                                 result.SetSubVersion(aSubVersion);
290
291                                 result.SetFirstRun(
292                                         aRunRange.GetFirstRun());
293                                 result.SetLastRun(
294                                         aRunRange.GetLastRun());
295                         } else if (result.GetVersion() == aVersion
296                                 && result.GetSubVersion() == aSubVersion){
297                                 AliError(Form("More than one object valid for run %d, version %d_%d!", 
298                                         query.GetFirstRun(), aVersion, aSubVersion));
299                                 gSystem->FreeDirectory(dirPtr);
300                                 return kFALSE; 
301                                 }
302                 }
303                 
304         } else if (!query.HasSubVersion()) { // version specified but not subversion -> look for highest subVersion
305
306                 result.SetVersion(query.GetVersion());
307
308                 while ((filename = gSystem->GetDirEntry(dirPtr))) { // loop on files
309
310                         TString aString(filename);
311                         if (aString == "." || aString == "..") continue;
312
313                         if (!FilenameToId(filename, aRunRange, aVersion, aSubVersion)) continue;       
314                         // aRunRange, aVersion, aSubVersion filled from filename
315
316                         if (!aRunRange.Comprises(query.GetAliCDBRunRange())) continue; 
317                         // aRunRange contains requested run!
318                         
319                         if(query.GetVersion() != aVersion) continue;
320                         // aVersion is requested version!
321                         
322                         if(result.GetSubVersion() == aSubVersion){
323                                 AliError(Form("More than one object valid for run %d, version %d_%d!", 
324                                         query.GetFirstRun(), aVersion, aSubVersion));
325                                 gSystem->FreeDirectory(dirPtr);
326                                 return kFALSE; 
327                         }
328                         if( result.GetSubVersion() < aSubVersion) {
329
330                                 result.SetSubVersion(aSubVersion);
331
332                                 result.SetFirstRun(
333                                         aRunRange.GetFirstRun());
334                                 result.SetLastRun(
335                                         aRunRange.GetLastRun());
336                         } 
337                 }
338
339         } else { // both version and subversion specified
340
341                 while ((filename = gSystem->GetDirEntry(dirPtr))) { // loop on files
342
343                         TString aString(filename);
344                         if (aString == "." || aString == "..") continue;
345
346                         if (!FilenameToId(filename, aRunRange, aVersion, aSubVersion)) continue;
347                         // aRunRange, aVersion, aSubVersion filled from filename
348                         
349                         if (!aRunRange.Comprises(query.GetAliCDBRunRange())) continue;
350                         // aRunRange contains requested run!
351
352                         if(query.GetVersion() != aVersion || query.GetSubVersion() != aSubVersion) continue; 
353                         // aVersion and aSubVersion are requested version and subVersion!
354                         
355                         if(result.GetVersion() == aVersion && result.GetSubVersion() == aSubVersion){
356                                 AliError(Form("More than one object valid for run %d, version %d_%d!", 
357                                         query.GetFirstRun(), aVersion, aSubVersion));
358                                 gSystem->FreeDirectory(dirPtr);
359                                 return kFALSE; 
360                         }
361                         result.SetVersion(aVersion);
362                         result.SetSubVersion(aSubVersion);
363                         result.SetFirstRun(aRunRange.GetFirstRun());
364                         result.SetLastRun(aRunRange.GetLastRun());
365                         
366                 }
367         }
368
369         gSystem->FreeDirectory(dirPtr);
370
371         return kTRUE;
372 }
373
374 //_____________________________________________________________________________
375 AliCDBEntry* AliCDBLocal::GetEntry(const AliCDBId& queryId) {
376 // get AliCDBEntry from the database
377
378         AliCDBId dataId(queryId.GetAliCDBPath(), -1, -1, -1, -1);
379         Bool_t result;
380                 
381         // look for a filename matching query requests (path, runRange, version, subVersion)
382         if (!queryId.HasVersion()) {
383                 // if version is not specified, first check the selection criteria list
384                 AliCDBId selectedId(queryId);
385                 GetSelection(&selectedId);
386                 result = GetId(selectedId, dataId);
387         } else {
388                 result = GetId(queryId, dataId);
389         }
390
391         if (!result || !dataId.IsSpecified()) return NULL;
392
393         TString filename;
394         if (!IdToFilename(dataId.GetAliCDBRunRange(), dataId.GetVersion(),
395                  dataId.GetSubVersion(), filename)) {
396
397                 AliError("Bad data ID encountered! Subnormal error!");
398                 return NULL;
399         }
400         
401         filename.Prepend((fBaseDirectory +'/' + queryId.GetPath() + '/'));
402
403         TFile file(filename, "READ"); // open file
404         if (!file.IsOpen()) {
405                 AliError(Form("Can't open file <%s>!", filename.Data()));
406                 return NULL;
407         }
408
409         // get the only AliCDBEntry object from the file
410         // the object in the file is an AliCDBEntry entry named "AliCDBEntry"
411         
412         TObject* anObject = file.Get("AliCDBEntry");
413         if (!anObject) {
414                 AliError("Bad storage data: NULL entry object!");
415                 return NULL;
416         }
417
418         if (AliCDBEntry::Class() != anObject->IsA()) {
419                 AliError("Bad storage data: Invalid entry object!");
420                 return NULL;
421         }
422         
423         AliCDBId entryId = ((AliCDBEntry* ) anObject)->GetId();
424  
425         // The object's Id are not reset during storage
426         // If object's Id runRange or version do not match with filename,
427         // it means that someone renamed file by hand. In this case a warning msg is issued.
428         
429         ((AliCDBEntry*) anObject)-> SetLastStorage("local");
430  
431         if(!((entryId.GetAliCDBRunRange()).IsEqual(& dataId.GetAliCDBRunRange())) || 
432                 (entryId.GetVersion() != dataId.GetVersion()) || (entryId.GetSubVersion() != dataId.GetSubVersion())){
433                 AliWarning(Form("Either object Id's RunRange or version do noth match with file name:"));
434                 AliWarning("someone renamed file by hand!");
435         }
436         
437         // close file, return retieved entry
438         file.Close();
439         return (AliCDBEntry*) anObject;
440 }
441
442 //_____________________________________________________________________________
443 void AliCDBLocal::GetEntriesForLevel0(const char* level0,
444         const AliCDBId& queryId, TList* result) {
445 // multiple request (AliCDBStorage::GetAll)
446
447         TString level0Dir;
448         level0Dir += fBaseDirectory;
449         level0Dir += '/';
450         level0Dir += level0;
451         
452         void* level0DirPtr = gSystem->OpenDirectory(level0Dir);
453         if (!level0DirPtr) {
454                 AliError(Form("Can't open level0 directory <%s>!", 
455                         level0Dir.Data()));
456                 return;
457         } 
458
459         const char* level1;
460         while ((level1 = gSystem->GetDirEntry(level0DirPtr))) {
461
462                 TString level1Str(level1);
463                 if (level1Str == "." || level1Str == "..") {
464                         continue;
465                 }
466
467                 if (queryId.GetAliCDBPath().Level1Comprises(level1)) {
468                         GetEntriesForLevel1(level0, level1, queryId, result);
469                 }
470         }
471
472         gSystem->FreeDirectory(level0DirPtr);
473 }
474
475 //_____________________________________________________________________________
476 void AliCDBLocal::GetEntriesForLevel1(const char* level0, const char* level1,
477         const AliCDBId& queryId, TList* result) {
478 // multiple request (AliCDBStorage::GetAll)
479
480         TString level1Dir;
481         level1Dir += fBaseDirectory;
482         level1Dir += '/';
483         level1Dir += level0;
484         level1Dir += '/';
485         level1Dir += level1;
486
487         void* level1DirPtr = gSystem->OpenDirectory(level1Dir);
488         if (!level1DirPtr) {
489                 AliError(Form("Can't open level1 directory <%s>!", 
490                         level1Dir.Data()));
491                 return;
492         }
493
494         const char* level2;
495         while ((level2 = gSystem->GetDirEntry(level1DirPtr))) {
496
497                 TString level2Str(level2);
498                 if (level2Str == "." || level2Str == "..") {
499                         continue;
500                 }
501
502                 if (queryId.GetAliCDBPath().Level2Comprises(level2)) {
503                         
504                         AliCDBPath entryPath(level0, level1, level2);
505                         AliCDBId entryId(entryPath, queryId.GetAliCDBRunRange(),
506                                 queryId.GetVersion(), queryId.GetSubVersion());
507
508                         AliCDBEntry* anEntry = GetEntry(entryId);
509                         if (anEntry) {
510                                 result->Add(anEntry);
511                         }
512                 }
513         }
514
515         gSystem->FreeDirectory(level1DirPtr);
516 }
517
518 //_____________________________________________________________________________
519 TList* AliCDBLocal::GetEntries(const AliCDBId& queryId) {
520 // multiple request (AliCDBStorage::GetAll)
521
522         void* storageDirPtr = gSystem->OpenDirectory(fBaseDirectory);
523         if (!storageDirPtr) {
524                 AliError(Form("Can't open storage directory <%s>",
525                         fBaseDirectory.Data()));
526                 return NULL;
527         }       
528
529         TList* result = new TList();
530         result->SetOwner();
531
532         const char* level0;
533         while ((level0 = gSystem->GetDirEntry(storageDirPtr))) {
534                 
535                 TString level0Str(level0);
536                 if (level0Str == "." || level0Str == "..") {
537                         continue;
538                 }
539
540                 if (queryId.GetAliCDBPath().Level0Comprises(level0)) {
541                         GetEntriesForLevel0(level0, queryId, result);   
542                 }
543         }       
544         
545         gSystem->FreeDirectory(storageDirPtr);
546
547         return result;  
548 }
549
550 //_____________________________________________________________________________
551 Bool_t AliCDBLocal::PutEntry(AliCDBEntry* entry) {
552 // put an AliCDBEntry object into the database
553
554         AliCDBId& id = entry->GetId();
555
556         // set version and subVersion for the entry to be stored
557         if (!PrepareId(id)) return kFALSE;              
558
559         
560         // build filename from entry's id
561         TString filename;
562         if (!IdToFilename(id.GetAliCDBRunRange(), id.GetVersion(),
563                 id.GetSubVersion(), filename)) {
564
565                 AliError("Bad ID encountered! Subnormal error!");
566                 return kFALSE;
567         }
568         
569         filename.Prepend(fBaseDirectory +'/' + id.GetPath() + '/');
570         
571         // open file
572         TFile file(filename, "CREATE");
573         if (!file.IsOpen()) {
574                 AliError(Form("Can't open file <%s>!", filename.Data()));
575                 return kFALSE;
576         }
577         
578         entry->SetVersion(id.GetVersion());
579         entry->SetSubVersion(id.GetSubVersion());
580         
581         // write object (key name: "AliCDBEntry")
582         Bool_t result = file.WriteTObject(entry, "AliCDBEntry");
583         if (!result) AliError(Form("Can't write entry to file: %s", filename.Data()));
584
585         file.Close();
586         if(result) AliInfo(Form("CDB object stored into file %s",filename.Data()));
587
588         return result;
589 }
590
591 //_____________________________________________________________________________
592 TList* AliCDBLocal::GetIdListFromFile(const char* fileName){
593
594         TString fullFileName(fileName);
595         fullFileName.Prepend(fBaseDirectory+'/');
596         TFile *file = TFile::Open(fullFileName);
597         if (!file) {
598                 AliError(Form("Can't open selection file <%s>!", fullFileName.Data()));
599                 return NULL;
600         }
601         file->cd();
602
603         TList *list = new TList();
604         list->SetOwner();
605         int i=0;
606         TString keycycle;
607         
608         AliCDBId *id;
609         while(1){
610                 i++;
611                 keycycle = "AliCDBId;";
612                 keycycle+=i;
613                 
614                 id = (AliCDBId*) file->Get(keycycle);
615                 if(!id) break;
616                 list->AddFirst(id);
617         }
618         file->Close(); delete file; file=0;     
619         return list;
620 }
621
622 //_____________________________________________________________________________
623 Bool_t AliCDBLocal::Contains(const char* path) const{
624 // check for path in storage's fBaseDirectory
625
626         TString dirName;
627         dirName += fBaseDirectory;
628         dirName += '/';
629         dirName += path; // dirName = fDBPath/path
630         Bool_t result=kFALSE;
631
632         void* dirPtr = gSystem->OpenDirectory(dirName); 
633         if (dirPtr) result=kTRUE;
634         gSystem->FreeDirectory(dirPtr);
635
636         return result;
637 }
638
639 /////////////////////////////////////////////////////////////////////////////////////////////////
640 //                                                                                             //
641 // AliCDBLocal factory                                                                         //
642 //                                                                                             //
643 /////////////////////////////////////////////////////////////////////////////////////////////////
644
645 ClassImp(AliCDBLocalFactory)
646
647 //_____________________________________________________________________________
648 Bool_t AliCDBLocalFactory::Validate(const char* dbString) {
649 // check if the string is valid local URI
650
651         TRegexp dbPattern("^local://.+$");
652
653         return TString(dbString).Contains(dbPattern);
654 }
655
656 //_____________________________________________________________________________
657 AliCDBParam* AliCDBLocalFactory::CreateParameter(const char* dbString) {
658 // create AliCDBLocalParam class from the URI string
659
660         if (!Validate(dbString)) {
661                 return NULL;
662         }
663
664         TString pathname(dbString + sizeof("local://") - 1);
665         
666         gSystem->ExpandPathName(pathname);
667
668         if (pathname[0] != '/') {
669                 pathname.Prepend(TString(gSystem->WorkingDirectory()) + '/');
670         }
671
672         return new AliCDBLocalParam(pathname);       
673 }
674
675 //_____________________________________________________________________________
676 AliCDBStorage* AliCDBLocalFactory::Create(const AliCDBParam* param) {
677 // create AliCDBLocal storage instance from parameters
678         
679         if (AliCDBLocalParam::Class() == param->IsA()) {
680                 
681                 const AliCDBLocalParam* localParam = 
682                         (const AliCDBLocalParam*) param;
683                 
684                 return new AliCDBLocal(localParam->GetPath());
685         }
686
687         return NULL;
688 }
689
690 /////////////////////////////////////////////////////////////////////////////////////////////////
691 //                                                                                             //
692 // AliCDBLocal Parameter class                                                                 //                                          //
693 //                                                                                             //
694 /////////////////////////////////////////////////////////////////////////////////////////////////
695
696 ClassImp(AliCDBLocalParam)
697
698 //_____________________________________________________________________________
699 AliCDBLocalParam::AliCDBLocalParam() {
700 // default constructor
701
702 }
703
704 //_____________________________________________________________________________
705 AliCDBLocalParam::AliCDBLocalParam(const char* dbPath):
706 fDBPath(dbPath)
707 {       
708 // constructor
709
710         SetType("local");
711         SetURI(TString("local://") + dbPath);
712 }
713
714 //_____________________________________________________________________________
715 AliCDBLocalParam::~AliCDBLocalParam() {
716 // destructor
717
718 }
719
720 //_____________________________________________________________________________
721 AliCDBParam* AliCDBLocalParam::CloneParam() const {
722 // clone parameter
723
724         return new AliCDBLocalParam(fDBPath);
725 }
726
727 //_____________________________________________________________________________
728 ULong_t AliCDBLocalParam::Hash() const {
729 // return Hash function
730
731        return fDBPath.Hash();
732 }
733
734 //_____________________________________________________________________________
735 Bool_t AliCDBLocalParam::IsEqual(const TObject* obj) const {
736 // check if this object is equal to AliCDBParam obj
737
738         if (this == obj) {
739                 return kTRUE;
740         }
741
742         if (AliCDBLocalParam::Class() != obj->IsA()) {
743                 return kFALSE;
744         }
745
746         AliCDBLocalParam* other = (AliCDBLocalParam*) obj;
747
748         return fDBPath == other->fDBPath;
749 }
750