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

CdbRooRoCdb.cc

Go to the documentation of this file.
00001 // File and Version Information:
00002 //      $Id: CdbRooRoCdb.cc,v 1.5 2005/11/11 01:41:26 gapon Exp $
00003 
00004 /// The implementation of the CdbRooRoCdb singleton.
00005 /**
00006   * @see CdbRooRoCdb
00007   */
00008 
00009 #include "BaBar/BaBar.hh"
00010 
00011 #include "CdbRooReadonly/CdbRooRoCdb.hh"
00012 
00013 #include "CdbBase/CdbView.hh"
00014 #include "CdbBase/CdbDatabase.hh"
00015 #include "CdbBase/CdbEnvironment.hh"
00016 #include "CdbBase/CdbDebugStream.hh"
00017 #include "CdbBase/CdbAnyTypeDict.hh"
00018 
00019 #include "CdbRooReadonly/CdbRooReadonly.hh"
00020 #include "CdbRooReadonly/CdbRooRoFileUtils.hh"
00021 #include "CdbRooReadonly/CdbRooRoDatabase.hh"
00022 #include "CdbRooReadonly/CdbRooRoDatabaseItr.hh"
00023 #include "CdbRooReadonly/CdbRooRoBootRecordR.hh"
00024 
00025 #include "ErrLogger/ErrLog.hh"
00026 
00027 #include "BbrStdUtils/Tokenize.hh"
00028 #include "BbrStdUtils/String.hh"
00029 using namespace babar::String;
00030 
00031 #include <stdlib.h>     // getenv()
00032 #include <stdio.h>      // sscanf()
00033 
00034 #include <string.h>
00035 #include <assert.h>
00036 
00037 #include <iostream>
00038 #include <fstream>
00039 #include <map>
00040 
00041 using std::ifstream;
00042 using std::cout;
00043 using std::cerr;
00044 using std::endl;
00045 
00046 namespace {
00047 
00048   /// Dummy transaction manager
00049   /**
00050     * DESIGN NOTE:
00051     *
00052     *   At the moment, we don't have a concept of the "transaction" in the current
00053     *   implementation of the CDB API, However we must provide this manager to comply
00054     *   with specifications of the technology-neutral CDB API.
00055     */
00056     class CdbRooRoDummyTransaction : public CdbTransactionBase {
00057 
00058     public:
00059 
00060         CdbRooRoDummyTransaction( ) : CdbTransactionBase( ) { }
00061 
00062         virtual ~CdbRooRoDummyTransaction( ) { }
00063 
00064         virtual void commitAndHold( ) { }
00065     };
00066 }
00067 
00068 ////////////////////////////////
00069 // CdbRooRoCdb implementation //
00070 ////////////////////////////////
00071 
00072 CdbRooRoCdb::CdbRooRoCdb( ) :
00073     Cdb( ),
00074     _isInitialized      (false),                    // For the sake of deffered initialization
00075     _defaultDatabaseName("<default>"),
00076     _defaultViewName    ("<local>::<recent>")
00077 {
00078     CDB_DEBUG_STREAM
00079         << "Condition/DB API instantiated for"
00080         << " TECHNOLOGY=\""     << CdbRooReadonly::technology( )     << "\""
00081         << " IMPLEMENTATION=\"" << CdbRooReadonly::implementation( ) << "\""
00082         << endl;
00083 
00084   // Try to register itself in the API registry.
00085   //
00086   // NOTE: If the registration will fail then we may probably encounter a fatal
00087   //       unrecoverable problem with implementations of CDB API. One of the possible
00088   //       reasons of the falure would be if another implementation of the API has already
00089   //       registered itself in the dictionary under the same names.
00090 
00091     CdbPtr myPtr = this;
00092 
00093     CdbStatus status = set( myPtr );
00094     assert( CdbStatus::Success == status );
00095 }
00096 
00097 CdbRooRoCdb::~CdbRooRoCdb( )
00098 { }
00099 
00100 const char*
00101 CdbRooRoCdb::technologyName( ) const
00102 {
00103     return CdbRooReadonly::technology( );
00104 }
00105 
00106 const char*
00107 CdbRooRoCdb::implementationName( ) const
00108 {
00109     return CdbRooReadonly::implementation( );
00110 }
00111 
00112 void
00113 CdbRooRoCdb::initialize( )
00114 {
00115     if( !_isInitialized ) {
00116 
00117       // IMPORTANT: This flag has to be set up first before doing any actual
00118       //            operations with the persistent store since we may have
00119       //            indirect recursion when setting default (the defaults setting
00120       //            algorithm may request initialization).
00121 
00122         _isInitialized = true;
00123 
00124       // Read the default "boot" file to configure the context of this CDB API implementation
00125 
00126         CdbStatus result = readBootFile( );
00127         if( CdbStatus::Success == result ) {
00128 
00129           // Okay, we have a consistent context
00130 
00131             ;
00132 
00133         } else if( CdbStatus::NotFound == result ) {
00134 
00135           // We have no context specific to the current implementation of the CDB API
00136 
00137             ;
00138 
00139         } else {
00140 
00141           // We had a failure when attempting to translate the context
00142 
00143             cerr << "CdbRooRoCdb::initialize() -- WARNING." << endl
00144                  << "    Failed to read and/or translate the contents of the boot file. See details above." << endl;
00145         }
00146 
00147       // Check the environment and see if there are optional parameters to rune-up this
00148       // implementation of the CDB API
00149 
00150         {
00151             const char* var = "CDB_ROO_MAX_TTREES";
00152             const char* ptr = getenv( var );
00153             if( ptr ) {
00154                 unsigned num = 0;
00155                 if( 1 == sscanf( ptr, "%u", &num )) {
00156                     const char* key = "Roo/Readonly/max_num_ttrees";
00157                     if( CdbStatus::Success != CdbEnvironment::extra( ).replace( key, num )) {
00158                         ErrMsg(fatal) << "CdbRooRoCdb::initialize( ) -- FATAL ERROR\n"
00159                                       << "    Failed to set the parameter '" << key << "' = " << num << " in CdbEnvironment.\n"
00160                                       << "    This is an unrecoverable error caused by an inconsistency in the CDB API Logic.\n"
00161                                       << "    Please, report the problem to CDB API developers." << endmsg;
00162                     }
00163                 }
00164                 CDB_DEBUG_STREAM
00165                     << "Condition/DB API for"
00166                     << " TECHNOLOGY=\""     << CdbRooReadonly::technology( )     << "\""
00167                     << " IMPLEMENTATION=\"" << CdbRooReadonly::implementation( ) << "\""
00168                     << " translated environment variable: " << var << " = " << num
00169                     << endl;
00170             }
00171         }
00172     }
00173 }
00174 
00175 bool
00176 CdbRooRoCdb::isInitialized( )
00177 {
00178     return _isInitialized;
00179 }
00180 
00181 CdbStatus
00182 CdbRooRoCdb::getDefaultDatabase( std::string& theDatabaseName )
00183 {
00184     assert( isInitialized( ));
00185 
00186     theDatabaseName = _defaultDatabaseName;
00187 
00188     return CdbStatus::Success;
00189 }
00190 
00191 CdbStatus
00192 CdbRooRoCdb::getDefaultView( std::string& theViewName,
00193                              const char*  theDatabaseName )
00194 {
00195     assert( isInitialized( ));
00196 
00197     if( 0 == theDatabaseName ) return CdbStatus::IllegalParameters;
00198 
00199   // We only allow the following database names:
00200   //
00201   //   - "<default>"
00202   //   - the actual BOOT file stored in the current object
00203 
00204     if( 0 != strcmp( theDatabaseName, "<default>" )) {
00205         if( theDatabaseName != _defaultDatabaseName )
00206             return CdbStatus::NotFound;
00207     }
00208 
00209   // Return the current default.
00210 
00211     theViewName = _defaultViewName;
00212 
00213     return CdbStatus::Success; 
00214 }
00215 
00216 CdbStatus
00217 CdbRooRoCdb::setDefaultDatabase( const char* theDatabaseName )
00218 {
00219     assert( isInitialized( ));
00220 
00221     if( 0 == theDatabaseName ) return CdbStatus::IllegalParameters;
00222 
00223   // First let's see if the passed name corresponds to one of the following
00224   // options:
00225   //
00226   //   - "<default>"
00227   //   - the actual BOOT file which exists and has the correct format
00228 
00229     if( 0 == strcmp( theDatabaseName, "<default>" )) return CdbStatus::Success;
00230     if( theDatabaseName == _defaultDatabaseName )    return CdbStatus::Success;
00231 
00232   // If it's something new then try to see what's in the one passed by the parameter.
00233 
00234    return readBootFile( theDatabaseName );
00235 }
00236 
00237 CdbStatus
00238 CdbRooRoCdb::setDefaultView( const char* theViewName,
00239                              const char* theDatabaseName )
00240 {
00241     assert( isInitialized( ));
00242 
00243     if( 0 == theViewName     ) return CdbStatus::IllegalParameters;
00244     if( 0 == theDatabaseName ) return CdbStatus::IllegalParameters;
00245 
00246   // This method will checks for the correctness of the database and view names.
00247   //
00248   // IMPLEMENTATION NOTE: It will NOT check if specified view is present in the database.
00249   //                      The reason is that certain operations with CDB may be permitted
00250   //                      without having finally established database.
00251 
00252   // We only allow the following database names:
00253   //
00254   //   - "<default>"
00255   //   - the actual BOOT file stored in the current object
00256 
00257     if( 0 != strcmp( theDatabaseName, "<default>" )) {
00258         if( theDatabaseName != _defaultDatabaseName )
00259             return CdbStatus::NotFound;
00260     }
00261 
00262   // Try open the database and the view to check if they both exist.
00263   /**
00264    ** IMPLEMENTATION NOTE: The following code is disabled to allow operations with
00265    **                      incomplete CDB.
00266    **
00267 
00268     CdbDatabasePtr databasePtr;
00269     if( CdbStatus::Success != findDatabase( databasePtr )) return CdbStatus::Error;
00270 
00271     CdbViewPtr viewPtr;
00272     if( CdbStatus::Success != databasePtr->findView( viewPtr, theViewName  )) return CdbStatus::Error;
00273 
00274    **
00275    **/
00276 
00277   // Done
00278 
00279     _defaultViewName = theViewName;
00280 
00281     return CdbStatus::Success; 
00282 }
00283 
00284 CdbStatus
00285 CdbRooRoCdb::findDatabase( CdbDatabasePtr& thePtr,
00286                            const char*     theName )
00287 {
00288     assert( isInitialized( ));
00289 
00290     CdbStatus result = CdbStatus::Error;
00291 
00292     thePtr = 0;
00293 
00294     do {
00295 
00296       // Verify and correct parameters if 0 pointer is passed to indicate
00297       // that default database is needed. The "<default>" string is also allowed
00298       // since the current implementation maps it onto the boot file name.
00299 
00300         std::string defaultDatabaseName;
00301         if( CdbStatus::Success != getDefaultDatabase( defaultDatabaseName )) break;
00302 
00303         std::string databaseName = defaultDatabaseName;
00304         if( 0 != theName ) {
00305             if( 0 == strcmp( "<default>", theName )) {
00306 
00307               // This is a special keyword to be mapped onto whatever default
00308               // bootfile name we have.
00309 
00310                 ;
00311 
00312             } else {
00313                 databaseName = theName;
00314             }
00315         }
00316 
00317         if( databaseName != defaultDatabaseName ) {
00318 
00319             cout << "CdbRooRoCdb::findDatabase( ) -- ERROR" << endl
00320                  << "    No such database in this implementation:  \"" << databaseName        << "\"" << endl
00321                  << "    The only name allowed is the default one: \"" << defaultDatabaseName << "\"" << endl;
00322 
00323             break;
00324         }
00325 
00326       // NOTE: - the above corrected parameters object is used.
00327       //       - a smart pointer onto itself is found through the registry.
00328 
00329         CdbPtr selfPtr;
00330         if( CdbStatus::Success != get( selfPtr,
00331                                        technologyName( ),
00332                                        implementationName( ))) {
00333 
00334             cout << "CdbRooRoCdb::findDatabase( ) -- FATAL ERROR" << endl
00335                  << "    Failed to recover its own instance of the CDB API." << endl
00336                  << "        TECHNOLOGY     : \"" << technologyName( ) << "\"" << endl
00337                  << "        IMPLEMENTATION : \"" << implementationName( ) << "\"" << endl;
00338 
00339             assert( 0 );
00340 
00341             break;
00342         }
00343         thePtr = new CdbRooRoDatabase( selfPtr,
00344                                        databaseName.c_str( ));
00345         result = CdbStatus::Success;
00346 
00347     } while( false );
00348 
00349     return result;
00350 }
00351 
00352 CdbStatus
00353 CdbRooRoCdb::databaseIterator( CdbDatabaseItr& theItr )
00354 {
00355     assert( isInitialized( ));
00356 
00357   // Note, that we find its own smart pointer through the Registry
00358 
00359   // ATTENTION: This is not a memory leak - the created object
00360   //            will be destroyed by the iterator.
00361 
00362     CdbPtr selfPtr;
00363     if( CdbStatus::Success != get( selfPtr,
00364                                    technologyName( ),
00365                                    implementationName( ))) {
00366 
00367         cout << "CdbRooRoCdb::databaseIterator( ) -- FATAL ERROR" << endl
00368              << "    Failed to recover its own instance of the CDB API." << endl
00369              << "        TECHNOLOGY     : \"" << technologyName( ) << "\"" << endl
00370              << "        IMPLEMENTATION : \"" << implementationName( ) << "\"" << endl;
00371 
00372         assert( 0 );
00373 
00374         return CdbStatus::Error;
00375     }
00376     theItr = CdbDatabaseItr( new CdbRooRoDatabaseItr( selfPtr ));
00377 
00378     return CdbStatus::Success;
00379 }
00380 
00381 CdbTransactionBase*
00382 CdbRooRoCdb::transaction( CdbTransaction::Mode theMode ) const
00383 {
00384     return new CdbRooRoDummyTransaction( );
00385 }
00386 
00387 CdbStatus
00388 CdbRooRoCdb::readBootFile( const char* theBootFileName )
00389 {
00390     const char* errorStr = "CdbRooRoCdb::readBootFile() -- ERROR.";
00391 
00392   // Try to find the bootfile first. Here is how we do the check:
00393   //
00394   //   - a value explicitly passed through the current method's parameter
00395   //
00396   // or
00397   //
00398   //   - an explicitly specified location using a special environment variable
00399   //   - a default file in the local directory
00400 
00401     const char* bootFileName = theBootFileName;
00402     std::string location;
00403 
00404     if( 0 != bootFileName ) {
00405         location = "the bootfile explicitly passed to the method";
00406     } else {
00407 
00408         const char* variable = "CDB_ROO_BOOT";
00409         bootFileName = getenv( variable );
00410 
00411         if( 0 != bootFileName ) {
00412             location = "the bootfile specified in the environment variable ";
00413             location += variable;
00414         } else {
00415             bootFileName = "con_cdb_boot.root";
00416             location = "default bootfile";
00417         }
00418     }
00419     assert( bootFileName );
00420     assert( !location.empty( ));
00421 
00422     TFile bootFile( bootFileName, "read" );
00423     if( bootFile.IsZombie( )) {
00424         cerr << errorStr << endl
00425                 << "    Failed to open " << location << ".\n"
00426                 << "    File name: \"" << bootFileName << "\"" << endl;
00427         return CdbStatus::Error;
00428     }
00429 
00430   // Read the boot record
00431 
00432     CdbCPtr<CdbRooRoBootRecordR> bootRecordPtr;
00433     {
00434         CdbRooRoBootRecordR* ptr;
00435         bootFile.GetObject( CdbRooRoBootRecordR::PersistentObjectName( ), ptr );
00436         if( !ptr ) {
00437             cerr << errorStr << endl
00438                  << "    Failed to find/read the '" << CdbRooRoBootRecordR::PersistentObjectName( ) << "' object in the boot file\n"
00439                  << "    '" << bootFile.GetName( ) << "'" << endl;
00440             return CdbStatus::Error;
00441         }
00442         bootRecordPtr = ptr;
00443     }
00444 
00445   // Configure the File Utility singleton with found parameters. This information
00446   // will be used later by the rest of the CDP API implementation.
00447   //
00448   // IMPLEMENTATION NOTE:
00449   //
00450   //    These parameters are passed through the singleton rather than via the current
00451   //    API class to avoid dangerous and nasty downcasting in the rest of the API
00452   //    implementation.
00453   //
00454   // @see class CdbRooRoFileUtils
00455 
00456     CdbRooRoFileUtils::instance( ).reset( );
00457     CdbRooRoFileUtils::instance( ).setLocalOrigin( bootRecordPtr->localOriginName( ),
00458                                                    bootRecordPtr->localOriginId( ));
00459     CdbRooRoFileUtils::instance( ).setBootFileLocation( bootFileName );
00460     CdbRooRoFileUtils::instance( ).setDatabase2LocationMap( bootRecordPtr->database2LocationMap( ));
00461     CdbRooRoFileUtils::instance( ).setObject2DatabaseMap( bootRecordPtr->object2DatabaseMap( ));
00462 
00463   // Done
00464 
00465     _defaultDatabaseName = bootFileName;
00466     _defaultViewName     = bootRecordPtr->defaultViewName( );
00467 
00468     return CdbStatus::Success;
00469 }
00470 
00471 /////////////////
00472 // End Of File //
00473 /////////////////

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