00001
00002
00003
00004
00005
00006
00007
00008 #include "BaBar/BaBar.hh"
00009
00010 #include "CdbRooDatabase/CdbRooDb.hh"
00011 #include "CdbRooDatabase/CdbRooDatabase.hh"
00012 #include "CdbRooDatabase/CdbRooDbObject.hh"
00013
00014 #include "CdbSQL/CdbSQLApiDatabase.hh"
00015 #include "CdbSQL/CdbSQLApiDatabaseItr.hh"
00016 #include "CdbSQL/CdbSQLObjectId.hh"
00017 #include "CdbSQL/CdbSQLCondition.hh"
00018 #include "CdbSQL/CdbSQLPartition.hh"
00019
00020 #include "CdbMySQL/CdbMySQL.hh"
00021
00022 #include "CdbBase/CdbDatabase.hh"
00023 #include "CdbBase/CdbCondition.hh"
00024 #include "CdbBase/CdbTransactionBase.hh"
00025 #include "CdbBase/CdbDebugStream.hh"
00026
00027 #include "CdbRoo/CdbRooObjectFactory.hh"
00028
00029 #include "BbrStdUtils/Tokenize.hh"
00030 #include "BbrStdUtils/String.hh"
00031 using namespace babar::String;
00032
00033 #include <stdlib.h>
00034 #include <stdio.h>
00035
00036 #include <string.h>
00037 #include <assert.h>
00038
00039 #include <TBuffer.h>
00040 #include <TClass.h>
00041
00042 #include <iostream>
00043 using std::cerr;
00044 using std::cout;
00045 using std::endl;
00046
00047 namespace {
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 class CdbRooDatabaseTransaction : public CdbTransactionBase {
00058
00059 public:
00060
00061 CdbRooDatabaseTransaction( ) : CdbTransactionBase( ) { }
00062
00063 virtual ~CdbRooDatabaseTransaction( ) { }
00064
00065 virtual void commitAndHold( ) { }
00066 };
00067 }
00068
00069 CdbRooDb::CdbRooDb( ) :
00070 CdbSQLApi( ),
00071 _isInitialized (false),
00072 _myDatabaseImplementationPtr(0),
00073 _defaultDatabaseName ("host=localhost,user=cdb,database=cdb,port=3306"),
00074 _defaultViewName ("<local>::<recent>")
00075 {
00076 CDB_DEBUG_STREAM << "Condition/DB API instantiated for"
00077 << " TECHNOLOGY=\"" << CdbRooDatabase::technology( ) << "\""
00078 << " IMPLEMENTATION=\"" << CdbRooDatabase::implementation( ) << "\""
00079 << endl;
00080
00081
00082
00083
00084
00085
00086
00087
00088 CdbPtr myPtr = this;
00089
00090 CdbStatus status = set( myPtr );
00091 assert( CdbStatus::Success == status );
00092 }
00093
00094 CdbRooDb::~CdbRooDb( )
00095 { }
00096
00097 const char*
00098 CdbRooDb::technologyName( ) const
00099 {
00100 return CdbRooDatabase::technology( );
00101 }
00102
00103 const char*
00104 CdbRooDb::implementationName( ) const
00105 {
00106 return CdbRooDatabase::implementation( );
00107 }
00108
00109 void
00110 CdbRooDb::initialize( )
00111 {
00112 const char* fatalStr = "CdbRooDb::initialize() -- FATAL.";
00113
00114 if( !_isInitialized ) {
00115
00116
00117
00118
00119 const char* database = getenv( "CDB_DATABASE_PATH" );
00120 if( 0 != database ) _defaultDatabaseName = database;
00121
00122
00123
00124 CdbCPtr<CdbSQL> implementationObjectPtr = createImplementationObject( _defaultDatabaseName );
00125 if( implementationObjectPtr.isNull( )) {
00126 cout << fatalStr << endl
00127 << " Failed to create an internal implementation object to deal with the specified" << endl
00128 << " server because of the incorrect value of the CDB_DATABASE_PATH environment variable." << endl
00129 << " CDB_DATABASE_PATH : \"" << _defaultDatabaseName << "\"" << endl
00130 << " The valid syntax should be :" << endl
00131 << " [host=<host>[,user=<user>[,database=<database>[,port=<port>]]]]" << endl;
00132 assert( 0 );
00133 return;
00134 }
00135 _myDatabaseImplementationPtr = implementationObjectPtr;
00136
00137
00138
00139 if( CdbStatus::Success != _myDatabaseImplementationPtr->find_default_view( _defaultViewName )) {
00140 cout << fatalStr << endl
00141 << " Failed to find the default view name at the specified/default database" << endl
00142 << " CURRENT/DEFAULT DATABASE NAME : \"" << _defaultDatabaseName << "\"" << endl;
00143 assert( 0 );
00144 return;
00145 }
00146 _isInitialized = true;
00147 }
00148 }
00149
00150 bool
00151 CdbRooDb::isInitialized( )
00152 {
00153 return _isInitialized;
00154 }
00155
00156 CdbStatus
00157 CdbRooDb::getDefaultDatabase( std::string& theDatabaseName)
00158 {
00159 assert( isInitialized( ));
00160
00161 theDatabaseName = _defaultDatabaseName;
00162
00163 return CdbStatus::Success;
00164 }
00165
00166 CdbStatus
00167 CdbRooDb::getDefaultView( std::string& theViewName,
00168 const char* theDatabaseName )
00169 {
00170 assert( isInitialized( ));
00171
00172 CdbStatus result = CdbStatus::NotFound;
00173 do {
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185 if( 0 == theDatabaseName ) break;
00186
00187 if( ! (( 0 == strcmp( theDatabaseName, "<default>" )) ||
00188 ( 0 == strcmp( theDatabaseName, _defaultDatabaseName.c_str( ))))) break;
00189
00190
00191
00192 theViewName = _defaultViewName;
00193
00194
00195
00196 result = CdbStatus::Success;
00197
00198 } while( false );
00199
00200 return result;
00201 }
00202
00203 CdbStatus
00204 CdbRooDb::setDefaultDatabase( const char* theDatabaseName )
00205 {
00206 const char* errorStr = "CdbRooDb::setDefaultDatabase() -- ERROR.";
00207
00208 assert( isInitialized( ));
00209
00210 CdbStatus result = CdbStatus::NotFound;
00211 do {
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223 if( 0 == theDatabaseName ) break;
00224
00225 if( 0 == strcmp( theDatabaseName, "<default>" )) {
00226
00227
00228
00229 ;
00230
00231 } else {
00232
00233
00234
00235 std::string database = theDatabaseName;
00236 CdbCPtr<CdbSQL> implementationObjectPtr = createImplementationObject( database );
00237
00238 if( implementationObjectPtr.isNull( )) {
00239
00240 cout << errorStr << endl
00241 << " Failed to create an internal implementation object to deal with the specified" << endl
00242 << " server because of the incorrect value of the passed database name." << endl
00243 << " DATABASE : \"" << database << "\"" << endl
00244 << " The valid syntax is:" << endl
00245 << " [host=<host>[,user=<user>[,database=<database>[,port=<port>]]]]" << endl;
00246
00247 result = CdbStatus::IllegalParameters;
00248 break;
00249 }
00250 _defaultDatabaseName = database;
00251 _myDatabaseImplementationPtr = implementationObjectPtr;
00252
00253
00254
00255
00256 _defaultViewName = "<local>::<recent>";
00257 }
00258
00259
00260
00261 result = CdbStatus::Success;
00262
00263 } while( false );
00264
00265 return result;
00266 }
00267
00268 CdbStatus
00269 CdbRooDb::setDefaultView( const char* theViewName,
00270 const char* theDatabaseName )
00271 {
00272 assert( isInitialized( ));
00273
00274
00275
00276
00277
00278
00279
00280 CdbStatus result = CdbStatus::NotFound;
00281 do {
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293 if( 0 == theDatabaseName ) break;
00294
00295 if( ! (( 0 == strcmp( theDatabaseName, "<default>" )) ||
00296 ( 0 == strcmp( theDatabaseName, _defaultDatabaseName.c_str( ))))) break;
00297
00298
00299
00300 if( 0 == theViewName ) break;
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317 _defaultViewName = theViewName;
00318
00319 result = CdbStatus::Success;
00320
00321 } while( false );
00322
00323 return result;
00324 }
00325
00326 CdbStatus
00327 CdbRooDb::findDatabase( CdbDatabasePtr& thePtr,
00328 const char* theName )
00329 {
00330 assert( isInitialized( ));
00331
00332 CdbStatus result = CdbStatus::Error;
00333
00334 thePtr = 0;
00335
00336 do {
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346 std::string defaultDatabaseName;
00347 if( CdbStatus::Success != getDefaultDatabase( defaultDatabaseName )) break;
00348
00349 std::string databaseName = defaultDatabaseName;
00350 if( 0 != theName ) {
00351 if( 0 != strcmp( "<default>", theName )) {
00352
00353
00354
00355
00356 ;
00357
00358 } else {
00359 databaseName = theName;
00360 }
00361 }
00362 if( databaseName != defaultDatabaseName ) {
00363
00364 cout << "CdbRooDb::findDatabase( ) -- ERROR" << endl
00365 << " No such database in this implementation: \"" << databaseName.c_str( ) << "\"" << endl
00366 << " The only name allowed is the default one: \"" << defaultDatabaseName.c_str( ) << "\"" << endl;
00367
00368 break;
00369 }
00370
00371
00372
00373
00374 CdbPtr selfPtr;
00375 if( CdbStatus::Success != get( selfPtr,
00376 technologyName( ),
00377 implementationName( ))) {
00378 cout << "CdbRooDb::findDatabase( ) -- FATAL ERROR" << endl
00379 << " Failed to recover its own instance of the CDB API." << endl
00380 << " TECHNOLOGY : \"" << technologyName( ) << "\"" << endl
00381 << " IMPLEMENTATION : \"" << implementationName( ) << "\"" << endl;
00382
00383 assert( 0 );
00384
00385 break;
00386 }
00387 thePtr = new CdbSQLApiDatabase( selfPtr,
00388 databaseName.c_str( ),
00389 _myDatabaseImplementationPtr );
00390
00391 result = CdbStatus::Success;
00392
00393 } while( false );
00394
00395 return result;
00396 }
00397
00398 CdbStatus
00399 CdbRooDb::databaseIterator( CdbDatabaseItr& theItr )
00400 {
00401 assert( isInitialized( ));
00402
00403
00404
00405
00406
00407
00408 CdbPtr selfPtr;
00409 if( CdbStatus::Success != get( selfPtr,
00410 technologyName( ),
00411 implementationName( ))) {
00412 cout << "CdbRooDb::databaseIterator( ) -- FATAL ERROR" << endl
00413 << " Failed to recover its own instance of the CDB API." << endl
00414 << " TECHNOLOGY : \"" << technologyName( ) << "\"" << endl
00415 << " IMPLEMENTATION : \"" << implementationName( ) << "\"" << endl;
00416
00417 assert( 0 );
00418
00419 return CdbStatus::Error;
00420 }
00421 theItr = CdbDatabaseItr( new CdbSQLApiDatabaseItr( selfPtr ));
00422
00423 return CdbStatus::Success;
00424 }
00425
00426 CdbTransactionBase*
00427 CdbRooDb::transaction( CdbTransaction::Mode theMode ) const
00428 {
00429 return new CdbRooDatabaseTransaction( );
00430 }
00431
00432 CdbStatus
00433 CdbRooDb::createObject( CdbObjectPtr& theObjectPtr,
00434 const CdbConditionPtr& theParentConditionPtr,
00435 const BdbTime& theOriginalValidityBeginTime,
00436 const BdbTime& theOriginalValidityEndTime,
00437 const BdbTime& theVisibleValidityBeginTime,
00438 const BdbTime& theVisibleValidityEndTime,
00439 const BdbTime& theDurationBeginTime,
00440 const BdbTime& theDurationEndTime,
00441 const BdbTime& theInsertionTime,
00442 const CdbSQLObjectId& theObjectId )
00443 {
00444 assert( isInitialized( ));
00445
00446
00447
00448
00449 assert( !theParentConditionPtr.isNull( ));
00450
00451
00452 assert( !( theOriginalValidityBeginTime >= theOriginalValidityEndTime ));
00453
00454
00455 assert( !( theVisibleValidityBeginTime >= theVisibleValidityEndTime ));
00456
00457
00458 assert( !( theDurationBeginTime >= theDurationEndTime ));
00459
00460
00461 assert( !( BdbTime::plusInfinity == theInsertionTime ));
00462
00463
00464 assert( theObjectId.isValid( ));
00465
00466
00467
00468 theObjectPtr = new CdbRooDbObject( theParentConditionPtr,
00469 theOriginalValidityBeginTime,
00470 theOriginalValidityEndTime,
00471 theVisibleValidityBeginTime,
00472 theVisibleValidityEndTime,
00473 theDurationBeginTime,
00474 theDurationEndTime,
00475 theInsertionTime,
00476 theObjectId,
00477 _myDatabaseImplementationPtr );
00478 return CdbStatus::Success;
00479 }
00480
00481 CdbStatus
00482 CdbRooDb::storeObject( CdbObjectPtr& theObjectPtr,
00483 CdbObjectFactoryBase& theObjectFactory,
00484 CdbCPtr<CdbSQLCondition>& thePersistentConditionPtr,
00485 CdbCPtr<CdbSQLPartition>& thePersistentPartitionPtr,
00486 const CdbConditionPtr& theParentConditionPtr,
00487 const BdbTime& theOriginalValidityBeginTime,
00488 const BdbTime& theOriginalValidityEndTime )
00489 {
00490 const char* errorStr = "CdbRooDb::storeObject() -- ERROR.";
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504 if( CdbStatus::Success != theObjectFactory.create( theObjectPtr,
00505 theParentConditionPtr,
00506 BdbTime::plusInfinity,
00507 BdbTime::minusInfinity )) {
00508 cerr << errorStr << "\n"
00509 << " Failed to create a persistent object via the supplied factory." << endl;
00510 return CdbStatus::Error;
00511 }
00512 assert( theObjectPtr.isNull( ));
00513
00514
00515
00516
00517
00518 CdbRooObjectFactory* objectFactoryPtr = dynamic_cast< CdbRooObjectFactory* >( &theObjectFactory );
00519 assert( 0 != objectFactoryPtr );
00520
00521 CdbCPtr<CdbRooObjectR> persistentObjectPtr = objectFactoryPtr->persistentObjectPtr( );
00522 assert( !persistentObjectPtr.isNull( ));
00523
00524
00525
00526 BdbTime insertionTime( BdbTime::now( ));
00527
00528
00529
00530 const std::string typeName = persistentObjectPtr->ClassName( );
00531
00532 TBuffer tBuffer( TBuffer::kWrite );
00533 if( 1 != tBuffer.WriteObjectAny( persistentObjectPtr.get( ),
00534 CdbRooObjectR::Class( ))) {
00535 cerr << errorStr << "\n"
00536 << " Failed to serialzie an object of type: " << typeName << "\n"
00537 << " by a pointer onto its base class: " << CdbRooObjectR::Class( )->GetName( ) << endl;
00538 return CdbStatus::Error;
00539 }
00540
00541
00542
00543
00544
00545 CdbSQLObjectId persistentObjectId;
00546
00547 if( CdbStatus::Success != thePersistentConditionPtr->store_object( persistentObjectId,
00548 thePersistentPartitionPtr,
00549 theOriginalValidityBeginTime,
00550 theOriginalValidityEndTime,
00551 insertionTime,
00552 typeName,
00553 tBuffer.Buffer( ) + tBuffer.GetBufferDisplacement( ),
00554 tBuffer.Length( ) )) {
00555 cerr << errorStr << "\n"
00556 << " Failed to store an object of type: " << typeName << endl;
00557 return CdbStatus::Error;
00558 }
00559
00560
00561
00562
00563 if( thePersistentConditionPtr->isPartitionable( )) {
00564 if( CdbStatus::Success != thePersistentPartitionPtr->update( insertionTime )) {
00565
00566 cerr << errorStr << errorStr << "\n"
00567 << " Failed to update the partition modification time.\"n"
00568 << " PARTITION ID: " << thePersistentPartitionPtr->id( ) << "\n"
00569 << " CONDITION NAME: \"" << theParentConditionPtr->name( ) << "\"" << endl;
00570 return CdbStatus::Error;
00571 }
00572 }
00573
00574
00575
00576 return createObject( theObjectPtr,
00577 theParentConditionPtr,
00578 theOriginalValidityBeginTime,
00579 theOriginalValidityEndTime,
00580 theOriginalValidityBeginTime,
00581 theOriginalValidityEndTime,
00582 insertionTime,
00583 BdbTime::plusInfinity,
00584 insertionTime,
00585 persistentObjectId );
00586 }
00587
00588 CdbCPtr<CdbSQL>
00589 CdbRooDb::createImplementationObject( const std::string& theDatabaseName )
00590 {
00591 if( theDatabaseName.empty( )) return 0;
00592
00593 std::string host = "localhost";
00594 std::string user = "cdb";
00595 std::string database = "cdb";
00596
00597 unsigned int port = 3306;
00598 {
00599 Tokenize parameters( theDatabaseName );
00600 std::string parameter;
00601
00602 while ( !( parameter = parameters( "," )).empty( )) {
00603
00604 Tokenize key_value( parameter );
00605
00606 std::string key = key_value( "=" );
00607 std::string value = key_value( "=" );
00608
00609
00610
00611 if( key.empty( ) || value.empty( )) return 0;
00612
00613 if( "host" == key ) {
00614 host = value;
00615 } else if( "user" == key ) {
00616 user = value;
00617 } else if( "database" == key ) {
00618 database = value;
00619 } else if( "port" == key ) {
00620 if( 1 != sscanf( value.c_str( ), "%u", &port )) return 0;
00621 } else {
00622 return 0;
00623 }
00624 }
00625 }
00626
00627
00628
00629
00630
00631
00632 const bool notExistingDatabaseFlag = false;
00633
00634 return CdbCPtr<CdbSQL>( new CdbMySQL( host,
00635 user,
00636 notExistingDatabaseFlag,
00637 database,
00638 port ));
00639 }
00640
00641
00642
00643