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

CdbBdbSMetaDataP.cc

Go to the documentation of this file.
00001 // File and Version Information:
00002 //      $Id: CdbBdbSMetaDataP.cc,v 1.15 2004/08/06 05:54:24 bartoldu Exp $
00003 
00004 /// The implementation file for the CdbBdbSMetaDataP class
00005 /**
00006   * @see CdbBdbSMetaDataP
00007   */
00008 
00009 #include "BaBar/BaBar.hh"
00010 
00011 #include "CdbBdbShared/CdbBdbSMetaDataP.hh"
00012 #include "CdbBdbShared/CdbBdbSRebuildAction.hh"
00013 
00014 #include "CdbBdb/CdbBdbObjectClone.hh"
00015 
00016 #include <iostream>
00017 #include <assert.h>
00018 #include <string.h>
00019 using std::cout;
00020 using std::endl;
00021 
00022 namespace {
00023 
00024     ///////////////////////////////
00025     // Class: RevisionIdIterator //
00026     ///////////////////////////////
00027 
00028     class RevisionIdIterator : public CdbItr<BdbTime>::InterfaceType {
00029 
00030     private:
00031 
00032       /// The default constructor (NOT IMPLEMENTED)
00033 
00034         RevisionIdIterator( );
00035 
00036       /// The assignment operator (NOT IMPLEMENTED)
00037 
00038         RevisionIdIterator& operator=( const RevisionIdIterator& theItr );
00039 
00040     protected:
00041 
00042       /// The copy constructor
00043       /**
00044         * The only reason why we have it implemented is because it's needed
00045         * to implement the clone method.
00046         *
00047         * @see RevisionIdIterator::clone()
00048         */
00049         RevisionIdIterator( const RevisionIdIterator& theItr ) :
00050             _revCollectionRef      (theItr._revCollectionRef),
00051             _appendTopmostFlag     (theItr._appendTopmostFlag),
00052             _isValid               (theItr._isValid),
00053             _hasEverBeenAdvanced   (theItr._hasEverBeenAdvanced),
00054             _value                 (theItr._value),
00055             _revItr                (theItr._revItr),
00056             _thereIsTopmostToAppend(theItr._thereIsTopmostToAppend)
00057         { }
00058 
00059     public:
00060 
00061       /// The normal constructor
00062 
00063         RevisionIdIterator( const BdbRef(CdbBdbSRevCollectionP)& theRef,
00064                             bool                                 appendTopmostFlag ) :
00065             _revCollectionRef      (theRef),
00066             _appendTopmostFlag     (appendTopmostFlag),
00067             _isValid               (false),
00068             _hasEverBeenAdvanced   (false),
00069             _thereIsTopmostToAppend(appendTopmostFlag)
00070         {
00071             assert( !BdbIsNull(theRef));
00072         }
00073 
00074       /// The destructor
00075 
00076         virtual ~RevisionIdIterator( )
00077         { }
00078 
00079       /// Reset an iterator to its initial state.
00080       /**
00081         * This implements the corresponding method of the base class.
00082         *
00083         * @see CdbIItr::reset
00084         * @see CdbStatus
00085         */
00086         virtual CdbStatus reset( )
00087         {
00088             _isValid             = false;
00089             _hasEverBeenAdvanced = false;
00090 
00091             _thereIsTopmostToAppend = _appendTopmostFlag;
00092 
00093             return CdbStatus::Success;
00094         }
00095 
00096       /// Advance an iterator to the next position.
00097       /**
00098         * This implements the corresponding method of the base class.
00099         *
00100         * @see CdbIItr::next()
00101         */
00102         virtual bool next( )
00103         {
00104             if( !_isValid ) {
00105 
00106                 if( !_hasEverBeenAdvanced ) {
00107                     _hasEverBeenAdvanced = true;
00108 
00109                     _revItr = _revCollectionRef->iterator_identifiers( );
00110 
00111                 } else {
00112 
00113                   // This iterator should remain at "PAST_LAST_ELEMENT" state. The only way
00114                   // to get out of this state is to to call ::reset() method.
00115 
00116                     return false;
00117                 }
00118             }
00119             if( _isValid && _revItr.isValid( ) && _revItr.next( )) {
00120 
00121               // We keep iterating in the valid state
00122 
00123                 _value = _revItr.value( );
00124 
00125             } else if( !_isValid && _revItr.next( )) {
00126 
00127               // The first attemp to advance an iterator since it was initialized
00128 
00129                 _value   = _revItr.value( );
00130                 _isValid = true;
00131 
00132             } else {
00133 
00134               // It does not matter what was the previous state of the iterator
00135               // before since the only source of information would be the topmost revision
00136               // if any.
00137 
00138                 if( _thereIsTopmostToAppend ) {
00139                     _thereIsTopmostToAppend = false;
00140 
00141                     _value   = BdbTime::plusInfinity;
00142                     _isValid = true;
00143 
00144                 } else {
00145 
00146                   // Now we've got into the "PAST_LAST_ELEMENT" state.
00147 
00148                     _isValid = false;
00149                 }
00150             }
00151             return _isValid;
00152         }
00153 
00154       /// Obtain the currently reffered value.
00155       /**
00156         * This implements the corresponding method of the base class.
00157         *
00158         * @see CdbIItr::value()
00159         * @see CdbIItr::ValueType
00160         *
00161         * @return the current value the iterator is set on
00162         */
00163         virtual ValueType value( )
00164         {
00165             if( _isValid ) {
00166                 return _value;
00167             }
00168 
00169           // Invalid revision identifier.
00170 
00171             return BdbTime::minusInfinity;
00172         }
00173 
00174       /// Check if an iterator is valid.
00175       /**
00176         * This implements the corresponding method of the base class.
00177         *
00178         * @see CdbIItr::isValid()
00179         */
00180         virtual bool isValid( )
00181         {
00182             return _isValid;
00183         }
00184 
00185       /// Make a clone of itself
00186       /**
00187         * @see CdbIItr::clone()
00188         */
00189         virtual InterfaceType* clone( ) const
00190         {
00191             return new RevisionIdIterator( *this );
00192         }
00193 
00194     private:
00195 
00196         BdbRef(CdbBdbSRevCollectionP) _revCollectionRef;
00197         bool                          _appendTopmostFlag;
00198 
00199         bool _isValid;
00200         bool _hasEverBeenAdvanced;
00201 
00202         BdbTime _value;
00203 
00204         CdbItr<BdbTime> _revItr;
00205 
00206       // This flag is used to trigger appending the topmost revision (if required
00207       // by the corresponding iterator parameter) by the end of the sequence when
00208       // the original collection of revisions is exausted.
00209 
00210         bool _thereIsTopmostToAppend;
00211     };
00212 
00213     /////////////////////////////////
00214     // Class: RevisionNameIterator //
00215     /////////////////////////////////
00216 
00217     class RevisionNameIterator : public CdbItr<const char*>::InterfaceType {
00218 
00219     private:
00220 
00221       /// The default constructor (NOT IMPLEMENTED)
00222 
00223         RevisionNameIterator( );
00224 
00225       /// The assignment operator (NOT IMPLEMENTED)
00226 
00227         RevisionNameIterator& operator=( const RevisionNameIterator& theItr );
00228 
00229     protected:
00230 
00231       /// The copy constructor
00232       /**
00233         * The only reason why we have it implemented is because it's needed
00234         * to implement the clone method.
00235         *
00236         * @see RevisionNameIterator::clone()
00237         */
00238         RevisionNameIterator( const RevisionNameIterator& theItr ) :
00239             _revCollectionRef      (theItr._revCollectionRef),
00240             _appendTopmostFlag     (theItr._appendTopmostFlag),
00241             _isValid               (theItr._isValid),
00242             _hasEverBeenAdvanced   (theItr._hasEverBeenAdvanced),
00243             _value                 (theItr._value),
00244             _revItr                (theItr._revItr),
00245             _thereIsTopmostToAppend(theItr._thereIsTopmostToAppend)
00246         { }
00247 
00248     public:
00249 
00250       /// The normal constructor
00251 
00252         RevisionNameIterator( const BdbRef(CdbBdbSRevCollectionP)& theRef,
00253                               bool                                 appendTopmostFlag ) :
00254             _revCollectionRef      (theRef),
00255             _appendTopmostFlag     (appendTopmostFlag),
00256             _isValid               (false),
00257             _hasEverBeenAdvanced   (false),
00258             _value                 (""),
00259             _revItr                (0),
00260             _thereIsTopmostToAppend(appendTopmostFlag)
00261         {
00262             assert( !BdbIsNull(theRef));
00263         }
00264 
00265       /// The destructor
00266 
00267         virtual ~RevisionNameIterator( )
00268         { }
00269 
00270       /// Reset an iterator to its initial state.
00271       /**
00272         * This implements the corresponding method of the base class.
00273         *
00274         * @see CdbIItr::reset
00275         * @see CdbStatus
00276         */
00277         virtual CdbStatus reset( )
00278         {
00279             _isValid             = false;
00280             _hasEverBeenAdvanced = false;
00281 
00282             _thereIsTopmostToAppend = _appendTopmostFlag;
00283 
00284             return CdbStatus::Success;
00285         }
00286 
00287       /// Advance an iterator to the next position.
00288       /**
00289         * This implements the corresponding method of the base class.
00290         *
00291         * @see CdbIItr::next()
00292         */
00293         virtual bool next( )
00294         {
00295             if( !_isValid ) {
00296 
00297                 if( !_hasEverBeenAdvanced ) {
00298                     _hasEverBeenAdvanced = true;
00299 
00300                     _revItr = _revCollectionRef->iterator_names( );
00301 
00302                 } else {
00303 
00304                   // This iterator should remain at "PAST_LAST_ELEMENT" state. The only way
00305                   // to get out of this state is to to call ::reset() method.
00306 
00307                     return false;
00308                 }
00309             }
00310             if( _isValid && _revItr.isValid( ) && _revItr.next( )) {
00311 
00312               // We keep iterating in the valid state
00313 
00314                 _value = _revItr.value( );
00315 
00316             } else if( !_isValid && _revItr.next( )) {
00317 
00318               // The first attemp to advance an iterator since it was initialized
00319 
00320                 _value   = _revItr.value( );
00321                 _isValid = true;
00322 
00323             } else {
00324 
00325               // It does not matter what was the previous state of the iterator
00326               // before since the only source of information would be the topmost revision
00327               // if any.
00328 
00329                 if( _thereIsTopmostToAppend ) {
00330                     _thereIsTopmostToAppend = false;
00331 
00332                     _value   = "<topmost>";
00333                     _isValid = true;
00334 
00335                 } else {
00336 
00337                   // Now we've got into the "PAST_LAST_ELEMENT" state.
00338 
00339                     _isValid = false;
00340                 }
00341             }
00342             return _isValid;
00343         }
00344 
00345       /// Obtain the currently reffered value.
00346       /**
00347         * This implements the corresponding method of the base class.
00348         *
00349         * @see CdbIItr::value()
00350         * @see CdbIItr::ValueType
00351         *
00352         * @return the current value the iterator is set on
00353         */
00354         virtual ValueType value( )
00355         {
00356             if( _isValid ) {
00357                 return _value.c_str( );
00358             }
00359 
00360           // Invalid revision name.
00361 
00362             return 0;
00363         }
00364 
00365       /// Check if an iterator is valid.
00366       /**
00367         * This implements the corresponding method of the base class.
00368         *
00369         * @see CdbIItr::isValid()
00370         */
00371         virtual bool isValid( )
00372         {
00373             return _isValid;
00374         }
00375 
00376       /// Make a clone of itself
00377       /**
00378         * @see CdbIItr::clone()
00379         */
00380         virtual InterfaceType* clone( ) const
00381         {
00382             return new RevisionNameIterator( *this );
00383         }
00384 
00385     private:
00386 
00387         BdbRef(CdbBdbSRevCollectionP) _revCollectionRef;
00388         bool                          _appendTopmostFlag;
00389 
00390         bool _isValid;
00391         bool _hasEverBeenAdvanced;
00392 
00393         std::string _value;
00394 
00395         CdbItr<const char*> _revItr;
00396 
00397       // This flag is used to trigger appending the topmost revision (if required
00398       // by the corresponding iterator parameter) by the end of the sequence when
00399       // the original collection of revisions is exausted.
00400 
00401         bool _thereIsTopmostToAppend;
00402     };
00403 
00404     /////////////////////////////////////
00405     // Class: CombinedIntervalIterator //
00406     /////////////////////////////////////
00407 
00408     class CombinedIntervalIterator : public CdbItr<CdbBdbSCi>::InterfaceType {
00409 
00410     private:
00411 
00412       /// The default constructor (NOT IMPLEMENTED)
00413 
00414         CombinedIntervalIterator( );
00415 
00416       /// The assignment operator (NOT IMPLEMENTED)
00417 
00418         CombinedIntervalIterator& operator=( const CombinedIntervalIterator& theItr );
00419 
00420     protected:
00421 
00422       /// The copy constructor
00423       /**
00424         * The only reason why we have it implemented is because it's needed
00425         * to implement the clone method.
00426         *
00427         * @see CombinedIntervalIterator::clone()
00428         */
00429         CombinedIntervalIterator( const CombinedIntervalIterator& theItr ) :
00430             _viCollectionH      (theItr._viCollectionH),
00431             _oiCollectionH      (theItr._oiCollectionH),
00432             _beginTime          (theItr._beginTime),
00433             _endTime            (theItr._endTime),
00434             _isValid            (theItr._isValid),
00435             _hasEverBeenAdvanced(theItr._hasEverBeenAdvanced),
00436             _value              (theItr._value),
00437             _viItr              (theItr._viItr)
00438         { }
00439 
00440     public:
00441 
00442       /// The normal constructor
00443 
00444         CombinedIntervalIterator( const BdbRef(CdbBdbSViCollectionP)& theViCollectionRef,
00445                                   const BdbRef(CdbBdbSOiCollectionP)& theOiCollectionRef,
00446                                   const BdbTime&                      theBeginTime,
00447                                   const BdbTime&                      theEndTime ) :
00448             _viCollectionH      (theViCollectionRef),
00449             _oiCollectionH      (theOiCollectionRef),
00450             _beginTime          (theBeginTime),
00451             _endTime            (theEndTime),
00452             _isValid            (false),
00453             _hasEverBeenAdvanced(false)
00454         {
00455             assert( !BdbIsNull(theViCollectionRef));
00456             assert( !BdbIsNull(theOiCollectionRef));
00457         }
00458 
00459       /// The destructor
00460 
00461         virtual ~CombinedIntervalIterator( )
00462         { }
00463 
00464       /// Reset an iterator to its initial state.
00465       /**
00466         * This implements the corresponding method of the base class.
00467         *
00468         * @see CdbIItr::reset
00469         * @see CdbStatus
00470         */
00471         virtual CdbStatus reset( )
00472         {
00473             _isValid             = false;
00474             _hasEverBeenAdvanced = false;
00475 
00476             return CdbStatus::Success;
00477         }
00478 
00479       /// Try advancing the input iterator
00480 
00481         bool tryNext( )
00482         {
00483             bool result = false;
00484             do {
00485 
00486               // Advance the VI iterator to the next interval
00487 
00488                 if( !_viItr.next( )) break;
00489 
00490                 CdbBdbSVi vi = _viItr.value( );
00491 
00492               // Check for the end condition requering that the begin time
00493               // of found visible interval fall into the iterator's validity limits.
00494               //
00495               // Either of two scenarious:
00496               //
00497               // - begin time of the interval #1 falls into Interval #2
00498               // - begin time of the interval #2 falls into Interval #1
00499               //
00500               // In other "words":
00501               //
00502               //   #1    [.....)
00503               //   #2   [....)
00504               //
00505               // or:
00506               //
00507               //   #1  [.....)
00508               //   #2    [.....)
00509 /*
00510  * DEBUG
00511                 cout << "_beginTime = " << _beginTime.getGmtSec( ) << "." << _beginTime.getGmtNsec( ) << endl
00512                      << "vi.begin   = " << vi.begin.getGmtSec  ( ) << "." << vi.begin.getGmtNsec  ( ) << endl
00513                      << "vi.end     = " << vi.end.getGmtSec    ( ) << "." << vi.end.getGmtNsec    ( ) << endl
00514                      << "_endTime   = " << _endTime.getGmtSec  ( ) << "." << _endTime.getGmtNsec  ( ) << endl;
00515 */
00516                 if( ! ((( _beginTime <= vi.begin   ) && ( vi.begin   < _endTime )) ||
00517                        (( vi.begin   <= _beginTime ) && ( _beginTime < vi.end   )))) break;
00518 
00519               // Construct the current value
00520               //
00521               // NOTE: We're not changing the "visibility" of found interval
00522               //       even if it partially falls beyond the limits of the current
00523               //       iterator. It's up to the application's logic to catch this
00524               //       problem. See the corresponding desciption in the client
00525               //       class's method.
00526 
00527                 if( 0 == vi.value ) {
00528 
00529                   // This is a "hole" in the visible timeline because there is
00530                   // no any object for the duration of foudn visible interval.
00531 
00532                     _value = CdbBdbSCi( vi.begin,
00533                                         vi.end );
00534                 } else {
00535 
00536                   // Ther emust be a valid object. Get the "original" interval
00537                   // describing it.
00538 
00539                     CdbBdbSOi oi;
00540                     BdbTime   beginOfDuration;  // not used
00541                     BdbTime   endOfDuration;    // not used
00542 
00543                     if( CdbStatus::Success != _oiCollectionH->find( vi.value,
00544                                                                     oi,
00545                                                                     beginOfDuration,
00546                                                                     endOfDuration )) {
00547 
00548                         assert( 0 );    // FATAL ERROR: inconsistent "visible"
00549                                         //              and "original" collections.
00550                         break;
00551                     }
00552                     _value = CdbBdbSCi( vi.begin,
00553                                         vi.end,
00554                                         oi );
00555                 }
00556 
00557               // Done.
00558 
00559                 result = true;
00560 
00561             } while( false );
00562 
00563             return result;
00564         }
00565 
00566       /// Advance an iterator to the next position.
00567       /**
00568         * This implements the corresponding method of the base class.
00569         *
00570         * @see CdbIItr::next()
00571         */
00572         virtual bool next( )
00573         {
00574             if( !_isValid ) {
00575 
00576                 if( !_hasEverBeenAdvanced ) {
00577                     _hasEverBeenAdvanced = true;
00578 
00579                     _viItr = _viCollectionH->iterator( _beginTime );
00580 
00581                 } else {
00582 
00583                   // This iterator should remain at "PAST_LAST_ELEMENT" state. The only way
00584                   // to get out of this state is to to call ::reset() method.
00585 
00586                     return false;
00587                 }
00588             }
00589             if( !_isValid ) {
00590 
00591               // The first attemp to advance an iterator since it was initialized
00592 
00593                 _isValid = tryNext( );
00594 
00595             } else if( _isValid && _viItr.isValid( )) {
00596 
00597               // We keep iterating in the valid state of the input iterator
00598 
00599                 _isValid = tryNext( );
00600 
00601             } else {
00602 
00603               // Now we've got into the "PAST_LAST_ELEMENT" state.
00604 
00605                _isValid = false;
00606             }
00607             return _isValid;
00608         }
00609 
00610       /// Obtain the currently reffered value.
00611       /**
00612         * This implements the corresponding method of the base class.
00613         *
00614         * @see CdbIItr::value()
00615         * @see CdbIItr::ValueType
00616         *
00617         * @return the current value the iterator is set on
00618         */
00619         virtual ValueType value( )
00620         {
00621             if( ! _isValid ) assert( 0 );
00622             return _value;
00623         }
00624 
00625       /// Check if an iterator is valid.
00626       /**
00627         * This implements the corresponding method of the base class.
00628         *
00629         * @see CdbIItr::isValid()
00630         */
00631         virtual bool isValid( )
00632         {
00633             return _isValid;
00634         }
00635 
00636       /// Make a clone of itself
00637       /**
00638         * @see CdbIItr::clone()
00639         */
00640         virtual InterfaceType* clone( ) const
00641         {
00642             return new CombinedIntervalIterator( *this );
00643         }
00644 
00645     private:
00646 
00647       // Parameters of the iterator
00648 
00649         BdbHandle(CdbBdbSViCollectionP) _viCollectionH;
00650         BdbHandle(CdbBdbSOiCollectionP) _oiCollectionH;
00651 
00652         BdbTime _beginTime;
00653         BdbTime _endTime;
00654 
00655       // The state of the iterator
00656 
00657         bool _isValid;
00658         bool _hasEverBeenAdvanced;
00659 
00660         CdbBdbSCi _value;
00661 
00662         CdbBdbSViCollectionP::IteratorOfIntervals _viItr;
00663     };
00664 };
00665 
00666 /////////////////////////////
00667 // Class: CdbBdbSMetaDataP //
00668 /////////////////////////////
00669 
00670 CdbBdbSMetaDataP::CdbBdbSMetaDataP( const BdbTime& theMinValidityTime,
00671                                     const BdbTime& theMaxValidityTime,
00672                                     const BdbTime& theMinInsertionTime ) :
00673     _minValidityTime(theMinValidityTime),
00674     _maxValidityTime(theMaxValidityTime),
00675     _minInsertionTime(theMinInsertionTime),
00676     _maxInsertionTime(BdbTime::plusInfinity),
00677     _modified(theMinInsertionTime)
00678 {
00679     _originalCollectionRef = new( ooThis( )) CdbBdbSOiCollectionP( );
00680     _topmostRevisionRef    = new( ooThis( )) CdbBdbSRevisionP( );
00681     _revCollectionRef      = new( ooThis( )) CdbBdbSRevCollectionP( );
00682 }
00683 
00684 CdbBdbSMetaDataP::~CdbBdbSMetaDataP( ) 
00685 {
00686     BdbDelete( _originalCollectionRef );
00687     BdbDelete( _topmostRevisionRef );
00688     BdbDelete( _revCollectionRef );
00689 }
00690 
00691 BdbTime
00692 CdbBdbSMetaDataP::minValidity ( ) const
00693 {
00694     return _minValidityTime;
00695 }
00696 
00697 BdbTime
00698 CdbBdbSMetaDataP::maxValidity ( ) const
00699 {
00700     return _maxValidityTime;
00701 }
00702 
00703 BdbTime
00704 CdbBdbSMetaDataP::minInsertion( ) const
00705 {
00706     return _minInsertionTime;
00707 }
00708 
00709 BdbTime
00710 CdbBdbSMetaDataP::maxInsertion( ) const
00711 {
00712     return _maxInsertionTime;
00713 }
00714 
00715 BdbRef( CdbBdbSOiCollectionP )
00716 CdbBdbSMetaDataP::originaIntervalsCollection( ) const
00717 {
00718     return _originalCollectionRef;
00719 }
00720 
00721 BdbTime
00722 CdbBdbSMetaDataP::modified( ) const
00723 {
00724     return _modified;
00725 }
00726 
00727 CdbStatus
00728 CdbBdbSMetaDataP::close( const BdbTime& theMaxInsertionTime,
00729                          const char*    theNewRevisionName,
00730                          const BdbTime& theNewRevisionCreationTime,
00731                          const char*    theNewRevisionDescription )
00732 {
00733     ooUpdate( );
00734 
00735     const char* errorStr = "CdbBdbSMetaDataP::close() -- ERROR";
00736 
00737     CdbStatus result = CdbStatus::Error;
00738     do {
00739 
00740       // Verify parameters
00741 
00742         if( CdbStatus::Success != verifyInsertionTime( theMaxInsertionTime )) {
00743             cout << errorStr << endl
00744                  << "    Specified insertion time is not correct." << endl
00745                  << "    See details above." << endl;
00746             break;
00747         }
00748         if( theMaxInsertionTime <= _modified ) {
00749             cout << errorStr << endl
00750                  << "    Specified insertion time is not correct." << endl
00751                  << "    Current operation requires this time to be strictly greater than" << endl
00752                  << "    the most recent modification time of the MetaData object." << endl
00753                  << "        PASSED MAX.INSERTION TIME: " << theMaxInsertionTime << endl
00754                  << "        CURRENT MODIFICATION TIME: " << _modified << endl;
00755             break;
00756         }
00757 
00758       // Check if there is a revision with the current value of the modification
00759       // time.
00760 
00761         BdbRef(CdbBdbSRevisionP) rRef;
00762         if( CdbStatus::Success != _revCollectionRef->find( _modified,
00763                                                            rRef )) {
00764 
00765           // Then we also require that revision parameters were passed.
00766 
00767             if(( 0 == theNewRevisionName ) ||
00768                ( BdbTime::minusInfinity == theNewRevisionCreationTime ) ||
00769                ( 0 == theNewRevisionDescription )) {
00770                 cout << errorStr << endl
00771                      << "    Invalid revision parameters passed to the procedure when" << endl
00772                      << "    a final revision is about to be created. This revision has" << endl
00773                      << "    be created before closing the MetaData object." << endl;
00774                 break;
00775             }
00776 
00777           // Create the one.
00778 
00779             if( CdbStatus::Success != createRevision( _modified,
00780                                                       theNewRevisionName,
00781                                                       theNewRevisionCreationTime,
00782                                                       theNewRevisionDescription )) {
00783                 cout << errorStr << endl
00784                      << "    Failed to create new revision before closing the MetaData object." << endl;
00785                 break;
00786             }
00787         }
00788 
00789       // Destroy the topmost revision.
00790 
00791         BdbDelete(_topmostRevisionRef);
00792         _topmostRevisionRef = 0;
00793 
00794       // Set up the time.
00795 
00796         _maxInsertionTime = theMaxInsertionTime;
00797 
00798       // Done.
00799 
00800         result = CdbStatus::Success;
00801 
00802     } while( false );
00803 
00804     return result;
00805 }
00806 
00807 CdbStatus
00808 CdbBdbSMetaDataP::insert( const CdbBdbSOi& theInterval )
00809 {
00810     ooUpdate( );
00811 
00812     const char* errorStr = "CdbBdbSMetaDataP::insert() -- ERROR";
00813     const char* fatalStr = "CdbBdbSMetaDataP::insert() -- FATAL INTERNAL ERROR!!!";
00814 
00815     CdbStatus result = CdbStatus::Error;
00816     do {
00817 
00818       // Verify parameters.
00819 
00820         if( CdbStatus::Success != verifyInsertionTime( theInterval.inserted )) {
00821             cout << errorStr << endl
00822                  << "    The insertion time of the passed interval is not correct." << endl
00823                  << "    See details above." << endl;
00824             break;
00825         }
00826         if( BdbIsNull( theInterval.object )) {
00827             cout << errorStr << endl
00828                  << "    The passed interval points to 0-0-0-0 condition object." << endl
00829                  << "    This interval can't be inserted." << endl;
00830             break;
00831         }
00832         if( theInterval.inserted < _modified ) {
00833             cout << errorStr << endl
00834                  << "    The insertion time of the passed interval is not correct." << endl
00835                  << "    Current operation requires this time to be greater or equal to" << endl
00836                  << "    the most recent modification time of the MetaData object." << endl
00837                  << "        PASSED INSERTION TIME:     " << theInterval.inserted << endl
00838                  << "        CURRENT MODIFICATION TIME: " << _modified << endl;
00839             break;
00840         }
00841 
00842       // Calculate the crossection of the passed interval with the "validity"
00843       // window of the current metadata object. The resulting interval should
00844       // not have 0 length.
00845 
00846         CdbBdbSOi oiInterval = theInterval;
00847 
00848         if( oiInterval.begin < _minValidityTime ) oiInterval.begin = _minValidityTime;
00849         if( oiInterval.end   > _maxValidityTime ) oiInterval.end   = _maxValidityTime;
00850 
00851         if( oiInterval.begin >= oiInterval.end ) {
00852             cout << errorStr << endl
00853                  << "    The passed interval does not have any cross-section" << endl
00854                  << "    with the validity window of the metadata object." << endl
00855                  << "    This interval can't be inserted." << endl;
00856             break;
00857         }
00858 
00859       // Insert into the "original" collection"
00860 
00861         d_ULong oiIdx;      // The subsequent operation will set up this value
00862                             // so it can be used to register new interval in
00863                             // the "visible" intervals collection.
00864 
00865         if( CdbStatus::Success != _originalCollectionRef->insert( oiInterval, oiIdx )) {
00866             cout << errorStr << endl
00867                  << "    Failed to register the interval in the 'original' intervals collection." << endl;
00868             break;
00869         }
00870 
00871       // Insert into the "visible" intervals collection of the "TOPMOST" revision.
00872 
00873         if( CdbStatus::Success != _topmostRevisionRef->collection( )->insert( oiInterval.begin,
00874                                                                               oiInterval.end,
00875                                                                               oiIdx )) {
00876             cout << fatalStr << endl
00877                  << "    Failed to register the interval in the 'visible' intervals collection" << endl
00878                  << "    of the 'TOPMOST' revision. This puts the metadata object into" << endl
00879                  << "    an inconsistent state." << endl;
00880 
00881             assert( 0 );    // FATAL INTERNAL ERROR!!!!
00882 
00883             break;
00884         }
00885 
00886       // Update modification time
00887 
00888         _modified = theInterval.inserted;
00889 
00890       // Done.
00891 
00892         result = CdbStatus::Success;
00893 
00894     } while( false );
00895 
00896     return result;
00897 }
00898 
00899 CdbStatus
00900 CdbBdbSMetaDataP:: rebuild( CdbBdbSRebuildAction* theRebuildAction,
00901                             const BdbTime&        theBeginTime,
00902                             const BdbTime&        theEndTime )
00903 {
00904     ooUpdate( );
00905 
00906     const char* errorStr = "CdbBdbSMetaDataP::rebuild() -- ERROR";
00907     const char* fatalStr = "CdbBdbSMetaDataP::rebuild() -- FATAL INTERNAL ERROR!!!";
00908 
00909     CdbStatus result = CdbStatus::Error;
00910     do {
00911 
00912       // Verify the parameters
00913 
00914         if( theBeginTime >= theEndTime ) {
00915             cout << errorStr << endl
00916                  << "    Incorrect validity time range passed to the procedure." << endl;
00917             break;
00918         }
00919 
00920       // Verify if there is non no-topmost revision in the metadata object.
00921       //
00922       // NOTES:
00923       //
00924       //   (1) We'll _NOT_ allow the current operation if there is at least one revision
00925       //       (except the 'TOPMOST' one) created at or after the specified "begin insertion"
00926       //       time.
00927       //
00928       //   (2) Revisions created strictly _before_ must be okay since "visible intervals"
00929       //       of the revisions are relying on numbers (indexes) of "original intervals"
00930       //       in the "original intervals collections", which itself has a fixed (continous)
00931       //       sequence of numbers starting from 1 (o is reserved for special purposes).
00932       //       It means that original intervals created before the specified "begin time"
00933       //       will get the same numbers in the recretead collection as they have it in
00934       //       the older one.
00935 
00936         {
00937             CdbItr<BdbTime> rItr;
00938             if( CdbStatus::Success != revisionIdIterator( rItr )) {
00939                 cout << errorStr << endl
00940                      << "    Failed to get an iterator of revisions for the current metadata object." << endl;
00941                 break;
00942             }
00943 
00944             bool failed = false;
00945 
00946             while( rItr.next( )) {
00947                 if( BdbTime::plusInfinity != rItr.value( )) {
00948                     if( rItr.value( ) >= theBeginTime ) {
00949                         cout << errorStr << endl
00950                              << "    A non-topmost revision created at or after the specifid begin time" << endl
00951                              << "    passed to the procedure has been detected:" << endl
00952                              << "        REVISION ID : " << rItr.value( ).getGmtSec( ) << "." << rItr.value( ).getGmtNsec( ) << " " << rItr.value( ) << endl
00953                              << "        BEGIN TIME  : " <<  theBeginTime.getGmtSec( ) << "." <<  theBeginTime.getGmtNsec( ) << " " << theBeginTime  << endl
00954                              << "    The operation is not allowed for this metadata." << endl;
00955                         failed = true;
00956                         break;
00957                     }
00958                 }
00959             }
00960             if( failed ) break;
00961         }
00962 
00963       // Verify if the current metadata object is still open
00964 
00965         if( BdbTime::plusInfinity != _maxInsertionTime ) {
00966             cout << errorStr << endl
00967                  << "    The current metadata object is in the 'closed' state." << endl
00968                  << "    The operation is not allowed for this metadata." << endl;
00969             break;
00970         }
00971 
00972 
00973       // Reset the current state of the metadata object and keep an old collection
00974       // of original intervals aside for the duratiuon of copying. The current state of
00975       // the metadata object will be updated when we'll be evaluating and copying
00976       // intervals from the input collection of original intervals.
00977 
00978       // 1: Reset the modification time back to the begin time of the "insertion"
00979       //    timeline window of the metadata. This modification time will be updated later on
00980       //    when copying original interval from the current collection into the output one.
00981 
00982         _modified = _minInsertionTime;
00983 
00984       // 2: Remember the old (input) collection of original intervals and create its
00985       //    replacement (the output one). The old collection will be destroyed when we'll
00986       //    finish rebuilding.
00987 
00988         BdbHandle( CdbBdbSOiCollectionP ) inputOriginalCollectionH = _originalCollectionRef;
00989         _originalCollectionRef = new( ooThis( )) CdbBdbSOiCollectionP( );
00990 
00991       // 3: Reset topmost revision which are going to be populated in a course of rebuilding.
00992 
00993         BdbDelete(_topmostRevisionRef);
00994         _topmostRevisionRef = new( ooThis( )) CdbBdbSRevisionP( );
00995 
00996       // 4: Keep a collection of non-topmost revisions since it's not going to be affected
00997       //    by the current operation (see the "Verify" section above for details).
00998       //
00999       //    IMPORTANT: As a temporary measure, to avoid confusing the ::insert()
01000       //               method we will create an empty temporary collection and preserve
01001       //               the current one. Then, when we'll finish updating intervals
01002       //               then we'll put the current collection back.
01003 
01004         BdbRef( CdbBdbSRevCollectionP ) savedRevCollectionRef = _revCollectionRef;
01005         _revCollectionRef = new( ooThis( )) CdbBdbSRevCollectionP( );
01006 
01007       // Scan input collections and fill the output ones using user supplied action object.
01008       //
01009       // NOTE: We're scanning the input collection begining from an interval
01010       //       with 1 index rather than with 0, which has a special meaning.
01011 
01012         bool failed = false;
01013 
01014         d_ULong num = inputOriginalCollectionH->size( );
01015         for( d_ULong i = 1; i < num; ++i ) {
01016 
01017           // Get next input interval
01018 
01019             CdbBdbSOi oi;
01020 
01021             BdbTime beginOfDuration;  // not used, but required by the API
01022             BdbTime endOfDuration;    // ditto
01023 
01024             if( CdbStatus::Success != inputOriginalCollectionH->find( i,
01025                                                                       oi,
01026                                                                       beginOfDuration,
01027                                                                       endOfDuration )) {
01028                 cout << fatalStr << endl
01029                      << "    Failed to obtain an original interval with index " << i << " from the current collection." << endl
01030                      << "    The collection may be corrupted." << endl;
01031 
01032                 assert( 0 );    // FATAL INTERNAL ERROR!!!!
01033 
01034                 failed = true;
01035                 break;
01036             }
01037 
01038           // If this interval is in the specified insertion time window then let a user
01039           // do decide on what to do with this interval. Otherwise simply copy it into the output
01040           // collections.
01041 
01042             CdbBdbSRebuildAction::ActionType action = CdbBdbSRebuildAction::ACTION_COPY;
01043 
01044             if(( theBeginTime <= oi.inserted ) && ( oi.inserted < theEndTime )) {
01045 
01046                 action = theRebuildAction->userAction( oi );
01047                 if( CdbBdbSRebuildAction::ACTION_ERROR == action ) {
01048 
01049                     cout << errorStr << endl
01050                          << "    User action has failed when processing an original interval." << endl;
01051 
01052                     failed = true;
01053                     break;
01054                 }
01055             }
01056 
01057           // Copy the interval into the output collections and register it in
01058           // the topmost revision.
01059           //
01060           // NOTE: We're using a local copy of the original interval, which
01061           //       may have been modified by a user action.
01062 
01063             if( CdbBdbSRebuildAction::ACTION_COPY == action ) {
01064                 if( CdbStatus::Success != insert( oi )) {
01065                     cout << errorStr << endl
01066                          << "    Failed to store an original interval in the rebuilt collection." << endl;
01067                     failed = true;
01068                     break;
01069                 }
01070             }
01071         }
01072         if( failed ) break;
01073 
01074       // Replace the temporary collection of revisions with the saved one.
01075       //
01076       // Then update the modification time to the most recent one, which would go either from
01077       // the collection of original intervals or from the latest revision.
01078 
01079         BdbDelete(_revCollectionRef);
01080         _revCollectionRef = savedRevCollectionRef;
01081 
01082         BdbTime recentlyModifiedTime = recentlyModified( );
01083         if( recentlyModifiedTime > _modified ) _modified = recentlyModifiedTime;
01084 
01085       // Got rid of the input original collection. We don't need it any more since
01086       // we've moved all relevant data into a right places.
01087 
01088         BdbDelete( inputOriginalCollectionH );
01089 
01090       // Done
01091 
01092         result = CdbStatus::Success;
01093 
01094     } while( false );
01095     
01096     return result;
01097 }
01098 
01099 CdbStatus
01100 CdbBdbSMetaDataP::repoint( CdbBdbObjectClone&         theObjectCloningTool,
01101                            CdbBdbCache<ooRef(ooObj)>& theTranslationDictionary )
01102 {
01103     const char* fatalStr = "CdbBdbSMetaDataP::repoint() -- FATAL INTERNAL ERROR!!!";
01104     const char* errorStr = "CdbBdbSMetaDataP::repoint() -- ERROR";
01105 
01106     CdbStatus result = CdbStatus::Error;
01107     do {
01108 
01109       // Scan the original collection and modify its elements
01110 
01111         bool failed = false;
01112 
01113         d_ULong num = _originalCollectionRef->size( );
01114         for( d_ULong i = 1; i < num; ++i ) {
01115 
01116           // Get next input interval
01117 
01118             CdbBdbSOi oi;
01119 
01120             BdbTime beginOfDuration;  // not used, but required by the API
01121             BdbTime endOfDuration;    // ditto
01122 
01123             if( CdbStatus::Success != _originalCollectionRef->find( i,
01124                                                                     oi,
01125                                                                     beginOfDuration,
01126                                                                     endOfDuration )) {
01127                 cout << fatalStr << endl
01128                      << "    Failed to obtain an original interval with index " << i << " from the current collection." << endl
01129                      << "    The collection may be corrupted." << endl;
01130 
01131                 assert( 0 );    // FATAL INTERNAL ERROR!!!!
01132 
01133                 failed = true;
01134                 break;
01135             }
01136 
01137           // Skip this intervak if the object is 0-0-0-0
01138 
01139             if( BdbIsNull( oi.object )) continue;
01140 
01141           // Clone the object.
01142 
01143             ooHandle(ooObj) oldH = oi.object;
01144             ooHandle(ooObj) newH = 0;
01145 
01146             if( !theObjectCloningTool.clone( oldH,
01147                                              newH )) {
01148 
01149                 cout << errorStr << endl
01150                      << "    Failed to clone an old object from the original interval with index " << i << " from the current collection." << endl
01151                      << "    The collection may be corrupted. Or there may be some other problem with the federation." << endl;
01152 
01153                 failed = true;
01154                 break;
01155             }
01156 
01157           // Repoint the oid object in the 'original' interval with the new objects
01158           // then update the original collection at the current index.
01159 
01160             ooRef(ooObj) newObjectRef = newH;               // Convert to the reference first
01161             oi.object = (BdbRef(BdbObject)) newObjectRef;   // Then cust and repoint
01162 
01163             if( CdbStatus::Success != _originalCollectionRef->replace( oi,
01164                                                                        i )) {
01165                 cout << errorStr << endl
01166                      << "    Failed to replace the original interval with updated one at index " << i << " of the current collection." << endl;
01167 
01168                 failed = true;
01169                 break;
01170             }
01171 
01172           // Update the dictionary
01173           //
01174           // NOTE: The logic of the update also includes a consistency check to make sure
01175           //       that the cloning algorithm is not broken (at least) in the scope of
01176           //       of the current metadata object. So, for example, we want to assure
01177           //       that there is a unique new OID for each old one.
01178 
01179             ooRef(ooObj) oldObjectRef = oldH;   // Convert to the reference first
01180 
01181             ooRef(ooObj) valueRef = theTranslationDictionary.findObject( oldObjectRef );
01182             if( 0 == valueRef ) {
01183                 theTranslationDictionary.addObject( oldObjectRef,
01184                                                     newObjectRef );
01185             } else {
01186                 if( valueRef != newObjectRef ) {
01187 
01188                     cout << fatalStr << endl
01189                          << "    Dangerous inconsistency found in the data structures used by" << endl
01190                          << "    the repointing operation. The resulting metadata object may be useless." << endl
01191                          << "    This may be an indication of a serious bug in the caller's code." << endl;
01192 
01193                     assert( 0 );    // FATAL INTERNAL ERROR!!!!
01194 
01195                     failed = true;
01196                     break;
01197                 }
01198             }
01199         }
01200         if( failed ) break;
01201 
01202       // Done
01203 
01204         result = CdbStatus::Success;
01205 
01206     } while( false );
01207     
01208     return result;
01209 }
01210 
01211 
01212 CdbStatus
01213 CdbBdbSMetaDataP::findByRevision( const BdbTime& theRevisionId,
01214                                   const BdbTime& theValidityTime,
01215                                   CdbBdbSOi&     theOriginalInterval,
01216                                   BdbTime&       theBeginOfVisiblePeriod,
01217                                   BdbTime&       theEndOfVisiblePeriod ) const
01218 {
01219     const char* errorStr = "CdbBdbSMetaDataP::findByRevision() -- ERROR";
01220     const char* fatalStr = "CdbBdbSMetaDataP::findByRevision() -- FATAL INTERNAL ERROR!!!";
01221 
01222     CdbStatus result = CdbStatus::Error;
01223     do {
01224 
01225       // This is required by the public contract of the method.
01226 
01227         theBeginOfVisiblePeriod = _minValidityTime;
01228         theEndOfVisiblePeriod   = _maxValidityTime;
01229 
01230       // Verify the parameters
01231 
01232         if(( theValidityTime <  _minValidityTime ) ||
01233            ( theValidityTime >= _maxValidityTime)) {
01234             cout << errorStr << endl
01235                  << "    The passed validity time is out of the validity window" << endl
01236                  << "    of the current metadata object." << endl;
01237             break;
01238         }
01239 
01240       // Get to the specified revision, and then to the collection
01241       // of "visible" intervals.
01242 
01243         BdbRef( CdbBdbSRevisionP ) revisionRef;
01244         if( BdbTime::plusInfinity == theRevisionId ) {
01245             if( BdbIsNull(_topmostRevisionRef)) {
01246                 cout << errorStr << endl
01247                      << "    The topmost revision is not available in this Meta Data collection" << endl
01248                      << "    because the collection is closed." << endl;
01249                 break;
01250             }
01251             revisionRef = _topmostRevisionRef;
01252         } else {
01253             if( CdbStatus::Success != _revCollectionRef->find( theRevisionId, revisionRef )) {
01254                 cout << errorStr << endl
01255                      << "    Specified revision was not found in the collection." << endl
01256                      << "        PASSED REVISION ID: " << theRevisionId << endl;
01257                 break;
01258             }
01259         }
01260         BdbRef( CdbBdbSViCollectionP ) collectionRef = revisionRef->collection( );
01261 
01262       // Find a "visible" interval through the "visible" collection.
01263       //
01264       // IMPORTANT NOTE:
01265       //
01266       //     This operation if successfull will return us a short description
01267       //     of visible interval. The "successful" may also mean 0 index. No matter what
01268       //     is the value of the original interval's index carried by the visible interval
01269       //     still we have very important information about the visible validity range of
01270       //     the found index. If this ois 0 index the we have the visible validity interval
01271       //     of a 'hole', and if it's not then its the interval of an actual object.
01272       //
01273       //     Assigning the correct value to the visible validity interval is required
01274       //     by the contract of the current method.
01275 
01276         CdbBdbSVi viInterval;
01277 
01278         if( ! collectionRef->find( viInterval, theValidityTime )) {
01279 
01280             assert( 0 );    // Inconsistent TimeLine. All range of the insertion time
01281                             // must be covered.
01282             break;
01283         }
01284 
01285         theBeginOfVisiblePeriod = viInterval.begin;
01286         theEndOfVisiblePeriod   = viInterval.end;
01287 
01288         d_ULong oiIdx = viInterval.value;       // Get to the index of the 'original' interval
01289         if( 0 == oiIdx ) {
01290             result = CdbStatus::NotFound;
01291             break;
01292         }
01293 
01294       // Extract the "original" interval information and setup the values
01295       // of parameters to be returned.
01296 
01297         BdbTime beginOfDurationPeriod( 0 );     // Don't need this information
01298         BdbTime endOfDurationPeriod  ( 0 );     // Don't need this information
01299 
01300         if( CdbStatus::Success != _originalCollectionRef->find( oiIdx,
01301                                                                 theOriginalInterval,
01302                                                                 beginOfDurationPeriod,
01303                                                                 endOfDurationPeriod )) {
01304             cout << fatalStr << endl
01305                  << "    The collection of 'visible' intervals does not match" << endl
01306                  << "    the collection of 'original' intervals." << endl;
01307 
01308             assert( 0 );    // FATAL INTERNAL ERROR!!!!
01309 
01310             break;
01311         }
01312 
01313       // Done
01314 
01315         result = CdbStatus::Success;
01316 
01317     } while( false );
01318     
01319     return result;
01320 }
01321 
01322 CdbStatus
01323 CdbBdbSMetaDataP::findByRevision( const char*    theRevisionName,
01324                                   const BdbTime& theValidityTime,
01325                                   CdbBdbSOi&     theOriginalInterval,
01326                                   BdbTime&       theBeginOfVisiblePeriod,
01327                                   BdbTime&       theEndOfVisiblePeriod ) const
01328 {
01329     const char* errorStr = "CdbBdbSMetaDataP::findByRevision() -- ERROR";
01330 
01331     CdbStatus result = CdbStatus::Error;
01332     do {
01333 
01334       // This is required by the public contract of the method.
01335 
01336         theBeginOfVisiblePeriod = _minValidityTime;
01337         theEndOfVisiblePeriod   = _maxValidityTime;
01338 
01339       // Do not verify anything - just find a revision by name
01340       // and do the rest through the similar procedure.
01341 
01342         BdbTime revisionId( 0 );
01343 
01344         if( 0 == theRevisionName ) {
01345             revisionId = BdbTime::plusInfinity;     // TOPMOST revision
01346         } else {
01347             BdbRef( CdbBdbSRevisionP ) revisionRef;
01348             if( CdbStatus::Success != _revCollectionRef->find( theRevisionName, revisionRef )) {
01349                 cout << errorStr << endl
01350                      << "    Specified revision was not found in the collection." << endl
01351                      << "        PASSED REVISION NAME: " << theRevisionName << endl;
01352                 break;
01353             }
01354             revisionId = revisionRef->id( );
01355         }
01356 
01357       // Proceed to the actual finder...
01358 
01359         result = findByRevision( revisionId,
01360                                  theValidityTime,
01361                                  theOriginalInterval,
01362                                  theBeginOfVisiblePeriod,
01363                                  theEndOfVisiblePeriod );
01364 
01365     } while( false );
01366     
01367     return result;
01368 }
01369 
01370 CdbStatus
01371 CdbBdbSMetaDataP::findByInsertion( const BdbTime& theInsertionTime,
01372                                    const BdbTime& theValidityTime,
01373                                    CdbBdbSOi&     theOriginalInterval,
01374                                    BdbTime&       theBeginOfDurationPeriod,
01375                                    BdbTime&       theEndOfDurationPeriod ) const
01376 {
01377     const char* errorStr = "CdbBdbSMetaDataP::findByInsertion() -- ERROR";
01378 
01379     CdbStatus result = CdbStatus::Error;
01380     do {
01381 
01382       // Verify the parameters
01383 
01384         if(( theValidityTime <  _minValidityTime ) ||
01385            ( theValidityTime >= _maxValidityTime)) {
01386             cout << errorStr << endl
01387                  << "    The passed validity time is out of the validity window" << endl
01388                  << "    of the current metadata object." << endl;
01389             break;
01390         }
01391         if(( theInsertionTime <  _minInsertionTime ) ||
01392            ( theInsertionTime >= _maxInsertionTime)) {
01393             cout << errorStr << endl
01394                  << "    The passed insertion time is out of the insertion window" << endl
01395                  << "    of the current metadata object." << endl;
01396             break;
01397         }
01398 
01399       // Find the "original" interval and its "duration" interval through
01400       // the "original" collection.
01401       //
01402       // NOTE: We preserve the returned status since it may also be equal
01403       //       to CdbStatus::NotFound if the 0-0-0-0 reference found instead
01404       //       of an actual object.
01405 
01406         CdbStatus status = _originalCollectionRef->find( theInsertionTime,
01407                                                          theOriginalInterval,
01408                                                          theBeginOfDurationPeriod,
01409                                                          theEndOfDurationPeriod );
01410         if( CdbStatus::Success != status ) {
01411             result = status;
01412             break;
01413         }
01414 
01415       // Check if the specified "validity" time falls into the "original"
01416       // "validity" of this interval.
01417 
01418         if(( theValidityTime <  theOriginalInterval.begin ) ||
01419            ( theValidityTime >= theOriginalInterval.end   )) {
01420             cout << errorStr << endl
01421                  << "    This is inappropriate use of this finding method since" << endl
01422                  << "    the passed validity time does not fall into the 'validity' period" << endl
01423                  << "    of found 'original' interval." << endl;
01424             break;
01425         }
01426 
01427       // Done
01428 
01429         result = CdbStatus::Success;
01430 
01431     } while( false );
01432     
01433     return result;
01434 }
01435 CdbStatus
01436 CdbBdbSMetaDataP::findRevision( const BdbTime&            theId,
01437                                 BdbRef(CdbBdbSRevisionP)& theRef ) const
01438 {
01439     CdbStatus result = CdbStatus::NotFound;
01440     do {
01441 
01442       // Check if the specified revision identifier time falls into
01443       // the "window" of current metadata object.
01444       //
01445       // NOTE: Passing +Infinity is allowed.
01446 
01447         if( theId < _minInsertionTime ) break;
01448         if(( BdbTime::plusInfinity != _maxInsertionTime ) && ( theId >= _maxInsertionTime )) break;
01449 
01450       // Check if the topmost revision was requested
01451 
01452         if( BdbTime::plusInfinity == theId ) {
01453 
01454             if( !BdbIsNull(_topmostRevisionRef)) {
01455                 theRef = _topmostRevisionRef;
01456                 result = CdbStatus::Success;
01457             }
01458 
01459         } else {
01460 
01461           // Delegate revision lookup down to the revisions collection
01462 
01463             result = _revCollectionRef->find( theId,
01464                                               theRef );
01465         }
01466 
01467     } while( false );
01468 
01469     return result;
01470 }
01471 
01472 CdbStatus
01473 CdbBdbSMetaDataP::findRevision( const char*               theName,
01474                                 BdbRef(CdbBdbSRevisionP)& theRef ) const
01475 {
01476     const char* errorStr = "CdbBdbSMetaDataP::findRevision(name) -- ERROR";
01477 
01478     CdbStatus result = CdbStatus::NotFound;
01479     do {
01480 
01481       // Verify parameters
01482 
01483         if( 0 == theName ) {
01484             cout << errorStr << endl
01485                  << "    Null pointer passed instead of a valid revision name." << endl;
01486             break;
01487         }
01488 
01489       // Check if the topmost revision was requested
01490 
01491         if( 0 == strcmp( "<topmost>", theName )) {
01492 
01493             if( !BdbIsNull(_topmostRevisionRef)) {
01494                 theRef = _topmostRevisionRef;
01495                 result = CdbStatus::Success;
01496             }
01497 
01498         } else {
01499 
01500           // Delegate revision lookup down to the revisions collection
01501 
01502             result = _revCollectionRef->find( theName,
01503                                               theRef );
01504         }
01505 
01506     } while( false );
01507 
01508     return result;
01509 }
01510 
01511 CdbStatus
01512 CdbBdbSMetaDataP::createRevision( const BdbTime& theId,
01513                                   const char*    theName,
01514                                   const BdbTime& theCreationTime,
01515                                   const char*    theDescription )
01516 {
01517     ooUpdate( );
01518 
01519     const char* errorStr = "CdbBdbSMetaDataP::createRevision -- ERROR";
01520 
01521     CdbStatus result = CdbStatus::Error;
01522     do {
01523 
01524       // Verify the parameters
01525 
01526         if( CdbStatus::Success != verifyInsertionTime( theId )) {
01527             cout << errorStr << endl
01528                  << "    Specified revision identifier is not correct." << endl
01529                  << "    See details above." << endl;
01530             break;
01531         }
01532         if( 0 == strcmp( "<topmost>", theName )) {
01533             cout << errorStr << endl
01534                  << "    The special name '<topmost>' passed as a new revision name." << endl
01535                  << "    This name is reserved for the automatically created topmost revision" << endl
01536                  << "    and can't be used to create user-defined revisions." << endl;
01537             break;
01538         }
01539         if( theCreationTime < theId ) {
01540             cout << errorStr << endl
01541                  << "    Invalid revision creation time passsed to the procedure. This name should not" << endl
01542                  << "    be less than the revision identifiedr time." << endl
01543                  << "        PASSED REVISION ID:            " << theId << endl
01544                  << "        PASSED REVISION CREATION TIME: " << theCreationTime << endl;
01545             break;
01546         }
01547         if( theId < _modified ) {
01548             cout << errorStr << endl
01549                  << "    The identifier time of the passed revision is not correct." << endl
01550                  << "    Current operation requires this time to be greater or equal to" << endl
01551                  << "    the most recent modification time of the MetaData object." << endl
01552                  << "        PASSED INSERTION TIME:     " << theId << endl
01553                  << "        CURRENT MODIFICATION TIME: " << _modified << endl;
01554             break;
01555         }
01556         if( 0 == theDescription ) {
01557             cout << errorStr << endl
01558                  << "    Null pointer passed instead a valid revision description." << endl;
01559             break;
01560         }
01561 
01562       // Create new revision object by taking a snapshot of the "visible"
01563       // intervals collection of the current topmost revision.
01564 
01565         BdbRef(CdbBdbSRevisionP) revisionRef;
01566         revisionRef = new ( ooThis( )) CdbBdbSRevisionP( theId,
01567                                                          theName,
01568                                                          _topmostRevisionRef->collection( ),
01569                                                          theCreationTime,
01570                                                          theDescription );
01571 
01572       // Register new revision in the collection.
01573       //
01574       // NOTE: This operation will also verify the parameters of the new revision
01575       //       in the collection's context.
01576 
01577         if( CdbStatus::Success != _revCollectionRef->insert( revisionRef )) {
01578             cout << errorStr << endl
01579                  << "    Failed to insert new revision into the collection." << endl;
01580             BdbDelete( revisionRef );
01581             break;
01582         }
01583 
01584       // Update modification time if the new revision identifier is greater
01585       // than the current value of the modification time.
01586 
01587         if( theId > _modified ) _modified = theId;
01588 
01589       // Done
01590 
01591         result = CdbStatus::Success;
01592 
01593     } while( false );
01594     
01595     return result;
01596 }
01597 
01598 CdbStatus
01599 CdbBdbSMetaDataP::revisionIdIterator( CdbItr<BdbTime>& theItr ) const
01600 {
01601   // ATTENTION: This is not a memory leak - the created object
01602   //            will be destroyed by the iterator.
01603 
01604     theItr = CdbItr<BdbTime>( new RevisionIdIterator( _revCollectionRef,
01605                                                       !BdbIsNull(_topmostRevisionRef)));
01606     return CdbStatus::Success;
01607 }
01608 
01609 CdbStatus
01610 CdbBdbSMetaDataP::revisionNameIterator( CdbItr<const char*>& theItr ) const
01611 {
01612   // ATTENTION: This is not a memory leak - the created object
01613   //            will be destroyed by the iterator.
01614 
01615     theItr = CdbItr<const char*>( new RevisionNameIterator( _revCollectionRef,
01616                                                             !BdbIsNull(_topmostRevisionRef)));
01617     return CdbStatus::Success;
01618 }
01619 
01620 bool
01621 CdbBdbSMetaDataP::verifyObjectIteratorParameters( const BdbTime& theBeginTime,
01622                                                   const BdbTime& theEndTime ) const
01623 {
01624     const char* errorStr = "CdbBdbSMetaDataP::verifyObjectIteratorParameters() -- ERROR";
01625 
01626     bool result = false;
01627     do {
01628 
01629       // See formal requirements at the class's description
01630 
01631         if( ! (( _minValidityTime <= theBeginTime ) && ( theBeginTime < _maxValidityTime ))) {
01632             cout << errorStr << endl
01633                  << "    Incorrect begin time passed to the method. It's out of the validity" << endl
01634                  << "    time window of the current meta-data object." << endl
01635                  << "        PASSED BEGIN TIME : " << theBeginTime << endl
01636                  << "        WINDOW BEGIN TIME : " << _minValidityTime << endl
01637                  << "        WINDOW END   TIME : " << _maxValidityTime << endl;
01638             break;
01639         }
01640         if( ! (( _minValidityTime < theEndTime ) && ( theEndTime <= _maxValidityTime ))) {
01641             cout << errorStr << endl
01642                  << "    Incorrect end time passed to the method. It's out of the validity" << endl
01643                  << "    time window of the current meta-data object." << endl
01644                  << "        PASSED END   TIME : " << theEndTime << endl
01645                  << "        WINDOW BEGIN TIME : " << _minValidityTime << endl
01646                  << "        WINDOW END   TIME : " << _maxValidityTime << endl;
01647             break;
01648         }
01649         if(  ! ( theBeginTime < theEndTime )) {
01650             cout << errorStr << endl
01651                  << "    Incorrect begin and end times passed to the method." << endl
01652                  << "    The begin time must be strictly less (older) than the end one. " << endl
01653                  << "        PASSED BEGIN TIME : " << theBeginTime << endl
01654                  << "        PASSED END   TIME : " << theEndTime << endl;
01655             break;
01656         }
01657 
01658       // Done
01659 
01660         result = true;
01661 
01662     } while( false );
01663 
01664     return result;
01665 }
01666 
01667 CdbStatus
01668 CdbBdbSMetaDataP::objectIterator( CdbItr<CdbBdbSCi>& theItr,
01669                                   const BdbTime&     theRevisionId,
01670                                   const BdbTime&     theBeginTime,
01671                                   const BdbTime&     theEndTime ) const
01672 {
01673     const char* errorStr = "CdbBdbSMetaDataP::objectIterator(id) -- ERROR";
01674 
01675     CdbStatus result = CdbStatus::Error;
01676     do {
01677 
01678         if( ! verifyObjectIteratorParameters( theBeginTime,
01679                                               theEndTime )) break;
01680       // Find revision
01681 
01682         BdbRef(CdbBdbSRevisionP) revisionRef;
01683         if( CdbStatus::Success != findRevision( theRevisionId,
01684                                                 revisionRef )) {
01685             cout << errorStr << endl
01686                  << "    Failed to find a revision for specified identifier." << endl
01687                  << "        REVISION IDENTIFIER : " << theRevisionId << endl;
01688         }
01689 
01690       // ATTENTION: This is not a memory leak - the created object
01691       //            will be destroyed by the iterator.
01692 
01693         theItr = CdbItr<CdbBdbSCi>( new CombinedIntervalIterator( revisionRef->collection( ),
01694                                                                   _originalCollectionRef,
01695                                                                   theBeginTime,
01696                                                                   theEndTime ));
01697 
01698       // Done
01699 
01700         result = CdbStatus::Success;
01701 
01702     } while( false );
01703 
01704     return result;
01705 }
01706 
01707 CdbStatus
01708 CdbBdbSMetaDataP::objectIterator( CdbItr<CdbBdbSCi>& theItr,
01709                                   const char*        theName,
01710                                   const BdbTime&     theBeginTime,
01711                                   const BdbTime&     theEndTime ) const
01712 {
01713     const char* errorStr = "CdbBdbSMetaDataP::objectIterator(name) -- ERROR";
01714 
01715     CdbStatus result = CdbStatus::Error;
01716     do {
01717 
01718         if( ! verifyObjectIteratorParameters( theBeginTime,
01719                                               theEndTime )) break;
01720 
01721       // Find revision
01722 
01723         BdbRef(CdbBdbSRevisionP) revisionRef;
01724         if( CdbStatus::Success != findRevision( theName,
01725                                                 revisionRef )) {
01726             cout << errorStr << endl
01727                  << "    Failed to find a revision for specified name." << endl
01728                  << "        REVISION NAME : " << theName << endl;
01729             break;
01730         }
01731 
01732       // ATTENTION: This is not a memory leak - the created object
01733       //            will be destroyed by the iterator.
01734 
01735         theItr = CdbItr<CdbBdbSCi>( new CombinedIntervalIterator( revisionRef->collection( ),
01736                                                                   _originalCollectionRef,
01737                                                                   theBeginTime,
01738                                                                   theEndTime ));
01739 
01740       // Done
01741 
01742         result = CdbStatus::Success;
01743 
01744     } while( false );
01745 
01746     return result;
01747 }
01748 
01749 bool
01750 CdbBdbSMetaDataP::isClosed( ) const
01751 {
01752     return BdbTime::plusInfinity != _maxInsertionTime;
01753 }
01754 
01755 BdbTime
01756 CdbBdbSMetaDataP::recentlyModified( ) const
01757 {
01758     BdbTime result = BdbTime::minusInfinity;
01759     {
01760       // Check the "original" intervals collection
01761 
01762         CdbBdbSOi lastOiInterval;
01763         if( CdbStatus::Success == _originalCollectionRef->last( lastOiInterval )) {
01764             if( lastOiInterval.inserted > result ) result = lastOiInterval.inserted;
01765         }
01766 
01767       // Check the collection of revisions (revisions may get created
01768       // at any after the "original" intervals insertions.
01769       //
01770       // We're only asking for the ID of this revision.
01771 
01772         BdbTime revId( 0 );
01773         if( CdbStatus::Success == _revCollectionRef->last( revId )) {
01774             if( revId > result ) result = revId;
01775         }
01776     }
01777     return result;
01778 }
01779 
01780 CdbStatus
01781 CdbBdbSMetaDataP::verifyInsertionTime( const BdbTime& theTime ) const
01782 {
01783     const char* errorStr = "CdbBdbSMetaDataP::verifyInsertionTime -- ERROR";
01784 
01785     CdbStatus result = CdbStatus::Error;
01786     do {
01787 
01788       // Verify the current context of the metadata object.
01789 
01790         if( isClosed( )) {
01791             cout << errorStr << endl
01792                  << "    The metadata object is already closed for further modifications." << endl;
01793             break;
01794         }
01795 
01796       // Verify the parameters
01797 
01798         if(( BdbTime::minusInfinity == theTime ) ||
01799            ( BdbTime::plusInfinity  == theTime )) {
01800             cout << errorStr << endl
01801                  << "    Invalid value of the insertion time. It should not be" << endl
01802                  << "    equal neither '-Infinity' nor the '+Infinity'." << endl;
01803             break;
01804         }
01805 
01806       // Check if specified insertion time is not older than the most recent
01807       // modification time.
01808 
01809         BdbTime recentModificationTime = recentlyModified( );
01810         if( theTime < recentModificationTime ) {
01811             cout << errorStr << endl
01812                  << "    The passed time must be greater or equal than the most recent" << endl
01813                  << "    modification time of the metadata window." << endl
01814                  << "        MODIFICATION TIME:     " << recentModificationTime << endl
01815                  << "        PASSED INSERTION TIME: " << theTime << endl;
01816             break;
01817         }
01818 
01819       // Done
01820 
01821         result = CdbStatus::Success;
01822 
01823     } while( false );
01824     
01825     return result;
01826 }
01827 
01828 /////////////////
01829 // End Of File //
01830 /////////////////

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