]> git.uio.no Git - u/mrichter/AliRoot.git/blob - STEER/AliCDBLocal.cxx
New version of CDB storage framework (A.Colla)
[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 // build AliCDBId from filename numbers
64
65         Int_t& version, Int_t& subVersion) {
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                 AliWarning(Form("Invalid run range <%d, %d>.", 
105                         runRange.GetFirstRun(), runRange.GetLastRun()));
106                 return kFALSE;
107         }
108
109         if (version < 0) {
110                 AliWarning(Form("Invalid version <%d>.", version));
111                 return kFALSE;
112         }
113
114         if (subVersion < 0) {
115                 AliWarning(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                                 AliWarning(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                                 AliWarning(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("*** WARNING! 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 AliCDBId AliCDBLocal::GetId(const AliCDBId& query) {
244 // look for filename matching query (called by GetEntry)
245
246         AliCDBId result(query.GetAliCDBPath(), -1, -1, -1, -1);
247
248         TString dirName;
249         dirName += fBaseDirectory;
250         dirName += '/';
251         dirName += query.GetPath(); // dirName = fDBPath/idPath
252
253         void* dirPtr = gSystem->OpenDirectory(dirName); 
254         if (!dirPtr) {
255                 AliError(Form("Directory <%s> not found", (query.GetPath()).Data()));
256                 AliError(Form("in DB folder %s", fBaseDirectory.Data()));
257                 return result;
258         }
259
260         const char* filename;   
261         
262         AliCDBRunRange aRunRange; // the runRange got from filename
263         Int_t aVersion, aSubVersion; // the version and subVersion got from filename
264
265         if (!query.HasVersion()) { // neither version and subversion specified -> look for highest version and subVersion
266                 
267                 while ((filename = gSystem->GetDirEntry(dirPtr))) { // loop on files
268                         
269                         TString aString(filename);
270                         if (aString == "." || aString == "..") continue;
271
272                         if (!FilenameToId(filename, aRunRange, aVersion, aSubVersion)) continue;
273                         // aRunRange, aVersion, aSubVersion filled from filename
274
275                         if (!aRunRange.Comprises(query.GetAliCDBRunRange())) continue;
276                         // aRunRange contains requested run!
277                         
278                         if (result.GetVersion() < aVersion) {
279                                 result.SetVersion(aVersion);
280                                 result.SetSubVersion(aSubVersion);
281
282                                 result.SetFirstRun(
283                                         aRunRange.GetFirstRun());
284                                 result.SetLastRun(
285                                         aRunRange.GetLastRun());
286
287                         } else if (result.GetVersion() == aVersion 
288                                 && result.GetSubVersion() 
289                                         < aSubVersion) {
290
291                                 result.SetSubVersion(aSubVersion);
292
293                                 result.SetFirstRun(
294                                         aRunRange.GetFirstRun());
295                                 result.SetLastRun(
296                                         aRunRange.GetLastRun());
297                         } else if (result.GetVersion() == aVersion
298                                 && result.GetSubVersion() == aSubVersion){
299                                 AliError(Form("More than one object valid for run %d, version %d_%d!", 
300                                         query.GetFirstRun(), aVersion, aSubVersion));
301                                 result.SetRunRange(-1,-1); result.SetVersion(-1); result.SetSubVersion(-1);
302                                 return result; 
303                                 }
304                 }
305                 
306         } else if (!query.HasSubVersion()) { // version specified but not subversion -> look for highest subVersion
307
308                 result.SetVersion(query.GetVersion());
309
310                 while ((filename = gSystem->GetDirEntry(dirPtr))) { // loop on files
311
312                         TString aString(filename);
313                         if (aString == "." || aString == "..") continue;
314
315                         if (!FilenameToId(filename, aRunRange, aVersion, aSubVersion)) continue;       
316                         // aRunRange, aVersion, aSubVersion filled from filename
317
318                         if (!aRunRange.Comprises(query.GetAliCDBRunRange())) continue; 
319                         // aRunRange contains requested run!
320                         
321                         if(query.GetVersion() != aVersion) continue;
322                         // aVersion is requested version!
323                         
324                         if(result.GetSubVersion() == aSubVersion){
325                                 AliError(Form("More than one object valid for run %d, version %d_%d!", 
326                                         query.GetFirstRun(), aVersion, aSubVersion));
327                                 result.SetRunRange(-1,-1); result.SetVersion(-1); result.SetSubVersion(-1);
328                                 return result; 
329                         }
330                         if( result.GetSubVersion() < aSubVersion) {
331
332                                 result.SetSubVersion(aSubVersion);
333
334                                 result.SetFirstRun(
335                                         aRunRange.GetFirstRun());
336                                 result.SetLastRun(
337                                         aRunRange.GetLastRun());
338                         } 
339                 }
340
341         } else { // both version and subversion specified
342
343                 while ((filename = gSystem->GetDirEntry(dirPtr))) { // loop on files
344
345                         TString aString(filename);
346                         if (aString == "." || aString == "..") continue;
347
348                         if (!FilenameToId(filename, aRunRange, aVersion, aSubVersion)) continue;
349                         // aRunRange, aVersion, aSubVersion filled from filename
350                         
351                         if (!aRunRange.Comprises(query.GetAliCDBRunRange())) continue;
352                         // aRunRange contains requested run!
353
354                         if(query.GetVersion() != aVersion || query.GetSubVersion() != aSubVersion) continue; 
355                         // aVersion and aSubVersion are requested version and subVersion!
356                         
357                         if(result.GetVersion() == aVersion && result.GetSubVersion() == aSubVersion){
358                                 AliError(Form("More than one object valid for run %d, version %d_%d!", 
359                                         query.GetFirstRun(), aVersion, aSubVersion));
360                                 result.SetRunRange(-1,-1); result.SetVersion(-1); result.SetSubVersion(-1);
361                                 return result; 
362                         }
363                         result.SetVersion(aVersion);
364                         result.SetSubVersion(aSubVersion);
365                         result.SetFirstRun(aRunRange.GetFirstRun());
366                         result.SetLastRun(aRunRange.GetLastRun());
367                         
368                 }
369         }
370
371         gSystem->FreeDirectory(dirPtr);
372
373         return result;
374 }
375
376 //_____________________________________________________________________________
377 AliCDBEntry* AliCDBLocal::GetEntry(const AliCDBId& queryId) {
378 // get AliCDBEntry from the database
379
380         AliCDBId dataId;
381         
382         // look for a filename matching query requests (path, runRange, version, subVersion)
383         if (!queryId.HasVersion()) {
384                 // if version is not specified, first check the selection criteria list
385                 dataId = GetId(GetSelection(queryId));
386         } else {
387                 dataId = GetId(queryId);
388         }
389
390         if (!dataId.IsSpecified()) return NULL;
391
392         TString filename;
393         if (!IdToFilename(dataId.GetAliCDBRunRange(), dataId.GetVersion(),
394                  dataId.GetSubVersion(), filename)) {
395
396                 AliError("Bad data ID encountered! Subnormal error!");
397                 return NULL;
398         }
399         
400         filename.Prepend((fBaseDirectory +'/' + queryId.GetPath() + '/'));
401
402         TFile file(filename, "READ"); // open file
403         if (!file.IsOpen()) {
404                 AliError(Form("Can't open file <%s>!", filename.Data()));
405                 return NULL;
406         }
407
408         // get the only AliCDBEntry object from the file
409         // the object in the file is an AliCDBEntry entry named "AliCDBEntry"
410         
411         TObject* anObject = file.Get("AliCDBEntry");
412         if (!anObject) {
413                 AliError("Bad storage data: NULL entry object!");
414                 return NULL;
415         }
416
417         if (AliCDBEntry::Class() != anObject->IsA()) {
418                 AliError("Bad storage data: Invalid entry object!");
419                 return NULL;
420         }
421         
422         AliCDBId entryId = ((AliCDBEntry* ) anObject)->GetId();
423  
424         // The object's Id are not reset during storage
425         // If object's Id runRange or version do not match with filename,
426         // it means that someone renamed file by hand. In this case a warning msg is issued.
427         
428         ((AliCDBEntry*) anObject)-> SetLastStorage("local");
429  
430         if(!((entryId.GetAliCDBRunRange()).IsEqual(& dataId.GetAliCDBRunRange())) || 
431                 (entryId.GetVersion() != dataId.GetVersion()) || (entryId.GetSubVersion() != dataId.GetSubVersion())){
432                 AliWarning(Form("Either object Id's RunRange or version do noth match with file name:"));
433                 AliWarning("someone renamed file by hand!");
434         }
435         
436         // close file, return retieved entry
437         file.Close();
438         return (AliCDBEntry*) anObject;
439 }
440
441 //_____________________________________________________________________________
442 void AliCDBLocal::GetEntriesForLevel0(const char* level0,
443         const AliCDBId& queryId, TList* result) {
444 // multiple request (AliCDBStorage::GetAll)
445
446         TString level0Dir;
447         level0Dir += fBaseDirectory;
448         level0Dir += '/';
449         level0Dir += level0;
450         
451         void* level0DirPtr = gSystem->OpenDirectory(level0Dir);
452         if (!level0DirPtr) {
453                 AliError(Form("Can't open level0 directory <%s>!", 
454                         level0Dir.Data()));
455                 return;
456         } 
457
458         const char* level1;
459         while ((level1 = gSystem->GetDirEntry(level0DirPtr))) {
460
461                 TString level1Str(level1);
462                 if (level1Str == "." || level1Str == "..") {
463                         continue;
464                 }
465
466                 if (queryId.GetAliCDBPath().Level1Comprises(level1)) {
467                         GetEntriesForLevel1(level0, level1, queryId, result);
468                 }
469         }
470
471         gSystem->FreeDirectory(level0DirPtr);
472 }
473
474 //_____________________________________________________________________________
475 void AliCDBLocal::GetEntriesForLevel1(const char* level0, const char* level1,
476         const AliCDBId& queryId, TList* result) {
477 // multiple request (AliCDBStorage::GetAll)
478
479         TString level1Dir;
480         level1Dir += fBaseDirectory;
481         level1Dir += '/';
482         level1Dir += level0;
483         level1Dir += '/';
484         level1Dir += level1;
485
486         void* level1DirPtr = gSystem->OpenDirectory(level1Dir);
487         if (!level1DirPtr) {
488                 AliError(Form("Can't open level1 directory <%s>!", 
489                         level1Dir.Data()));
490                 return;
491         }
492
493         const char* level2;
494         while ((level2 = gSystem->GetDirEntry(level1DirPtr))) {
495
496                 TString level2Str(level2);
497                 if (level2Str == "." || level2Str == "..") {
498                         continue;
499                 }
500
501                 if (queryId.GetAliCDBPath().Level2Comprises(level2)) {
502                         
503                         AliCDBPath entryPath(level0, level1, level2);
504                         AliCDBId entryId(entryPath, queryId.GetAliCDBRunRange(),
505                                 queryId.GetVersion(), queryId.GetSubVersion());
506
507                         AliCDBEntry* anEntry = GetEntry(entryId);
508                         if (anEntry) {
509                                 result->Add(anEntry);
510                         }
511                 }
512         }
513
514         gSystem->FreeDirectory(level1DirPtr);
515 }
516
517 //_____________________________________________________________________________
518 TList* AliCDBLocal::GetEntries(const AliCDBId& queryId) {
519 // multiple request (AliCDBStorage::GetAll)
520
521         void* storageDirPtr = gSystem->OpenDirectory(fBaseDirectory);
522         if (!storageDirPtr) {
523                 AliError(Form("Can't open storage directory <%s>",
524                         fBaseDirectory.Data()));
525                 return NULL;
526         }       
527
528         TList* result = new TList();
529         result->SetOwner();
530
531         const char* level0;
532         while ((level0 = gSystem->GetDirEntry(storageDirPtr))) {
533                 
534                 TString level0Str(level0);
535                 if (level0Str == "." || level0Str == "..") {
536                         continue;
537                 }
538
539                 if (queryId.GetAliCDBPath().Level0Comprises(level0)) {
540                         GetEntriesForLevel0(level0, queryId, result);   
541                 }
542         }       
543         
544         gSystem->FreeDirectory(storageDirPtr);
545
546         return result;  
547 }
548
549 //_____________________________________________________________________________
550 Bool_t AliCDBLocal::PutEntry(AliCDBEntry* entry) {
551 // put an AliCDBEntry object into the database
552
553         AliCDBId& id = entry->GetId();
554
555         // set version and subVersion for the entry to be stored
556         if (!PrepareId(id)) return kFALSE;              
557
558         
559         // build filename from entry's id
560         TString filename;
561         if (!IdToFilename(id.GetAliCDBRunRange(), id.GetVersion(),
562                 id.GetSubVersion(), filename)) {
563
564                 AliError("Bad ID encountered! Subnormal error!");
565                 return kFALSE;
566         }
567         
568         filename.Prepend(fBaseDirectory +'/' + id.GetPath() + '/');
569         
570         // open file
571         TFile file(filename, "CREATE");
572         if (!file.IsOpen()) {
573                 AliError(Form("Can't open file <%s>!", filename.Data()));
574                 return kFALSE;
575         }
576         
577         entry->SetVersion(id.GetVersion());
578         entry->SetSubVersion(id.GetSubVersion());
579         
580         // write object (key name: "AliCDBEntry")
581         Bool_t result = file.WriteTObject(entry, "AliCDBEntry");
582         if (!result) AliError(Form("Can't write entry to file: %s", filename.Data()));
583
584         file.Close();
585         if(result) AliInfo(Form("AliCDBEntry stored into file %s",filename.Data()));
586
587         return result;
588 }
589
590 /////////////////////////////////////////////////////////////////////////////////////////////////
591 //                                                                                             //
592 // AliCDBLocal factory                                                                         //
593 //                                                                                             //
594 /////////////////////////////////////////////////////////////////////////////////////////////////
595
596 ClassImp(AliCDBLocalFactory)
597
598 //_____________________________________________________________________________
599 Bool_t AliCDBLocalFactory::Validate(const char* dbString) {
600 // check if the string is valid local URI
601
602         TRegexp dbPattern("^local://.+$");
603
604         return TString(dbString).Contains(dbPattern);
605 }
606
607 //_____________________________________________________________________________
608 AliCDBParam* AliCDBLocalFactory::CreateParameter(const char* dbString) {
609 // create AliCDBLocalParam class from the URI string
610
611         if (!Validate(dbString)) {
612                 return NULL;
613         }
614
615         TString pathname(dbString + sizeof("local://") - 1);
616         
617         gSystem->ExpandPathName(pathname);
618
619         if (pathname[0] != '/') {
620                 pathname.Prepend(TString(gSystem->WorkingDirectory()) + '/');
621         }
622
623         AliInfo(pathname);
624
625         return new AliCDBLocalParam(pathname);       
626 }
627
628 //_____________________________________________________________________________
629 AliCDBStorage* AliCDBLocalFactory::Create(const AliCDBParam* param) {
630 // create AliCDBLocal storage instance from parameters
631         
632         if (AliCDBLocalParam::Class() == param->IsA()) {
633                 
634                 const AliCDBLocalParam* localParam = 
635                         (const AliCDBLocalParam*) param;
636                 
637                 return new AliCDBLocal(localParam->GetPath());
638         }
639
640         return NULL;
641 }
642
643 /////////////////////////////////////////////////////////////////////////////////////////////////
644 //                                                                                             //
645 // AliCDBLocal Parameter class                                                                 //                                          //
646 //                                                                                             //
647 /////////////////////////////////////////////////////////////////////////////////////////////////
648
649 ClassImp(AliCDBLocalParam)
650
651 //_____________________________________________________________________________
652 AliCDBLocalParam::AliCDBLocalParam() {
653 // default constructor
654
655 }
656
657 //_____________________________________________________________________________
658 AliCDBLocalParam::AliCDBLocalParam(const char* dbPath):
659 fDBPath(dbPath)
660 {       
661 // constructor
662
663         SetType("local");
664         SetURI(TString("local://") + dbPath);
665 }
666
667 //_____________________________________________________________________________
668 AliCDBLocalParam::~AliCDBLocalParam() {
669 // destructor
670
671 }
672
673 //_____________________________________________________________________________
674 AliCDBParam* AliCDBLocalParam::CloneParam() const {
675 // clone parameter
676
677         return new AliCDBLocalParam(fDBPath);
678 }
679
680 //_____________________________________________________________________________
681 ULong_t AliCDBLocalParam::Hash() const {
682 // return Hash function
683
684        return fDBPath.Hash();
685 }
686
687 //_____________________________________________________________________________
688 Bool_t AliCDBLocalParam::IsEqual(const TObject* obj) const {
689 // check if this object is equal to AliCDBParam obj
690
691         if (this == obj) {
692                 return kTRUE;
693         }
694
695         if (AliCDBLocalParam::Class() != obj->IsA()) {
696                 return kFALSE;
697         }
698
699         AliCDBLocalParam* other = (AliCDBLocalParam*) obj;
700
701         return fDBPath == other->fDBPath;
702 }
703