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

CdbBdbSCondition.cc

Go to the documentation of this file.
00001 // File and Version Information:
00002 //      $Id: CdbBdbSCondition.cc,v 1.36 2005/10/31 22:19:34 gapon Exp $
00003 #include "BaBar/BaBar.hh"
00004 
00005 /// The implementation of the CdbBdbSCondition class.
00006 /**
00007   * @see CdbBdbSCondition
00008   */
00009 
00010 #include "CdbBdbShared/CdbBdbSCondition.hh"
00011 
00012 #include "CdbBase/Cdb.hh"
00013 #include "CdbBase/CdbEnvironment.hh"
00014 #include "CdbBase/CdbFolder.hh"
00015 #include "CdbBase/CdbRevision.hh"
00016 #include "CdbBase/CdbRevisionPolicy.hh"
00017 #include "CdbBase/CdbObject.hh"
00018 #include "CdbBase/CdbObjectFactoryBase.hh"
00019 #include "CdbBase/CdbItr.hh"
00020 #include "CdbBase/CdbId.hh"
00021 #include "CdbBase/CdbCompositeName.hh"
00022 #include "CdbBase/CdbTimeUtils.hh"
00023 #include "CdbBase/CdbDebugStream.hh"
00024 
00025 #include "CdbBdb/CdbBdbObjectCreator.hh"
00026 #include "CdbBdb/CdbBdbObjectConvertor.hh"
00027 
00028 #include "CdbBdbShared/CdbBdbSViewP.hh"
00029 #include "CdbBdbShared/CdbBdbSFolderP.hh"
00030 #include "CdbBdbShared/CdbBdbSConditionAtFolderP.hh"
00031 #include "CdbBdbShared/CdbBdbSClusterP.hh"
00032 #include "CdbBdbShared/CdbBdbSSimpleClusterP.hh"
00033 #include "CdbBdbShared/CdbBdbSClusterCollectionP.hh"
00034 #include "CdbBdbShared/CdbBdbSPartitionP.hh"
00035 #include "CdbBdbShared/CdbBdbSPartitionsLayoutP.hh"
00036 #include "CdbBdbShared/CdbBdbSMetaDataP.hh"
00037 #include "CdbBdbShared/CdbBdbSConfigCollectionP.hh"
00038 #include "CdbBdbShared/CdbBdbSOriginP.hh"
00039 #include "CdbBdbShared/CdbBdbSOriginCollectionP.hh"
00040 #include "CdbBdbShared/CdbBdbSRevision.hh"
00041 
00042 #include "CdbBdbShared/CdbBdbSUtils.hh"
00043 #include "CdbBdbShared/CdbBdbSOi.hh"
00044 #include "CdbBdbShared/CdbBdbSView.hh"
00045 #include "CdbBdbShared/CdbBdbSSimpleConfigIterator.hh"
00046 
00047 #include "BdbApplication/BdbDomain.hh"
00048 
00049 #include "BdbTime/BdbTime.hh"
00050 #include "BdbCond/BdbObject.hh"
00051 
00052 #include <stdio.h>
00053 #include <iostream>
00054 
00055 #include <vector>
00056 #include <stack>
00057 using std::cout;
00058 using std::endl;
00059 using std::ends;
00060 
00061 namespace {
00062 
00063 /////////////////////////////////////////////
00064 // Function declaration: Meta Data locator //
00065 /////////////////////////////////////////////
00066 
00067 /// Find MetaData object(s) for specified condition
00068 /**
00069   * The contence of the output vector varies depending on the values of flags
00070   * passed to the function.
00071   *
00072   *     - if "allIncrementsFlag" is set (true) then metadata objects will be
00073   *       found for all increments. Then the increments numbers can be used to
00074   *       as the vector's indexes to fet to tyhe corresponding meta-data.
00075   *       The subsequent parameters are ignored in this case.
00076   *
00077   *     - else if "recentIncrementFlag" is set then the output vector will only
00078   *       containe the metadata reference for the most recently created increment.
00079   *
00080   *     - else the specified increment number will be used to locate the corresponding
00081   *       metadata object.
00082   *
00083   * The partition identifier is only used if the corresponding condition
00084   * is the partitionable.
00085   *
00086   * IMPORTANT NOTE: The procedure will use the condition's creation time
00087   *                 when looking for a subset of increments including or newer
00088   *                 than that time. The reason is that conditions could be created
00089   *                 later on when a number of increments for a cluster/partition may
00090   *                 already exist.
00091   */
00092 CdbStatus
00093 findMetaData( std::vector<BdbRef(CdbBdbSMetaDataP)>& theVectorOfRefs,
00094               const BdbHandle(CdbBdbSRegistryP)&     theMasterRegistryH,
00095               const BdbHandle(CdbBdbSRegistryP)&     theLocalRegistryH,
00096               const CdbBdbSId&                       theExtendedConditionId,
00097               d_UShort                               thePartitionId,
00098               bool                                   allIncrementsFlag   = true,
00099               bool                                   recentIncrementFlag = true,
00100               d_UShort                               theIncrementNumber  = 0 );
00101 
00102 /// Serialize a value of time into a string
00103 
00104 std::string
00105 time2string( const BdbTime& theTime );
00106 
00107 ///////////////////////////////
00108 // Class: RevisionIdIterator //
00109 ///////////////////////////////
00110 
00111 class RevisionIdIterator : public CdbItr<BdbTime>::InterfaceType {
00112 
00113 private:
00114 
00115     RevisionIdIterator( );
00116 
00117     RevisionIdIterator& operator=( const RevisionIdIterator& theItr );
00118 
00119 protected:
00120 
00121     RevisionIdIterator( const RevisionIdIterator& theItr ) :
00122         _metaDataRefs       (theItr._metaDataRefs),
00123         _isValid            (theItr._isValid),
00124         _hasEverBeenAdvanced(theItr._hasEverBeenAdvanced),
00125         _value              (theItr._value),
00126         _itr                (theItr._itr),
00127         _revItr             (theItr._revItr)
00128     { }
00129 
00130 public:
00131 
00132 
00133     RevisionIdIterator( const std::vector<BdbRef(CdbBdbSMetaDataP)>& theMetaDataRefs ) :
00134         _metaDataRefs       (theMetaDataRefs),
00135         _isValid            (false),
00136         _hasEverBeenAdvanced(false)
00137     { }
00138 
00139     virtual ~RevisionIdIterator( )
00140     { }
00141 
00142     virtual CdbStatus reset( )
00143     {
00144         _isValid             = false;
00145         _hasEverBeenAdvanced = false;
00146 
00147         return CdbStatus::Success;
00148     }
00149 
00150     bool tryNext( )
00151     {
00152         if( _revItr.next( )) {
00153             return true;
00154         } else {
00155 
00156           // Switch to the next metaData (if any)
00157 
00158             ++_itr;
00159             if( _metaDataRefs.end( ) != _itr ) {
00160 
00161                 BdbRef(CdbBdbSMetaDataP) rRef = (*_itr);
00162                 if( CdbStatus::Success != rRef->revisionIdIterator( _revItr )) {
00163                     return false;
00164                 }
00165                 return tryNext( );
00166             }
00167         }
00168         return false;
00169     }
00170 
00171     virtual bool next( )
00172     {
00173         if( _hasEverBeenAdvanced && !_isValid ) {
00174             return _isValid;        // stay in "past the last element" state
00175         }
00176 
00177         if( !_hasEverBeenAdvanced ) {
00178             _hasEverBeenAdvanced = true;
00179 
00180             _itr = _metaDataRefs.begin( );
00181             if( _metaDataRefs.end( ) == _itr ) {
00182                 _isValid = false;
00183                 return _isValid;    // go into the "past the last element" state      
00184             }
00185             BdbRef(CdbBdbSMetaDataP) rRef = (*_itr);
00186 
00187             if( CdbStatus::Success != rRef->revisionIdIterator( _revItr )) {
00188                 _isValid = false;
00189                 return _isValid;    // go into the "past the last element" state      
00190             }
00191 
00192           // At this point _itr points onto the very first MetaData in the vector
00193           // and _revItr is just before the very first revision of this metadata.
00194         }
00195 
00196       // At this point _itr points onto some MetaDat ain the vector
00197       // and _revItr is before the next element we're intrested in (if still there
00198       // is some in this MetaData).
00199 
00200         if( tryNext( )) {
00201             _value = _revItr.value( );
00202             _isValid = true;
00203         } else {
00204             _isValid = false;   // go into the "past the last element" state
00205         }
00206         return _isValid;
00207     }
00208 
00209     virtual ValueType value( )
00210     {
00211         if( _isValid ) {
00212             return _value;
00213         }
00214         return BdbTime::minusInfinity;
00215     }
00216 
00217     virtual bool isValid( )
00218     {
00219         return _isValid;
00220     }
00221 
00222     virtual InterfaceType* clone( ) const
00223     {
00224         return new RevisionIdIterator( *this );
00225     }
00226 
00227 private:
00228 
00229     std::vector<BdbRef(CdbBdbSMetaDataP)> _metaDataRefs;
00230 
00231     bool _isValid;
00232     bool _hasEverBeenAdvanced;
00233 
00234     BdbTime _value;
00235 
00236   // A pointer onto the current element at the above defined vector of
00237   // metadata references.
00238 
00239     std::vector<BdbRef(CdbBdbSMetaDataP)>::const_iterator _itr;
00240 
00241   // The current iterator for the currently indexed metadata reference.
00242 
00243     CdbItr<BdbTime> _revItr;
00244 };
00245 
00246 /////////////////////////////////
00247 // Class: RevisionNameIterator //
00248 /////////////////////////////////
00249 
00250 class RevisionNameIterator : public CdbItr<const char*>::InterfaceType {
00251 
00252 private:
00253 
00254     RevisionNameIterator( );
00255 
00256     RevisionNameIterator& operator=( const RevisionNameIterator& theItr );
00257 
00258 protected:
00259 
00260     RevisionNameIterator( const RevisionNameIterator& theItr ) :
00261         _metaDataRefs       (theItr._metaDataRefs),
00262         _isValid            (theItr._isValid),
00263         _hasEverBeenAdvanced(theItr._hasEverBeenAdvanced),
00264         _value              (theItr._value),
00265         _itr                (theItr._itr),
00266         _revItr             (theItr._revItr)
00267     { }
00268 
00269 public:
00270 
00271 
00272     RevisionNameIterator( const std::vector<BdbRef(CdbBdbSMetaDataP)>& theMetaDataRefs ) :
00273         _metaDataRefs       (theMetaDataRefs),
00274         _isValid            (false),
00275         _hasEverBeenAdvanced(false),
00276         _value("")
00277     { }
00278 
00279     virtual ~RevisionNameIterator( )
00280     { }
00281 
00282     virtual CdbStatus reset( )
00283     {
00284         _isValid             = false;
00285         _hasEverBeenAdvanced = false;
00286 
00287         return CdbStatus::Success;
00288     }
00289 
00290     bool tryNext( )
00291     {
00292         if( _revItr.next( )) {
00293             return true;
00294         } else {
00295 
00296           // Switch to the next metaData (if any)
00297 
00298             ++_itr;
00299             if( _metaDataRefs.end( ) != _itr ) {
00300 
00301                 BdbRef(CdbBdbSMetaDataP) rRef = (*_itr);
00302                 if( CdbStatus::Success != rRef->revisionNameIterator( _revItr )) {
00303                     return false;
00304                 }
00305                 return tryNext( );
00306             }
00307         }
00308         return false;
00309     }
00310 
00311     virtual bool next( )
00312     {
00313         if( _hasEverBeenAdvanced && !_isValid ) {
00314             return _isValid;        // stay in "past the last element" state
00315         }
00316 
00317         if( !_hasEverBeenAdvanced ) {
00318             _hasEverBeenAdvanced = true;
00319 
00320             _itr = _metaDataRefs.begin( );
00321             if( _metaDataRefs.end( ) == _itr ) {
00322                 _isValid = false;
00323                 return _isValid;    // go into the "past the last element" state      
00324             }
00325             BdbRef(CdbBdbSMetaDataP) rRef = (*_itr);
00326 
00327             if( CdbStatus::Success != rRef->revisionNameIterator( _revItr )) {
00328                 _isValid = false;
00329                 return _isValid;    // go into the "past the last element" state      
00330             }
00331 
00332           // At this point _itr points onto the very first MetaData in the vector
00333           // and _revItr is just before the very first revision of this metadata.
00334         }
00335 
00336       // At this point _itr points onto some MetaDat ain the vector
00337       // and _revItr is before the next element we're intrested in (if still there
00338       // is some in this MetaData).
00339 
00340         if( tryNext( )) {
00341             _value = _revItr.value( );
00342             _isValid = true;
00343         } else {
00344             _isValid = false;   // go into the "past the last element" state
00345         }
00346         return _isValid;
00347     }
00348 
00349     virtual ValueType value( )
00350     {
00351         if( _isValid ) {
00352             return _value.c_str( );
00353         }
00354         return 0;
00355     }
00356 
00357     virtual bool isValid( )
00358     {
00359         return _isValid;
00360     }
00361 
00362     virtual InterfaceType* clone( ) const
00363     {
00364         return new RevisionNameIterator( *this );
00365     }
00366 
00367 private:
00368 
00369     std::vector<BdbRef(CdbBdbSMetaDataP)> _metaDataRefs;
00370 
00371     bool _isValid;
00372     bool _hasEverBeenAdvanced;
00373 
00374     std::string _value;
00375 
00376   // A pointer onto the current element at the above defined vector of
00377   // metadata references.
00378 
00379     std::vector<BdbRef(CdbBdbSMetaDataP)>::const_iterator _itr;
00380 
00381   // The current iterator for the currently indexed metadata reference.
00382 
00383     CdbItr<const char*> _revItr;
00384 };
00385 
00386 ////////////////////////////////////////
00387 // Class: PartitionableObjectIterator //
00388 ////////////////////////////////////////
00389 
00390 class PartitionableObjectIterator : public CdbObjectItr::InterfaceType {
00391 
00392 private:
00393 
00394   // These forms of object construction are not implemented
00395 
00396     PartitionableObjectIterator( );
00397 
00398     PartitionableObjectIterator& operator=( const PartitionableObjectIterator& theItr );
00399 
00400 protected:
00401 
00402   // This form of the constructor is only used by the clone operation
00403 
00404     PartitionableObjectIterator( const PartitionableObjectIterator& theItr );
00405 
00406 public:
00407 
00408   /// Normal constructor
00409   /**
00410     * If the configuration collection parameter is pointing onto a zero object
00411     * then the revision policy must be used.
00412     */
00413     PartitionableObjectIterator( const CdbConditionPtr&                 theParentPtr,
00414                                  const BdbTime&                         theBegin,
00415                                  const BdbTime&                         theEnd,
00416                                  const CdbItr< CdbBdbSConfigInterval >& theConfigItr,
00417                                  const BdbHandle(CdbBdbSRegistryP)&     theMasterRegistryH,
00418                                  const BdbHandle(CdbBdbSRegistryP)&     theLocalRegistryH,
00419                                  const CdbBdbSId&                       theExtendedConditionId,
00420                                  const BdbTime&                         theConditionCreationTime );
00421 
00422     virtual ~PartitionableObjectIterator( );
00423 
00424   // Methods implementing public interface of the geneic iterator
00425 
00426     virtual CdbStatus reset( );
00427 
00428     virtual bool next( );
00429 
00430     virtual ValueType value( );
00431 
00432     virtual bool isValid( );
00433 
00434     virtual InterfaceType* clone( ) const;
00435 
00436 private:
00437 
00438   // Helpers
00439 
00440     bool tryNextObject( );
00441 
00442     bool tryNextPartition( const BdbTime& theBeginTime,
00443                            const BdbTime& theEndTime );
00444 
00445     bool tryNextConfigElement( );
00446 
00447     bool findPartition( BdbHandle(CdbBdbSPartitionP)& theHandle,
00448                         d_UShort                      thePartitionId );
00449 
00450 private:
00451 
00452   // Parameters
00453 
00454     CdbConditionPtr _parent;
00455 
00456     BdbTime _begin;
00457     BdbTime _end;
00458 
00459     CdbItr< CdbBdbSConfigInterval > _configItr;
00460 
00461     BdbHandle(CdbBdbSRegistryP) _masterRegistryH;
00462     BdbHandle(CdbBdbSRegistryP) _localRegistryH;
00463 
00464     CdbBdbSId _extendedConditionId;
00465 
00466     BdbTime _conditionCreationTime;
00467 
00468   // The current state
00469 
00470     bool _isValid;
00471     bool _hasEverBeenAdvanced;
00472 
00473     CdbObjectPtr _value;
00474 
00475   // The context : configuration element
00476 
00477     BdbTime _beginConfig;
00478     BdbTime _endConfig;
00479     BdbTime _revisionId;
00480 
00481   // Other contexts to follow as a hierarchy of objects of two nested
00482   // classes MD and PARTITION. These classes are also used by the iterator
00483   // set up and next element location algorithms.
00484   //
00485   // DESIGN NOTES: In the current design the PARTITION object contains
00486   //               objects of the MD class. MD objects describe MetaData
00487   //               for the container PARTITION.
00488   //               There is one PARTITION descrybing the current context
00489   //               (a data member of _cxt defined below) in which the iterator
00490   //               is. The previous contexts (if any) are put into the stack
00491   //               of PARTITION-s.
00492 
00493 public:
00494 
00495   // NOTE: This class lives in the public scope since it's used
00496   //       by the PARTITION class defined below
00497 
00498     class MD {
00499 
00500     public:
00501 
00502         MD( );
00503 
00504         MD( const BdbHandle(CdbBdbSMetaDataP)& theMetaDataH,
00505             const BdbTime&                     theRevisionId );
00506 
00507         MD( const BdbHandle(CdbBdbSMetaDataP)& theMetaDataH,
00508             const CdbItr<CdbBdbSCi>&           theObjectItr,
00509             const BdbTime&                     theRevisionId,
00510             const BdbTime&                     theBeginTime,
00511             const BdbTime&                     theEndTime );
00512 
00513         MD( const MD& theMd );
00514 
00515         ~MD( );
00516 
00517         MD& operator=( const MD& theMd );
00518 
00519     public:
00520 
00521         BdbHandle(CdbBdbSMetaDataP) handle;
00522 
00523         CdbItr<CdbBdbSCi> itr;
00524 
00525         BdbTime revision;
00526         BdbTime begin;
00527         BdbTime end;
00528 
00529         bool inHole;
00530 
00531         CdbItr< CdbBdbSPartitionInterval > pItr;
00532     };
00533 
00534 private:
00535 
00536     class PARTITION {
00537 
00538       // We need this definition in order to comply with C++ requirements
00539       // on the scope resolution. The problem is that MD and PARTITION
00540       // can't see each other since they are defined independently
00541       // inside the host class.
00542 
00543         typedef PartitionableObjectIterator::MD MD;
00544 
00545     public:
00546 
00547         PARTITION( );
00548 
00549         PARTITION( d_UShort                           thePartitionId,
00550                    const BdbTime&                     theBeginTime,
00551                    const BdbTime&                     theEndTime,
00552                    const std::vector< MD >&           theMd,
00553                    const std::vector< MD >::size_type theMdCurrent );
00554 
00555         PARTITION( const PARTITION& thePartition  );
00556 
00557         ~PARTITION( );
00558 
00559         PARTITION& operator=( const PARTITION& thePartition );
00560 
00561     public:
00562 
00563         d_UShort _partitionId;
00564 
00565         BdbTime _begin;
00566         BdbTime _end;
00567 
00568         std::vector< MD >            _md;
00569         std::vector< MD >::size_type _mdCurrent;
00570     };
00571 
00572 private:
00573 
00574   // The context : partition & metadata
00575 
00576     PARTITION             _cxt;
00577     std::stack<PARTITION> _previousCxt;
00578 };
00579 
00580 /////////////////////////////////////////////////////////////////
00581 // Implementation of the PartitionableObjectIterator::MD class //
00582 /////////////////////////////////////////////////////////////////
00583 
00584 PartitionableObjectIterator::MD::MD( )
00585 { }
00586 
00587 PartitionableObjectIterator::MD::MD( const BdbHandle(CdbBdbSMetaDataP)& theMetaDataH,
00588                                      const BdbTime&                     theRevisionId ) :
00589     handle  (theMetaDataH ),
00590     revision(theRevisionId),
00591     inHole  (false        )
00592 { }
00593 
00594 PartitionableObjectIterator::MD::MD( const BdbHandle(CdbBdbSMetaDataP)& theMetaDataH,
00595                                      const CdbItr<CdbBdbSCi>&           theObjectItr,
00596                                      const BdbTime&                     theRevisionId,
00597                                      const BdbTime&                     theBeginTime,
00598                                      const BdbTime&                     theEndTime ) :
00599     handle  (theMetaDataH ),
00600     itr     (theObjectItr ),
00601     revision(theRevisionId),
00602     begin   (theBeginTime ),
00603     end     (theEndTime   ),
00604     inHole  (false        )
00605 { }
00606 
00607 PartitionableObjectIterator::MD::MD( const PartitionableObjectIterator::MD& theMd ) :
00608     handle  (theMd.handle  ),
00609     itr     (theMd.itr     ),
00610     revision(theMd.revision),
00611     begin   (theMd.begin   ),
00612     end     (theMd.end     ),
00613     inHole  (theMd.inHole  ),
00614     pItr    (theMd.pItr    ) { }
00615 
00616 PartitionableObjectIterator::MD::~MD( )
00617 { }
00618 
00619 PartitionableObjectIterator::MD&
00620 PartitionableObjectIterator::MD::operator=( const PartitionableObjectIterator::MD& theMd )
00621 {
00622     if( this != &theMd ) {
00623         handle   = theMd.handle;
00624         itr      = theMd.itr;
00625         revision = theMd.revision;
00626         begin    = theMd.begin;
00627         end      = theMd.end;
00628         inHole   = theMd.inHole;
00629         pItr     = theMd.pItr;
00630     }
00631     return *this;
00632 }
00633 
00634 ////////////////////////////////////////////////////////////////////////
00635 // Implementation of the PartitionableObjectIterator::PARTITION class //
00636 ////////////////////////////////////////////////////////////////////////
00637 
00638 PartitionableObjectIterator::PARTITION::PARTITION( )
00639 { }
00640 
00641 PartitionableObjectIterator::PARTITION::PARTITION( d_UShort                           thePartitionId,
00642                                                    const BdbTime&                     theBeginTime,
00643                                                    const BdbTime&                     theEndTime,
00644                                                    const std::vector< MD >&           theMd,
00645                                                    const std::vector< MD >::size_type theMdCurrent ) :
00646     _partitionId(thePartitionId),
00647     _begin      (theBeginTime  ),
00648     _end        (theEndTime    ),
00649     _md         (theMd         ),
00650     _mdCurrent  (theMdCurrent  )
00651 { }
00652 
00653 PartitionableObjectIterator::PARTITION::PARTITION( const PartitionableObjectIterator::PARTITION& thePartition  ) :
00654     _partitionId(thePartition._partitionId),
00655     _begin      (thePartition._begin      ),
00656     _end        (thePartition._end        ),
00657     _md         (thePartition._md         ),
00658     _mdCurrent  (thePartition._mdCurrent  )
00659 { }
00660 
00661 PartitionableObjectIterator::PARTITION::~PARTITION( )
00662 { }
00663 
00664 PartitionableObjectIterator::PARTITION&
00665 PartitionableObjectIterator::PARTITION::operator=( const PartitionableObjectIterator::PARTITION& thePartition )
00666 {
00667     if( this != &thePartition ) {
00668         _partitionId = thePartition._partitionId;
00669         _begin       = thePartition._begin;
00670         _end         = thePartition._end;
00671         _md          = thePartition._md;
00672         _mdCurrent   = thePartition._mdCurrent;
00673     }
00674     return *this;
00675 }
00676 
00677 /////////////////////////////////////////////////////////////
00678 // Implementation of the PartitionableObjectIterator class //
00679 /////////////////////////////////////////////////////////////
00680 
00681 PartitionableObjectIterator::PartitionableObjectIterator( const PartitionableObjectIterator& theItr ) :
00682 
00683     _parent               (theItr._parent),
00684     _begin                (theItr._begin),
00685     _end                  (theItr._end),
00686     _configItr            (theItr._configItr),
00687     _masterRegistryH      (theItr._masterRegistryH),
00688     _localRegistryH       (theItr._localRegistryH),
00689     _extendedConditionId  (theItr._extendedConditionId),
00690     _conditionCreationTime(theItr._conditionCreationTime),
00691 
00692     _isValid              (theItr._isValid),
00693     _hasEverBeenAdvanced  (theItr._hasEverBeenAdvanced),
00694     _value                (theItr._value),
00695 
00696     _beginConfig          (theItr._beginConfig),
00697     _endConfig            (theItr._endConfig),
00698     _revisionId           (theItr._revisionId),
00699 
00700     _cxt                  (theItr._cxt),
00701     _previousCxt          (theItr._previousCxt)
00702 { }
00703 
00704 PartitionableObjectIterator::PartitionableObjectIterator( const CdbConditionPtr&                 theParentPtr,
00705                                                           const BdbTime&                         theBegin,
00706                                                           const BdbTime&                         theEnd,
00707                                                           const CdbItr< CdbBdbSConfigInterval >& theConfigItr,
00708                                                           const BdbHandle(CdbBdbSRegistryP)&     theMasterRegistryH,
00709                                                           const BdbHandle(CdbBdbSRegistryP)&     theLocalRegistryH,
00710                                                           const CdbBdbSId&                       theExtendedConditionId,
00711                                                           const BdbTime&                         theConditionCreationTime ) :
00712     _parent               (theParentPtr),
00713     _begin                (theBegin),
00714     _end                  (theEnd),
00715     _configItr            (theConfigItr),
00716     _masterRegistryH      (theMasterRegistryH),
00717     _localRegistryH       (theLocalRegistryH),
00718     _extendedConditionId  (theExtendedConditionId),
00719     _conditionCreationTime(theConditionCreationTime),
00720     _isValid              (false),
00721     _hasEverBeenAdvanced  (false)
00722 { }
00723 
00724 PartitionableObjectIterator::~PartitionableObjectIterator( )
00725 { }
00726 
00727 CdbStatus
00728 PartitionableObjectIterator::reset( )
00729 {
00730     _isValid             = false;
00731     _hasEverBeenAdvanced = false;
00732 
00733     return CdbStatus::Success;
00734 }
00735 
00736 bool
00737 PartitionableObjectIterator::next( )
00738 {
00739     if( _hasEverBeenAdvanced ) {
00740         if( ! _isValid ) {
00741 
00742           // Stay at BEYOND_PAST_ELEMENT state
00743 
00744             ;
00745 
00746         } else {
00747 
00748           // Try to get next object...
00749 
00750             _isValid = tryNextObject( );
00751         }
00752 
00753     } else {
00754 
00755       // Set up initial context of the iterator. Then proceed down
00756       // to the first object of the collection starting from the configuration.
00757 
00758         _configItr.reset( );
00759 
00760         _hasEverBeenAdvanced = true;
00761         _isValid             = tryNextConfigElement( );
00762     }
00763     return _isValid;
00764 }
00765 
00766 PartitionableObjectIterator::ValueType
00767 PartitionableObjectIterator::value( )
00768 {
00769     if( ! _isValid ) {
00770         assert( 0 );
00771     }
00772     return _value;
00773 }
00774 
00775 bool
00776 PartitionableObjectIterator::isValid( )
00777 {
00778     return _isValid;
00779 }
00780 
00781 PartitionableObjectIterator::InterfaceType*
00782 PartitionableObjectIterator::PartitionableObjectIterator::clone( ) const
00783 {
00784     return new PartitionableObjectIterator( *this );
00785 }
00786 
00787 bool
00788 PartitionableObjectIterator::tryNextPartition( const BdbTime& theBeginTime,
00789                                                const BdbTime& theEndTime )
00790 {
00791     const char* debugStr = "CdbBdbSCondition::PartitionableObjectIterator::tryNextPartition()";
00792     const char* errorStr = "CdbBdbSCondition::PartitionableObjectIterator::tryNextPartition() -- ERROR";
00793 
00794 /*********************************************************************************************/
00795 if( CdbEnvironment::getDebugMode( ) != 0 )
00796     cout << debugStr << endl
00797          << "{" << endl
00798          << "    Trying to set up partition iterator below the 'hole' at the bottom MD" << endl
00799          << "    of the current partition." << endl
00800          << "        _cxt._partitionId = " << _cxt._partitionId << endl
00801          << "        theBeginTime      = " << time2string( theBeginTime ).c_str( ) << endl
00802          << "        theEndTime        = " << time2string( theEndTime ).c_str( ) << endl
00803          << "}" << endl;
00804 /*********************************************************************************************/
00805 
00806   // Find the bottom insertion time of the current partition.
00807 
00808     BdbHandle(CdbBdbSPartitionsLayoutP) pLayoutH;
00809 
00810     pLayoutH = _masterRegistryH->partitionsLayout( );
00811     if( BdbIsNull(pLayoutH)) {
00812         cout << errorStr << endl
00813              << "    The database could be corrupted or be in an inconsistent state." << endl;
00814         assert( 0 );
00815         return false;
00816     }
00817     BdbRef(CdbBdbSPartitionP) pRef;
00818     if( CdbStatus::Success != pLayoutH->find( _cxt._partitionId, pRef )) {
00819         cout << errorStr << endl
00820              << "    The database could be corrupted or be in an inconsistent state." << endl;
00821         assert( 0 );
00822         return false;
00823     }
00824 
00825   // Set up the iterator of partitions below the found bottom time
00826   // and withing the limits of a hole passed as parameters to the current method.
00827 
00828     _cxt._md[_cxt._mdCurrent].pItr = pLayoutH->iterator( pRef->cell( ).beginInsertion,
00829                                                          theBeginTime,
00830                                                          theEndTime );
00831 
00832   // Set up special flag to engage the partition iterator when
00833   // calling the "tryNextObject()" method below.
00834 
00835     _cxt._md[_cxt._mdCurrent].inHole = true;
00836 
00837     return tryNextObject( );
00838 }
00839 
00840 bool
00841 PartitionableObjectIterator::tryNextObject( )
00842 {
00843     const char* debugStr = "CdbBdbSCondition::PartitionableObjectIterator::tryNextObject()";
00844     const char* errorStr = "CdbBdbSCondition::PartitionableObjectIterator::tryNextObject() -- ERROR";
00845 
00846     assert( _cxt._md.size( ) > 0 );
00847     assert( _cxt._mdCurrent < _cxt._md.size( ));
00848 
00849 /******************************************************************/
00850 if( CdbEnvironment::getDebugMode( ) != 0 )
00851     cout << debugStr << endl
00852          << "{" << endl
00853          << "    ENTERING THE METHOD..." << endl
00854          << "}" << endl;
00855 /******************************************************************/
00856 
00857   // Check if we're running in the 'hole'. Then we'd need to try advancing
00858   // the partition iterator one step forward and get the whole stack of metada data
00859   // of this partition. Then we push current context into the stack and proceed as usually.
00860   //
00861   // NOTE: If we find "closed" partitions, whose upper "insertion" time boundry is older
00862   //       than the creation time of the condition then we do not jump down into these partitions
00863   //       and skip them and go to the next element of the partitions iterator.
00864 
00865     if( _cxt._md[_cxt._mdCurrent].inHole ) {
00866 
00867         bool found = false;
00868 
00869         while( _cxt._md[_cxt._mdCurrent].pItr.next( )) {
00870 
00871           // We're staying in this loop till the end of the iterator of partitions
00872           // because this iterator was supposed to be set up exactly for the duration of
00873           // the current "hole" we're in.
00874 
00875             CdbBdbSPartitionInterval iVal = _cxt._md[_cxt._mdCurrent].pItr.value( );
00876 
00877             if( !iVal.isEmpty ) {
00878 
00879               // Make this test before switching context. It's meant to reassure
00880               // that partitions iterator delivers correct partitions.
00881 
00882                 assert( _cxt._md[_cxt._mdCurrent].begin <= iVal.begin );
00883                 assert( iVal.end <= _cxt._md[_cxt._mdCurrent].end );
00884 
00885               // Find out the partition to see if it's in the "closed" state. If so then we need
00886               // to check if its upper "insertion" time boundry is not older than the creation
00887               // time of the condition. If it happens that the condition is newer than the partition
00888               // closeout time then we just bail out since there should not be any MetaData information
00889               // in this partition for our current condition. Then we skip this partition.
00890 
00891                 {
00892                     d_UShort partitionId = iVal.id;
00893 
00894                     BdbHandle(CdbBdbSPartitionP) pH;
00895                     if( ! findPartition( pH, partitionId )) {
00896                         cout << errorStr << endl
00897                              << "    Failed to locate the partition with ID=" << partitionId << endl;
00898                         return false;
00899                     }
00900 
00901 /******************************************************************/
00902 if( CdbEnvironment::getDebugMode( ) != 0 )
00903     cout << debugStr << endl
00904          << "{" << endl
00905          << "    Found partition ID=" << pH->id( ) << endl
00906          << "}" << endl;
00907 /******************************************************************/
00908 
00909                     if( pH->isClosed( )) {
00910                         CdbBdbSCell pCell = pH->cell( );
00911                         if( pCell.endInsertion <= _conditionCreationTime ) {
00912 
00913 /**********************************************************************************************************************/
00914 if( CdbEnvironment::getDebugMode( ) != 0 )
00915     cout << debugStr << endl
00916          << "{" << endl
00917          << "    The above found partition required by the current configuration interval is already 'closed'" << endl
00918          << "    and its upper 'insertion' time limit is older than the creation time of the current condition." << endl
00919          << "    Skipping the current configuration interval." << endl
00920          << "        partitionId            : " << partitionId << endl
00921          << "        _conditionCreationTime : " << _conditionCreationTime << endl
00922          << "        pCell.endInsertion     : " << pCell.endInsertion << endl
00923          << "}" << endl;
00924 /**********************************************************************************************************************/
00925 
00926                             continue;
00927                         }
00928                     }
00929                 }
00930 
00931               // Okay. This partition is fine. Dive into the partition.
00932 
00933               // ATTENTION:
00934               //
00935               //   Before diving we should reset the current iterator of objects
00936               //   to begin where the just found partition ends. We need it to resume
00937               //   iteration of objects from that time after we'll return from this partition.
00938               //
00939               //     [ Otherwise we may miss the rest of the current context, which can easily happen
00940               //       for example of the current hole is longer than a partition we're going
00941               //       to dive in. If we didn't do this then we would just miss any information
00942               //       between the end of the partition we're diving in and the end of the current 'hole'. ]
00943               //
00944               //    NOTE_1: In fact we have a similar (although not the same) problem when diving into
00945               //            MetaData within the same partition. However this problem is already solved below.
00946               //            These two cases are not equal because when we're diving into MetaDate only then
00947               //            we always reset its parameters (begin, end and iterator) since we use this MD object
00948               //            for the 'hole' only. Meanwhile in the current (diving into another partition case)
00949               //            we are not modifying the end time of the MD context, which we're going to reuse. Therefore we
00950               //            just can't modify the limits (begin, end) of the current context, just the iterator.
00951               //
00952               //    NOTE_2: Pay attention that iterator is reset only if the partition interval's where
00953               //            we're going to dive into does not last till +Infinity. In this specific case
00954               //            it does not make any sense to reset the iterator and also the iterator initialization
00955               //            operatio will simply fail to set up the iterator for the interval: [+Infinity,+Infinity).
00956               //
00957               //    NOTE_3: A similar to the previous NOTE_2 comment is that we'll reset the iterator
00958               //            only if the partition below wher we're going to dive into ends strictly
00959               //            _before_ the current one does. Otherwise we will wrongfully try to set up
00960               //            an iterator with 0 length, which will cause complains from the iterator.
00961 
00962                 if(( BdbTime::plusInfinity != iVal.end ) && ( iVal.end < _cxt._md[_cxt._mdCurrent].end )) {
00963 
00964                     _cxt._md[_cxt._mdCurrent].begin = iVal.end;
00965 
00966 /**************************************************************************************************************************************/
00967 if( CdbEnvironment::getDebugMode( ) != 0 )
00968     cout << debugStr << endl
00969          << "{" << endl
00970          << "    Resetting object iterator before to diving into a partition below the 'hole'." << endl
00971          << "    _cxt._md[" << _cxt._mdCurrent << "].begin    = " << time2string( _cxt._md[_cxt._mdCurrent].begin    ).c_str( ) << endl
00972          << "    _cxt._md[" << _cxt._mdCurrent << "].end      = " << time2string( _cxt._md[_cxt._mdCurrent].end      ).c_str( ) << endl
00973          << "    _cxt._md[" << _cxt._mdCurrent << "].revision = " << time2string( _cxt._md[_cxt._mdCurrent].revision ).c_str( ) << endl
00974          << "}" << endl;
00975 /**************************************************************************************************************************************/
00976 
00977                     if( CdbStatus::Success != _cxt._md[_cxt._mdCurrent].handle->objectIterator( _cxt._md[_cxt._mdCurrent].itr,
00978                                                                                                 _cxt._md[_cxt._mdCurrent].revision,
00979                                                                                                 _cxt._md[_cxt._mdCurrent].begin,
00980                                                                                                 _cxt._md[_cxt._mdCurrent].end )) {
00981                         cout << errorStr << endl
00982                              << "    Failed to reset the iterator of objects to begin where the partition we're" << endl
00983                              << "    diving in ends up." << endl;
00984                         return false;
00985                     }
00986                 }
00987 
00988               // Save curent context
00989 
00990                 _previousCxt.push( _cxt );
00991 
00992               // Prepare new current context
00993               //
00994               // NOTE: Unlike the very topmost context we're accepting all MetaData
00995               //       objects. Besides we're alway using "modification" time of each
00996               //       of these MD objects to determine their highest revisions.
00997 
00998                 _cxt._partitionId = iVal.id;
00999                 _cxt._begin       = iVal.begin;
01000                 _cxt._end         = iVal.end;
01001 
01002 /*******************************************************************************************/
01003 if( CdbEnvironment::getDebugMode( ) != 0 )
01004     cout << debugStr << endl
01005          << "{" << endl
01006          << "    Diving into a partition below the 'hole'." << endl
01007          << "        _previousCxt.size( ) = " << _previousCxt.size( ) << endl
01008          << "        _cxt._partitionId    = " << _cxt._partitionId << endl
01009          << "        _cxt._begin          = " << time2string( _cxt._begin ).c_str( ) << endl
01010          << "        _cxt._end            = " << time2string( _cxt._end ).c_str( ) << endl
01011          << "}" << endl;
01012 
01013 /*******************************************************************************************/
01014 
01015                 std::vector< BdbRef(CdbBdbSMetaDataP) > vectorOfMdRefs;
01016 
01017                 bool allIncrementsFlag = true;
01018 
01019                 if( CdbStatus::Success != findMetaData( vectorOfMdRefs,
01020                                                         _masterRegistryH,
01021                                                         _localRegistryH,
01022                                                         _extendedConditionId,
01023                                                         _cxt._partitionId,
01024                                                         allIncrementsFlag )) {
01025                     cout << errorStr << endl
01026                          << "    Failed to locate the MetaData objects for the current condition/partition." << endl;
01027                     break;
01028                 }
01029 
01030                 _cxt._md.clear( );
01031 
01032                 std::vector< BdbRef(CdbBdbSMetaDataP) >::size_type i;
01033                 std::vector< BdbRef(CdbBdbSMetaDataP) >::size_type num = vectorOfMdRefs.size( );
01034 
01035                 for( i = 0; i < num; ++i ) {
01036 
01037                     BdbHandle(CdbBdbSMetaDataP) mdH;
01038                     mdH = vectorOfMdRefs[i];
01039 
01040                     BdbTime modified = mdH->modified( );
01041                     assert( BdbTime::plusInfinity != modified );
01042 
01043                   // Check for special case of the topmost element of the stack of MD. We're going
01044                   // to set up both the iterator and the limits of this element since we have
01045                   // sufficient information for this.
01046 
01047                     if(( i + 1 ) >= num ) {
01048 
01049                       // Set up an iterator matching the revision.
01050 
01051                         CdbItr<CdbBdbSCi> itr;
01052                         if( CdbStatus::Success != mdH->objectIterator( itr,
01053                                                                        modified,
01054                                                                        _cxt._begin,
01055                                                                        _cxt._end )) {
01056                             cout << errorStr << endl
01057                                  << "    Failed to set up the iterator." << endl;
01058                             return false;
01059                         }
01060 
01061                       // Top element of the stack
01062 
01063                         _cxt._md.push_back( MD( mdH,
01064                                                 itr,
01065                                                 modified,
01066                                                 _cxt._begin,
01067                                                 _cxt._end ));
01068 
01069                     } else {
01070 
01071                       // This is a MetaData object below the top
01072 
01073                       // We're not establishing the composite objects iterator now
01074                       // because we don't know yet which validity range
01075                       // we're going to use this iterator for. This range will be defined
01076                       // by a "hole" in a MD above. Setting up the iterator now would
01077                       // also be very inefficient since we might never use it or we would need
01078                       // to skip many intervals in it due to ongoing development at above
01079                       // iterators.
01080 
01081                         _cxt._md.push_back( MD( mdH,
01082                                                 modified ));
01083                     }
01084                }
01085 
01086               // Switch to the topmost MD of the prepared context
01087 
01088                 if( 0 == _cxt._md.size( )) {
01089                     cout << errorStr << endl
01090                          << "    The database could be corrupted or be in an inconsistent state." << endl;
01091                     assert( 0 );
01092                     return false;
01093                 }
01094                 _cxt._mdCurrent = _cxt._md.size( ) - 1;
01095 
01096               // Done with context switch
01097 
01098                 found = true;
01099                 break;
01100             }
01101         }
01102         if( !found ) {
01103 
01104           // No more partitions below current one or the hole has ended. Then just proceed
01105           // with the next element at the bottom of the stack trying to hit a non-empty
01106           // one object or reach the end of the current MetaData object.
01107 
01108             _cxt._md[_cxt._mdCurrent].inHole = false;
01109         }
01110     }
01111 
01112   // Proceed within current PARTITION context and MD
01113 
01114     do {
01115 
01116         while( _cxt._md[_cxt._mdCurrent].itr.next( )) {
01117 
01118             CdbBdbSCi ci = _cxt._md[_cxt._mdCurrent].itr.value( );
01119 
01120 /**************************************************************************************************************************************/
01121 if( CdbEnvironment::getDebugMode( ) != 0 )
01122     cout << debugStr << endl
01123          << "{" << endl
01124          << "    _cxt._md[" << _cxt._mdCurrent << "].begin    = " << time2string( _cxt._md[_cxt._mdCurrent].begin    ).c_str( ) << endl
01125          << "    _cxt._md[" << _cxt._mdCurrent << "].end      = " << time2string( _cxt._md[_cxt._mdCurrent].end      ).c_str( ) << endl
01126          << "    _cxt._md[" << _cxt._mdCurrent << "].revision = " << time2string( _cxt._md[_cxt._mdCurrent].revision ).c_str( ) << endl
01127          << "    ci = " << ci << endl
01128          << "}" << endl;
01129 /**************************************************************************************************************************************/
01130 
01131           // Make adjustments for the validity time of the found interval if it's needed.
01132 
01133             BdbTime begin = ci.begin;
01134             BdbTime end   = ci.end;
01135 
01136             if( begin < _cxt._md[_cxt._mdCurrent].begin ) begin = _cxt._md[_cxt._mdCurrent].begin;
01137             if( end   > _cxt._md[_cxt._mdCurrent].end   ) end   = _cxt._md[_cxt._mdCurrent].end;
01138 
01139             assert( end >= begin );
01140 
01141           // Check if the validity of the found object is still within
01142           // the limits of the "md" entry at this level. If not then we should
01143           // back off to let the upper level (another "md" or "partition" or "configuration"
01144           // or the iterator ) to take further actions.
01145 
01146             if( begin >= _cxt._md[_cxt._mdCurrent].end ) {
01147 
01148                 _cxt._mdCurrent++;
01149                 if( _cxt._mdCurrent >= _cxt._md.size( )) {
01150 
01151                     if( _previousCxt.empty( )) return tryNextConfigElement( );
01152 
01153                   // One step up to previous partition
01154 
01155                     _cxt = _previousCxt.top( );
01156                     _previousCxt.pop( );
01157 
01158                   // Remove "inHole" flag from the previous partition's MD
01159 
01160                     _cxt._md[_cxt._mdCurrent].inHole = false;
01161 
01162                   // And proceed with next attemp to locate an object below.
01163 
01164                 }
01165                 return tryNextObject( );
01166 
01167             } else {
01168 
01169               // Check for a "hole". If there is one then we need to go down
01170               // the stack of MetaData.
01171 
01172                 if( ci.isEmpty ) {
01173 
01174                   // If we're at the bottom of the stack then we'll try to set up
01175                   // an iterator for partitions below the current one to see if we
01176                   // could proceed down.
01177 
01178                     if( 0 == _cxt._mdCurrent ) {
01179                         return tryNextPartition( begin, end );
01180                     }
01181                     _cxt._mdCurrent--;
01182 
01183                   // Prepare the MD object, including its validity limits and the iterator.
01184 
01185                     _cxt._md[_cxt._mdCurrent].begin = begin;
01186                     _cxt._md[_cxt._mdCurrent].end   = end;
01187 
01188                     if( CdbStatus::Success != _cxt._md[_cxt._mdCurrent].handle->objectIterator( _cxt._md[_cxt._mdCurrent].itr,
01189                                                                                                 _cxt._md[_cxt._mdCurrent].revision,
01190                                                                                                 _cxt._md[_cxt._mdCurrent].begin,
01191                                                                                                 _cxt._md[_cxt._mdCurrent].end )) {
01192                         cout << errorStr << endl
01193                              << "    Failed to set up the iterator." << endl;
01194                         return false;
01195                     }
01196 
01197                     return tryNextObject( );
01198 
01199                 } else {
01200 
01201                   // Construct the current value of the iterator and return with success.
01202 
01203                     if( CdbStatus::Success != CdbBdbObjectCreator::object( _value,
01204                                                                            _parent,
01205                                                                            ci.original.begin,       // begin of "original" period
01206                                                                            ci.original.end,         // begin of "original" period
01207                                                                            begin,
01208                                                                            end,
01209                                                                            ci.original.inserted,    // begin of "duration" period
01210                                                                            BdbTime::plusInfinity,   // end   of "duration" period
01211                                                                            ci.original.inserted,
01212                                                                            ci.original.object )) {
01213                         cout << errorStr << endl
01214                              << "    Failed to creae a generic object." << endl;
01215                         return false;
01216                     }
01217 
01218                     return true;
01219                 }
01220             }
01221 
01222         }
01223 
01224       // We may get here only if the iterator in the loop above got
01225       // beyond its last element while iterating over the bottom-most layer
01226       // of MD. So now we need either back off to the upper
01227       // MD object (if any), or previous partition (if any). Otherwise we back off to
01228       // the configuration.
01229 
01230         _cxt._mdCurrent++;
01231         if( _cxt._mdCurrent >= _cxt._md.size( )) {
01232 
01233             if( _previousCxt.empty( )) return tryNextConfigElement( );
01234 
01235           // One step up to previous partition
01236 
01237             _cxt = _previousCxt.top( );
01238             _previousCxt.pop( );
01239 
01240           // Remove "inHole" flag from the previous partition's MD
01241 
01242             _cxt._md[_cxt._mdCurrent].inHole = false;
01243 
01244           // And proceed with next attemp to locate an object withing the current method
01245           // but in the just "pop"-ped previous context.
01246         }
01247 
01248     } while( true );
01249 
01250     return false;
01251 }
01252 
01253 bool
01254 PartitionableObjectIterator::findPartition( BdbHandle(CdbBdbSPartitionP)& theHandle,
01255                                             d_UShort                      thePartitionId )
01256 {
01257     const char* errorStr = "CdbBdbSCondition::PartitionableObjectIterator::findPartition() -- ERROR";
01258 
01259     bool result = false;
01260     do {
01261 
01262       // The temporary partition reference required by some interfaces.
01263 
01264         BdbRef(CdbBdbSPartitionP) pRef;
01265 
01266       // The partition location can be a two-stage process, First we look for general
01267       // partition information at the MASTER registry. Then we need to verify if the
01268       // found partition belongs to the local registry. If so then we reload
01269       // partition information from the local registry since this partition
01270       // is supposed to be modified locally.
01271 
01272         BdbRef(CdbBdbSPartitionsLayoutP) pLayoutRef = _masterRegistryH->partitionsLayout( );
01273         assert( ! BdbIsNull(pLayoutRef));
01274 
01275         if( CdbStatus::Success != pLayoutRef->find( thePartitionId,
01276                                                     pRef )) {
01277             cout << errorStr << endl
01278                      << "    Failed to find a partition #" << thePartitionId << " at the master registry." << endl;
01279             break;
01280         }
01281         theHandle = pRef;
01282 
01283         if(( _localRegistryH->originId( ) == theHandle->originId( )) &&
01284            ( _localRegistryH->originId( ) != _masterRegistryH->originId( ))) {
01285 
01286             pLayoutRef = _localRegistryH->partitionsLayout( );
01287             assert( ! BdbIsNull(pLayoutRef));
01288 
01289             if( CdbStatus::Success != pLayoutRef->find( thePartitionId,
01290                                                         pRef )) {
01291                 cout << errorStr << endl
01292                      << "    Failed to find a partition #" << thePartitionId << " at the local registry." << endl;
01293                 break;
01294             }
01295             theHandle = pRef;
01296         }
01297 
01298       // Done.
01299 
01300         result = true;
01301 
01302     } while( false );
01303 
01304     return result;
01305 }
01306 
01307 bool
01308 PartitionableObjectIterator::tryNextConfigElement( )
01309 {
01310     const char* debugStr = "CdbBdbSCondition::PartitionableObjectIterator::tryNextConfigElement()";
01311     const char* errorStr = "CdbBdbSCondition::PartitionableObjectIterator::tryNextConfigElement() -- ERROR";
01312 
01313 /******************************************************************/
01314 if( CdbEnvironment::getDebugMode( ) != 0 )
01315     cout << debugStr << endl
01316          << "{" << endl
01317          << "    ENTERING THE METHOD..." << endl
01318          << "}" << endl;
01319 /******************************************************************/
01320 
01321     while( _configItr.next( )) {
01322 
01323       // Get rid of any previous contexts of partitions
01324 
01325         _previousCxt = std::stack<PARTITION>( );
01326 
01327       // Get next element
01328       //
01329       // Skip the whole configuration interval if the found
01330       // configuration element will say so.
01331       //
01332       // ATTENTION: If the config element says "do not use revisions"
01333       //            then we just ignore this statement and replace it
01334       //            with "use topmost revisiono instead."
01335 
01336         CdbBdbSConfigInterval in = _configItr.value( );
01337         if( ! in.value.accessIsAllowed( )) continue;
01338 
01339         _beginConfig = in.begin;
01340         _endConfig   = in.end;
01341 
01342         if( in.value.useRevision ) _revisionId = in.value.revision;
01343         else                       _revisionId = BdbTime::plusInfinity;
01344 
01345         _cxt._partitionId = in.value.partition;
01346 
01347       // Check if we need to skip or shorten this configuration element
01348       // because the specified iterator's range:
01349       //
01350       //     _begin   _end       ACTION:
01351       //          :   :
01352       //      [---)   :          1: skip
01353       //      [---:---)          2: cut on the left only
01354       //      [---:---:---)      3: cut on the left and on the right
01355       //          [---)          4: none
01356       //          [---:---)      5: cut on the right only
01357       //          :   [---)      6: finish (not found)
01358 
01359         if( _endConfig   <= _begin ) continue;              // #1
01360         if( _beginConfig >= _end   ) break;                 // #6
01361         if( _beginConfig < _begin  ) _beginConfig = _begin; // #2, #3
01362         if( _endConfig   > _end    ) _endConfig   = _end;   // #3, #5
01363 
01364         _cxt._begin = _beginConfig;
01365         _cxt._end   = _endConfig;
01366 
01367       // Find out the partition to see if it's in the "closed" state. If so then we need
01368       // to check if its upper "insertion" time boundry is not older than the creation
01369       // time of the condition. If it happens that the condition is newer than the partition
01370       // closeout time then we just bail out since there should not be any MetaData information
01371       // in this partition for our current condition. Then we skip this config element.
01372 
01373         {
01374             BdbHandle(CdbBdbSPartitionP) pH;
01375             if( ! findPartition( pH, _cxt._partitionId )) {
01376                 cout << errorStr << endl
01377                      << "    Failed to locate the partition with ID=" << _cxt._partitionId << endl;
01378                 break;
01379             }
01380 
01381 /******************************************************************/
01382 if( CdbEnvironment::getDebugMode( ) != 0 )
01383     cout << debugStr << endl
01384          << "{" << endl
01385          << "    Found partition ID=" << pH->id( ) << endl
01386          << "}" << endl;
01387 /******************************************************************/
01388 
01389             if( pH->isClosed( )) {
01390                 CdbBdbSCell pCell = pH->cell( );
01391                 if( pCell.endInsertion <= _conditionCreationTime ) {
01392 
01393 /**********************************************************************************************************************/
01394 if( CdbEnvironment::getDebugMode( ) != 0 )
01395     cout << debugStr << endl
01396          << "{" << endl
01397          << "    The above found partition required by the current configuration interval is already 'closed'" << endl
01398          << "    and its upper 'insertion' time limit is older than the creation time of the current condition." << endl
01399          << "    Skipping the current configuration interval." << endl
01400          << "        _cxt._partitionId      : " << _cxt._partitionId << endl
01401          << "        _conditionCreationTime : " << _conditionCreationTime << endl
01402          << "        pCell.endInsertion     : " << pCell.endInsertion << endl
01403          << "}" << endl;
01404 /**********************************************************************************************************************/
01405 
01406                     continue;
01407                 }
01408             }
01409         }
01410 
01411       // Build a stack of MetaData for the found element. This operation is done
01412       // in the folowing steps:
01413       //
01414       //   1) Get a list of all MetaData objects for specified condition/partition.
01415       //
01416       //   2) Find the MetaData corresponding to specified revision.
01417       //
01418       //   3) Discard any MetaData-s above the one containing specified revision
01419       //      and keep the others.
01420       //
01421       //   4) Create a vector of objects of the nested MD class. The rules for these
01422       //      objects differ for the top element in the vector and thoses below it:
01423       //
01424       //      - top element always gets the original revision ID established above.
01425       //        Its composite objects iterator is also set up for a validity
01426       //        interval of the current configuration element.
01427       //
01428       //      - other elements are set up with their most recent revisions
01429       //        corresponding to the "modified" time of these MD objects.
01430       //        Their composite objects iterators are not set.
01431 
01432         std::vector< BdbRef(CdbBdbSMetaDataP) > vectorOfMdRefs;
01433 
01434         bool allIncrementsFlag = true;
01435 
01436         if( CdbStatus::Success !=  findMetaData( vectorOfMdRefs,
01437                                                  _masterRegistryH,
01438                                                  _localRegistryH,
01439                                                  _extendedConditionId,
01440                                                  _cxt._partitionId,
01441                                                  allIncrementsFlag )) {
01442             cout << errorStr << endl
01443                  << "    Failed to locate the MetaData objects for the current condition/partition." << endl;
01444             break;
01445         }
01446 
01447         const std::vector< BdbRef(CdbBdbSMetaDataP) >::size_type numPart = vectorOfMdRefs.size( );
01448         if( 0 == numPart ) {
01449             cout << errorStr << endl
01450                  << "    There is no MetaData objects for the current condition/partition." << endl
01451                  << "    The condition/partition could not be properly initialized/loaded." << endl;
01452             break;
01453         }
01454 
01455         _cxt._md.clear( );
01456 
01457         for( std::vector< BdbRef(CdbBdbSMetaDataP) >::size_type i = 0; i < numPart; ++i ) {
01458 
01459             BdbHandle(CdbBdbSMetaDataP) mdH;
01460             mdH = vectorOfMdRefs[i];
01461 
01462             if( _revisionId >= mdH->minInsertion( )) {
01463 
01464               // Three ways to set up the MD at the context:
01465               //
01466               //   1: This is for a top MD element (not nessesarily the top at the input
01467               //      vector) only. This is the last MD including specified revision.
01468               //
01469               //        1.1: We also cover the case of the topmost revision at
01470               //             "open" partitions.
01471               //
01472               //   2: This is a variation of the 1.1 case above for "closed" partitions.
01473               //      The reason why we put it into a special case is that "closed" partitions
01474               //      do not have the topmost revision. HOwever we still need to provide
01475               //      backward compatibility for teh old views configured for the topmost
01476               //      revision in the same way it's done for regular conditions.
01477               //      Here we map the topmost revision onto the final revision of the MD object
01478               //      whose actual revision iD corresponds to the revision modification timestamp.
01479               //
01480               //   3. In the final case of the non-top MD objects we use the modification
01481               //      timestamp of the MD object as the revision identifier.
01482 
01483                 if((( BdbTime::plusInfinity == _revisionId ) && ( BdbTime::plusInfinity == mdH->maxInsertion( ))) ||
01484                    ( _revisionId < mdH->maxInsertion( ))) {
01485 
01486                   // -1-
01487 
01488                   // Set up an iterator matching the exact revision.
01489 
01490                     CdbItr<CdbBdbSCi> itr;
01491                     if( CdbStatus::Success != mdH->objectIterator( itr,
01492                                                                    _revisionId,
01493                                                                    _beginConfig,
01494                                                                    _endConfig )) {
01495                         cout << errorStr << endl
01496                              << "    Failed to set up the iterator." << endl;
01497                         return false;
01498                     }
01499 
01500                   // Top element of the stack
01501 
01502                     _cxt._md.push_back( MD( mdH,
01503                                             itr,
01504                                             _revisionId,
01505                                             _cxt._begin,
01506                                             _cxt._end ));
01507 
01508 /**************************************************************************************************************************************/
01509 if( CdbEnvironment::getDebugMode( ) != 0 )
01510     cout << debugStr << endl
01511          << "{" << endl
01512          << "    Case #1: Regular top MetaData/Increment object which has exactly the required" << endl
01513          << "             revision. This use case also include 'open' partition and 'topmost' revision." << endl
01514          << "    {" << endl
01515          << "        _cxt._partitionId    = " << _cxt._partitionId << endl
01516          << "        _cxt._begin          = " << time2string( _cxt._begin ).c_str( ) << endl
01517          << "        _cxt._end            = " << time2string( _cxt._end ).c_str( ) << endl
01518          << "        mdH->minInsertion( ) = " << time2string( mdH->minInsertion( )).c_str( ) << endl
01519          << "        mdH->maxInsertion( ) = " << time2string( mdH->maxInsertion( )).c_str( ) << endl
01520          << "        _revisionId          = " << time2string( _revisionId ).c_str( ) << endl
01521          << "    }" << endl
01522          << "}" << endl;
01523 /**************************************************************************************************************************************/
01524 
01525                   // Since we found the top MD objects so we need to stop here.
01526 
01527                     break;
01528 
01529                 } else if((( numPart - 1 ) == i ) &&
01530                           ( BdbTime::plusInfinity == _revisionId ) &&
01531                           ( BdbTime::plusInfinity != mdH->maxInsertion( ))){
01532 
01533                   // -2-
01534 
01535                   // Set up an iterator matching the final revision of the MD object.
01536 
01537                     BdbTime modified = mdH->modified( );
01538 
01539                     CdbItr<CdbBdbSCi> itr;
01540                     if( CdbStatus::Success != mdH->objectIterator( itr,
01541                                                                    modified,
01542                                                                    _beginConfig,
01543                                                                    _endConfig )) {
01544                         cout << errorStr << endl
01545                              << "    Failed to set up the iterator." << endl;
01546                         return false;
01547                     }
01548 
01549                   // Top element of the stack
01550 
01551                     _cxt._md.push_back( MD( mdH,
01552                                             itr,
01553                                             modified,
01554                                             _cxt._begin,
01555                                             _cxt._end ));
01556 
01557 /**************************************************************************************************************************************/
01558 if( CdbEnvironment::getDebugMode( ) != 0 )
01559     cout << debugStr << endl
01560          << "{" << endl
01561          << "    Case #2. Special case of a 'closed' partition when the 'topmost' (+Infinity)" << endl
01562          << "             revision identifier is required by the view configuration." << endl
01563          << "             The solution in this case is to find out the most recent reveision in this" << endl
01564          << "             partition and to treat it as the topmost one. The identifier of this most" << endl
01565          << "             recent revision is equal to the 'modified' time of the top MetaData/Increment" << endl
01566          << "             object of the partition." << endl
01567          << "    {" << endl
01568          << "        _cxt._partitionId    = " << _cxt._partitionId << endl
01569          << "        _cxt._begin          = " << time2string( _cxt._begin ).c_str( ) << endl
01570          << "        _cxt._end            = " << time2string( _cxt._end ).c_str( ) << endl
01571          << "        mdH->minInsertion( ) = " << time2string( mdH->minInsertion( )).c_str( ) << endl
01572          << "        mdH->maxInsertion( ) = " << time2string( mdH->maxInsertion( )).c_str( ) << endl
01573          << "        modified             = " << time2string( modified ).c_str( ) << endl
01574          << "    }" << endl
01575          << "}" << endl;
01576 /**************************************************************************************************************************************/
01577 
01578                 } else {
01579 
01580                   // -3-
01581 
01582                   // It will use the MetaData object's modification time
01583                   // time to set up the composite object iterator. We're not establishing
01584                   // this iterator now because we don't know yet which validity range
01585                   // we're going to use this iterator for. This range will be defined
01586                   // by a "hole" in a revision above. Setting up the iterator now would
01587                   // also be veru inefficient since we might never use it or we would need
01588                   // to skip many intervals in it due to ongoing development at above
01589                   // iterators.
01590 
01591                     BdbTime modified = mdH->modified( );
01592                     assert( BdbTime::plusInfinity != modified );
01593 
01594                     _cxt._md.push_back( MD( mdH,
01595                                         modified ));
01596 
01597 /**************************************************************************************************************************************/
01598 if( CdbEnvironment::getDebugMode( ) != 0 )
01599     cout << debugStr << endl
01600          << "{" << endl
01601          << "    Case #3: MetaData/Increment object below the topmost one for this partition." << endl
01602          << "             We should use the 'modified' time of this MetaData/Increment object as an actual" << endl
01603          << "             revision identifier." << endl
01604          << "    {" << endl
01605          << "        _cxt._partitionId    = " << _cxt._partitionId << endl
01606          << "        _cxt._begin          = " << time2string( _cxt._begin ).c_str( ) << endl
01607          << "        _cxt._end            = " << time2string( _cxt._end ).c_str( ) << endl
01608          << "        mdH->minInsertion( ) = " << time2string( mdH->minInsertion( )).c_str( ) << endl
01609          << "        mdH->maxInsertion( ) = " << time2string( mdH->maxInsertion( )).c_str( ) << endl
01610          << "        modified             = " << time2string( modified ).c_str( ) << endl
01611          << "    }" << endl
01612          << "}" << endl;
01613 /**************************************************************************************************************************************/
01614 
01615                 }
01616 
01617             } else {
01618 
01619               // We're above specified revision.
01620 
01621                 break;
01622             }
01623         }
01624         if( 0 == _cxt._md.size( )) {
01625             cout << errorStr << endl
01626                  << "    The database could be corrupted or be in an inconsistent state." << endl;
01627             assert( 0 );
01628             return false;
01629         }
01630         _cxt._mdCurrent = _cxt._md.size( ) - 1;
01631 
01632 /***************************************************************/
01633 if( CdbEnvironment::getDebugMode( ) != 0 )
01634     cout << debugStr << endl
01635          << "{" << endl
01636          << "    _cxt._mdCurrent = " << _cxt._mdCurrent << endl
01637          << "}" << endl;
01638 /***************************************************************/
01639 
01640       // Proceed down to the first element in the stack
01641 
01642         if( tryNextObject( )) return true;
01643     }
01644 
01645     return false;
01646 }
01647 
01648 //////////////////////////////////
01649 // Class: RegularObjectIterator //
01650 //////////////////////////////////
01651 
01652 class RegularObjectIterator : public CdbObjectItr::InterfaceType {
01653 
01654 private:
01655 
01656     RegularObjectIterator( );
01657 
01658     RegularObjectIterator& operator=( const RegularObjectIterator& theItr );
01659 
01660 protected:
01661 
01662     RegularObjectIterator( const RegularObjectIterator& theItr ) :
01663 
01664         _parent             (theItr._parent),
01665         _begin              (theItr._begin),
01666         _end                (theItr._end),
01667         _configItr          (theItr._configItr),
01668         _masterRegistryH    (theItr._masterRegistryH),
01669         _localRegistryH     (theItr._localRegistryH),
01670         _extendedConditionId(theItr._extendedConditionId),
01671 
01672         _isValid            (theItr._isValid),
01673         _hasEverBeenAdvanced(theItr._hasEverBeenAdvanced),
01674         _value              (theItr._value),
01675 
01676         _beginConfig        (theItr._beginConfig),
01677         _endConfig          (theItr._endConfig),
01678         _revisionId         (theItr._revisionId),
01679         _partitionId        (theItr._partitionId),
01680 
01681         _md                 (theItr._md),
01682         _mdCurrent          (theItr._mdCurrent)
01683     { }
01684 
01685 public:
01686 
01687   /// Normal constructor
01688   /**
01689     * If the configuration collection parameter is pointing onto a zero object
01690     * then the revision policy must be used.
01691     */
01692     RegularObjectIterator( const CdbConditionPtr&                theParentPtr,
01693                            const BdbTime&                        theBegin,
01694                            const BdbTime&                        theEnd,
01695                            const CdbItr< CdbBdbSConfigInterval > theConfigItr,
01696                            const BdbHandle(CdbBdbSRegistryP)&    theMasterRegistryH,
01697                            const BdbHandle(CdbBdbSRegistryP)&    theLocalRegistryH,
01698                            const CdbBdbSId&                      theExtendedConditionId ) :
01699         _parent             (theParentPtr),
01700         _begin              (theBegin),
01701         _end                (theEnd),
01702         _configItr          (theConfigItr),
01703         _masterRegistryH    (theMasterRegistryH),
01704         _localRegistryH     (theLocalRegistryH),
01705         _extendedConditionId(theExtendedConditionId),
01706         _isValid            (false),
01707         _hasEverBeenAdvanced(false)
01708     { }
01709 
01710     virtual ~RegularObjectIterator( )
01711     { }
01712 
01713     virtual CdbStatus reset( )
01714     {
01715         _isValid             = false;
01716         _hasEverBeenAdvanced = false;
01717 
01718         return CdbStatus::Success;
01719     }
01720 
01721     bool tryNextObject( );
01722     bool tryNextConfigElement( );
01723 
01724     virtual bool next( )
01725     {
01726         if( _hasEverBeenAdvanced ) {
01727             if( ! _isValid ) {
01728 
01729               // Stay at BEYOND_PAST_ELEMENT state
01730 
01731                 ;
01732 
01733             } else {
01734 
01735               // Try to get next object...
01736 
01737                 _isValid = tryNextObject( );
01738             }
01739 
01740         } else {
01741 
01742           // Set up initial context of the iterator. Then proceed down
01743           // to the first object of the collection starting from the configuration.
01744 
01745             _configItr.reset( );
01746 
01747             _hasEverBeenAdvanced = true;
01748             _isValid             = tryNextConfigElement( );
01749         }
01750         return _isValid;
01751     }
01752 
01753     virtual ValueType value( )
01754     {
01755         if( ! _isValid ) {
01756             assert( 0 );
01757         }
01758         return _value;
01759     }
01760 
01761     virtual bool isValid( )
01762     {
01763         return _isValid;
01764     }
01765 
01766     virtual InterfaceType* clone( ) const
01767     {
01768         return new RegularObjectIterator( *this );
01769     }
01770 
01771 private:
01772 
01773   // Parameters
01774 
01775     CdbConditionPtr _parent;
01776 
01777     BdbTime _begin;
01778     BdbTime _end;
01779 
01780     CdbItr< CdbBdbSConfigInterval > _configItr;
01781 
01782     BdbHandle(CdbBdbSRegistryP) _masterRegistryH;
01783     BdbHandle(CdbBdbSRegistryP) _localRegistryH;
01784 
01785     CdbBdbSId _extendedConditionId;
01786 
01787   // The current state
01788 
01789     bool _isValid;
01790     bool _hasEverBeenAdvanced;
01791 
01792     CdbObjectPtr _value;
01793 
01794   // The context : configuration element
01795 
01796     BdbTime _beginConfig;
01797     BdbTime _endConfig;
01798     BdbTime _revisionId;
01799 
01800     d_UShort _partitionId;
01801 
01802   // The context : meta-data
01803 
01804     class MD {
01805 
01806     public:
01807 
01808         MD( ) { }
01809 
01810         MD( const BdbHandle(CdbBdbSMetaDataP)& theMetaDataH,
01811             const BdbTime&                     theRevisionId ) :
01812             handle  (theMetaDataH ),
01813             revision(theRevisionId) { }
01814 
01815         MD( const BdbHandle(CdbBdbSMetaDataP)& theMetaDataH,
01816             const CdbItr<CdbBdbSCi>&           theObjectItr,
01817             const BdbTime&                     theRevisionId,
01818             const BdbTime&                     theBeginTime,
01819             const BdbTime&                     theEndTime ) :
01820             handle  (theMetaDataH ),
01821             itr     (theObjectItr ),
01822             revision(theRevisionId),
01823             begin   (theBeginTime ),
01824             end     (theEndTime   ) { }
01825 
01826         MD( const MD& theMd ) :
01827             handle  (theMd.handle  ),
01828             itr     (theMd.itr     ),
01829             revision(theMd.revision),
01830             begin   (theMd.begin   ),
01831             end     (theMd.end     ) { }
01832 
01833         ~MD( ) { }
01834 
01835         MD& operator=( const MD& theMd )
01836         {
01837             if( this != &theMd ) {
01838                 handle   = theMd.handle;
01839                 itr      = theMd.itr;
01840                 revision = theMd.revision;
01841                 begin    = theMd.begin;
01842                 end      = theMd.end;
01843             }
01844             return *this;
01845         }
01846 
01847     public:
01848 
01849         BdbHandle(CdbBdbSMetaDataP) handle;
01850 
01851         CdbItr<CdbBdbSCi> itr;
01852 
01853         BdbTime revision;
01854         BdbTime begin;
01855         BdbTime end;
01856     };
01857     std::vector< MD >            _md;
01858     std::vector< MD >::size_type _mdCurrent;
01859 
01860   // The context : object
01861 };
01862 
01863 bool
01864 RegularObjectIterator::tryNextObject( )
01865 {
01866     const char* debugStr = "CdbBdbSCondition::RegularObjectIterator::tryNextObject()";
01867     const char* errorStr = "CdbBdbSCondition::RegularObjectIterator::tryNextObject() -- ERROR";
01868 
01869     assert( _md.size( ) > 0 );
01870     assert( _mdCurrent < _md.size( ));
01871 
01872     do {
01873 
01874         while( _md[_mdCurrent].itr.next( )) {
01875 
01876             CdbBdbSCi ci = _md[_mdCurrent].itr.value( );
01877 
01878 /**************************************************************************************************************/
01879 if( CdbEnvironment::getDebugMode( ) != 0 )
01880     cout << debugStr << endl
01881          << "{" << endl
01882          << "    _md[" << _mdCurrent << "].begin    = " << time2string( _md[_mdCurrent].begin    ).c_str( ) << endl
01883          << "    _md[" << _mdCurrent << "].end      = " << time2string( _md[_mdCurrent].end      ).c_str( ) << endl
01884          << "    _md[" << _mdCurrent << "].revision = " << time2string( _md[_mdCurrent].revision ).c_str( ) << endl
01885          << "    ci = " << ci << endl
01886          << "}" << endl;
01887 /**************************************************************************************************************/
01888 
01889           // Make adjustments for the validity time of the found interval if it's needed.
01890 
01891             BdbTime begin = ci.begin;
01892             BdbTime end   = ci.end;
01893 
01894             if( begin < _md[_mdCurrent].begin ) begin = _md[_mdCurrent].begin;
01895             if( end   > _md[_mdCurrent].end   ) end   = _md[_mdCurrent].end;
01896 
01897             assert( end >= begin );
01898 
01899           // Check if the validity of the found object is still within
01900           // the limits of the "md" entry at this level. If not then we should
01901           // back off to let the upper level (another "md" or "configuration"
01902           // or the iterator ) to take further actions.
01903 
01904             if( begin >= _md[_mdCurrent].end ) {
01905 
01906                 _mdCurrent++;
01907                 if( _mdCurrent >= _md.size( )) return tryNextConfigElement( );
01908 
01909                 return tryNextObject( );
01910 
01911             } else {
01912 
01913               // Check for a "hole". If there is one then we need to go down
01914               // the stack of MetaData.
01915 
01916                 if( ci.isEmpty ) {
01917 
01918                   // If we're at the bottom of the stack then we have nowhere
01919                   // else to look for intervals. So we'll try to proceed down along
01920                   // the validity time dimension hoping to hit a non-zero object.
01921 
01922                     if( 0 == _mdCurrent ) continue;
01923                     _mdCurrent--;
01924 
01925                   // Prepare the MD object, including its validity limits and the iterator.
01926 
01927                     _md[_mdCurrent].begin = begin;
01928                     _md[_mdCurrent].end   = end;
01929 
01930                     if( CdbStatus::Success != _md[_mdCurrent].handle->objectIterator( _md[_mdCurrent].itr,
01931                                                                                       _md[_mdCurrent].revision,
01932                                                                                       _md[_mdCurrent].begin,
01933                                                                                       _md[_mdCurrent].end )) {
01934                         cout << errorStr << endl
01935                              << "    Failed to set up the iterator." << endl;
01936                         return false;
01937                     }
01938 
01939                     return tryNextObject( );
01940 
01941                 } else {
01942 
01943                   // Construct the current value of the iterator and return with success.
01944 
01945                     if( CdbStatus::Success != CdbBdbObjectCreator::object( _value,
01946                                                                            _parent,
01947                                                                            ci.original.begin,       // begin of "original" period
01948                                                                            ci.original.end,         // begin of "original" period
01949                                                                            begin,
01950                                                                            end,
01951                                                                            ci.original.inserted,    // begin of "duration" period
01952                                                                            BdbTime::plusInfinity,   // end   of "duration" period
01953                                                                            ci.original.inserted,
01954                                                                            ci.original.object )) {
01955                         cout << errorStr << endl
01956                              << "    Failed to creae a generic object." << endl;
01957                         return false;
01958                     }
01959 
01960                     return true;
01961                 }
01962             }
01963 
01964         }
01965 
01966       // We may gete here only of the iterator in the loop above got
01967       // beyond its last element while iterating over the bottom-most layer
01968       // of MD. So now we need either back off to the upper
01969       // MD object (if any). Otherwise we back off to the configuration.
01970 
01971         _mdCurrent++;
01972         if( _mdCurrent >= _md.size( )) return tryNextConfigElement( );
01973 
01974     } while( true );
01975 
01976     return false;
01977 }
01978 
01979 bool
01980 RegularObjectIterator::tryNextConfigElement( )
01981 {
01982     const char* debugStr = "CdbBdbSCondition::RegularObjectIterator::tryNextConfigElement()";
01983     const char* errorStr = "CdbBdbSCondition::RegularObjectIterator::tryNextConfigElement() -- ERROR";
01984 
01985     while( _configItr.next( )) {
01986 
01987       // Get next element
01988       //
01989       // Skip the whole configuration interval if the found
01990       // configuration element will say so.
01991       //
01992       // ATTENTION: If the config element says "do not use revisions"
01993       //            then we just ignore this statement and replace it
01994       //            with "use topmost revisiono instead."
01995 
01996         CdbBdbSConfigInterval in = _configItr.value( );
01997         if( ! in.value.accessIsAllowed( )) continue;
01998 
01999         _beginConfig = in.begin;
02000         _endConfig   = in.end;
02001 
02002         if( in.value.useRevision ) _revisionId = in.value.revision;
02003         else                       _revisionId = BdbTime::plusInfinity;
02004 
02005         _partitionId = in.value.partition;
02006 
02007       // Check if we need to skip or shorten this configuration element
02008       // because the specified iterator's range:
02009       //
02010       //     _begin   _end       ACTION:
02011       //          :   :
02012       //      [---)   :          1: skip
02013       //      [---:---)          2: cut on the left only
02014       //      [---:---:---)      3: cut on the left and on the right
02015       //          [---)          4: none
02016       //          [---:---)      5: cut on the right only
02017       //          :   [---)      6: finish (not found)
02018 
02019         if( _endConfig   <= _begin ) continue;              // #1
02020         if( _beginConfig >= _end   ) break;                 // #6
02021         if( _beginConfig < _begin  ) _beginConfig = _begin; // #2, #3
02022         if( _endConfig   > _end    ) _endConfig   = _end;   // #3, #5
02023 
02024       // Build a stack of MetaData for the found element. This operation is done
02025       // in the folowing steps:
02026       //
02027       //   1) Get a list of all MetaData objects for specified condition/partition.
02028       //
02029       //   2) Find the MetaData corresponding to specified revision.
02030       //
02031       //   3) Discard any MetaData-s above the one containing specified revision
02032       //      and keep the others.
02033       //
02034       //   4) Create a vector of objects of the nested MD class. The rules for these
02035       //      objects differ for the top element in the vector and thoses below it:
02036       //
02037       //      - top element always gets the original revision ID established above.
02038       //        Its composite objects iterator is also set up for a validity
02039       //        interval of the current configuration element.
02040       //
02041       //      - other elements are set up with their most recent revisions
02042       //        corresponding to the "modified" time of these MD objects.
02043       //        Their composite objects iterators are not set.
02044 
02045         std::vector< BdbRef(CdbBdbSMetaDataP) > vectorOfMdRefs;
02046 
02047         bool allIncrementsFlag = true;
02048 
02049         if( CdbStatus::Success !=  findMetaData( vectorOfMdRefs,
02050                                                  _masterRegistryH,
02051                                                  _localRegistryH,
02052                                                  _extendedConditionId,
02053                                                  _partitionId,
02054                                                  allIncrementsFlag )) {
02055             cout << errorStr << endl
02056                  << "    Failed to locate the MetaData objects for the current condition/partition." << endl;
02057             break;
02058         }
02059 
02060         _md.clear( );
02061 
02062         for( std::vector< BdbRef(CdbBdbSMetaDataP) >::size_type i = 0; i < vectorOfMdRefs.size( ); ++i ) {
02063 
02064             BdbHandle(CdbBdbSMetaDataP) mdH;
02065             mdH = vectorOfMdRefs[i];
02066 
02067             if( _revisionId >= mdH->minInsertion( )) {
02068 
02069               // Check for a separate case of the top element in the stack. Don't forget
02070               // about a special case when we have the topmost revision since this require
02071               // more relaxing check on the upper border of the MetaData object.
02072 
02073                 if((( BdbTime::plusInfinity == _revisionId ) && ( BdbTime::plusInfinity == mdH->maxInsertion( )))
02074                     ||
02075                     ( _revisionId < mdH->maxInsertion( ))) {
02076 
02077                   // Set up an iterator matching the revision.
02078 
02079                     CdbItr<CdbBdbSCi> itr;
02080                     if( CdbStatus::Success != mdH->objectIterator( itr,
02081                                                                    _revisionId,
02082                                                                    _beginConfig,
02083                                                                    _endConfig )) {
02084                         cout << errorStr << endl
02085                              << "    Failed to set up the iterator." << endl;
02086                         return false;
02087                     }
02088 
02089                   // Top element of the stack
02090 
02091                     _md.push_back( MD( mdH,
02092                                        itr,
02093                                        _revisionId,
02094                                        _beginConfig,
02095                                        _endConfig ));
02096 
02097                   // At the next step we'll be above specified revision.
02098 
02099                     break;
02100 
02101                 } else {
02102 
02103                   // This is a MetaData object below the top
02104 
02105                   // It will use the MetaData object's modification time
02106                   // time to set up the composite object iterator. We're not establishing
02107                   // this iterator now because we don't know yet which validity range
02108                   // we're going to use this iterator for. This range will be defined
02109                   // by a "hole" in a revision above. Setting up the iterator now would
02110                   // also be veru inefficient since we might never use it or we would need
02111                   // to skip many intervals in it due to ongoing development at above
02112                   // iterators.
02113 
02114                     BdbTime modified = mdH->modified( );
02115                     assert( BdbTime::plusInfinity != modified );
02116 
02117                     _md.push_back( MD( mdH,
02118                                        modified ));
02119                 }
02120 
02121             } else {
02122 
02123               // We're above specified revision.
02124 
02125                 break;
02126             }
02127         }
02128         if( 0 == _md.size( )) {
02129             cout << errorStr << endl
02130                  << "    The database could be corrupted or be in an inconsistent state." << endl;
02131             assert( 0 );
02132             return false;
02133         }
02134         _mdCurrent = _md.size( ) - 1;
02135 
02136 /*****************************************************/
02137 if( CdbEnvironment::getDebugMode( ) != 0 )
02138     cout << debugStr << endl
02139          << "{" << endl
02140          << "    _mdCurrent = " << _mdCurrent << endl
02141          << "}" << endl;
02142 /*****************************************************/
02143 
02144       // Proceed down to the first element in the stack
02145 
02146         if( tryNextObject( )) return true;
02147     }
02148 
02149     return false;
02150 }
02151 
02152 ///////////////////////////////////
02153 // Class: OriginalObjectIterator //
02154 ///////////////////////////////////
02155 
02156 class OriginalObjectIterator : public CdbObjectItr::InterfaceType {
02157 
02158 private:
02159 
02160     OriginalObjectIterator( );
02161 
02162     OriginalObjectIterator& operator=( const OriginalObjectIterator& theItr );
02163 
02164 protected:
02165 
02166     OriginalObjectIterator( const OriginalObjectIterator& theItr ) :
02167 
02168         _parent                (theItr._parent),
02169         _begin                 (theItr._begin),
02170         _end                   (theItr._end),
02171         _masterRegistryH       (theItr._masterRegistryH),
02172         _localRegistryH        (theItr._localRegistryH),
02173         _extendedConditionId   (theItr._extendedConditionId),
02174         _partitionId           (theItr._partitionId),
02175 
02176         _isValid               (theItr._isValid),
02177         _hasEverBeenAdvanced   (theItr._hasEverBeenAdvanced),
02178         _value                 (theItr._value),
02179 
02180         _md                    (theItr._md),
02181         _mdCurrent             (theItr._mdCurrent),
02182         _mdCurrentOiCollectionH(theItr._mdCurrentOiCollectionH),
02183         _mdCurrentOi           (theItr._mdCurrentOi)
02184     { }
02185 
02186 public:
02187 
02188     OriginalObjectIterator( const CdbConditionPtr&             theParentPtr,
02189                             const BdbTime&                     theBegin,
02190                             const BdbTime&                     theEnd,
02191                             const BdbHandle(CdbBdbSRegistryP)& theMasterRegistryH,
02192                             const BdbHandle(CdbBdbSRegistryP)& theLocalRegistryH,
02193                             const CdbBdbSId&                   theExtendedConditionId,
02194                             const d_UShort                     thePartitionId ) :
02195         _parent             (theParentPtr),
02196         _begin              (theBegin),
02197         _end                (theEnd),
02198         _masterRegistryH    (theMasterRegistryH),
02199         _localRegistryH     (theLocalRegistryH),
02200         _extendedConditionId(theExtendedConditionId),
02201         _partitionId        (thePartitionId),
02202         _isValid            (false),
02203         _hasEverBeenAdvanced(false)
02204     { }
02205 
02206     virtual ~OriginalObjectIterator( )
02207     { }
02208 
02209     virtual CdbStatus reset( )
02210     {
02211         _isValid             = false;
02212         _hasEverBeenAdvanced = false;
02213 
02214         return CdbStatus::Success;
02215     }
02216 
02217     bool tryNextMetaData( );
02218     bool tryNextObject( );
02219 
02220     virtual bool next( )
02221     {
02222         const char* errorStr = "CdbBdbSCondition::OriginalObjectIterator::next() -- ERROR";
02223 
02224         if( _hasEverBeenAdvanced ) {
02225             if( ! _isValid ) {
02226 
02227               // Stay at BEYOND_PAST_ELEMENT state
02228 
02229                 ;
02230 
02231             } else {
02232 
02233               // Try to get next object...
02234 
02235                 _isValid = tryNextObject( );
02236             }
02237 
02238         } else {
02239 
02240             _hasEverBeenAdvanced = true;
02241 
02242           // Set up initial context of the iterator. Then proceed down
02243           // to the first object of the collection starting from the configuration.
02244 
02245             bool allIncrementsFlag = true;
02246 
02247             if( CdbStatus::Success !=  findMetaData( _md,
02248                                                      _masterRegistryH,
02249                                                      _localRegistryH,
02250                                                      _extendedConditionId,
02251                                                      _partitionId,
02252                                                      allIncrementsFlag )) {
02253                 cout << errorStr << endl
02254                      << "    Failed to locate the MetaData objects for the current condition/partition." << endl;
02255 
02256                  _isValid = false;
02257 
02258             } else {
02259 
02260                 _mdCurrent = 0;     // This is the very bottom increment to begin with.
02261 
02262                 _mdCurrentOiCollectionH = _md[_mdCurrent]->originaIntervalsCollection( );
02263 
02264                 _mdCurrentOi = 0;   // This number will _always_ get incremented by ::tryNextObject()
02265                                     // method. Therefore we're safe to put 0 (which is a special
02266                                     // index in the cllections of 'original' intervals) into here.
02267 
02268                 _isValid = tryNextObject( );
02269             }
02270         }
02271         return _isValid;
02272     }
02273 
02274     virtual ValueType value( )
02275     {
02276         if( ! _isValid ) {
02277             assert( 0 );
02278         }
02279         return _value;
02280     }
02281 
02282     virtual bool isValid( )
02283     {
02284         return _isValid;
02285     }
02286 
02287     virtual InterfaceType* clone( ) const
02288     {
02289         return new OriginalObjectIterator( *this );
02290     }
02291 
02292 private:
02293 
02294   // Parameters
02295 
02296     CdbConditionPtr _parent;
02297 
02298     BdbTime _begin;
02299     BdbTime _end;
02300 
02301     BdbHandle(CdbBdbSRegistryP) _masterRegistryH;
02302     BdbHandle(CdbBdbSRegistryP) _localRegistryH;
02303 
02304     CdbBdbSId _extendedConditionId;
02305 
02306     d_UShort _partitionId;
02307 
02308   // The current state
02309 
02310     bool _isValid;
02311     bool _hasEverBeenAdvanced;
02312 
02313     CdbObjectPtr _value;
02314 
02315   // The context : meta-data
02316 
02317     std::vector<BdbRef(CdbBdbSMetaDataP)>            _md;
02318     std::vector<BdbRef(CdbBdbSMetaDataP)>::size_type _mdCurrent;
02319 
02320   // Have this handle for the sake of optimization when traversing intervals
02321   // within the same MetaData.
02322 
02323     BdbHandle( CdbBdbSOiCollectionP ) _mdCurrentOiCollectionH;
02324 
02325     d_ULong _mdCurrentOi;   // The current index of the original intyerval in
02326                             // the corresponding collection of the current metadata object.
02327 };
02328 
02329 
02330 bool
02331 OriginalObjectIterator::tryNextMetaData( )
02332 {
02333   // Try to switch to another MetaData (if any)
02334 
02335     ++_mdCurrent;
02336     if( _mdCurrent >= _md.size( )) {
02337 
02338       // No more MetaData. We've reached the end.
02339 
02340         return false;
02341     }
02342 
02343   // Proceed to the next increment
02344 
02345     _mdCurrentOiCollectionH = _md[_mdCurrent]->originaIntervalsCollection( );
02346     _mdCurrentOi = 0;
02347 
02348     return tryNextObject( );    // This number will _always_ get incremented by ::tryNextObject()
02349                                 // method. Therefore we're safe to put 0 (which is a special
02350                                 // index in the cllections of 'original' intervals) into here.
02351 }
02352 
02353 bool
02354 OriginalObjectIterator::tryNextObject( )
02355 {
02356     const char* errorStr = "CdbBdbSCondition::OriginalObjectIterator::tryNextObject() -- ERROR";
02357 
02358     assert( _md.size( ) > 0 );
02359     assert( _mdCurrent < _md.size( ));
02360     assert( !BdbIsNull(_mdCurrentOiCollectionH));
02361     assert( _mdCurrentOi < _mdCurrentOiCollectionH->size( ));
02362 
02363   // Try to look for the next interval in the current MetaData or proceed
02364   // to the next one if the current one got exausted.
02365 
02366     ++_mdCurrentOi;
02367     if( _mdCurrentOi >= _mdCurrentOiCollectionH->size( )) return tryNextMetaData( );
02368 
02369   // Get the next 'original' interval and its 'duration' in the 'insertion' time dimension
02370   // then check if this interval falls into the specified 'duration' window.
02371   // If not then proceed to the next interval till an appropriate one would be found
02372   // or we'll run out of available MetaData.
02373   //
02374   // NOTE: The algorithm used below is just partially recursive. It uses plain cycle
02375   //       when iterating over intervals within the same MetaData and it uses
02376   //       recursive calls to switch to another MetaData. This's done for the sake
02377   //       of optimization.
02378 
02379     CdbBdbSOi oi;
02380 
02381     BdbTime beginDuration;
02382     BdbTime endDuration;
02383 
02384     do {
02385 
02386         if( CdbStatus::Success != _mdCurrentOiCollectionH->find( _mdCurrentOi,
02387                                                                  oi,
02388                                                                  beginDuration,
02389                                                                  endDuration )) {
02390             cout << errorStr << endl
02391                  << "    Failed to obtain the next 'original' interval from the current MetaData." << endl;
02392             return false;
02393         }
02394         if(( _begin <= oi.inserted ) && ( oi.inserted < _end )) {
02395 
02396           // We've found the right interval. Proceed to form the result.
02397 
02398             break;
02399         }
02400 
02401       // Try to look for the next interval in the current MetaData or proceed
02402       // to the next one if the current one got exausted.
02403 
02404         ++_mdCurrentOi;
02405         if( _mdCurrentOi >= _mdCurrentOiCollectionH->size( )) return tryNextMetaData( );
02406 
02407     } while( true );
02408 
02409   // Finally, convert this information into a technology & implementation transparent object.
02410 
02411     if( CdbStatus::Success != CdbBdbObjectCreator::object( _value,
02412                                                            _parent,
02413                                                            oi.begin,            // begin of "original" period
02414                                                            oi.end,              // end   of "original" period
02415                                                            oi.begin,            // begin of "visible" period (same as "original" in this context)
02416                                                            oi.end,              // end   of "visible" period (same as "original" in this context)
02417                                                            beginDuration,       // begin of "duration" period
02418                                                            endDuration,         // end   of "duration" period
02419                                                            oi.inserted,
02420                                                            oi.object )) {
02421         cout << errorStr << endl
02422              << "    Failed to create a generic object." << endl;
02423 
02424         return false;
02425     }
02426     return true;
02427 }
02428 
02429 //////////////////////////////////////////////
02430 // Function: Build Composite Condition Name //
02431 //////////////////////////////////////////////
02432 //
02433 // DESCRIPTION:
02434 //
02435 //   This function will attempt to translate the condition identifier into a composite
02436 //   name. The corresponding physical condition must be available in the database.
02437 //
02438 // NOTES:
02439 //
02440 //   The output value passed to the function by its reference
02441 //   will not change if the operation will fail.
02442 //
02443 //   If the function will fail for one or another reason then
02444 //   it will print the corresponding message onto the styandard output
02445 //   and return CdbStatus::Error.
02446 
02447 CdbStatus
02448 buildCompositeConditionName( CdbCompositeName&                  theCompositeName,
02449                              const CdbBdbSId&                   theId,
02450                              const BdbHandle(CdbBdbSRegistryP)& theMasterRegistryH );
02451 
02452 /////////////////////////////////////////////////////
02453 // Function: Calculate Condition Modification Time //
02454 /////////////////////////////////////////////////////
02455 //
02456 // DESCRIPTION:
02457 //
02458 //   This method will calculate the condition modification time as it's seen through
02459 //   the current view. In reality it may mean that the actual modification time may be newer
02460 //   than the one found by this method. However in practice the clients of the view should not
02461 //   be aware about this.
02462 //
02463 // NOTES:
02464 //
02465 //   The output value passed to the function by its reference
02466 //   will not change if the operation will fail.
02467 //
02468 //   If the function will fail for one or another reason then
02469 //   it will print the corresponding message onto the styandard output
02470 //   and return CdbStatus::Error.
02471 
02472 CdbStatus
02473 calculateConditionModificationTime( BdbTime&                                    theModificationTime,
02474                                     const CdbBdbSId&                            thePhysicalAddress,
02475                                     const BdbHandle(CdbBdbSConditionAtFolderP)& theConditionAtFolderH,
02476                                     const BdbHandle(CdbBdbSRegistryP)&          theMasterRegistryH,
02477                                     const BdbHandle(CdbBdbSRegistryP)&          theLocalRegistryH );
02478 };
02479 
02480 //////////////////////////////
02481 /// Class: CdbBdbSCondition //
02482 //////////////////////////////
02483 
02484 CdbCondition*
02485 CdbBdbSCondition::clone( ) const
02486 {
02487     return new CdbBdbSCondition( *this );
02488 }
02489 
02490 CdbBdbSCondition::CdbBdbSCondition( const CdbFolderPtr&                         theFolderPtr,
02491                                     const CdbDatabasePtr&                       theDatabasePtr,
02492                                     const char*                                 theName,
02493                                     const CdbBdbSId&                            thePhysicalAddress,
02494                                     const BdbHandle(CdbBdbSConditionAtFolderP)& theConditionAtFolderH,
02495                                     const BdbHandle(CdbBdbSConditionP)&         theConditionH,
02496                                     const BdbHandle(CdbBdbSRegistryP)&          theMasterRegistryH,
02497                                     const BdbHandle(CdbBdbSRegistryP)&          theLocalRegistryH ) :
02498     CdbCondition( theFolderPtr,
02499                   theDatabasePtr,
02500                   theName ),
02501     _physicalAddress   (thePhysicalAddress),
02502     _conditionAtFolderH(theConditionAtFolderH),
02503     _conditionH        (theConditionH),
02504     _masterRegistryH   (theMasterRegistryH),
02505     _localRegistryH    (theLocalRegistryH),
02506     _mdContH           (0),
02507     _obContH           (0)
02508 { }
02509 
02510 CdbBdbSCondition::CdbBdbSCondition( const CdbBdbSCondition& theCondition ) :
02511     CdbCondition( theCondition ),
02512     _physicalAddress   (theCondition._physicalAddress),
02513     _conditionAtFolderH(theCondition._conditionAtFolderH),
02514     _conditionH        (theCondition._conditionH),
02515     _masterRegistryH   (theCondition._masterRegistryH),
02516     _localRegistryH    (theCondition._localRegistryH),
02517     _mdContH           (theCondition._mdContH),
02518     _obContH           (theCondition._obContH)
02519 { }
02520 
02521 CdbBdbSCondition::~CdbBdbSCondition( )
02522 { }
02523 
02524 std::string
02525 CdbBdbSCondition::description( ) const
02526 {
02527     if( BdbIsNull(_conditionAtFolderH)) return std::string( _conditionH->description( ).head( ));
02528     return std::string( _conditionAtFolderH->description( ).head( ));
02529 }
02530 
02531 bool
02532 CdbBdbSCondition::isPartitionable( ) const
02533 {
02534     return _conditionH->isPartitionable( );
02535 }
02536 
02537 CdbCompositeName
02538 CdbBdbSCondition::physicalName( ) const
02539 {
02540     CdbCompositeName result;    // object in the "non-valid" state
02541 
02542     if( CdbStatus::Success != buildCompositeConditionName( result,
02543                                                            _physicalAddress,
02544                                                            _masterRegistryH )) {
02545 
02546       // By the contract of the above used method it's not going to change
02547       // the original value of the returned object unless operation is successfull.
02548 
02549       // No further actions to be taken here. Just return an object in the "non-valid".
02550       // It's up to the client applications to catch up this problem properly.
02551 
02552         ;
02553     }
02554     return result;
02555 }
02556 
02557 CdbId
02558 CdbBdbSCondition::physicalId( ) const
02559 {
02560     return CdbId( _physicalAddress.origin,
02561                   _physicalAddress.local );
02562 }
02563 
02564 BdbTime
02565 CdbBdbSCondition::created( ) const
02566 {
02567     return _conditionH->created( );
02568 }
02569 
02570 BdbTime
02571 CdbBdbSCondition::registered( ) const
02572 {
02573     if( BdbIsNull(_conditionAtFolderH)) return _conditionH->created( );
02574     return _conditionAtFolderH->created( );
02575 }
02576 
02577 BdbTime
02578 CdbBdbSCondition::modified( ) const
02579 {
02580     BdbTime result = BdbTime::minusInfinity;    // this default value means a failure of the algorithm
02581 
02582     if( CdbStatus::Success != calculateConditionModificationTime( result,
02583                                                                   _physicalAddress,
02584                                                                   _conditionAtFolderH,
02585                                                                   _masterRegistryH,
02586                                                                   _localRegistryH )) {
02587 
02588       // By the contract of the above used method it's not going to change
02589       // the original value of the returned object unless operation is successfull.
02590 
02591       // No further actions to be taken here. Just return an object in its default state.
02592       // It's up to the client applications to catch up this problem properly.
02593 
02594         ;
02595     }
02596     return result;
02597 
02598 }
02599 
02600 CdbStatus
02601 CdbBdbSCondition::findObject( CdbObjectPtr&  theObjectPtr,
02602                               const BdbTime& theValidityTime,
02603                               const BdbTime& theInsertionTime )
02604 {
02605     const char* errorStr = "CdbBdbSCondition::findObject() -- ERROR";
02606 
02607   /*
02608    * =================
02609    * EXECUTION PATH I: 'physical address' conditions only
02610    * =================
02611    *
02612    * If the condition is available by its 'physical address' only
02613    * then we don't have any asociation with views & folders, therefore no such things
02614    * as condition configurations are available. The "insertion" time will play a role
02615    * of the secondary (in addition to the validity time) key. Here are the rules
02616    * for different values of the insertion time and condition types
02617    *
02618    *   o if the insertion time is +Infinity then:
02619    *
02620    *     REGULAR       : the TOPMOST revision will always be used
02621    *
02622    *     PARTITIONABLE : the most recent revision of the "topmost" (at given validity time)
02623    *                     partition will be used. In case if this is an "open" partition
02624    *                     then its TOPMOST revision will be used.
02625    *
02626    *   o for any other values of the insertion time:
02627    *
02628    *     REGULAR       : the specified insertion time would be used
02629    *
02630    *     PARTITIONABLE : the specified insertion time would be used
02631    */
02632 
02633     if( BdbIsNull(_conditionAtFolderH)) {
02634 
02635       // The default constructor of the policy would assume that we're going
02636       // to use the actual insertion time rather than any explicitly found revision.
02637 
02638         CdbRevisionPolicy rPolicy;
02639 
02640         if( BdbTime::plusInfinity == theInsertionTime ) {
02641 
02642           // Okay, we need to find the most recent partition & revision
02643 
02644             if( _conditionH->isPartitionable( )) {
02645 
02646               // Find an appropriate partition for the specified validity and insertion
02647               // timestamps.
02648               //
02649               // @see CdbBdbSCondition::findInitialPartition()
02650 
02651                 d_ULong partitionId = 0;
02652                 {
02653                     BdbHandle(CdbBdbSPartitionP) pH;
02654 
02655                     std::string dbIdRange;  // don't really need and use it here.
02656 
02657                     if( CdbStatus::Success != findInitialPartition( theValidityTime,
02658                                                                     theInsertionTime,
02659                                                                     pH,
02660                                                                     dbIdRange )) {
02661                         cout << errorStr << endl
02662                              << "    Failed to find an initial partition for the specified validity and insertion" << endl
02663                              << "    for a condition found by its 'physical address'." << endl
02664                              << "        PHYSICAL CONDITION ADDRESS : " << _physicalAddress << endl
02665                              << "        VALIDITY TIME              : " << time2string( theValidityTime ).c_str( )  << " : " << theValidityTime  << endl
02666                              << "        INSERTION TIME             : " << time2string( theInsertionTime ).c_str( ) << " : " << theInsertionTime << endl;
02667 
02668                         return CdbStatus::Error;
02669                     }
02670                     partitionId = pH->id( );
02671                 }
02672 
02673               // Find the most recent (can be "<topmost>" if the partition is in the "open"
02674               // state) revision in the partition.
02675               //
02676               // NOTE: The default value for the revision is -Infinity, which we'll
02677               //       also use as a flag indicationg whether any revision is found
02678               //       or not.
02679 
02680                 BdbTime rId = BdbTime::minusInfinity;
02681                 {
02682                    // Find the most recent metadata object for the specified condition/partition
02683 
02684                     std::vector<BdbRef(CdbBdbSMetaDataP)> vectorOfMdRefs;
02685 
02686                     bool allIncrementsFlag   = false;
02687                     bool recentIncrementFlag = true;
02688 
02689 
02690                     if( CdbStatus::Success != findMetaData( vectorOfMdRefs,
02691                                                             _masterRegistryH,
02692                                                             _localRegistryH,
02693                                                             _physicalAddress,
02694                                                             partitionId,
02695                                                             allIncrementsFlag,
02696                                                             recentIncrementFlag )) {
02697                         cout << errorStr << endl
02698                              << "    Failed to locate the most recent MetaData objects for" << endl
02699                              << "    the current condition/partition." << endl
02700                              << "        PARTITION                  : " << partitionId << endl
02701                              << "        PHYSICAL CONDITION ADDRESS : " << _physicalAddress << endl
02702                              << "        VALIDITY TIME              : " << time2string( theValidityTime ).c_str( )  << " : " << theValidityTime  << endl
02703                              << "        INSERTION TIME             : " << time2string( theInsertionTime ).c_str( ) << " : " << theInsertionTime << endl;
02704 
02705                         return CdbStatus::Error;
02706                     }
02707 
02708                   // Make sure just one metadata found. If not then something is broken
02709                   // in the current implementation.
02710 
02711                     assert( 1 == vectorOfMdRefs.size( ));
02712 
02713                   // Find the most recent revision
02714 
02715                     BdbHandle(CdbBdbSMetaDataP) mdH = vectorOfMdRefs[0];
02716 
02717                     CdbItr<BdbTime> rItr;
02718 
02719                     if( CdbStatus::Success != mdH->revisionIdIterator( rItr )) {
02720 
02721                         cout << errorStr << endl
02722                              << "    Failed to setup an iterator of revision identifiers in" << endl
02723                              << "    the most recent MetaData objects for the current condition/partition." << endl
02724                              << "        META-DATA OBJECT           : " << mdH.sprint( ) << endl
02725                              << "        PARTITION                  : " << partitionId << endl
02726                              << "        PHYSICAL CONDITION ADDRESS : " << _physicalAddress << endl
02727                              << "        VALIDITY TIME              : " << time2string( theValidityTime ).c_str( )  << " : " << theValidityTime  << endl
02728                              << "        INSERTION TIME             : " << time2string( theInsertionTime ).c_str( ) << " : " << theInsertionTime << endl;
02729 
02730                         return CdbStatus::Error;
02731                     }
02732                     while( rItr.next( )) {
02733                         if( rItr.value( ) > rId ) {
02734                             rId = rItr.value( );
02735                         }
02736                     }
02737 
02738                   // Make sure we've found what we wanted to find. If not then something
02739                   // is broken in persistent data structures. So we don't even bother to complain
02740                   // in verbose form.
02741 
02742                     assert( BdbTime::minusInfinity != rId );
02743                 }
02744 
02745             } else {
02746 
02747               // Just use TOPMOST revision for REGULAR conditions.
02748 
02749                 rPolicy = CdbRevisionPolicy( BdbTime::plusInfinity, 0 );
02750             }
02751         }
02752 
02753       // Proceed with the policy driven search.
02754 
02755         return findObject( theObjectPtr,
02756                            rPolicy,
02757                            theValidityTime,
02758                            theInsertionTime );
02759     }
02760 
02761   /*
02762    * ==================
02763    * EXECUTION PATH II: 'view/folder/config' conditions only
02764    * ==================
02765    */
02766 
02767     CDB_DEBUG_STREAM
02768         << "CDB_FIND_OBJECT_1: condition=" << CdbCondition::fullPathName( this->clone( ))
02769         << " validity_time=" << theValidityTime.getGmtSec( ) << "." << theValidityTime.getGmtNsec( )
02770         << " insertion_time=" << theInsertionTime.getGmtSec( ) << "." << theInsertionTime.getGmtNsec( ) << endl;
02771 
02772     theObjectPtr = 0;
02773 
02774     BdbRef(BdbObject) foundObjectRef = 0;
02775     CdbStatus         result         = CdbStatus::Error;
02776     do {
02777 
02778       // Check if the current view is frozen.
02779 
02780         BdbRef(CdbBdbSFolderP) fRef = _conditionAtFolderH->parentFolder( );
02781         assert( !BdbIsNull(fRef));
02782 
02783         BdbRef(CdbBdbSViewP) vRef = fRef->parentView( );
02784         assert( !BdbIsNull(vRef));
02785 /***
02786  *** NOTE: This test is disabled because we should allow reading through
02787  ***       views even though they are open for modifications.
02788  ***
02789         if( !vRef->isFrozen( )) {
02790             cout << errorStr << endl
02791                  << "    The current view is not 'frozen' from modifications. This sort of view" << endl
02792                  << "    can not be used to find condition objects at the database." << endl
02793                  << "        VIEW NAME: \"" << parent( )->parentView( )->name( ) << "\"" << endl;
02794             break;
02795         }
02796 ***/
02797       // Check if specified validity time is covered by the validity
02798       // interval of the current view.
02799 
02800         if(( theValidityTime <  vRef->minValidity( )) ||
02801            ( theValidityTime >= vRef->maxValidity( ))) {
02802 
02803             cout << errorStr << endl
02804                  << "    Specified validity time does not fit into the validity range" << endl
02805                  << "    of the current view." << endl
02806                  << "        VIEW NAME:   \"" << parent( )->parentView( )->name( ) << "\"" << endl
02807                  << "        PASSED TIME: " << theValidityTime << endl;
02808             break;
02809         }
02810 
02811       // All we need to do is to find out a revision policy for
02812       // the condition.
02813 
02814         CdbBdbSConfigInterval rConfigInterval;
02815         {
02816             BdbRef(CdbBdbSConfigCollectionP) rConfigRef = _conditionAtFolderH->config( );
02817             if( BdbIsNull(rConfigRef)) {
02818 
02819                 rConfigRef = vRef->defaultConfig( );
02820                 if( BdbIsNull(rConfigRef)) {
02821                     cout << errorStr << endl
02822                          << "    Failed to find revision configuration for current condition" << endl
02823                          << "    at the current view." << endl
02824                          << "    The view may be inproperly configured." << endl
02825                          << "        CONDITION NAME: \"" << name( ) << "\"" << endl
02826                          << "        VIEW NAME:      \"" << parent( )->parentView( )->name( ) << "\"" << endl;
02827                     break;
02828                 }
02829             }
02830             if( CdbStatus::Success != rConfigRef->find( theValidityTime,
02831                                                         rConfigInterval )) {
02832                 cout << errorStr << endl
02833                      << "    Failed to find revision policy information for specified validity time" << endl
02834                      << "    at the condition description of the  the current view." << endl
02835                      << "    The view may be inproperly configured." << endl
02836                      << "        PASSED TIME:    " << theValidityTime << endl
02837                      << "        CONDITION NAME: \"" << name( ) << "\"" << endl
02838                      << "        VIEW NAME:      \"" << parent( )->parentView( )->name( ) << "\"" << endl;
02839                 break;
02840             }
02841         }
02842         if( ! rConfigInterval.value.accessIsAllowed( )) {
02843             cout << errorStr << endl
02844                  << "    The current view prohibits accessing conditions at specified" << endl
02845                  << "    point of the validity timeline." << endl
02846                  << "        VIEW NAME:   \"" << parent( )->parentView( )->name( ) << "\"" << endl
02847                  << "        PASSED TIME: " << theValidityTime << endl;
02848             break;
02849         }
02850         CdbRevisionPolicy rPolicy;
02851         {
02852             CdbBdbSConfigElement rConfigElement = rConfigInterval.value;
02853             if( d_True == rConfigElement.useRevision ) {
02854                 rPolicy = CdbRevisionPolicy( rConfigElement.revision,
02855                                              rConfigElement.partition );
02856             }
02857         }
02858 
02859       // Given the found policy, propagate the call down to the next
02860       // method requiring explicit policy to be specified among
02861       // the method's parameters.
02862 
02863         CdbBdbSOi originalInterval;
02864 
02865         BdbTime beginOfVisiblePeriod ( 0 );
02866         BdbTime endOfVisiblePeriod   ( 0 );
02867         BdbTime beginOfDurationPeriod( 0 );
02868         BdbTime endOfDurationPeriod  ( 0 );
02869 
02870         if( _conditionH->isPartitionable( )) {
02871             if( CdbStatus::Success != doFindObjectAtPartition( rPolicy,
02872                                                                theValidityTime,
02873                                                                theInsertionTime,
02874                                                                originalInterval, 
02875                                                                beginOfVisiblePeriod,
02876                                                                endOfVisiblePeriod,
02877                                                                beginOfDurationPeriod,
02878                                                                endOfDurationPeriod )) break;
02879         } else {
02880             if( CdbStatus::Success != doFindObject( rPolicy,
02881                                                     theValidityTime,
02882                                                     theInsertionTime,
02883                                                     originalInterval, 
02884                                                     beginOfVisiblePeriod,
02885                                                     endOfVisiblePeriod,
02886                                                     beginOfDurationPeriod,
02887                                                     endOfDurationPeriod )) break;
02888         }
02889 
02890       // Now we should check if the found visible validity interval must be
02891       // narrowed down to the limits enforced by the current policy interval.
02892 
02893         if( rConfigInterval.begin > beginOfVisiblePeriod ) beginOfVisiblePeriod = rConfigInterval.begin;
02894         if( rConfigInterval.end   < endOfVisiblePeriod   ) endOfVisiblePeriod   = rConfigInterval.end;
02895 
02896       // Create a transient object through the creator factory.
02897       //
02898       // DESIGN NOTE: We need to construct a smart pointer against a clone since
02899       //              we don't know a smart pointer pointing to the current
02900       //              instance, therefore we can't guarantee the lifetime
02901       //              of the current instance.
02902 
02903         CdbConditionPtr myPtr( this->clone( ));
02904 
02905         if( CdbStatus::Success != CdbBdbObjectCreator::object( theObjectPtr,
02906                                                                myPtr,
02907                                                                originalInterval.begin,
02908                                                                originalInterval.end,
02909                                                                beginOfVisiblePeriod,
02910                                                                endOfVisiblePeriod,
02911                                                                beginOfDurationPeriod,
02912                                                                endOfDurationPeriod,
02913                                                                originalInterval.inserted,
02914                                                                originalInterval.object )) break;
02915 
02916      // Done
02917 
02918        foundObjectRef = originalInterval.object;
02919        result         = CdbStatus::Success;
02920 
02921     } while( false );
02922 
02923     CDB_DEBUG_STREAM << "CDB_FIND_OBJECT_1: " << foundObjectRef.sprint( ) << endl;
02924 
02925     return result;
02926 }
02927 
02928 CdbStatus
02929 CdbBdbSCondition::findObject( CdbObjectPtr&            theObjectPtr,
02930                               const CdbRevisionPolicy& thePolicy,
02931                               const BdbTime&           theValidityTime,
02932                               const BdbTime&           theInsertionTime )
02933 {
02934     theObjectPtr = 0;
02935 
02936     CDB_DEBUG_STREAM
02937         << "CDB_FIND_OBJECT_2: condition=" << CdbCondition::fullPathName( this->clone( ))
02938         << " validity_time=" << theValidityTime.getGmtSec( ) << "." << theValidityTime.getGmtNsec( ) 
02939         << " insertion_time=" << theInsertionTime.getGmtSec( ) << "." << theInsertionTime.getGmtNsec( ) << endl;
02940 
02941     BdbRef(BdbObject) foundObjectRef = 0;
02942     CdbStatus         result         = CdbStatus::Error;
02943     do {
02944 
02945       // Given the found policy, propagate the call down to the next
02946       // method requiring explicit policy to be specified among
02947       // the method's parameters.
02948 
02949         CdbBdbSOi originalInterval;
02950 
02951         BdbTime beginOfVisiblePeriod ( 0 );
02952         BdbTime endOfVisiblePeriod   ( 0 );
02953         BdbTime beginOfDurationPeriod( 0 );
02954         BdbTime endOfDurationPeriod  ( 0 );
02955 
02956         if( _conditionH->isPartitionable( )) {
02957             if( CdbStatus::Success != doFindObjectAtPartition( thePolicy,
02958                                                                theValidityTime,
02959                                                                theInsertionTime,
02960                                                                originalInterval, 
02961                                                                beginOfVisiblePeriod,
02962                                                                endOfVisiblePeriod,
02963                                                                beginOfDurationPeriod,
02964                                                                endOfDurationPeriod )) break;
02965         } else {
02966             if( CdbStatus::Success != doFindObject( thePolicy,
02967                                                     theValidityTime,
02968                                                     theInsertionTime,
02969                                                     originalInterval, 
02970                                                     beginOfVisiblePeriod,
02971                                                     endOfVisiblePeriod,
02972                                                     beginOfDurationPeriod,
02973                                                     endOfDurationPeriod )) break;
02974         }
02975 
02976       // Create a transient object through the creator factory.
02977       //
02978       // DESIGN NOTE: We need to construct a smart pointer against a clone since
02979       //              we don't know a smart pointer pointing to the current
02980       //              instance, therefore we can't guarantee the lifetime
02981       //              of the current instance.
02982 
02983         CdbConditionPtr myPtr( this->clone( ));
02984 
02985         if( CdbStatus::Success != CdbBdbObjectCreator::object( theObjectPtr,
02986                                                                myPtr,
02987                                                                originalInterval.begin,
02988                                                                originalInterval.end,
02989                                                                beginOfVisiblePeriod,
02990                                                                endOfVisiblePeriod,
02991                                                                beginOfDurationPeriod,
02992                                                                endOfDurationPeriod,
02993                                                                originalInterval.inserted,
02994                                                                originalInterval.object )) break;
02995 
02996      // Done
02997  
02998        foundObjectRef = originalInterval.object;
02999        result         = CdbStatus::Success;
03000  
03001     } while( false );
03002  
03003     CDB_DEBUG_STREAM << "CDB_FIND_OBJECT_2: " << foundObjectRef.sprint( ) << endl; 
03004 
03005     return result;
03006 }
03007 
03008 CdbStatus
03009 CdbBdbSCondition::objectIterator( CdbObjectItr&  theItr,
03010                                   const BdbTime& theBeginValidity,
03011                                   const BdbTime& theEndValidity )
03012 {
03013     const char* errorStr = "CdbBdbSCondition::objectIterator() -- ERROR";
03014 
03015   /*
03016    * =================
03017    * EXECUTION PATH I: 'physical address' conditions only
03018    * =================
03019    *
03020    * This path is not currently implemented. A complicated algorithm to iterate
03021    * over a validity timeline of the "topmost" partitions would be needed for
03022    * PARTITIONABLE conditions. Things are trivial for REGULAR conditions though.
03023    * However to avoid an incomplete implementation of this part of the code let's just
03024    * postpone it as a whole.
03025    *
03026    * AN IDEA: Having a super-iterator composed of elementary iterators for individual
03027    *          "topmost" partitions would be a good idea. That would require to extend
03028    *          the API of P-Layout to deliver an iterator of "topmost" partitions. The
03029    *          one currently available does not respect non-instantiated partitions.
03030    */
03031 
03032     if( BdbIsNull(_conditionAtFolderH)) {
03033         return CdbStatus::NotImplemented;
03034     }
03035 
03036   /*
03037    * ==================
03038    * EXECUTION PATH II: 'view/folder/config' conditions only
03039    * ==================
03040    */
03041 
03042     CdbStatus result = CdbStatus::NotFound;
03043     do {
03044 
03045       // Verify parameters
03046 
03047         if( theEndValidity <= theBeginValidity ) {
03048             cout << errorStr << endl
03049                  << "    Invalid validity interval range passed to the method." << endl
03050                  << "    The end time should be greater or equal than the begin one." << endl
03051                  << "        PASSED BEGIN TIME : " << theBeginValidity << endl
03052                  << "        PASSED END   TIME : " << theEndValidity << endl
03053                  << "        CONDITION         : \"" << name( ) << "\"" << endl;
03054             break;
03055         }
03056 
03057         BdbHandle(CdbBdbSViewP) viewH;
03058         viewH = _conditionAtFolderH->parentFolder( )->parentView( );
03059 
03060         BdbTime minValidity = viewH->minValidity( );
03061         BdbTime maxValidity = viewH->maxValidity( );
03062 
03063         if(( theBeginValidity >= maxValidity ) || ( theEndValidity <= minValidity )) {
03064             cout << errorStr << endl
03065                  << "    Invalid validity interval range passed to the method." << endl
03066                  << "    This interval does not fit into the validity range" << endl
03067                  << "    allowed by the current view." << endl
03068                  << "        PASSED BEGIN TIME : " << theBeginValidity << endl
03069                  << "        PASSED END   TIME : " << theEndValidity << endl
03070                  << "        VIEW'S BEGIN TIME : " << minValidity << endl
03071                  << "        VIEW'S END   TIME : " << maxValidity << endl
03072                  << "        VIEW              : \"" << parent( )->parentView( )->name( ) << "\"" << endl
03073                  << "        CONDITION         : \"" << name( ) << "\"" << endl;
03074             break;
03075         }
03076 
03077       // Find the right configuration. This is going to be either specific one
03078       // at the level of the condition, or the default one at the level of the view.
03079 
03080         BdbRef(CdbBdbSConfigCollectionP) configCollRef = _conditionAtFolderH->config( );
03081         if( BdbIsNull(configCollRef)) {
03082 
03083             configCollRef = viewH->defaultConfig( );
03084             if( BdbIsNull(configCollRef)) {
03085                 cout << errorStr << endl
03086                      << "    The current view is inproperly configured for specified condition." << endl
03087                      << "    No configuration found both at specified condition scope and" << endl
03088                      << "    at the view level." << endl
03089                      << "        VIEW              : \"" << parent( )->parentView( )->name( ) << "\"" << endl
03090                      << "        CONDITION         : \"" << name( ) << "\"" << endl;
03091                 break;
03092             }
03093         }
03094 
03095       // Now pick up the right iterator and let it to do the rest...
03096 
03097         CdbConditionPtr myPtr( this->clone( ));
03098 
03099         if( _conditionH->isPartitionable( )) {
03100 
03101           // ATTENTION: This is not a memory leak - the created object
03102           //            will be destroyed by the iterator.
03103 
03104             theItr = CdbObjectItr( new PartitionableObjectIterator( myPtr,
03105                                                                     theBeginValidity,
03106                                                                     theEndValidity,
03107                                                                     configCollRef->iterator( ),
03108                                                                     _masterRegistryH,
03109                                                                     _localRegistryH,
03110                                                                     _physicalAddress,
03111                                                                     _conditionH->created( )));
03112         } else {
03113 
03114           // ATTENTION: This is not a memory leak - the created object
03115           //            will be destroyed by the iterator.
03116 
03117             theItr = CdbObjectItr( new RegularObjectIterator( myPtr,
03118                                                               theBeginValidity,
03119                                                               theEndValidity,
03120                                                               configCollRef->iterator( ),
03121                                                               _masterRegistryH,
03122                                                               _localRegistryH,
03123                                                               _physicalAddress));
03124         }
03125 
03126       // Done
03127  
03128        result = CdbStatus::Success;
03129  
03130     } while( false );
03131 
03132     return result;
03133 }
03134 
03135 CdbStatus
03136 CdbBdbSCondition::objectIterator( CdbObjectItr&            theItr,
03137                                   const CdbRevisionPolicy& thePolicy,
03138                                   const BdbTime&           theBeginValidity,
03139                                   const BdbTime&           theEndValidity )
03140 {
03141     const char* errorStr = "CdbBdbSCondition::objectIterator(by policy) -- ERROR";
03142 
03143     CdbStatus result = CdbStatus::NotFound;
03144     do {
03145 
03146       // Verify parameters
03147 
03148         if( theEndValidity <= theBeginValidity ) {
03149             cout << errorStr << endl
03150                  << "    Invalid validity interval range passed to the method." << endl
03151                  << "    The end time should be greater or equal than the begin one." << endl
03152                  << "        PASSED BEGIN TIME : " << theBeginValidity << endl
03153                  << "        PASSED END   TIME : " << theEndValidity << endl
03154                  << "        CONDITION         : \"" << name( ) << "\"" << endl;
03155             break;
03156         }
03157 
03158       // Prepare a special iterator to serve single configuration record
03159       //
03160       // ATTENTION: This is not a memory leak - the created object
03161       //            will be destroyed by the iterator.
03162 
03163         CdbItr<CdbBdbSConfigInterval> configItr( new CdbBdbSSimpleConfigIterator( CdbBdbSConfigElement( thePolicy.revisionId( ),
03164                                                                                                         thePolicy.partitionId( ),
03165                                                                                                         thePolicy.useRevision( )),
03166                                                                                   theBeginValidity,
03167                                                                                   theEndValidity ));
03168 
03169       // Now pick up the right iterator and let it to do the rest...
03170 
03171         CdbConditionPtr myPtr( this->clone( ));
03172 
03173         if( _conditionH->isPartitionable( )) {
03174 
03175           // ATTENTION: This is not a memory leak - the created object
03176           //            will be destroyed by the iterator.
03177 
03178             theItr = CdbObjectItr( new PartitionableObjectIterator( myPtr,
03179                                                                     theBeginValidity,
03180                                                                     theEndValidity,
03181                                                                     configItr,
03182                                                                     _masterRegistryH,
03183                                                                     _localRegistryH,
03184                                                                     _physicalAddress,
03185                                                                     _conditionH->created( )));
03186         } else {
03187 
03188           // ATTENTION: This is not a memory leak - the created object
03189           //            will be destroyed by the iterator.
03190 
03191             theItr = CdbObjectItr( new RegularObjectIterator( myPtr,
03192                                                               theBeginValidity,
03193                                                               theEndValidity,
03194                                                               configItr,
03195                                                               _masterRegistryH,
03196                                                               _localRegistryH,
03197                                                               _physicalAddress ));
03198         }
03199 
03200       // Done
03201  
03202        result = CdbStatus::Success;
03203  
03204     } while( false );
03205 
03206     return result;
03207 }
03208 
03209 CdbStatus
03210 CdbBdbSCondition::originalObjectIterator( CdbObjectItr&        theItr,
03211                                           const BdbTime&       theBeginInsertion,
03212                                           const BdbTime&       theEndInsertion,
03213                                           const unsigned short thePartitionId )
03214 {
03215     const char* errorStr = "CdbBdbSCondition::originalObjectIterator() -- ERROR";
03216 
03217     CdbStatus result = CdbStatus::NotFound;
03218     do {
03219 
03220       // Verify parameters
03221 
03222         if( theBeginInsertion >= theEndInsertion ) {
03223             cout << errorStr << endl
03224                  << "    Invalid 'insertion' interval range passed to the method." << endl
03225                  << "    The end time should be greater or equal than the begin one." << endl
03226                  << "        PASSED BEGIN TIME : " << theBeginInsertion << endl
03227                  << "        PASSED END   TIME : " << theEndInsertion << endl
03228                  << "        CONDITION         : \"" << name( ) << "\"" << endl;
03229             break;
03230         }
03231 
03232       // Now pick up the right iterator and let it to do the rest...
03233 
03234         CdbConditionPtr myPtr( this->clone( ));
03235 
03236 
03237       // ATTENTION: This is not a memory leak - the created object
03238       //            will be destroyed by the iterator.
03239 
03240         theItr = CdbObjectItr( new OriginalObjectIterator( myPtr,
03241                                                            theBeginInsertion,
03242                                                            theEndInsertion,
03243                                                            _masterRegistryH,
03244                                                            _localRegistryH,
03245                                                            _physicalAddress,
03246                                                            thePartitionId ));
03247 
03248       // Done
03249  
03250        result = CdbStatus::Success;
03251  
03252     } while( false );
03253 
03254     return result;
03255 }
03256 
03257 CdbStatus
03258 CdbBdbSCondition::storeObject( CdbObjectFactoryBase& theObjectFactory,
03259                                const BdbTime&        theBegin,
03260                                const BdbTime&        theEnd,
03261                                CdbObjectPtr&         theObjectPtr )
03262 {
03263     const char* errorStr = "CdbBdbSCondition::storeObject() -- ERROR";
03264 
03265     CDB_DEBUG_STREAM
03266         << "CDB_STORE_OBJECT_1: condition=" << CdbCondition::fullPathName( this->clone( ))
03267         << " begin_time=" << theBegin.getGmtSec( ) << "." << theBegin.getGmtNsec( ) 
03268         << " end_time=" << theEnd.getGmtSec( ) << "." << theEnd.getGmtNsec( ) << endl;
03269 
03270     CdbStatus result = CdbStatus::Error;
03271 
03272     theObjectPtr = 0;
03273 
03274     do {
03275 
03276       // Truncated end validity time for the new object.
03277       //
03278       // NOTES:
03279       //
03280       //    (1) This time can be truncated to the end of the current partition if this
03281       //        is a partitionable condition and if the end time does not fit into the
03282       //        same partition the begin time falls into.
03283       //
03284       //    (2) This time can be further truncated if the "truncate" parameter delivered
03285       //        by by CdbEnvironment is less than the adjusted end time. This rule applies
03286       //        for both 'regular' and 'partitionable' conditions.
03287       //
03288       //        NOTE: The resulting truncate time should not be less or equal to the begin
03289       //              time. Otherwise the current operation would fail.
03290 
03291         BdbTime truncatedEnd = theEnd;
03292 
03293       // Find out a the cluster the condition belongs to
03294 
03295         BdbRef(CdbBdbSClusterP) clusterRef = _conditionH->cluster( );
03296         assert( !BdbIsNull(clusterRef));
03297 
03298       // Find & verify the partition if the current condition is the partitionable one.
03299       // We may also truncate the end time of the partition if required.
03300 
03301         bool isPartitionable = _conditionH->isPartitionable( );
03302 
03303         BdbRef(CdbBdbSPartitionP) pRef;
03304         if( isPartitionable ) {
03305 
03306           // Find the partition
03307 
03308             BdbRef(CdbBdbSPartitionsLayoutP) pLayoutRef = _localRegistryH->partitionsLayout( );
03309             assert( !BdbIsNull(pLayoutRef));
03310 
03311             if( CdbStatus::Success != pLayoutRef->find( theBegin,
03312                                                         pRef )) {
03313                 cout << errorStr << endl
03314                      << "    Failed to locate an open partition for the begin time" << endl
03315                      << "        BEGIN VALIDITY TIME: " << theBegin << endl
03316                      << "        CONDITION NAME:      \"" << name( ) << "\"" << endl;
03317                 break;
03318             }
03319 
03320           // Verify the partition
03321 
03322             if( pRef->isClosed( )) {
03323                 cout << errorStr << endl
03324                      << "    The partition is closed for modifications." << endl
03325                      << "    Storing new objects in the closed partition is not allowed." << endl
03326                      << "        PARTITION ID:   " << pRef->id( ) << endl
03327                      << "        CONDITION NAME: \"" << name( ) << "\"" << endl;
03328                 break;
03329             }
03330             if( !pRef->isInstantiated( )) {
03331                 cout << errorStr << endl
03332                      << "    The partition is not instantiated yet." << endl
03333                      << "    Storing new objects into a partition in this state is not allowed." << endl
03334                      << "        PARTITION ID:   " << pRef->id( ) << endl
03335                      << "        CONDITION NAME: \"" << name( ) << "\"" << endl;
03336                 break;
03337             }
03338 
03339           // Truncate the end time if needed.
03340 
03341             CdbBdbSCell cell = pRef->cell( );
03342             if( truncatedEnd > cell.endValidity ) truncatedEnd = cell.endValidity;
03343         }
03344 
03345       // Now make another adjustment (for both 'regular' and 'partitionable' conditions)
03346       // to the end time if the corresponding restriction is required by CdbEnvironment.
03347 
03348         {
03349             BdbTime truncateTime = CdbEnvironment::getTruncateTime( );
03350             if( truncateTime  < truncatedEnd ) {
03351 
03352                 if( truncateTime <= theBegin ) {
03353                     cout << errorStr << endl
03354                          << "    Wrong value of the truncate time found in the job's environment." << endl
03355                          << "    This time is not allwed to be less or equal to the begin time" << endl
03356                          << "    of stored objects. The job may be inproperly configured." << endl
03357                          << "        TRUNCATE TIME: " << truncatedEnd.getGmtSec( ) << "." << truncatedEnd.getGmtNsec( ) << endl;
03358                     break;
03359                 }
03360                 truncatedEnd = truncateTime;
03361 
03362                 CDB_DEBUG_STREAM << "CDB_STORE_OBJECT_1: truncated_end_time=" << truncatedEnd.getGmtSec( ) << "." << truncatedEnd.getGmtNsec( ) << endl;
03363             }
03364         }
03365 
03366       // Get the identifier of the condition and check if it can be modified
03367       // localy.
03368 
03369         CdbBdbSId cId = _physicalAddress;
03370         if( isPartitionable ) {
03371             if( _localRegistryH->originId( ) != pRef->originId( )) {
03372                 cout << errorStr << endl
03373                      << "    The partition does not belong to current database. Therefore it can't" << endl
03374                      << "    be used to store new objects locally." << endl
03375                      << "        PARTITION ID:   " << pRef->id( ) << endl
03376                      << "        CONDITION NAME: \"" << name( ) << "\"" << endl;
03377                 break;
03378             }
03379         } else {
03380             if( _localRegistryH->originId( ) != cId.origin ) {
03381                 cout << errorStr << endl
03382                      << "    The condition does not belong to current database. Therefore it can't" << endl
03383                      << "    be used to store new objects locally." << endl
03384                      << "        CONDITION NAME: \"" << name( ) << "\"" << endl;
03385                 break;
03386             }
03387         }
03388 
03389       // Find out the most recent increment number for the condition
03390 
03391         d_UShort clusterIncrement = 0;
03392         {
03393             d_UShort numIncrementes = 0;
03394             if( isPartitionable ) {
03395                 numIncrementes = pRef->numIncrements( );
03396             } else {
03397                 BdbRef(CdbBdbSSimpleClusterP) simpleClusterRef = (const BdbRef(CdbBdbSSimpleClusterP)&) clusterRef;
03398                 numIncrementes = simpleClusterRef->numIncrements( );
03399             }
03400             assert( numIncrementes > 0 );
03401             clusterIncrement = numIncrementes - 1;
03402         }
03403 
03404       // Now we've got everything to build the system name of the database file
03405       // containing the "topmost" meta-data container and the corresponding container
03406       // with condition objects.
03407 
03408         char cIdStr[12];
03409         sprintf( cIdStr, "%u", cId.local );
03410 
03411         std::string databaseName( "con_cdb" );
03412         {
03413             if( isPartitionable ) {
03414 
03415                 char pIdStr[12];
03416                 sprintf( pIdStr, "%u", pRef->id( ));
03417 
03418                 databaseName = databaseName + std::string( "_p" ) + std::string( pIdStr );
03419             }
03420 
03421             char clusterIdStr[12];
03422             char clusterIncrementStr[12];
03423 
03424             sprintf( clusterIdStr, "%u", clusterRef->id( ));
03425             sprintf( clusterIncrementStr, "%u", clusterIncrement );
03426 
03427             std::string localDbIdRange;
03428             if( CdbStatus::Success != CdbBdbSUtils::getLocalDbIdRange( localDbIdRange )) {
03429                 cout << errorStr << endl
03430                      << "    Failed to obtain the local DBID range. The current federation" << endl
03431                      << "    may not be properly initialized/loaded." << endl;
03432                 break;
03433             }
03434 
03435             databaseName = databaseName + std::string( "_c" ) + std::string( clusterIdStr ) +
03436                                           std::string( "_i" ) + std::string( clusterIncrementStr ) +
03437                                           std::string( "_"  ) + localDbIdRange;
03438         }
03439         std::string mdContainerName = std::string( "MetaData." ) + std::string( cIdStr );
03440         std::string obContainerName = std::string( "Objects."  ) + std::string( cIdStr );
03441 
03442       // Find these containers
03443       //
03444       // IMPLEMENTATION NOTE:
03445       // WARNING: Watch for the optimization of very expensive
03446       //          database location operations. We use a current object data member
03447       //          to cache container handles. Our assumption is that this cache
03448       //          never gets invalidated during the lifetime of the current object, which
03449       //          in theory can be wrong. For example if a new partition/increment was created.
03450       //          This scenario will be evalueated later.
03451 
03452         if( BdbIsNull(_mdContH)) {
03453             if( CdbStatus::Success != CdbBdbSUtils::findContainer( _mdContH,
03454                                                                    databaseName.c_str( ),
03455                                                                    mdContainerName.c_str( ),
03456                                                                    BdbcUpdate )) {
03457                 cout << errorStr << endl
03458                      << "    Failed to locate/open a persistent container with meta-data." << endl
03459                      << "    The database may not be properly initialized/loaded." << endl
03460                      << "        CONTAINER NAME:     \"" << mdContainerName.c_str( ) << "\"" << endl
03461                      << "        DATABASE FILE NAME: \"" << databaseName.c_str( ) << "\"" << endl;
03462                 break;
03463             }
03464         }
03465         if( BdbIsNull(_obContH)) {
03466             if( CdbStatus::Success != CdbBdbSUtils::findContainer( _obContH,
03467                                                                    databaseName.c_str( ),
03468                                                                    obContainerName.c_str( ),
03469                                                                    BdbcUpdate )) {
03470                 cout << errorStr << endl
03471                      << "    Failed to locate/open a persistent container with condition objects." << endl
03472                      << "    The database may not be properly initialized/loaded." << endl
03473                      << "        CONTAINER NAME:     \"" << obContainerName.c_str( ) << "\"" << endl
03474                      << "        DATABASE FILE NAME: \"" << databaseName.c_str( ) << "\"" << endl;
03475                 break;
03476             }
03477         }
03478 
03479       // Find out the meta-data object.
03480 
03481         BdbHandle(CdbBdbSMetaDataP) mdH;
03482         if( BdbcSuccess != mdH.lookupObj( _mdContH,
03483                                           "MetaData" )) {
03484             cout << errorStr << endl
03485                  << "    Failed to locate the \"MetaData\" registry object in the container." << endl
03486                  << "    The database may not be properly initialized/loaded." << endl
03487                  << "        CONTAINER NAME:     \"" << mdContainerName.c_str( ) << "\"" << endl
03488                  << "        DATABASE FILE NAME: \"" << databaseName.c_str( ) << "\"" << endl;
03489             break;
03490         }
03491         assert( mdH->ooIsKindOf( ooTypeN( CdbBdbSMetaDataP )));
03492 
03493       // Invoke the object creator.
03494       //
03495       // NOTE #1: That we're using the truncated end time instead of the original
03496       //          one. It's important for partitionable conditions.
03497       //
03498       // NOTE #2: The creator will use the condition objects container open above
03499       //          to place new condition objects.
03500 
03501         CdbConditionPtr myPtr( this->clone( ));
03502 
03503         if( CdbStatus::Success != theObjectFactory.create( theObjectPtr,
03504                                                            myPtr,
03505                                                            theBegin,
03506                                                            truncatedEnd )) break;
03507         assert( !theObjectPtr.isNull( ));
03508 
03509       // Get object handle
03510 
03511         BdbHandle(BdbObject) objectH;
03512         if( CdbStatus::Success != CdbBdbObjectConvertor::narrow( objectH,
03513                                                                  theObjectPtr )) {
03514             cout << errorStr << endl
03515                  << "    Failed to narrow just created object into a paersistent handle." << endl
03516                  << "        CONDITION NAME: \"" << name( ) << "\"" << endl;
03517             break;
03518         }
03519         assert( !BdbIsNull(objectH));
03520 
03521       // Update partition's modification time if the current condition
03522       // is the partitionable one.
03523 
03524         BdbTime insertionTime( BdbTime::now( ));
03525 
03526         if( isPartitionable ) {
03527             if( CdbStatus::Success != pRef->update( insertionTime )) {
03528 
03529                 cout << errorStr << endl
03530                      << "    Failed to update the partition modification time." << endl
03531                      << "        PARTITION ID:   " << pRef->id( ) << endl
03532                      << "        CONDITION NAME: \"" << name( ) << "\"" << endl;
03533 
03534                 BdbDelete(objectH);
03535                 break;
03536             }
03537         }
03538 
03539       // Register the persistent object in the meta-data.
03540 
03541         if( CdbStatus::Success != mdH->insert( CdbBdbSOi( theBegin,
03542                                                           truncatedEnd,
03543                                                           insertionTime,
03544                                                           objectH ))) {
03545             cout << errorStr << endl
03546                  << "    Failed to insert the information about a newely created object" << endl
03547                  << "    into meta-data structures of the condition." << endl
03548                  << "        CONDITION NAME: \"" << name( ) << "\"" << endl;
03549 
03550             BdbDelete(objectH);
03551             break;
03552         }
03553 
03554         CDB_DEBUG_STREAM << "CDB_STORE_OBJECT_1: " << objectH.sprint( ) << endl; 
03555 
03556       // Done
03557 
03558         result = CdbStatus::Success;
03559 
03560     } while( false );
03561 
03562     return result;
03563 }
03564 
03565 CdbStatus
03566 CdbBdbSCondition::storeAndTruncateObject( CdbObjectFactoryBase& theObjectFactory,
03567                                           const BdbTime&        theStoreTime,
03568                                           const BdbTime&        theTruncateTime,
03569                                           CdbObjectPtr&         theObjectPtr )
03570 {
03571     return storeObject( theObjectFactory,
03572                         theStoreTime,
03573                         BdbTime::plusInfinity,
03574                         theObjectPtr );
03575 }
03576 
03577 CdbStatus
03578 CdbBdbSCondition::split( const BdbTime& theTime )
03579 {
03580     cout << "CdbBdbSCondition::split() -- WARNING" << endl
03581          << "    The 'split interval' is the 'noop' operations in this" << endl
03582          << "    implementation of the API. This operation is only provided for backward" << endl
03583          << "    compatibility with the old condition database. Eventually it will be phased out." << endl;
03584 
03585     return CdbStatus::Success;
03586 }
03587 
03588 bool
03589 CdbBdbSCondition::isValid( )
03590 {
03591     return true;
03592 }
03593 
03594 bool
03595 CdbBdbSCondition::isOpen( )
03596 {
03597     return true;
03598 }
03599 
03600 CdbStatus
03601 CdbBdbSCondition::open( )
03602 {
03603     return CdbStatus::Success;
03604 }
03605 
03606 CdbStatus
03607 CdbBdbSCondition::close( )
03608 {
03609     return CdbStatus::Success;
03610 }
03611 
03612 CdbStatus
03613 CdbBdbSCondition::findRevision( CdbRevisionPtr& thePtr,
03614                                 const BdbTime&  theId,
03615                                 unsigned short  thePartitionId )
03616 {
03617     const char* errorStr = "CdbBdbSCondition::findRevision(id) -- ERROR";
03618 
03619     CdbStatus result = CdbStatus::NotFound;
03620     do {
03621 
03622        // Find all metadata objects corresponding to current condition/partition.
03623 
03624         std::vector<BdbRef(CdbBdbSMetaDataP)> vectorOfMdRefs;
03625 
03626         bool allIncrementsFlag = true;
03627 
03628         if( CdbStatus::Success !=  findMetaData( vectorOfMdRefs,
03629                                                  _masterRegistryH,
03630                                                  _localRegistryH,
03631                                                  _physicalAddress,
03632                                                  thePartitionId,
03633                                                  allIncrementsFlag )) {
03634             cout << errorStr << endl
03635                  << "    Failed to locate the MetaData objects for the current condition/partition." << endl;
03636             break;
03637         }
03638 
03639       // Find an appropriate one
03640 
03641         BdbRef(CdbBdbSRevisionP) rRef;
03642         {
03643             bool found = false;
03644 
03645             std::vector<BdbRef(CdbBdbSMetaDataP)>::const_iterator itr;
03646             for( itr = vectorOfMdRefs.begin( ); itr < vectorOfMdRefs.end( ); ++itr ) {
03647 
03648                 BdbRef(CdbBdbSMetaDataP) mdRef = (*itr);
03649                 if( CdbStatus::Success == mdRef->findRevision( theId,
03650                                                                rRef )) {
03651                     found = true;
03652                     break;
03653                 }
03654             }
03655             if( !found ) break;
03656         }
03657 
03658       // Construct the transient revision object.
03659 
03660       //
03661       // DESIGN NOTE: We need to construct a smart pointer against a clone since
03662       //              we don't know a smart pointer pointing to the current
03663       //              instance, therefore we can't guarantee the lifetime
03664       //              of the current instance.
03665 
03666         CdbConditionPtr myPtr( this->clone( ));
03667 
03668         thePtr = new CdbBdbSRevision( myPtr,
03669                                       rRef );
03670 
03671       // Done
03672 
03673         result = CdbStatus::Success;
03674 
03675     } while( false );
03676 
03677     return result;
03678 }
03679 
03680 CdbStatus
03681 CdbBdbSCondition::findRevision( CdbRevisionPtr& thePtr,
03682                                 const char*     theName,
03683                                 unsigned short  thePartitionId )
03684 {
03685     const char* errorStr = "CdbBdbSCondition::findRevision(name) -- ERROR";
03686 
03687     CdbStatus result = CdbStatus::NotFound;
03688     do {
03689 
03690        // Find all metadata objects corresponding to current condition/partition.
03691 
03692         std::vector<BdbRef(CdbBdbSMetaDataP)> vectorOfMdRefs;
03693 
03694         bool allIncrementsFlag = true;
03695 
03696         if( CdbStatus::Success !=  findMetaData( vectorOfMdRefs,
03697                                                  _masterRegistryH,
03698                                                  _localRegistryH,
03699                                                  _physicalAddress,
03700                                                  thePartitionId,
03701                                                  allIncrementsFlag )) {
03702             cout << errorStr << endl
03703                  << "    Failed to locate the MetaData objects for the current condition/partition." << endl;
03704             break;
03705         }
03706 
03707       // Find an appropriate one
03708 
03709         BdbRef(CdbBdbSRevisionP) rRef;
03710         {
03711             bool found = false;
03712 
03713             std::vector<BdbRef(CdbBdbSMetaDataP)>::const_iterator itr;
03714             for( itr = vectorOfMdRefs.begin( ); itr < vectorOfMdRefs.end( ); ++itr ) {
03715 
03716                 BdbRef(CdbBdbSMetaDataP) mdRef = (*itr);
03717                 if( CdbStatus::Success == mdRef->findRevision( theName,
03718                                                                rRef )) {
03719                     found = true;
03720                     break;
03721                 }
03722             }
03723             if( !found ) break;
03724         }
03725 
03726       // Construct the transient revision object.
03727 
03728       //
03729       // DESIGN NOTE: We need to construct a smart pointer against a clone since
03730       //              we don't know a smart pointer pointing to the current
03731       //              instance, therefore we can't guarantee the lifetime
03732       //              of the current instance.
03733 
03734         CdbConditionPtr myPtr( this->clone( ));
03735 
03736         thePtr = new CdbBdbSRevision( myPtr,
03737                                       rRef );
03738 
03739       // Done
03740 
03741         result = CdbStatus::Success;
03742 
03743     } while( false );
03744 
03745     return result;
03746 }
03747 
03748 CdbStatus
03749 CdbBdbSCondition::revisionIdIterator( CdbItr<BdbTime>& theItr,
03750                                       unsigned short   thePartitionId )
03751 {
03752     const char* errorStr = "CdbBdbSCondition::revisionIdIterator() -- ERROR";
03753 
03754     CdbStatus result = CdbStatus::Error;
03755     do {
03756 
03757       // Find all metadata objects corresponding to current condition/partition.
03758 
03759         std::vector<BdbRef(CdbBdbSMetaDataP)> vectorOfMdRefs;
03760 
03761         bool allIncrementsFlag = true;
03762 
03763         if( CdbStatus::Success !=  findMetaData( vectorOfMdRefs,
03764                                                  _masterRegistryH,
03765                                                  _localRegistryH,
03766                                                  _physicalAddress,
03767                                                  thePartitionId,
03768                                                  allIncrementsFlag )) {
03769             cout << errorStr << endl
03770                  << "    Failed to locate the MetaData objects for the current condition/partition." << endl;
03771             break;
03772         }
03773 
03774       // ATTENTION: This is not a memory leak - the created object
03775       //            will be destroyed by the iterator.
03776 
03777         theItr = CdbItr<BdbTime>( new RevisionIdIterator( vectorOfMdRefs ));
03778 
03779       // Done
03780 
03781         result = CdbStatus::Success;
03782 
03783     } while( false );
03784 
03785     return result;
03786 }
03787 
03788 CdbStatus
03789 CdbBdbSCondition::revisionNameIterator( CdbItr<const char*>& theItr,
03790                                         unsigned short       thePartitionId )
03791 {
03792     const char* errorStr = "CdbBdbSCondition::revisionNameIterator() -- ERROR";
03793 
03794     CdbStatus result = CdbStatus::Error;
03795     do {
03796 
03797       // Find all metadata objects corresponding to current condition/partition.
03798 
03799         std::vector<BdbRef(CdbBdbSMetaDataP)> vectorOfMdRefs;
03800 
03801         bool allIncrementsFlag = true;
03802 
03803         if( CdbStatus::Success !=  findMetaData( vectorOfMdRefs,
03804                                                  _masterRegistryH,
03805                                                  _localRegistryH,
03806                                                  _physicalAddress,
03807                                                  thePartitionId,
03808                                                  allIncrementsFlag )) {
03809             cout << errorStr << endl
03810                  << "    Failed to locate the MetaData objects for the current condition/partition." << endl;
03811             break;
03812         }
03813 
03814       // ATTENTION: This is not a memory leak - the created object
03815       //            will be destroyed by the iterator.
03816 
03817         theItr = CdbItr<const char*>( new RevisionNameIterator( vectorOfMdRefs ));
03818 
03819       // Done
03820 
03821         result = CdbStatus::Success;
03822 
03823     } while( false );
03824 
03825     return result;
03826 }
03827 
03828 CdbStatus
03829 CdbBdbSCondition::createRevision( CdbRevisionPtr& thePtr,
03830                                   const BdbTime&  theId,
03831                                   const char*     theName,
03832                                   const char*     theDescription,
03833                                   unsigned short  thePartitionId )
03834 {
03835     const char* errorStr = "CdbBdbSCondition::createRevision() -- ERROR";
03836     const char* fatalStr = "CdbBdbSCondition::createRevision() -- FATAL ERROR";
03837 
03838     CdbStatus result = CdbStatus::Error;
03839     do {
03840 
03841       // Verify parameters
03842 
03843         if( 0 == theName ) {
03844             cout << errorStr << endl
03845                  << "    The null pointer passed as a parameter where a revision name was expected." << endl
03846                  << "        CONDITION NAME               : \"" << name( ) << "\"" << endl
03847                  << "        CONDITION 'PHYSICAL ADDRESS' : " << _physicalAddress << endl;
03848             break;            
03849         }
03850 
03851       // Check if the revsion can be created in the current condition
03852       // (and specified partition if we have a 'PARTITIONABLE' condition).
03853       //
03854       // The criteria is as follows:
03855       //
03856       //   'regular'       :  these condition can only be modified in their (condition's) origin database
03857       //
03858       //   'partitionable' :  the specified partition of these conditions can only be modified
03859       //                      in their (partition's) origin database. The partition must be "instantiated"
03860       //                      and it must be in the "open" state.
03861 
03862         if( isPartitionable( )) {
03863 
03864           // Find the partition
03865 
03866             BdbHandle(CdbBdbSPartitionP) pH;
03867             if( CdbStatus::Success != findPartition( pH,thePartitionId )) {
03868                 cout << errorStr << endl
03869                      << "    Failed to find the specified partition." << endl
03870                      << "        PARTITION ID : " << thePartitionId << endl;
03871                 break;            
03872             }
03873 
03874           // Cross-check the partition's origin against the current database's origin
03875           // to see if they're equal.
03876 
03877             if( _localRegistryH->originId( ) != pH->originId( )) {
03878                 cout << errorStr << endl
03879                      << "    The specified partition is not the local one. This operation does" << endl
03880                      << "    not allow modifying partitions of 'partitionable' conditions which" << endl
03881                      << "    are not owned by the current database origin." << endl
03882                      << "        CONDITION NAME               : \"" << name( ) << "\"" << endl
03883                      << "        CONDITION 'PHYSICAL ADDRESS' : " << _physicalAddress << endl
03884                      << "        PARTITION ID                 : " << thePartitionId << endl
03885                      << "        LOCAL ORIGIN ID              : " << _localRegistryH->originId( ) << endl
03886                      << "        PARTITION ORIGIN ID          : " << pH->originId( ) << endl;
03887                 break;
03888             }
03889 
03890           // Also check if the partition is in the right state.
03891 
03892             if( !pH->isInstantiated( )) {
03893                 cout << errorStr << endl
03894                      << "    The specified partition is not instantiated inthe local database." << endl
03895                      << "        CONDITION NAME               : \"" << name( ) << "\"" << endl
03896                      << "        CONDITION 'PHYSICAL ADDRESS' : " << _physicalAddress << endl
03897                      << "        PARTITION ID                 : " << thePartitionId << endl;
03898                 break;
03899             }
03900             if( pH->isClosed( )) {
03901                 cout << errorStr << endl
03902                      << "    The specified partition is already 'closed' for any further modifications." << endl
03903                      << "    The requested operations can not be completed." << endl
03904                      << "        CONDITION NAME               : \"" << name( ) << "\"" << endl
03905                      << "        CONDITION 'PHYSICAL ADDRESS' : " << _physicalAddress << endl
03906                      << "        PARTITION ID                 : " << thePartitionId << endl;
03907                 break;
03908             }
03909 
03910         } else {
03911 
03912           // Just cross-check the origin of the condition with the local origin.
03913 
03914             if( _localRegistryH->originId( ) != _physicalAddress.origin ) {
03915                 cout << errorStr << endl
03916                      << "    The current condition is not the local one. This operation does" << endl
03917                      << "    not allow modifying 'regular' conditions which" << endl
03918                      << "    are not owned by the current database origin." << endl
03919                      << "        CONDITION NAME               : \"" << name( ) << "\"" << endl
03920                      << "        CONDITION 'PHYSICAL ADDRESS' : " << _physicalAddress << endl
03921                      << "        LOCAL ORIGIN ID              : " << _localRegistryH->originId( ) << endl;
03922                 break;
03923             }
03924         }
03925 
03926       // Find the metadata object corresponding to the topmost revision.
03927       // This is where we're going to ceate a new revision by cloning from
03928       // the topmost one.
03929 
03930         BdbHandle(CdbBdbSMetaDataP) mdH;
03931         {
03932             std::vector<BdbRef(CdbBdbSMetaDataP)> vectorOfMdRefs;
03933 
03934             bool allIncrementsFlag   = false;
03935             bool recentIncrementFlag = true;
03936 
03937             if( CdbStatus::Success !=  findMetaData( vectorOfMdRefs,
03938                                                      _masterRegistryH,
03939                                                      _localRegistryH,
03940                                                      _physicalAddress,
03941                                                      thePartitionId,
03942                                                      allIncrementsFlag,
03943                                                      recentIncrementFlag )) {
03944                 cout << errorStr << endl
03945                      << "    Failed to locate the most recent MetaData object for the condition/partition." << endl
03946                      << "        CONDITION NAME               : \"" << name( ) << "\"" << endl
03947                      << "        CONDITION 'PHYSICAL ADDRESS' : " << _physicalAddress << endl
03948                      << "        PARTITION ID                 : " << thePartitionId << endl;
03949                 break;
03950             }
03951             assert( 1 == vectorOfMdRefs.size( ));
03952 
03953             mdH = vectorOfMdRefs[0];
03954         }
03955 
03956       // Create the specified revision
03957 
03958         BdbTime rCreated( BdbTime::now( ));
03959 
03960         if( CdbStatus::Success !=  mdH->createRevision( theId,
03961                                                         theName,
03962                                                         rCreated,
03963                                                         theDescription )) {
03964             cout << errorStr << endl
03965                  << "    Failed to create a new revision with specified parameters in the most recent" << endl
03966                  << "    MetaData object for the condition/partition." << endl
03967                  << "        CONDITION NAME               : \"" << name( ) << "\"" << endl
03968                  << "        CONDITION 'PHYSICAL ADDRESS' : " << _physicalAddress << endl
03969                  << "        PARTITION ID                 : " << thePartitionId << endl
03970                  << "        REVISION ID                  : " << CdbTimeUtils::time2string( theId ) << " : " << theId << endl
03971                  << "        REVISION NAME                : \"" << theName << endl;
03972             break;
03973         }
03974 
03975       // Create a transient API object representing a newely created revision
03976 
03977         {
03978 
03979           // Find the persistent object
03980 
03981             BdbRef(CdbBdbSRevisionP) rRef;
03982             if( CdbStatus::Success !=  mdH->findRevision( theId,
03983                                                           rRef )) {
03984                 cout << fatalStr << endl
03985                      << "    Failed to find just created new revision in the most recent" << endl
03986                      << "    MetaData object for the condition/partition." << endl
03987                      << "        CONDITION NAME               : \"" << name( ) << "\"" << endl
03988                      << "        CONDITION 'PHYSICAL ADDRESS' : " << _physicalAddress << endl
03989                      << "        PARTITION ID                 : " << thePartitionId << endl
03990                      << "        REVISION ID                  : " << CdbTimeUtils::time2string( theId ) << " : " << theId << endl
03991                      << "        REVISION NAME                : \"" << theName << endl;
03992 
03993                 assert(0);
03994 
03995                 break;
03996             }
03997 
03998           // Construct the transient revision object.
03999 
04000           //
04001           // DESIGN NOTE: We need to construct a smart pointer against a clone since
04002           //              we don't know a smart pointer pointing to the current
04003           //              instance, therefore we can't guarantee the lifetime
04004           //              of the current instance.
04005 
04006             CdbConditionPtr myPtr( this->clone( ));
04007 
04008             thePtr = new CdbBdbSRevision( myPtr,
04009                                           rRef );
04010         }
04011 
04012       // Done
04013 
04014         result = CdbStatus::Success;
04015 
04016     } while( false );
04017 
04018     return result;
04019 }
04020 
04021 CdbStatus
04022 CdbBdbSCondition::historyEventIterator( CdbHistoryEventItr& theItr,
04023                                         const BdbTime&      theBeginTime,
04024                                         const BdbTime&      theEndTime,
04025                                         const char**        theEventsToSelect )
04026 {
04027     return CdbStatus::NotImplemented;
04028 }
04029 
04030 CdbStatus
04031 CdbBdbSCondition::historyEventTypeIterator( CdbHistoryEventTypeItr& theItr )
04032 {
04033     return CdbStatus::NotImplemented;
04034 }
04035 
04036 CdbStatus
04037 CdbBdbSCondition::hint( BdbRefAny&     theHint,
04038                         const BdbTime& theBegin,
04039                         const BdbTime& theEnd )
04040 {
04041     CdbStatus result = CdbStatus::NotFound;
04042     do {
04043 
04044         assert( !BdbIsNull(_obContH));
04045 
04046       // Return the cached value of the objects container handle
04047       // initialized at the "storeObject()" stage.
04048 
04049         theHint = _obContH;
04050 
04051       // Done
04052 
04053         result = CdbStatus::Success;
04054 
04055     } while( false );
04056 
04057     return result;
04058 }
04059 
04060 CdbStatus
04061 CdbBdbSCondition::verify( const BdbRefAny&         theHint,
04062                           const BdbRef(BdbObject)& theObjectRef )
04063 {
04064     CdbStatus result = CdbStatus::Error;
04065 
04066     do {
04067 
04068       // All we're going to check is to see if both the hint and
04069       // the objects are located in the same container.
04070 
04071         if( BdbIsNull( theHint ))      break;
04072         if( BdbIsNull( theObjectRef )) break;
04073 
04074         BdbRef(BdbContObj) hintContRef;
04075         BdbRef(BdbContObj) objectContRef;
04076 
04077         theHint.containedIn( hintContRef );
04078         theObjectRef.containedIn( objectContRef );
04079 
04080         if( BdbIsNull( hintContRef ))   break;
04081         if( BdbIsNull( objectContRef )) break;
04082 
04083         if( hintContRef == objectContRef ) result = CdbStatus::Success;
04084 
04085     } while( false );
04086 
04087     return result;
04088 }
04089 
04090 CdbStatus
04091 CdbBdbSCondition::findPartition( BdbHandle(CdbBdbSPartitionP)& theHandle,
04092                                  d_UShort                      thePartitonId ) const
04093 {
04094     const char* errorStr = "CdbBdbSCondition::findPartition() -- ERROR";
04095 
04096     CdbStatus result = CdbStatus::Error;
04097 
04098     do {
04099 
04100       // The partition location can be a two-stage process, First we look for general
04101       // partition information at the MASTER registry. Then we need to verify if the
04102       // found partition belongs to the local registry. If so then we reload
04103       // partition information from the local registry since this partition
04104       // is supposed to be modified locally.
04105 
04106         BdbHandle(CdbBdbSPartitionP) pH;
04107         {
04108             BdbHandle(CdbBdbSPartitionsLayoutP) pLayoutH = _masterRegistryH->partitionsLayout( );
04109             assert( ! BdbIsNull(pLayoutH));
04110 
04111             BdbRef(CdbBdbSPartitionP) pRef;
04112             if( CdbStatus::Success != pLayoutH->find( thePartitonId,
04113                                                       pRef )) {
04114                 cout << errorStr << endl
04115                      << "    Failed to find a partition #" << thePartitonId << " at the MASTER registry." << endl;
04116                 break;
04117             }
04118             pH = pRef;
04119         }
04120         if(( _localRegistryH->originId( ) == pH->originId( )) &&
04121            ( _localRegistryH->originId( ) != _masterRegistryH->originId( ))) {
04122 
04123             BdbHandle(CdbBdbSPartitionsLayoutP) pLayoutH = _localRegistryH->partitionsLayout( );
04124             assert( ! BdbIsNull(pLayoutH));
04125 
04126             BdbRef(CdbBdbSPartitionP) pRef;
04127             if( CdbStatus::Success != pLayoutH->find( thePartitonId,
04128                                                       pRef )) {
04129                 cout << errorStr << endl
04130                      << "    Failed to find a partition #" << thePartitonId << " at the local registry." << endl
04131                      << "    Perhaps the partition has not been 'instantiated' yet in the local" << endl
04132                      << "    database after being created by MASTER CDB." << endl;
04133                 break;
04134             }
04135             pH = pRef;
04136         }
04137         theHandle = pH;
04138 
04139       // Done
04140 
04141         result = CdbStatus::Success;
04142 
04143     } while( false );
04144 
04145     return result;
04146 }
04147 
04148 CdbStatus
04149 CdbBdbSCondition::findInitialPartition( const BdbTime&                theValidityTime,
04150                                         const BdbTime&                theInsertionTime,
04151                                         BdbHandle(CdbBdbSPartitionP)& theHandle,
04152                                         std::string&                  theDbIdRange ) const
04153 {
04154     const char* errorStr = "CdbBdbSCondition::findInitialPartition() -- ERROR";
04155 
04156     CdbStatus result = CdbStatus::Error;
04157 
04158     do {
04159 
04160       // The temporary partition reference required by some interfaces.
04161 
04162         BdbRef(CdbBdbSPartitionP) pRef;
04163 
04164       // The partition location can be a two-stage process, First we look for general
04165       // partition information at the MASTER registry. Then we need to verify if the
04166       // found partition belongs to the local registry. If so then we reload
04167       // partition information from the local registry since this partition
04168       // is supposed to be modified locally.
04169 
04170         BdbRef(CdbBdbSPartitionsLayoutP) pLayoutRef = _masterRegistryH->partitionsLayout( );
04171         assert( ! BdbIsNull(pLayoutRef));
04172 
04173         if( BdbTime::plusInfinity == theInsertionTime ) {
04174 
04175             if( CdbStatus::Success != pLayoutRef->topmost( theValidityTime,
04176                                                            pRef )) {
04177                 cout << errorStr << endl
04178                      << "    Failed to find a 'topmost' partition for specified validity time" << endl
04179                      << "    at the master registry." << endl
04180                      << "        VALIDITY TIME: " << theValidityTime << endl;
04181                 break;
04182             }
04183 
04184         } else {
04185 
04186             if( CdbStatus::Success != pLayoutRef->find( theValidityTime,
04187                                                         theInsertionTime,
04188                                                         pRef )) {
04189                 cout << errorStr << endl
04190                      << "    Failed to find a partition at specified point of 2-D timespace" << endl
04191                      << "    at the master registry." << endl
04192                      << "        VALIDITY  TIME: " << theValidityTime << endl
04193                      << "        INSERTION TIME: " << theInsertionTime << endl;
04194                 break;
04195             }
04196         }
04197         theHandle = pRef;
04198 
04199         d_UShort partitionId = theHandle->id( );
04200 
04201         if(( _localRegistryH->originId( ) == theHandle->originId( )) &&
04202            ( _localRegistryH->originId( ) != _masterRegistryH->originId( ))) {
04203 
04204             pLayoutRef = _localRegistryH->partitionsLayout( );
04205             assert( ! BdbIsNull(pLayoutRef));
04206 
04207             if( CdbStatus::Success != pLayoutRef->find( partitionId,
04208                                                         pRef )) {
04209                 cout << errorStr << endl
04210                      << "    Failed to find a partition #" << partitionId << " at the local registry." << endl;
04211                 break;
04212             }
04213             theHandle = pRef;
04214         }
04215 
04216       // Now find the DBID range name for the partition
04217 
04218         BdbRef(CdbBdbSOriginCollectionP) originCollRef = _masterRegistryH->originCollection( );
04219         assert( ! BdbIsNull(originCollRef));
04220 
04221         BdbRef(CdbBdbSOriginP) originRef;
04222         if( CdbStatus::Success != originCollRef->find( theHandle->originId( ),
04223                                                        originRef )) {
04224             cout << errorStr << endl
04225                  << "    Failed to find origin information for the partition #" << partitionId << " at the master registry." << endl;
04226             break;
04227         }
04228         theDbIdRange = originRef->dbidrange( ).head( );
04229 
04230       // Done
04231 
04232         result = CdbStatus::Success;
04233 
04234     } while( false );
04235 
04236     return result;
04237 }
04238 
04239 CdbStatus
04240 CdbBdbSCondition::findNextPartition( const BdbTime&                theValidityTime,
04241                                      BdbHandle(CdbBdbSPartitionP)& theHandle,
04242                                      std::string&                  theDbIdRange ) const
04243 {
04244     const char* errorStr = "CdbBdbSCondition::findNextPartition() -- ERROR";
04245 
04246     assert( !BdbIsNull(theHandle));
04247 
04248     CdbStatus result = CdbStatus::Error;
04249 
04250     do {
04251 
04252       // The partition location can be a tree-stage process,
04253       //
04254       //  (1) First we look for general partition information corresponding to the old
04255       //      partition at the MASTER registry. We need this step since the "next" operation
04256       //      could be based on comparision of references rather than partitions identifiers.
04257       //      So we need to obtain the right reference to succeed.
04258       //
04259       //  (2) Then we're trying to locate the information about the next partition from
04260       //      the same master registry.
04261       //
04262       //  (3) And finally we need to verify if the found partition belongs to the local registry.
04263       //      If so then we reload partition information from the local registry since this partition
04264       //      is supposed to be modified locally.
04265 
04266       // -1-
04267 
04268         BdbRef(CdbBdbSPartitionsLayoutP) pLayoutRef = _masterRegistryH->partitionsLayout( );
04269         assert( ! BdbIsNull(pLayoutRef));
04270 
04271         d_UShort prevPartitionId = theHandle->id( );
04272 
04273         BdbRef(CdbBdbSPartitionP) prevPartRef;
04274         if( CdbStatus::Success != pLayoutRef->find( prevPartitionId,
04275                                                     prevPartRef )) {
04276             cout << errorStr << endl
04277                      << "    Failed to find a partition #" << prevPartitionId << " at the master registry." << endl;
04278             break;
04279         }
04280 
04281       // -2-
04282 
04283         BdbRef(CdbBdbSPartitionP) nextPartRef = prevPartRef;
04284         CdbStatus tmpResult = pLayoutRef->next( theValidityTime,
04285                                                 nextPartRef );
04286         if( CdbStatus::Success == tmpResult ) {
04287             ;
04288         } else {
04289             if( CdbStatus::NotFound == tmpResult ) {
04290                 result = tmpResult;
04291             } else {
04292                 cout << errorStr << endl
04293                      << "    Failed to find a 'next' partition for specified validity time" << endl
04294                      << "    at the master registry." << endl
04295                      << "        VALIDITY TIME:       " << theValidityTime << endl
04296                      << "        PREVIOUS PARTITION: #" << prevPartitionId << endl;
04297             }
04298             break;
04299         }
04300 
04301       // -3-
04302 
04303         theHandle = nextPartRef;
04304 
04305         d_UShort partitionId = theHandle->id( );
04306 
04307         if(( _localRegistryH->originId( ) == theHandle->originId( )) &&
04308            ( _localRegistryH->originId( ) != _masterRegistryH->originId( ))) {
04309 
04310             pLayoutRef = _localRegistryH->partitionsLayout( );
04311             assert( ! BdbIsNull(pLayoutRef));
04312 
04313             BdbRef(CdbBdbSPartitionP) pRef;
04314             if( CdbStatus::Success != pLayoutRef->find( partitionId,
04315                                                         pRef )) {
04316                 cout << errorStr << endl
04317                      << "    Failed to find a partition #" << partitionId << " at the local registry." << endl;
04318                 break;
04319             }
04320             theHandle = pRef;
04321         }
04322 
04323       // Now find the DBID range name for the partition
04324 
04325         BdbRef(CdbBdbSOriginCollectionP) originCollRef = _masterRegistryH->originCollection( );
04326         assert( ! BdbIsNull(originCollRef));
04327 
04328         BdbRef(CdbBdbSOriginP) originRef;
04329         if( CdbStatus::Success != originCollRef->find( theHandle->originId( ),
04330                                                        originRef )) {
04331             cout << errorStr << endl
04332                  << "    Failed to find origin information for the partition #" << partitionId << " at the master registry." << endl;
04333             break;
04334         }
04335         theDbIdRange = originRef->dbidrange( ).head( );
04336 
04337       // Done
04338 
04339         result = CdbStatus::Success;
04340 
04341     } while( false );
04342 
04343     return result;
04344 }
04345 
04346 CdbStatus
04347 CdbBdbSCondition::doFindObjectAtPartition( const CdbRevisionPolicy& thePolicy,
04348                                            const BdbTime&           theValidityTime,
04349                                            const BdbTime&           theInsertionTime,
04350                                            CdbBdbSOi&               theOriginalInterval,
04351                                            BdbTime&                 theBeginOfVisiblePeriod,
04352                                            BdbTime&                 theEndOfVisiblePeriod,
04353                                            BdbTime&                 theBeginOfDurationPeriod,
04354                                            BdbTime&                 theEndOfDurationPeriod ) const
04355 {
04356     const char* debugStr = "CdbBdbSCondition::doFindObjectAtPartition()";
04357     const char* errorStr = "CdbBdbSCondition::doFindObjectAtPartition() -- ERROR";
04358 
04359     CdbStatus result = CdbStatus::Error;
04360 
04361     do {
04362 
04363       // Make sure this is a proper use of the algorithm. Just in case...
04364 
04365         assert( _conditionH->isPartitionable( ));
04366 
04367       // Verify parameters and extract revision to begin with
04368 
04369         bool    useRevisions = thePolicy.useRevision( );
04370         BdbTime rId          = thePolicy.revisionId( );
04371 
04372         if( useRevisions ) {
04373 
04374             ;   // Nothing more to say
04375 
04376         } else if( BdbTime::plusInfinity == theInsertionTime ) {
04377 
04378             useRevisions = true;                    // Need this for the topmost revision
04379             rId          = BdbTime::plusInfinity;   // TOPMOST revision
04380 
04381         } else {
04382 
04383             rId = theInsertionTime;     // Still, no revisions
04384         }
04385 
04386       // Get the condition creation time.
04387       //
04388       // IMPORTANT NOTE:
04389       //
04390       //     We would need this information to see which increments (MetaData)
04391       //     to include into the search,
04392       //     The reason why we're doing this check is that conditions
04393       //     may be created (put into a cluster) when the correspodning clusters
04394       //     already have more than 1 increment. Therefore some earlier partitions or increments
04395       //     may just not have any MetaData fore newer conditions.
04396 
04397         BdbTime creationTime = _conditionH->created( );
04398 
04399         if( rId < creationTime ) {
04400             cout << errorStr << endl
04401                  << "    Specified revision identifier / insertion time is older" << endl
04402                  << "    than the time when the condition was created." << endl
04403                  << "    The current view may be inproperly configured for the condition." << endl
04404                  << "        REVISION ID / INSERTION TIME : " << rId << endl
04405                  << "        CONDITION CREATION TIME      : " << creationTime << endl
04406                  << "        CONDITION NAME               : \"" << name( ) << "\"" << endl
04407                  << "        PARENT FOLDER NAME           : \"" << parent( )->name( ) << "\"" << endl
04408                  << "        VIEW NAME                    : \"" << parent( )->parentView( )->name( ) << "\"" << endl;
04409             break;
04410         }
04411 
04412       // Find out a the cluster the condition belongs to.
04413 
04414         BdbRef(CdbBdbSClusterP) clusterRef = _conditionH->cluster( );
04415         assert( !BdbIsNull(clusterRef));
04416 
04417       // Find the initial <partition> to begin with.
04418       //
04419       // NOTE: We're going to check if the partion is closed. If so if its
04420       //       upper "insertion" time boundry is strictly above the condition
04421       //       creation time. Otherwise we just quit here since no MetaData
04422       //       for the recently created condition should exist in his partition.
04423 
04424         BdbHandle(CdbBdbSPartitionP) pH;
04425 
04426         std::string dbIdRange;
04427 
04428         if( CdbStatus::Success != findInitialPartition( theValidityTime,
04429                                                         rId,
04430                                                         pH,
04431                                                         dbIdRange )) {
04432             break;
04433         }
04434 
04435 /******************************************************************/
04436 if( CdbEnvironment::getDebugMode( ) != 0 )
04437     cout << debugStr << endl
04438          << "{" << endl
04439          << "    Found initial partition ID=" << pH->id( ) << endl
04440          << "}" << endl;
04441 /******************************************************************/
04442 
04443         if( pH->isClosed( )) {
04444             CdbBdbSCell pCell = pH->cell( );
04445             if( pCell.endInsertion <= creationTime ) {
04446 
04447 /***************************************************************/
04448 if( CdbEnvironment::getDebugMode( ) != 0 )
04449 cout << debugStr << endl
04450  << "{" << endl
04451  << "    The just found partition is already 'closed' and its upper 'insertion'" << endl
04452  << "    time limit is older than the creation time of the current condition." << endl
04453  << "    So no object has been found." << endl
04454  << "        creationTime       : " << creationTime << endl
04455  << "        pCell.endInsertion : " << pCell.endInsertion << endl
04456  << "}" << endl;
04457 /***************************************************************/
04458 
04459                 result = CdbStatus::NotFound;
04460                 break;
04461             }
04462         }
04463 
04464       //  Then find the increments range for specified revision time.
04465 
04466         d_UShort firstIncrement = 0;
04467         d_UShort lastIncrement  = 0;
04468         {
04469             d_UShort numIncrements = pH->numIncrements( );
04470             assert( numIncrements > 0 );
04471 
04472           // Find the very first increment including the creation time
04473           // of the condition.
04474 
04475             {
04476                 bool failed = true;
04477 
04478                 for( d_UShort i = 0; i < numIncrements; ++i ) {
04479 
04480                     CdbBdbSIncrement iVal;
04481                     if( CdbStatus::Success != pH->increment( i,
04482                                                              iVal )) {
04483                         break;
04484                     }
04485                     if( creationTime < iVal.end ) {
04486 
04487                         firstIncrement = i;
04488 
04489                         failed = false;
04490                         break;
04491                     }
04492                 }
04493                 if( failed ) {
04494                     cout << errorStr << endl
04495                          << "    Failed to find the smallest increment number at a partition #" << pH->id( ) << endl
04496                          << "    The current federation may not be properly initialized/loaded." << endl;
04497                     break;
04498                 }
04499             }
04500 
04501           // Find the very last increment including specified revision
04502           //
04503           // NOTE: This search begins with the above found very first
04504           //       increment number.
04505 
04506             if( BdbTime::plusInfinity == rId ) {
04507                 lastIncrement = numIncrements - 1;
04508             } else {
04509 
04510                 bool failed = true;
04511 
04512                 for( d_UShort i = firstIncrement; i < numIncrements; ++i ) {
04513 
04514                     CdbBdbSIncrement iVal;
04515                     if( CdbStatus::Success != pH->increment( i,
04516                                                              iVal )) {
04517                         break;
04518                     }
04519                     if(( rId >= iVal.begin ) && ( rId <  iVal.end )) {
04520 
04521                         lastIncrement = i;
04522 
04523                         failed = false;
04524                         break;
04525                     }
04526                 }
04527                 if( failed ) {
04528                     cout << errorStr << endl
04529                          << "    Failed to find the biggest increment number at a partition #" << pH->id( ) << endl
04530                          << "    The current federation may not be properly initialized/loaded." << endl;
04531                     break;
04532                 }
04533             }
04534         }
04535 
04536 /*********************************************************************/
04537 if( CdbEnvironment::getDebugMode( ) != 0 )
04538     cout << debugStr << endl
04539          << "{" << endl
04540          << "    Initial firstIncrement : " << firstIncrement << endl
04541          << "            lastIncrement  : " << lastIncrement  << endl
04542          << "}" << endl;
04543 /*********************************************************************/
04544 
04545       // Invariant parameters of the databases with metadata information.
04546       // Other parameters, including <partition> & <increment> will be dynamically
04547       // (re-)calculated by the mining algorith described below.
04548 
04549         CdbBdbSId cId = _physicalAddress;
04550 
04551         char cIdStr[12];
04552         sprintf( cIdStr, "%u", cId.local );
04553 
04554         char clusterIdStr[12];
04555         sprintf( clusterIdStr, "%u", clusterRef->id( ));
04556 
04557         std::string mdContainerName = std::string( "MetaData." ) + std::string( cIdStr );
04558 
04559       // Now we're ready to begin seraching for condition objects through
04560       // the sequence of partitions & increments.
04561       //
04562       // == ALGORITHM DESCRIPTION ==
04563       //
04564       //  (1) The search algorithm begins with the specified revision/insertion time
04565       //      of the initially found partition & increment and it will proceed down
04566       //      to final revisions of previous increments of the this partition until
04567       //      either the desired interval is found or the bottom of the increments
04568       //      stack is met. The bottom is defined as the lowest increment including
04569       //      the condition's creation time.
04570       //
04571       //  (2) If the bottom of the initial partition is met and desired interval
04572       //      is still not found then we switch to the next partition below
04573       //      the initial one and proceed with the search begining with the final
04574       //      revision of that partition.
04575       //
04576       //  (3) We proceed with step (2) until either we find desired interval or
04577       //      we reach the bottom of the condition. Note, that definition of
04578       //      the "bottom" given at (1) above.
04579       //
04580       // This algorithm is used for both states of the "useRevisions" flag
04581       // calculated above. The only difference is that in case of "!useRevisions"
04582       // we're only given one chance to try the above calculated initial partition & increment
04583       // where the answer for specified insertionTime should be.
04584       // See the details at the implementation of the CdbBdbSMetaDataP::findByInsertion()
04585       // method.
04586       //
04587       // Here is a pseudo-graphical representation of this process:
04588       //
04589       //           <validity time>
04590       //                   |
04591       //                   |
04592       // ..................|..............................................
04593       // :Partition M      |                                             :
04594       // : ................|............................................ :
04595       // : :Increment MAX  |                                           : :
04596       // : :               |                              ============ : :
04597       // : :               |                         ================= : :
04598       // : + + + + + + + + X + + + + + + + + + + + + + + + + + + + + + + +  Rev.M/insertion time
04599       // : :               |                   ======================= : :
04600       // : :               |              ============================ : :
04601       // : :               |        ================================== : :
04602       // : ................|............................................ :
04603       // : ................|............................................ :
04604       // : :Increment 0    |                                           : :
04605       // : + + + + + + + + X + + + + + + + + + + + + + + + + + + + + + + +  Rev.Final
04606       // : :               |                     ===================== : :
04607       // : :               |                 ========================= : :
04608       // : ................|............................................ :
04609       // ..................|..............................................
04610       //                   |
04611       // ..................|............................
04612       // :Partition L      |                           :
04613       // : ................|.......................... :
04614       // : :Increment MAX  |                         : :
04615       // : + + + + + + + + X + + + + + + + + + + + + + +  Rev.Final
04616       // : :               |     =================== : :
04617       // : :               | ======================= : :
04618       // : :               X======================== : :
04619       // : :         =============================== : :
04620       // : ........................................... :
04621       // ...............................................
04622       //
04623       // This algorithm can be optimized in the future by caching all the relevant
04624       // information in the virtual memory of an application to avoid expensive
04625       // operations with peristsent store.
04626       //
04627       // NOT IMPLEMENTED: Will be implemented after the special failure test will
04628       //                  be done.
04629       //
04630       // == CALCULATING THE VISIBLE VALIDITY INTERVAL OF FOUND OBJECT ==
04631       //
04632       // The basic idea is that the visible validity interval is the shortest interval
04633       // of any of the following validity intervals met by the above described
04634       // algorithm:
04635       //
04636       // - the validity range of any partition explored
04637       // - the validity range of any failed as CdbStatus::NotFound attempts
04638       //   to find desired object at any MetaData object of partitions & increments explored
04639       // - the visibke validity for a successfully found object
04640       //
04641       // IMPORTANT: This algorithm needs thorough testing before deploying it.
04642 
04643         CdbBdbSCell pCell = pH->cell( );
04644 
04645         theBeginOfVisiblePeriod = pCell.beginValidity;
04646         theEndOfVisiblePeriod   = pCell.endValidity;
04647 
04648         assert( theBeginOfVisiblePeriod < theEndOfVisiblePeriod );
04649 
04650       // Begin the algorithm...
04651 
04652         bool isFirstPath = true;
04653 
04654         do {
04655 
04656 /**************************************************************************/
04657 if( CdbEnvironment::getDebugMode( ) != 0 )
04658     cout << debugStr << endl
04659          << "{" << endl
04660          << "    isFirstPath : " << ( isFirstPath ? "Yes" : "No" ) << endl
04661          << "}" << endl;
04662 /**************************************************************************/
04663 
04664             if( !isFirstPath ) {
04665 
04666               // Reload <partition>
04667               //
04668               // NOTE: We're going to check if the partion is closed. If so if its
04669               //       upper "insertion" time boundry is strictly above the condition
04670               //       creation time. Otherwise we just quit here since no MetaData
04671               //       for the recently created condition should exist in his partition.
04672 
04673                 if( CdbStatus::Success != findNextPartition( theValidityTime,
04674                                                              pH,
04675                                                              dbIdRange )) {
04676                     break;
04677                 }
04678 
04679 /***************************************************************/
04680 if( CdbEnvironment::getDebugMode( ) != 0 )
04681     cout << debugStr << endl
04682          << "{" << endl
04683          << "    Found next partition ID=" << pH->id( ) << endl
04684          << "}" << endl;
04685 /***************************************************************/
04686 
04687                 if( pH->isClosed( )) {
04688                     CdbBdbSCell pCell = pH->cell( );
04689                     if( pCell.endInsertion <= creationTime ) {
04690 
04691 /***************************************************************/
04692 if( CdbEnvironment::getDebugMode( ) != 0 )
04693     cout << debugStr << endl
04694          << "{" << endl
04695          << "    The just found partition is already 'closed' and its upper 'insertion'" << endl
04696          << "    time limit is older than the creation time of the current condition." << endl
04697          << "    So no object has been found." << endl
04698          << "        creationTime       : " << creationTime << endl
04699          << "        pCell.endInsertion : " << pCell.endInsertion << endl
04700          << "}" << endl;
04701 /***************************************************************/
04702 
04703                         result = CdbStatus::NotFound;
04704                         break;
04705                     }
04706                 }
04707 
04708               // ...and <increment>
04709               //
04710               // NOTE: We're going to recalculate the first and last increment numbers
04711               //       of the partition taking into accound the condition creation time.
04712 
04713                 {
04714                     d_UShort numIncrements = pH->numIncrements( );
04715                     assert( numIncrements > 0 );
04716 
04717 /************************************************************************************************/
04718 if( CdbEnvironment::getDebugMode( ) != 0 )
04719     cout << debugStr << endl
04720          << "{" << endl
04721          << "    num increments : " << numIncrements << " at partition ID=" << pH->id( ) << endl
04722          << "}" << endl;
04723 /************************************************************************************************/
04724 
04725                   // Find the first increment first
04726 
04727                     bool found  = false;
04728                     bool failed = true;
04729 
04730                     for( d_UShort i = 0; i < numIncrements; ++i ) {
04731 
04732                         CdbBdbSIncrement iVal;
04733                         if( CdbStatus::Success != pH->increment( i,
04734                                                                  iVal )) {
04735                             cout << errorStr << endl
04736                                  << "    Failed to find the increment #" << i << " at the partition #" << pH->id( ) << endl
04737                                  << "    The current federation may not be properly initialized/loaded." << endl;
04738                             break;
04739                         }
04740 
04741 /*********************************************************/
04742 if( CdbEnvironment::getDebugMode( ) != 0 )
04743     cout << debugStr << endl
04744          << "{" << endl
04745          << "    creation time : " << creationTime << endl
04746          << "    iVal.end      : " << iVal.end << endl
04747          << "}" << endl;
04748 /*********************************************************/
04749 
04750                         if( creationTime < iVal.end ) {
04751 
04752                             firstIncrement = i;
04753 
04754                             found  = true;
04755                             failed = false;
04756 
04757                             break;
04758                         }
04759                     }
04760                     if( failed ) {
04761                         break;
04762                     }
04763                     if( !found ) {
04764                         result = CdbStatus::NotFound;
04765                         break;
04766                     }
04767 
04768                   // The last increment is alway the biggest one since we're
04769                   // already below the revision/insertion time
04770 
04771                     lastIncrement = numIncrements - 1;
04772                 }
04773 
04774 /******************************************************************/
04775 if( CdbEnvironment::getDebugMode( ) != 0 )
04776     cout << debugStr << endl
04777          << "{" << endl
04778          << "    next firstIncrement : " << firstIncrement << endl
04779          << "         lastIncrement  : " << lastIncrement  << endl
04780          << "}" << endl;
04781 /******************************************************************/
04782 
04783               // Narrow down the visible interval to the partition limits
04784 
04785                 pCell = pH->cell( );
04786 
04787                 if( pCell.beginValidity > theBeginOfVisiblePeriod ) theBeginOfVisiblePeriod = pCell.beginValidity;
04788                 if( pCell.endValidity   < theEndOfVisiblePeriod   ) theEndOfVisiblePeriod   = pCell.endValidity;
04789 
04790                 assert( theBeginOfVisiblePeriod < theEndOfVisiblePeriod );
04791             }
04792 
04793             char partitionIdStr[12];
04794             sprintf( partitionIdStr, "%u", pH->id( ));
04795 
04796             bool isBreaking  = false;
04797 
04798             for( int i = lastIncrement; i >= firstIncrement; --i ) {
04799 
04800               // Now we've got everything to build the system name of the database file
04801               // containing the "topmost" meta-data container.
04802 
04803                 std::string databaseName( "con_cdb" );
04804                 {
04805                     char clusterIncrementStr[12];
04806                     sprintf( clusterIncrementStr, "%u", i );
04807 
04808                     databaseName = databaseName + std::string( "_p" ) + std::string( partitionIdStr ) +
04809                                                   std::string( "_c" ) + std::string( clusterIdStr ) +
04810                                                   std::string( "_i" ) + std::string( clusterIncrementStr ) +
04811                                                   std::string( "_"  ) + dbIdRange;
04812                 }
04813 
04814               // Find the container
04815 
04816                 BdbHandle(BdbContObj) mdContH;
04817                 if( CdbStatus::Success != CdbBdbSUtils::findContainer( mdContH,
04818                                                                        databaseName.c_str( ),
04819                                                                        mdContainerName.c_str( ),
04820                                                                        BdbcRead )) {
04821                     cout << errorStr << endl
04822                          << "    Failed to locate/open a persistent container with meta-data." << endl
04823                          << "    The database may not be properly initialized/loaded." << endl
04824                          << "        CONTAINER NAME:     \"" << mdContainerName.c_str( ) << "\"" << endl
04825                          << "        DATABASE FILE NAME: \"" << databaseName.c_str( ) << "\"" << endl;
04826 
04827                     isBreaking = true;
04828                     break;
04829                 }
04830 
04831               // Find out the meta-data object.
04832 
04833                 BdbHandle(CdbBdbSMetaDataP) mdH;
04834                 if( BdbcSuccess != mdH.lookupObj( mdContH,
04835                                                   "MetaData" )) {
04836                     cout << errorStr << endl
04837                          << "    Failed to locate the \"MetaData\" registry object in the container." << endl
04838                          << "    The database may not be properly initialized/loaded." << endl
04839                          << "        CONTAINER NAME:     \"" << mdContainerName.c_str( ) << "\"" << endl
04840                          << "        DATABASE FILE NAME: \"" << databaseName.c_str( ) << "\"" << endl;
04841 
04842                     isBreaking = true;
04843                     break;
04844                 }
04845                 assert( mdH->ooIsKindOf( ooTypeN( CdbBdbSMetaDataP )));
04846 
04847               // If this is not the very first step in the <partition> & <increment> loop
04848               // then we need to switch to the "final" revision of the just found metadata object.
04849               //
04850               // NOTE: The "final" revision of a metadata object is the one corresponding
04851               //       to its most recent "modification" time.
04852               //
04853               //       @see CdbBdbSMetaDataP::modified()
04854 
04855                 if( isFirstPath && ( i == lastIncrement )) {
04856                     ;
04857                 } else {
04858                     rId = mdH->modified( );
04859                 }
04860 
04861               // Try finding the persistent object in the meta-data object of
04862               // the current increment.
04863               //
04864               // NOTE: We do only one attemp for "useRevisions == false".
04865 
04866                 BdbTime beginOfVisiblePeriod( 0 );
04867                 BdbTime endOfVisiblePeriod  ( 0 );
04868 
04869                 if( useRevisions ) {
04870 
04871 /*************************************************************************************************/
04872 if( CdbEnvironment::getDebugMode( ) != 0 )
04873     cout << debugStr << endl
04874          << "{" << endl
04875          << "    Find by revision" << endl
04876          << "       next    curent increment number : " << i << endl
04877          << "               database                : \"" << databaseName.c_str( ) << "\"" << endl
04878          << "               rId                     : " << rId << endl
04879          << "               theValidityTime         : " << theValidityTime << endl
04880          << "}" << endl;
04881 /*************************************************************************************************/
04882 
04883                     result = mdH->findByRevision( rId,
04884                                                   theValidityTime,
04885                                                   theOriginalInterval,
04886                                                   beginOfVisiblePeriod,
04887                                                   endOfVisiblePeriod );
04888 
04889 /************************************************/
04890 if( CdbEnvironment::getDebugMode( ) != 0 )
04891     cout << debugStr << endl
04892          << "{" << endl
04893          << "    result : " << result << endl
04894          << "}" << endl;
04895 /************************************************/
04896 
04897                     if( beginOfVisiblePeriod > theBeginOfVisiblePeriod ) theBeginOfVisiblePeriod = beginOfVisiblePeriod;
04898                     if( endOfVisiblePeriod   < theEndOfVisiblePeriod   ) theEndOfVisiblePeriod   = endOfVisiblePeriod;
04899 
04900                     assert( theBeginOfVisiblePeriod < theEndOfVisiblePeriod );
04901 
04902                     if( CdbStatus::NotFound != result ) {
04903 
04904                       // The duration of this object begins with its insertion time up
04905                       // to +Infinity
04906 
04907                         theBeginOfDurationPeriod = theOriginalInterval.inserted;
04908                         theEndOfDurationPeriod   = BdbTime::plusInfinity;
04909 
04910                       // No matter if it's success or anything else except "NotFound".
04911 
04912                         isBreaking = true;
04913                         break;
04914                     }
04915 
04916                 } else {
04917 
04918                     result = mdH->findByInsertion( rId,
04919                                                    theValidityTime,
04920                                                    theOriginalInterval,
04921                                                    theBeginOfDurationPeriod,
04922                                                    theEndOfDurationPeriod );
04923 
04924                   // Special situation when an 'original' interval becomes the 'visible' one
04925 
04926                     theBeginOfVisiblePeriod = theOriginalInterval.begin;
04927                     theEndOfVisiblePeriod   = theOriginalInterval.end;
04928 
04929                   // No more attempts.
04930 
04931                     isBreaking = true;
04932                     break;
04933                 }
04934             }
04935             if( isBreaking ) break;
04936 
04937             isFirstPath = false;
04938 
04939         } while( true );    // Should be broken by the logic above.
04940 
04941     } while( false );
04942 
04943     return result;
04944 }
04945 
04946 CdbStatus
04947 CdbBdbSCondition::doFindObject( const CdbRevisionPolicy& thePolicy,
04948                                 const BdbTime&           theValidityTime,
04949                                 const BdbTime&           theInsertionTime,
04950                                 CdbBdbSOi&               theOriginalInterval, 
04951                                 BdbTime&                 theBeginOfVisiblePeriod,
04952                                 BdbTime&                 theEndOfVisiblePeriod,
04953                                 BdbTime&                 theBeginOfDurationPeriod,
04954                                 BdbTime&                 theEndOfDurationPeriod ) const
04955 {
04956     const char* debugStr = "CdbBdbSCondition::doFindObject()";
04957     const char* errorStr = "CdbBdbSCondition::doFindObject() -- ERROR";
04958 
04959     CdbStatus result = CdbStatus::Error;
04960 
04961     do {
04962 
04963       // Make sure this is a proper use of the algorithm. Just in case...
04964 
04965         assert( !_conditionH->isPartitionable( ));
04966 
04967       // Verify parameters and extract revision to begin with
04968 
04969         bool    useRevisions = thePolicy.useRevision( );
04970         BdbTime rId          = thePolicy.revisionId( );
04971 
04972         if( useRevisions ) {
04973 
04974             ;   // Nothing more to say
04975 
04976         } else if( BdbTime::plusInfinity == theInsertionTime ) {
04977 
04978             useRevisions = true;                    // Need this for the topmost revision
04979             rId          = BdbTime::plusInfinity;   // TOPMOST revision
04980 
04981         } else {
04982 
04983             rId = theInsertionTime;     // Still, no revisions
04984         }
04985 
04986       // Set up some initial "visible" validity period. This window will be corrected
04987       // by the condition lookup algorithm.
04988 
04989         theBeginOfVisiblePeriod = BdbTime::minusInfinity;
04990         theEndOfVisiblePeriod   = BdbTime::plusInfinity;
04991 
04992       // Get the condition creation time.
04993       //
04994       // IMPORTANT NOTE:
04995       //
04996       //     We would need this information to see which increments (MetaData)
04997       //     to include into the search,
04998       //     The reason why we're doing this check is that conditions
04999       //     may be created (put into a cluster) when the correspodning clusters
05000       //     already have more than 1 increment. Therefore some earlier increments
05001       //     may just not have any MetaData fore newer conditions.
05002 
05003         BdbTime creationTime = _conditionH->created( );
05004 
05005         if( rId < creationTime ) {
05006             cout << errorStr << endl
05007                  << "    Specified revision identifier / insertion time is older" << endl
05008                  << "    than the time when the condition was created." << endl
05009                  << "    The current view may be inproperly configured for the condition." << endl
05010                  << "        REVISION ID / INSERTION TIME : " << rId << endl
05011                  << "        CONDITION CREATION TIME      : " << creationTime << endl
05012                  << "        CONDITION NAME               : \"" << name( ) << "\"" << endl
05013                  << "        PARENT FOLDER NAME           : \"" << parent( )->name( ) << "\"" << endl
05014                  << "        VIEW NAME                    : \"" << parent( )->parentView( )->name( ) << "\"" << endl;
05015             break;
05016         }
05017 
05018       // Find out a the cluster the condition belongs to. Then find the increments
05019       // range for specified revision time.
05020 
05021         BdbRef(CdbBdbSClusterP) clusterRef = _conditionH->cluster( );
05022         assert( !BdbIsNull(clusterRef));
05023 
05024         d_UShort firstIncrement = 0;
05025         d_UShort lastIncrement  = 0;
05026         {
05027             BdbHandle(CdbBdbSSimpleClusterP) simpleClusterH;
05028             simpleClusterH = (const BdbRef(CdbBdbSSimpleClusterP)&) clusterRef;
05029 
05030             d_UShort numIncrements = simpleClusterH->numIncrements( );
05031             assert( numIncrements > 0 );
05032 
05033           // Find the very first increment including the creation time
05034           // of the condition.
05035 
05036             {
05037                 bool failed = true;
05038 
05039                 for( d_UShort i = 0; i < numIncrements; ++i ) {
05040 
05041                     CdbBdbSIncrement iVal;
05042                     if( CdbStatus::Success != simpleClusterH->increment( i,
05043                                                                          iVal )) {
05044                         break;
05045                     }
05046                     if( creationTime < iVal.end ) {
05047 
05048                         firstIncrement = i;
05049 
05050                         failed = false;
05051                         break;
05052                     }
05053                 }
05054                 if( failed ) {
05055                     cout << errorStr << endl
05056                          << "    Failed to find the smallest increment number for the condition." << endl
05057                          << "    The current federation may not be properly initialized/loaded." << endl;
05058                     break;
05059                 }
05060             }
05061 
05062           // Find the very last increment including specified revision
05063           //
05064           // NOTE: This search begins with the above found very first
05065           //       increment number.
05066 
05067             if( BdbTime::plusInfinity == rId ) {
05068                 lastIncrement = numIncrements - 1;
05069             } else {
05070 
05071                 bool failed = true;
05072 
05073                 for( d_UShort i = firstIncrement; i < numIncrements; ++i ) {
05074 
05075                     CdbBdbSIncrement iVal;
05076                     if( CdbStatus::Success != simpleClusterH->increment( i,
05077                                                                          iVal )) {
05078                         break;
05079                     }
05080                     if(( rId >= iVal.begin ) && ( rId <  iVal.end )) {
05081 
05082                         lastIncrement = i;
05083 
05084                         failed = false;
05085                         break;
05086                     }
05087                 }
05088                 if( failed ) {
05089                     cout << errorStr << endl
05090                          << "    Failed to find the biggest increment number for the condition." << endl
05091                          << "    The current federation may not be properly initialized/loaded." << endl;
05092                     break;
05093                 }
05094             }
05095 /***********************************************************/
05096 if( CdbEnvironment::getDebugMode( ) != 0 )
05097     cout << debugStr << endl
05098          << "{" << endl
05099          << "    creationTime   : " << creationTime   << endl
05100          << "    firstIncrement : " << firstIncrement << endl
05101          << "    lastIncrement  : " << lastIncrement  << endl
05102          << "    numIncrements  : " << numIncrements  << endl
05103          << "}" << endl;
05104 /***********************************************************/
05105         }
05106 
05107       // Get the identifier of the condition and the corresponding DBID range name.
05108 
05109         CdbBdbSId cId = _physicalAddress;
05110 
05111         std::string dbIdRange;
05112         {
05113           // Trivial optimization if the condition is in the local DBID range
05114 
05115             if( _localRegistryH->originId( ) == cId.origin ) {
05116 
05117                 if( CdbStatus::Success != CdbBdbSUtils::getLocalDbIdRange( dbIdRange )) {
05118                     cout << errorStr << endl
05119                          << "    Failed to obtain the local DBID range. The current federation" << endl
05120                          << "    may not be properly initialized/loaded." << endl;
05121                     break;
05122                 }
05123 
05124             } else {
05125 
05126                 BdbRef(CdbBdbSOriginCollectionP) oCollRef = _masterRegistryH->originCollection( );
05127                 assert( !BdbIsNull(oCollRef));
05128 
05129                 BdbRef(CdbBdbSOriginP) oRef;
05130                 if( CdbStatus::Success != oCollRef->find( cId.origin,
05131                                                           oRef )) {
05132                     cout << errorStr << endl
05133                          << "    Failed to obtain the origin from the corresponding collection." << endl
05134                          << "    The current federation may not be properly initialized/loaded." << endl;
05135                     break;
05136                 }
05137                 dbIdRange = oRef->dbidrange( ).head( );
05138             }
05139         }
05140 
05141       // Now we're ready to begin seraching for condition objects through
05142       // the sequence of increments. The search begins with the specified revision
05143       // of the found increment and it will proceed down to final revisions
05144       // of previous increments until either the desired interval is found or the smallest
05145       // avaialble for this condition increment of the stack is met.
05146       //
05147       // NOTE: This algorithm is used for both states of the "useRevisions" flag
05148       //       calculated above. The only difference is that in case of "!useRevisions"
05149       //       we're only given one chance to try the above calculated increment
05150       //       where the answer for specified insertionTime should be.
05151       //       See the details at the implementation of the CdbBdbSMetaDataP::findByInsertion()
05152       //       method.
05153       //
05154       // Here is a pseudo-graphical representation of this process:
05155       //
05156       //           <validity time>
05157       //                   |
05158       //   ................|....................................................
05159       //   :Increment N    |                                                   :
05160       //   :               |                              ==================== :
05161       //   :               |                         ========================= :
05162       //   + + + + + + + + X + + + + + + + + + + + + + + + + + + + + + + + + + +  Rev.M/insertion time
05163       //   :               |                   =============================== :
05164       //   :               |              ==================================== :
05165       //   :               |        ========================================== :
05166       //   ................|....................................................
05167       //                   |
05168       //   ................|....................................................
05169       //   :Increment N-1  |                                                   :
05170       //   + + + + + + + + X + + + + + + + + + + + + + + + + + + + + + + + + + +  Rev.Final
05171       //   :               |     ============================================= :
05172       //   :               | ================================================= :
05173       //   :             ==X================================================== :
05174       //   :         ========================================================= :
05175       //   .....................................................................
05176       //
05177       // This algorithm can be optimized in the future by caching all the relevant
05178       // information in the virtual memory of an application to avoid expensive
05179       // operations with peristsent store.
05180       //
05181       // NOT IMPLEMENTED: Will be implemented after the special failure test will
05182       //                  be done.
05183 
05184         char cIdStr[12];
05185         sprintf( cIdStr, "%u", cId.local );
05186 
05187         char clusterIdStr[12];
05188         sprintf( clusterIdStr, "%u", clusterRef->id( ));
05189 
05190         std::string mdContainerName = std::string( "MetaData." ) + std::string( cIdStr );
05191 
05192         for( int i = lastIncrement; i >= firstIncrement; --i ) {
05193 
05194           // Now we've got everything to build the system name of the database file
05195           // containing the "topmost" meta-data container.
05196 
05197             std::string databaseName( "con_cdb" );
05198             {
05199                 char clusterIncrementStr[12];
05200                 sprintf( clusterIncrementStr, "%u", i );
05201 
05202                 databaseName = databaseName + std::string( "_c" ) + std::string( clusterIdStr ) +
05203                                               std::string( "_i" ) + std::string( clusterIncrementStr ) +
05204                                               std::string( "_"  ) + dbIdRange;
05205             }
05206 
05207           // Find the container
05208 
05209             BdbHandle(BdbContObj) mdContH;
05210             if( CdbStatus::Success != CdbBdbSUtils::findContainer( mdContH,
05211                                                                    databaseName.c_str( ),
05212                                                                    mdContainerName.c_str( ),
05213                                                                    BdbcRead )) {
05214                 cout << errorStr << endl
05215                      << "    Failed to locate/open a persistent container with meta-data." << endl
05216                      << "    The database may not be properly initialized/loaded." << endl
05217                      << "        CONTAINER NAME:     \"" << mdContainerName.c_str( ) << "\"" << endl
05218                      << "        DATABASE FILE NAME: \"" << databaseName.c_str( ) << "\"" << endl;
05219                 break;
05220             }
05221 
05222           // Find out the meta-data object.
05223 
05224             BdbHandle(CdbBdbSMetaDataP) mdH;
05225             if( BdbcSuccess != mdH.lookupObj( mdContH,
05226                                               "MetaData" )) {
05227                 cout << errorStr << endl
05228                      << "    Failed to locate the \"MetaData\" registry object in the container." << endl
05229                      << "    The database may not be properly initialized/loaded." << endl
05230                      << "        CONTAINER NAME:     \"" << mdContainerName.c_str( ) << "\"" << endl
05231                      << "        DATABASE FILE NAME: \"" << databaseName.c_str( ) << "\"" << endl;
05232                 break;
05233             }
05234             assert( mdH->ooIsKindOf( ooTypeN( CdbBdbSMetaDataP )));
05235 
05236           // If this is not the very first step in the loop then we need to switch
05237           // to the "final" revision of the just found metadata object.
05238           //
05239           // NOTE: The "final" revision of a metadata object is the one corresponding
05240           //       to its most recent "modification" time.
05241           //
05242           //       @see CdbBdbSMetaDataP::modified()
05243 
05244             if( i != lastIncrement ) rId = mdH->modified( );
05245 
05246           // Try finding the persistent object in the meta-data object of
05247           // the current increment.
05248           //
05249           // NOTE: We do only one attemp for "useRevisions == false".
05250 
05251             if( useRevisions ) {
05252 
05253               // The explicit "visible" validity interval correction at this level of
05254               // the object mining algorithm may be needed when "diving" into metadata-s
05255               // beneath an upper one.
05256 
05257                 BdbTime beginOfVisiblePeriod = BdbTime( 0 );        // Just to have an initialized value
05258                 BdbTime endOfVisiblePeriod   = BdbTime( 0 );        // -//-
05259 
05260                 result = mdH->findByRevision( rId,
05261                                               theValidityTime,
05262                                               theOriginalInterval,
05263                                               beginOfVisiblePeriod,
05264                                               endOfVisiblePeriod );
05265 
05266                 if( beginOfVisiblePeriod > theBeginOfVisiblePeriod ) theBeginOfVisiblePeriod = beginOfVisiblePeriod;
05267                 if( endOfVisiblePeriod   < theEndOfVisiblePeriod   ) theEndOfVisiblePeriod   = endOfVisiblePeriod;
05268 
05269                 if( CdbStatus::NotFound != result ) {
05270 
05271                   // The duration of this object begins with its insertion time up
05272                   // to +Infinity
05273 
05274                     theBeginOfDurationPeriod = theOriginalInterval.inserted;
05275                     theEndOfDurationPeriod   = BdbTime::plusInfinity;
05276 
05277                   // No matter if it's success or anything else except "NotFound".
05278 
05279                     break;
05280                 }
05281 
05282             } else {
05283 
05284                 result = mdH->findByInsertion( rId,
05285                                                theValidityTime,
05286                                                theOriginalInterval,
05287                                                theBeginOfDurationPeriod,
05288                                                theEndOfDurationPeriod );
05289 
05290               // Special situation when an 'original' interval becomes the 'visible' one
05291 
05292                 theBeginOfVisiblePeriod = theOriginalInterval.begin;
05293                 theEndOfVisiblePeriod   = theOriginalInterval.end;
05294 
05295               // No more attempts.
05296 
05297                 break;
05298             }
05299         }
05300 
05301     } while( false );
05302 
05303     return result;
05304 }
05305 
05306 namespace {
05307 
05308 /////////////////////////////////
05309 // Function: Meta Data locator //
05310 /////////////////////////////////
05311 
05312 CdbStatus
05313 findMetaData( std::vector<BdbRef(CdbBdbSMetaDataP)>& theVectorOfRefs,
05314               const BdbHandle(CdbBdbSRegistryP)&     theMasterRegistryH,
05315               const BdbHandle(CdbBdbSRegistryP)&     theLocalRegistryH,
05316               const CdbBdbSId&                       theExtendedConditionId,
05317               d_UShort                               thePartitionId,
05318               bool                                   allIncrementsFlag,
05319               bool                                   recentIncrementFlag,
05320               d_UShort                               theIncrementNumber )
05321 {
05322     const char* errorStr = "CdbBdbSCondition::findMetaData() -- ERROR";
05323 
05324     CdbStatus result = CdbStatus::Error;
05325     do {
05326 
05327       // Make sure the procedure is called with correct set of parameters
05328 
05329         assert( ! BdbIsNull( theMasterRegistryH ));
05330         assert( ! BdbIsNull( theLocalRegistryH ));
05331         assert( theMasterRegistryH->isMaster( ));
05332 
05333         d_UShort originId    = theExtendedConditionId.origin;
05334         d_UShort conditionId = theExtendedConditionId.local;
05335 
05336       // Find out which registry may be required to accomplish our mission.
05337       //
05338       // NOTE: There is a little optimization.
05339 
05340         BdbHandle(CdbBdbSRegistryP) originRegistryH;
05341         {
05342             if( theLocalRegistryH->originId( ) == originId ) {
05343                 originRegistryH = theLocalRegistryH;
05344 
05345             } else if( theMasterRegistryH->originId( ) == originId ) {
05346                 originRegistryH = theMasterRegistryH;
05347 
05348             } else {
05349                 if( CdbStatus::Success != CdbBdbSRegistryP::findByOrigin( originRegistryH,
05350                                                                           originId )) {
05351                     cout << errorStr << endl
05352                          << "    Registry for specified origin ID #" << originId << " not found." << endl;
05353                     break;
05354                 }
05355             }
05356         }
05357 
05358       // Find specified condition in the collection.
05359 
05360         BdbRef(CdbBdbSConditionCollectionP) cCollRef = originRegistryH->conditionCollection( );
05361         assert( ! BdbIsNull(cCollRef));
05362 
05363         BdbRef(CdbBdbSConditionP) cRef;
05364         if( CdbStatus::Success != cCollRef->find( conditionId,
05365                                                   cRef )) {
05366             cout << errorStr << endl
05367                  << "    Condition with ID #" << conditionId << " not found" << endl
05368                  << "    at the collection with the origin ID #" << originId << endl;
05369             break;
05370         }
05371 
05372       // Get the characteristics of the condition
05373       // Currently there are two of them:
05374       //
05375       // - its creation time. We would need this information
05376       //   when looking for a subset of increments including or newer
05377       //   than that time. The reason is that conditions could be created
05378       //   later on when a number of increments for a cluster/partition may
05379       //   already exist.
05380       //
05381       // - its "partitionable" property. This will tell us which (of two)
05382       //   groups of clusters we should use. Partitionable conditions
05383       //   go into a separate set of clusters.
05384 
05385         BdbTime creationTime = cRef->created( );
05386 
05387         bool isPartitionableFlag = cRef->isPartitionable( );
05388 
05389         BdbRef(CdbBdbSPartitionP) pRef;
05390         if( isPartitionableFlag ) {
05391 
05392           // Use master to get general information about the partition
05393 
05394             BdbRef(CdbBdbSPartitionsLayoutP) pLayoutRef = theMasterRegistryH->partitionsLayout( );
05395             assert( ! BdbIsNull(pLayoutRef));
05396 
05397             if( CdbStatus::Success != pLayoutRef->find( thePartitionId,
05398                                                         pRef )) {
05399                 cout << errorStr << endl
05400                      << "    Partition with ID #" << thePartitionId << " not found" << endl
05401                      << "    at the master collection." << endl;
05402                 break;
05403             }
05404 
05405           // Check if this partition is available
05406 
05407             if( theLocalRegistryH->originId( ) == pRef->originId( )) {
05408 
05409               // Switch to the actual partition object if the current database
05410               // is not the master one and if the partition belongs to the current database.
05411               // Then the current (local) database is the ultimate source of information.
05412 
05413                 if( theLocalRegistryH->originId( ) != theMasterRegistryH->originId( )) {
05414 
05415                     BdbRef(CdbBdbSPartitionsLayoutP) localPartitionsLayoutRef = theLocalRegistryH->partitionsLayout( );
05416                     assert( ! BdbIsNull(localPartitionsLayoutRef));
05417 
05418                     if( CdbStatus::Success != localPartitionsLayoutRef->find( thePartitionId,
05419                                                                               pRef )) {
05420                         cout << errorStr << endl
05421                              << "    Partition with ID #" << thePartitionId << " not found" << endl
05422                              << "    at the local (non-master) collection." << endl;
05423                         break;
05424                     }
05425                 }
05426             }
05427             if( !pRef->isInstantiated( )) {
05428                 cout << errorStr << endl
05429                      << "    Partition with ID #" << thePartitionId << " is not instantiated." << endl
05430                      << "    No MetaData containers should exist for this condition yet." << endl;
05431                 break;
05432             }
05433         }
05434 
05435       // Get the DBID range for the condition/partition
05436 
05437         std::string dbIdRange;
05438         {
05439           // For partitionable conditions we should use the partition's origin
05440           // rather than the one of the condition itself in order to get the DBID
05441           // range name of database files where the MetaData objects are located.
05442 
05443             d_UShort oId = originId;
05444             if( isPartitionableFlag ) {
05445                 oId = pRef->originId( );
05446             }
05447 
05448           // Get the origin
05449 
05450             BdbRef(CdbBdbSOriginCollectionP) oCollRef = theMasterRegistryH->originCollection( );
05451             assert( ! BdbIsNull(oCollRef));
05452 
05453             BdbRef(CdbBdbSOriginP) oRef;
05454             if( CdbStatus::Success != oCollRef->find( oId,
05455                                                       oRef )) {
05456                 cout << errorStr << endl
05457                      << "    Origin with ID #" << oId << " not found." << endl;
05458                 break;
05459             }
05460 
05461           // Fetch the range's name
05462 
05463             dbIdRange = std::string( oRef->dbidrange( ).head( ));
05464         }
05465 
05466       // Get the range of increments for the condition/partition
05467       //
05468       // NOTE: We're using the condition creation time to determine the first
05469       //       increment inclusing this time. We do it because a condition may
05470       //       be created when a number of increments already exist in the cluster.
05471 
05472         BdbRef(CdbBdbSClusterP) clusterRef = cRef->cluster( );
05473         assert( ! BdbIsNull(clusterRef));
05474 
05475         d_UShort firstIncrement = 0;
05476         d_UShort lastIncrement  = 0;
05477         {
05478             bool failed = false;
05479 
05480             d_UShort numIncrements = 0;
05481 
05482             if( isPartitionableFlag ) {
05483 
05484                 numIncrements = pRef->numIncrements( );
05485                 for( d_UShort i = 0; i < numIncrements; ++i ) {
05486 
05487                     CdbBdbSIncrement iVal;
05488                     if( CdbStatus::Success != pRef->increment( i,
05489                                                                iVal )) {
05490                         failed = true;
05491                         break;
05492                     }
05493                     if( creationTime < iVal.end ) {
05494                         firstIncrement = i;
05495                         break;
05496                     }
05497                 }
05498                 if( failed ) break;
05499 
05500             } else {
05501 
05502                 BdbHandle(CdbBdbSSimpleClusterP) simpleClusterH;
05503                 simpleClusterH = (const BdbRef(CdbBdbSSimpleClusterP)&) clusterRef;
05504 
05505                 numIncrements = simpleClusterH->numIncrements( );
05506                 for( d_UShort i = 0; i < numIncrements; ++i ) {
05507 
05508                     CdbBdbSIncrement iVal;
05509                     if( CdbStatus::Success != simpleClusterH->increment( i,
05510                                                                          iVal )) {
05511                         failed = true;
05512                         break;
05513                     }
05514                     if( creationTime < iVal.end ) {
05515                         firstIncrement = i;
05516                         break;
05517                     }
05518                 }
05519                 if( failed ) break;
05520 
05521             }
05522             if( numIncrements < 1 ) {
05523                 assert( 0 );
05524                 break;
05525             }
05526             lastIncrement = numIncrements - 1;
05527         }
05528 
05529         d_UShort clusterId = clusterRef->id( );
05530 
05531       // Find metadata for specified increment(s)
05532 
05533         theVectorOfRefs.clear( );
05534 
05535         BdbRef(CdbBdbSMetaDataP) mdRef;
05536 
05537         if( allIncrementsFlag ) {
05538 
05539             bool failed = false;
05540             {
05541                 for( d_UShort i = firstIncrement; i <= lastIncrement; ++i ) {
05542 
05543                     if( CdbStatus::Success != CdbBdbSUtils::findMetaData( mdRef,
05544                                                                           conditionId,
05545                                                                           isPartitionableFlag,
05546                                                                           thePartitionId,
05547                                                                           clusterId,
05548                                                                           i,
05549                                                                           dbIdRange )) {
05550 
05551                         cout << errorStr << endl
05552                              << "    Failed to find a MetaData object for increment #" << i << endl;
05553 
05554                         failed = true;
05555                         break;
05556                     }
05557                     theVectorOfRefs.push_back( mdRef );
05558                 }
05559             }
05560             if( failed ) break;
05561 
05562         } else {
05563 
05564             if( recentIncrementFlag ) {
05565 
05566                 if( CdbStatus::Success != CdbBdbSUtils::findMetaData( mdRef,
05567                                                                       conditionId,
05568                                                                       isPartitionableFlag,
05569                                                                       thePartitionId,
05570                                                                       clusterId,
05571                                                                       lastIncrement,
05572                                                                       dbIdRange )) {
05573 
05574                     cout << errorStr << endl
05575                          << "    Failed to find a MetaData object for recent increment #" << lastIncrement << endl;
05576                     break;
05577                 }
05578                 theVectorOfRefs.push_back( mdRef );
05579 
05580             } else {
05581 
05582                 if( theIncrementNumber > lastIncrement ) {
05583                     cout << errorStr << endl
05584                          << "    Passed increment number is not valid." << endl
05585                          << "        PASSED NUMBER:       " << theIncrementNumber << endl
05586                          << "        MAX.POSSIBLE NUMBER: " << lastIncrement << endl;
05587                     break;
05588                 }
05589                 if( CdbStatus::Success != CdbBdbSUtils::findMetaData( mdRef,
05590                                                                       conditionId,
05591                                                                       isPartitionableFlag,
05592                                                                       thePartitionId,
05593                                                                       clusterId,
05594                                                                       theIncrementNumber,
05595                                                                       dbIdRange )) {
05596                     cout << errorStr << endl
05597                          << "    Failed to find a MetaData object for specified increment #" << theIncrementNumber << endl;
05598                     break;
05599                 }
05600                 theVectorOfRefs.push_back( mdRef );
05601             }
05602         }
05603 
05604       // Done
05605 
05606         result = CdbStatus::Success;
05607 
05608     } while( false );
05609 
05610     return result;
05611 }
05612 
05613 std::string
05614 time2string( const BdbTime& theTime )
05615 {
05616     char buf[80];
05617     if       ( BdbTime::minusInfinity == theTime ) {
05618         sprintf( buf, "      -Infinity      " );
05619     } else if( BdbTime::plusInfinity  == theTime ) {
05620         sprintf( buf, "      +Infinity      " );
05621     } else {
05622         sprintf( buf, "%10.10u.%10.10u", theTime.getGmtSec( ), theTime.getGmtNsec( ));
05623     }
05624     return std::string( buf );
05625 }
05626 
05627 
05628 //////////////////////////////////////////////
05629 // Function: Build Composite Condition Name //
05630 //////////////////////////////////////////////
05631 
05632 CdbStatus
05633 buildCompositeConditionName( CdbCompositeName&                  theCompositeName,
05634                              const CdbBdbSId&                   theId,
05635                              const BdbHandle(CdbBdbSRegistryP)& theMasterRegistryH )
05636 {
05637     const char* errorStr = "CdbBdbSCondition::anonymous::buildCompositeConditionName() -- ERROR";
05638 
05639     assert( !BdbIsNull(theMasterRegistryH));
05640     assert( theMasterRegistryH->isMaster( ));
05641 
05642     CdbStatus result = CdbStatus::Error;
05643 
05644     do {
05645 
05646       // Get to the origin first
05647 
05648         BdbRef(CdbBdbSOriginP) originRef;
05649         {
05650           // Get to the collection of origins
05651 
05652             BdbRef(CdbBdbSOriginCollectionP) originCollectionRef;
05653             originCollectionRef = theMasterRegistryH->originCollection( );
05654             assert( !BdbIsNull(originCollectionRef));
05655 
05656           // Find the origin matchin specified identifier
05657 
05658             if( CdbStatus::Success != originCollectionRef->find( theId.origin, originRef )) {
05659                 cout << errorStr << endl
05660                      << "    Failed to obtain a persistent object describing the 'origin' for" << endl
05661                      << "    the following ID=" << theId.origin << endl;
05662                 break;
05663             }
05664             assert( !BdbIsNull(originRef));
05665         }
05666 
05667       // Find the physical condition by its identifier
05668 
05669         BdbRef(CdbBdbSConditionP) conditionRef;
05670         {
05671 
05672           // Get to a collection of conditions of this origin. This collection can be
05673           // be located through the registry corresponding to specified origin.
05674           //
05675           // NOTE: A little optimization if the above found origin corresponds to the MASTER one.
05676 
05677             BdbRef(CdbBdbSConditionCollectionP) conditionCollectionRef;
05678             if( theId.origin == theMasterRegistryH->originId( )) {
05679                 conditionCollectionRef = theMasterRegistryH->conditionCollection( );
05680             } else {
05681 
05682               // Get to the registry
05683 
05684                 BdbHandle(CdbBdbSRegistryP) registryH;
05685                 if( CdbStatus::Success != CdbBdbSRegistryP::findByOrigin( registryH, theId.origin )) {
05686                     cout << errorStr << endl
05687                          << "    Failed to obtain a persistent object describing the 'registry' for" << endl
05688                          << "    the following ID=" << theId.origin << endl;
05689                     break;
05690                 }
05691                 assert( !BdbIsNull(registryH));
05692 
05693               // Get to the collection of conditions
05694 
05695                 conditionCollectionRef = registryH->conditionCollection( );                
05696             }
05697             assert( !BdbIsNull(conditionCollectionRef));
05698 
05699           // Find the physical condition matching the specified one by its identifier
05700 
05701             if( CdbStatus::Success != conditionCollectionRef->find( theId.local, conditionRef )) {
05702                 cout << errorStr << endl
05703                      << "    Failed to obtain a persistent object describing the 'physical' condition for" << endl
05704                      << "    the following ID=" << theId.local << " in the 'origin' with ID=" << theId.origin << endl;
05705                 break;
05706             }
05707             assert( !BdbIsNull(conditionRef));
05708         }
05709 
05710       // Done.
05711 
05712         theCompositeName = CdbCompositeName( originRef->name( ).head( ),
05713                                              conditionRef->name( ).head( ));
05714 
05715         result = CdbStatus::Success;
05716 
05717     } while( false );
05718 
05719     return result;
05720 }
05721 
05722 
05723 /////////////////////////////////////////////////////
05724 // Function: Calculate Condition Modification Time //
05725 /////////////////////////////////////////////////////
05726 
05727 CdbStatus
05728 calculateConditionModificationTime( BdbTime&                                    theModificationTime,
05729                                     const CdbBdbSId&                            thePhysicalAddress,
05730                                     const BdbHandle(CdbBdbSConditionAtFolderP)& theConditionAtFolderH,
05731                                     const BdbHandle(CdbBdbSRegistryP)&          theMasterRegistryH,
05732                                     const BdbHandle(CdbBdbSRegistryP)&          theLocalRegistryH )
05733 {
05734     const char* errorStr = "CdbBdbSCondition::anonymous::calculateConditionModificationTime() -- ERROR";
05735 
05736     assert( !BdbIsNull(theMasterRegistryH));
05737     assert( theMasterRegistryH->isMaster( ));
05738     assert( !BdbIsNull(theLocalRegistryH));
05739 
05740   /*
05741    * =================
05742    * EXECUTION PATH I: 'physical address' conditions only
05743    * =================
05744    *
05745    * This path is not currently implemented. A complicated algorithm to iterate
05746    * over a validity timeline of the "topmost" partitions would be needed for
05747    * PARTITIONABLE conditions. Things are trivial for REGULAR conditions though.
05748    * However to avoid an incomplete implementation of this part of the code let's just
05749    * postpone it as a whole.
05750    *
05751    * AN IDEA: Having a super-iterator composed of elementary iterators for individual
05752    *          "topmost" partitions would be a good idea. That would require to extend
05753    *          the API of P-Layout to deliver an iterator of "topmost" partitions. The
05754    *          one currently available does not respect non-instantiated partitions.
05755    */
05756 
05757     if( BdbIsNull(theConditionAtFolderH)) {
05758         return CdbStatus::NotImplemented;
05759     }
05760 
05761   /*
05762    * ==================
05763    * EXECUTION PATH II: 'view/folder/config' conditions only
05764    * ==================
05765    */
05766 
05767     BdbTime modificationTime = theModificationTime; // This value will be modified and returned
05768                                                     // in case of success.
05769 
05770     CdbStatus result = CdbStatus::Error;
05771 
05772     do {
05773 
05774       // Use the specific configuration of the condition.
05775 
05776         BdbRef(CdbBdbSConfigCollectionP) configCollRef = theConditionAtFolderH->config( );
05777         if( BdbIsNull(configCollRef)) {
05778             break;
05779         }
05780 
05781       // Iterate through the configuration intervals to determine the result.
05782 
05783         CdbBdbSConfigCollectionP::IteratorOfIntervals itr = configCollRef->iterator( );
05784         while( itr.next( )) {
05785 
05786             CdbBdbSConfigInterval configInterval = itr.value( );
05787             CdbBdbSConfigElement  configElement  = configInterval.value;
05788 
05789           // Skeep the found element if it tells us that the corresponding range of the validity
05790           // timeline is not accessible for the current application.
05791 
05792             if( !configElement.accessIsAllowed( )) continue;
05793 
05794           // If we're supposed to use revisions and if this is not the 'topmost' one
05795           // then then we use that revision ID as the modification time.
05796 
05797             BdbTime cModificationTime = BdbTime::minusInfinity;
05798             if( configElement.useRevision && ( BdbTime::plusInfinity != configElement.revision )) {
05799                 cModificationTime = configElement.revision;
05800             } else {
05801 
05802               // Otherwise we use the modification time of the most recent Meta-Data object.
05803 
05804                 std::vector<BdbRef(CdbBdbSMetaDataP)> mdRefs;
05805 
05806                 bool allIncrementsFlag   = false;
05807                 bool recentIncrementFlag = true;
05808 
05809                 if( CdbStatus::Success != findMetaData( mdRefs,
05810                                                         theMasterRegistryH,
05811                                                         theLocalRegistryH,
05812                                                         thePhysicalAddress,
05813                                                         configElement.partition,
05814                                                         allIncrementsFlag,
05815                                                         recentIncrementFlag )) {
05816                     cout << errorStr << endl
05817                          << "    Failed to find the most recent MetaData objects for the condition known as \"" << theConditionAtFolderH->name( ).head( ) << "\"" << endl
05818                          << "    at the current view." << endl
05819                          << "    The database may not be properly initialized/loaded." << endl;
05820 
05821                     break;
05822                 }
05823                 assert( 1 == mdRefs.size( ));
05824 
05825                 cModificationTime = mdRefs[0]->modified( );
05826             }
05827             assert( BdbTime::minusInfinity != cModificationTime );
05828             assert( BdbTime::plusInfinity  != cModificationTime );
05829 
05830           // Check if the found time is newer than the one we have now.
05831 
05832             if( cModificationTime > modificationTime ) modificationTime = cModificationTime;
05833         }
05834 
05835       // Done.
05836 
05837         theModificationTime = modificationTime;
05838 
05839         result = CdbStatus::Success;
05840 
05841     } while( false );
05842 
05843     return result;
05844 }
05845 
05846 };
05847 
05848 /////////////////
05849 // End Of File //
05850 /////////////////

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