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