00001
00002 #include <vector>
00003
00004 #include "TSystem.h"
00005
00006 #include "TString.h"
00007
00008 #include "DatabaseInterface/DbiExceptionLog.h"
00009 #include "DatabaseInterface/DbiBinaryFile.h"
00010 #include "DatabaseInterface/DbiCache.h"
00011 #include "DatabaseInterface/DbiCascader.h"
00012 #include "DatabaseInterface/DbiConfigSet.h"
00013 #include "DatabaseInterface/DbiRecord.h"
00014 #include "DatabaseInterface/DbiServices.h"
00015 #include "DatabaseInterface/DbiTableProxyRegistry.h"
00016 #include "DatabaseInterface/DbiTableProxy.h"
00017 #include "LeakChecker/Lea.h"
00018 #include "MessageService/MsgService.h"
00019 #include "Util/UtilString.h"
00020
00021 ClassImp(DbiTableProxyRegistry)
00022
00023
00024
00025
00026 CVSID("$Id: DbiTableProxyRegistry.cxx,v 1.38 2008/08/22 10:27:57 nwest Exp $");
00027
00028 DbiTableProxyRegistry* DbiTableProxyRegistry::fgInstance = 0;
00029 int DbiTableProxyRegistry::Cleaner::fgCount = 0;
00030
00031
00032
00033
00034
00035
00036
00037
00038 DbiTableProxyRegistry::DbiTableProxyRegistry() :
00039 fCascader(0)
00040 {
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 LEA_CTOR
00062
00063
00064
00065 fCascader = new DbiCascader;
00066
00067
00068
00069 this->SetConfigFromEnvironment();
00070
00071
00072
00073 DbiServices::SetRecord(new DbiRecord);
00074
00075 MSG("Dbi", Msg::kVerbose) << "Creating DbiTableProxyRegistry"
00076 << endl;
00077
00078
00079 }
00080
00081
00082
00083 DbiTableProxyRegistry::~DbiTableProxyRegistry() {
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101 LEA_DTOR
00102
00103 if ( DbiExceptionLog::GetGELog().Size() ) {
00104 MSG("Dbi",Msg::kInfo) << "Database Global Exception Log contains "
00105 << DbiExceptionLog::GetGELog().Size() << " entries:-" << endl;;
00106 DbiExceptionLog::GetGELog().Print();
00107 }
00108
00109 int shutdown = 0;
00110 if ( ! this->GetConfig().Get("Shutdown",shutdown)
00111 || shutdown == 0 ) {
00112 MSG("Dbi",Msg::kInfo) << "DatabaseInterface shutdown not requested" << endl;
00113 return;
00114 }
00115
00116 MSG("Dbi",Msg::kInfo) << "DatabaseInterface shutting down..." << endl;
00117
00118
00119
00120 for ( std::map<std::string,DbiTableProxy*>::iterator itr = fTPmap.begin();
00121 itr != fTPmap.end();
00122 ++itr) {
00123 DbiTableProxy* tp = (*itr).second;
00124 delete tp;
00125 }
00126
00127 delete fCascader;
00128 fCascader = 0;
00129
00130 delete DbiServices::GetRecord();
00131 DbiServices::SetRecord(0);
00132
00133 MSG("Dbi", Msg::kVerbose)
00134 << "Destroying DbiTableProxyRegistry" << endl;
00135
00136 MSG("Dbi", Msg::kInfo) << "DatabaseInterface shutdown complete." << endl;
00137 DbiTableProxyRegistry::fgInstance = 0;
00138
00139 }
00140
00141
00142
00143 void DbiTableProxyRegistry::ApplySqlCondition() const {
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156 std::map<std::string,DbiTableProxy*>::const_iterator itr = fTPmap.begin();
00157 std::map<std::string,DbiTableProxy*>::const_iterator itrEnd = fTPmap.end();
00158 for ( ; itr != itrEnd; ++itr) this->ApplySqlCondition(itr->second);
00159 }
00160
00161
00162
00163 void DbiTableProxyRegistry::ApplySqlCondition(DbiTableProxy* proxy) const {
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174 string sqlFull = fSqlCondition;
00175 const string tableName(proxy->GetTableName());
00176 const string& date = fRollbackDates.GetDate(tableName);
00177 if ( date.size() ) {
00178 if ( sqlFull.size() ) sqlFull += " and ";
00179 sqlFull += fRollbackDates.GetType(tableName);
00180 sqlFull += " < \'";
00181 sqlFull += date;
00182 sqlFull += "\'";
00183 }
00184
00185 proxy->SetSqlCondition(sqlFull);
00186 }
00187
00188
00189
00190 void DbiTableProxyRegistry::ClearRollbackDates() {
00191
00192 fRollbackDates.Clear();
00193 this->ApplySqlCondition();
00194 }
00195
00196
00197
00198 void DbiTableProxyRegistry::ClearSimFlagAssociation() {
00199
00200 fSimFlagAss.Clear();
00201 }
00202
00203
00204 void DbiTableProxyRegistry::Config() {
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221 Registry& reg = this->GetConfig();
00222
00223
00224 fSimFlagAss.Set(reg);
00225
00226
00227 fRollbackDates.Set(reg);
00228
00229
00230 this->ApplySqlCondition();
00231
00232
00233
00234 const char* dir;
00235 if ( reg.Get("Level2Cache",dir) ) {
00236
00237 TString tmp(dir);
00238
00239
00240 gSystem->ExpandPathName(tmp);
00241 if ( tmp.Contains("$" ) ) {
00242 dir = "./";
00243 MSG("Dbi",Msg::kWarning) << "Directory name expansion failed, using "
00244 << dir << " instead" << endl;
00245 }
00246 else {
00247 dir = tmp.Data();
00248 }
00249
00250 DbiBinaryFile::SetWorkDir(dir);
00251 MSG("Dbi",Msg::kInfo) << "DbiTableProxyRegistry: Setting L2 Cache to: " << dir << endl;
00252 }
00253
00254
00255
00256
00257 int connectionsPermanent = 0;
00258 if ( reg.Get("MakeConnectionsPermanent",connectionsPermanent) ) {
00259 reg.RemoveKey("MakeConnectionsPermanent");
00260 Int_t dbNo =fCascader->GetNumDb();
00261 if ( connectionsPermanent > 0 ) {
00262 while ( --dbNo >= 0 ) fCascader->SetPermanent(dbNo);
00263 MSG("Dbi",Msg::kInfo) << "Making all database connections permanent" << endl;
00264
00265 DbiServices::fAsciiDBConectionsTemporary = false;
00266 }
00267 else {
00268 while ( --dbNo >= 0 ) fCascader->SetPermanent(dbNo,false);
00269 MSG("Dbi",Msg::kInfo) << "Forcing all connections, including ASCII DB, to be temporary" << endl;
00270
00271 DbiServices::fAsciiDBConectionsTemporary = true;
00272 }
00273 }
00274
00275
00276
00277 int OrderContextQuery = 0;
00278 if ( reg.Get("OrderContextQuery",OrderContextQuery) ) {
00279 reg.RemoveKey("OrderContextQuery");
00280 if ( OrderContextQuery ) {
00281 DbiServices::fOrderContextQuery = true;
00282 MSG("Dbi",Msg::kInfo) << "Forcing ordering of all context queries" << endl;
00283 }
00284 }
00285
00286
00287
00288 const char* knownKeys[] = { "Level2Cache",
00289 "Shutdown" };
00290 int numKnownKeys = sizeof(knownKeys)/sizeof(char*);
00291 bool hasUnknownKeys = false;
00292
00293 Registry::RegistryKey keyItr(&this->GetConfig());
00294 while ( const char* foundKey = keyItr() ) {
00295 bool keyUnknown = true;
00296 for (int keyNum = 0; keyNum < numKnownKeys; ++keyNum ) {
00297 if ( ! strcmp(foundKey,knownKeys[keyNum]) ) keyUnknown = false;
00298 }
00299 if ( keyUnknown ) {
00300 MSG("Dbi",Msg::kFatal)
00301 << "Illegal registry item: " << foundKey << endl;
00302 hasUnknownKeys = true;
00303 }
00304 }
00305
00306 if ( hasUnknownKeys ) {
00307 MSG("Dbi",Msg::kFatal) << "Aborting due to illegal registry items." << endl;
00308 abort();
00309 }
00310 }
00311
00312
00313
00314 DbiTableProxy& DbiTableProxyRegistry::GetTableProxy
00315 (const std::string& tableNameReq,
00316 const DbiTableRow* tableRow) {
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343 std::string tableName = tableNameReq;
00344 std::string vldSuffix = "Validity";
00345 if ( ! fCascader->TableExists(tableName + vldSuffix ) ) {
00346 tableName = UtilString::ToUpper(tableName);
00347 vldSuffix = "VLD";
00348 }
00349 std::string proxyName = tableName;
00350
00351 proxyName.append("::");
00352 proxyName.append(tableRow->ClassName());
00353 DbiTableProxy* qpp = fTPmap[proxyName];
00354 if ( ! qpp ) {
00355 qpp = new DbiTableProxy(fCascader,tableName,vldSuffix,tableRow);
00356 this->ApplySqlCondition(qpp);
00357 fTPmap[proxyName] = qpp;
00358 }
00359
00360 return *qpp;
00361
00362 }
00363
00364
00365
00366 Bool_t DbiTableProxyRegistry::HasRowCounter(const std::string& tableName) {
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387 DbiConfigSet cfs;
00388 DbiTableProxy& tp = this->GetTableProxy(tableName,&cfs);
00389 return tp.GetMetaData().HasRowCounter();
00390
00391 }
00392
00393
00394
00395 DbiTableProxyRegistry& DbiTableProxyRegistry::Instance() {
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416 if ( ! fgInstance ) {
00417
00418 fgInstance = new DbiTableProxyRegistry();
00419 }
00420 return *fgInstance;
00421
00422 }
00423
00424
00425
00426 void DbiTableProxyRegistry::PurgeCaches() {
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451 for ( std::map<std::string,DbiTableProxy*>::iterator itr = fTPmap.begin();
00452 itr != fTPmap.end();
00453 ++itr) {
00454 DbiTableProxy* tp = (*itr).second;
00455 tp->GetCache()->Purge();
00456 }
00457
00458 }
00459
00460
00461
00462 void DbiTableProxyRegistry::RefreshMetaData(const std::string& tableName) {
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478 std::map<std::string,DbiTableProxy*>::iterator itr = fTPmap.begin();
00479 std::map<std::string,DbiTableProxy*>::iterator itrEnd = fTPmap.end();
00480 for ( ; itr != itrEnd; ++itr) {
00481 DbiTableProxy* table = (*itr).second;
00482 if ( table && table->GetTableName() == tableName ) table->RefreshMetaData();
00483 }
00484
00485 }
00486
00487
00488 void DbiTableProxyRegistry::SetConfigFromEnvironment() {
00489
00490
00491
00492
00493
00494
00495 const char* strENV_DBI = gSystem->Getenv("ENV_DBI");
00496 if ( strENV_DBI == 0 || strlen(strENV_DBI) == 0 ) return;
00497
00498 MSG("Dbi",Msg::kInfo) << "\nConfiguring DatabaseInterface from the environmental "
00499 << "variable ENV_DBI:-\n " << strENV_DBI << endl;
00500 std::vector<std::string> configRequests;
00501 UtilString::StringTok(configRequests, strENV_DBI, ";");
00502
00503 for (unsigned entry = 0; entry < configRequests.size(); ++entry )
00504 this->Set(configRequests[entry].c_str());
00505 this->Update();
00506 }
00507
00508
00509
00510 void DbiTableProxyRegistry::SetSqlCondition(const std::string& sql) {
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537 fSqlCondition = sql;
00538 this->ApplySqlCondition();
00539 }
00540
00541
00542
00543 void DbiTableProxyRegistry::ShowStatistics() const {
00544
00545
00546
00547
00548
00549
00550 MsgStream msg = MSGSTREAM("Dbi",Msg::kInfo);
00551 msg << "\n\nCache statistics:-\n\n"
00552 << "Table Name "
00553 << " Current Maximum Total Total\n"
00554 << " "
00555 << " Size Size Adopted Reused" << endl;
00556
00557
00558
00559 for ( std::map<std::string,DbiTableProxy*>::const_iterator itr = fTPmap.begin();
00560 itr != fTPmap.end();
00561 ++itr) {
00562 const DbiTableProxy* tp = (*itr).second;
00563 std::string name = (*itr).first;
00564 if ( name.size() < 40 ) name.append(40-name.size(),' ');
00565 msg << name;
00566
00567 const_cast<DbiTableProxy*>(tp)->GetCache()->ShowStatistics(msg);
00568 msg << endl;
00569 }
00570 msg << "\n" << endl;
00571
00572
00573
00574 MSG("Dbi",Msg::kInfo) << const_cast<DbiTableProxyRegistry*>(this)->GetCascader();
00575
00576
00577 }