]> git.uio.no Git - u/mrichter/AliRoot.git/blob - STEER/AliCDBGrid.cxx
Coding conventions
[u/mrichter/AliRoot.git] / STEER / AliCDBGrid.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 // AliCDBGrid                                                                                  //
19 // access class to a DataBase in an AliEn storage                                              //
20 //                                                                                             //
21 /////////////////////////////////////////////////////////////////////////////////////////////////
22
23
24 #include <TGrid.h>
25 #include <TGridResult.h>
26 #include <TFile.h>
27 #include <TROOT.h>
28 #include <TObjArray.h>
29 #include <TObjString.h>
30 #include <TRegexp.h>
31
32 #include "AliLog.h"
33 #include "AliCDBEntry.h"
34 #include "AliCDBGrid.h"
35 #include "AliCDBMetaData.h"
36
37
38 ClassImp(AliCDBGrid)
39
40 //_____________________________________________________________________________
41 AliCDBGrid::AliCDBGrid(const char *gridUrl, const char *user, const char *dbFolder, const char *se) :
42 AliCDBStorage(),
43 fGridUrl(gridUrl),
44 fUser(user),
45 fDBFolder(dbFolder),
46 fSE(se)
47 {
48 // constructor //
49
50         // if the same Grid is alreay active, skip connection
51         if (!gGrid || fGridUrl != gGrid->GridUrl()  
52              || (( fUser != "" ) && ( fUser != gGrid->GetUser() )) ) {
53                 // connection to the Grid
54                 AliInfo("Connection to the Grid...");
55                 if(gGrid){
56                         AliInfo(Form("gGrid = %x; fGridUrl = %s; gGrid->GridUrl() = %s",gGrid,fGridUrl.Data(), gGrid->GridUrl()));
57                         AliInfo(Form("fUser = %s; gGrid->GetUser() = %s",fUser.Data(), gGrid->GetUser()));
58                 }
59                 TGrid::Connect(fGridUrl.Data(),fUser.Data());
60         }
61
62         if(!gGrid) {
63                 AliError("Connection failed!");
64                 return;
65         }
66
67         TString initDir(gGrid->Pwd(0));
68         if (fDBFolder[0] != '/') {
69                 fDBFolder.Prepend(initDir);
70         }
71
72         // check DBFolder: trying to cd to DBFolder; if it does not exist, create it
73         if(!gGrid->Cd(fDBFolder.Data(),0)){
74                 AliDebug(2,Form("Creating new folder <%s> ...",fDBFolder.Data()));
75                 if(!gGrid->Mkdir(fDBFolder.Data(),"",0)){
76                         AliError(Form("Cannot create folder <%s> !",fDBFolder.Data())); 
77                 }
78         } else {
79                 AliDebug(2,Form("Folder <%s> found",fDBFolder.Data()));
80         }
81
82         // removes any '/' at the end of path, then append one '/'
83         while(fDBFolder.EndsWith("/")) fDBFolder.Remove(fDBFolder.Last('/')); 
84         fDBFolder+="/";
85
86         fType="alien";
87         fBaseFolder = fDBFolder;
88
89         // return to the initial directory
90         gGrid->Cd(initDir.Data(),0);
91 }
92
93 //_____________________________________________________________________________
94 AliCDBGrid::~AliCDBGrid()
95 {
96 // destructor
97         delete gGrid; gGrid=0;
98
99 }
100
101 //_____________________________________________________________________________
102 Bool_t AliCDBGrid::FilenameToId(TString& filename, AliCDBId& id) {
103 // build AliCDBId from full path filename (fDBFolder/path/Run#x_#y_v#z.root)
104
105         if(filename.Contains(fDBFolder)){
106                 filename = filename(fDBFolder.Length(),filename.Length()-fDBFolder.Length());
107         }
108
109         TString idPath = filename(0,filename.Last('/'));
110         id.SetPath(idPath);
111         if(!id.IsValid()) return kFALSE;
112
113         filename=filename(idPath.Length()+1,filename.Length()-idPath.Length());
114
115         Ssiz_t mSize;
116         // valid filename: Run#firstRun_#lastRun_v#version.root
117         TRegexp keyPattern("^Run[0-9]+_[0-9]+_v[0-9]+.root$");
118         keyPattern.Index(filename, &mSize);
119         if (!mSize) {
120                 AliDebug(2,Form("Bad filename <%s>.", filename.Data()));
121                 return kFALSE;
122         }
123
124         filename.Resize(filename.Length() - sizeof(".root") + 1);
125
126         TObjArray* strArray = (TObjArray*) filename.Tokenize("_");
127
128         TString firstRunString(((TObjString*) strArray->At(0))->GetString());
129         id.SetFirstRun(atoi(firstRunString.Data() + 3));
130         id.SetLastRun(atoi(((TObjString*) strArray->At(1))->GetString()));
131
132         TString verString(((TObjString*) strArray->At(2))->GetString());
133         id.SetVersion(atoi(verString.Data() + 1));
134
135         delete strArray;
136
137         return kTRUE;
138 }
139
140 //_____________________________________________________________________________
141 Bool_t AliCDBGrid::IdToFilename(const AliCDBId& id, TString& filename) const {
142 // build file name from AliCDBId (path, run range, version) and fDBFolder
143
144         if (!id.GetAliCDBRunRange().IsValid()) {
145                 AliDebug(2,Form("Invalid run range <%d, %d>.",
146                         id.GetFirstRun(), id.GetLastRun()));
147                 return kFALSE;
148         }
149
150         if (id.GetVersion() < 0) {
151                 AliDebug(2,Form("Invalid version <%d>.", id.GetVersion()));
152                 return kFALSE;
153         }
154
155         filename = Form("Run%d_%d_v%d.root",
156                                 id.GetFirstRun(),
157                                 id.GetLastRun(),
158                                 id.GetVersion());
159
160         filename.Prepend(fDBFolder + id.GetPath() + '/');
161
162         return kTRUE;
163 }
164
165 //_____________________________________________________________________________
166 Bool_t AliCDBGrid::PrepareId(AliCDBId& id) {
167 // prepare id (version) of the object that will be stored (called by PutEntry)
168
169         TString initDir(gGrid->Pwd(0));
170         TString pathName= id.GetPath();
171
172         TString dirName(fDBFolder);
173
174         Bool_t dirExist=kFALSE;
175  
176         // go to the path; if directory does not exist, create it
177         TObjArray *arrName=pathName.Tokenize("/");
178         for(int i=0;i<arrName->GetEntries();i++){
179                 TString buffer((arrName->At(i))->GetName());
180                 dirName+=buffer; dirName+="/";
181                 dirExist=gGrid->Cd(dirName,0);
182                 if (!dirExist) {
183                         AliDebug(2,Form("Creating new folder <%s> ...",dirName.Data()));
184                         if(!gGrid->Mkdir(dirName,"",0)){
185                                 AliError(Form("Cannot create directory <%s> !",dirName.Data()));
186                                 gGrid->Cd(initDir.Data());
187                         return kFALSE;
188                         }
189                 }
190         }
191         delete arrName;
192         gGrid->Cd(initDir,0);
193
194         TString filename;
195         AliCDBId anId; // the id got from filename
196         AliCDBRunRange lastRunRange(-1,-1); // highest runRange found
197         Int_t lastVersion=0; // highest version found
198
199         TGridResult *res = gGrid->Ls(dirName);
200
201         //loop on the files in the directory, look for highest version
202         for(int i=0; i < res->GetEntries(); i++){
203                 filename=res->GetFileNamePath(i);
204                 if (!FilenameToId(filename, anId)) continue;
205                 if (anId.GetAliCDBRunRange().Overlaps(id.GetAliCDBRunRange()) && anId.GetVersion() > lastVersion) {
206                         lastVersion = anId.GetVersion();
207                         lastRunRange = anId.GetAliCDBRunRange();
208                 }
209
210         }
211         delete res; 
212  
213         id.SetVersion(lastVersion + 1);
214
215         TString lastStorage = id.GetLastStorage();
216         if(lastStorage.Contains(TString("new"), TString::kIgnoreCase) && id.GetVersion() > 1 ){
217                 AliDebug(2, Form("A NEW object is being stored with version %d",
218                                         id.GetVersion()));
219                 AliDebug(2, Form("and it will hide previously stored object with version %d!",
220                                         id.GetVersion()-1));
221         }
222
223         if(!lastRunRange.IsAnyRange() && !(lastRunRange.IsEqual(&id.GetAliCDBRunRange()))) 
224                 AliWarning(Form("Run range modified w.r.t. previous version (Run%d_%d_v%d)",
225                         lastRunRange.GetFirstRun(), lastRunRange.GetLastRun(), id.GetVersion()));
226     
227         return kTRUE;
228 }
229
230 //_____________________________________________________________________________
231 AliCDBId* AliCDBGrid::GetId(const TList& validFileIds, const AliCDBId& query) {
232 // look for the Id that matches query's requests (highest or exact version)
233
234         if(validFileIds.GetEntries() < 1) {
235                 return NULL;
236         } else if (validFileIds.GetEntries() == 1) {
237                 return dynamic_cast<AliCDBId*> (validFileIds.At(0));
238         }
239
240         TIter iter(&validFileIds);
241
242         AliCDBId *anIdPtr=0;
243         AliCDBId* result=0;
244
245         while((anIdPtr = dynamic_cast<AliCDBId*> (iter.Next()))){
246                 if(anIdPtr->GetPath() != query.GetPath()) continue;
247
248                 //if(!CheckVersion(query, anIdPtr, result)) return NULL;
249
250                 if (!query.HasVersion()){ // look for highest version
251                         if(result && result->GetVersion() > anIdPtr->GetVersion()) continue;
252                         if(result && result->GetVersion() == anIdPtr->GetVersion()) {
253                                 AliDebug(2,Form("More than one object valid for run %d, version %d!",
254                                         query.GetFirstRun(), anIdPtr->GetVersion()));
255                                 return NULL;
256                         }
257                         result = anIdPtr;
258                 } else { // look for specified version
259                         if(query.GetVersion() != anIdPtr->GetVersion()) continue;
260                         if(result && result->GetVersion() == anIdPtr->GetVersion()){
261                                 AliDebug(2,Form("More than one object valid for run %d, version %d!",
262                                         query.GetFirstRun(), anIdPtr->GetVersion()));
263                                 return NULL;
264                         }
265                         result = anIdPtr;
266                 }
267
268         }
269
270
271         return result;
272 }
273
274 //_____________________________________________________________________________
275 AliCDBEntry* AliCDBGrid::GetEntry(const AliCDBId& queryId) {
276 // get AliCDBEntry from the database
277
278         AliCDBId* dataId=0;
279
280         AliCDBId selectedId(queryId);
281         if (!selectedId.HasVersion()) {
282                 // if version is not specified, first check the selection criteria list
283                 GetSelection(&selectedId);
284         }
285
286         TList validFileIds;
287         validFileIds.SetOwner(1);
288
289         // look for file matching query requests (path, runRange, version)
290         if(selectedId.GetFirstRun() == fRun &&
291                         fPathFilter.Comprises(selectedId.GetAliCDBPath()) && fVersion < 0 && !fMetaDataFilter){
292                 // look into list of valid files previously loaded with AliCDBStorage::FillValidFileIds()
293                 AliDebug(2, Form("List of files valid for run %d and for path %s was loaded. Looking there!",
294                                         selectedId.GetFirstRun(), selectedId.GetPath().Data()));
295                 dataId = GetId(fValidFileIds, selectedId);
296
297         } else {
298                 // List of files valid for reqested run was not loaded. Looking directly into CDB
299                 AliDebug(2, Form("List of files valid for run %d and for path %s was not loaded. Looking directly into CDB!",
300                                         selectedId.GetFirstRun(), selectedId.GetPath().Data()));
301
302                 TString filter;
303                 MakeQueryFilter(selectedId.GetFirstRun(), selectedId.GetLastRun(),
304                                 selectedId.GetAliCDBPath(), selectedId.GetVersion(), 0, filter);
305
306                 TGridResult *res = gGrid->Query(fDBFolder, "Run*.root", filter, "");
307                 AliCDBId validFileId;
308                 for(int i=0; i<res->GetEntries(); i++){
309                         TString filename = res->GetKey(i, "lfn");
310                         if(filename == "") continue;
311                         if(FilenameToId(filename, validFileId))
312                                         validFileIds.AddLast(validFileId.Clone());
313                 }
314                 delete res;
315                 dataId = GetId(validFileIds, selectedId);
316         }
317
318         if (!dataId) return NULL;
319
320         TString filename;
321         if (!IdToFilename(*dataId, filename)) {
322                 AliDebug(2,Form("Bad data ID encountered! Subnormal error!"));
323                 return NULL;
324         }
325
326         AliCDBEntry* anEntry = GetEntryFromFile(filename, dataId);
327
328         return anEntry;
329 }
330
331 //_____________________________________________________________________________
332 AliCDBEntry* AliCDBGrid::GetEntryFromFile(TString& filename, const AliCDBId* dataId){
333 // Get AliCBEntry object from file "filename"
334
335         AliDebug(2,Form("Opening file: %s",filename.Data()));
336
337         filename.Prepend("/alien");
338         TFile *file = TFile::Open(filename);
339         if (!file) {
340                 AliDebug(2,Form("Can't open file <%s>!", filename.Data()));
341                 return NULL;
342         }
343
344         // get the only AliCDBEntry object from the file
345         // the object in the file is an AliCDBEntry entry named "AliCDBEntry"
346
347         AliCDBEntry* anEntry = dynamic_cast<AliCDBEntry*> (file->Get("AliCDBEntry"));
348
349         if (!anEntry) {
350                 AliDebug(2,Form("Bad storage data: file does not contain an AliCDBEntry object!"));
351                 file->Close();
352                 return NULL;
353         }
354
355         // The object's Id is not reset during storage
356         // If object's Id runRange or version do not match with filename,
357         // it means that someone renamed file by hand. In this case a warning msg is issued.
358
359         if(anEntry){
360                 AliCDBId entryId = anEntry->GetId();
361                 if(!((entryId.GetAliCDBRunRange()).IsEqual(&(dataId->GetAliCDBRunRange()))) ||
362                         entryId.GetVersion() != dataId->GetVersion()){
363                         AliWarning(Form("Either RunRange or gridVersion in the object's metadata"));
364                         AliWarning(Form("do noth match with fileName numbers:"));
365                         AliWarning(Form("someone renamed file by hand!"));
366                 }
367         }
368
369         anEntry->SetLastStorage("grid");
370
371         // close file, return retieved entry
372         file->Close(); delete file; file=0;
373
374         return anEntry;
375 }
376
377 //_____________________________________________________________________________
378 TList* AliCDBGrid::GetEntries(const AliCDBId& queryId) {
379 // multiple request (AliCDBStorage::GetAll)
380
381         TList* result = new TList();
382         result->SetOwner();
383
384         TList validFileIds;
385         validFileIds.SetOwner(1);
386
387         Bool_t alreadyLoaded = kFALSE;
388
389         // look for file matching query requests (path, runRange)
390         if(queryId.GetFirstRun() == fRun &&
391                         fPathFilter.Comprises(queryId.GetAliCDBPath()) && fVersion < 0 && !fMetaDataFilter){
392                 // look into list of valid files previously loaded with AliCDBStorage::FillValidFileIds()
393                 AliDebug(2,Form("List of files valid for run %d and for path %s was loaded. Looking there!",
394                                         queryId.GetFirstRun(), queryId.GetPath().Data()));
395
396                 alreadyLoaded = kTRUE;
397
398         } else {
399                 // List of files valid for reqested run was not loaded. Looking directly into CDB
400                 AliDebug(2,Form("List of files valid for run %d and for path %s was not loaded. Looking directly into CDB!",
401                                         queryId.GetFirstRun(), queryId.GetPath().Data()));
402
403                 TString filter;
404                 MakeQueryFilter(queryId.GetFirstRun(), queryId.GetLastRun(),
405                                 queryId.GetAliCDBPath(), queryId.GetVersion(), 0, filter);
406
407                 TGridResult *res = gGrid->Query(fDBFolder, "Run*.root", filter, "");
408                 AliCDBId validFileId;
409                 for(int i=0; i<res->GetEntries(); i++){
410                         TString filename = res->GetKey(i, "lfn");
411                         if(filename == "") continue;
412                         if(FilenameToId(filename, validFileId))
413                                         validFileIds.AddLast(validFileId.Clone());
414                 }
415                 delete res;
416         }
417
418         TIter *iter=0;
419         if(alreadyLoaded){
420                 iter = new TIter(&fValidFileIds);
421         } else {
422                 iter = new TIter(&validFileIds);
423         }
424
425         TList selectedIds;
426         selectedIds.SetOwner(1);
427
428         // loop on list of valid Ids to select the right version to get.
429         // According to query and to the selection criteria list, version can be the highest or exact
430         AliCDBPath pathCopy;
431         AliCDBId* anIdPtr=0;
432         AliCDBId* dataId=0;
433         AliCDBPath queryPath = queryId.GetAliCDBPath();
434         while((anIdPtr = dynamic_cast<AliCDBId*> (iter->Next()))){
435                 AliCDBPath thisCDBPath = anIdPtr->GetAliCDBPath();
436                 if(!(queryPath.Comprises(thisCDBPath)) || pathCopy.GetPath() == thisCDBPath.GetPath()) continue;
437                 pathCopy = thisCDBPath;
438
439                 // check the selection criteria list for this query
440                 AliCDBId thisId(*anIdPtr);
441                 thisId.SetVersion(queryId.GetVersion());
442                 if(!thisId.HasVersion()) GetSelection(&thisId);
443
444                 if(alreadyLoaded){
445                         dataId = GetId(fValidFileIds, thisId);
446                 } else {
447                         dataId = GetId(validFileIds, thisId);
448                 }
449                 if(dataId) selectedIds.Add(dataId->Clone());
450         }
451
452         delete iter; iter=0;
453
454         // selectedIds contains the Ids of the files matching all requests of query!
455         // All the objects are now ready to be retrieved
456         iter = new TIter(&selectedIds);
457         while((anIdPtr = dynamic_cast<AliCDBId*> (iter->Next()))){
458                 TString filename;
459                 if (!IdToFilename(*anIdPtr, filename)) {
460                         AliDebug(2,Form("Bad data ID encountered! Subnormal error!"));
461                         continue;
462                 }
463
464                 AliCDBEntry* anEntry = GetEntryFromFile(filename, anIdPtr);
465
466                 if(anEntry) result->Add(anEntry);
467
468         }
469         delete iter; iter=0;
470
471         return result;
472 }
473
474 //_____________________________________________________________________________
475 Bool_t AliCDBGrid::PutEntry(AliCDBEntry* entry) {
476 // put an AliCDBEntry object into the database
477
478         AliCDBId& id = entry->GetId();
479
480         // set version for the entry to be stored
481         if (!PrepareId(id)) return kFALSE;
482
483         // build filename from entry's id
484         TString filename;
485         if (!IdToFilename(id, filename)) {
486                 AliError("Bad ID encountered! Subnormal error!");
487                 return kFALSE;
488         }
489
490         TString folderToTag = Form("%s%s",
491                                         fDBFolder.Data(),
492                                         id.GetPath().Data());
493
494         // add CDB and CDB_MD tag to folder
495         // TODO how to check that folder has already tags?
496         AddTag(folderToTag,"CDB");
497         AddTag(folderToTag,"CDB_MD");
498
499         TDirectory* saveDir = gDirectory;
500
501         // specify SE to filename
502         TString fullFilename = Form("/alien%s?se=%s", filename.Data(), fSE.Data());
503
504         // open file
505         TFile *file = TFile::Open(fullFilename,"CREATE");
506         if(!file || !file->IsWritable()){
507                 AliError(Form("Can't open file <%s>!", filename.Data()));
508                 if(file && !file->IsWritable()) file->Close(); delete file; file=0;
509                 return kFALSE;
510         }
511
512         file->cd();
513
514         entry->SetVersion(id.GetVersion());
515
516         // write object (key name: "AliCDBEntry")
517         Bool_t result = (entry->Write("AliCDBEntry") != 0); 
518         if (!result) AliError(Form("Can't write entry to file <%s>!", filename.Data()));
519
520
521         if (saveDir) saveDir->cd(); else gROOT->cd();
522         file->Close(); delete file; file=0;
523
524         if(result) {
525                 AliInfo(Form("CDB object stored into file %s", filename.Data()));
526                 AliInfo(Form("using S.E. %s", fSE.Data()));
527
528                 if(!TagFileId(filename, &id)){
529                         AliInfo(Form("CDB tagging failed. Deleting file %s!",filename.Data()));
530                         if(!gGrid->Rm(filename.Data()))
531                                 AliError("Can't delete file!");
532                         return kFALSE;
533                 }
534
535                 TagFileMetaData(filename, entry->GetMetaData());
536         }
537
538         return result;
539 }
540 //_____________________________________________________________________________
541 Bool_t AliCDBGrid::AddTag(TString& folderToTag, const char* tagname){
542 // add "tagname" tag (CDB or CDB_MD) to folder where object will be stored
543
544         Bool_t result = kTRUE;
545         AliDebug(2, Form("adding %s tag to folder %s", tagname, folderToTag.Data()));
546         TString addTag = Form("addTag %s %s", folderToTag.Data(), tagname);
547         TGridResult *gridres = gGrid->Command(addTag.Data());
548         const char* resCode = gridres->GetKey(0,"__result__"); // '1' if success
549         if(resCode[0] != '1') {
550                 AliError(Form("Couldn't add %s tags to folder %s !",
551                                                 tagname, folderToTag.Data()));
552                 result = kFALSE;
553         }
554         delete gridres;
555         return result;
556 }
557
558 //_____________________________________________________________________________
559 Bool_t AliCDBGrid::TagFileId(TString& filename, const AliCDBId* id){
560 // tag stored object in CDB table using object Id's parameters
561
562         TString addTagValue1 = Form("addTagValue %s CDB ", filename.Data());
563         TString addTagValue2 = Form("first_run=%d last_run=%d version=%d ",
564                                         id->GetFirstRun(),
565                                         id->GetLastRun(),
566                                         id->GetVersion());
567         TString addTagValue3 = Form("path_level_0=\"%s\" path_level_1=\"%s\" path_level_2=\"%s\"",
568                                         id->GetLevel0().Data(),
569                                         id->GetLevel1().Data(),
570                                         id->GetLevel2().Data());
571         TString addTagValue = Form("%s%s%s",
572                                         addTagValue1.Data(),
573                                         addTagValue2.Data(),
574                                         addTagValue3.Data());
575
576         Bool_t result = kFALSE;
577         AliDebug(2, Form("Tagging file. Tag command: %s", addTagValue.Data()));
578         TGridResult* res = gGrid->Command(addTagValue.Data());
579         const char* resCode = res->GetKey(0,"__result__"); // '1' if success
580         if(resCode[0] != '1') {
581                 AliError(Form("Couldn't add CDB tag value to file %s !",
582                                                 filename.Data()));
583                 result = kFALSE;
584         } else {
585                 AliInfo("Object successfully tagged.");
586                 result = kTRUE;
587         }
588         delete res;
589         return result;
590
591 }
592
593 //_____________________________________________________________________________
594 Bool_t AliCDBGrid::TagFileMetaData(TString& filename, const AliCDBMetaData* md){
595 // tag stored object in CDB table using object Id's parameters
596
597         TString addTagValue1 = Form("addTagValue %s CDB_MD ", filename.Data());
598         TString addTagValue2 = Form("object_classname=\"%s\" responsible=\"%s\" beam_period=%d ",
599                                         md->GetObjectClassName(),
600                                         md->GetResponsible(),
601                                         md->GetBeamPeriod());
602         TString addTagValue3 = Form("aliroot_version=\"%s\" comment=\"%s\"",
603                                         md->GetAliRootVersion(),
604                                         md->GetComment());
605         TString addTagValue = Form("%s%s%s",
606                                         addTagValue1.Data(),
607                                         addTagValue2.Data(),
608                                         addTagValue3.Data());
609
610         Bool_t result = kFALSE;
611         AliDebug(2, Form("Tagging file. Tag command: %s", addTagValue.Data()));
612         TGridResult* res = gGrid->Command(addTagValue.Data());
613         const char* resCode = res->GetKey(0,"__result__"); // '1' if success
614         if(resCode[0] != '1') {
615                 AliWarning(Form("Couldn't add CDB_MD tag value to file %s !",
616                                                 filename.Data()));
617                 result = kFALSE;
618         } else {
619                 AliInfo("Object successfully tagged.");
620                 result = kTRUE;
621         }
622         return result;
623 }
624
625 //_____________________________________________________________________________
626 TList* AliCDBGrid::GetIdListFromFile(const char* fileName){
627   // Gets the CDB Id list from the file fileName
628         TString turl(fileName);
629         turl.Prepend("/alien" + fDBFolder);
630         turl += "?se="; turl += fSE.Data();
631         TFile *file = TFile::Open(turl);
632         if (!file) {
633                 AliError(Form("Can't open selection file <%s>!", turl.Data()));
634                 return NULL;
635         }
636
637         TList *list = new TList();
638         list->SetOwner();
639         int i=0;
640         TString keycycle;
641
642         AliCDBId *id;
643         while(1){
644                 i++;
645                 keycycle = "AliCDBId;";
646                 keycycle+=i;
647                 
648                 id = (AliCDBId*) file->Get(keycycle);
649                 if(!id) break;
650                 list->AddFirst(id);
651         }
652         file->Close(); delete file; file=0;
653         
654         return list;
655
656
657 }
658
659 //_____________________________________________________________________________
660 Bool_t AliCDBGrid::Contains(const char* path) const{
661 // check for path in storage's DBFolder
662
663         TString initDir(gGrid->Pwd(0));
664         TString dirName(fDBFolder);
665         dirName += path; // dirName = fDBFolder/path
666         Bool_t result=kFALSE;
667         if (gGrid->Cd(dirName,0)) result=kTRUE;
668         gGrid->Cd(initDir.Data(),0);
669         return result;
670 }
671
672 //_____________________________________________________________________________
673 void AliCDBGrid::QueryValidFiles()
674 {
675 // Query the CDB for files valid for AliCDBStorage::fRun
676 // fills list fValidFileIds with AliCDBId objects created from file name
677
678         TString filter;
679         MakeQueryFilter(fRun, fRun, fPathFilter, fVersion, fMetaDataFilter, filter);
680
681         TGridResult *res = gGrid->Query(fDBFolder, "Run*.root", filter, "");
682         AliCDBId validFileId;
683         for(int i=0; i<res->GetEntries(); i++){
684                 TString filename = res->GetKey(i, "lfn");
685                 if(filename == "") continue;
686                 AliDebug(2,Form("Found valid file: %s", filename.Data()));
687                 Bool_t result = FilenameToId(filename, validFileId);
688                 if(result) {
689                         fValidFileIds.AddLast(validFileId.Clone());
690                 }
691         }
692         delete res;
693
694 }
695
696 //_____________________________________________________________________________
697 void AliCDBGrid::MakeQueryFilter(Int_t firstRun, Int_t lastRun,
698                                         const AliCDBPath& pathFilter, Int_t version,
699                                         const AliCDBMetaData* md, TString& result) const
700 {
701 // create filter for file query
702
703         result = Form("CDB:first_run<=%d and CDB:last_run>=%d", firstRun, lastRun);
704
705         if(version >= 0) {
706                 result += Form(" and CDB:version=%d", version);
707         }
708         if(pathFilter.GetLevel0() != "*") {
709                 result += Form(" and CDB:path_level_0=\"%s\"", pathFilter.GetLevel0().Data());
710         }
711         if(pathFilter.GetLevel1() != "*") {
712                 result += Form(" and CDB:path_level_1=\"%s\"", pathFilter.GetLevel1().Data());
713         }
714         if(pathFilter.GetLevel2() != "*") {
715                 result += Form(" and CDB:path_level_2=\"%s\"", pathFilter.GetLevel2().Data());
716         }
717
718         if(md){
719                 if(md->GetObjectClassName()[0] != '\0') {
720                         result += Form(" and CDB_MD:object_classname=\"%s\"", md->GetObjectClassName());
721                 }
722                 if(md->GetResponsible()[0] != '\0') {
723                         result += Form(" and CDB_MD:responsible=\"%s\"", md->GetResponsible());
724                 }
725                 if(md->GetBeamPeriod() != 0) {
726                         result += Form(" and CDB_MD:beam_period=%d", md->GetBeamPeriod());
727                 }
728                 if(md->GetAliRootVersion()[0] != '\0') {
729                         result += Form(" and CDB_MD:aliroot_version=\"%s\"", md->GetAliRootVersion());
730                 }
731                 if(md->GetComment()[0] != '\0') {
732                         result += Form(" and CDB_MD:comment=\"%s\"", md->GetComment());
733                 }
734         }
735         AliDebug(2, Form("filter: %s",result.Data()));
736
737 }
738
739 //_____________________________________________________________________________
740 Int_t AliCDBGrid::GetLatestVersion(const char* path, Int_t run){
741 // get last version found in the database valid for run and path
742
743         TList validFileIds;
744         validFileIds.SetOwner(1);
745
746         AliCDBPath aCDBPath(path);
747         if(!aCDBPath.IsValid() || aCDBPath.IsWildcard()) {
748                 AliError(Form("Invalid path in request: %s", path));
749                 return -1;
750         }
751         AliCDBId query(path, run, run, -1, -1);
752         AliCDBId* dataId = 0;
753
754         // look for file matching query requests (path, runRange, version)
755         if(run == fRun &&
756                         fPathFilter.Comprises(aCDBPath) && fVersion < 0){
757                 // look into list of valid files previously loaded with AliCDBStorage::FillValidFileIds()
758                 AliDebug(2, Form("List of files valid for run %d and for path %s was loaded. Looking there!",
759                                         run, path));
760                 dataId = GetId(fValidFileIds, query);
761                 if (!dataId) return -1;
762                 return dataId->GetVersion();
763
764         }
765         // List of files valid for reqested run was not loaded. Looking directly into CDB
766         AliDebug(2, Form("List of files valid for run %d and for path %s was not loaded. Looking directly into CDB!",
767                                 run, path));
768
769         TString filter;
770         MakeQueryFilter(run, run, aCDBPath, -1, 0, filter);
771
772         TGridResult *res = gGrid->Query(fDBFolder, "Run*.root", filter, "");
773         AliCDBId validFileId;
774         for(int i=0; i<res->GetEntries(); i++){
775                 TString filename = res->GetKey(i, "lfn");
776                 if(filename == "") continue;
777                 if(FilenameToId(filename, validFileId))
778                                 validFileIds.AddLast(validFileId.Clone());
779         }
780         delete res;
781
782         dataId = GetId(validFileIds, query);
783         if (!dataId) return -1;
784
785         return dataId->GetVersion();
786
787 }
788
789 //_____________________________________________________________________________
790 Int_t AliCDBGrid::GetLatestSubVersion(const char* /*path*/, Int_t /*run*/, Int_t /*version*/){
791 // get last subversion found in the database valid for run and path
792         AliError("Objects in GRID storage have no sub version!");
793         return -1;
794 }
795
796
797 /////////////////////////////////////////////////////////////////////////////////////////////////
798 //                                                                                             //
799 // AliCDBGrid factory                                                                          //
800 //                                                                                             //
801 /////////////////////////////////////////////////////////////////////////////////////////////////
802
803 ClassImp(AliCDBGridFactory)
804
805 //_____________________________________________________________________________
806 Bool_t AliCDBGridFactory::Validate(const char* gridString) {
807 // check if the string is valid Grid URI
808
809         // pattern: alien://hostName:Port;user;dbPath;SE
810         // example of a valid pattern:
811         // "alien://aliendb4.cern.ch:9000;colla;DBTest;ALICE::CERN::Server"
812 //        TRegexp gridPattern("^alien://.+:[0-9]+;[a-zA-Z0-9_-.]+;.+;.+$");
813         TRegexp gridPattern("^alien://.+$");
814
815         return TString(gridString).Contains(gridPattern);
816 }
817
818 //_____________________________________________________________________________
819 AliCDBParam* AliCDBGridFactory::CreateParameter(const char* gridString) {
820 // create AliCDBGridParam class from the URI string
821
822         if (!Validate(gridString)) {
823                 return NULL;
824         }
825         //TString buffer(gridString + sizeof("alien://") - 1);
826         TString buffer(gridString);
827
828         TString gridUrl         = "alien://";
829         TString user            = "";
830         TString dbFolder        = "DBGrid";
831         TString se              = "ALICE::CERN::se01";
832
833         TObjArray *arr = buffer.Tokenize('?');
834         TIter iter(arr);
835         TObjString *str = 0;
836         
837         while((str = (TObjString*) iter.Next())){
838                 TString entry(str->String());
839                 Int_t indeq = entry.Index('=');
840                 if(indeq == -1) {
841                         if(entry.BeginsWith("alien://")) { // maybe it's a gridUrl!
842                                 gridUrl = entry;
843                                 continue;
844                         } else {
845                                 AliError(Form("Invalid entry! %s",entry.Data()));
846                                 continue;
847                         }
848                 }
849                 
850                 TString key = entry(0,indeq);
851                 TString value = entry(indeq+1,entry.Length()-indeq);
852
853                 if(key.Contains("grid",TString::kIgnoreCase)) {
854                         gridUrl += value;
855                 } 
856                 else if (key.Contains("user",TString::kIgnoreCase)){
857                         user = value;
858                 }
859                 else if (key.Contains("folder",TString::kIgnoreCase)){
860                         dbFolder = value;
861                 }
862                 else if (key.Contains("se",TString::kIgnoreCase)){
863                         se = value;
864                 }
865                 else{
866                         AliError(Form("Invalid entry! %s",entry.Data()));
867                 }
868         }
869         delete arr; arr=0;
870                 
871         AliDebug(2, Form("gridUrl:      %s",gridUrl.Data()));
872         AliDebug(2, Form("user: %s",user.Data()));
873         AliDebug(2, Form("dbFolder:     %s",dbFolder.Data()));
874         AliDebug(2, Form("s.e.: %s",se.Data()));
875
876         return new AliCDBGridParam(gridUrl.Data(), user.Data(), dbFolder.Data(), se.Data());
877 }
878
879 //_____________________________________________________________________________
880 AliCDBStorage* AliCDBGridFactory::Create(const AliCDBParam* param) {
881 // create AliCDBGrid storage instance from parameters
882         
883         AliCDBGrid *grid = 0;
884         if (AliCDBGridParam::Class() == param->IsA()) {
885
886                 const AliCDBGridParam* gridParam = (const AliCDBGridParam*) param;
887                 grid = new AliCDBGrid(gridParam->GridUrl().Data(),
888                                       gridParam->GetUser().Data(),
889                                       gridParam->GetDBFolder().Data(),
890                                       gridParam->GetSE().Data());
891
892         }
893
894         if(!gGrid && grid) {
895                 delete grid; grid=0;
896         }
897
898         return grid;
899 }
900
901 /////////////////////////////////////////////////////////////////////////////////////////////////
902 //                                                                                             //
903 // AliCDBGrid Parameter class                                                                  //                                          //
904 //                                                                                             //
905 /////////////////////////////////////////////////////////////////////////////////////////////////
906
907 ClassImp(AliCDBGridParam)
908
909 //_____________________________________________________________________________
910 AliCDBGridParam::AliCDBGridParam():
911  AliCDBParam(),
912  fGridUrl(),
913  fUser(),
914  fDBFolder(),
915  fSE()
916  {
917 // default constructor
918
919 }
920
921 //_____________________________________________________________________________
922 AliCDBGridParam::AliCDBGridParam(const char* gridUrl, 
923                                 const char* user,
924                                 const char* dbFolder, 
925                                 const char* se):
926  AliCDBParam(),
927  fGridUrl(gridUrl),
928  fUser(user),
929  fDBFolder(dbFolder),
930  fSE(se)
931 {
932 // constructor
933         
934         SetType("alien");
935
936         TString uri = Form("%s?User=%s?DBFolder=%s?SE=%s",
937                         fGridUrl.Data(), fUser.Data(),
938                         fDBFolder.Data(), fSE.Data());
939
940         SetURI(uri.Data());
941 }
942
943 //_____________________________________________________________________________
944 AliCDBGridParam::~AliCDBGridParam() {
945 // destructor
946
947 }
948
949 //_____________________________________________________________________________
950 AliCDBParam* AliCDBGridParam::CloneParam() const {
951 // clone parameter
952
953         return new AliCDBGridParam(fGridUrl.Data(), fUser.Data(),
954                                         fDBFolder.Data(), fSE.Data());
955 }
956
957 //_____________________________________________________________________________
958 ULong_t AliCDBGridParam::Hash() const {
959 // return Hash function
960
961         return fGridUrl.Hash()+fUser.Hash()+fDBFolder.Hash()+fSE.Hash();
962 }
963
964 //_____________________________________________________________________________
965 Bool_t AliCDBGridParam::IsEqual(const TObject* obj) const {
966 // check if this object is equal to AliCDBParam obj
967
968         if (this == obj) {
969                 return kTRUE;
970         }
971
972         if (AliCDBGridParam::Class() != obj->IsA()) {
973                 return kFALSE;
974         }
975
976         AliCDBGridParam* other = (AliCDBGridParam*) obj;
977
978         if(fGridUrl != other->fGridUrl) return kFALSE;
979         if(fUser != other->fUser) return kFALSE;
980         if(fDBFolder != other->fDBFolder) return kFALSE;
981         if(fSE != other->fSE) return kFALSE;
982         return kTRUE;
983 }
984