#include <cstdlib>
#include <TSystem.h>
#include <TKey.h>
#include <TFile.h>
#include <TRegexp.h>
#include <TObjString.h>
#include <TList.h>
#include "AliCDBDump.h"
#include "AliCDBEntry.h"
#include "AliLog.h"
ClassImp(AliCDBDump)
AliCDBDump::AliCDBDump(const char* dbFile, Bool_t readOnly):
fFile(NULL), fReadOnly(readOnly)
{
fFile = TFile::Open(dbFile, fReadOnly ? "READ" : "UPDATE");
if (!fFile) {
AliError(Form("Can't open file <%s>!" , dbFile));
} else {
AliDebug(2,Form("File <%s> opened",dbFile));
if(fReadOnly) AliDebug(2,Form("in read-only mode"));
}
fType="dump";
fBaseFolder = dbFile;
}
AliCDBDump::~AliCDBDump() {
if (fFile) {
fFile->Close();
delete fFile;
}
}
Bool_t AliCDBDump::KeyNameToId(const char* keyname, AliCDBRunRange& runRange,
Int_t& version, Int_t& subVersion) {
Ssiz_t mSize;
TRegexp keyPattern("^Run[0-9]+_[0-9]+_v[0-9]+_s[0-9]+$");
keyPattern.Index(keyname, &mSize);
if (!mSize) {
AliDebug(2,Form("Bad keyname <%s>.", keyname));
return kFALSE;
}
TObjArray* strArray = (TObjArray*) TString(keyname).Tokenize("_");
TString firstRunString(((TObjString*) strArray->At(0))->GetString());
runRange.SetFirstRun(atoi(firstRunString.Data() + 3));
runRange.SetLastRun(atoi(((TObjString*) strArray->At(1))->GetString()));
TString verString(((TObjString*) strArray->At(2))->GetString());
version = atoi(verString.Data() + 1);
TString subVerString(((TObjString*) strArray->At(3))->GetString());
subVersion = atoi(subVerString.Data() + 1);
delete strArray;
return kTRUE;
}
Bool_t AliCDBDump::IdToKeyName(const AliCDBRunRange& runRange, Int_t version,
Int_t subVersion, TString& keyname) {
if (!runRange.IsValid()) {
AliDebug(2,Form("Invalid run range <%d, %d>.",
runRange.GetFirstRun(), runRange.GetLastRun()));
return kFALSE;
}
if (version < 0) {
AliDebug(2,Form("Invalid version <%d>.", version));
return kFALSE;
}
if (subVersion < 0) {
AliDebug(2,Form("Invalid subversion <%d>.", subVersion));
return kFALSE;
}
keyname += "Run";
keyname += runRange.GetFirstRun();
keyname += "_";
keyname += runRange.GetLastRun();
keyname += "_v";
keyname += version;
keyname += "_s";
keyname += subVersion;
return kTRUE;
}
Bool_t AliCDBDump::MkDir(const TString& path) {
TObjArray* strArray = (TObjArray*) path.Tokenize("/");
TIter iter(strArray);
TObjString* str;
while ((str = (TObjString*) iter.Next())) {
TString dirName(str->GetString());
if (!dirName.Length()) {
continue;
}
if (gDirectory->cd(dirName)) {
continue;
}
TDirectory* aDir = gDirectory->mkdir(dirName, "");
if (!aDir) {
AliError(Form("Can't create directory <%s>!",
dirName.Data()));
delete strArray;
return kFALSE;
}
aDir->cd();
}
delete strArray;
return kTRUE;
}
Bool_t AliCDBDump::PrepareId(AliCDBId& id) {
AliCDBRunRange aRunRange;
AliCDBRunRange lastRunRange(-1,-1);
Int_t aVersion, aSubVersion;
Int_t lastVersion = 0, lastSubVersion = -1;
TIter iter(gDirectory->GetListOfKeys());
TKey* key;
if (!id.HasVersion()) {
while ((key = (TKey*) iter.Next())) {
const char* keyName = key->GetName();
if (!KeyNameToId(keyName, aRunRange, aVersion,
aSubVersion)) {
AliDebug(2,Form(
"Bad keyname <%s>!I'll skip it.", keyName));
continue;
}
if (!aRunRange.Overlaps(id.GetAliCDBRunRange())) continue;
if(aVersion < lastVersion) continue;
if(aVersion > lastVersion) lastSubVersion = -1;
if(aSubVersion < lastSubVersion) continue;
lastVersion = aVersion;
lastSubVersion = aSubVersion;
lastRunRange = aRunRange;
}
id.SetVersion(lastVersion);
id.SetSubVersion(lastSubVersion + 1);
} else {
while ((key = (TKey*) iter.Next())) {
const char* keyName = key->GetName();
if (!KeyNameToId(keyName, aRunRange, aVersion,
aSubVersion)) {
AliDebug(2,Form(
"Bad keyname <%s>!I'll skip it.", keyName));
continue;
}
if (aRunRange.Overlaps(id.GetAliCDBRunRange())
&& aVersion == id.GetVersion()
&& aSubVersion > lastSubVersion) {
lastSubVersion = aSubVersion;
lastRunRange = aRunRange;
}
}
id.SetSubVersion(lastSubVersion + 1);
}
TString lastStorage = id.GetLastStorage();
if(lastStorage.Contains(TString("grid"), TString::kIgnoreCase) &&
id.GetSubVersion() > 0 ){
AliError(Form("Grid to Dump Storage error! local object with version v%d_s%d found:",id.GetVersion(), id.GetSubVersion()-1));
AliError(Form("This object has been already transferred from Grid (check v%d_s0)!",id.GetVersion()));
return kFALSE;
}
if(lastStorage.Contains(TString("new"), TString::kIgnoreCase) &&
id.GetSubVersion() > 0 ){
AliDebug(2, Form("A NEW object is being stored with version v%d_s%d",
id.GetVersion(),id.GetSubVersion()));
AliDebug(2, Form("and it will hide previously stored object with v%d_s%d!",
id.GetVersion(),id.GetSubVersion()-1));
}
if(!lastRunRange.IsAnyRange() && !(lastRunRange.IsEqual(& id.GetAliCDBRunRange())))
AliWarning(Form("Run range modified w.r.t. previous version (Run%d_%d_v%d_s%d)",
lastRunRange.GetFirstRun(), lastRunRange.GetLastRun(),
id.GetVersion(), id.GetSubVersion()-1));
return kTRUE;
}
AliCDBId* AliCDBDump::GetId(const AliCDBId& query) {
AliCDBRunRange aRunRange;
Int_t aVersion, aSubVersion;
TIter iter(gDirectory->GetListOfKeys());
TKey* key;
AliCDBId* result = new AliCDBId();
result->SetPath(query.GetPath());
if (!query.HasVersion()) {
while ((key = (TKey*) iter.Next())) {
if (!KeyNameToId(key->GetName(), aRunRange, aVersion, aSubVersion)) continue;
if (!aRunRange.Comprises(query.GetAliCDBRunRange())) continue;
if (result->GetVersion() < aVersion) {
result->SetVersion(aVersion);
result->SetSubVersion(aSubVersion);
result->SetFirstRun(
aRunRange.GetFirstRun());
result->SetLastRun(
aRunRange.GetLastRun());
} else if (result->GetVersion() == aVersion
&& result->GetSubVersion()
< aSubVersion) {
result->SetSubVersion(aSubVersion);
result->SetFirstRun(
aRunRange.GetFirstRun());
result->SetLastRun(
aRunRange.GetLastRun());
} else if (result->GetVersion() == aVersion
&& result->GetSubVersion() == aSubVersion){
AliError(Form("More than one object valid for run %d, version %d_%d!",
query.GetFirstRun(), aVersion, aSubVersion));
delete result;
return NULL;
}
}
} else if (!query.HasSubVersion()) {
result->SetVersion(query.GetVersion());
while ((key = (TKey*) iter.Next())) {
if (!KeyNameToId(key->GetName(), aRunRange, aVersion, aSubVersion)) continue;
if (!aRunRange.Comprises(query.GetAliCDBRunRange())) continue;
if(query.GetVersion() != aVersion) continue;
if(result->GetSubVersion() == aSubVersion){
AliError(Form("More than one object valid for run %d, version %d_%d!",
query.GetFirstRun(), aVersion, aSubVersion));
delete result;
return NULL;
}
if( result->GetSubVersion() < aSubVersion) {
result->SetSubVersion(aSubVersion);
result->SetFirstRun(
aRunRange.GetFirstRun());
result->SetLastRun(
aRunRange.GetLastRun());
}
}
} else {
while ((key = (TKey*) iter.Next())) {
if (!KeyNameToId(key->GetName(), aRunRange, aVersion, aSubVersion)) continue;
if (!aRunRange.Comprises(query.GetAliCDBRunRange())) continue;
if(query.GetVersion() != aVersion || query.GetSubVersion() != aSubVersion) continue;
if(result->GetVersion() == aVersion && result->GetSubVersion() == aSubVersion){
AliError(Form("More than one object valid for run %d, version %d_%d!",
query.GetFirstRun(), aVersion, aSubVersion));
delete result;
return NULL;
}
result->SetVersion(aVersion);
result->SetSubVersion(aSubVersion);
result->SetFirstRun(aRunRange.GetFirstRun());
result->SetLastRun(aRunRange.GetLastRun());
}
}
return result;
}
AliCDBEntry* AliCDBDump::GetEntry(const AliCDBId& queryId) {
TDirectory::TContext context(gDirectory, fFile);
if (!(fFile && fFile->IsOpen())) {
AliError("AliCDBDump storage is not initialized properly");
return NULL;
}
if (!gDirectory->cd(queryId.GetPath())) {
return NULL;
}
AliCDBId *dataId = GetEntryId(queryId);
if (!dataId || !dataId->IsSpecified()) {
if(dataId) delete dataId;
return NULL;
}
TString keyname;
if (!IdToKeyName(dataId->GetAliCDBRunRange(), dataId->GetVersion(),
dataId->GetSubVersion(), keyname)) {
AliDebug(2,Form("Bad ID encountered! Subnormal error!"));
delete dataId;
return NULL;
}
TObject* anObject = gDirectory->Get(keyname);
if (!anObject) {
AliDebug(2,Form("Bad storage data: NULL entry object!"));
delete dataId;
return NULL;
}
if (AliCDBEntry::Class() != anObject->IsA()) {
AliDebug(2,Form("Bad storage data: Invalid entry object!"));
delete dataId;
return NULL;
}
((AliCDBEntry*) anObject)->SetLastStorage("dump");
delete dataId;
return (AliCDBEntry*) anObject;
}
AliCDBId* AliCDBDump::GetEntryId(const AliCDBId& queryId) {
TDirectory::TContext context(gDirectory, fFile);
if (!(fFile && fFile->IsOpen())) {
AliError("AliCDBDump storage is not initialized properly");
return NULL;
}
if (!gDirectory->cd(queryId.GetPath())) {
return NULL;
}
AliCDBId* dataId = 0;
if (!queryId.HasVersion()) {
AliCDBId selectedId(queryId);
GetSelection(&selectedId);
dataId = GetId(queryId);
} else {
dataId = GetId(queryId);
}
if (dataId && !dataId->IsSpecified()) {
delete dataId;
return NULL;
}
return dataId;
}
void AliCDBDump::GetEntriesForLevel0(const AliCDBId& queryId, TList* result) {
TDirectory* saveDir = gDirectory;
TIter iter(gDirectory->GetListOfKeys());
TKey* key;
while ((key = (TKey*) iter.Next())) {
TString keyNameStr(key->GetName());
if (queryId.GetAliCDBPath().Level1Comprises(keyNameStr)) {
gDirectory->cd(keyNameStr);
GetEntriesForLevel1(queryId, result);
saveDir->cd();
}
}
}
void AliCDBDump::GetEntriesForLevel1(const AliCDBId& queryId, TList* result) {
TIter iter(gDirectory->GetListOfKeys());
TKey* key;
TDirectory* level0Dir = (TDirectory*) gDirectory->GetMother();
while ((key = (TKey*) iter.Next())) {
TString keyNameStr(key->GetName());
if (queryId.GetAliCDBPath().Level2Comprises(keyNameStr)) {
AliCDBPath aPath(level0Dir->GetName(),
gDirectory->GetName(), keyNameStr);
AliCDBId anId(aPath, queryId.GetAliCDBRunRange(),
queryId.GetVersion(), -1);
AliCDBEntry* anEntry = GetEntry(anId);
if (anEntry) {
result->Add(anEntry);
}
}
}
}
TList* AliCDBDump::GetEntries(const AliCDBId& queryId) {
TDirectory::TContext context(gDirectory, fFile);
if (!(fFile && fFile->IsOpen())) {
AliError("AliCDBDump storage is not initialized properly");
return NULL;
}
TList* result = new TList();
result->SetOwner();
TIter iter(gDirectory->GetListOfKeys());
TKey* key;
while ((key = (TKey*) iter.Next())) {
TString keyNameStr(key->GetName());
if (queryId.GetAliCDBPath().Level0Comprises(keyNameStr)) {
gDirectory->cd(keyNameStr);
GetEntriesForLevel0(queryId, result);
fFile->cd();
}
}
return result;
}
Bool_t AliCDBDump::PutEntry(AliCDBEntry* entry, const char* mirrors) {
TDirectory::TContext context(gDirectory, fFile);
if (!(fFile && fFile->IsOpen())) {
AliError("AliCDBDump storage is not initialized properly");
return kFALSE;
}
if (fReadOnly) {
AliError("AliCDBDump storage is read only!");
return kFALSE;
}
TString mirrorsString(mirrors);
if(!mirrorsString.IsNull())
AliWarning("AliCDBLocal storage cannot take mirror SEs into account. They will be ignored.");
AliCDBId& id = entry->GetId();
if (!gDirectory->cd(id.GetPath())) {
if (!MkDir(id.GetPath())) {
AliError(Form("Can't open directory <%s>!",
id.GetPath().Data()));
return kFALSE;
}
}
if (!PrepareId(id)) {
return kFALSE;
}
TString keyname;
if (!IdToKeyName(id.GetAliCDBRunRange(), id.GetVersion(), id.GetSubVersion(), keyname)) {
AliError("Invalid ID encountered! Subnormal error!");
return kFALSE;
}
Bool_t result = gDirectory->WriteTObject(entry, keyname);
if (!result) {
AliError(Form("Can't write entry to file: %s",
fFile->GetName()));
}
if(result) {
AliInfo(Form("CDB object stored into file %s",fFile->GetName()));
AliInfo(Form("TDirectory/key name: %s/%s",id.GetPath().Data(),keyname.Data()));
}
return result;
}
TList* AliCDBDump::GetIdListFromFile(const char* fileName){
TString turl(fileName);
if (turl[0] != '/') {
turl.Prepend(TString(gSystem->WorkingDirectory()) + '/');
}
TFile *file = TFile::Open(turl);
if (!file) {
AliError(Form("Can't open selection file <%s>!", turl.Data()));
return NULL;
}
file->cd();
TList *list = new TList();
list->SetOwner();
int i=0;
TString keycycle;
AliCDBId *id;
while(1){
i++;
keycycle = "AliCDBId;";
keycycle+=i;
id = (AliCDBId*) file->Get(keycycle);
if(!id) break;
list->AddFirst(id);
}
file->Close(); delete file; file=0;
return list;
}
Bool_t AliCDBDump::Contains(const char* path) const{
TDirectory::TContext context(gDirectory, fFile);
if (!(fFile && fFile->IsOpen())) {
AliError("AliCDBDump storage is not initialized properly");
return kFALSE;
}
return gDirectory->cd(path);
}
void AliCDBDump::QueryValidFiles()
{
AliError("Not yet (and maybe never) implemented");
}
Bool_t AliCDBDump::IdToFilename(const AliCDBId& , TString& ) const {
AliError("Not implemented");
return kFALSE;
}
void AliCDBDump::SetRetry(Int_t , Int_t ) {
AliInfo("This function sets the exponential retry for putting entries in the OCDB - to be used ONLY for AliCDBGrid --> returning without doing anything");
return;
}
ClassImp(AliCDBDumpFactory)
Bool_t AliCDBDumpFactory::Validate(const char* dbString) {
TRegexp dbPattern("^dump://.+$");
return TString(dbString).Contains(dbPattern);
}
AliCDBParam* AliCDBDumpFactory::CreateParameter(const char* dbString) {
if (!Validate(dbString)) {
return NULL;
}
TString pathname(dbString + sizeof("dump://") - 1);
Bool_t readOnly;
if (pathname.Contains(TRegexp(";ReadOnly$"))) {
pathname.Resize(pathname.Length() - sizeof(";ReadOnly") + 1);
readOnly = kTRUE;
} else {
readOnly = kFALSE;
}
gSystem->ExpandPathName(pathname);
if (pathname[0] != '/') {
pathname.Prepend(TString(gSystem->WorkingDirectory()) + '/');
}
return new AliCDBDumpParam(pathname, readOnly);
}
AliCDBStorage* AliCDBDumpFactory::Create(const AliCDBParam* param) {
if (AliCDBDumpParam::Class() == param->IsA()) {
const AliCDBDumpParam* dumpParam =
(const AliCDBDumpParam*) param;
return new AliCDBDump(dumpParam->GetPath(),
dumpParam->IsReadOnly());
}
return NULL;
}
ClassImp(AliCDBDumpParam)
AliCDBDumpParam::AliCDBDumpParam():
fDBPath(), fReadOnly(kFALSE)
{
}
AliCDBDumpParam::AliCDBDumpParam(const char* dbPath, Bool_t readOnly):
fDBPath(dbPath), fReadOnly(readOnly)
{
TString uri;
uri += "dump://";
uri += dbPath;
if (fReadOnly) {
uri += ";ReadOnly";
}
SetURI(uri);
SetType("dump");
}
AliCDBDumpParam::~AliCDBDumpParam() {
}
AliCDBParam* AliCDBDumpParam::CloneParam() const {
return new AliCDBDumpParam(fDBPath, fReadOnly);
}
ULong_t AliCDBDumpParam::Hash() const {
return fDBPath.Hash();
}
Bool_t AliCDBDumpParam::IsEqual(const TObject* obj) const {
if (this == obj) {
return kTRUE;
}
if (AliCDBDumpParam::Class() != obj->IsA()) {
return kFALSE;
}
AliCDBDumpParam* other = (AliCDBDumpParam*) obj;
return fDBPath == other->fDBPath;
}