TDbiDatabaseManager.cxx

Go to the documentation of this file.
00001 // $Id: TDbiDatabaseManager.cxx,v 1.2 2011/06/09 14:44:29 finch Exp $
00002 #include <vector>
00003 #include <cstdlib>
00004 
00005 #include "TSystem.h"
00006 
00007 #include "TString.h"
00008 
00009 #include "TDbiExceptionLog.hxx"
00010 #include "TDbiBinaryFile.hxx"
00011 #include "TDbiCache.hxx"
00012 #include "TDbiCascader.hxx"
00013 #include "TDbiConfigSet.hxx"
00014 #include "TDbiServices.hxx"
00015 #include "TDbiDatabaseManager.hxx"
00016 #include "TSK_DBI_Log.hxx"
00017 #include "TDbiTableProxy.hxx"
00018 #include <MsgFormat.h>
00019 using std::endl;
00020 #include "UtilString.hxx"
00021 
00022 ClassImp(TDbiDatabaseManager)
00023 
00024 //   Definition of static data members
00025 //   *********************************
00026 
00027 
00028 TDbiDatabaseManager* TDbiDatabaseManager::fgInstance       = 0;
00029 int                    TDbiDatabaseManager::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 TDbiDatabaseManager::TDbiDatabaseManager() :
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 
00062 // Create cascader for database access.
00063 
00064   fCascader = new TDbiCascader;
00065 
00066 // Get any environment configuration.
00067 
00068   this->SetConfigFromEnvironment();
00069 
00070   SK_DBI_Trace( "Creating TDbiDatabaseManager"
00071     << "  ");
00072 
00073 
00074 }
00075 
00076 //.....................................................................
00077 
00078 TDbiDatabaseManager::~TDbiDatabaseManager() {
00079 //
00080 //
00081 //  Purpose: Destructor
00082 //
00083 //  Arguments:
00084 //    None.
00085 //
00086 //  Return:    n/a
00087 //
00088 //  Contact:   N. West
00089 //
00090 //  Specification:-
00091 //  =============
00092 //
00093 //  o  Destroy all TDbiTableProxies if Shutdown required.
00094 
00095 
00096 
00097   if (  TDbiExceptionLog::GetGELog().Size() ) {
00098      SK_DBI_Info( "Database Global Exception Log contains "
00099           << TDbiExceptionLog::GetGELog().Size() << " entries:-" << "  ");;
00100      TDbiExceptionLog::GetGELog().Print();
00101   }
00102 
00103   int shutdown = 0;
00104   if (    ! this->GetConfig().Get("Shutdown",shutdown)
00105          || shutdown == 0 ) {
00106     SK_DBI_Info( "DatabaseInterface shutdown not requested" << "  ");
00107     return;
00108   }
00109 
00110   SK_DBI_Info( "DatabaseInterface shutting down..." << "  ");
00111 
00112 // Destroy all owned objects.
00113 
00114   for ( std::map<std::string,TDbiTableProxy*>::iterator itr = fTPmap.begin();
00115         itr != fTPmap.end();
00116         ++itr) {
00117     TDbiTableProxy* tp = (*itr).second;
00118     delete tp;
00119   }
00120 
00121   delete fCascader;
00122   fCascader = 0;
00123 
00124   SK_DBI_Trace(  "Destroying TDbiDatabaseManager" << "  ");
00125 
00126   SK_DBI_Info( "DatabaseInterface shutdown complete." << "  ");
00127   TDbiDatabaseManager::fgInstance = 0;
00128 
00129 }
00130 
00131 //.....................................................................
00132 
00133 void TDbiDatabaseManager::ApplySqlCondition() const {
00134 //
00135 //
00136 //  Purpose: Apply Sql condition to existing TDbiTableProxys.
00137 //
00138 //  Contact:   N. West
00139 //
00140 //  Specification:-
00141 //  =============
00142 //
00143 //  o Apply global Sql condition, together with any prevailing rollback to
00144 //    all existing TDbiTableProxys.
00145 
00146   std::map<std::string,TDbiTableProxy*>::const_iterator itr = fTPmap.begin();
00147   std::map<std::string,TDbiTableProxy*>::const_iterator itrEnd = fTPmap.end();
00148   for ( ; itr != itrEnd; ++itr) this->ApplySqlCondition(itr->second);
00149 }
00150 
00151 //.....................................................................
00152 
00153 void TDbiDatabaseManager::ApplySqlCondition(TDbiTableProxy* proxy) const {
00154 //
00155 //
00156 //  Purpose: Apply Sql condition to specific TDbiTableProxy.
00157 //
00158 //  Arguments:
00159 //    proxy        in    TDbiTableProxy to which condition is to be applied.
00160 //
00161 //  Contact:   N. West
00162 //
00163 
00164   string sqlFull = fSqlCondition;
00165   const string tableName(proxy->GetTableName());
00166   const string& date = fRollbackDates.GetDate(tableName);
00167   if ( date.size() ) {
00168     if ( sqlFull.size() ) sqlFull += " and ";
00169     sqlFull += fRollbackDates.GetType(tableName);
00170     sqlFull += " < \'";
00171     sqlFull += date;
00172     sqlFull += "\'";
00173   }
00174   const string& epoch_condition = fEpochRollback.GetEpochCondition(tableName);
00175   if ( epoch_condition.size() ) {
00176     if ( sqlFull.size() ) sqlFull += " and ";
00177     sqlFull += epoch_condition;
00178   }
00179 
00180   proxy->SetSqlCondition(sqlFull);
00181 }
00182 
00183 //.....................................................................
00184 
00185 void TDbiDatabaseManager::ClearRollbacks() {
00186 
00187   fEpochRollback.Clear();
00188   fRollbackDates.Clear();
00189   this->ApplySqlCondition();
00190 }
00191 
00192 //.....................................................................
00193 
00194 void TDbiDatabaseManager::ClearSimFlagAssociation() {
00195 
00196   fSimFlagAss.Clear();
00197 }
00198 //.....................................................................
00199 ///
00200 ///
00201 ///  Purpose:  Reconfigure after internal registry update.
00202 ///
00203 ///
00204 ///    Throws  EBadTDbiRegistryKeys()  if TDbiRegistry contains any unknown keys
00205 void TDbiDatabaseManager::Config() {
00206 //  Contact:   N. West
00207 //
00208 //  Specification:-
00209 //  =============
00210 //
00211 //  o
00212 
00213 //  Program Notes:-
00214 //  =============
00215 
00216 //  None.
00217 
00218   TDbiRegistry& reg = this->GetConfig();
00219 
00220   //Load up SimFlag Associations and remove them from the TDbiRegistry.
00221   fSimFlagAss.Set(reg);
00222 
00223   //Load up Rollback dates and epochs and remove them from the TDbiRegistry.
00224   fEpochRollback.Set(reg);
00225   fRollbackDates.Set(reg);
00226 
00227   //Apply any rollback now in force.
00228   this->ApplySqlCondition();
00229 
00230   // If Level 2 cache enabled establish working directory
00231   // for TDbiBinaryFile.
00232   const char*  dir;
00233   if ( reg.Get("Level2Cache",dir) ) {
00234     // Expand any environmental variables.
00235     TString tmp(dir);
00236     //  March 2004 ExpandPathName returns false even if it works, so test for failure
00237     //  by looking for an unexpanded symbol.
00238     gSystem->ExpandPathName(tmp);
00239     if ( tmp.Contains("$" ) ) {
00240       dir = "./";
00241       SK_DBI_Warn( "Directory name expansion failed, using "
00242                              << dir << " instead" << "  ");
00243     }
00244     else {
00245       dir = tmp.Data();
00246     }
00247 
00248     TDbiBinaryFile::SetWorkDir(dir);
00249     SK_DBI_Log( "TDbiDatabaseManager: Setting L2 Cache to: " << dir << "  ");
00250   }
00251 
00252   // Check for request to make all cascade connections permanent
00253   // and remove from the TDbiRegistry.
00254 
00255   int connectionsPermanent = 0;
00256   if ( reg.Get("MakeConnectionsPermanent",connectionsPermanent) ) {
00257     reg.RemoveKey("MakeConnectionsPermanent");
00258     Int_t dbNo =fCascader->GetNumDb();
00259     if ( connectionsPermanent > 0 ) {
00260       while ( --dbNo >= 0 ) fCascader->SetPermanent(dbNo);
00261       SK_DBI_Info( "Making all database connections permanent" << "  ");
00262       // Inform TDbiServices so that TDbiConnection can check when opening new connections.
00263       TDbiServices::fAsciiDBConectionsTemporary = false;
00264     }
00265     else {
00266       while ( --dbNo >= 0 ) fCascader->SetPermanent(dbNo,false);
00267       SK_DBI_Info( "Forcing all connections, including ASCII DB, to be temporary" << "  ");
00268       // Inform TDbiServices so that TDbiConnection can check when opening new connections.
00269       TDbiServices::fAsciiDBConectionsTemporary = true;
00270     }
00271   }
00272 
00273   // Check for request to order context queries and remove from the TDbiRegistry.
00274 
00275   int OrderContextQuery = 0;
00276   if ( reg.Get("OrderContextQuery",OrderContextQuery) ) {
00277     reg.RemoveKey("OrderContextQuery");
00278     if ( OrderContextQuery ) {
00279       TDbiServices::fOrderContextQuery = true;
00280       SK_DBI_Info( "Forcing ordering of all context queries" << "  ");
00281     }
00282   }
00283 
00284   // Abort if TDbiRegistry contains any unknown keys
00285 
00286   const char* knownKeys[]   = { "Level2Cache",
00287                                 "Shutdown" };
00288   int numKnownKeys          = sizeof(knownKeys)/sizeof(char*);
00289   bool hasUnknownKeys       = false;
00290 
00291   TDbiRegistry::TDbiRegistryKey keyItr(&this->GetConfig());
00292   while ( const char* foundKey = keyItr() ) {
00293     bool keyUnknown = true;
00294     for (int keyNum = 0; keyNum < numKnownKeys; ++keyNum ) {
00295       if ( ! strcmp(foundKey,knownKeys[keyNum]) ) keyUnknown = false;
00296     }
00297     if ( keyUnknown ) {
00298      SK_DBI_Severe( "FATAL: "
00299         << "Illegal registry item: " << foundKey << "  ");
00300        hasUnknownKeys = true;
00301     }
00302   }
00303 
00304   if ( hasUnknownKeys ) {
00305     SK_DBI_Severe( "FATAL: " << "Aborting due to illegal registry items." << "  ");
00306     throw  EBadTDbiRegistryKeys();
00307   }
00308 }
00309 
00310 //.....................................................................
00311 
00312 TDbiTableProxy& TDbiDatabaseManager::GetTableProxy
00313                                     (const std::string& tableNameReq,
00314                                      const TDbiTableRow* tableRow) {
00315 //
00316 //
00317 //  Purpose:  Locate, or if necessary create, TDbiTableProxy for
00318 //            named table.
00319 //
00320 //  Arguments:
00321 //    tableNameReq in    Name of table requested.
00322 //    tableRow     in    Example of a Table Row object.
00323 //
00324 //  Return:    TDbiTableProxy for table.
00325 //
00326 //  Contact:   N. West
00327 //
00328 //  Specification:-
00329 //  =============
00330 //
00331 //  o Locate, or if necessary create, TDbiTableProxy for named table.
00332 //
00333 //  o If creating apply prevailing SQL condition.
00334 
00335 //  Program Notes:-
00336 //  =============
00337 
00338 //  None.
00339 
00340 // Force upper case name.
00341   std::string tableName = UtilString::ToUpper(tableNameReq);
00342   std::string proxyName = tableName;
00343 
00344   proxyName.append("::");
00345   proxyName.append(tableRow->ClassName());
00346   TDbiTableProxy* qpp = fTPmap[proxyName];
00347   if ( ! qpp ) {
00348     qpp = new TDbiTableProxy(fCascader,tableName,tableRow);
00349     this->ApplySqlCondition(qpp);
00350     fTPmap[proxyName] = qpp;
00351   }
00352 
00353   return *qpp;
00354 
00355 }
00356 
00357 //.....................................................................
00358 
00359 TDbiDatabaseManager& TDbiDatabaseManager::Instance() {
00360 //
00361 //
00362 //  Purpose: Locate, or create, TDbiDatabaseManager singleton.
00363 //
00364 //  Arguments:     None.
00365 //
00366 //  Return:    TDbiDatabaseManager singleton.
00367 //
00368 //  Contact:   N. West
00369 //
00370 //  Specification:-
00371 //  =============
00372 //
00373 //  o Locate, or if necessary create, TDbiDatabaseManager singleton.
00374 
00375 //  Program Notes:-
00376 //  =============
00377 
00378 //  None.
00379 
00380   if ( ! fgInstance ) {
00381 // Delete is handled by Cleaner class based on #include count
00382     fgInstance = new TDbiDatabaseManager();
00383   }
00384   return *fgInstance;
00385 
00386 }
00387 
00388 //.....................................................................
00389 
00390 void TDbiDatabaseManager::PurgeCaches() {
00391 //
00392 //
00393 //  Purpose: Purge all caches.
00394 //
00395 //  Arguments:
00396 //    None.
00397 //
00398 //  Return:    n/a
00399 //
00400 //  Contact:   N. West
00401 //
00402 //  Specification:-
00403 //  =============
00404 //
00405 //  o  Purge all caches.
00406 
00407 
00408 //  Program Notes:-
00409 //  =============
00410 
00411 //  None.
00412 
00413 // Pruge all caches.
00414 
00415   for ( std::map<std::string,TDbiTableProxy*>::iterator itr = fTPmap.begin();
00416         itr != fTPmap.end();
00417         ++itr) {
00418     TDbiTableProxy* tp = (*itr).second;
00419     tp->GetCache()->Purge();
00420   }
00421 
00422 }
00423 
00424 //.....................................................................
00425 
00426 void TDbiDatabaseManager::RefreshMetaData(const std::string& tableName) {
00427 //
00428 //
00429 //  Purpose: Refresh meta data for specied table.
00430 //
00431 //  Arguments:
00432 //    tableName    in    Name of table to be refreshed.
00433 
00434 
00435 //  Program Notes:-
00436 //  =============
00437 
00438 //  This method is currently only used by TDbiSqlValPacket after
00439 //  it has created a new table in the database.  In such cases
00440 //  the pre-existing corresponding TDbiTableProxy.hxxas to be refreshed.
00441 
00442   std::map<std::string,TDbiTableProxy*>::iterator itr = fTPmap.begin();
00443   std::map<std::string,TDbiTableProxy*>::iterator itrEnd = fTPmap.end();
00444   for ( ; itr != itrEnd; ++itr) {
00445     TDbiTableProxy* table = (*itr).second;
00446     if ( table && table->GetTableName() == tableName ) table->RefreshMetaData();
00447   }
00448 
00449 }
00450 //.....................................................................
00451 
00452 void TDbiDatabaseManager::SetConfigFromEnvironment() {
00453 //
00454 //
00455 //  Purpose:  Set up configuration from ENV_DBI environmental variable
00456 //            which consists of a semi-colon separated list of DBI
00457 //            configuration requests.
00458 
00459   const char* strENV_DBI = gSystem->Getenv("ENV_DBI");
00460   if ( strENV_DBI == 0  || strlen(strENV_DBI) == 0 ) return;
00461 
00462   SK_DBI_Info( "\nConfiguring DatabaseInterface from the environmental "
00463              << "variable ENV_DBI:-\n  " << strENV_DBI << "  ");
00464   std::vector<std::string> configRequests;
00465   UtilString::StringTok(configRequests, strENV_DBI, ";");
00466 
00467   for (unsigned entry = 0; entry < configRequests.size(); ++entry )
00468                   this->Set(configRequests[entry].c_str());
00469   this->Update();
00470 }
00471 
00472 //.....................................................................
00473 
00474 void TDbiDatabaseManager::SetSqlCondition(const std::string& sql) {
00475 //
00476 //
00477 //  Purpose: Record and apply global SQL condition.
00478 //
00479 //  Arguments:
00480 //    sql          in    SQL condition string (excluding where).
00481 //
00482 //                       See Program Notes.
00483 //  Contact:   N. West
00484 //
00485 //  Specification:-
00486 //  =============
00487 //
00488 //  o Record global SQL condition and apply to existing TDbiTableProxys.
00489 
00490 
00491 //  Program Notes:-
00492 //  =============
00493 
00494 //  The SQL condition must behave as a single expression as
00495 //  additional conditions e.g. rollback, may be appended using
00496 // AND.  This means that if the expression contains sub-expressions
00497 //  combined using OR, then the entire expression should be enclosed
00498 //  in parentheses.
00499 
00500 
00501   fSqlCondition = sql;
00502   this->ApplySqlCondition();
00503 }
00504 
00505 //.....................................................................
00506 
00507 void TDbiDatabaseManager::ShowStatistics() const {
00508 //
00509 //
00510 //  Purpose:  Show total statistics.
00511 //
00512 //  Contact:   N. West
00513 
00514 }

Generated on 11 Aug 2013 for SKDatabase by  doxygen 1.6.1