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

CdbBdbSUtils.cc

Go to the documentation of this file.
00001 // File and Version Information:
00002 //      $Id: CdbBdbSUtils.cc,v 1.10 2004/08/06 05:54:25 bartoldu Exp $
00003 
00004 /// Implementation file for the CdbBdbSUtils lass
00005 /**
00006   * @see CdbBdbSCell
00007   */
00008 
00009 #include "BaBar/BaBar.hh"
00010 
00011 #include "CdbBdbShared/CdbBdbSUtils.hh"
00012 
00013 #include "BdbApplication/BdbDomain.hh"
00014 #include "BdbApplication/BdbCondFSNamesStr.hh"
00015 
00016 #include "BdbAccess/BdbDbAccessMgr.hh"
00017 #include "BdbAccess/BdbContAccessMgr.hh"
00018 #include "BdbAccess/BdbAccessErrors.hh"
00019 
00020 #include "BdbDistribution/BdbStandardDbIdMgr.hh"
00021 #include "BdbDistribution/BdbDbIdAlloc.hh"
00022 #include "BdbDistribution/BdbFdName.hh"
00023 
00024 #include "BdbCond/BdbConditions.hh"
00025 
00026 #include <stdlib.h>
00027 #include <string.h>
00028 #include <stdio.h>
00029 #include <assert.h>
00030 using std::cout;
00031 using std::endl;
00032 
00033 namespace {
00034 
00035   /// Build the database name from specified components
00036   /**
00037     */
00038     std::string buildDatabaseName( bool               isPartitionableFlag,
00039                                    d_UShort           thePartitionId,
00040                                    d_UShort           theClusterId,
00041                                    d_UShort           theIncrementNumber,
00042                                    const std::string& theDbIdRange )
00043     {
00044         std::string databaseName( "con_cdb" );
00045 
00046         if( isPartitionableFlag ) {
00047 
00048             char numberStr[12];
00049             sprintf( numberStr, "%u", thePartitionId );
00050 
00051             databaseName = databaseName +
00052                            std::string( "_p" ) +
00053                            std::string( numberStr );
00054         }
00055         {
00056             char numberStr[12];
00057             sprintf( numberStr, "%u", theClusterId );
00058 
00059             databaseName = databaseName +
00060                            std::string( "_c" ) +
00061                            std::string( numberStr );
00062         }
00063         {
00064             char numberStr[12];
00065             sprintf( numberStr, "%u", theIncrementNumber );
00066 
00067             databaseName = databaseName +
00068                            std::string( "_i" ) +
00069                            std::string( numberStr );
00070         }
00071         databaseName = databaseName +
00072                        std::string( "_" ) +
00073                        theDbIdRange;
00074 
00075         return databaseName;
00076     }
00077 };
00078 
00079 std::string
00080 CdbBdbSUtils::_localDbIdRange = "";
00081 
00082 CdbStatus
00083 CdbBdbSUtils::getLocalDbIdRange( std::string& theName )
00084 {
00085   // WARNING: The method is using the cached value of the range, which might not
00086   //          work if there is more than one Objectivity context for the Condition/DB.
00087 
00088     CdbStatus result = CdbStatus::NotFound;
00089     do {
00090 
00091       // Still need to load the cache?
00092 
00093         if ( _localDbIdRange == "" ) {
00094 
00095           // The following operations are executed withing a separate context
00096           // in order not to leave locks 
00097 
00098             BdbStatus status;
00099 
00100             status = BdbApplicationOrDomain::activeInstance( )->startNestedRead( );
00101             if( status != BdbcSuccess ) {
00102                 assert( 0 );
00103                 result = CdbStatus::Error;
00104                 break;
00105             }
00106             {
00107                 BdbHandle(BdbFdName) theFdNameH;
00108                 theFdNameH = BdbFdName::localInstance( BdbApplicationOrDomain::activeInstance()->fd( ));
00109 
00110                 const char* rangeName = BdbStandardDbIdMgr::findKey( theFdNameH, "con" );
00111                 if ( 0 != rangeName ) _localDbIdRange = rangeName;
00112             }
00113             status = BdbApplicationOrDomain::activeInstance( )->commitNested( );
00114             if( status != BdbcSuccess ) {
00115                 assert( 0 );
00116                 result = CdbStatus::Error;
00117                 break;
00118             }
00119         }
00120         if ( _localDbIdRange != "" ) {
00121             theName = _localDbIdRange;
00122             result = CdbStatus::Success;
00123         }
00124 
00125     } while( false );
00126 
00127     return result;
00128 }
00129 
00130 CdbStatus
00131 CdbBdbSUtils::verifyDbIdRange( const char* theName )
00132 {
00133     CdbStatus result = CdbStatus::NotFound;
00134     do {
00135 
00136         if( 0 != theName ) {
00137 
00138           // The following operations are executed withing a separate context
00139           // in order not to leave locks 
00140 
00141             BdbStatus status;
00142 
00143             status = BdbApplicationOrDomain::activeInstance( )->startNestedRead( );
00144             if( status != BdbcSuccess ) {
00145                 assert( 0 );
00146                 result = CdbStatus::Error;
00147                 break;
00148             }
00149             {
00150                 BdbHandle(BdbDbIdAlloc) allocH;
00151                 allocH = BdbDbIdAlloc::localInstance( BdbApplicationOrDomain::activeInstance()->fd( ));
00152                 if( ! BdbIsNull(allocH)) {
00153 
00154                     char** aList = 0;
00155                     size_t aNum  = 0;
00156                     
00157                     aNum = allocH->keys( aList );
00158                     if(( 0 != aList ) && ( 0 != aNum )) {
00159                         for( size_t i = 0; i < aNum; ++i ) {
00160                             if( 0 == strcmp( theName, aList[i] )) result = CdbStatus::Success;
00161                             delete [] aList[i]; // Don't need this anymore
00162                         }
00163                         delete [] aList;    // Don't need the list anymore
00164                     }
00165                 }
00166             }
00167             status = BdbApplicationOrDomain::activeInstance( )->commitNested( );
00168             if( status != BdbcSuccess ) {
00169                 assert( 0 );
00170                 result = CdbStatus::Error;
00171                 break;
00172             }
00173         }
00174 
00175     } while( false );
00176 
00177     return result;
00178 }
00179 
00180 /*
00181  * BEGIN: This is an obsolete and inefficient implementation of these methods. It has been
00182  *        replaced with the one using a transient cache of databases and container handles.
00183  *
00184 
00185 CdbStatus
00186 CdbBdbSUtils::findContainer( BdbHandle(BdbContObj)& theContH,
00187                              const char*            theDatabaseName,
00188                              const char*            theContainerName,
00189                              const BdbMode          theOpenMode )
00190 {
00191     const char* errorStr = "CdbBdbSUtils::findContainer() - ERROR.";
00192 
00193     CdbStatus result = CdbStatus::NotFound;
00194     do {
00195 
00196       // Find the database
00197 
00198         BdbHandle(BdbDBObj) dH;
00199 
00200         if( CdbStatus::Success != findDatabase( dH,
00201                                                 theDatabaseName,
00202                                                 BdbcRead )) {
00203             break;
00204         }
00205 
00206       // Find the container.
00207 
00208         BdbStatus status;
00209 
00210         BdbHandle(BdbContObj) cH;
00211 
00212         if( d_True != cH.exist( dH,
00213                                 theContainerName,
00214                                 BdbcNoOpen )) {
00215             break;
00216         }
00217         status = cH.open( dH,
00218                           theContainerName,
00219                           theOpenMode );
00220         if(( BdbcSuccess != status ) || BdbIsNull(cH)) {
00221             cout << errorStr << endl
00222                  << "    Failed to open the container: \"" << theContainerName << "\"" << endl
00223                  << "    at the database:              \"" << theDatabaseName << "\"" << endl;
00224             result = CdbStatus::Error;
00225             break;
00226         }
00227 
00228       // Done
00229 
00230         theContH = cH;
00231 
00232         result = CdbStatus::Success;
00233 
00234     } while( false );
00235 
00236     return result;
00237 }
00238 
00239 CdbStatus
00240 CdbBdbSUtils::findDatabase( BdbHandle(BdbDBObj)& theDatabaseH,
00241                             const char*          theDatabaseName,
00242                             const BdbMode        theOpenMode )
00243 {
00244     const char* errorStr = "CdbBdbSUtils::findDatabase() - ERROR.";
00245 
00246     CdbStatus result = CdbStatus::NotFound;
00247     do {
00248 
00249         BdbStatus status;
00250 
00251       // Find the database
00252 
00253         BdbHandle(BdbDBObj) dH;
00254 
00255         if( d_True != dH.exist( BdbApplicationOrDomain::activeInstance()->fd( ),
00256                                 theDatabaseName,
00257                                 BdbcNoOpen )) {
00258             break;
00259         }
00260         status = dH.open( BdbApplicationOrDomain::activeInstance()->fd( ),
00261                           theDatabaseName,
00262                           theOpenMode );
00263         if(( BdbcSuccess != status ) || BdbIsNull(dH)) {
00264             cout << errorStr << endl
00265                  << "    Failed to open the database: \"" << theDatabaseName << "\"" << endl;
00266             result = CdbStatus::Error;
00267             break;
00268         }
00269 
00270       // Done
00271 
00272         theDatabaseH = dH;
00273 
00274         result = CdbStatus::Success;
00275 
00276     } while( false );
00277 
00278     return result;
00279 }
00280 
00281  *
00282  * END: See the efficient implementations of these methods below.
00283  */
00284 
00285 
00286 CdbStatus
00287 CdbBdbSUtils::findContainer( BdbHandle(BdbContObj)& theContH,
00288                              const char*            theDatabaseName,
00289                              const char*            theContainerName,
00290                              const BdbMode          theOpenMode )
00291 {
00292     const char* errorStr = "CdbBdbSUtils::findContainer() - ERROR.";
00293 
00294     CdbStatus result = CdbStatus::Error;
00295     do {
00296 
00297       // Find the container handle through the transient access manager. This manager
00298       // also manages the transient cach of handles (one per ooContext & ooTransaction)
00299       // to avoid FDB catalog operations if possible.
00300 
00301         d_Long    lockWait = -2;        // default value of this parameter
00302         d_Boolean useCache = d_True;    // default value of this parameter
00303         d_Boolean quiet    = d_True;    // ovverride the default value of this parameter
00304 
00305         BdbContAccessMgr      aMgr;
00306         BdbHandle(BdbContObj) cH;
00307         BdbStatus             status = aMgr.openDbAndCont( theDatabaseName,
00308                                                            cH,
00309                                                            theContainerName,
00310                                                            theOpenMode,
00311                                                            lockWait,
00312                                                            useCache,
00313                                                            quiet );
00314 
00315         if(( BdbAccessErrDbNotExist.errorN == status ) || ( BdbAccessErrContNotFound.errorN == status )) {
00316 
00317           // This might be a normal situation from the point of view of
00318           // a client of the current method.
00319 
00320             return CdbStatus::NotFound;
00321 
00322         } else if(( BdbcSuccess != status ) || BdbIsNull(cH)) {
00323             cout << errorStr << endl
00324                  << "    Failed to open the container: \"" << theContainerName << "\"" << endl
00325                  << "    at the database:              \"" << theDatabaseName << "\"" << endl;
00326             break;
00327         }
00328 
00329       // Done
00330 
00331         theContH = cH;
00332 
00333         result = CdbStatus::Success;
00334 
00335     } while( false );
00336 
00337     return result;
00338 }
00339 
00340 CdbStatus
00341 CdbBdbSUtils::findDatabase( BdbHandle(BdbDBObj)& theDatabaseH,
00342                             const char*          theDatabaseName,
00343                             const BdbMode        theOpenMode )
00344 {
00345     const char* errorStr = "CdbBdbSUtils::findDatabase() - ERROR.";
00346 
00347     CdbStatus result = CdbStatus::Error;
00348     do {
00349 
00350       // Find the database handle through the transient access manager. This manager
00351       // also manages the transient cach of handles (one per ooContext & ooTransaction)
00352       // to avoid FDB catalog operations if possible.
00353 
00354         BdbDbAccessMgr      aMgr;
00355         BdbHandle(BdbDBObj) dH;
00356         BdbStatus           status = aMgr.openDb( dH,
00357                                                   theDatabaseName,
00358                                                   theOpenMode );
00359 
00360         if( BdbAccessErrDbNotExist.errorN == status ) {
00361 
00362           // This might be a normal situation from the point of view of
00363           // a client of the current method.
00364 
00365             return CdbStatus::NotFound;
00366 
00367         } else if(( BdbcSuccess != status ) || BdbIsNull(dH)) {
00368             cout << errorStr << endl
00369                  << "    Failed to open the database: \"" << theDatabaseName << "\"" << endl;
00370             break;
00371         }
00372 
00373       // Done
00374 
00375         theDatabaseH = dH;
00376 
00377         result = CdbStatus::Success;
00378 
00379     } while( false );
00380 
00381     return result;
00382 }
00383 
00384 CdbStatus
00385 CdbBdbSUtils::findMetaData( BdbRef(CdbBdbSMetaDataP)& theRef,
00386                             const d_UShort            theConditionId,
00387                             bool                      isPartitionableFlag,
00388                             d_UShort                  thePartitionId,
00389                             d_UShort                  theClusterId,
00390                             d_UShort                  theIncrementNumber,
00391                             const std::string&        theDbIdRange )
00392 {
00393     const char* errorStr = "CdbBdbSUtils::findMetaData() -- ERROR";
00394 
00395     CdbStatus result = CdbStatus::Error;
00396     do {
00397 
00398       // Build the database name
00399 
00400         std::string databaseName = buildDatabaseName( isPartitionableFlag,
00401                                                       thePartitionId,
00402                                                       theClusterId,
00403                                                       theIncrementNumber,
00404                                                       theDbIdRange );
00405 
00406       // Build the container name
00407 
00408         char cIdStr[12];
00409         sprintf( cIdStr, "%u", theConditionId );
00410 
00411         std::string mdContainerName = std::string( "MetaData." ) +
00412                                       std::string( cIdStr );
00413 
00414       // Try to locate the container and the MetaData object in this
00415       // container.
00416 
00417         BdbHandle(BdbContObj) mdContH;
00418         if( CdbStatus::Success != CdbBdbSUtils::findContainer( mdContH,
00419                                                                databaseName.c_str( ),
00420                                                                mdContainerName.c_str( ))) {
00421             cout << errorStr << endl
00422                  << "    Failed to locate/open a persistent container with meta-data." << endl
00423                  << "    The database may not be properly initialized/loaded." << endl
00424                  << "        CONTAINER NAME:     \"" << mdContainerName.c_str( ) << "\"" << endl
00425                  << "        DATABASE FILE NAME: \"" << databaseName.c_str( ) << "\"" << endl;
00426             break;
00427         }
00428 
00429         BdbHandle(CdbBdbSMetaDataP) mdH;
00430         if( BdbcSuccess != mdH.lookupObj( mdContH,
00431                                           "MetaData" )) {
00432             cout << errorStr << endl
00433                  << "    Failed to locate the \"MetaData\" registry object in the container." << endl
00434                  << "    The database may not be properly initialized/loaded." << endl
00435                  << "        CONTAINER NAME:     \"" << mdContainerName.c_str( ) << "\"" << endl
00436                  << "        DATABASE FILE NAME: \"" << databaseName.c_str( ) << "\"" << endl;
00437             break;
00438         }
00439         assert( mdH->ooIsKindOf( ooTypeN( CdbBdbSMetaDataP )));
00440 
00441       // Done.
00442 
00443         theRef = mdH;
00444 
00445         result = CdbStatus::Success;
00446 
00447     } while( false );
00448 
00449     return result;
00450 }
00451 
00452 CdbStatus
00453 CdbBdbSUtils::databaseSize( d_ULong&           theNumPages,
00454                             d_ULong&           thePageSize,
00455                             bool               isPartitionableFlag,
00456                             d_UShort           thePartitionId,
00457                             d_UShort           theClusterId,
00458                             d_UShort           theIncrementNumber,
00459                             const std::string& theDbIdRange )
00460 {
00461     const char* errorStr = "CdbBdbSUtils::databaseSize(meta-data & objects) -- ERROR";
00462 
00463     CdbStatus result = CdbStatus::Error;
00464     do {
00465 
00466       // Build the database name
00467 
00468         std::string databaseName = buildDatabaseName( isPartitionableFlag,
00469                                                       thePartitionId,
00470                                                       theClusterId,
00471                                                       theIncrementNumber,
00472                                                       theDbIdRange );
00473 
00474       // Try to measure the database size
00475 
00476         if( CdbStatus::Success != measureDatabaseSize( theNumPages,
00477                                                        thePageSize,
00478                                                        databaseName.c_str( ))) {
00479             cout << errorStr << endl
00480                  << "    Failed to measure the size of a persistent database with meta-data and objects." << endl
00481                  << "    The database may not be properly initialized/loaded." << endl
00482                  << "        DATABASE FILE NAME: \"" << databaseName.c_str( ) << "\"" << endl;
00483             break;
00484         }
00485 
00486       // Done.
00487 
00488         result = CdbStatus::Success;
00489 
00490     } while( false );
00491 
00492     return result;
00493 }
00494 
00495 CdbStatus
00496 CdbBdbSUtils::databaseSize( d_ULong& theNumPages,
00497                             d_ULong& thePageSize )
00498 {
00499     const char* errorStr = "CdbBdbSUtils::databaseSize(master) -- ERROR";
00500 
00501     CdbStatus result = CdbStatus::Error;
00502     do {
00503 
00504       // Build the database name
00505 
00506         std::string databaseName = "con_cdb_database";
00507 
00508       // Try to measure the database size
00509 
00510         if( CdbStatus::Success != measureDatabaseSize( theNumPages,
00511                                                        thePageSize,
00512                                                        databaseName.c_str( ))) {
00513             cout << errorStr << endl
00514                  << "    Failed to measure the size of the MASTER registry database." << endl
00515                  << "    The database may not be properly initialized/loaded." << endl
00516                  << "        DATABASE FILE NAME: \"" << databaseName.c_str( ) << "\"" << endl;
00517             break;
00518         }
00519 
00520       // Done.
00521 
00522         result = CdbStatus::Success;
00523 
00524     } while( false );
00525 
00526     return result;
00527 }
00528 
00529 CdbStatus
00530 CdbBdbSUtils::databaseSize( d_ULong&           theNumPages,
00531                             d_ULong&           thePageSize,
00532                             const std::string& theDbIdRange )
00533 {
00534     const char* errorStr = "CdbBdbSUtils::databaseSize(local) -- ERROR";
00535 
00536     CdbStatus result = CdbStatus::Error;
00537     do {
00538 
00539       // Build the database name
00540 
00541         std::string databaseName = "con_cdb_database_" + theDbIdRange;
00542 
00543       // Try to measure the database size. Don't warry about "NotFound" status - just
00544       // propagate it up to the caller because some local databases images may just not exist
00545       // either because they've not been imported yet or because the current database
00546       // is the MASTER one.
00547 
00548         result = measureDatabaseSize( theNumPages,
00549                                       thePageSize,
00550                                       databaseName.c_str( ));
00551         if( CdbStatus::Success == result ) {
00552             ;
00553         } else if( CdbStatus::NotFound == result ) {
00554             ;
00555         } else {
00556             cout << errorStr << endl
00557                  << "    Failed to measure the size of the local registry database." << endl
00558                  << "    The database may not be properly initialized/loaded." << endl
00559                  << "        DATABASE FILE NAME: \"" << databaseName.c_str( ) << "\"" << endl;
00560         }
00561 
00562     } while( false );
00563 
00564     return result;
00565 }
00566 
00567 CdbStatus
00568 CdbBdbSUtils::measureDatabaseSize( d_ULong&           theNumPages,
00569                                    d_ULong&           thePageSize,
00570                                    const std::string& theDatabaseName )
00571 {
00572     const char* errorStr = "CdbBdbSUtils::measureDatabaseSize() -- ERROR";
00573 
00574     CdbStatus result = CdbStatus::Error;
00575     do {
00576 
00577       // Find the database
00578 
00579         BdbHandle(BdbDBObj) dH;
00580 
00581         CdbStatus findDatabaseStatus = findDatabase( dH,
00582                                                      theDatabaseName.c_str( ),
00583                                                      BdbcRead );
00584         if( CdbStatus::Success != findDatabaseStatus ) {
00585             result = findDatabaseStatus;
00586             break;
00587         }
00588 
00589       // Count the number of pages in all containers
00590       // including the default one.
00591 
00592         d_ULong total = 0;
00593         {
00594           // Set up an iterator of contaniers to iterate over this database
00595           // 
00596           // NOTE: This method will not affect the internal state of this object.
00597           //       This is why we open the database here explicitly.
00598  
00599             BdbItr(BdbContObj) itr;
00600             dH.contains( itr );
00601   
00602             bool failed = false;
00603 
00604             while ( itr.next( )) {
00605 
00606                 d_ULong num = itr.nPage( );
00607                 if( 0 == num ) {
00608                     cout << errorStr << endl
00609                          << "    Failed to determine the size of a persistent container." << endl
00610                          << "    The container is not found or could not be open." << endl
00611                          << "        CONTAINER NAME:     \"" << itr.name( ) << "\"" << endl
00612                          << "        DATABASE FILE NAME: \"" << theDatabaseName.c_str( ) << "\"" << endl;
00613                     failed = true;
00614                     break;
00615                 }
00616                 total += num;
00617             }
00618             if( failed ) break;
00619         }
00620         theNumPages = total;
00621 
00622       // Get the page size.
00623 
00624         thePageSize = BdbApplicationOrDomain::activeInstance()->fd( ).pageSize( );
00625 
00626       // Done.
00627 
00628         result = CdbStatus::Success;
00629 
00630     } while( false );
00631 
00632     return result;
00633 }
00634 
00635 CdbStatus
00636 CdbBdbSUtils::setPlacementStrategy( bool        useDefaultStrategyFlag,
00637                                     const char* theExplicitPathName )
00638 {
00639     const char* errorStr = "CdbBdbSUtils::setPlacementStrategy() -- ERROR";
00640 
00641     CdbStatus result = CdbStatus::Error;
00642     do {
00643 
00644       // Get the value of 'FDB_LOCAL_NAME' used when creating
00645       // the current federation
00646 
00647         std::string localDbIdRange;
00648         if( CdbStatus::Success != getLocalDbIdRange( localDbIdRange )) {
00649             cout << errorStr << endl
00650                  << "    Failed to obtain the local DBID range name of the current federation." << endl;
00651             break;
00652         }
00653 
00654       // Check if the old path was required by a user
00655 
00656         std::string customClusteringPath;
00657         {
00658             if( useDefaultStrategyFlag ) customClusteringPath = "conditions/" + localDbIdRange ;
00659             else                         customClusteringPath = theExplicitPathName;
00660         }
00661 
00662       // Aplly whatever path is required
00663 
00664         BdbCondFSNamesStr* strategy = new BdbCondFSNamesStr;
00665         strategy->setCustomRelativePath( customClusteringPath.c_str( ));
00666 
00667         BdbConditions::instance( )->setStrategyObj( strategy );
00668 
00669       // Done.
00670 
00671         result = CdbStatus::Success;
00672 
00673     } while( false );
00674 
00675     return result;
00676 }
00677 
00678 /////////////////
00679 // End Of File //
00680 /////////////////

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