Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members  

CdbBdbSCdb.cc

Go to the documentation of this file.
00001 // File and Version Information:
00002 //      $Id: CdbBdbSCdb.cc,v 1.17 2005/04/30 02:05:45 gapon Exp $
00003 
00004 /// The implementation of the CdbBdbSCdb singleton.
00005 /**
00006   * @see CdbBdbSCdb
00007   */
00008 
00009 #include "BaBar/BaBar.hh"
00010 
00011 #include "CdbBdbShared/CdbBdbSCdb.hh"
00012 
00013 #include "CdbBase/CdbView.hh"
00014 #include "CdbBase/CdbDatabase.hh"
00015 #include "CdbBase/CdbEnvironment.hh"
00016 #include "CdbBase/CdbDebugStream.hh"
00017 
00018 #include "CdbBdb/CdbBdbTransaction.hh"
00019 
00020 #include "CdbBdbShared/CdbBdbShared.hh"
00021 #include "CdbBdbShared/CdbBdbSDatabase.hh"
00022 #include "CdbBdbShared/CdbBdbSDatabaseItr.hh"
00023 #include "CdbBdbShared/CdbBdbSMasterRegistryP.hh"
00024 #include "CdbBdbShared/CdbBdbSSlaveRegistryP.hh"
00025 #include "CdbBdbShared/CdbBdbSTestRegistryP.hh"
00026 
00027 #include "BdbTime/BdbTime.hh"
00028 
00029 #include "BdbCond/BdbConditions.hh"
00030 
00031 #include "BdbApplication/BdbDomain.hh"
00032 
00033 #include "ErrLogger/ErrLog.hh"
00034 
00035 #include <string.h>
00036 #include <assert.h>
00037 #include <iostream>
00038 using std::cout;
00039 using std::endl;
00040 
00041 namespace {
00042 
00043   ////////////////////
00044   // V-table loader //
00045   ////////////////////
00046 
00047     void
00048     loadVTables( const CdbPtr& thePtr )
00049     {
00050         const char* fatalStr = "CdbBdbSCdb::<anonymous>::loadVTables() -- FATAL ERROR.";
00051 
00052       // The smart pointer passed down to this method should always
00053       // point to something to avoid crash below.
00054 
00055         if( thePtr.isNull( )) {
00056 
00057           // Except their creation time, the following classes are never used on its
00058           // own - only through their base classes.
00059           //
00060           // NOTE: It's important to call a virtual method to ensure that the corresponding
00061           //       v-tables are loaded. Just constructing a transient object of a final
00062           //       persistent class is not going to help for some compilers or optimized
00063           //       compilation modes.
00064 
00065             CdbBdbSMasterRegistryP master( "This constructor never gets executed here",
00066                                             BdbTime::plusInfinity );
00067 
00068             BdbRef(CdbBdbSOriginCollectionP) masterOriginCollRef = master.originCollection( );
00069             if( ! BdbIsNull(masterOriginCollRef)) {
00070 
00071                 cout << fatalStr << endl
00072                      << "    You should never see this message. Still if you do then a nasty" << endl
00073                      << "    memory corruption is taking place in the current application." << endl
00074                      << "    Here is a number: " << masterOriginCollRef->elements( ) << endl;
00075                 assert( 0 );
00076 
00077                 return;
00078             }
00079 
00080             CdbBdbSSlaveRegistryP slave( 0,
00081                                          "This constructor never gets executed here",
00082                                           BdbTime::plusInfinity,
00083                                           BdbTime::plusInfinity );
00084 
00085             BdbRef(CdbBdbSOriginCollectionP) slaveOriginCollRef = slave.originCollection( );
00086             if( ! BdbIsNull(slaveOriginCollRef)) {
00087 
00088                 cout << fatalStr << endl
00089                      << "    You should never see this message. Still if you do then a nasty" << endl
00090                      << "    memory corruption is taking place in the current application." << endl
00091                      << "    Here is a number: " << slaveOriginCollRef->elements( ) << endl;
00092                 assert( 0 );
00093 
00094                 return;
00095             }
00096 
00097             CdbBdbSTestRegistryP test( "This constructor never gets executed here",
00098                                        BdbTime::plusInfinity,
00099                                        BdbTime::plusInfinity );
00100 
00101             BdbRef(CdbBdbSOriginCollectionP) testOriginCollRef = test.originCollection( );
00102             if( ! BdbIsNull(testOriginCollRef)) {
00103 
00104                 cout << fatalStr << endl
00105                      << "    You should never see this message. Still if you do then a nasty" << endl
00106                      << "    memory corruption is taking place in the current application." << endl
00107                      << "    Here is a number: " << testOriginCollRef->elements( ) << endl;
00108                 assert( 0 );
00109 
00110                 return;
00111             }
00112         }
00113     }
00114 
00115   ////////////////////////////////////////////////
00116   // Check the status of teh current federation //
00117   ////////////////////////////////////////////////
00118 
00119     bool currentFederationIsInitialized( )
00120     {
00121         CdbTransaction transactioni( CdbBdbShared::technology( ),
00122                                      CdbBdbShared::implementation( ));
00123 
00124         BdbHandle(BdbDBObj) dH;
00125         return d_True == dH.exist( BdbApplicationOrDomain::activeInstance( )->fd( ),
00126                                    "con_cdb_database",
00127                                    BdbcNoOpen );
00128     }
00129 };
00130 
00131 ///////////////////////////////
00132 // CdbBdbSCdb implementation //
00133 ///////////////////////////////
00134 
00135 CdbBdbSCdb::CdbBdbSCdb( ) :
00136     Cdb( ),
00137     _isInitialized(false),                  // For the sake of deffered initialization
00138     _defaultViewName("<local>::<recent>")
00139 {
00140     CDB_DEBUG_STREAM
00141         << "Condition/DB API instantiated for"
00142         << " TECHNOLOGY=\""     << CdbBdbShared::technology( )     << "\""
00143         << " IMPLEMENTATION=\"" << CdbBdbShared::implementation( ) << "\""
00144         << endl;
00145 
00146   // Try to register itself in the API registry.
00147   //
00148   // NOTE: If the registration will fail then we may probably encounter a fatal
00149   //       unrecoverable problem with implementations of CDB API. One of the possible
00150   //       reasons of the falure would be if another implementation of the API has already
00151   //       registered itself in the dictionary under the same names.
00152 
00153     CdbPtr myPtr = this;
00154 
00155     CdbStatus status = set( myPtr );
00156     assert( CdbStatus::Success == status );
00157 
00158   // Make sure that v-tables for persistent classes are loaded
00159 
00160     loadVTables( myPtr );
00161 }
00162 
00163 CdbBdbSCdb::~CdbBdbSCdb( )
00164 { }
00165 
00166 const char*
00167 CdbBdbSCdb::technologyName( ) const
00168 {
00169     return CdbBdbShared::technology( );
00170 }
00171 
00172 const char*
00173 CdbBdbSCdb::implementationName( ) const
00174 {
00175     return CdbBdbShared::implementation( );
00176 }
00177 
00178 void
00179 CdbBdbSCdb::initialize( )
00180 {
00181     if( !_isInitialized ) {
00182 
00183       // IMPORTANT: This flag has to be set up first before doing any actual
00184       //            operations with the persistent store since we may have
00185       //            indirect recursion when setting default (the defaults setting
00186       //            algorithm may request initialization).
00187 
00188         _isInitialized = true;
00189 
00190       // Check for the presense of the "Shared" databases in the federation and
00191       // if they are found setup the proper default.
00192 
00193         if( currentFederationIsInitialized( )) {
00194             CdbEnvironment::setDefault( CdbBdbShared::technology( ),
00195                                         CdbBdbShared::implementation( ),
00196                                         BdbConditions::instance( )->bootName( ),
00197                                         "<local>::<recent>" );
00198         }
00199     }
00200 }
00201 
00202 bool
00203 CdbBdbSCdb::isInitialized( )
00204 {
00205     return _isInitialized;
00206 }
00207 
00208 CdbStatus
00209 CdbBdbSCdb::getDefaultDatabase( std::string& theDatabaseName )
00210 {
00211     assert( isInitialized( ));
00212 
00213     theDatabaseName = BdbConditions::instance( )->bootName( );
00214 
00215     return CdbStatus::Success;
00216 }
00217 
00218 CdbStatus
00219 CdbBdbSCdb::getDefaultView( std::string& theViewName,
00220                             const char*  theDatabaseName )
00221 {
00222     assert( isInitialized( ));
00223 
00224     CdbStatus result = CdbStatus::NotFound;
00225     do {
00226 
00227       // Verify the database name
00228       //
00229       // We only allow the following:
00230       //
00231       //   - "<default>"
00232       //   - the actual BOOT file name of the CDB federation.
00233       //
00234       // All these options are treated equally since we only have just one database
00235       // in the current implementation.
00236 
00237         if( 0 == theDatabaseName ) break;
00238 
00239         if( ! (( 0 == strcmp( theDatabaseName, "<default>" )) ||
00240                ( 0 == strcmp( theDatabaseName, BdbConditions::instance( )->bootName( ))))) break;
00241 
00242       // Return the current default.
00243 
00244         theViewName = _defaultViewName;
00245 
00246       // Done
00247 
00248         result = CdbStatus::Success;
00249 
00250     } while( false );
00251 
00252     return result; 
00253 }
00254 
00255 CdbStatus
00256 CdbBdbSCdb::setDefaultDatabase( const char* theDatabaseName )
00257 {
00258     assert( isInitialized( ));
00259 
00260   // This is basically "do nothing; method. It just checks for the correctness
00261   // of the database name.
00262 
00263     CdbStatus result = CdbStatus::NotFound;
00264     do {
00265 
00266       // Verify the database name
00267       //
00268       // We only allow the following:
00269       //
00270       //   - "<default>"
00271       //   - the actual BOOT file name of the CDB federation.
00272       //
00273       // All these options are treated equally since we only have just one database
00274       // in the current implementation.
00275 
00276         if( 0 == theDatabaseName ) break;
00277 
00278         if( ! (( 0 == strcmp( theDatabaseName, "<default>" )) ||
00279                ( 0 == strcmp( theDatabaseName, BdbConditions::instance( )->bootName( ))))) break;
00280 
00281       // Done
00282 
00283         result = CdbStatus::Success;
00284 
00285     } while( false );
00286 
00287     return result; 
00288 }
00289 
00290 CdbStatus
00291 CdbBdbSCdb::setDefaultView( const char* theViewName,
00292                             const char* theDatabaseName )
00293 {
00294     assert( isInitialized( ));
00295 
00296   // This method will checks for the correctness of the database and view names.
00297   //
00298   // IMPLEMENTATION NOTE: It will NOT check if specified view is present in the database.
00299   //                      The reason is that certain operations with CDB may be permitted
00300   //                      without having finally established database.
00301 
00302     CdbStatus result = CdbStatus::NotFound;
00303     do {
00304 
00305       // Verify the database name
00306       //
00307       // We only allow the following:
00308       //
00309       //   - "<default>"
00310       //   - the actual BOOT file name of the CDB federation.
00311       //
00312       // All these options are treated equally since we only have just one database
00313       // in the current implementation.
00314 
00315         if( 0 == theDatabaseName ) break;
00316 
00317         if( ! (( 0 == strcmp( theDatabaseName, "<default>" )) ||
00318                ( 0 == strcmp( theDatabaseName, BdbConditions::instance( )->bootName( ))))) break;
00319 
00320 
00321       // Verify the database name
00322 
00323         if( 0 == theViewName ) break;
00324 /**
00325  ** IMPLEMENTATION NOTE: The following code is disabled to allow operations with
00326  **                      incomplete CDB.
00327  **
00328       // Try open the database and the view to check if they both exist.
00329 
00330         CdbDatabasePtr databasePtr;
00331         if( CdbStatus::Success != findDatabase( databasePtr )) break;
00332 
00333         CdbViewPtr viewPtr;
00334         if( CdbStatus::Success != databasePtr->findView( viewPtr, theViewName  )) break;
00335  **
00336  **/
00337       // Done
00338 
00339         _defaultViewName = theViewName;
00340 
00341         result = CdbStatus::Success;
00342 
00343     } while( false );
00344 
00345     return result; 
00346 }
00347 
00348 CdbStatus
00349 CdbBdbSCdb::findDatabase( CdbDatabasePtr& thePtr,
00350                           const char*     theName )
00351 {
00352     assert( isInitialized( ));
00353 
00354     CdbStatus result = CdbStatus::Error;
00355 
00356     thePtr = 0;
00357 
00358     do {
00359 
00360       // Verify and correct parameters if 0 pointer is passed to indicate
00361       // that default database is needed. The "<default>" string is also allowed
00362       // since the current implementation maps it onto the boot file name.
00363 
00364         std::string defaultDatabaseName;
00365         if( CdbStatus::Success != getDefaultDatabase( defaultDatabaseName )) break;
00366 
00367         std::string databaseName = defaultDatabaseName;
00368         if( 0 != theName ) {
00369             if( 0 == strcmp( "<default>", theName )) {
00370 
00371               // This is a special keyword to be mapped onto whatever default
00372               // bootfile name we have.
00373 
00374                 ;
00375 
00376             } else {
00377                 databaseName = theName;
00378             }
00379         }
00380 
00381         if( databaseName != defaultDatabaseName ) {
00382 
00383             cout << "CdbBdbSCdb::findDatabase( ) -- ERROR" << endl
00384                  << "    No such database in this implementation:  \"" << databaseName.c_str( )        << "\"" << endl
00385                  << "    The only name allowed is the default one: \"" << defaultDatabaseName.c_str( ) << "\"" << endl;
00386 
00387             break;
00388         }
00389 
00390       // NOTE: - the above corrected parameters object is used.
00391       //       - a smart pointer onto itself is found through the registry.
00392 
00393         CdbPtr selfPtr;
00394         if( CdbStatus::Success != get( selfPtr,
00395                                        technologyName( ),
00396                                        implementationName( ))) {
00397             cout << "CdbBdbSCdb::findDatabase( ) -- FATAL ERROR" << endl
00398                  << "    Failed to recover its own instance of the CDB API." << endl
00399                  << "        TECHNOLOGY     : \"" << technologyName( ) << "\"" << endl
00400                  << "        IMPLEMENTATION : \"" << implementationName( ) << "\"" << endl;
00401 
00402             assert( 0 );
00403 
00404             break;
00405         }
00406         thePtr = new CdbBdbSDatabase( selfPtr,
00407                                       databaseName.c_str( ));
00408         result = CdbStatus::Success;
00409 
00410     } while( false );
00411 
00412     return result;
00413 }
00414 
00415 CdbStatus
00416 CdbBdbSCdb::databaseIterator( CdbDatabaseItr& theItr )
00417 {
00418     assert( isInitialized( ));
00419 
00420   // Note, that we find its own smart pointer through the Registry
00421 
00422   // ATTENTION: This is not a memory leak - the created object
00423   //            will be destroyed by the iterator.
00424 
00425     CdbPtr selfPtr;
00426     if( CdbStatus::Success != get( selfPtr,
00427                                    technologyName( ),
00428                                    implementationName( ))) {
00429         cout << "CdbBdbSCdb::databaseIterator( ) -- FATAL ERROR" << endl
00430              << "    Failed to recover its own instance of the CDB API." << endl
00431              << "        TECHNOLOGY     : \"" << technologyName( ) << "\"" << endl
00432              << "        IMPLEMENTATION : \"" << implementationName( ) << "\"" << endl;
00433 
00434         assert( 0 );
00435 
00436         return CdbStatus::Error;
00437     }
00438     theItr = CdbDatabaseItr( new CdbBdbSDatabaseItr( selfPtr ));
00439 
00440     return CdbStatus::Success;
00441 }
00442 
00443 CdbTransactionBase*
00444 CdbBdbSCdb::transaction( CdbTransaction::Mode theMode ) const
00445 {
00446   // Translate the transaction mode from "Bdb"-specific enum into
00447   // the corresponding technology-neutral one.
00448 
00449     switch( theMode ) {
00450     case CdbTransaction::Read:   return new CdbBdbTransaction( BdbcRead );
00451     case CdbTransaction::Update: return new CdbBdbTransaction( BdbcUpdate );
00452     };
00453 
00454   // For unknown mode complain report the problem, try to crash the application,
00455   // and if this doesn't help then return 0.
00456 
00457     ErrMsg(fatal) << "CdbBdbSCdb::transaction( ) -- FATAL ERROR" << endl
00458                   << "    Unssuported transaction mode: " << theMode << endl
00459                   << "    The implementation of the current method doesn't seem to follow changes" << endl
00460                   << "    in the technology-neutral CDB API." << endmsg;
00461     return 0;
00462 }
00463 
00464 /////////////////
00465 // End Of File //
00466 /////////////////

Generated on Mon Dec 5 18:22:01 2005 for CDB by doxygen1.3-rc3