1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
16 /////////////////////////////////////////////////////////////////////
18 // class AliCDBDump //
19 // access class to a DataBase in a dump storage (single file) //
21 /////////////////////////////////////////////////////////////////////
27 #include <TObjString.h>
30 #include "AliCDBDump.h"
31 #include "AliCDBEntry.h"
36 //_____________________________________________________________________________
37 AliCDBDump::AliCDBDump(const char* dbFile, Bool_t readOnly):
38 fFile(NULL), fReadOnly(readOnly) {
42 fFile = TFile::Open(dbFile, fReadOnly ? "READ" : "UPDATE");
44 AliError(Form("Can't open file <%s>!" , dbFile));
46 AliDebug(2,Form("File <%s> opened",dbFile));
47 if(fReadOnly) AliDebug(2,Form("in read-only mode"));
51 //_____________________________________________________________________________
52 AliCDBDump::~AliCDBDump() {
62 //_____________________________________________________________________________
63 Bool_t AliCDBDump::KeyNameToId(const char* keyname, AliCDBRunRange& runRange,
64 Int_t& version, Int_t& subVersion) {
65 // build AliCDBId from keyname numbers
69 // valid keyname: Run#firstRun_#lastRun_v#version_s#subVersion.root
70 TRegexp keyPattern("^Run[0-9]+_[0-9]+_v[0-9]+_s[0-9]+$");
71 keyPattern.Index(keyname, &mSize);
73 AliDebug(2,Form("Bad keyname <%s>.", keyname));
77 TObjArray* strArray = (TObjArray*) TString(keyname).Tokenize("_");
79 TString firstRunString(((TObjString*) strArray->At(0))->GetString());
80 runRange.SetFirstRun(atoi(firstRunString.Data() + 3));
81 runRange.SetLastRun(atoi(((TObjString*) strArray->At(1))->GetString()));
83 TString verString(((TObjString*) strArray->At(2))->GetString());
84 version = atoi(verString.Data() + 1);
86 TString subVerString(((TObjString*) strArray->At(3))->GetString());
87 subVersion = atoi(subVerString.Data() + 1);
94 //_____________________________________________________________________________
95 Bool_t AliCDBDump::IdToKeyName(const AliCDBRunRange& runRange, Int_t version,
96 Int_t subVersion, TString& keyname) {
97 // build key name from AliCDBId data (run range, version, subVersion)
99 if (!runRange.IsValid()) {
100 AliDebug(2,Form("Invalid run range <%d, %d>.",
101 runRange.GetFirstRun(), runRange.GetLastRun()));
106 AliDebug(2,Form("Invalid version <%d>.", version));
110 if (subVersion < 0) {
111 AliDebug(2,Form("Invalid subversion <%s>.", subVersion));
116 keyname += runRange.GetFirstRun();
118 keyname += runRange.GetLastRun();
122 keyname += subVersion;
127 //_____________________________________________________________________________
128 Bool_t AliCDBDump::MkDir(const TString& path) {
129 // descend into TDirectory, making TDirectories if they don't exist
130 TObjArray* strArray = (TObjArray*) path.Tokenize("/");
132 TIter iter(strArray);
135 while ((str = (TObjString*) iter.Next())) {
137 TString dirName(str->GetString());
138 if (!dirName.Length()) {
142 if (gDirectory->cd(dirName)) {
146 TDirectory* aDir = gDirectory->mkdir(dirName, "");
148 AliError(Form("Can't create directory <%s>!",
163 //_____________________________________________________________________________
164 Bool_t AliCDBDump::PrepareId(AliCDBId& id) {
165 // prepare id (version, subVersion) of the object that will be stored (called by PutEntry)
167 AliCDBRunRange aRunRange; // the runRange got from filename
168 AliCDBRunRange lastRunRange(-1,-1); // highest runRange found
169 Int_t aVersion, aSubVersion; // the version subVersion got from filename
170 Int_t lastVersion = 0, lastSubVersion = -1; // highest version and subVersion found
173 TIter iter(gDirectory->GetListOfKeys());
176 if (!id.HasVersion()) { // version not specified: look for highest version & subVersion
178 while ((key = (TKey*) iter.Next())) { // loop on keys
180 const char* keyName = key->GetName();
182 if (!KeyNameToId(keyName, aRunRange, aVersion,
185 "Bad keyname <%s>!I'll skip it.", keyName));
189 if (!aRunRange.Overlaps(id.GetAliCDBRunRange())) continue;
190 if(aVersion < lastVersion) continue;
191 if(aVersion > lastVersion) lastSubVersion = -1;
192 if(aSubVersion < lastSubVersion) continue;
193 lastVersion = aVersion;
194 lastSubVersion = aSubVersion;
195 lastRunRange = aRunRange;
198 id.SetVersion(lastVersion);
199 id.SetSubVersion(lastSubVersion + 1);
201 } else { // version specified, look for highest subVersion only
203 while ((key = (TKey*) iter.Next())) { // loop on the keys
205 const char* keyName = key->GetName();
207 if (!KeyNameToId(keyName, aRunRange, aVersion,
210 "Bad keyname <%s>!I'll skip it.", keyName));
214 if (aRunRange.Overlaps(id.GetAliCDBRunRange())
215 && aVersion == id.GetVersion()
216 && aSubVersion > lastSubVersion) {
217 lastSubVersion = aSubVersion;
218 lastRunRange = aRunRange;
223 id.SetSubVersion(lastSubVersion + 1);
226 TString lastStorage = id.GetLastStorage();
227 if(lastStorage.Contains(TString("grid"), TString::kIgnoreCase) &&
228 id.GetSubVersion() > 0 ){
229 AliError(Form("Grid to Dump Storage error! local object with version v%d_s%d found:",id.GetVersion(), id.GetSubVersion()-1));
230 AliError(Form("This object has been already transferred from Grid (check v%d_s0)!",id.GetVersion()));
234 if(lastStorage.Contains(TString("new"), TString::kIgnoreCase) &&
235 id.GetSubVersion() > 0 ){
236 AliWarning(Form("A NEW object is being stored with version v%d_s%d",
237 id.GetVersion(),id.GetSubVersion()));
238 AliWarning(Form("and it will hide previously stored object with v%d_s%d!",
239 id.GetVersion(),id.GetSubVersion()-1));
242 if(!lastRunRange.IsAnyRange() && !(lastRunRange.IsEqual(& id.GetAliCDBRunRange())))
243 AliWarning(Form("Run range modified w.r.t. previous version (Run%d_%d_v%d_s%d)",
244 lastRunRange.GetFirstRun(), lastRunRange.GetLastRun(),
245 id.GetVersion(), id.GetSubVersion()-1));
252 //_____________________________________________________________________________
253 AliCDBId AliCDBDump::GetId(const AliCDBId& query) {
254 // look for filename matching query (called by GetEntry)
256 AliCDBId result(query.GetAliCDBPath(), -1, -1, -1, -1);
258 AliCDBRunRange aRunRange; // the runRange got from filename
259 Int_t aVersion, aSubVersion; // the version and subVersion got from filename
261 TIter iter(gDirectory->GetListOfKeys());
264 if (!query.HasVersion()) { // neither version and subversion specified -> look for highest version and subVersion
266 while ((key = (TKey*) iter.Next())) { // loop on the keys
268 if (!KeyNameToId(key->GetName(), aRunRange, aVersion, aSubVersion)) continue;
269 // aRunRange, aVersion, aSubVersion filled from filename
271 if (!aRunRange.Comprises(query.GetAliCDBRunRange())) continue;
272 // aRunRange contains requested run!
274 if (result.GetVersion() < aVersion) {
275 result.SetVersion(aVersion);
276 result.SetSubVersion(aSubVersion);
279 aRunRange.GetFirstRun());
281 aRunRange.GetLastRun());
283 } else if (result.GetVersion() == aVersion
284 && result.GetSubVersion()
287 result.SetSubVersion(aSubVersion);
290 aRunRange.GetFirstRun());
292 aRunRange.GetLastRun());
293 } else if (result.GetVersion() == aVersion
294 && result.GetSubVersion() == aSubVersion){
295 AliError(Form("More than one object valid for run %d, version %d_%d!",
296 query.GetFirstRun(), aVersion, aSubVersion));
297 result.SetRunRange(-1,-1); result.SetVersion(-1); result.SetSubVersion(-1);
302 } else if (!query.HasSubVersion()) { // version specified but not subversion -> look for highest subVersion
304 result.SetVersion(query.GetVersion());
306 while ((key = (TKey*) iter.Next())) { // loop on the keys
308 if (!KeyNameToId(key->GetName(), aRunRange, aVersion, aSubVersion)) continue;
309 // aRunRange, aVersion, aSubVersion filled from filename
311 if (!aRunRange.Comprises(query.GetAliCDBRunRange())) continue;
312 // aRunRange contains requested run!
314 if(query.GetVersion() != aVersion) continue;
315 // aVersion is requested version!
317 if(result.GetSubVersion() == aSubVersion){
318 AliError(Form("More than one object valid for run %d, version %d_%d!",
319 query.GetFirstRun(), aVersion, aSubVersion));
320 result.SetRunRange(-1,-1); result.SetVersion(-1); result.SetSubVersion(-1);
323 if( result.GetSubVersion() < aSubVersion) {
325 result.SetSubVersion(aSubVersion);
328 aRunRange.GetFirstRun());
330 aRunRange.GetLastRun());
334 } else { // both version and subversion specified
336 while ((key = (TKey*) iter.Next())) { // loop on the keys
338 if (!KeyNameToId(key->GetName(), aRunRange, aVersion, aSubVersion)) continue;
339 // aRunRange, aVersion, aSubVersion filled from filename
341 if (!aRunRange.Comprises(query.GetAliCDBRunRange())) continue;
342 // aRunRange contains requested run!
344 if(query.GetVersion() != aVersion || query.GetSubVersion() != aSubVersion) continue;
345 // aVersion and aSubVersion are requested version and subVersion!
347 if(result.GetVersion() == aVersion && result.GetSubVersion() == aSubVersion){
348 AliError(Form("More than one object valid for run %d, version %d_%d!",
349 query.GetFirstRun(), aVersion, aSubVersion));
350 result.SetRunRange(-1,-1); result.SetVersion(-1); result.SetSubVersion(-1);
353 result.SetVersion(aVersion);
354 result.SetSubVersion(aSubVersion);
355 result.SetFirstRun(aRunRange.GetFirstRun());
356 result.SetLastRun(aRunRange.GetLastRun());
364 //_____________________________________________________________________________
365 AliCDBEntry* AliCDBDump::GetEntry(const AliCDBId& query) {
366 // get AliCDBEntry from the database
368 TDirectory::TContext context(gDirectory, fFile);
370 if (!(fFile && fFile->IsOpen())) {
371 AliError("AliCDBDump storage is not initialized properly");
375 if (!gDirectory->cd(query.GetPath())) {
381 // look for a filename matching query requests (path, runRange, version, subVersion)
382 if (!query.HasVersion()) {
383 // if version is not specified, first check the selection criteria list
384 dataId = GetId(GetSelection(query));
386 dataId = GetId(query);
389 if (!dataId.IsSpecified()) {
394 if (!IdToKeyName(dataId.GetAliCDBRunRange(), dataId.GetVersion(),
395 dataId.GetSubVersion(), keyname)) {
396 AliError("Bad ID encountered! Subnormal error!");
400 // get the only AliCDBEntry object from the file
401 // the object in the file is an AliCDBEntry entry named keyname
402 // keyName = Run#firstRun_#lastRun_v#version_s#subVersion
404 TObject* anObject = gDirectory->Get(keyname);
406 AliError("Bad storage data: NULL entry object!");
410 if (AliCDBEntry::Class() != anObject->IsA()) {
411 AliError("Bad storage data: Invalid entry object!");
415 ((AliCDBEntry*) anObject)->SetLastStorage("dump");
417 return (AliCDBEntry*) anObject;
420 //_____________________________________________________________________________
421 void AliCDBDump::GetEntriesForLevel0(const AliCDBId& queryId, TList* result) {
422 // multiple request (AliCDBStorage::GetAll)
424 TDirectory* saveDir = gDirectory;
426 TIter iter(gDirectory->GetListOfKeys());
429 while ((key = (TKey*) iter.Next())) {
431 TString keyNameStr(key->GetName());
432 if (queryId.GetAliCDBPath().Level1Comprises(keyNameStr)) {
433 gDirectory->cd(keyNameStr);
434 GetEntriesForLevel1(queryId, result);
441 //_____________________________________________________________________________
442 void AliCDBDump::GetEntriesForLevel1(const AliCDBId& queryId, TList* result) {
443 // multiple request (AliCDBStorage::GetAll)
445 TIter iter(gDirectory->GetListOfKeys());
448 TDirectory* level0Dir = (TDirectory*) gDirectory->GetMother();
450 while ((key = (TKey*) iter.Next())) {
452 TString keyNameStr(key->GetName());
453 if (queryId.GetAliCDBPath().Level2Comprises(keyNameStr)) {
455 AliCDBPath aPath(level0Dir->GetName(),
456 gDirectory->GetName(), keyNameStr);
457 AliCDBId anId(aPath, queryId.GetAliCDBRunRange(),
458 queryId.GetVersion(), -1);
460 AliCDBEntry* anEntry = GetEntry(anId);
462 result->Add(anEntry);
471 //_____________________________________________________________________________
472 TList* AliCDBDump::GetEntries(const AliCDBId& queryId) {
473 // multiple request (AliCDBStorage::GetAll)
475 TDirectory::TContext context(gDirectory, fFile);
477 if (!(fFile && fFile->IsOpen())) {
478 AliError("AliCDBDump storage is not initialized properly");
482 TList* result = new TList();
485 TIter iter(gDirectory->GetListOfKeys());
488 while ((key = (TKey*) iter.Next())) {
490 TString keyNameStr(key->GetName());
491 if (queryId.GetAliCDBPath().Level0Comprises(keyNameStr)) {
492 gDirectory->cd(keyNameStr);
493 GetEntriesForLevel0(queryId, result);
502 //_____________________________________________________________________________
503 Bool_t AliCDBDump::PutEntry(AliCDBEntry* entry) {
504 // put an AliCDBEntry object into the database
506 TDirectory::TContext context(gDirectory, fFile);
508 if (!(fFile && fFile->IsOpen())) {
509 AliError("AliCDBDump storage is not initialized properly");
514 AliError("AliCDBDump storage is read only!");
518 AliCDBId& id = entry->GetId();
520 if (!gDirectory->cd(id.GetPath())) {
521 if (!MkDir(id.GetPath())) {
522 AliError(Form("Can't open directory <%s>!",
523 id.GetPath().Data()));
528 // set version and subVersion for the entry to be stored
529 if (!PrepareId(id)) {
533 // build keyname from entry's id
535 if (!IdToKeyName(id.GetAliCDBRunRange(), id.GetVersion(), id.GetSubVersion(), keyname)) {
536 AliError("Invalid ID encountered! Subnormal error!");
540 // write object (key name: Run#firstRun_#lastRun_v#version_s#subVersion)
541 Bool_t result = gDirectory->WriteTObject(entry, keyname);
543 AliError(Form("Can't write entry to file: %s",
548 AliInfo(Form("CDB object stored into file %s",fFile->GetName()));
549 AliInfo(Form("TDirectory/key name: %s/%s",id.GetPath().Data(),keyname.Data()));
554 //_____________________________________________________________________________
555 TList* AliCDBDump::GetIdListFromFile(const char* fileName){
557 TString turl(fileName);
558 if (turl[0] != '/') {
559 turl.Prepend(TString(gSystem->WorkingDirectory()) + '/');
561 TFile *file = TFile::Open(turl);
563 AliError(Form("Can't open selection file <%s>!", turl.Data()));
568 TList *list = new TList();
576 keycycle = "AliCDBId;";
579 id = (AliCDBId*) file->Get(keycycle);
583 file->Close(); delete file; file=0;
587 //_____________________________________________________________________________
588 Bool_t AliCDBDump::Contains(const char* path) const{
589 // check for path in storage
591 TDirectory::TContext context(gDirectory, fFile);
592 if (!(fFile && fFile->IsOpen())) {
593 AliError("AliCDBDump storage is not initialized properly");
597 return gDirectory->cd(path);
601 /////////////////////////////////////////////////////////////////////////////////////////////////
603 // AliCDBDump factory //
605 /////////////////////////////////////////////////////////////////////////////////////////////////
607 ClassImp(AliCDBDumpFactory)
609 //_____________________________________________________________________________
610 Bool_t AliCDBDumpFactory::Validate(const char* dbString) {
611 // check if the string is valid dump URI
613 TRegexp dbPattern("^dump://.+$");
615 return TString(dbString).Contains(dbPattern);
618 //_____________________________________________________________________________
619 AliCDBParam* AliCDBDumpFactory::CreateParameter(const char* dbString) {
620 // create AliCDBDumpParam class from the URI string
622 if (!Validate(dbString)) {
626 TString pathname(dbString + sizeof("dump://") - 1);
630 if (pathname.Contains(TRegexp(";ReadOnly$"))) {
631 pathname.Resize(pathname.Length() - sizeof(";ReadOnly") + 1);
637 gSystem->ExpandPathName(pathname);
639 if (pathname[0] != '/') {
640 pathname.Prepend(TString(gSystem->WorkingDirectory()) + '/');
643 return new AliCDBDumpParam(pathname, readOnly);
646 //_____________________________________________________________________________
647 AliCDBStorage* AliCDBDumpFactory::Create(const AliCDBParam* param) {
648 // create AliCDBDump storage instance from parameters
650 if (AliCDBDumpParam::Class() == param->IsA()) {
652 const AliCDBDumpParam* dumpParam =
653 (const AliCDBDumpParam*) param;
655 return new AliCDBDump(dumpParam->GetPath(),
656 dumpParam->IsReadOnly());
662 /////////////////////////////////////////////////////////////////////////////////////////////////
664 // AliCDBDump parameter class //
666 /////////////////////////////////////////////////////////////////////////////////////////////////
668 ClassImp(AliCDBDumpParam)
670 //_____________________________________________________________________________
671 AliCDBDumpParam::AliCDBDumpParam() {
672 // default constructor
676 //_____________________________________________________________________________
677 AliCDBDumpParam::AliCDBDumpParam(const char* dbPath, Bool_t readOnly):
678 fDBPath(dbPath), fReadOnly(readOnly)
694 //_____________________________________________________________________________
695 AliCDBDumpParam::~AliCDBDumpParam() {
700 //_____________________________________________________________________________
701 AliCDBParam* AliCDBDumpParam::CloneParam() const {
704 return new AliCDBDumpParam(fDBPath, fReadOnly);
707 //_____________________________________________________________________________
708 ULong_t AliCDBDumpParam::Hash() const {
709 // return Hash function
711 return fDBPath.Hash();
714 //_____________________________________________________________________________
715 Bool_t AliCDBDumpParam::IsEqual(const TObject* obj) const {
716 // check if this object is equal to AliCDBParam obj
722 if (AliCDBDumpParam::Class() != obj->IsA()) {
726 AliCDBDumpParam* other = (AliCDBDumpParam*) obj;
728 return fDBPath == other->fDBPath;