Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

DbiTableProxyRegistry.cxx

Go to the documentation of this file.
00001 // $Id: DbiTableProxyRegistry.cxx,v 1.38 2008/08/22 10:27:57 nwest Exp $
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 //   Definition of static data members
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 //    Definition of all member functions (static or otherwise)
00032 //    *******************************************************
00033 //
00034 //    -  ordered: ctors, dtor, operators then in alphabetical order.
00035 
00036 //.....................................................................
00037 
00038 DbiTableProxyRegistry::DbiTableProxyRegistry() :
00039 fCascader(0)
00040 {
00041 //
00042 //
00043 //  Purpose:  Constructor
00044 //
00045 //  Arguments: None.
00046 //
00047 //  Return:    n/a
00048 //
00049 //  Contact:   N. West
00050 //
00051 //  Specification:-
00052 //  =============
00053 //
00054 //  o Create factory
00055 
00056 //  Program Notes:-
00057 //  =============
00058 
00059 //  None.
00060 
00061   LEA_CTOR    //Leak Checker
00062 
00063 // Create cascader for database access.
00064 
00065   fCascader = new DbiCascader;
00066 
00067 // Get any environment configuration.
00068 
00069   this->SetConfigFromEnvironment();
00070 
00071 // Create a DbiRecord to record a summary of all DbiResults in memory
00072 // and register it as a service.
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 //  Purpose: Destructor
00087 //
00088 //  Arguments: 
00089 //    None.
00090 //
00091 //  Return:    n/a
00092 //
00093 //  Contact:   N. West
00094 //
00095 //  Specification:-
00096 //  =============
00097 //
00098 //  o  Destroy all DbiTableProxies if Shutdown required.
00099 
00100 
00101   LEA_DTOR    //Leak Checker
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 // Destroy all owned objects.
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 //  Purpose: Apply Sql condition to existing DbiTableProxys.
00147 //
00148 //  Contact:   N. West
00149 //
00150 //  Specification:-
00151 //  =============
00152 //
00153 //  o Apply global Sql condition, together with any prevailing rollback to 
00154 //    all existing DbiTableProxys.
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 //  Purpose: Apply Sql condition to specific DbiTableProxy.
00167 //
00168 //  Arguments: 
00169 //    proxy        in    DbiTableProxy to which condition is to be applied.
00170 //
00171 //  Contact:   N. West
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 //  Purpose:  Reconfigure after internal registry update.
00208 //
00209 //  Contact:   N. West
00210 //
00211 //  Specification:-
00212 //  =============
00213 //
00214 //  o 
00215 
00216 //  Program Notes:-
00217 //  =============
00218 
00219 //  None.
00220 
00221   Registry& reg = this->GetConfig();
00222 
00223   //Load up SimFlag Associations and remove them from the Registry.
00224   fSimFlagAss.Set(reg);
00225 
00226   //Load up Rollback dates and remove them from the Registry.
00227   fRollbackDates.Set(reg);
00228 
00229   //Apply any rollback now in force.
00230   this->ApplySqlCondition();
00231 
00232   // If Level 2 cache enabled establish working directory 
00233   // for DbiBinaryFile. 
00234   const char*  dir;
00235   if ( reg.Get("Level2Cache",dir) ) {
00236     // Expand any environmental variables.
00237     TString tmp(dir);
00238     //  March 2004 ExpandPathName returns false even if it works, so test for failure
00239     //  by looking for an unexpanded symbol.
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   // Check for request to make all cascade connections permanent
00255   // and remove from the Registry.
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       // Inform DbiServices so that DbiConnection can check when opening new connections.
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       // Inform DbiServices so that DbiConnection can check when opening new connections.
00271       DbiServices::fAsciiDBConectionsTemporary = true;
00272     }
00273   }
00274 
00275   // Check for request to order context queries and remove from the Registry.
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   // Abort if Registry contains any unknown keys
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 //  Purpose:  Locate, or if necessary create, DbiTableProxy for 
00320 //            named table. 
00321 //
00322 //  Arguments: 
00323 //    tableNameReq in    Name of table requested.
00324 //    tableRow     in    Example of a Table Row object.
00325 //
00326 //  Return:    DbiTableProxy for table. 
00327 //
00328 //  Contact:   N. West
00329 //
00330 //  Specification:-
00331 //  =============
00332 //
00333 //  o Locate, or if necessary create, DbiTableProxy for named table.
00334 //
00335 //  o If creating apply prevailing SQL condition.
00336 
00337 //  Program Notes:-
00338 //  =============
00339 
00340 //  None.
00341 
00342 // Assume upper case name if cannot find request.
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 //  Purpose:  Test to see if table has a ROW_COUNTER column.
00370 //
00371 //  Arguments: 
00372 //    tableName    in    Name of table to be checked.
00373 //
00374 //  Return:    true of table has ROW_COUNTER.
00375 
00376 //  Program Notes:-
00377 //  =============
00378 
00379 //  This is a temporary method to help migration to main tables 
00380 //  with a primary key (SEQNO,ROW_COUNTER) by providing a simple
00381 //  way for clients to detect if any specific table has migrated
00382 //  and adapt accordingly.
00383 
00384 //  Once migration is complete, this method will be withdrawn as
00385 //  it should not be needed and creates otherwise useless DbiTableProxys.
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 //  Purpose: Locate, or create, DbiTableProxyRegistry singleton.   
00399 //
00400 //  Arguments:     None.
00401 //
00402 //  Return:    DbiTableProxyRegistry singleton. 
00403 //
00404 //  Contact:   N. West
00405 //
00406 //  Specification:-
00407 //  =============
00408 //
00409 //  o Locate, or if necessary create, DbiTableProxyRegistry singleton.
00410 
00411 //  Program Notes:-
00412 //  =============
00413 
00414 //  None.
00415 
00416   if ( ! fgInstance ) {
00417 // Delete is handled by Cleaner class based on #include count
00418     fgInstance = new DbiTableProxyRegistry();
00419   }
00420   return *fgInstance;
00421 
00422 }
00423 
00424 //.....................................................................
00425 
00426 void DbiTableProxyRegistry::PurgeCaches() {
00427 //
00428 //
00429 //  Purpose: Purge all caches.
00430 //
00431 //  Arguments: 
00432 //    None.
00433 //
00434 //  Return:    n/a
00435 //
00436 //  Contact:   N. West
00437 //
00438 //  Specification:-
00439 //  =============
00440 //
00441 //  o  Purge all caches.
00442 
00443 
00444 //  Program Notes:-
00445 //  =============
00446 
00447 //  None.
00448 
00449 // Pruge all caches.
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 //  Purpose: Refresh meta data for specied table.
00466 //
00467 //  Arguments: 
00468 //    tableName    in    Name of table to be refreshed.
00469 
00470 
00471 //  Program Notes:-
00472 //  =============
00473 
00474 //  This method is currently only used by DbiSqlValPacket after
00475 //  it has created a new table in the database.  In such cases
00476 //  the pre-existing corresponding DbiTableProxy has to be refreshed.
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 //  Purpose:  Set up configuration from ENV_DBI environmental variable
00492 //            which consists of a semi-colon separated list of DBI
00493 //            configuration requests.
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 //  Purpose: Record and apply global SQL condition.
00514 //
00515 //  Arguments: 
00516 //    sql          in    SQL condition string (excluding where).
00517 //
00518 //                       See Program Notes.
00519 //  Contact:   N. West
00520 //
00521 //  Specification:-
00522 //  =============
00523 //
00524 //  o Record global SQL condition and apply to existing DbiTableProxys.
00525 
00526 
00527 //  Program Notes:-
00528 //  =============
00529 
00530 //  The SQL condition must behave as a single expression as 
00531 //  additional conditions e.g. rollback, may be appended using
00532 // AND.  This means that if the expression contains sub-expressions
00533 //  combined using OR, then the entire expression should be enclosed
00534 //  in parentheses.
00535 
00536 
00537   fSqlCondition = sql;
00538   this->ApplySqlCondition();
00539 }
00540 
00541 //.....................................................................
00542 
00543 void DbiTableProxyRegistry::ShowStatistics() const {
00544 //
00545 //
00546 //  Purpose:  Show total statistics.
00547 //
00548 //  Contact:   N. West
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 // Loop over all owned objects.
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 //  Only want to look at cache so by-pass constness.
00567     const_cast<DbiTableProxy*>(tp)->GetCache()->ShowStatistics(msg);
00568    msg << endl;
00569   }
00570   msg << "\n" << endl;
00571 
00572 //  Only want to look at cascader so by-pass constness.
00573 
00574   MSG("Dbi",Msg::kInfo) << const_cast<DbiTableProxyRegistry*>(this)->GetCascader();
00575 
00576 
00577 }

Generated on Mon Feb 15 11:06:35 2010 for loon by  doxygen 1.3.9.1