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

CdbBdbSRevCollectionP.cc

Go to the documentation of this file.
00001 // File and Version Information:
00002 //      $Id: CdbBdbSRevCollectionP.cc,v 1.10 2004/08/06 05:54:25 bartoldu Exp $
00003 
00004 /// Implementation file for the CdbBdbSRallocatorP class
00005 /**
00006   * @see CdbBdbSRallocatorP
00007   */
00008 
00009 #include "BaBar/BaBar.hh"
00010 
00011 #include "CdbBdbShared/CdbBdbSRevCollectionP.hh"
00012 
00013 #include <assert.h>
00014 using std::cout;
00015 using std::endl;
00016 using std::ostream;
00017 
00018 namespace {
00019 
00020     ///////////////////////////////
00021     // Class: RevisionIdIterator //
00022     ///////////////////////////////
00023 
00024     class RevisionIdIterator : public CdbItr<BdbTime>::InterfaceType {
00025 
00026     private:
00027 
00028       /// The default constructor (NOT IMPLEMENTED)
00029 
00030         RevisionIdIterator( );
00031 
00032       /// The assignment operator (NOT IMPLEMENTED)
00033 
00034         RevisionIdIterator& operator=( const RevisionIdIterator& theItr );
00035 
00036     protected:
00037 
00038       /// The copy constructor
00039       /**
00040         * The only reason why we have it implemented is because it's needed
00041         * to implement the clone method.
00042         *
00043         * @see RevisionIdIterator::clone()
00044         */
00045         RevisionIdIterator( const RevisionIdIterator& theItr ) :
00046             _itr(theItr._itr)
00047         { }
00048 
00049     public:
00050 
00051       /// The normal constructor
00052 
00053         RevisionIdIterator( const CdbBdbSTimeLineP< BdbRef(CdbBdbSRevisionP) >::IteratorOfIntervals& theItr ) :
00054             _itr(theItr)
00055         { }
00056 
00057       /// The destructor
00058 
00059         virtual ~RevisionIdIterator( )
00060         { }
00061 
00062       /// Reset an iterator to its initial state.
00063       /**
00064         * This implements the corresponding method of the base class.
00065         *
00066         * @see CdbIItr::reset
00067         * @see CdbStatus
00068         */
00069         virtual CdbStatus reset( )
00070         {
00071             return _itr.reset( );
00072         }
00073 
00074       /// Advance an iterator to the next position.
00075       /**
00076         * This implements the corresponding method of the base class.
00077         *
00078         * @see CdbIItr::next()
00079         */
00080         virtual bool next( )
00081         {
00082             if( _itr.next( )) {
00083 
00084                 CdbBdbSTimeLineInterval< BdbRef(CdbBdbSRevisionP) > i = _itr.value( );
00085 
00086                 BdbRef(CdbBdbSRevisionP) rRef = i.value;
00087 
00088               // IMPLEMENTATION NOTE: if the revision reference is 0-0-0-0 it means that
00089               //                      there is no revision in that block of the timeline.
00090               //                      This is only allowed for the very first element of
00091               //                      the time line.
00092               //                      However we're not performing this test now and just
00093               //                      repeating the operation.
00094 
00095                 if( BdbIsNull(rRef)) return next( );
00096 
00097                 _value = rRef->id( );
00098 
00099                 return true;
00100             }
00101             return false;
00102         }
00103 
00104       /// Obtain the currently reffered value.
00105       /**
00106         * This implements the corresponding method of the base class.
00107         *
00108         * @see CdbIItr::value()
00109         * @see CdbIItr::ValueType
00110         *
00111         * @return the current value the iterator is set on
00112         */
00113         virtual ValueType value( )
00114         {
00115             if( isValid( )) {
00116                 return _value;
00117             }
00118 
00119           // Invalid revision identifier.
00120 
00121             return BdbTime::minusInfinity;
00122         }
00123 
00124       /// Check if an iterator is valid.
00125       /**
00126         * This implements the corresponding method of the base class.
00127         *
00128         * @see CdbIItr::isValid()
00129         */
00130         virtual bool isValid( )
00131         {
00132             return _itr.isValid( );
00133         }
00134 
00135       /// Make a clone of itself
00136       /**
00137         * @see CdbIItr::clone()
00138         */
00139         virtual InterfaceType* clone( ) const
00140         {
00141             return new RevisionIdIterator( *this );
00142         }
00143 
00144     private:
00145 
00146       // We're delegating all the operations to this iterator
00147 
00148         CdbBdbSTimeLineP< BdbRef(CdbBdbSRevisionP) >::IteratorOfIntervals _itr;
00149 
00150         BdbTime _value;
00151     };
00152 
00153     /////////////////////////////////
00154     // Class: RevisionNameIterator //
00155     /////////////////////////////////
00156 
00157     class RevisionNameIterator : public CdbItr<const char*>::InterfaceType {
00158 
00159     private:
00160 
00161       /// The default constructor (NOT IMPLEMENTED)
00162 
00163         RevisionNameIterator( );
00164 
00165       /// The assignment operator (NOT IMPLEMENTED)
00166 
00167         RevisionNameIterator& operator=( const RevisionNameIterator& theItr );
00168 
00169     protected:
00170 
00171       /// The copy constructor
00172       /**
00173         * The only reason why we have it implemented is because it's needed
00174         * to implement the clone method.
00175         *
00176         * @see RevisionNameIterator::clone()
00177         */
00178         RevisionNameIterator( const RevisionNameIterator& theItr ) :
00179             _itr(theItr._itr),
00180             _value(theItr._value)
00181         { }
00182 
00183     public:
00184 
00185       /// The normal constructor
00186 
00187         RevisionNameIterator( const CdbBdbSTimeLineP< BdbRef(CdbBdbSRevisionP) >::IteratorOfIntervals& theItr ) :
00188             _itr(theItr),
00189             _value("")
00190         { }
00191 
00192       /// The destructor
00193 
00194         virtual ~RevisionNameIterator( )
00195         { }
00196 
00197       /// Reset an iterator to its initial state.
00198       /**
00199         * This implements the corresponding method of the base class.
00200         *
00201         * @see CdbIItr::reset
00202         * @see CdbStatus
00203         */
00204         virtual CdbStatus reset( )
00205         {
00206             return _itr.reset( );
00207         }
00208 
00209       /// Advance an iterator to the next position.
00210       /**
00211         * This implements the corresponding method of the base class.
00212         *
00213         * @see CdbIItr::next()
00214         */
00215         virtual bool next( )
00216         {
00217             if( _itr.next( )) {
00218 
00219                 CdbBdbSTimeLineInterval< BdbRef(CdbBdbSRevisionP) > i = _itr.value( );
00220 
00221                 BdbRef(CdbBdbSRevisionP) rRef = i.value;
00222 
00223               // IMPLEMENTATION NOTE: if the revision reference is 0-0-0-0 it means that
00224               //                      there is no revision in that block of the timeline.
00225               //                      This is only allowed for the very first element of
00226               //                      the time line.
00227               //                      However we're not performing this test now and just
00228               //                      repeating the operation.
00229 
00230                 if( BdbIsNull(rRef)) return next( );
00231 
00232                 _value = rRef->name( );
00233 
00234                 return true;
00235             }
00236             return false;
00237         }
00238 
00239       /// Obtain the currently reffered value.
00240       /**
00241         * This implements the corresponding method of the base class.
00242         *
00243         * @see CdbIItr::value()
00244         * @see CdbIItr::ValueType
00245         *
00246         * @return the current value the iterator is set on
00247         */
00248         virtual ValueType value( )
00249         {
00250             if( isValid(  )) {
00251                 return _value.c_str( );
00252             }
00253 
00254           // Invalid revision name.
00255 
00256             return 0;
00257         }
00258 
00259       /// Check if an iterator is valid.
00260       /**
00261         * This implements the corresponding method of the base class.
00262         *
00263         * @see CdbIItr::isValid()
00264         */
00265         virtual bool isValid( )
00266         {
00267             return _itr.isValid( );
00268         }
00269 
00270       /// Make a clone of itself
00271       /**
00272         * @see CdbIItr::clone()
00273         */
00274         virtual InterfaceType* clone( ) const
00275         {
00276             return new RevisionNameIterator( *this );
00277         }
00278 
00279     private:
00280 
00281       // We're delegating all the operations to this iterator
00282 
00283         CdbBdbSTimeLineP< BdbRef(CdbBdbSRevisionP) >::IteratorOfIntervals _itr;
00284 
00285         std::string _value;
00286     };
00287 };
00288 
00289 //////////////////////////////////
00290 // Class: CdbBdbSRevCollectionP //
00291 //////////////////////////////////
00292 
00293 CdbBdbSRevCollectionP::CdbBdbSRevCollectionP( )
00294 {
00295     _timeLineRef = new( ooThis( )) CdbBdbSTimeLineP< BdbRef(CdbBdbSRevisionP) >( );
00296     _mapRef      = new( ooThis( )) BdbMap( );
00297 }
00298 
00299 CdbBdbSRevCollectionP::~CdbBdbSRevCollectionP( ) 
00300 {
00301   // Delete the registered revisions first
00302 
00303     CdbBdbSTimeLineP< BdbRef(CdbBdbSRevisionP) >::IteratorOfIntervals itr
00304         = _timeLineRef->iterator( );
00305 
00306     while( itr.next( )) {
00307 
00308         Interval i = itr.value( );
00309 
00310         BdbRef(CdbBdbSRevisionP) revisionRef = i.value;
00311         if( ! BdbIsNull(revisionRef)) BdbDelete( revisionRef );
00312     }
00313 
00314   // Then we delete the local data structures
00315 
00316     BdbDelete( _timeLineRef );
00317     BdbDelete( _mapRef );
00318 }
00319 
00320 CdbStatus
00321 CdbBdbSRevCollectionP::insert( const BdbRef(CdbBdbSRevisionP)& theRevisionRef )
00322 {
00323     const char* errorMsg = "CdbBdbSRevCollectionP::insert() -- ERROR";
00324 
00325     ooUpdate( );
00326 
00327     CdbStatus result = CdbStatus::Error;
00328     do {
00329 
00330       // Verify parameters.
00331 
00332         if( BdbIsNull(theRevisionRef) || !theRevisionRef.isValid( )) {
00333             cout << errorMsg << endl
00334                  << "    Null or invalid persistent revision object " << theRevisionRef.sprint( ) << " passed to the procedure." << endl;
00335             break;
00336         }
00337         BdbTime   id   = theRevisionRef->id( );
00338         ooVString name = theRevisionRef->name( );
00339 
00340         if(( BdbTime::minusInfinity == id ) || ( BdbTime::plusInfinity == id ))  {
00341             cout << errorMsg << endl << "    Passed persistent revision object has invalid identifier. " << endl;
00342             break;
00343         }
00344         if( 0 == name.length( ))  {
00345             cout << errorMsg << endl << "    Passed persistent revision object does not have a name. " << endl;
00346             break;
00347         }
00348 
00349       // Follow up with revision registration in the map and the TimeLine
00350       //
00351       // NOTE: The registration sequence is only important from the recovery point
00352       //       of view just in case this (recovery) would be required. Removing an element
00353       //       from the map is much easier than from the TimeLine
00354 
00355         if( CdbStatus::Success != insertIntoMap( theRevisionRef)) {
00356             break;
00357         }
00358         if( CdbStatus::Success != insertIntoTimeLine( theRevisionRef ))  {
00359             removeFromMap( name.head( ));   // To maintain consistency of the collection's context.
00360             break;
00361         }
00362 
00363       // Done.
00364 
00365         result = CdbStatus::Success;
00366 
00367     } while( false );
00368 
00369     return result;
00370 }
00371 
00372 CdbStatus
00373 CdbBdbSRevCollectionP::find( const BdbTime&            theId,
00374                              BdbRef(CdbBdbSRevisionP)& theRevisionRef ) const
00375 {
00376     const char* errorMsg = "CdbBdbSRevCollectionP::find(id) -- ERROR";
00377 
00378     CdbStatus result = CdbStatus::Error;
00379     do {
00380 
00381       // Verify the parameters
00382 
00383         if(( BdbTime::minusInfinity == theId ) || ( BdbTime::plusInfinity == theId ))  {
00384             cout << errorMsg << endl
00385                  << "    Passed revision identifier is not valid in this context." << endl
00386                  << "        ID: " << theId << endl;
00387             break;
00388         }
00389 
00390       // This method uses "exact match" search in the B-tree to locate specified
00391       // revision object.
00392 
00393         Interval i;
00394         if(( ! _timeLineRef->findAtBegin( i, theId )) || BdbIsNull(i.value)) {
00395             result = CdbStatus::NotFound;
00396             break;
00397         }
00398         theRevisionRef = i.value;
00399 
00400       // Done
00401 
00402         result = CdbStatus::Success;
00403 
00404     } while( false );
00405     
00406     return result;
00407 }
00408 
00409 CdbStatus
00410 CdbBdbSRevCollectionP::find( const char*               theName,
00411                              BdbRef(CdbBdbSRevisionP)& theRevisionRef ) const
00412 {
00413     const char* errorMsg = "CdbBdbSRevCollectionP::find(name) -- ERROR";
00414 
00415     CdbStatus result = CdbStatus::Error;
00416     do {
00417 
00418       // Verify the parameters
00419 
00420         if( 0 == theName )  {
00421             cout << errorMsg << endl
00422                  << "    Passed revision name can't be 0 in this context." << endl;
00423             break;
00424         }
00425 
00426       // Look up the object in the map.
00427       //
00428       // NOTE: If the object is not found then we let a client to interpret
00429       //       the result of this search.
00430 
00431         BdbRef(BdbPersObj) objectRef;
00432         if( BdbcSuccess != _mapRef->lookup( theName,
00433                                             objectRef )) {
00434             result = CdbStatus::NotFound;
00435             break;
00436         }
00437 
00438       // Make sure it has correct type.
00439 
00440         BdbRef(CdbBdbSRevisionP) revisionRef = (const BdbRef(CdbBdbSRevisionP)&) objectRef;
00441         if( !revisionRef.isValid( ) || BdbIsNull(revisionRef)) {
00442 
00443             cout << errorMsg << endl
00444                  << "    Fatal internal error #2." << endl
00445                  << "    Map contain elements of unexpected persistent type." << endl;
00446 
00447             assert( 0 );
00448 
00449             break;
00450         }
00451         theRevisionRef = revisionRef;
00452 
00453       // Done
00454 
00455         result = CdbStatus::Success;
00456 
00457     } while( false );
00458     
00459     return result;
00460 }
00461 
00462 CdbStatus
00463 CdbBdbSRevCollectionP::last( BdbTime& theId ) const
00464 {
00465     Interval i;
00466 
00467     CdbStatus result = _timeLineRef->last( i );
00468     if( CdbStatus::Success == result ) theId = i.begin;
00469 
00470     return result;
00471 }
00472 
00473 CdbItr<BdbTime>
00474 CdbBdbSRevCollectionP::iterator_identifiers( ) const
00475 {
00476   // ATTENTION: This is not a memory leak - the created object
00477   //            will be destroyed by the iterator.
00478 
00479     return CdbItr<BdbTime>( new RevisionIdIterator( _timeLineRef->iterator( )));
00480 }
00481 
00482 
00483 CdbItr<const char*>
00484 CdbBdbSRevCollectionP::iterator_names( ) const
00485 {
00486   // ATTENTION: This is not a memory leak - the created object
00487   //            will be destroyed by the iterator.
00488 
00489     return CdbItr<const char*>( new RevisionNameIterator( _timeLineRef->iterator( )));
00490 }
00491 
00492 void
00493 CdbBdbSRevCollectionP::dump( ostream& o ) const
00494 {
00495     do {
00496 
00497       // Do the dump
00498 
00499         o << "=== REVISIONS COLLECTION ===" << endl
00500           << endl;
00501 
00502         CdbBdbSTimeLineP< BdbRef(CdbBdbSRevisionP) >::IteratorOfIntervals itr
00503             = _timeLineRef->iterator( );
00504 
00505         while( itr.next( )) {
00506 
00507             Interval i = itr.value( );
00508 
00509             BdbRef(CdbBdbSRevisionP) revisionRef = i.value;
00510             if( BdbIsNull(revisionRef)) {
00511 
00512                 o << "  <IS EMPTY>" << endl
00513                   << endl;
00514 
00515             } else {
00516 
00517                 o << revisionRef.sprint( ) << endl
00518                   << endl
00519                   << "  ID:            " << revisionRef->id( ) << endl
00520                   << "  NAME:          " << revisionRef->name( ).head( ) << endl
00521                   << "  VI COLLECTION: " << revisionRef->collection( ).sprint( ) << endl
00522                   << "  DURATION:      " << "[ " << i.begin.getGmtSec( ) << "." << i.begin.getGmtNsec( ) << " , "
00523                   <<                                i.end.getGmtSec  ( ) << "." << i.end.getGmtNsec  ( ) << " )" << endl
00524                   << endl;
00525             }
00526         }
00527 
00528         o << "=== END OF COLLECTION ===" << endl;
00529 
00530     } while( false );
00531 }
00532 
00533 CdbStatus
00534 CdbBdbSRevCollectionP::insertIntoMap( const BdbRef(CdbBdbSRevisionP)& theRevisionRef )
00535 {
00536     const char* errorMsg = "CdbBdbSRevCollectionP::insertIntoMap() -- ERROR";
00537 
00538     CdbStatus result = CdbStatus::Error;
00539     do {
00540 
00541       // Verify if the map does not contain any revision with such name.
00542 
00543         ooVString name = theRevisionRef->name( );
00544 
00545         if( _mapRef->isMember( name.head( ))) {
00546             cout << errorMsg << endl
00547                  << "    There is already a revision with such name." << endl
00548                  << "        Passed revision name: " << name.head( ) << endl;
00549             break;
00550         }
00551 
00552       // Now just add the revision.
00553 
00554         if( BdbcSuccess != _mapRef->add( name.head( ), theRevisionRef )) {
00555             cout << errorMsg << endl
00556                  << "    Failed to add new name to the map." << endl
00557                  << "        Passed revision name: " << name.head( ) << endl;
00558             break;
00559         }
00560 
00561       // Done.
00562 
00563         result = CdbStatus::Success;
00564 
00565     } while( false );
00566 
00567     return result;
00568 }
00569 
00570 void
00571 CdbBdbSRevCollectionP::removeFromMap( const char* theName )
00572 {
00573     _mapRef->remove( theName );
00574 }
00575 
00576 CdbStatus
00577 CdbBdbSRevCollectionP::insertIntoTimeLine( const BdbRef(CdbBdbSRevisionP)& theRevisionRef )
00578 {
00579     const char* errorMsg = "CdbBdbSRevCollectionP::insertIntoTimeLine() -- ERROR";
00580 
00581     CdbStatus result = CdbStatus::Error;
00582     do {
00583 
00584       // Verify the value of the revisin identifier. It must not be older
00585       // (less or equal) than the most recently known revision.
00586 
00587         BdbTime id = theRevisionRef->id( );
00588 
00589         Interval lastInterval;
00590         if( CdbStatus::Success != _timeLineRef->last( lastInterval )) {
00591             cout << errorMsg << endl
00592                  << "    Failed to obtain the last interval from the TimeLine." << endl;
00593             break;
00594         }
00595         if( id <= lastInterval.begin ) {
00596             cout << errorMsg << endl
00597                  << "    Passed revision object has incorrect identifier time, which" << endl
00598                  << "    should never be less or equal than the one of the last known revision." << endl
00599                  << "        Passed revision     ID: " << id << endl
00600                  << "        Last known revision ID: " << lastInterval.begin << endl;
00601             break;
00602         }
00603 
00604       // Append the "revision duration" interval by the end of the TimeLine.
00605       // This operation will cut existing "last" interval at the specified
00606       // insertion time point.
00607       //
00608       // NOTE: Intervals have the following semantics: [begin,end)
00609 
00610         if( CdbStatus::Success != _timeLineRef->insert( id,
00611                                                         BdbTime::plusInfinity,
00612                                                         theRevisionRef )) {
00613             cout << errorMsg << endl
00614                  << "    Failed to insert new interval into the TimeLine." << endl;
00615             break;
00616         }
00617 
00618       // Done.
00619 
00620         result = CdbStatus::Success;
00621 
00622     } while( false );
00623 
00624     return result;
00625 }
00626 
00627 /////////////////
00628 // End Of File //
00629 /////////////////

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