00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "BaBar/BaBar.hh"
00010
00011 #include "CdbRooReadonly/CdbRooRoRevCollectionR.hh"
00012 #include "CdbRooReadonly/CdbRooRoCollectionAddressR.hh"
00013
00014 #include "CdbBase/CdbVectorAdapterItr.hh"
00015 #include "CdbBase/CdbSimpleVectorAdapterItr.hh"
00016 #include "CdbBase/CdbTimeUtils.hh"
00017
00018 #include "ErrLogger/ErrLog.hh"
00019
00020 #include <assert.h>
00021
00022 #include <iostream>
00023 using std::cout;
00024 using std::endl;
00025
00026 namespace {
00027
00028
00029
00030
00031
00032 class RevisionNameIterator : public CdbVectorAdapterItr< const char*, std::string > {
00033
00034 private:
00035
00036
00037
00038 RevisionNameIterator( );
00039
00040 protected:
00041
00042
00043
00044 RevisionNameIterator( const RevisionNameIterator& theOther ) :
00045 CdbVectorAdapterItr< const char*, std::string >( theOther )
00046 { }
00047
00048 public:
00049
00050
00051
00052
00053
00054 RevisionNameIterator( const std::vector< std::string >& theList ) :
00055 CdbVectorAdapterItr< const char*, std::string >( theList )
00056 { }
00057
00058
00059
00060
00061
00062 virtual CdbVectorAdapterItr< const char*, std::string >::InterfaceType* clone( ) const
00063 {
00064 return new RevisionNameIterator( *this );
00065 }
00066
00067 protected:
00068
00069
00070
00071
00072
00073 virtual const char* toValue( const std::string& theValue ) const
00074 {
00075 return theValue.c_str( );
00076 }
00077 };
00078 }
00079
00080
00081
00082
00083
00084 CdbRooRoRevCollectionR::CdbRooRoRevCollectionR( ) :
00085 CdbRooRoPersistentCollectionR( ),
00086 _revisions (1),
00087 _useTopmostRevision(false)
00088 { }
00089
00090 UInt_t
00091 CdbRooRoRevCollectionR::size( ) const
00092 {
00093
00094
00095
00096
00097
00098 return _revisions.size( ) - 1 + ( _useTopmostRevision ? 1 : 0 );
00099 }
00100
00101 CdbStatus
00102 CdbRooRoRevCollectionR::insert( const CdbRooRoRevisionR& theRevision )
00103 {
00104 const char* errorMsg = "CdbRooRoRevCollectionR::insert() -- ERROR";
00105
00106 CdbStatus result = CdbStatus::Error;
00107
00108 if( isStored( )) return CdbStatus::Error;
00109
00110
00111
00112 BdbTime id = theRevision.id( );
00113 std::string name = theRevision.name( );
00114
00115 if( BdbTime::minusInfinity == id ) {
00116 cout << errorMsg << endl
00117 << " Passed persistent revision object has invalid identifier. " << endl;
00118 return CdbStatus::IllegalParameters;
00119 }
00120
00121
00122
00123
00124 if( BdbTime::plusInfinity == id ) {
00125
00126 if( _useTopmostRevision ) {
00127 cout << errorMsg << endl
00128 << " Sorry, the 'topmost' revision is already stored in the collection. " << endl;
00129 return CdbStatus::Error;
00130 }
00131 _useTopmostRevision = true;
00132 _topmostRevision = theRevision;
00133
00134 return CdbStatus::Success;
00135 }
00136
00137
00138
00139
00140 UInt_t numBeforeInsert = _revisions.size( );
00141
00142 if( CdbStatus::Success != _revisions.addElement( theRevision )) {
00143 ErrMsg(error)
00144 << errorMsg << endl
00145 << " Failed to add a revision into the internal storage."
00146 << endmsg;
00147 return CdbStatus::Error;
00148 }
00149
00150 UInt_t idx = numBeforeInsert;
00151 assert( 0 != idx );
00152
00153
00154
00155
00156
00157
00158
00159 if( CdbStatus::Success != ( result = insertIntoMap( theRevision,
00160 idx ))) {
00161
00162 if( CdbStatus::Success != _revisions.resize( numBeforeInsert )) {
00163 ErrMsg(error)
00164 << errorMsg << endl
00165 << " Failed to resize the internal storage after failing to insert" << endl
00166 << " a new revision into the map."
00167 << endmsg;
00168 }
00169 return result;
00170 }
00171 if( CdbStatus::Success != ( result = insertIntoTimeLine( theRevision,
00172 idx ))) {
00173
00174
00175
00176 removeFromMap( theRevision.name( ));
00177
00178 if( CdbStatus::Success != _revisions.resize( numBeforeInsert )) {
00179 ErrMsg(error)
00180 << errorMsg << endl
00181 << " Failed to resize the internal storage after failing to insert" << endl
00182 << " a new revision into the timeline."
00183 << endmsg;
00184 }
00185 return result;
00186 }
00187 return CdbStatus::Success;
00188 }
00189
00190 CdbStatus
00191 CdbRooRoRevCollectionR::find( const BdbTime& theId,
00192 CdbRooRoRevisionR& theRevision ) const
00193 {
00194 const char* errorMsg = "CdbRooRoRevCollectionR::find(id) -- ERROR";
00195
00196
00197
00198 if( BdbTime::minusInfinity == theId ) {
00199 cout << errorMsg << endl
00200 << " Passed revision identifier is not valid in this context." << endl
00201 << " ID: " << CdbTimeUtils::time2string( theId ) << " : " << theId << endl;
00202 return CdbStatus::Error;
00203 }
00204
00205
00206
00207
00208 if( BdbTime::plusInfinity == theId ) {
00209
00210 if( !_useTopmostRevision ) return CdbStatus::NotFound;
00211
00212 theRevision = _topmostRevision;
00213
00214 return CdbStatus::Success;
00215 }
00216
00217
00218
00219
00220 Interval dInterval;
00221 if(( !_indexById.findAtBegin( dInterval, theId )) || ( 0 == dInterval.value( ))) {
00222 return CdbStatus::NotFound;
00223 }
00224 if( CdbStatus::Success != _revisions.elementAt( dInterval.value( ),
00225 theRevision )) {
00226 ErrMsg(error)
00227 << errorMsg << endl
00228 << " Failed to find a revision in the internal storage."
00229 << endmsg;
00230 return CdbStatus::Error;
00231 }
00232 return CdbStatus::Success;
00233 }
00234
00235 CdbStatus
00236 CdbRooRoRevCollectionR::find( const char* theName,
00237 CdbRooRoRevisionR& theRevision ) const
00238 {
00239 const char* errorMsg = "CdbRooRoRevCollectionR::find(name) -- ERROR";
00240
00241
00242
00243 if( 0 == theName ) {
00244 cout << errorMsg << endl
00245 << " Passed revision name can't be 0 in this context." << endl;
00246 return CdbStatus::Error;
00247 }
00248
00249
00250
00251
00252 if( std::string( "<topmost>" ) == theName ) {
00253
00254 if( !_useTopmostRevision ) return CdbStatus::NotFound;
00255
00256 theRevision = _topmostRevision;
00257
00258 return CdbStatus::Success;
00259 }
00260
00261
00262
00263
00264
00265
00266 std::map< std::string, UInt_t >::const_iterator itr = _indexByName.find( theName );
00267 if( itr == _indexByName.end( )) {
00268 return CdbStatus::NotFound;
00269 }
00270 UInt_t idx = (*itr).second;
00271 assert( 0 != idx );
00272
00273 if( CdbStatus::Success != _revisions.elementAt( idx,
00274 theRevision )) {
00275 ErrMsg(error)
00276 << errorMsg << endl
00277 << " Failed to find a revision in the internal storage."
00278 << endmsg;
00279 return CdbStatus::Error;
00280 }
00281 return CdbStatus::Success;
00282 }
00283
00284 CdbStatus
00285 CdbRooRoRevCollectionR::last( BdbTime& theId ) const
00286 {
00287
00288
00289 if( _useTopmostRevision ) {
00290 theId = BdbTime::plusInfinity;
00291 return CdbStatus::Success;
00292 }
00293
00294
00295
00296 Interval dInterval;
00297
00298 CdbStatus result = _indexById.last( dInterval );
00299 if( CdbStatus::Success == result ) {
00300
00301 if( 0 != dInterval.value( )) {
00302 theId = dInterval.begin( );
00303 } else {
00304 result = CdbStatus::NotFound;
00305 }
00306 }
00307 return result;
00308 }
00309
00310 CdbItr<BdbTime>
00311 CdbRooRoRevCollectionR::iterator_identifiers( ) const
00312 {
00313 const char* fatalMsg = "CdbRooRoRevCollectionR::iterator_identifiers() -- FATAL ERROR";
00314
00315
00316
00317 std::vector<BdbTime> vectorOfIdentifiers;
00318 {
00319
00320
00321 CdbRooRoTimeLineR< UInt_t >::IteratorOfIntervals itr = _indexById.iterator( );
00322 while( itr.next( )) {
00323
00324 UInt_t idx = itr.value( ).value( );
00325
00326 if( 0 == idx ) continue;
00327
00328
00329 CdbRooRoRevisionR revision;
00330 if( CdbStatus::Success != _revisions.elementAt( idx,
00331 revision )) {
00332 ErrMsg(fatal)
00333 << fatalMsg << endl
00334 << " Failed to find a revision in the internal storage."
00335 << endmsg;
00336 break;
00337 }
00338 vectorOfIdentifiers.push_back( revision.id( ));
00339 }
00340
00341
00342
00343 if( _useTopmostRevision ) vectorOfIdentifiers.push_back( BdbTime::plusInfinity );
00344 }
00345
00346
00347
00348 CdbItr<BdbTime> itr( new CdbSimpleVectorAdapterItr<BdbTime>( vectorOfIdentifiers ));
00349
00350 return itr;
00351 }
00352
00353 CdbItr<const char*>
00354 CdbRooRoRevCollectionR::iterator_names( ) const
00355 {
00356 const char* fatalMsg = "CdbRooRoRevCollectionR::iterator_names() -- FATAL ERROR";
00357
00358
00359
00360 std::vector<std::string> vectorOfNames;
00361 {
00362
00363
00364 CdbRooRoTimeLineR< UInt_t >::IteratorOfIntervals itr = _indexById.iterator( );
00365 while( itr.next( )) {
00366
00367 UInt_t idx = itr.value( ).value( );
00368
00369 if( 0 == idx ) continue;
00370
00371
00372 CdbRooRoRevisionR revision;
00373 if( CdbStatus::Success != _revisions.elementAt( idx,
00374 revision )) {
00375 ErrMsg(fatal)
00376 << fatalMsg << endl
00377 << " Failed to find a revision in the internal storage."
00378 << endmsg;
00379 break;
00380 }
00381 vectorOfNames.push_back( revision.name( ));
00382 }
00383
00384
00385
00386 if( _useTopmostRevision ) vectorOfNames.push_back( std::string( "<topmost>" ));
00387 }
00388
00389
00390
00391 CdbItr<const char*> itr( new RevisionNameIterator( vectorOfNames ));
00392
00393 return itr;
00394 }
00395
00396 void
00397 CdbRooRoRevCollectionR::dump( std::ostream& o ) const
00398 {
00399 const char* fatalMsg = "CdbRooRoRevCollectionR::dump() -- FATAL ERROR";
00400
00401 do {
00402
00403
00404
00405 o << "** COLLECTION OF REVISIONS **" << endl
00406 << endl;
00407
00408 CdbRooRoTimeLineR< UInt_t >::IteratorOfIntervals itr = _indexById.iterator( );
00409
00410 while( itr.next( )) {
00411
00412 Interval dInterval = itr.value( );
00413 UInt_t idx = dInterval.value( );
00414
00415 if( 0 == idx ) {
00416
00417 o << " <IS EMPTY>" << endl
00418 << endl;
00419
00420 } else {
00421
00422
00423
00424
00425 BdbTime rId = BdbTime::plusInfinity;
00426 std::string rName = "<topmost>";
00427
00428 if( !_useTopmostRevision ) {
00429
00430 CdbRooRoRevisionR revision;
00431 if( CdbStatus::Success != _revisions.elementAt( idx,
00432 revision )) {
00433 ErrMsg(fatal)
00434 << fatalMsg << endl
00435 << " Failed to find a revision in the internal storage."
00436 << endmsg;
00437 break;
00438 }
00439 rId = revision.id( );
00440 rName = revision.name( );
00441 }
00442
00443 o << " ID : " << CdbTimeUtils::time2string( rId ) << " : " << rId << endl
00444 << " NAME : \"" << rName << "\"" << endl
00445 << " DURATION : " << "[ " << CdbTimeUtils::time2string( dInterval.begin( ), true ) << " , "
00446 << CdbTimeUtils::time2string( dInterval.end( ), true ) << " )" << endl
00447 << endl;
00448 }
00449 }
00450
00451 o << "** END OF THE COLLECTION **" << endl;
00452
00453 } while( false );
00454 }
00455
00456 CdbStatus
00457 CdbRooRoRevCollectionR::storeSubCollectionsAt( const CdbRooRoCollectionAddressR& theCollectionAddress,
00458 const CdbCPtr<TFile>& theFilePtr,
00459 Int_t& theNumBytesStored )
00460 {
00461 const char* errorStr = "CdbRooRoRevCollectionR::storeSubCollectionsAt() -- ERROR";
00462
00463 Int_t numBytesStored = 0;
00464
00465
00466
00467 Int_t numBytes = 0;
00468
00469 const CdbRooRoCollectionAddressR subCollectionAddress =
00470 CdbRooRoCollectionAddressR::createSubCollection( theCollectionAddress,
00471 ".Revisions" );
00472
00473 CdbStatus status = _revisions.storeAsEmbeddedAt( subCollectionAddress,
00474 theFilePtr,
00475 numBytes );
00476 if( CdbStatus::Success != status ) {
00477
00478 ErrMsg(error) << errorStr << endl
00479 << " Failed to store an embedded sub-collection of revisions." << endl
00480 << " File Name : " << theFilePtr->GetName( ) << endl
00481 << " Sub.Collection Address : " << subCollectionAddress << endl
00482 << " Error Status : " << status
00483 << endmsg;
00484 return status;
00485 }
00486 numBytesStored += numBytes;
00487
00488
00489
00490 theNumBytesStored = numBytesStored;
00491
00492 return CdbStatus::Success;
00493 }
00494
00495 CdbStatus
00496 CdbRooRoRevCollectionR::insertIntoMap( const CdbRooRoRevisionR& theRevision,
00497 UInt_t theIdx )
00498 {
00499 const char* errorMsg = "CdbRooRoRevCollectionR::insertIntoMap() -- ERROR";
00500
00501 assert( 0 != theIdx );
00502
00503 CdbStatus result = CdbStatus::Error;
00504 do {
00505
00506
00507
00508 std::string name = theRevision.name( );
00509
00510 std::map< std::string, UInt_t >::const_iterator itr = _indexByName.find( name );
00511 if( itr != _indexByName.end( )) {
00512 cout << errorMsg << endl
00513 << " There is already a revision with such name." << endl
00514 << " Passed revision name: \"" << name << "\"" << endl;
00515 break;
00516 }
00517
00518
00519
00520 _indexByName[name] = theIdx;
00521
00522
00523
00524 result = CdbStatus::Success;
00525
00526 } while( false );
00527
00528 return result;
00529 }
00530
00531 void
00532 CdbRooRoRevCollectionR::removeFromMap( const std::string& theName )
00533 {
00534 std::map< std::string, UInt_t >::iterator itr = _indexByName.find( theName );
00535 if( itr != _indexByName.end( )) _indexByName.erase( itr );
00536 }
00537
00538 CdbStatus
00539 CdbRooRoRevCollectionR::insertIntoTimeLine( const CdbRooRoRevisionR& theRevision,
00540 UInt_t theIdx )
00541 {
00542 const char* errorMsg = "CdbRooRoRevCollectionR::insertIntoTimeLine() -- ERROR";
00543
00544 assert( 0 != theIdx );
00545
00546 CdbStatus result = CdbStatus::Error;
00547 do {
00548
00549
00550
00551
00552 BdbTime id = theRevision.id( );
00553
00554 Interval lastInterval;
00555 if( CdbStatus::Success != _indexById.last( lastInterval )) {
00556 cout << errorMsg << endl
00557 << " Failed to obtain the last interval from the TimeLine." << endl;
00558 break;
00559 }
00560 if( id <= lastInterval.begin( )) {
00561 cout << errorMsg << endl
00562 << " Passed revision object has incorrect identifier time, which" << endl
00563 << " should never be less or equal than the one of the last known revision." << endl
00564 << " Passed revision ID: " << CdbTimeUtils::time2string( id ) << " : " << id << endl
00565 << " Last known revision ID: " << CdbTimeUtils::time2string( lastInterval.begin( )) << " : " << lastInterval.begin( ) << endl;
00566 break;
00567 }
00568
00569
00570
00571
00572
00573
00574
00575 if( CdbStatus::Success != _indexById.insert( id,
00576 BdbTime::plusInfinity,
00577 theIdx )) {
00578 cout << errorMsg << endl
00579 << " Failed to insert new interval into the TimeLine." << endl;
00580 break;
00581 }
00582
00583
00584
00585 result = CdbStatus::Success;
00586
00587 } while( false );
00588
00589 return result;
00590 }
00591
00592
00593
00594