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

CdbRooRoCondition.cc

Go to the documentation of this file.
00001 // File and Version Information:
00002 //      $Id: CdbRooRoCondition.cc,v 1.7 2005/06/23 23:44:43 gapon Exp $
00003 #include "BaBar/BaBar.hh"
00004 
00005 /// The implementation of the CdbRooRoCondition class.
00006 /**
00007   * @see CdbRooRoCondition
00008   */
00009 
00010 #include "CdbRooReadonly/CdbRooRoCondition.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 "CdbRooReadonly/CdbRooRoFolderR.hh"
00026 #include "CdbRooReadonly/CdbRooRoViewR.hh"
00027 #include "CdbRooReadonly/CdbRooRoView.hh"
00028 #include "CdbRooReadonly/CdbRooRoConditionAtFolderR.hh"
00029 #include "CdbRooReadonly/CdbRooRoPartitionR.hh"
00030 #include "CdbRooReadonly/CdbRooRoPartitionsLayoutR.hh"
00031 #include "CdbRooReadonly/CdbRooRoMetaDataR.hh"
00032 #include "CdbRooReadonly/CdbRooRoConfigCollectionR.hh"
00033 #include "CdbRooReadonly/CdbRooRoOriginR.hh"
00034 #include "CdbRooReadonly/CdbRooRoOriginCollectionR.hh"
00035 #include "CdbRooReadonly/CdbRooRoRevision.hh"
00036 #include "CdbRooReadonly/CdbRooRoOiCollectionR.hh"
00037 #include "CdbRooReadonly/CdbRooRoFileUtils.hh"
00038 #include "CdbRooReadonly/CdbRooRoOiR.hh"
00039 #include "CdbRooReadonly/CdbRooRoSimpleConfigIterator.hh"
00040 #include "CdbRooReadonly/CdbRooRoCi.hh"
00041 #include "CdbRooReadonly/CdbRooRoObject.hh"
00042 #include "CdbRooReadonly/CdbRooRoRClusterR.hh"
00043 #include "CdbRooReadonly/CdbRooRoRClusterCollectionR.hh"
00044 #include "CdbRooReadonly/CdbRooRoConditionCollectionR.hh"
00045 
00046 #include "BdbTime/BdbTime.hh"
00047 
00048 #include <stdio.h>
00049 #include <iostream>
00050 
00051 #include <vector>
00052 #include <stack>
00053 using std::cout;
00054 using std::cerr;
00055 using std::endl;
00056 using std::ends;
00057 
00058 namespace {
00059 
00060   /// Calculate the full path for the condition
00061   /**
00062     * The path would include all preceeding folders and the specified condition
00063     * itself.
00064     *
00065     * The method will return an empty path containing "" in case of any problem met
00066     * while calculating the path.
00067     *
00068     * NOTE: For conditions found via their 'physical' names or addresses the nethod
00069     *       will return that empty path since their (CdbCondition) API objects
00070     *       do not have any parent folders or views.
00071     * 
00072     * @see class CdbCondition
00073     */ 
00074     std::string fullPathName( const CdbRooRoCondition* theConditionPtr );
00075 
00076   /// Find MetaData object(s) for specified condition
00077   /**
00078     * DESIGN NOTE:
00079     *
00080     *   This operation is put out of the current class's context to make it usable by other classes
00081     *   defined in the scope of the current implementation file.
00082     *
00083     * The contence of the output vector varies depending on the values of flags
00084     * passed to the function.
00085     *
00086     *     - if "allIncrementsFlag" is set (true) then metadata objects will be
00087     *       found for all increments. Then the increments numbers can be used to
00088     *       as the vector's indexes to fet to tyhe corresponding meta-data.
00089     *       The subsequent parameters are ignored in this case.
00090     *
00091     *     - else if "recentIncrementFlag" is set then the output vector will only
00092     *       containe the metadata reference for the most recently created increment.
00093     *
00094     *     - else the specified increment number will be used to locate the corresponding
00095     *       metadata object.
00096     *
00097     * The partition identifier is only used if the corresponding condition
00098     * is the partitionable.
00099     *
00100     * IMPORTANT NOTE: The procedure will use the condition's creation time
00101     *                 when looking for a subset of increments including or newer
00102     *                 than that time. The reason is that conditions could be created
00103     *                 later on when a number of increments for a cluster/partition may
00104     *                 already exist.
00105     */
00106     CdbStatus findMetaData( std::vector< CdbCPtr< CdbRooRoMetaDataR > >& theVectorOfPtrs,
00107                             const CdbCPtr< CdbRooRoRegistry >&           theMasterRegistryPtr,
00108                             const CdbCPtr< CdbRooRoRegistry >&           theLocalRegistryPtr,
00109                             const CdbId&                                 theExtendedConditionId,
00110                             UShort_t                                     thePartitionId,
00111                             bool                                         allIncrementsFlag   = true,
00112                             bool                                         recentIncrementFlag = true,
00113                             UShort_t                                     theIncrementNumber  = 0 );
00114 
00115   /// An implementation class for the iterator of revision identifiers
00116   /**
00117     * @see class CdbItr
00118     */
00119     class RevisionIdIterator : public CdbItr<BdbTime>::InterfaceType {
00120 
00121     private:
00122 
00123         RevisionIdIterator( );
00124 
00125         RevisionIdIterator& operator=( const RevisionIdIterator& theItr );
00126 
00127     protected:
00128 
00129         RevisionIdIterator( const RevisionIdIterator& theItr ) :
00130             _metaDataPtrs       (theItr._metaDataPtrs),
00131             _isValid            (theItr._isValid),
00132             _hasEverBeenAdvanced(theItr._hasEverBeenAdvanced),
00133             _value              (theItr._value),
00134             _itr                (theItr._itr),
00135             _revItr             (theItr._revItr)
00136         { }
00137 
00138     public:
00139 
00140 
00141         RevisionIdIterator( const std::vector< CdbCPtr< CdbRooRoMetaDataR > >& theMetaDataPtrs ) :
00142             _metaDataPtrs       (theMetaDataPtrs),
00143             _isValid            (false),
00144             _hasEverBeenAdvanced(false)
00145         { }
00146 
00147         virtual ~RevisionIdIterator( )
00148         { }
00149 
00150         virtual CdbStatus reset( )
00151         {
00152             _isValid             = false;
00153             _hasEverBeenAdvanced = false;
00154 
00155             return CdbStatus::Success;
00156         }
00157 
00158         bool tryNext( )
00159         {
00160             if( _revItr.next( )) {
00161                 return true;
00162             } else {
00163 
00164               // Switch to the next metaData (if any)
00165 
00166                 ++_itr;
00167                 if( _metaDataPtrs.end( ) != _itr ) {
00168 
00169                     CdbCPtr< CdbRooRoMetaDataR > mdPtr = (*_itr);
00170                     if( CdbStatus::Success != mdPtr->revisionIdIterator( _revItr )) {
00171                         return false;
00172                     }
00173                     return tryNext( );
00174                 }
00175             }
00176             return false;
00177         }
00178 
00179         virtual bool next( )
00180         {
00181             if( _hasEverBeenAdvanced && !_isValid ) {
00182                 return _isValid;        // stay in "past the last element" state
00183             }
00184 
00185             if( !_hasEverBeenAdvanced ) {
00186                 _hasEverBeenAdvanced = true;
00187 
00188                 _itr = _metaDataPtrs.begin( );
00189                 if( _metaDataPtrs.end( ) == _itr ) {
00190                     _isValid = false;
00191                     return _isValid;    // go into the "past the last element" state      
00192                 }
00193                 CdbCPtr< CdbRooRoMetaDataR > mdPtr = (*_itr);
00194 
00195                 if( CdbStatus::Success != mdPtr->revisionIdIterator( _revItr )) {
00196                     _isValid = false;
00197                     return _isValid;    // go into the "past the last element" state      
00198                 }
00199 
00200               // At this point _itr points onto the very first MetaData in the vector
00201               // and _revItr is just before the very first revision of this metadata.
00202             }
00203 
00204           // At this point _itr points onto some MetaDat ain the vector
00205           // and _revItr is before the next element we're intrested in (if still there
00206           // is some in this MetaData).
00207 
00208             if( tryNext( )) {
00209                 _value = _revItr.value( );
00210                 _isValid = true;
00211             } else {
00212                 _isValid = false;   // go into the "past the last element" state
00213             }
00214             return _isValid;
00215         }
00216 
00217         virtual ValueType value( )
00218         {
00219             if( _isValid ) {
00220                 return _value;
00221             }
00222             return BdbTime::minusInfinity;
00223         }
00224 
00225         virtual bool isValid( )
00226         {
00227             return _isValid;
00228         }
00229 
00230         virtual InterfaceType* clone( ) const
00231         {
00232             return new RevisionIdIterator( *this );
00233         }
00234 
00235     private:
00236 
00237         std::vector< CdbCPtr< CdbRooRoMetaDataR > > _metaDataPtrs;
00238 
00239         bool _isValid;
00240         bool _hasEverBeenAdvanced;
00241 
00242         BdbTime _value;
00243 
00244       // A pointer onto the current element at the above defined vector of
00245       // metadata references.
00246 
00247         std::vector< CdbCPtr< CdbRooRoMetaDataR > >::const_iterator _itr;
00248 
00249       // The current iterator for the currently indexed metadata reference.
00250 
00251         CdbItr<BdbTime> _revItr;
00252     };
00253 
00254   /// An implementation class for the iterator of revision names
00255   /**
00256     * @see class CdbItr
00257     */
00258     class RevisionNameIterator : public CdbItr<const char*>::InterfaceType {
00259 
00260     private:
00261 
00262         RevisionNameIterator( );
00263 
00264         RevisionNameIterator& operator=( const RevisionNameIterator& theItr );
00265 
00266     protected:
00267 
00268         RevisionNameIterator( const RevisionNameIterator& theItr ) :
00269             _metaDataPtrs       (theItr._metaDataPtrs),
00270             _isValid            (theItr._isValid),
00271             _hasEverBeenAdvanced(theItr._hasEverBeenAdvanced),
00272             _value              (theItr._value),
00273             _itr                (theItr._itr),
00274             _revItr             (theItr._revItr)
00275         { }
00276 
00277     public:
00278 
00279         RevisionNameIterator( const std::vector< CdbCPtr< CdbRooRoMetaDataR > >& theMetaDataPtrs ) :
00280             _metaDataPtrs       (theMetaDataPtrs),
00281             _isValid            (false),
00282             _hasEverBeenAdvanced(false),
00283             _value("")
00284         { }
00285 
00286         virtual ~RevisionNameIterator( )
00287         { }
00288 
00289         virtual CdbStatus reset( )
00290         {
00291             _isValid             = false;
00292             _hasEverBeenAdvanced = false;
00293 
00294             return CdbStatus::Success;
00295         }
00296 
00297         bool tryNext( )
00298         {
00299             if( _revItr.next( )) {
00300                 return true;
00301             } else {
00302 
00303               // Switch to the next metaData (if any)
00304 
00305                 ++_itr;
00306                 if( _metaDataPtrs.end( ) != _itr ) {
00307 
00308                     CdbCPtr< CdbRooRoMetaDataR > mdPtr = (*_itr);
00309                     if( CdbStatus::Success != mdPtr->revisionNameIterator( _revItr )) {
00310                         return false;
00311                     }
00312                     return tryNext( );
00313                 }
00314             }
00315             return false;
00316         }
00317 
00318         virtual bool next( )
00319         {
00320             if( _hasEverBeenAdvanced && !_isValid ) {
00321                 return _isValid;        // stay in "past the last element" state
00322             }
00323 
00324             if( !_hasEverBeenAdvanced ) {
00325                 _hasEverBeenAdvanced = true;
00326 
00327                 _itr = _metaDataPtrs.begin( );
00328                 if( _metaDataPtrs.end( ) == _itr ) {
00329                     _isValid = false;
00330                     return _isValid;    // go into the "past the last element" state      
00331                 }
00332                 CdbCPtr< CdbRooRoMetaDataR > mdPtr = (*_itr);
00333 
00334                 if( CdbStatus::Success != mdPtr->revisionNameIterator( _revItr )) {
00335                     _isValid = false;
00336                     return _isValid;    // go into the "past the last element" state      
00337                 }
00338 
00339               // At this point _itr points onto the very first MetaData in the vector
00340               // and _revItr is just before the very first revision of this metadata.
00341             }
00342 
00343           // At this point _itr points onto some MetaDat ain the vector
00344           // and _revItr is before the next element we're intrested in (if still there
00345           // is some in this MetaData).
00346 
00347             if( tryNext( )) {
00348                 _value = _revItr.value( );
00349                 _isValid = true;
00350             } else {
00351                 _isValid = false;   // go into the "past the last element" state
00352             }
00353             return _isValid;
00354         }
00355 
00356         virtual ValueType value( )
00357         {
00358             if( _isValid ) {
00359                 return _value.c_str( );
00360             }
00361             return 0;
00362         }
00363 
00364         virtual bool isValid( )
00365         {
00366             return _isValid;
00367         }
00368 
00369         virtual InterfaceType* clone( ) const
00370         {
00371             return new RevisionNameIterator( *this );
00372         }
00373 
00374     private:
00375 
00376         std::vector< CdbCPtr< CdbRooRoMetaDataR > > _metaDataPtrs;
00377 
00378         bool _isValid;
00379         bool _hasEverBeenAdvanced;
00380 
00381         std::string _value;
00382 
00383       // A pointer onto the current element at the above defined vector of
00384       // metadata references.
00385 
00386         std::vector< CdbCPtr< CdbRooRoMetaDataR > >::const_iterator _itr;
00387 
00388       // The current iterator for the currently indexed metadata reference.
00389 
00390         CdbItr<const char*> _revItr;
00391     };
00392 
00393   ////////////////////////////////////////
00394   // Class: PartitionableObjectIterator //
00395   ////////////////////////////////////////
00396 
00397     class PartitionableObjectIterator : public CdbObjectItr::InterfaceType {
00398 
00399     private:
00400 
00401       // These forms of object construction are not implemented
00402 
00403         PartitionableObjectIterator( );
00404 
00405         PartitionableObjectIterator& operator=( const PartitionableObjectIterator& theItr );
00406 
00407     protected:
00408 
00409       // This form of the constructor is only used by the clone operation
00410 
00411         PartitionableObjectIterator( const PartitionableObjectIterator& theItr );
00412 
00413     public:
00414 
00415       /// Normal constructor
00416       /**
00417         * If the configuration collection parameter is pointing onto a zero object
00418         * then the revision policy must be used.
00419         */
00420         PartitionableObjectIterator( const CdbConditionPtr&             theParentPtr,
00421                                      const BdbTime&                     theBegin,
00422                                      const BdbTime&                     theEnd,
00423                                      const CdbItr< CdbConfigElement >&  theConfigItr,
00424                                      const CdbCPtr< CdbRooRoRegistry >& theMasterRegistryPtr,
00425                                      const CdbCPtr< CdbRooRoRegistry >& theLocalRegistryPtr,
00426                                      const CdbId&                       theExtendedConditionId,
00427                                      const BdbTime&                     theConditionCreationTime );
00428 
00429         virtual ~PartitionableObjectIterator( );
00430 
00431       // Methods implementing public interface of the geneic iterator
00432 
00433         virtual CdbStatus reset( );
00434 
00435         virtual bool next( );
00436 
00437         virtual ValueType value( );
00438 
00439         virtual bool isValid( );
00440 
00441         virtual InterfaceType* clone( ) const;
00442 
00443     private:
00444 
00445       // Helpers
00446 
00447         bool tryNextObject( );
00448 
00449         bool tryNextPartition( const BdbTime& theBeginTime,
00450                                const BdbTime& theEndTime );
00451 
00452         bool tryNextConfigElement( );
00453 
00454         bool findPartition( CdbCPtr< CdbRooRoPartitionR >& thePersistentPartitionPtr,
00455                             UShort_t                       thePartitionId );
00456 
00457     private:
00458 
00459       // Parameters
00460 
00461         CdbConditionPtr _parent;
00462 
00463         BdbTime _begin;
00464         BdbTime _end;
00465 
00466         CdbItr< CdbConfigElement > _configItr;
00467 
00468         CdbCPtr< CdbRooRoRegistry > _masterRegistryPtr;
00469         CdbCPtr< CdbRooRoRegistry > _localRegistryPtr;
00470 
00471         CdbId _extendedConditionId;
00472 
00473         BdbTime _conditionCreationTime;
00474 
00475       // The current state
00476 
00477         bool _isValid;
00478         bool _hasEverBeenAdvanced;
00479 
00480         CdbObjectPtr _value;
00481 
00482       // The context : configuration element
00483 
00484         BdbTime _beginConfig;
00485         BdbTime _endConfig;
00486         BdbTime _revisionId;
00487 
00488       // Other contexts to follow as a hierarchy of objects of two nested
00489       // classes MD and PARTITION. These classes are also used by the iterator
00490       // set up and next element location algorithms.
00491       //
00492       // DESIGN NOTES: In the current design the PARTITION object contains
00493       //               objects of the MD class. MD objects describe MetaData
00494       //               for the container PARTITION.
00495       //               There is one PARTITION descrybing the current context
00496       //               (a data member of _cxt defined below) in which the iterator
00497       //               is. The previous contexts (if any) are put into the stack
00498       //               of PARTITION-s.
00499 
00500     public:
00501 
00502       // NOTE: This class lives in the public scope since it's used
00503       //       by the PARTITION class defined below
00504 
00505         class MD {
00506 
00507         public:
00508 
00509             MD( );
00510 
00511             MD( const CdbCPtr< CdbRooRoMetaDataR >& theMetaDataPtr,
00512                 const BdbTime&                      theRevisionId );
00513 
00514             MD( const CdbCPtr< CdbRooRoMetaDataR >& theMetaDataPtr,
00515                 const CdbItr<CdbRooRoCi>&           theObjectItr,
00516                 const BdbTime&                      theRevisionId,
00517                 const BdbTime&                      theBeginTime,
00518                 const BdbTime&                      theEndTime );
00519 
00520             MD( const MD& theMd );
00521 
00522             ~MD( );
00523 
00524             MD& operator=( const MD& theMd );
00525 
00526         public:
00527 
00528             CdbCPtr< CdbRooRoMetaDataR > mdPtr;
00529 
00530             CdbItr<CdbRooRoCi> itr;
00531 
00532             BdbTime revision;
00533             BdbTime begin;
00534             BdbTime end;
00535 
00536             bool inHole;
00537 
00538             CdbItr< CdbRooRoPartitionIntervalR > pItr;
00539         };
00540 
00541     private:
00542 
00543         class PARTITION {
00544 
00545           // We need this definition in order to comply with C++ requirements
00546           // on the scope resolution. The problem is that MD and PARTITION
00547           // can't see each other since they are defined independently
00548           // inside the host class.
00549 
00550             typedef PartitionableObjectIterator::MD MD;
00551 
00552         public:
00553 
00554             PARTITION( );
00555 
00556             PARTITION( UShort_t                           thePartitionId,
00557                        const BdbTime&                     theBeginTime,
00558                        const BdbTime&                     theEndTime,
00559                        const std::vector< MD >&           theMd,
00560                        const std::vector< MD >::size_type theMdCurrent );
00561 
00562             PARTITION( const PARTITION& thePartition  );
00563 
00564             ~PARTITION( );
00565 
00566             PARTITION& operator=( const PARTITION& thePartition );
00567 
00568         public:
00569 
00570             UShort_t _partitionId;
00571 
00572             BdbTime _begin;
00573             BdbTime _end;
00574 
00575             std::vector< MD >            _md;
00576             std::vector< MD >::size_type _mdCurrent;
00577         };
00578 
00579     private:
00580 
00581       // The context : partition & metadata
00582 
00583         PARTITION             _cxt;
00584         std::stack<PARTITION> _previousCxt;
00585     };
00586 
00587   /////////////////////////////////////////////////////////////////
00588   // Implementation of the PartitionableObjectIterator::MD class //
00589   /////////////////////////////////////////////////////////////////
00590 
00591     PartitionableObjectIterator::MD::MD( )
00592     { }
00593 
00594     PartitionableObjectIterator::MD::MD( const CdbCPtr< CdbRooRoMetaDataR >& theMetaDataPtr,
00595                                          const BdbTime&                      theRevisionId ) :
00596         mdPtr   (theMetaDataPtr),
00597         revision(theRevisionId ),
00598         inHole  (false         )
00599     { }
00600 
00601     PartitionableObjectIterator::MD::MD( const CdbCPtr< CdbRooRoMetaDataR >& theMetaDataPtr,
00602                                          const CdbItr<CdbRooRoCi>&           theObjectItr,
00603                                          const BdbTime&                      theRevisionId,
00604                                          const BdbTime&                      theBeginTime,
00605                                          const BdbTime&                      theEndTime ) :
00606         mdPtr   (theMetaDataPtr),
00607         itr     (theObjectItr  ),
00608         revision(theRevisionId ),
00609         begin   (theBeginTime  ),
00610         end     (theEndTime    ),
00611         inHole  (false         )
00612     { }
00613 
00614     PartitionableObjectIterator::MD::MD( const PartitionableObjectIterator::MD& theMd ) :
00615         mdPtr   (theMd.mdPtr   ),
00616         itr     (theMd.itr     ),
00617         revision(theMd.revision),
00618         begin   (theMd.begin   ),
00619         end     (theMd.end     ),
00620         inHole  (theMd.inHole  ),
00621         pItr    (theMd.pItr    ) { }
00622 
00623     PartitionableObjectIterator::MD::~MD( )
00624     { }
00625 
00626     PartitionableObjectIterator::MD&
00627     PartitionableObjectIterator::MD::operator=( const PartitionableObjectIterator::MD& theMd )
00628     {
00629         if( this != &theMd ) {
00630             mdPtr    = theMd.mdPtr;
00631             itr      = theMd.itr;
00632             revision = theMd.revision;
00633             begin    = theMd.begin;
00634             end      = theMd.end;
00635             inHole   = theMd.inHole;
00636             pItr     = theMd.pItr;
00637         }
00638         return *this;
00639     }
00640 
00641   ////////////////////////////////////////////////////////////////////////
00642   // Implementation of the PartitionableObjectIterator::PARTITION class //
00643   ////////////////////////////////////////////////////////////////////////
00644 
00645     PartitionableObjectIterator::PARTITION::PARTITION( )
00646     { }
00647 
00648     PartitionableObjectIterator::PARTITION::PARTITION( UShort_t                           thePartitionId,
00649                                                        const BdbTime&                     theBeginTime,
00650                                                        const BdbTime&                     theEndTime,
00651                                                        const std::vector< MD >&           theMd,
00652                                                        const std::vector< MD >::size_type theMdCurrent ) :
00653         _partitionId(thePartitionId),
00654         _begin      (theBeginTime  ),
00655         _end        (theEndTime    ),
00656         _md         (theMd         ),
00657         _mdCurrent  (theMdCurrent  )
00658     { }
00659 
00660     PartitionableObjectIterator::PARTITION::PARTITION( const PartitionableObjectIterator::PARTITION& thePartition  ) :
00661         _partitionId(thePartition._partitionId),
00662         _begin      (thePartition._begin      ),
00663         _end        (thePartition._end        ),
00664         _md         (thePartition._md         ),
00665         _mdCurrent  (thePartition._mdCurrent  )
00666     { }
00667 
00668     PartitionableObjectIterator::PARTITION::~PARTITION( )
00669     { }
00670 
00671     PartitionableObjectIterator::PARTITION&
00672     PartitionableObjectIterator::PARTITION::operator=( const PartitionableObjectIterator::PARTITION& thePartition )
00673     {
00674         if( this != &thePartition ) {
00675             _partitionId = thePartition._partitionId;
00676             _begin       = thePartition._begin;
00677             _end         = thePartition._end;
00678             _md          = thePartition._md;
00679             _mdCurrent   = thePartition._mdCurrent;
00680         }
00681         return *this;
00682     }
00683 
00684   /////////////////////////////////////////////////////////////
00685   // Implementation of the PartitionableObjectIterator class //
00686   /////////////////////////////////////////////////////////////
00687 
00688     PartitionableObjectIterator::PartitionableObjectIterator( const PartitionableObjectIterator& theItr ) :
00689 
00690         _parent               (theItr._parent),
00691         _begin                (theItr._begin),
00692         _end                  (theItr._end),
00693         _configItr            (theItr._configItr),
00694         _masterRegistryPtr    (theItr._masterRegistryPtr),
00695         _localRegistryPtr     (theItr._localRegistryPtr),
00696         _extendedConditionId  (theItr._extendedConditionId),
00697         _conditionCreationTime(theItr._conditionCreationTime),
00698 
00699         _isValid              (theItr._isValid),
00700         _hasEverBeenAdvanced  (theItr._hasEverBeenAdvanced),
00701         _value                (theItr._value),
00702 
00703         _beginConfig          (theItr._beginConfig),
00704         _endConfig            (theItr._endConfig),
00705         _revisionId           (theItr._revisionId),
00706 
00707         _cxt                  (theItr._cxt),
00708         _previousCxt          (theItr._previousCxt)
00709     { }
00710 
00711     PartitionableObjectIterator::PartitionableObjectIterator( const CdbConditionPtr&             theParentPtr,
00712                                                               const BdbTime&                     theBegin,
00713                                                               const BdbTime&                     theEnd,
00714                                                               const CdbItr< CdbConfigElement >&  theConfigItr,
00715                                                               const CdbCPtr< CdbRooRoRegistry >& theMasterRegistryPtr,
00716                                                               const CdbCPtr< CdbRooRoRegistry >& theLocalRegistryPtr,
00717                                                               const CdbId&                       theExtendedConditionId,
00718                                                               const BdbTime&                     theConditionCreationTime ) :
00719         _parent               (theParentPtr),
00720         _begin                (theBegin),
00721         _end                  (theEnd),
00722         _configItr            (theConfigItr),
00723         _masterRegistryPtr    (theMasterRegistryPtr),
00724         _localRegistryPtr     (theLocalRegistryPtr),
00725         _extendedConditionId  (theExtendedConditionId),
00726         _conditionCreationTime(theConditionCreationTime),
00727         _isValid              (false),
00728         _hasEverBeenAdvanced  (false)
00729     { }
00730 
00731     PartitionableObjectIterator::~PartitionableObjectIterator( )
00732     { }
00733 
00734     CdbStatus
00735     PartitionableObjectIterator::reset( )
00736     {
00737         _isValid             = false;
00738         _hasEverBeenAdvanced = false;
00739 
00740         return CdbStatus::Success;
00741     }
00742 
00743     bool
00744     PartitionableObjectIterator::next( )
00745     {
00746         if( _hasEverBeenAdvanced ) {
00747             if( ! _isValid ) {
00748 
00749               // Stay at BEYOND_PAST_ELEMENT state
00750 
00751                 ;
00752 
00753             } else {
00754 
00755               // Try to get next object...
00756 
00757                 _isValid = tryNextObject( );
00758             }
00759 
00760         } else {
00761 
00762           // Set up initial context of the iterator. Then proceed down
00763           // to the first object of the collection starting from the configuration.
00764 
00765             _configItr.reset( );
00766 
00767             _hasEverBeenAdvanced = true;
00768             _isValid             = tryNextConfigElement( );
00769         }
00770         return _isValid;
00771     }
00772 
00773     PartitionableObjectIterator::ValueType
00774     PartitionableObjectIterator::value( )
00775     {
00776         if( ! _isValid ) {
00777             assert( 0 );
00778         }
00779         return _value;
00780     }
00781 
00782     bool
00783     PartitionableObjectIterator::isValid( )
00784     {
00785         return _isValid;
00786     }
00787 
00788     PartitionableObjectIterator::InterfaceType*
00789     PartitionableObjectIterator::PartitionableObjectIterator::clone( ) const
00790     {
00791         return new PartitionableObjectIterator( *this );
00792     }
00793 
00794     bool
00795     PartitionableObjectIterator::tryNextPartition( const BdbTime& theBeginTime,
00796                                                    const BdbTime& theEndTime )
00797     {
00798         const char* debugStr = "CdbRooRoCondition::PartitionableObjectIterator::tryNextPartition()";
00799         const char* errorStr = "CdbRooRoCondition::PartitionableObjectIterator::tryNextPartition() -- ERROR";
00800 
00801 /*********************************************************************************************/
00802 if( CdbEnvironment::getDebugMode( ) != 0 )
00803     cout << debugStr << endl
00804          << "{" << endl
00805          << "    Trying to set up partition iterator below the 'hole' at the bottom MD" << endl
00806          << "    of the current partition." << endl
00807          << "        _cxt._partitionId = " << _cxt._partitionId << endl
00808          << "        theBeginTime      = " << CdbTimeUtils::time2string( theBeginTime ) << endl
00809          << "        theEndTime        = " << CdbTimeUtils::time2string( theEndTime   ) << endl
00810          << "}" << endl;
00811 /*********************************************************************************************/
00812 
00813       // Find the bottom insertion time of the current partition.
00814 
00815         CdbCPtr< CdbRooRoPartitionR > persistentPartitionPtr;
00816 
00817         if( CdbStatus::Success != _masterRegistryPtr->partitionsLayout( )->find( _cxt._partitionId,
00818                                                                                  persistentPartitionPtr )) {
00819             cerr << 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 = _masterRegistryPtr->partitionsLayout( )->iterator( persistentPartitionPtr->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 = "CdbRooRoCondition::PartitionableObjectIterator::tryNextObject()";
00844         const char* errorStr = "CdbRooRoCondition::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                 CdbRooRoPartitionIntervalR 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                         UShort_t partitionId = iVal.id( );
00893 
00894                         CdbCPtr< CdbRooRoPartitionR > persistentPartitionPtr;
00895                         if( !findPartition( persistentPartitionPtr,
00896                                             partitionId )) {
00897                             cerr << errorStr << endl
00898                                  << "    Failed to locate the partition with ID=" << partitionId << endl;
00899                             return false;
00900                         }
00901 
00902 /******************************************************************/
00903 if( CdbEnvironment::getDebugMode( ) != 0 )
00904     cout << debugStr << endl
00905          << "{" << endl
00906          << "    Found partition ID=" << persistentPartitionPtr->id( ) << endl
00907          << "}" << endl;
00908 /******************************************************************/
00909 
00910                         if( persistentPartitionPtr->isClosed( )) {
00911                             CdbRooRoCellR pCell = persistentPartitionPtr->cell( );
00912                             if( pCell.endInsertion( ) <= _conditionCreationTime ) {
00913 
00914 /**********************************************************************************************************************/
00915 if( CdbEnvironment::getDebugMode( ) != 0 )
00916     cout << debugStr << endl
00917          << "{" << endl
00918          << "    The above found partition required by the current configuration interval is already 'closed'" << endl
00919          << "    and its upper 'insertion' time limit is older than the creation time of the current condition." << endl
00920          << "    Skipping the current configuration interval." << endl
00921          << "        partitionId            : " << partitionId << endl
00922          << "        _conditionCreationTime : " << _conditionCreationTime << endl
00923          << "        pCell.endInsertion     : " << pCell.endInsertion( ) << endl
00924          << "}" << endl;
00925 /**********************************************************************************************************************/
00926 
00927                                 continue;
00928                             }
00929                         }
00930                     }
00931 
00932                   // Okay. This partition is fine. Dive into the partition.
00933 
00934                   // ATTENTION:
00935                   //
00936                   //   Before diving we should reset the current iterator of objects
00937                   //   to begin where the just found partition ends. We need it to resume
00938                   //   iteration of objects from that time after we'll return from this partition.
00939                   //
00940                   //     [ Otherwise we may miss the rest of the current context, which can easily happen
00941                   //       for example of the current hole is longer than a partition we're going
00942                   //       to dive in. If we didn't do this then we would just miss any information
00943                   //       between the end of the partition we're diving in and the end of the current 'hole'. ]
00944                   //
00945                   //    NOTE_1: In fact we have a similar (although not the same) problem when diving into
00946                   //            MetaData within the same partition. However this problem is already solved below.
00947                   //            These two cases are not equal because when we're diving into MetaDate only then
00948                   //            we always reset its parameters (begin, end and iterator) since we use this MD object
00949                   //            for the 'hole' only. Meanwhile in the current (diving into another partition case)
00950                   //            we are not modifying the end time of the MD context, which we're going to reuse. Therefore we
00951                   //            just can't modify the limits (begin, end) of the current context, just the iterator.
00952                   //
00953                   //    NOTE_2: Pay attention that iterator is reset only if the partition interval's where
00954                   //            we're going to dive into does not last till +Infinity. In this specific case
00955                   //            it does not make any sense to reset the iterator and also the iterator initialization
00956                   //            operatio will simply fail to set up the iterator for the interval: [+Infinity,+Infinity).
00957                   //
00958                   //    NOTE_3: A similar to the previous NOTE_2 comment is that we'll reset the iterator
00959                   //            only if the partition below wher we're going to dive into ends strictly
00960                   //            _before_ the current one does. Otherwise we will wrongfully try to set up
00961                   //            an iterator with 0 length, which will cause complains from the iterator.
00962 
00963                     if(( BdbTime::plusInfinity != iVal.end( )) && ( iVal.end( ) < _cxt._md[_cxt._mdCurrent].end )) {
00964 
00965                         _cxt._md[_cxt._mdCurrent].begin = iVal.end( );
00966 
00967 /**************************************************************************************************************************************/
00968 if( CdbEnvironment::getDebugMode( ) != 0 )
00969     cout << debugStr << endl
00970          << "{" << endl
00971          << "    Resetting object iterator before to diving into a partition below the 'hole'." << endl
00972          << "    _cxt._md[" << _cxt._mdCurrent << "].begin    = " << CdbTimeUtils::time2string( _cxt._md[_cxt._mdCurrent].begin    ) << endl
00973          << "    _cxt._md[" << _cxt._mdCurrent << "].end      = " << CdbTimeUtils::time2string( _cxt._md[_cxt._mdCurrent].end      ) << endl
00974          << "    _cxt._md[" << _cxt._mdCurrent << "].revision = " << CdbTimeUtils::time2string( _cxt._md[_cxt._mdCurrent].revision ) << endl
00975          << "}" << endl;
00976 /**************************************************************************************************************************************/
00977 
00978                         if( CdbStatus::Success != _cxt._md[_cxt._mdCurrent].mdPtr->objectIterator( _cxt._md[_cxt._mdCurrent].itr,
00979                                                                                                    _cxt._md[_cxt._mdCurrent].revision,
00980                                                                                                    _cxt._md[_cxt._mdCurrent].begin,
00981                                                                                                    _cxt._md[_cxt._mdCurrent].end )) {
00982                             cerr << errorStr << endl
00983                                  << "    Failed to reset the iterator of objects to begin where the partition we're" << endl
00984                                  << "    diving in ends up." << endl;
00985                             return false;
00986                         }
00987                     }
00988 
00989                   // Save curent context
00990 
00991                     _previousCxt.push( _cxt );
00992 
00993                   // Prepare new current context
00994                   //
00995                   // NOTE: Unlike the very topmost context we're accepting all MetaData
00996                   //       objects. Besides we're alway using "modification" time of each
00997                   //       of these MD objects to determine their highest revisions.
00998 
00999                     _cxt._partitionId = iVal.id   ( );
01000                     _cxt._begin       = iVal.begin( );
01001                     _cxt._end         = iVal.end  ( );
01002 
01003 /*******************************************************************************************/
01004 if( CdbEnvironment::getDebugMode( ) != 0 )
01005     cout << debugStr << endl
01006          << "{" << endl
01007          << "    Diving into a partition below the 'hole'." << endl
01008          << "        _previousCxt.size( ) = " << _previousCxt.size( ) << endl
01009          << "        _cxt._partitionId    = " << _cxt._partitionId << endl
01010          << "        _cxt._begin          = " << CdbTimeUtils::time2string( _cxt._begin ) << endl
01011          << "        _cxt._end            = " << CdbTimeUtils::time2string( _cxt._end ) << endl
01012          << "}" << endl;
01013 
01014 /*******************************************************************************************/
01015 
01016                     std::vector< CdbCPtr< CdbRooRoMetaDataR > > vectorOfMdPtrs;
01017 
01018                     bool allIncrementsFlag = true;
01019 
01020                     if( CdbStatus::Success != findMetaData( vectorOfMdPtrs,
01021                                                             _masterRegistryPtr,
01022                                                             _localRegistryPtr,
01023                                                             _extendedConditionId,
01024                                                             _cxt._partitionId,
01025                                                             allIncrementsFlag )) {
01026                         cerr << errorStr << endl
01027                              << "    Failed to locate the MetaData objects for the current condition/partition." << endl;
01028                         break;
01029                     }
01030 
01031                     _cxt._md.clear( );
01032 
01033                     std::vector< CdbCPtr< CdbRooRoMetaDataR > >::size_type i;
01034                     std::vector< CdbCPtr< CdbRooRoMetaDataR > >::size_type num = vectorOfMdPtrs.size( );
01035 
01036                     for( i = 0; i < num; ++i ) {
01037 
01038                         CdbCPtr< CdbRooRoMetaDataR > mdPtr;
01039                         mdPtr = vectorOfMdPtrs[i];
01040 
01041                         BdbTime modified = mdPtr->modified( );
01042                         assert( BdbTime::plusInfinity != modified );
01043 
01044                       // Check for special case of the topmost element of the stack of MD. We're going
01045                       // to set up both the iterator and the limits of this element since we have
01046                       // sufficient information for this.
01047 
01048                         if(( i + 1 ) >= num ) {
01049 
01050                           // Set up an iterator matching the revision.
01051 
01052                             CdbItr<CdbRooRoCi> itr;
01053                             if( CdbStatus::Success != mdPtr->objectIterator( itr,
01054                                                                              modified,
01055                                                                              _cxt._begin,
01056                                                                              _cxt._end )) {
01057                                 cerr << errorStr << endl
01058                                      << "    Failed to set up the iterator." << endl;
01059                                 return false;
01060                             }
01061 
01062                           // Top element of the stack
01063 
01064                             _cxt._md.push_back( MD( mdPtr,
01065                                                     itr,
01066                                                     modified,
01067                                                     _cxt._begin,
01068                                                     _cxt._end ));
01069 
01070                         } else {
01071 
01072                           // This is a MetaData object below the top
01073 
01074                           // We're not establishing the composite objects iterator now
01075                           // because we don't know yet which validity range
01076                           // we're going to use this iterator for. This range will be defined
01077                           // by a "hole" in a MD above. Setting up the iterator now would
01078                           // also be very inefficient since we might never use it or we would need
01079                           // to skip many intervals in it due to ongoing development at above
01080                           // iterators.
01081 
01082                             _cxt._md.push_back( MD( mdPtr,
01083                                                     modified ));
01084                         }
01085                    }
01086 
01087                   // Switch to the topmost MD of the prepared context
01088 
01089                     if( 0 == _cxt._md.size( )) {
01090                         cerr << errorStr << endl
01091                              << "    The database could be corrupted or be in an inconsistent state." << endl;
01092                         assert( 0 );
01093                         return false;
01094                     }
01095                     _cxt._mdCurrent = _cxt._md.size( ) - 1;
01096 
01097                   // Done with context switch
01098 
01099                     found = true;
01100                     break;
01101                 }
01102             }
01103             if( !found ) {
01104 
01105               // No more partitions below current one or the hole has ended. Then just proceed
01106               // with the next element at the bottom of the stack trying to hit a non-empty
01107               // one object or reach the end of the current MetaData object.
01108 
01109                 _cxt._md[_cxt._mdCurrent].inHole = false;
01110             }
01111         }
01112 
01113       // Proceed within current PARTITION context and MD
01114 
01115         do {
01116 
01117             while( _cxt._md[_cxt._mdCurrent].itr.next( )) {
01118 
01119                 CdbRooRoCi ci = _cxt._md[_cxt._mdCurrent].itr.value( );
01120 
01121 /**************************************************************************************************************************************/
01122 if( CdbEnvironment::getDebugMode( ) != 0 )
01123     cout << debugStr << endl
01124          << "{" << endl
01125          << "    _cxt._md[" << _cxt._mdCurrent << "].begin    = " << CdbTimeUtils::time2string( _cxt._md[_cxt._mdCurrent].begin    ) << endl
01126          << "    _cxt._md[" << _cxt._mdCurrent << "].end      = " << CdbTimeUtils::time2string( _cxt._md[_cxt._mdCurrent].end      ) << endl
01127          << "    _cxt._md[" << _cxt._mdCurrent << "].revision = " << CdbTimeUtils::time2string( _cxt._md[_cxt._mdCurrent].revision ) << endl
01128          << "    ci = " << ci << endl
01129          << "}" << endl;
01130 /**************************************************************************************************************************************/
01131 
01132               // Make adjustments for the validity time of the found interval if it's needed.
01133 
01134                 BdbTime begin = ci.begin( );
01135                 BdbTime end   = ci.end  ( );
01136 
01137                 if( begin < _cxt._md[_cxt._mdCurrent].begin ) begin = _cxt._md[_cxt._mdCurrent].begin;
01138                 if( end   > _cxt._md[_cxt._mdCurrent].end   ) end   = _cxt._md[_cxt._mdCurrent].end;
01139 
01140                 assert( end >= begin );
01141 
01142               // Check if the validity of the found object is still within
01143               // the limits of the "md" entry at this level. If not then we should
01144               // back off to let the upper level (another "md" or "partition" or "configuration"
01145               // or the iterator ) to take further actions.
01146 
01147                 if( begin >= _cxt._md[_cxt._mdCurrent].end ) {
01148 
01149                     _cxt._mdCurrent++;
01150                     if( _cxt._mdCurrent >= _cxt._md.size( )) {
01151 
01152                         if( _previousCxt.empty( )) return tryNextConfigElement( );
01153 
01154                       // One step up to previous partition
01155 
01156                         _cxt = _previousCxt.top( );
01157                         _previousCxt.pop( );
01158 
01159                       // Remove "inHole" flag from the previous partition's MD
01160 
01161                         _cxt._md[_cxt._mdCurrent].inHole = false;
01162 
01163                       // And proceed with next attemp to locate an object below.
01164 
01165                     }
01166                     return tryNextObject( );
01167 
01168                 } else {
01169 
01170                   // Check for a "hole". If there is one then we need to go down
01171                   // the stack of MetaData.
01172 
01173                     if( ci.isEmpty( )) {
01174 
01175                       // If we're at the bottom of the stack then we'll try to set up
01176                       // an iterator for partitions below the current one to see if we
01177                       // could proceed down.
01178 
01179                         if( 0 == _cxt._mdCurrent ) {
01180                             return tryNextPartition( begin, end );
01181                         }
01182                         _cxt._mdCurrent--;
01183 
01184                       // Prepare the MD object, including its validity limits and the iterator.
01185 
01186                         _cxt._md[_cxt._mdCurrent].begin = begin;
01187                         _cxt._md[_cxt._mdCurrent].end   = end;
01188 
01189                         if( CdbStatus::Success != _cxt._md[_cxt._mdCurrent].mdPtr->objectIterator( _cxt._md[_cxt._mdCurrent].itr,
01190                                                                                                    _cxt._md[_cxt._mdCurrent].revision,
01191                                                                                                    _cxt._md[_cxt._mdCurrent].begin,
01192                                                                                                    _cxt._md[_cxt._mdCurrent].end )) {
01193                             cerr << errorStr << endl
01194                                  << "    Failed to set up the iterator." << endl;
01195                             return false;
01196                         }
01197 
01198                         return tryNextObject( );
01199 
01200                     } else {
01201 
01202                       // Construct the current value of the iterator and return with success.
01203 
01204                         _value = new CdbRooRoObject( _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                                                      ci.original( ).legacyObjectAddress( ));
01214                         return true;
01215                     }
01216                 }
01217 
01218             }
01219 
01220           // We may get here only if the iterator in the loop above got
01221           // beyond its last element while iterating over the bottom-most layer
01222           // of MD. So now we need either back off to the upper
01223           // MD object (if any), or previous partition (if any). Otherwise we back off to
01224           // the configuration.
01225 
01226             _cxt._mdCurrent++;
01227             if( _cxt._mdCurrent >= _cxt._md.size( )) {
01228 
01229                 if( _previousCxt.empty( )) return tryNextConfigElement( );
01230 
01231               // One step up to previous partition
01232 
01233                 _cxt = _previousCxt.top( );
01234                 _previousCxt.pop( );
01235 
01236               // Remove "inHole" flag from the previous partition's MD
01237 
01238                 _cxt._md[_cxt._mdCurrent].inHole = false;
01239 
01240               // And proceed with next attemp to locate an object withing the current method
01241               // but in the just "pop"-ped previous context.
01242             }
01243 
01244         } while( true );
01245 
01246         return false;
01247     }
01248 
01249     bool
01250     PartitionableObjectIterator::findPartition( CdbCPtr< CdbRooRoPartitionR >& thePersistentPartitionPtr,
01251                                                 UShort_t                       thePartitionId )
01252     {
01253         const char* errorStr = "CdbRooRoCondition::PartitionableObjectIterator::findPartition() -- ERROR";
01254 
01255         bool result = false;
01256         do {
01257 
01258           // The temporary partition reference required by some interfaces.
01259 
01260             CdbCPtr< CdbRooRoPartitionR > persistentPartitionPtr;
01261 
01262           // The partition location can be a two-stage process, First we look for general
01263           // partition information at the MASTER registry. Then we need to verify if the
01264           // found partition belongs to the local registry. If so then we reload
01265           // partition information from the local registry since this partition
01266           // is supposed to be modified locally.
01267 
01268             if( CdbStatus::Success != _masterRegistryPtr->partitionsLayout( )->find( thePartitionId,
01269                                                                                      persistentPartitionPtr )) {
01270                 cerr << errorStr << endl
01271                          << "    Failed to find a partition #" << thePartitionId << " at the master registry." << endl;
01272                 break;
01273             }
01274 
01275             if(( _localRegistryPtr->originId( ) == persistentPartitionPtr->originId( )) &&
01276                ( _localRegistryPtr->originId( ) != _masterRegistryPtr->originId( ))) {
01277 
01278                 if( CdbStatus::Success != _localRegistryPtr->partitionsLayout( )->find( thePartitionId,
01279                                                                                         persistentPartitionPtr )) {
01280                     cerr << errorStr << endl
01281                          << "    Failed to find a partition #" << thePartitionId << " at the local registry." << endl;
01282                     break;
01283                 }
01284             }
01285 
01286           // Done.
01287 
01288             thePersistentPartitionPtr = persistentPartitionPtr;
01289             result                    = true;
01290 
01291         } while( false );
01292 
01293         return result;
01294     }
01295 
01296     bool
01297     PartitionableObjectIterator::tryNextConfigElement( )
01298     {
01299         const char* debugStr = "CdbRooRoCondition::PartitionableObjectIterator::tryNextConfigElement()";
01300         const char* errorStr = "CdbRooRoCondition::PartitionableObjectIterator::tryNextConfigElement() -- ERROR";
01301 
01302 /******************************************************************/
01303 if( CdbEnvironment::getDebugMode( ) != 0 )
01304     cout << debugStr << endl
01305          << "{" << endl
01306          << "    ENTERING THE METHOD..." << endl
01307          << "}" << endl;
01308 /******************************************************************/
01309 
01310         while( _configItr.next( )) {
01311 
01312           // Get rid of any previous contexts of partitions
01313 
01314             _previousCxt = std::stack<PARTITION>( );
01315 
01316           // Get next element
01317           //
01318           // Skip the whole configuration interval if the found
01319           // configuration element will say so.
01320           //
01321           // ATTENTION: If the config element says "do not use revisions"
01322           //            then we just ignore this statement and replace it
01323           //            with "use topmost revisiono instead."
01324 
01325             CdbConfigElement in = _configItr.value( );
01326             if( !in.accessIsAllowed ) continue;
01327 
01328             _beginConfig = in.begin;
01329             _endConfig   = in.end;
01330 
01331             if( in.policy.useRevision( )) _revisionId = in.policy.revisionId( );
01332             else                          _revisionId = BdbTime::plusInfinity;
01333 
01334             _cxt._partitionId = in.policy.partitionId( );
01335 
01336           // Check if we need to skip or shorten this configuration element
01337           // because the specified iterator's range:
01338           //
01339           //     _begin   _end       ACTION:
01340           //          :   :
01341           //      [---)   :          1: skip
01342           //      [---:---)          2: cut on the left only
01343           //      [---:---:---)      3: cut on the left and on the right
01344           //          [---)          4: none
01345           //          [---:---)      5: cut on the right only
01346           //          :   [---)      6: finish (not found)
01347 
01348             if( _endConfig   <= _begin ) continue;              // #1
01349             if( _beginConfig >= _end   ) break;                 // #6
01350             if( _beginConfig < _begin  ) _beginConfig = _begin; // #2, #3
01351             if( _endConfig   > _end    ) _endConfig   = _end;   // #3, #5
01352 
01353             _cxt._begin = _beginConfig;
01354             _cxt._end   = _endConfig;
01355 
01356           // Find out the partition to see if it's in the "closed" state. If so then we need
01357           // to check if its upper "insertion" time boundry is not older than the creation
01358           // time of the condition. If it happens that the condition is newer than the partition
01359           // closeout time then we just bail out since there should not be any MetaData information
01360           // in this partition for our current condition. Then we skip this config element.
01361 
01362             {
01363                 CdbCPtr< CdbRooRoPartitionR > persistentPartitionPtr;
01364                 if( ! findPartition( persistentPartitionPtr,
01365                                      _cxt._partitionId )) {
01366                     cerr << errorStr << endl
01367                          << "    Failed to locate the partition with ID=" << _cxt._partitionId << endl;
01368                     break;
01369                 }
01370 
01371 /******************************************************************/
01372 if( CdbEnvironment::getDebugMode( ) != 0 )
01373     cout << debugStr << endl
01374          << "{" << endl
01375          << "    Found partition ID=" << persistentPartitionPtr->id( ) << endl
01376          << "}" << endl;
01377 /******************************************************************/
01378 
01379                 if( persistentPartitionPtr->isClosed( )) {
01380                     CdbRooRoCellR pCell = persistentPartitionPtr->cell( );
01381                     if( pCell.endInsertion( ) <= _conditionCreationTime ) {
01382 
01383 /**********************************************************************************************************************/
01384 if( CdbEnvironment::getDebugMode( ) != 0 )
01385     cout << debugStr << endl
01386          << "{" << endl
01387          << "    The above found partition required by the current configuration interval is already 'closed'" << endl
01388          << "    and its upper 'insertion' time limit is older than the creation time of the current condition." << endl
01389          << "    Skipping the current configuration interval." << endl
01390          << "        _cxt._partitionId      : " << _cxt._partitionId << endl
01391          << "        _conditionCreationTime : " << _conditionCreationTime << endl
01392          << "        pCell.endInsertion     : " << pCell.endInsertion( ) << endl
01393          << "}" << endl;
01394 /**********************************************************************************************************************/
01395 
01396                         continue;
01397                     }
01398                 }
01399             }
01400 
01401           // Build a stack of MetaData for the found element. This operation is done
01402           // in the folowing steps:
01403           //
01404           //   1) Get a list of all MetaData objects for specified condition/partition.
01405           //
01406           //   2) Find the MetaData corresponding to specified revision.
01407           //
01408           //   3) Discard any MetaData-s above the one containing specified revision
01409           //      and keep the others.
01410           //
01411           //   4) Create a vector of objects of the nested MD class. The rules for these
01412           //      objects differ for the top element in the vector and thoses below it:
01413           //
01414           //      - top element always gets the original revision ID established above.
01415           //        Its composite objects iterator is also set up for a validity
01416           //        interval of the current configuration element.
01417           //
01418           //      - other elements are set up with their most recent revisions
01419           //        corresponding to the "modified" time of these MD objects.
01420           //        Their composite objects iterators are not set.
01421 
01422             std::vector< CdbCPtr< CdbRooRoMetaDataR > > vectorOfMdPtrs;
01423 
01424             bool allIncrementsFlag = true;
01425 
01426             if( CdbStatus::Success !=  findMetaData( vectorOfMdPtrs,
01427                                                      _masterRegistryPtr,
01428                                                      _localRegistryPtr,
01429                                                      _extendedConditionId,
01430                                                      _cxt._partitionId,
01431                                                      allIncrementsFlag )) {
01432                 cerr << errorStr << endl
01433                      << "    Failed to locate the MetaData objects for the current condition/partition." << endl;
01434                 break;
01435             }
01436 
01437             const std::vector< CdbCPtr< CdbRooRoMetaDataR > >::size_type numPart = vectorOfMdPtrs.size( );
01438             if( 0 == numPart ) {
01439                 cerr << errorStr << endl
01440                      << "    There is no MetaData objects for the current condition/partition." << endl
01441                      << "    The condition/partition could not be properly initialized/loaded." << endl;
01442                 break;
01443             }
01444 
01445             _cxt._md.clear( );
01446 
01447             for( std::vector< CdbCPtr< CdbRooRoMetaDataR > >::size_type i = 0; i < numPart; ++i ) {
01448 
01449                 CdbCPtr< CdbRooRoMetaDataR > mdPtr;
01450                 mdPtr = vectorOfMdPtrs[i];
01451 
01452                 if( _revisionId >= mdPtr->minInsertion( )) {
01453 
01454                   // Three ways to set up the MD at the context:
01455                   //
01456                   //   1: This is for a top MD element (not nessesarily the top at the input
01457                   //      vector) only. This is the last MD including specified revision.
01458                   //
01459                   //        1.1: We also cover the case of the topmost revision at
01460                   //             "open" partitions.
01461                   //
01462                   //   2: This is a variation of the 1.1 case above for "closed" partitions.
01463                   //      The reason why we put it into a special case is that "closed" partitions
01464                   //      do not have the topmost revision. HOwever we still need to provide
01465                   //      backward compatibility for teh old views configured for the topmost
01466                   //      revision in the same way it's done for regular conditions.
01467                   //      Here we map the topmost revision onto the final revision of the MD object
01468                   //      whose actual revision iD corresponds to the revision modification timestamp.
01469                   //
01470                   //   3. In the final case of the non-top MD objects we use the modification
01471                   //      timestamp of the MD object as the revision identifier.
01472 
01473                     if((( BdbTime::plusInfinity == _revisionId ) && ( BdbTime::plusInfinity == mdPtr->maxInsertion( ))) ||
01474                        ( _revisionId < mdPtr->maxInsertion( ))) {
01475 
01476                       // -1-
01477 
01478                       // Set up an iterator matching the exact revision.
01479 
01480                         CdbItr<CdbRooRoCi> itr;
01481                         if( CdbStatus::Success != mdPtr->objectIterator( itr,
01482                                                                          _revisionId,
01483                                                                          _beginConfig,
01484                                                                          _endConfig )) {
01485                             cerr << errorStr << endl
01486                                  << "    Failed to set up the iterator." << endl;
01487                             return false;
01488                         }
01489 
01490                       // Top element of the stack
01491 
01492                         _cxt._md.push_back( MD( mdPtr,
01493                                                 itr,
01494                                                 _revisionId,
01495                                                 _cxt._begin,
01496                                                 _cxt._end ));
01497 
01498 /**************************************************************************************************************************************/
01499 if( CdbEnvironment::getDebugMode( ) != 0 )
01500     cout << debugStr << endl
01501          << "{" << endl
01502          << "    Case #1: Regular top MetaData/Increment object which has exactly the required" << endl
01503          << "             revision. This use case also include 'open' partition and 'topmost' revision." << endl
01504          << "    {" << endl
01505          << "        _cxt._partitionId      = " << _cxt._partitionId << endl
01506          << "        _cxt._begin            = " << CdbTimeUtils::time2string( _cxt._begin ) << endl
01507          << "        _cxt._end              = " << CdbTimeUtils::time2string( _cxt._end ) << endl
01508          << "        mdPtr->minInsertion( ) = " << CdbTimeUtils::time2string( mdPtr->minInsertion( )) << endl
01509          << "        mdPtr->maxInsertion( ) = " << CdbTimeUtils::time2string( mdPtr->maxInsertion( )) << endl
01510          << "        _revisionId            = " << CdbTimeUtils::time2string( _revisionId ) << endl
01511          << "    }" << endl
01512          << "}" << endl;
01513 /**************************************************************************************************************************************/
01514 
01515                       // Since we found the top MD objects so we need to stop here.
01516 
01517                         break;
01518 
01519                     } else if((( numPart - 1 ) == i ) &&
01520                               ( BdbTime::plusInfinity == _revisionId ) &&
01521                               ( BdbTime::plusInfinity != mdPtr->maxInsertion( ))){
01522 
01523                       // -2-
01524 
01525                       // Set up an iterator matching the final revision of the MD object.
01526 
01527                         BdbTime modified = mdPtr->modified( );
01528 
01529                         CdbItr<CdbRooRoCi> itr;
01530                         if( CdbStatus::Success != mdPtr->objectIterator( itr,
01531                                                                          modified,
01532                                                                          _beginConfig,
01533                                                                          _endConfig )) {
01534                             cerr << errorStr << endl
01535                                  << "    Failed to set up the iterator." << endl;
01536                             return false;
01537                         }
01538 
01539                       // Top element of the stack
01540 
01541                         _cxt._md.push_back( MD( mdPtr,
01542                                                 itr,
01543                                                 modified,
01544                                                 _cxt._begin,
01545                                                 _cxt._end ));
01546 
01547 /**************************************************************************************************************************************/
01548 if( CdbEnvironment::getDebugMode( ) != 0 )
01549     cout << debugStr << endl
01550          << "{" << endl
01551          << "    Case #2. Special case of a 'closed' partition when the 'topmost' (+Infinity)" << endl
01552          << "             revision identifier is required by the view configuration." << endl
01553          << "             The solution in this case is to find out the most recent reveision in this" << endl
01554          << "             partition and to treat it as the topmost one. The identifier of this most" << endl
01555          << "             recent revision is equal to the 'modified' time of the top MetaData/Increment" << endl
01556          << "             object of the partition." << endl
01557          << "    {" << endl
01558          << "        _cxt._partitionId      = " << _cxt._partitionId << endl
01559          << "        _cxt._begin            = " << CdbTimeUtils::time2string( _cxt._begin ) << endl
01560          << "        _cxt._end              = " << CdbTimeUtils::time2string( _cxt._end ) << endl
01561          << "        mdPtr->minInsertion( ) = " << CdbTimeUtils::time2string( mdPtr->minInsertion( )) << endl
01562          << "        mdPtr->maxInsertion( ) = " << CdbTimeUtils::time2string( mdPtr->maxInsertion( )) << endl
01563          << "        modified               = " << CdbTimeUtils::time2string( modified ) << endl
01564          << "    }" << endl
01565          << "}" << endl;
01566 /**************************************************************************************************************************************/
01567 
01568                     } else {
01569 
01570                       // -3-
01571 
01572                       // It will use the MetaData object's modification time
01573                       // time to set up the composite object iterator. We're not establishing
01574                       // this iterator now because we don't know yet which validity range
01575                       // we're going to use this iterator for. This range will be defined
01576                       // by a "hole" in a revision above. Setting up the iterator now would
01577                       // also be veru inefficient since we might never use it or we would need
01578                       // to skip many intervals in it due to ongoing development at above
01579                       // iterators.
01580 
01581                         BdbTime modified = mdPtr->modified( );
01582                         assert( BdbTime::plusInfinity != modified );
01583 
01584                         _cxt._md.push_back( MD( mdPtr,
01585                                             modified ));
01586 
01587 /**************************************************************************************************************************************/
01588 if( CdbEnvironment::getDebugMode( ) != 0 )
01589     cout << debugStr << endl
01590          << "{" << endl
01591          << "    Case #3: MetaData/Increment object below the topmost one for this partition." << endl
01592          << "             We should use the 'modified' time of this MetaData/Increment object as an actual" << endl
01593          << "             revision identifier." << endl
01594          << "    {" << endl
01595          << "        _cxt._partitionId      = " << _cxt._partitionId << endl
01596          << "        _cxt._begin            = " << CdbTimeUtils::time2string( _cxt._begin ) << endl
01597          << "        _cxt._end              = " << CdbTimeUtils::time2string( _cxt._end ) << endl
01598          << "        mdPtr->minInsertion( ) = " << CdbTimeUtils::time2string( mdPtr->minInsertion( )) << endl
01599          << "        mdPtr->maxInsertion( ) = " << CdbTimeUtils::time2string( mdPtr->maxInsertion( )) << endl
01600          << "        modified               = " << CdbTimeUtils::time2string( modified ) << endl
01601          << "    }" << endl
01602          << "}" << endl;
01603 /**************************************************************************************************************************************/
01604 
01605                     }
01606 
01607                 } else {
01608 
01609                   // We're above specified revision.
01610 
01611                     break;
01612                 }
01613             }
01614             if( 0 == _cxt._md.size( )) {
01615                 cerr << errorStr << endl
01616                      << "    The database could be corrupted or be in an inconsistent state." << endl;
01617                 assert( 0 );
01618                 return false;
01619             }
01620             _cxt._mdCurrent = _cxt._md.size( ) - 1;
01621 
01622 /***************************************************************/
01623 if( CdbEnvironment::getDebugMode( ) != 0 )
01624     cout << debugStr << endl
01625          << "{" << endl
01626          << "    _cxt._mdCurrent = " << _cxt._mdCurrent << endl
01627          << "}" << endl;
01628 /***************************************************************/
01629 
01630           // Proceed down to the first element in the stack
01631 
01632             if( tryNextObject( )) return true;
01633         }
01634 
01635         return false;
01636     }
01637 
01638   //////////////////////////////////
01639   // Class: RegularObjectIterator //
01640   //////////////////////////////////
01641 
01642     class RegularObjectIterator : public CdbObjectItr::InterfaceType {
01643 
01644     private:
01645 
01646         RegularObjectIterator( );
01647 
01648         RegularObjectIterator& operator=( const RegularObjectIterator& theItr );
01649 
01650     protected:
01651 
01652         RegularObjectIterator( const RegularObjectIterator& theItr ) :
01653 
01654             _parent             (theItr._parent),
01655             _begin              (theItr._begin),
01656             _end                (theItr._end),
01657             _configItr          (theItr._configItr),
01658             _masterRegistryPtr  (theItr._masterRegistryPtr),
01659             _localRegistryPtr   (theItr._localRegistryPtr),
01660             _extendedConditionId(theItr._extendedConditionId),
01661 
01662             _isValid            (theItr._isValid),
01663             _hasEverBeenAdvanced(theItr._hasEverBeenAdvanced),
01664             _value              (theItr._value),
01665 
01666             _beginConfig        (theItr._beginConfig),
01667             _endConfig          (theItr._endConfig),
01668             _revisionId         (theItr._revisionId),
01669             _partitionId        (theItr._partitionId),
01670 
01671             _md                 (theItr._md),
01672             _mdCurrent          (theItr._mdCurrent)
01673         { }
01674 
01675     public:
01676 
01677       /// Normal constructor
01678       /**
01679         * If the configuration collection parameter is pointing onto a zero object
01680         * then the revision policy must be used.
01681         */
01682         RegularObjectIterator( const CdbConditionPtr&             theParentPtr,
01683                                const BdbTime&                     theBegin,
01684                                const BdbTime&                     theEnd,
01685                                const CdbItr< CdbConfigElement >&  theConfigItr,
01686                                const CdbCPtr< CdbRooRoRegistry >& theMasterRegistryPtr,
01687                                const CdbCPtr< CdbRooRoRegistry >& theLocalRegistryPtr,
01688                                const CdbId&                       theExtendedConditionId ) :
01689             _parent             (theParentPtr),
01690             _begin              (theBegin),
01691             _end                (theEnd),
01692             _configItr          (theConfigItr),
01693             _masterRegistryPtr  (theMasterRegistryPtr),
01694             _localRegistryPtr   (theLocalRegistryPtr),
01695             _extendedConditionId(theExtendedConditionId),
01696             _isValid            (false),
01697             _hasEverBeenAdvanced(false)
01698         { }
01699 
01700         virtual ~RegularObjectIterator( )
01701         { }
01702 
01703         virtual CdbStatus reset( )
01704         {
01705             _isValid             = false;
01706             _hasEverBeenAdvanced = false;
01707 
01708             return CdbStatus::Success;
01709         }
01710 
01711         bool tryNextObject( );
01712         bool tryNextConfigElement( );
01713 
01714         virtual bool next( )
01715         {
01716             if( _hasEverBeenAdvanced ) {
01717                 if( ! _isValid ) {
01718 
01719                   // Stay at BEYOND_PAST_ELEMENT state
01720 
01721                     ;
01722 
01723                 } else {
01724 
01725                   // Try to get next object...
01726 
01727                     _isValid = tryNextObject( );
01728                 }
01729 
01730             } else {
01731 
01732               // Set up initial context of the iterator. Then proceed down
01733               // to the first object of the collection starting from the configuration.
01734 
01735                 _configItr.reset( );
01736 
01737                 _hasEverBeenAdvanced = true;
01738                 _isValid             = tryNextConfigElement( );
01739             }
01740             return _isValid;
01741         }
01742 
01743         virtual ValueType value( )
01744         {
01745             if( ! _isValid ) {
01746                 assert( 0 );
01747             }
01748             return _value;
01749         }
01750 
01751         virtual bool isValid( )
01752         {
01753             return _isValid;
01754         }
01755 
01756         virtual InterfaceType* clone( ) const
01757         {
01758             return new RegularObjectIterator( *this );
01759         }
01760 
01761     private:
01762 
01763       // Parameters
01764 
01765         CdbConditionPtr _parent;
01766 
01767         BdbTime _begin;
01768         BdbTime _end;
01769 
01770         CdbItr< CdbConfigElement > _configItr;
01771 
01772         CdbCPtr< CdbRooRoRegistry > _masterRegistryPtr;
01773         CdbCPtr< CdbRooRoRegistry > _localRegistryPtr;
01774 
01775         CdbId _extendedConditionId;
01776 
01777       // The current state
01778 
01779         bool _isValid;
01780         bool _hasEverBeenAdvanced;
01781 
01782         CdbObjectPtr _value;
01783 
01784       // The context : configuration element
01785 
01786         BdbTime _beginConfig;
01787         BdbTime _endConfig;
01788         BdbTime _revisionId;
01789 
01790         UShort_t _partitionId;
01791 
01792       // The context : meta-data
01793 
01794         class MD {
01795 
01796         public:
01797 
01798             MD( ) { }
01799 
01800             MD( const CdbCPtr< CdbRooRoMetaDataR >& theMetaDataPtr,
01801                 const BdbTime&                      theRevisionId ) :
01802                 mdPtr   (theMetaDataPtr),
01803                 revision(theRevisionId ) { }
01804 
01805             MD( const CdbCPtr< CdbRooRoMetaDataR >& theMetaDataPtr,
01806                 const CdbItr<CdbRooRoCi>&           theObjectItr,
01807                 const BdbTime&                      theRevisionId,
01808                 const BdbTime&                      theBeginTime,
01809                 const BdbTime&                      theEndTime ) :
01810                 mdPtr   (theMetaDataPtr),
01811                 itr     (theObjectItr  ),
01812                 revision(theRevisionId ),
01813                 begin   (theBeginTime  ),
01814                 end     (theEndTime    ) { }
01815 
01816             MD( const MD& theMd ) :
01817                 mdPtr   (theMd.mdPtr   ),
01818                 itr     (theMd.itr     ),
01819                 revision(theMd.revision),
01820                 begin   (theMd.begin   ),
01821                 end     (theMd.end     ) { }
01822 
01823             ~MD( ) { }
01824 
01825             MD& operator=( const MD& theMd )
01826             {
01827                 if( this != &theMd ) {
01828                     mdPtr    = theMd.mdPtr;
01829                     itr      = theMd.itr;
01830                     revision = theMd.revision;
01831                     begin    = theMd.begin;
01832                     end      = theMd.end;
01833                 }
01834                 return *this;
01835             }
01836 
01837         public:
01838 
01839             CdbCPtr< CdbRooRoMetaDataR > mdPtr;
01840 
01841             CdbItr<CdbRooRoCi> itr;
01842 
01843             BdbTime revision;
01844             BdbTime begin;
01845             BdbTime end;
01846         };
01847         std::vector< MD >            _md;
01848         std::vector< MD >::size_type _mdCurrent;
01849 
01850       // The context : object
01851     };
01852 
01853   ///////////////////////////////////////////////////////
01854   // Implementation of the RegularObjectIterator class //
01855   ///////////////////////////////////////////////////////
01856 
01857     bool
01858     RegularObjectIterator::tryNextObject( )
01859     {
01860         const char* debugStr = "CdbRooRoCondition::RegularObjectIterator::tryNextObject()";
01861         const char* errorStr = "CdbRooRoCondition::RegularObjectIterator::tryNextObject() -- ERROR";
01862 
01863         assert( _md.size( ) > 0 );
01864         assert( _mdCurrent < _md.size( ));
01865 
01866         do {
01867 
01868             while( _md[_mdCurrent].itr.next( )) {
01869 
01870                 CdbRooRoCi ci = _md[_mdCurrent].itr.value( );
01871 
01872 /**************************************************************************************************************/
01873 if( CdbEnvironment::getDebugMode( ) != 0 )
01874     cout << debugStr << endl
01875          << "{" << endl
01876          << "    _md[" << _mdCurrent << "].begin    = " << CdbTimeUtils::time2string( _md[_mdCurrent].begin    ) << endl
01877          << "    _md[" << _mdCurrent << "].end      = " << CdbTimeUtils::time2string( _md[_mdCurrent].end      ) << endl
01878          << "    _md[" << _mdCurrent << "].revision = " << CdbTimeUtils::time2string( _md[_mdCurrent].revision ) << endl
01879          << "    ci = " << ci << endl
01880          << "}" << endl;
01881 /**************************************************************************************************************/
01882 
01883               // Make adjustments for the validity time of the found interval if it's needed.
01884 
01885                 BdbTime begin = ci.begin( );
01886                 BdbTime end   = ci.end  ( );
01887 
01888                 if( begin < _md[_mdCurrent].begin ) begin = _md[_mdCurrent].begin;
01889                 if( end   > _md[_mdCurrent].end   ) end   = _md[_mdCurrent].end;
01890 
01891                 assert( end >= begin );
01892 
01893               // Check if the validity of the found object is still within
01894               // the limits of the "md" entry at this level. If not then we should
01895               // back off to let the upper level (another "md" or "configuration"
01896               // or the iterator ) to take further actions.
01897 
01898                 if( begin >= _md[_mdCurrent].end ) {
01899 
01900                     _mdCurrent++;
01901                     if( _mdCurrent >= _md.size( )) return tryNextConfigElement( );
01902 
01903                     return tryNextObject( );
01904 
01905                 } else {
01906 
01907                   // Check for a "hole". If there is one then we need to go down
01908                   // the stack of MetaData.
01909 
01910                     if( ci.isEmpty( )) {
01911 
01912                       // If we're at the bottom of the stack then we have nowhere
01913                       // else to look for intervals. So we'll try to proceed down along
01914                       // the validity time dimension hoping to hit a non-zero object.
01915 
01916                         if( 0 == _mdCurrent ) continue;
01917                         _mdCurrent--;
01918 
01919                       // Prepare the MD object, including its validity limits and the iterator.
01920 
01921                         _md[_mdCurrent].begin = begin;
01922                         _md[_mdCurrent].end   = end;
01923 
01924                         if( CdbStatus::Success != _md[_mdCurrent].mdPtr->objectIterator( _md[_mdCurrent].itr,
01925                                                                                          _md[_mdCurrent].revision,
01926                                                                                          _md[_mdCurrent].begin,
01927                                                                                          _md[_mdCurrent].end )) {
01928                             cerr << errorStr << endl
01929                                  << "    Failed to set up the iterator." << endl;
01930                             return false;
01931                         }
01932 
01933                         return tryNextObject( );
01934 
01935                     } else {
01936 
01937                       // Construct the current value of the iterator and return with success.
01938 
01939                         _value = new CdbRooRoObject( _parent,
01940                                                      ci.original( ).begin( ),       // begin of "original" period
01941                                                      ci.original( ).end( ),         // begin of "original" period
01942                                                      begin,
01943                                                      end,
01944                                                      ci.original( ).inserted( ),    // begin of "duration" period
01945                                                      BdbTime::plusInfinity,         // end   of "duration" period
01946                                                      ci.original( ).inserted( ),
01947                                                      ci.original( ).object( ),
01948                                                      ci.original( ).legacyObjectAddress( ));
01949                         return true;
01950                     }
01951                 }
01952 
01953             }
01954 
01955           // We may gete here only of the iterator in the loop above got
01956           // beyond its last element while iterating over the bottom-most layer
01957           // of MD. So now we need either back off to the upper
01958           // MD object (if any). Otherwise we back off to the configuration.
01959 
01960             _mdCurrent++;
01961             if( _mdCurrent >= _md.size( )) return tryNextConfigElement( );
01962 
01963         } while( true );
01964 
01965         return false;
01966     }
01967 
01968     bool
01969     RegularObjectIterator::tryNextConfigElement( )
01970     {
01971         const char* debugStr = "CdbRooRoCondition::RegularObjectIterator::tryNextConfigElement()";
01972         const char* errorStr = "CdbRooRoCondition::RegularObjectIterator::tryNextConfigElement() -- ERROR";
01973 
01974         while( _configItr.next( )) {
01975 
01976           // Get next element
01977           //
01978           // Skip the whole configuration interval if the found
01979           // configuration element will say so.
01980           //
01981           // ATTENTION: If the config element says "do not use revisions"
01982           //            then we just ignore this statement and replace it
01983           //            with "use topmost revisiono instead."
01984 
01985             CdbConfigElement in = _configItr.value( );
01986             if( ! in.accessIsAllowed ) continue;
01987 
01988             _beginConfig = in.begin;
01989             _endConfig   = in.end;
01990 
01991             if( in.policy.useRevision( )) _revisionId = in.policy.revisionId( );
01992             else                          _revisionId = BdbTime::plusInfinity;
01993 
01994             _partitionId = in.policy.partitionId( );
01995 
01996           // Check if we need to skip or shorten this configuration element
01997           // because the specified iterator's range:
01998           //
01999           //     _begin   _end       ACTION:
02000           //          :   :
02001           //      [---)   :          1: skip
02002           //      [---:---)          2: cut on the left only
02003           //      [---:---:---)      3: cut on the left and on the right
02004           //          [---)          4: none
02005           //          [---:---)      5: cut on the right only
02006           //          :   [---)      6: finish (not found)
02007 
02008             if( _endConfig   <= _begin ) continue;              // #1
02009             if( _beginConfig >= _end   ) break;                 // #6
02010             if( _beginConfig < _begin  ) _beginConfig = _begin; // #2, #3
02011             if( _endConfig   > _end    ) _endConfig   = _end;   // #3, #5
02012 
02013           // Build a stack of MetaData for the found element. This operation is done
02014           // in the folowing steps:
02015           //
02016           //   1) Get a list of all MetaData objects for specified condition/partition.
02017           //
02018           //   2) Find the MetaData corresponding to specified revision.
02019           //
02020           //   3) Discard any MetaData-s above the one containing specified revision
02021           //      and keep the others.
02022           //
02023           //   4) Create a vector of objects of the nested MD class. The rules for these
02024           //      objects differ for the top element in the vector and thoses below it:
02025           //
02026           //      - top element always gets the original revision ID established above.
02027           //        Its composite objects iterator is also set up for a validity
02028           //        interval of the current configuration element.
02029           //
02030           //      - other elements are set up with their most recent revisions
02031           //        corresponding to the "modified" time of these MD objects.
02032           //        Their composite objects iterators are not set.
02033 
02034             std::vector< CdbCPtr< CdbRooRoMetaDataR > > vectorOfMdPtrs;
02035 
02036             bool allIncrementsFlag = true;
02037 
02038             if( CdbStatus::Success !=  findMetaData( vectorOfMdPtrs,
02039                                                      _masterRegistryPtr,
02040                                                      _localRegistryPtr,
02041                                                      _extendedConditionId,
02042                                                      _partitionId,
02043                                                      allIncrementsFlag )) {
02044                 cerr << errorStr << endl
02045                      << "    Failed to locate the MetaData objects for the current condition/partition." << endl;
02046                 break;
02047             }
02048 
02049             _md.clear( );
02050 
02051             for( std::vector< CdbCPtr< CdbRooRoMetaDataR > >::size_type i = 0; i < vectorOfMdPtrs.size( ); ++i ) {
02052 
02053                 CdbCPtr< CdbRooRoMetaDataR > mdPtr;
02054                 mdPtr = vectorOfMdPtrs[i];
02055 
02056                 if( _revisionId >= mdPtr->minInsertion( )) {
02057 
02058                   // Check for a separate case of the top element in the stack. Don't forget
02059                   // about a special case when we have the topmost revision since this require
02060                   // more relaxing check on the upper border of the MetaData object.
02061 
02062                     if((( BdbTime::plusInfinity == _revisionId ) && ( BdbTime::plusInfinity == mdPtr->maxInsertion( )))
02063                         ||
02064                         ( _revisionId < mdPtr->maxInsertion( ))) {
02065 
02066                       // Set up an iterator matching the revision.
02067 
02068                         CdbItr<CdbRooRoCi> itr;
02069                         if( CdbStatus::Success != mdPtr->objectIterator( itr,
02070                                                                          _revisionId,
02071                                                                          _beginConfig,
02072                                                                          _endConfig )) {
02073                             cerr << errorStr << endl
02074                                  << "    Failed to set up the iterator." << endl;
02075                             return false;
02076                         }
02077 
02078                       // Top element of the stack
02079 
02080                         _md.push_back( MD( mdPtr,
02081                                            itr,
02082                                            _revisionId,
02083                                            _beginConfig,
02084                                            _endConfig ));
02085 
02086                       // At the next step we'll be above specified revision.
02087 
02088                         break;
02089 
02090                     } else {
02091 
02092                       // This is a MetaData object below the top
02093 
02094                       // It will use the MetaData object's modification time
02095                       // time to set up the composite object iterator. We're not establishing
02096                       // this iterator now because we don't know yet which validity range
02097                       // we're going to use this iterator for. This range will be defined
02098                       // by a "hole" in a revision above. Setting up the iterator now would
02099                       // also be veru inefficient since we might never use it or we would need
02100                       // to skip many intervals in it due to ongoing development at above
02101                       // iterators.
02102 
02103                         BdbTime modified = mdPtr->modified( );
02104                         assert( BdbTime::plusInfinity != modified );
02105 
02106                         _md.push_back( MD( mdPtr,
02107                                            modified ));
02108                     }
02109 
02110                 } else {
02111 
02112                   // We're above specified revision.
02113 
02114                     break;
02115                 }
02116             }
02117             if( 0 == _md.size( )) {
02118                 cerr << errorStr << endl
02119                      << "    The database could be corrupted or be in an inconsistent state." << endl;
02120                 assert( 0 );
02121                 return false;
02122             }
02123             _mdCurrent = _md.size( ) - 1;
02124 
02125 /*****************************************************/
02126 if( CdbEnvironment::getDebugMode( ) != 0 )
02127     cout << debugStr << endl
02128          << "{" << endl
02129          << "    _mdCurrent = " << _mdCurrent << endl
02130          << "}" << endl;
02131 /*****************************************************/
02132 
02133           // Proceed down to the first element in the stack
02134 
02135             if( tryNextObject( )) return true;
02136         }
02137 
02138         return false;
02139     }
02140 
02141   /// An implementation class for the iterator of original objects
02142   /**
02143     * @see class CdbItr
02144     */
02145     class OriginalObjectIterator : public CdbObjectItr::InterfaceType {
02146 
02147     private:
02148 
02149         OriginalObjectIterator( );
02150 
02151         OriginalObjectIterator& operator=( const OriginalObjectIterator& theItr );
02152 
02153     protected:
02154 
02155         OriginalObjectIterator( const OriginalObjectIterator& theItr ) :
02156 
02157             _parent                  (theItr._parent),
02158             _begin                   (theItr._begin),
02159             _end                     (theItr._end),
02160             _masterRegistryPtr       (theItr._masterRegistryPtr),
02161             _localRegistryPtr        (theItr._localRegistryPtr),
02162             _extendedConditionId     (theItr._extendedConditionId),
02163             _partitionId             (theItr._partitionId),
02164             _isValid                 (theItr._isValid),
02165             _hasEverBeenAdvanced     (theItr._hasEverBeenAdvanced),
02166             _value                   (theItr._value),
02167             _md                      (theItr._md),
02168             _mdCurrent               (theItr._mdCurrent),
02169             _mdCurrentOiCollectionPtr(theItr._mdCurrentOiCollectionPtr),
02170             _mdCurrentOi             (theItr._mdCurrentOi)
02171         { }
02172 
02173     public:
02174 
02175         OriginalObjectIterator( const CdbConditionPtr&             theParentPtr,
02176                                 const BdbTime&                     theBegin,
02177                                 const BdbTime&                     theEnd,
02178                                 const CdbCPtr< CdbRooRoRegistry >& theMasterRegistryPtr,
02179                                 const CdbCPtr< CdbRooRoRegistry >& theLocalRegistryPtr,
02180                                 const CdbId&                       theExtendedConditionId,
02181                                 const UShort_t                     thePartitionId ) :
02182             _parent             (theParentPtr),
02183             _begin              (theBegin),
02184             _end                (theEnd),
02185             _masterRegistryPtr  (theMasterRegistryPtr),
02186             _localRegistryPtr   (theLocalRegistryPtr),
02187             _extendedConditionId(theExtendedConditionId),
02188             _partitionId        (thePartitionId),
02189             _isValid            (false),
02190             _hasEverBeenAdvanced(false)
02191         { }
02192 
02193         virtual ~OriginalObjectIterator( )
02194         { }
02195 
02196         virtual CdbStatus reset( )
02197         {
02198             _isValid             = false;
02199             _hasEverBeenAdvanced = false;
02200 
02201             return CdbStatus::Success;
02202         }
02203 
02204         bool tryNextMetaData( );
02205         bool tryNextObject( );
02206 
02207         virtual bool next( )
02208         {
02209             const char* errorStr = "CdbRooRoCondition::OriginalObjectIterator::next() -- ERROR";
02210 
02211             if( _hasEverBeenAdvanced ) {
02212                 if( ! _isValid ) {
02213 
02214                   // Stay at BEYOND_PAST_ELEMENT state
02215 
02216                     ;
02217 
02218                 } else {
02219 
02220                   // Try to get next object...
02221 
02222                     _isValid = tryNextObject( );
02223                 }
02224 
02225             } else {
02226 
02227                 _hasEverBeenAdvanced = true;
02228 
02229               // Set up initial context of the iterator. Then proceed down
02230               // to the first object of the collection starting from the configuration.
02231 
02232                 bool allIncrementsFlag = true;
02233 
02234                 if( CdbStatus::Success !=  ::findMetaData( _md,
02235                                                            _masterRegistryPtr,
02236                                                            _localRegistryPtr,
02237                                                            _extendedConditionId,
02238                                                            _partitionId,
02239                                                            allIncrementsFlag )) {
02240                     cerr << errorStr << endl
02241                          << "    Failed to locate the MetaData objects for the current condition/partition." << endl;
02242 
02243                      _isValid = false;
02244 
02245                 } else {
02246 
02247                     _mdCurrent = 0;     // This is the very bottom increment to begin with.
02248 
02249                     _mdCurrentOiCollectionPtr = _md[_mdCurrent]->originalIntervalsCollection( );
02250 
02251                     _mdCurrentOi = 0;   // This number will _always_ get incremented by ::tryNextObject()
02252                                         // method. Therefore we're safe to put 0 (which is a special
02253                                         // index in the cllections of 'original' intervals) into here.
02254 
02255                     _isValid = tryNextObject( );
02256                 }
02257             }
02258             return _isValid;
02259         }
02260 
02261         virtual ValueType value( )
02262         {
02263             if( ! _isValid ) {
02264                 assert( 0 );
02265             }
02266             return _value;
02267         }
02268 
02269         virtual bool isValid( )
02270         {
02271             return _isValid;
02272         }
02273 
02274         virtual InterfaceType* clone( ) const
02275         {
02276             return new OriginalObjectIterator( *this );
02277         }
02278 
02279     private:
02280 
02281       // Parameters
02282 
02283         CdbConditionPtr _parent;
02284 
02285         BdbTime _begin;
02286         BdbTime _end;
02287 
02288         CdbCPtr< CdbRooRoRegistry > _masterRegistryPtr;
02289         CdbCPtr< CdbRooRoRegistry > _localRegistryPtr;
02290 
02291         CdbId _extendedConditionId;
02292 
02293         UShort_t _partitionId;
02294 
02295       // The current state
02296 
02297         bool _isValid;
02298         bool _hasEverBeenAdvanced;
02299 
02300         CdbObjectPtr _value;
02301 
02302       // The context : meta-data
02303 
02304         std::vector< CdbCPtr< CdbRooRoMetaDataR > >            _md;
02305         std::vector< CdbCPtr< CdbRooRoMetaDataR > >::size_type _mdCurrent;
02306 
02307       // Have this pointer for the sake of optimization when traversing intervals
02308       // within the same MetaData.
02309 
02310         CdbCPtr< CdbRooRoOiCollectionR > _mdCurrentOiCollectionPtr;
02311 
02312         UInt_t _mdCurrentOi;    // The current index of the original intyerval in
02313                                 // the corresponding collection of the current metadata object.
02314     };
02315 
02316     bool
02317     OriginalObjectIterator::tryNextMetaData( )
02318     {
02319       // Try to switch to another MetaData (if any)
02320 
02321         ++_mdCurrent;
02322         if( _mdCurrent >= _md.size( )) {
02323 
02324           // No more MetaData. We've reached the end.
02325 
02326             return false;
02327         }
02328 
02329       // Proceed to the next increment
02330 
02331         _mdCurrentOiCollectionPtr = _md[_mdCurrent]->originalIntervalsCollection( );
02332         _mdCurrentOi = 0;
02333 
02334         return tryNextObject( );    // This number will _always_ get incremented by ::tryNextObject()
02335                                     // method. Therefore we're safe to put 0 (which is a special
02336                                     // index in the cllections of 'original' intervals) into here.
02337     }
02338 
02339     bool
02340     OriginalObjectIterator::tryNextObject( )
02341     {
02342         const char* errorStr = "CdbRooRoCondition::OriginalObjectIterator::tryNextObject() -- ERROR";
02343 
02344         assert( _md.size( ) > 0 );
02345         assert( _mdCurrent < _md.size( ));
02346         assert( !_mdCurrentOiCollectionPtr.isNull( ));
02347         assert( _mdCurrentOi < _mdCurrentOiCollectionPtr->size( ));
02348 
02349       // Try to look for the next interval in the current MetaData or proceed
02350       // to the next one if the current one got exausted.
02351 
02352         ++_mdCurrentOi;
02353         if( _mdCurrentOi >= _mdCurrentOiCollectionPtr->size( )) return tryNextMetaData( );
02354 
02355       // Get the next 'original' interval and its 'duration' in the 'insertion' time dimension
02356       // then check if this interval falls into the specified 'duration' window.
02357       // If not then proceed to the next interval till an appropriate one would be found
02358       // or we'll run out of available MetaData.
02359       //
02360       // NOTE: The algorithm used below is just partially recursive. It uses plain cycle
02361       //       when iterating over intervals within the same MetaData and it uses
02362       //       recursive calls to switch to another MetaData. This's done for the sake
02363       //       of optimization.
02364 
02365         CdbRooRoOiR oi;
02366 
02367         BdbTime beginDuration;
02368         BdbTime endDuration;
02369 
02370         do {
02371 
02372             if( CdbStatus::Success != _mdCurrentOiCollectionPtr->find( _mdCurrentOi,
02373                                                                        oi,
02374                                                                        beginDuration,
02375                                                                        endDuration )) {
02376                 cerr << errorStr << endl
02377                      << "    Failed to obtain the next 'original' interval from the current MetaData." << endl;
02378                 return false;
02379             }
02380             if(( _begin <= oi.inserted( )) && ( oi.inserted( ) < _end )) {
02381 
02382               // We've found the right interval. Proceed to form the result.
02383 
02384                 break;
02385             }
02386 
02387           // Try to look for the next interval in the current MetaData or proceed
02388           // to the next one if the current one got exausted.
02389 
02390             ++_mdCurrentOi;
02391             if( _mdCurrentOi >= _mdCurrentOiCollectionPtr->size( )) return tryNextMetaData( );
02392 
02393         } while( true );
02394 
02395       // Finally, convert this information into a technology & implementation transparent object.
02396 
02397         _value = new CdbRooRoObject( _parent,
02398                                      oi.begin( ),       // begin of "original" period
02399                                      oi.end( ),         // end   of "original" period
02400                                      oi.begin( ),       // begin of "visible" period (same as "original" in this context)
02401                                      oi.end( ),         // end   of "visible" period (same as "original" in this context)
02402                                      beginDuration,     // begin of "duration" period
02403                                      endDuration,       // end   of "duration" period
02404                                      oi.inserted( ),
02405                                      oi.object( ),
02406                                      oi.legacyObjectAddress( ));
02407         return true;
02408     }
02409 
02410   ////////////////////////////////////
02411   // End Of The Anonymous Namespace //
02412   ////////////////////////////////////
02413 }
02414 
02415 CdbCondition*
02416 CdbRooRoCondition::clone( ) const
02417 {
02418     return new CdbRooRoCondition( *this );
02419 }
02420 
02421 CdbRooRoCondition::CdbRooRoCondition( const CdbFolderPtr&                  theFolderPtr,
02422                                       const CdbDatabasePtr&                theDatabasePtr,
02423                                       const char*                          theName,
02424                                       const CdbId&                         thePhysicalAddress,
02425                                       CdbRooRoConditionAtFolderR*          thePersistentConditionAtFolderPtr,
02426                                       const CdbCPtr< CdbRooRoConditionR >& thePersistentConditionPtr,
02427                                       const CdbCPtr< CdbRooRoRegistry >&   theMasterRegistryPtr,
02428                                       const CdbCPtr< CdbRooRoRegistry >&   theLocalRegistryPtr ) :
02429     CdbCondition( theFolderPtr,
02430                   theDatabasePtr,
02431                   theName ),
02432     _physicalAddress               (thePhysicalAddress),
02433     _persistentConditionAtFolderPtr(thePersistentConditionAtFolderPtr),
02434     _persistentConditionPtr        (thePersistentConditionPtr),
02435     _masterRegistryPtr             (theMasterRegistryPtr),
02436     _localRegistryPtr              (theLocalRegistryPtr)
02437 { }
02438 
02439 CdbRooRoCondition::CdbRooRoCondition( const CdbRooRoCondition& theCondition ) :
02440     CdbCondition( theCondition ),
02441     _physicalAddress               (theCondition._physicalAddress),
02442     _persistentConditionAtFolderPtr(theCondition._persistentConditionAtFolderPtr),
02443     _persistentConditionPtr        (theCondition._persistentConditionPtr),
02444     _masterRegistryPtr             (theCondition._masterRegistryPtr),
02445     _localRegistryPtr              (theCondition._localRegistryPtr)
02446 { }
02447 
02448 CdbRooRoCondition::~CdbRooRoCondition( )
02449 { }
02450 
02451 std::string
02452 CdbRooRoCondition::description( ) const
02453 {
02454     if( 0 == _persistentConditionAtFolderPtr ) return _persistentConditionPtr->description( );
02455     return _persistentConditionAtFolderPtr->description( );
02456 }
02457 
02458 bool
02459 CdbRooRoCondition::isPartitionable( ) const
02460 {
02461     return _persistentConditionPtr->isPartitionable( );
02462 }
02463 
02464 CdbCompositeName
02465 CdbRooRoCondition::physicalName( ) const
02466 {
02467     const char* errorStr = "CdbRooRoCondition::physicalName() -- ERROR.";
02468 
02469   // Get to the origin first by its identifier. We need it to get the name
02470   // of the origin.
02471 
02472     CdbCPtr< CdbRooRoOriginR > persistentOriginPtr;
02473 
02474     if( CdbStatus::Success != _masterRegistryPtr->originCollection( )->find( _physicalAddress.origin,
02475                                                                              persistentOriginPtr )) {
02476         cerr << errorStr << endl
02477              << "    Failed to obtain a persistent object describing the 'origin' for" << endl
02478              << "    the following ID=" << _physicalAddress.origin << endl;
02479 
02480         return CdbCompositeName( ); // object in the "non-valid" state
02481     }
02482 
02483   // Construct a valid object
02484 
02485     return  CdbCompositeName( persistentOriginPtr->name( ).c_str( ),
02486                               _persistentConditionPtr->name( ).c_str( ));
02487 
02488 }
02489 
02490 CdbId
02491 CdbRooRoCondition::physicalId( ) const
02492 {
02493     return _physicalAddress;
02494 }
02495 
02496 BdbTime
02497 CdbRooRoCondition::created( ) const
02498 {
02499     return _persistentConditionPtr->created( );
02500 }
02501 
02502 BdbTime
02503 CdbRooRoCondition::registered( ) const
02504 {
02505     if( 0 == _persistentConditionAtFolderPtr ) return _persistentConditionPtr->created( );
02506     return _persistentConditionAtFolderPtr->created( );
02507 }
02508 
02509 BdbTime
02510 CdbRooRoCondition::modified( ) const
02511 {
02512     const char* errorStr = "CdbRooRoCondition::modified() -- ERROR";
02513 
02514   // CONTRACT NOTE:
02515   //
02516   //    The method will always return "BdbTime::minusInfinity" in case of any failure
02517   //    to calculate the modification time.
02518 
02519     BdbTime defaultResultInCaseOfFailure = BdbTime::minusInfinity;
02520 
02521   /*
02522    * =================
02523    * EXECUTION PATH I: 'physical address' conditions only
02524    * =================
02525    *
02526    * This path is not currently implemented. A complicated algorithm to iterate
02527    * over a validity timeline of the "topmost" partitions would be needed for
02528    * PARTITIONABLE conditions. Things are trivial for REGULAR conditions though.
02529    * However to avoid an incomplete implementation of this part of the code let's just
02530    * postpone it as a whole.
02531    *
02532    * AN IDEA: Having a super-iterator composed of elementary iterators for individual
02533    *          "topmost" partitions would be a good idea. That would require to extend
02534    *          the API of P-Layout to deliver an iterator of "topmost" partitions. The
02535    *          one currently available does not respect non-instantiated partitions.
02536    */
02537 
02538     if( 0 == _persistentConditionAtFolderPtr ) return defaultResultInCaseOfFailure;
02539 
02540   /*
02541    * ==================
02542    * EXECUTION PATH II: 'view/folder/config' conditions only
02543    * ==================
02544    */
02545 
02546     BdbTime modificationTime = defaultResultInCaseOfFailure;
02547     {
02548 
02549       // Use the specific configuration of the condition.
02550 
02551         const CdbRooRoConfigCollectionR* configCollPtr = _persistentConditionAtFolderPtr->config( );
02552         if( 0 == configCollPtr ) {
02553 
02554             cerr << errorStr << endl
02555                  << "    The current condition has no configuration in the default view." << endl
02556                  << "    The application may be misconfigured." << endl
02557                  << "    The condition name is \"" << name( ) << "\"" << endl;
02558 
02559             return defaultResultInCaseOfFailure;
02560         }
02561 
02562       // Iterate through the configuration intervals to determine the result.
02563 
02564         CdbRooRoConfigCollectionR::IteratorOfIntervals itr = configCollPtr->iterator( );
02565         while( itr.next( )) {
02566 
02567             CdbRooRoConfigInterval configInterval = itr.value( );
02568             CdbRooRoConfigElementR configElement  = configInterval.value( );
02569 
02570           // Skeep the found element if it tells us that the corresponding range of the validity
02571           // timeline is not accessible for the current application.
02572 
02573             if( !configElement.accessIsAllowed( )) continue;
02574 
02575           // If we're supposed to use revisions and if this is not the 'topmost' one
02576           // then then we use that revision ID as the modification time.
02577 
02578             BdbTime cModificationTime = BdbTime::minusInfinity;
02579             if( configElement.useRevision( ) && ( BdbTime::plusInfinity != configElement.revision( ))) {
02580                 cModificationTime = configElement.revision( );
02581             } else {
02582 
02583               // Otherwise we use the modification time of the most recent Meta-Data object.
02584 
02585                 std::vector< CdbCPtr< CdbRooRoMetaDataR > > mdPtrs;
02586 
02587                 bool allIncrementsFlag   = false;
02588                 bool recentIncrementFlag = true;
02589 
02590                 if( CdbStatus::Success != findMetaData( mdPtrs,
02591                                                         _masterRegistryPtr,
02592                                                         _localRegistryPtr,
02593                                                         _physicalAddress,
02594                                                         configElement.partition( ),
02595                                                         allIncrementsFlag,
02596                                                         recentIncrementFlag )) {
02597                     cerr << errorStr << endl
02598                          << "    Failed to find the most recent MetaData objects for the current condition." << endl
02599                          << "    The database may not be properly initialized/loaded." << endl
02600                          << "    The condition name is \"" << name( ) << "\"" << endl;
02601 
02602                     return defaultResultInCaseOfFailure;
02603                 }
02604                 assert( 1 == mdPtrs.size( ));
02605 
02606                 cModificationTime = mdPtrs[0]->modified( );
02607             }
02608             assert( BdbTime::minusInfinity != cModificationTime );
02609             assert( BdbTime::plusInfinity  != cModificationTime );
02610 
02611           // Check if the found time is newer than the one we have now.
02612 
02613             if( cModificationTime > modificationTime ) modificationTime = cModificationTime;
02614         }
02615     }
02616     return modificationTime;
02617 }
02618 
02619 CdbStatus
02620 CdbRooRoCondition::findObject( CdbObjectPtr&  theObjectPtr,
02621                                const BdbTime& theValidityTime,
02622                                const BdbTime& theInsertionTime )
02623 {
02624     const char* errorStr = "CdbRooRoCondition::findObject() -- ERROR";
02625 
02626   /*
02627    * =================
02628    * EXECUTION PATH I: 'physical address' conditions only
02629    * =================
02630    *
02631    * If the condition is available by its 'physical address' only
02632    * then we don't have any asociation with views & folders, therefore no such things
02633    * as condition configurations are available. The "insertion" time will play a role
02634    * of the secondary (in addition to the validity time) key. Here are the rules
02635    * for different values of the insertion time and condition types
02636    *
02637    *   o if the insertion time is +Infinity then:
02638    *
02639    *     REGULAR       : the TOPMOST revision will always be used
02640    *
02641    *     PARTITIONABLE : the most recent revision of the "topmost" (at given validity time)
02642    *                     partition will be used. In case if this is an "open" partition
02643    *                     then its TOPMOST revision will be used.
02644    *
02645    *   o for any other values of the insertion time:
02646    *
02647    *     REGULAR       : the specified insertion time would be used
02648    *
02649    *     PARTITIONABLE : the specified insertion time would be used
02650    */
02651 
02652     if( 0 == _persistentConditionAtFolderPtr ) {
02653 
02654       // The default constructor of the policy would assume that we're going
02655       // to use the actual insertion time rather than any explicitly found revision.
02656 
02657         CdbRevisionPolicy rPolicy;
02658 
02659         if( BdbTime::plusInfinity == theInsertionTime ) {
02660 
02661           // Okay, we need to find the most recent partition & revision
02662 
02663             if( _persistentConditionPtr->isPartitionable( )) {
02664 
02665               // Find an appropriate partition for the specified validity and insertion
02666               // timestamps.
02667               //
02668               // @see CdbRooRoCondition::findInitialPartition()
02669 
02670                 UShort_t partitionId = 0;
02671                 {
02672                     CdbCPtr< CdbRooRoPartitionR > persistentPartitionPtr;
02673 
02674                     if( CdbStatus::Success != findInitialPartition( theValidityTime,
02675                                                                     theInsertionTime,
02676                                                                     persistentPartitionPtr )) {
02677                         cerr << errorStr << endl
02678                              << "    Failed to find an initial partition for the specified validity and insertion" << endl
02679                              << "    for a condition found by its 'physical address'." << endl
02680                              << "        PHYSICAL CONDITION ADDRESS : " << _physicalAddress << endl
02681                              << "        VALIDITY TIME              : " << CdbTimeUtils::time2string( theValidityTime )  << " : " << theValidityTime  << endl
02682                              << "        INSERTION TIME             : " << CdbTimeUtils::time2string( theInsertionTime ) << " : " << theInsertionTime << endl;
02683 
02684                         return CdbStatus::Error;
02685                     }
02686                     partitionId = persistentPartitionPtr->id( );
02687                 }
02688 
02689               // Find the most recent (can be "<topmost>" if the partition is in the "open"
02690               // state) revision in the partition.
02691               //
02692               // NOTE: The default value for the revision is -Infinity, which we'll
02693               //       also use as a flag indicationg whether any revision is found
02694               //       or not.
02695 
02696                 BdbTime rId = BdbTime::minusInfinity;
02697                 {
02698                    // Find the most recent metadata object for the specified condition/partition
02699 
02700                     std::vector< CdbCPtr< CdbRooRoMetaDataR > > vectorOfMdPtrs;
02701 
02702                     bool allIncrementsFlag   = false;
02703                     bool recentIncrementFlag = true;
02704 
02705 
02706                     if( CdbStatus::Success != findMetaData( vectorOfMdPtrs,
02707                                                             _masterRegistryPtr,
02708                                                             _localRegistryPtr,
02709                                                             _physicalAddress,
02710                                                             partitionId,
02711                                                             allIncrementsFlag,
02712                                                             recentIncrementFlag )) {
02713                         cerr << errorStr << endl
02714                              << "    Failed to locate the most recent MetaData objects for" << endl
02715                              << "    the current condition/partition." << endl
02716                              << "        PARTITION                  : " << partitionId << endl
02717                              << "        PHYSICAL CONDITION ADDRESS : " << _physicalAddress << endl
02718                              << "        VALIDITY TIME              : " << CdbTimeUtils::time2string( theValidityTime )  << " : " << theValidityTime  << endl
02719                              << "        INSERTION TIME             : " << CdbTimeUtils::time2string( theInsertionTime ) << " : " << theInsertionTime << endl;
02720 
02721                         return CdbStatus::Error;
02722                     }
02723 
02724                   // Make sure just one metadata found. If not then something is broken
02725                   // in the current implementation.
02726 
02727                     assert( 1 == vectorOfMdPtrs.size( ));
02728 
02729                   // Find the most recent revision
02730 
02731                     CdbCPtr< CdbRooRoMetaDataR > mdPtr = vectorOfMdPtrs[0];
02732 
02733                     CdbItr<BdbTime> rItr;
02734 
02735                     if( CdbStatus::Success != mdPtr->revisionIdIterator( rItr )) {
02736 
02737                         cerr << errorStr << endl
02738                              << "    Failed to setup an iterator of revision identifiers in" << endl
02739                              << "    the most recent MetaData objects for the current condition/partition." << endl
02740                              << "        PARTITION                  : " << partitionId << endl
02741                              << "        PHYSICAL CONDITION ADDRESS : " << _physicalAddress << endl
02742                              << "        VALIDITY TIME              : " << CdbTimeUtils::time2string( theValidityTime )  << " : " << theValidityTime  << endl
02743                              << "        INSERTION TIME             : " << CdbTimeUtils::time2string( theInsertionTime ) << " : " << theInsertionTime << endl;
02744 
02745                         return CdbStatus::Error;
02746                     }
02747                     while( rItr.next( )) {
02748                         if( rItr.value( ) > rId ) {
02749                             rId = rItr.value( );
02750                         }
02751                     }
02752 
02753                   // Make sure we've found what we wanted to find. If not then something
02754                   // is broken in persistent data structures. So we don't even bother to complain
02755                   // in verbose form.
02756 
02757                     assert( BdbTime::minusInfinity != rId );
02758                 }
02759 
02760             } else {
02761 
02762               // Just use TOPMOST revision for REGULAR conditions.
02763 
02764                 rPolicy = CdbRevisionPolicy( BdbTime::plusInfinity, 0 );
02765             }
02766         }
02767 
02768       // Proceed with the policy driven search.
02769 
02770         return findObject( theObjectPtr,
02771                            rPolicy,
02772                            theValidityTime,
02773                            theInsertionTime );
02774     }
02775 
02776   /*
02777    * ==================
02778    * EXECUTION PATH II: 'view/folder/config' conditions only
02779    * ==================
02780    */
02781 
02782     CDB_DEBUG_STREAM
02783         << "CDB_FIND_OBJECT_1: condition=" << name( )
02784         << " validity_time=" << CdbTimeUtils::time2string( theValidityTime )
02785         << " insertion_time=" << CdbTimeUtils::time2string( theInsertionTime ) << endl;
02786 
02787     theObjectPtr = 0;
02788 
02789     CdbRooRoObjectIdR foundObjectId;
02790     CdbStatus         result = CdbStatus::Error;
02791     do {
02792 
02793       // Check if specified validity time is covered by the validity
02794       // interval of the current view.
02795 
02796         if(( theValidityTime <  parent( )->parentView( )->minValidity( )) ||
02797            ( theValidityTime >= parent( )->parentView( )->maxValidity( ))) {
02798 
02799             cerr << errorStr << endl
02800                  << "    Specified validity time does not fit into the validity range" << endl
02801                  << "    of the current view." << endl
02802                  << "        VIEW NAME:   \"" << parent( )->parentView( )->name( ) << "\"" << endl
02803                  << "        PASSED TIME: " << CdbTimeUtils::time2string( theValidityTime ) << " : " << theValidityTime << endl;
02804             break;
02805         }
02806 
02807       // For the specified validity time, find a configuration element which would tell
02808       // us how we're going to proceed with a further interval mining.
02809       //
02810       // NOTE: That we're using the default view the current application
02811       //       is configured with.
02812       //
02813       // ROOT I/O IMPLEMENTATION NOTE:
02814       //
02815       //    The persistentcy specific configuration element/interval
02816       //    has been replacd with technology neutral way of finding the default configuration.
02817       //    This needs to be tested well before deploying! Otherwise it's safer to revert back
02818       //    to the original approach.
02819 
02820         CdbConfigElement configElement;
02821         if( CdbStatus::Success != parent( )->parentView( )->get( ::fullPathName( this ).c_str( ),
02822                                                                  theValidityTime,
02823                                                                  configElement )) {
02824             cerr << errorStr << endl
02825                  << "    Failed to find the configuration element for specified validity time" << endl
02826                  << "    at the condition description of the  the current view." << endl
02827                  << "    The view may be inproperly configured." << endl
02828                  << "        PASSED TIME:    " << CdbTimeUtils::time2string( theValidityTime ) << " : " << theValidityTime << endl
02829                  << "        CONDITION NAME: \"" << name( ) << "\"" << endl
02830                  << "        VIEW NAME:      \"" << parent( )->parentView( )->name( ) << "\"" << endl;
02831             break;
02832         }
02833         if( !configElement.accessIsAllowed ) {
02834             cerr << errorStr << endl
02835                  << "    The current view prohibits accessing conditions at specified" << endl
02836                  << "    point of the validity timeline." << endl
02837                  << "        VIEW NAME:   \"" << parent( )->parentView( )->name( ) << "\"" << endl
02838                  << "        PASSED TIME: " << CdbTimeUtils::time2string( theValidityTime ) << " : " << theValidityTime << endl;
02839             break;
02840         }
02841 
02842       // Given the found policy, propagate the call down to the next
02843       // method requiring explicit policy to be specified among
02844       // the method's parameters.
02845 
02846         CdbRooRoOiR originalInterval;
02847 
02848         BdbTime beginOfVisiblePeriod ( 0 );
02849         BdbTime endOfVisiblePeriod   ( 0 );
02850         BdbTime beginOfDurationPeriod( 0 );
02851         BdbTime endOfDurationPeriod  ( 0 );
02852 
02853         if( _persistentConditionPtr->isPartitionable( )) {
02854 
02855             if( CdbStatus::Success != doFindObjectAtPartition( configElement.policy,
02856                                                                theValidityTime,
02857                                                                theInsertionTime,
02858                                                                originalInterval, 
02859                                                                beginOfVisiblePeriod,
02860                                                                endOfVisiblePeriod,
02861                                                                beginOfDurationPeriod,
02862                                                                endOfDurationPeriod )) break;
02863         } else {
02864 
02865             if( CdbStatus::Success != doFindObject( configElement.policy,
02866                                                     theValidityTime,
02867                                                     theInsertionTime,
02868                                                     originalInterval, 
02869                                                     beginOfVisiblePeriod,
02870                                                     endOfVisiblePeriod,
02871                                                     beginOfDurationPeriod,
02872                                                     endOfDurationPeriod )) break;
02873         }
02874 
02875       // Now we should check if the found visible validity interval must be
02876       // narrowed down to the limits enforced by the current policy interval.
02877 
02878         if( configElement.begin > beginOfVisiblePeriod ) beginOfVisiblePeriod = configElement.begin;
02879         if( configElement.end   < endOfVisiblePeriod   ) endOfVisiblePeriod   = configElement.end;
02880 
02881       // Create a transient object through the creator factory.
02882       //
02883       // DESIGN NOTE: We need to construct a smart pointer against a clone since
02884       //              we don't know a smart pointer pointing to the current
02885       //              instance, therefore we can't guarantee the lifetime
02886       //              of the current instance.
02887 
02888         theObjectPtr = new CdbRooRoObject( CdbConditionPtr( this->clone( )),
02889                                            originalInterval.begin( ),
02890                                            originalInterval.end( ),
02891                                            beginOfVisiblePeriod,
02892                                            endOfVisiblePeriod,
02893                                            beginOfDurationPeriod,
02894                                            endOfDurationPeriod,
02895                                            originalInterval.inserted( ),
02896                                            originalInterval.object( ),
02897                                            originalInterval.legacyObjectAddress( ));
02898 
02899      // Done
02900 
02901        foundObjectId = originalInterval.object( );
02902        result        = CdbStatus::Success;
02903 
02904     } while( false );
02905 
02906     CDB_DEBUG_STREAM << "CDB_FIND_OBJECT_1: " << foundObjectId << endl;
02907 
02908     return result;
02909 }
02910 
02911 CdbStatus
02912 CdbRooRoCondition::findObject( CdbObjectPtr&            theObjectPtr,
02913                                const CdbRevisionPolicy& thePolicy,
02914                                const BdbTime&           theValidityTime,
02915                                const BdbTime&           theInsertionTime )
02916 {
02917     theObjectPtr = 0;
02918 
02919     CDB_DEBUG_STREAM
02920         << "CDB_FIND_OBJECT_2: condition=" << name( ) 
02921         << " validity_time=" << CdbTimeUtils::time2string( theValidityTime ) 
02922         << " insertion_time=" << CdbTimeUtils::time2string( theInsertionTime ) << endl;
02923 
02924     CdbRooRoObjectIdR foundObjectId;
02925     CdbStatus         result = CdbStatus::Error;
02926     do {
02927 
02928       // Given the found policy, propagate the call down to the next
02929       // method requiring explicit policy to be specified among
02930       // the method's parameters.
02931 
02932         CdbRooRoOiR originalInterval;
02933 
02934         BdbTime beginOfVisiblePeriod ( 0 );
02935         BdbTime endOfVisiblePeriod   ( 0 );
02936         BdbTime beginOfDurationPeriod( 0 );
02937         BdbTime endOfDurationPeriod  ( 0 );
02938 
02939         if( _persistentConditionPtr->isPartitionable( )) {
02940 
02941             if( CdbStatus::Success != doFindObjectAtPartition( thePolicy,
02942                                                                theValidityTime,
02943                                                                theInsertionTime,
02944                                                                originalInterval, 
02945                                                                beginOfVisiblePeriod,
02946                                                                endOfVisiblePeriod,
02947                                                                beginOfDurationPeriod,
02948                                                                endOfDurationPeriod )) break;
02949         } else {
02950 
02951             if( CdbStatus::Success != doFindObject( thePolicy,
02952                                                     theValidityTime,
02953                                                     theInsertionTime,
02954                                                     originalInterval, 
02955                                                     beginOfVisiblePeriod,
02956                                                     endOfVisiblePeriod,
02957                                                     beginOfDurationPeriod,
02958                                                     endOfDurationPeriod )) break;
02959         }
02960 
02961       // Create a transient object through the creator factory.
02962       //
02963       // DESIGN NOTE: We need to construct a smart pointer against a clone since
02964       //              we don't know a smart pointer pointing to the current
02965       //              instance, therefore we can't guarantee the lifetime
02966       //              of the current instance.
02967 
02968         theObjectPtr = new CdbRooRoObject( CdbConditionPtr( this->clone( )),
02969                                            originalInterval.begin( ),
02970                                            originalInterval.end( ),
02971                                            beginOfVisiblePeriod,
02972                                            endOfVisiblePeriod,
02973                                            beginOfDurationPeriod,
02974                                            endOfDurationPeriod,
02975                                            originalInterval.inserted( ),
02976                                            originalInterval.object( ),
02977                                            originalInterval.legacyObjectAddress( ));
02978 
02979      // Done
02980  
02981        foundObjectId = originalInterval.object( );
02982        result        = CdbStatus::Success;
02983  
02984     } while( false );
02985  
02986     CDB_DEBUG_STREAM << "CDB_FIND_OBJECT_2: " << foundObjectId << endl; 
02987 
02988     return result;
02989 }
02990 
02991 CdbStatus
02992 CdbRooRoCondition::objectIterator( CdbObjectItr&  theItr,
02993                                    const BdbTime& theBeginValidity,
02994                                    const BdbTime& theEndValidity )
02995 {
02996     const char* errorStr = "CdbRooRoCondition::objectIterator() -- ERROR";
02997 
02998   /*
02999    * =================
03000    * EXECUTION PATH I: 'physical address' conditions only
03001    * =================
03002    *
03003    * This path is not currently implemented. A complicated algorithm to iterate
03004    * over a validity timeline of the "topmost" partitions would be needed for
03005    * PARTITIONABLE conditions. Things are trivial for REGULAR conditions though.
03006    * However to avoid an incomplete implementation of this part of the code let's just
03007    * postpone it as a whole.
03008    *
03009    * AN IDEA: Having a super-iterator composed of elementary iterators for individual
03010    *          "topmost" partitions would be a good idea. That would require to extend
03011    *          the API of P-Layout to deliver an iterator of "topmost" partitions. The
03012    *          one currently available does not respect non-instantiated partitions.
03013    */
03014 
03015     if( 0 == _persistentConditionAtFolderPtr ) return CdbStatus::NotImplemented;
03016 
03017   /*
03018    * ==================
03019    * EXECUTION PATH II: 'view/folder/config' conditions only
03020    * ==================
03021    */
03022 
03023     CdbStatus result = CdbStatus::NotFound;
03024     do {
03025 
03026       // Verify parameters
03027 
03028         if( theEndValidity <= theBeginValidity ) {
03029             cerr << errorStr << endl
03030                  << "    Invalid validity interval range passed to the method." << endl
03031                  << "    The end time should be greater or equal than the begin one." << endl
03032                  << "        PASSED BEGIN TIME : " << theBeginValidity << endl
03033                  << "        PASSED END   TIME : " << theEndValidity << endl
03034                  << "        CONDITION         : \"" << name( ) << "\"" << endl;
03035             break;
03036         }
03037 
03038         BdbTime minValidity = parent( )->parentView( )->minValidity( );
03039         BdbTime maxValidity = parent( )->parentView( )->maxValidity( );
03040 
03041         if(( theBeginValidity >= maxValidity ) || ( theEndValidity <= minValidity )) {
03042             cerr << errorStr << endl
03043                  << "    Invalid validity interval range passed to the method." << endl
03044                  << "    This interval does not fit into the validity range" << endl
03045                  << "    allowed by the current view." << endl
03046                  << "        PASSED BEGIN TIME : " << theBeginValidity << endl
03047                  << "        PASSED END   TIME : " << theEndValidity << endl
03048                  << "        VIEW'S BEGIN TIME : " << minValidity << endl
03049                  << "        VIEW'S END   TIME : " << maxValidity << endl
03050                  << "        VIEW              : \"" << parent( )->parentView( )->name( ) << "\"" << endl
03051                  << "        CONDITION         : \"" << name( ) << "\"" << endl;
03052             break;
03053         }
03054 
03055       // Find an iterator for the right configuration. This is going to be either specific one
03056       // at the level of the condition, or the default one at the level of the view.
03057       //
03058       // NOTE: That we're using the default view the current application
03059       //       is configured with.
03060       //
03061       // ROOT I/O IMPLEMENTATION NOTE:
03062       //
03063       //    The persistentcy specific configuration
03064       //    has been replacd with technology neutral way of finding the default configuration.
03065       //    This needs to be tested well before deploying! Otherwise it's safer to revert back
03066       //    to the original approach.
03067 
03068         CdbItr<CdbConfigElement> configItr;
03069         if( CdbStatus::Success != parent( )->parentView( )->configIterator( ::fullPathName( this ).c_str( ),
03070                                                                             configItr )) {
03071             cerr << errorStr << endl
03072                  << "    Failed to find the configuration iterator" << endl
03073                  << "    at the condition description of the  the current view." << endl
03074                  << "    The view may be inproperly configured." << endl
03075                  << "        CONDITION NAME: \"" << name( ) << "\"" << endl
03076                  << "        VIEW NAME:      \"" << parent( )->parentView( )->name( ) << "\"" << endl;
03077             break;
03078         }
03079 
03080       // Now pick up the right iterator and let it to do the rest...
03081 
03082         if( _persistentConditionPtr->isPartitionable( )) {
03083 
03084           // ATTENTION: This is not a memory leak - the created object
03085           //            will be destroyed by the iterator.
03086 
03087             theItr = CdbObjectItr( new PartitionableObjectIterator( CdbConditionPtr( this->clone( )),
03088                                                                     theBeginValidity,
03089                                                                     theEndValidity,
03090                                                                     configItr,
03091                                                                     _masterRegistryPtr,
03092                                                                     _localRegistryPtr,
03093                                                                     _physicalAddress,
03094                                                                     _persistentConditionPtr->created( )));
03095         } else {
03096 
03097           // ATTENTION: This is not a memory leak - the created object
03098           //            will be destroyed by the iterator.
03099 
03100             theItr = CdbObjectItr( new RegularObjectIterator( CdbConditionPtr( this->clone( )),
03101                                                               theBeginValidity,
03102                                                               theEndValidity,
03103                                                               configItr,
03104                                                               _masterRegistryPtr,
03105                                                               _localRegistryPtr,
03106                                                               _physicalAddress));
03107         }
03108 
03109       // Done
03110  
03111        result = CdbStatus::Success;
03112  
03113     } while( false );
03114 
03115     return result;
03116 }
03117 
03118 CdbStatus
03119 CdbRooRoCondition::objectIterator( CdbObjectItr&            theItr,
03120                                    const CdbRevisionPolicy& thePolicy,
03121                                    const BdbTime&           theBeginValidity,
03122                                    const BdbTime&           theEndValidity )
03123 {
03124     const char* errorStr = "CdbRooRoCondition::objectIterator(by policy) -- ERROR";
03125 
03126     CdbStatus result = CdbStatus::NotFound;
03127     do {
03128 
03129       // Verify parameters
03130 
03131         if( theEndValidity <= theBeginValidity ) {
03132             cerr << errorStr << endl
03133                  << "    Invalid validity interval range passed to the method." << endl
03134                  << "    The end time should be greater or equal than the begin one." << endl
03135                  << "        PASSED BEGIN TIME : " << theBeginValidity << endl
03136                  << "        PASSED END   TIME : " << theEndValidity << endl
03137                  << "        CONDITION         : \"" << name( ) << "\"" << endl;
03138             break;
03139         }
03140 
03141       // Prepare a special iterator to serve single configuration record
03142       //
03143       // ATTENTION: This is not a memory leak - the created object
03144       //            will be destroyed by the iterator.
03145 
03146         CdbItr<CdbConfigElement> configItr( new CdbRooRoSimpleConfigIterator( CdbConfigElement( thePolicy,
03147                                                                                                 theBeginValidity,
03148                                                                                                 theEndValidity )));
03149 
03150       // Now pick up the right iterator and let it to do the rest...
03151 
03152         if( _persistentConditionPtr->isPartitionable( )) {
03153 
03154           // ATTENTION: This is not a memory leak - the created object
03155           //            will be destroyed by the iterator.
03156 
03157             theItr = CdbObjectItr( new PartitionableObjectIterator( CdbConditionPtr( this->clone( )),
03158                                                                     theBeginValidity,
03159                                                                     theEndValidity,
03160                                                                     configItr,
03161                                                                     _masterRegistryPtr,
03162                                                                     _localRegistryPtr,
03163                                                                     _physicalAddress,
03164                                                                     _persistentConditionPtr->created( )));
03165         } else {
03166 
03167           // ATTENTION: This is not a memory leak - the created object
03168           //            will be destroyed by the iterator.
03169 
03170             theItr = CdbObjectItr( new RegularObjectIterator( CdbConditionPtr( this->clone( )),
03171                                                               theBeginValidity,
03172                                                               theEndValidity,
03173                                                               configItr,
03174                                                               _masterRegistryPtr,
03175                                                               _localRegistryPtr,
03176                                                               _physicalAddress ));
03177         }
03178 
03179       // Done
03180  
03181        result = CdbStatus::Success;
03182  
03183     } while( false );
03184 
03185     return result;
03186 }
03187 
03188 CdbStatus
03189 CdbRooRoCondition::originalObjectIterator( CdbObjectItr&        theItr,
03190                                            const BdbTime&       theBeginInsertion,
03191                                            const BdbTime&       theEndInsertion,
03192                                            const unsigned short thePartitionId )
03193 {
03194     const char* errorStr = "CdbRooRoCondition::originalObjectIterator() -- ERROR";
03195 
03196     CdbStatus result = CdbStatus::NotFound;
03197     do {
03198 
03199       // Verify parameters
03200 
03201         if( theBeginInsertion >= theEndInsertion ) {
03202             cerr << errorStr << endl
03203                  << "    Invalid 'insertion' interval range passed to the method." << endl
03204                  << "    The end time should be greater or equal than the begin one." << endl
03205                  << "        PASSED BEGIN TIME : " << theBeginInsertion << endl
03206                  << "        PASSED END   TIME : " << theEndInsertion << endl
03207                  << "        CONDITION         : \"" << name( ) << "\"" << endl;
03208             break;
03209         }
03210 
03211       // Now pick up the right iterator and let it to do the rest...
03212       //
03213       // ATTENTION: This is not a memory leak - the created object
03214       //            will be destroyed by the iterator.
03215 
03216         theItr = CdbObjectItr( new OriginalObjectIterator( CdbConditionPtr( this->clone( )),
03217                                                            theBeginInsertion,
03218                                                            theEndInsertion,
03219                                                            _masterRegistryPtr,
03220                                                            _localRegistryPtr,
03221                                                            _physicalAddress,
03222                                                            thePartitionId ));
03223 
03224       // Done
03225  
03226        result = CdbStatus::Success;
03227  
03228     } while( false );
03229 
03230     return result;
03231 }
03232 
03233 CdbStatus
03234 CdbRooRoCondition::storeObject( CdbObjectFactoryBase& theObjectFactory,
03235                                 const BdbTime&        theBegin,
03236                                 const BdbTime&        theEnd,
03237                                 CdbObjectPtr&         theObjectPtr )
03238 {
03239     return CdbStatus::NotImplemented;
03240 }
03241 
03242 CdbStatus
03243 CdbRooRoCondition::storeAndTruncateObject( CdbObjectFactoryBase& theObjectFactory,
03244                                            const BdbTime&        theStoreTime,
03245                                            const BdbTime&        theTruncateTime,
03246                                            CdbObjectPtr&         theObjectPtr )
03247 {
03248     return CdbStatus::NotImplemented;
03249 }
03250 
03251 CdbStatus
03252 CdbRooRoCondition::split( const BdbTime& theTime )
03253 {
03254     return CdbStatus::NotImplemented;
03255 }
03256 
03257 bool
03258 CdbRooRoCondition::isValid( )
03259 {
03260     return true;
03261 }
03262 
03263 bool
03264 CdbRooRoCondition::isOpen( )
03265 {
03266     return true;
03267 }
03268 
03269 CdbStatus
03270 CdbRooRoCondition::open( )
03271 {
03272     return CdbStatus::Success;
03273 }
03274 
03275 CdbStatus
03276 CdbRooRoCondition::close( )
03277 {
03278     return CdbStatus::Success;
03279 }
03280 
03281 CdbStatus
03282 CdbRooRoCondition::findRevision( CdbRevisionPtr& thePtr,
03283                                  const BdbTime&  theId,
03284                                  unsigned short  thePartitionId )
03285 {
03286     const char* errorStr = "CdbRooRoCondition::findRevision(id) -- ERROR";
03287 
03288     CdbStatus result = CdbStatus::NotFound;
03289     do {
03290 
03291        // Find all metadata objects corresponding to current condition/partition.
03292 
03293         std::vector< CdbCPtr< CdbRooRoMetaDataR > > vectorOfMdPtrs;
03294 
03295         bool allIncrementsFlag = true;
03296 
03297         if( CdbStatus::Success !=  findMetaData( vectorOfMdPtrs,
03298                                                  _masterRegistryPtr,
03299                                                  _localRegistryPtr,
03300                                                  _physicalAddress,
03301                                                  thePartitionId,
03302                                                  allIncrementsFlag )) {
03303             cerr << errorStr << endl
03304                  << "    Failed to locate the MetaData objects for the current condition/partition." << endl;
03305             break;
03306         }
03307 
03308       // Find an appropriate one
03309 
03310         CdbCPtr< CdbRooRoRevisionR > persistentRevisionPtr;
03311         {
03312             bool found = false;
03313 
03314             std::vector< CdbCPtr< CdbRooRoMetaDataR > >::const_iterator itr;
03315             for( itr = vectorOfMdPtrs.begin( ); itr < vectorOfMdPtrs.end( ); ++itr ) {
03316 
03317                 CdbCPtr< CdbRooRoMetaDataR > mdPtr = (*itr);
03318                 if( CdbStatus::Success == mdPtr->findRevision( theId,
03319                                                                persistentRevisionPtr )) {
03320                     found = true;
03321                     break;
03322                 }
03323             }
03324             if( !found ) break;
03325         }
03326 
03327       // Construct the transient revision object.
03328       //
03329       // DESIGN NOTE: We need to construct a smart pointer against a clone since
03330       //              we don't know a smart pointer pointing to the current
03331       //              instance, therefore we can't guarantee the lifetime
03332       //              of the current instance.
03333 
03334         thePtr = new CdbRooRoRevision( CdbConditionPtr( this->clone( )),
03335                                        persistentRevisionPtr );
03336 
03337       // Done
03338 
03339         result = CdbStatus::Success;
03340 
03341     } while( false );
03342 
03343     return result;
03344 }
03345 
03346 CdbStatus
03347 CdbRooRoCondition::findRevision( CdbRevisionPtr& thePtr,
03348                                  const char*     theName,
03349                                  unsigned short  thePartitionId )
03350 {
03351     const char* errorStr = "CdbRooRoCondition::findRevision(name) -- ERROR";
03352 
03353     CdbStatus result = CdbStatus::NotFound;
03354     do {
03355 
03356        // Find all metadata objects corresponding to current condition/partition.
03357 
03358         std::vector< CdbCPtr< CdbRooRoMetaDataR > > vectorOfMdPtrs;
03359 
03360         bool allIncrementsFlag = true;
03361 
03362         if( CdbStatus::Success !=  findMetaData( vectorOfMdPtrs,
03363                                                  _masterRegistryPtr,
03364                                                  _localRegistryPtr,
03365                                                  _physicalAddress,
03366                                                  thePartitionId,
03367                                                  allIncrementsFlag )) {
03368             cerr << errorStr << endl
03369                  << "    Failed to locate the MetaData objects for the current condition/partition." << endl;
03370             break;
03371         }
03372 
03373       // Find an appropriate one
03374 
03375         CdbCPtr< CdbRooRoRevisionR > persistentRevisionPtr;
03376         {
03377             bool found = false;
03378 
03379             std::vector< CdbCPtr< CdbRooRoMetaDataR > >::const_iterator itr;
03380             for( itr = vectorOfMdPtrs.begin( ); itr < vectorOfMdPtrs.end( ); ++itr ) {
03381 
03382                 CdbCPtr< CdbRooRoMetaDataR > mdPtr = (*itr);
03383                 if( CdbStatus::Success == mdPtr->findRevision( theName,
03384                                                                persistentRevisionPtr )) {
03385                     found = true;
03386                     break;
03387                 }
03388             }
03389             if( !found ) break;
03390         }
03391 
03392       // Construct the transient revision object.
03393       //
03394       // DESIGN NOTE: We need to construct a smart pointer against a clone since
03395       //              we don't know a smart pointer pointing to the current
03396       //              instance, therefore we can't guarantee the lifetime
03397       //              of the current instance.
03398 
03399         thePtr = new CdbRooRoRevision( CdbConditionPtr( this->clone( )),
03400                                        persistentRevisionPtr );
03401 
03402       // Done
03403 
03404         result = CdbStatus::Success;
03405 
03406     } while( false );
03407 
03408     return result;
03409 }
03410 
03411 CdbStatus
03412 CdbRooRoCondition::revisionIdIterator( CdbItr<BdbTime>& theItr,
03413                                        unsigned short   thePartitionId )
03414 {
03415     const char* errorStr = "CdbRooRoCondition::revisionIdIterator() -- ERROR";
03416 
03417     CdbStatus result = CdbStatus::Error;
03418     do {
03419 
03420       // Find all metadata objects corresponding to current condition/partition.
03421 
03422         std::vector< CdbCPtr< CdbRooRoMetaDataR > > vectorOfMdPtrs;
03423 
03424         bool allIncrementsFlag = true;
03425 
03426         if( CdbStatus::Success !=  findMetaData( vectorOfMdPtrs,
03427                                                  _masterRegistryPtr,
03428                                                  _localRegistryPtr,
03429                                                  _physicalAddress,
03430                                                  thePartitionId,
03431                                                  allIncrementsFlag )) {
03432             cerr << errorStr << endl
03433                  << "    Failed to locate the MetaData objects for the current condition/partition." << endl;
03434             break;
03435         }
03436 
03437       // ATTENTION: This is not a memory leak - the created object
03438       //            will be destroyed by the iterator.
03439 
03440         theItr = CdbItr<BdbTime>( new RevisionIdIterator( vectorOfMdPtrs ));
03441 
03442       // Done
03443 
03444         result = CdbStatus::Success;
03445 
03446     } while( false );
03447 
03448     return result;
03449 }
03450 
03451 CdbStatus
03452 CdbRooRoCondition::revisionNameIterator( CdbItr<const char*>& theItr,
03453                                          unsigned short       thePartitionId )
03454 {
03455     const char* errorStr = "CdbRooRoCondition::revisionNameIterator() -- ERROR";
03456 
03457     CdbStatus result = CdbStatus::Error;
03458     do {
03459 
03460       // Find all metadata objects corresponding to current condition/partition.
03461 
03462         std::vector< CdbCPtr< CdbRooRoMetaDataR > > vectorOfMdPtrs;
03463 
03464         bool allIncrementsFlag = true;
03465 
03466         if( CdbStatus::Success !=  findMetaData( vectorOfMdPtrs,
03467                                                  _masterRegistryPtr,
03468                                                  _localRegistryPtr,
03469                                                  _physicalAddress,
03470                                                  thePartitionId,
03471                                                  allIncrementsFlag )) {
03472             cerr << errorStr << endl
03473                  << "    Failed to locate the MetaData objects for the current condition/partition." << endl;
03474             break;
03475         }
03476 
03477       // ATTENTION: This is not a memory leak - the created object
03478       //            will be destroyed by the iterator.
03479 
03480         theItr = CdbItr<const char*>( new RevisionNameIterator( vectorOfMdPtrs ));
03481 
03482       // Done
03483 
03484         result = CdbStatus::Success;
03485 
03486     } while( false );
03487 
03488     return result;
03489 }
03490 
03491 CdbStatus
03492 CdbRooRoCondition::createRevision( CdbRevisionPtr& thePtr,
03493                                    const BdbTime&  theId,
03494                                    const char*     theName,
03495                                    const char*     theDescription,
03496                                    unsigned short  thePartitionId )
03497 {
03498     return CdbStatus::NotImplemented;
03499 }
03500 
03501 CdbStatus
03502 CdbRooRoCondition::historyEventIterator( CdbHistoryEventItr& theItr,
03503                                          const BdbTime&      theBeginTime,
03504                                          const BdbTime&      theEndTime,
03505                                          const char**        theEventsToSelect )
03506 {
03507     return CdbStatus::NotImplemented;
03508 }
03509 
03510 CdbStatus
03511 CdbRooRoCondition::historyEventTypeIterator( CdbHistoryEventTypeItr& theItr )
03512 {
03513     return CdbStatus::NotImplemented;
03514 }
03515 
03516 CdbStatus
03517 CdbRooRoCondition::findPartition( CdbCPtr< CdbRooRoPartitionR >& thePtr,
03518                                   UShort_t                       thePartitonId ) const
03519 {
03520     const char* errorStr = "CdbRooRoCondition::findPartition() -- ERROR";
03521 
03522     CdbStatus result = CdbStatus::Error;
03523 
03524     do {
03525 
03526       // The partition location can be a two-stage process, First we look for general
03527       // partition information at the MASTER registry. Then we need to verify if the
03528       // found partition belongs to the local registry. If so then we reload
03529       // partition information from the local registry since this partition
03530       // is supposed to be modified locally.
03531 
03532         CdbCPtr< CdbRooRoPartitionR > persistentPartitionPtr;
03533 
03534         if( CdbStatus::Success != _masterRegistryPtr->partitionsLayout( )->find( thePartitonId,
03535                                                                                  persistentPartitionPtr )) {
03536             cerr << errorStr << endl
03537                  << "    Failed to find a partition #" << thePartitonId << " at the MASTER registry." << endl;
03538             break;
03539         }
03540 
03541         if(( _localRegistryPtr->originId( ) == persistentPartitionPtr->originId( )) &&
03542            ( _localRegistryPtr->originId( ) != _masterRegistryPtr->originId( ))) {
03543 
03544             if( CdbStatus::Success != _localRegistryPtr->partitionsLayout( )->find( thePartitonId,
03545                                                                                     persistentPartitionPtr )) {
03546                 cerr << errorStr << endl
03547                      << "    Failed to find a partition #" << thePartitonId << " at the local registry." << endl
03548                      << "    Perhaps the partition has not been 'instantiated' yet in the local" << endl
03549                      << "    database after being created by MASTER CDB." << endl;
03550                 break;
03551             }
03552         }
03553 
03554       // Done
03555 
03556         thePtr = persistentPartitionPtr;
03557         result = CdbStatus::Success;
03558 
03559     } while( false );
03560 
03561     return result;
03562 }
03563 
03564 CdbStatus
03565 CdbRooRoCondition::findInitialPartition( const BdbTime&                 theValidityTime,
03566                                          const BdbTime&                 theInsertionTime,
03567                                          CdbCPtr< CdbRooRoPartitionR >& thePersistentPartitionPtr ) const
03568 {
03569     const char* errorStr = "CdbRooRoCondition::findInitialPartition() -- ERROR";
03570 
03571     CdbStatus result = CdbStatus::Error;
03572 
03573     do {
03574 
03575       // The temporary partition reference required by some interfaces.
03576 
03577         CdbCPtr< CdbRooRoPartitionR > persistentPartitionPtr;
03578 
03579       // The partition location can be a two-stage process, First we look for general
03580       // partition information at the MASTER registry. Then we need to verify if the
03581       // found partition belongs to the local registry. If so then we reload
03582       // partition information from the local registry since this partition
03583       // is supposed to be modified locally.
03584 
03585         if( BdbTime::plusInfinity == theInsertionTime ) {
03586 
03587             if( CdbStatus::Success != _masterRegistryPtr->partitionsLayout( )->topmost( theValidityTime,
03588                                                                                         persistentPartitionPtr )) {
03589                 cerr << errorStr << endl
03590                      << "    Failed to find a 'topmost' partition for specified validity time" << endl
03591                      << "    at the master registry." << endl
03592                      << "        VALIDITY TIME: " << theValidityTime << endl;
03593                 break;
03594             }
03595 
03596         } else {
03597 
03598             if( CdbStatus::Success != _masterRegistryPtr->partitionsLayout( )->find( theValidityTime,
03599                                                                                      theInsertionTime,
03600                                                                                      persistentPartitionPtr )) {
03601                 cerr << errorStr << endl
03602                      << "    Failed to find a partition at specified point of 2-D timespace" << endl
03603                      << "    at the master registry." << endl
03604                      << "        VALIDITY  TIME: " << theValidityTime << endl
03605                      << "        INSERTION TIME: " << theInsertionTime << endl;
03606                 break;
03607             }
03608         }
03609 
03610         UShort_t partitionId = persistentPartitionPtr->id( );
03611 
03612         if(( _localRegistryPtr->originId( ) == persistentPartitionPtr->originId( )) &&
03613            ( _localRegistryPtr->originId( ) != _masterRegistryPtr->originId( ))) {
03614 
03615             if( CdbStatus::Success != _localRegistryPtr->partitionsLayout( )->find( partitionId,
03616                                                                                     persistentPartitionPtr )) {
03617                 cerr << errorStr << endl
03618                      << "    Failed to find a partition #" << partitionId << " at the local registry." << endl;
03619                 break;
03620             }
03621         }
03622 
03623       // Done
03624 
03625         thePersistentPartitionPtr = persistentPartitionPtr;
03626 
03627         result = CdbStatus::Success;
03628 
03629     } while( false );
03630 
03631     return result;
03632 }
03633 
03634 CdbStatus
03635 CdbRooRoCondition::findNextPartition( const BdbTime&                 theValidityTime,
03636                                       CdbCPtr< CdbRooRoPartitionR >& thePersistentPartitionPtr ) const
03637 {
03638     const char* errorStr = "CdbRooRoCondition::findNextPartition() -- ERROR";
03639 
03640     assert( !thePersistentPartitionPtr.isNull( ));
03641 
03642     CdbStatus result = CdbStatus::Error;
03643 
03644     do {
03645 
03646       // The partition location can be a tree-stage process,
03647       //
03648       //  (1) First we look for general partition information corresponding to the old
03649       //      partition at the MASTER registry. We need this step since the "next" operation
03650       //      could be based on comparision of references rather than partitions identifiers.
03651       //      So we need to obtain the right reference to succeed.
03652       //
03653       //  (2) Then we're trying to locate the information about the next partition from
03654       //      the same master registry.
03655       //
03656       //  (3) And finally we need to verify if the found partition belongs to the local registry.
03657       //      If so then we reload partition information from the local registry since this partition
03658       //      is supposed to be modified locally.
03659 
03660       // -1-
03661 
03662         UShort_t prevPartitionId = thePersistentPartitionPtr->id( );
03663 
03664         CdbCPtr< CdbRooRoPartitionR > prevPartPtr;
03665 
03666         if( CdbStatus::Success != _masterRegistryPtr->partitionsLayout( )->find( prevPartitionId,
03667                                                                                  prevPartPtr )) {
03668             cerr << errorStr << endl
03669                      << "    Failed to find a partition #" << prevPartitionId << " at the master registry." << endl;
03670             break;
03671         }
03672 
03673       // -2-
03674 
03675         CdbCPtr< CdbRooRoPartitionR > nextPartPtr = prevPartPtr;
03676 
03677         CdbStatus tmpResult = _masterRegistryPtr->partitionsLayout( )->next( theValidityTime,
03678                                                                              nextPartPtr );
03679         if( CdbStatus::Success == tmpResult ) {
03680             ;
03681         } else {
03682             if( CdbStatus::NotFound == tmpResult ) {
03683                 result = tmpResult;
03684             } else {
03685                 cerr << errorStr << endl
03686                      << "    Failed to find a 'next' partition for specified validity time" << endl
03687                      << "    at the master registry." << endl
03688                      << "        VALIDITY TIME:       " << theValidityTime << endl
03689                      << "        PREVIOUS PARTITION: #" << prevPartitionId << endl;
03690             }
03691             break;
03692         }
03693 
03694       // -3-
03695 
03696         UShort_t partitionId = nextPartPtr->id( );
03697 
03698         if(( _localRegistryPtr->originId( ) == nextPartPtr->originId( )) &&
03699            ( _localRegistryPtr->originId( ) != _masterRegistryPtr->originId( ))) {
03700 
03701             if( CdbStatus::Success != _localRegistryPtr->partitionsLayout( )->find( partitionId,
03702                                                                                     nextPartPtr )) {
03703                 cerr << errorStr << endl
03704                      << "    Failed to find a partition #" << partitionId << " at the local registry." << endl;
03705                 break;
03706             }
03707         }
03708 
03709       // Done
03710 
03711         thePersistentPartitionPtr = nextPartPtr;
03712         result                    = CdbStatus::Success;
03713 
03714     } while( false );
03715 
03716     return result;
03717 }
03718 
03719 CdbStatus
03720 CdbRooRoCondition::doFindObjectAtPartition( const CdbRevisionPolicy& thePolicy,
03721                                             const BdbTime&           theValidityTime,
03722                                             const BdbTime&           theInsertionTime,
03723                                             CdbRooRoOiR&             theOriginalInterval,
03724                                             BdbTime&                 theBeginOfVisiblePeriod,
03725                                             BdbTime&                 theEndOfVisiblePeriod,
03726                                             BdbTime&                 theBeginOfDurationPeriod,
03727                                             BdbTime&                 theEndOfDurationPeriod ) const
03728 {
03729     const char* debugStr = "CdbRooRoCondition::doFindObjectAtPartition()";
03730     const char* errorStr = "CdbRooRoCondition::doFindObjectAtPartition() -- ERROR";
03731 
03732     CdbStatus result = CdbStatus::Error;
03733 
03734     do {
03735 
03736       // Make sure this is a proper use of the algorithm. Just in case...
03737 
03738         assert( _persistentConditionPtr->isPartitionable( ));
03739 
03740       // Verify parameters and extract revision to begin with
03741 
03742         bool    useRevisions = thePolicy.useRevision( );
03743         BdbTime rId          = thePolicy.revisionId( );
03744 
03745         if( useRevisions ) {
03746 
03747             ;   // Nothing more to say
03748 
03749         } else if( BdbTime::plusInfinity == theInsertionTime ) {
03750 
03751             useRevisions = true;                    // Need this for the topmost revision
03752             rId          = BdbTime::plusInfinity;   // TOPMOST revision
03753 
03754         } else {
03755 
03756             rId = theInsertionTime;     // Still, no revisions
03757         }
03758 
03759       // Get the condition creation time.
03760       //
03761       // IMPORTANT NOTE:
03762       //
03763       //     We would need this information to see which increments (MetaData)
03764       //     to include into the search,
03765       //     The reason why we're doing this check is that conditions
03766       //     may be created (put into a cluster) when the correspodning clusters
03767       //     already have more than 1 increment. Therefore some earlier partitions or increments
03768       //     may just not have any MetaData fore newer conditions.
03769 
03770         BdbTime creationTime = _persistentConditionPtr->created( );
03771 
03772         if( rId < creationTime ) {
03773             cerr << errorStr << endl
03774                  << "    Specified revision identifier / insertion time is older" << endl
03775                  << "    than the time when the condition was created." << endl
03776                  << "    The current view may be inproperly configured for the condition." << endl
03777                  << "        REVISION ID / INSERTION TIME : " << rId << endl
03778                  << "        CONDITION CREATION TIME      : " << creationTime << endl
03779                  << "        CONDITION NAME               : \"" << name( ) << "\"" << endl
03780                  << "        PARENT FOLDER NAME           : \"" << parent( )->name( ) << "\"" << endl
03781                  << "        VIEW NAME                    : \"" << parent( )->parentView( )->name( ) << "\"" << endl;
03782             break;
03783         }
03784 
03785       // Find the initial <partition> to begin with.
03786       //
03787       // NOTE: We're going to check if the partion is closed. If so if its
03788       //       upper "insertion" time boundry is strictly above the condition
03789       //       creation time. Otherwise we just quit here since no MetaData
03790       //       for the recently created condition should exist in his partition.
03791 
03792         CdbCPtr< CdbRooRoPartitionR > persistentPartitionPtr;
03793 
03794         if( CdbStatus::Success != findInitialPartition( theValidityTime,
03795                                                         rId,
03796                                                         persistentPartitionPtr )) {
03797             break;
03798         }
03799 
03800 /******************************************************************/
03801 if( CdbEnvironment::getDebugMode( ) != 0 )
03802     cout << debugStr << endl
03803          << "{" << endl
03804          << "    Found initial partition ID=" << persistentPartitionPtr->id( ) << endl
03805          << "}" << endl;
03806 /******************************************************************/
03807 
03808         if( persistentPartitionPtr->isClosed( )) {
03809 
03810             CdbRooRoCellR pCell = persistentPartitionPtr->cell( );
03811 
03812             if( pCell.endInsertion( ) <= creationTime ) {
03813 
03814 /***************************************************************/
03815 if( CdbEnvironment::getDebugMode( ) != 0 )
03816 cout << debugStr << endl
03817  << "{" << endl
03818  << "    The just found partition is already 'closed' and its upper 'insertion'" << endl
03819  << "    time limit is older than the creation time of the current condition." << endl
03820  << "    So no object has been found." << endl
03821  << "        creationTime       : " << creationTime << endl
03822  << "        pCell.endInsertion : " << pCell.endInsertion( ) << endl
03823  << "}" << endl;
03824 /***************************************************************/
03825 
03826                 result = CdbStatus::NotFound;
03827                 break;
03828             }
03829         }
03830 
03831       //  Then find the increments range for specified revision time.
03832 
03833         UShort_t firstIncrement = 0;
03834         UShort_t lastIncrement  = 0;
03835         {
03836             UShort_t numIncrements = persistentPartitionPtr->numIncrements( );
03837             assert( numIncrements > 0 );
03838 
03839           // Find the very first increment including the creation time
03840           // of the condition.
03841 
03842             {
03843                 bool failed = true;
03844 
03845                 for( UShort_t i = 0; i < numIncrements; ++i ) {
03846 
03847                     CdbRooRoIncrementR iVal;
03848                     if( CdbStatus::Success != persistentPartitionPtr->increment( i,
03849                                                                                  iVal )) {
03850                         break;
03851                     }
03852                     if( creationTime < iVal.end( )) {
03853 
03854                         firstIncrement = i;
03855 
03856                         failed = false;
03857                         break;
03858                     }
03859                 }
03860                 if( failed ) {
03861                     cerr << errorStr << endl
03862                          << "    Failed to find the smallest increment number at a partition #" << persistentPartitionPtr->id( ) << endl
03863                          << "    The current federation may not be properly initialized/loaded." << endl;
03864                     break;
03865                 }
03866             }
03867 
03868           // Find the very last increment including specified revision
03869           //
03870           // NOTE: This search begins with the above found very first
03871           //       increment number.
03872 
03873             if( BdbTime::plusInfinity == rId ) {
03874                 lastIncrement = numIncrements - 1;
03875             } else {
03876 
03877                 bool failed = true;
03878 
03879                 for( UShort_t i = firstIncrement; i < numIncrements; ++i ) {
03880 
03881                     CdbRooRoIncrementR iVal;
03882                     if( CdbStatus::Success != persistentPartitionPtr->increment( i,
03883                                                                                  iVal )) {
03884                         break;
03885                     }
03886                     if(( rId >= iVal.begin( )) && ( rId <  iVal.end( ))) {
03887 
03888                         lastIncrement = i;
03889 
03890                         failed = false;
03891                         break;
03892                     }
03893                 }
03894                 if( failed ) {
03895                     cerr << errorStr << endl
03896                          << "    Failed to find the biggest increment number at a partition #" << persistentPartitionPtr->id( ) << endl
03897                          << "    The current federation may not be properly initialized/loaded." << endl;
03898                     break;
03899                 }
03900             }
03901         }
03902 
03903 /*********************************************************************/
03904 if( CdbEnvironment::getDebugMode( ) != 0 )
03905     cout << debugStr << endl
03906          << "{" << endl
03907          << "    Initial firstIncrement : " << firstIncrement << endl
03908          << "            lastIncrement  : " << lastIncrement  << endl
03909          << "}" << endl;
03910 /*********************************************************************/
03911 
03912       // Now we're ready to begin seraching for condition objects through
03913       // the sequence of partitions & increments.
03914       //
03915       // == ALGORITHM DESCRIPTION ==
03916       //
03917       //  (1) The search algorithm begins with the specified revision/insertion time
03918       //      of the initially found partition & increment and it will proceed down
03919       //      to final revisions of previous increments of the this partition until
03920       //      either the desired interval is found or the bottom of the increments
03921       //      stack is met. The bottom is defined as the lowest increment including
03922       //      the condition's creation time.
03923       //
03924       //  (2) If the bottom of the initial partition is met and desired interval
03925       //      is still not found then we switch to the next partition below
03926       //      the initial one and proceed with the search begining with the final
03927       //      revision of that partition.
03928       //
03929       //  (3) We proceed with step (2) until either we find desired interval or
03930       //      we reach the bottom of the condition. Note, that definition of
03931       //      the "bottom" given at (1) above.
03932       //
03933       // This algorithm is used for both states of the "useRevisions" flag
03934       // calculated above. The only difference is that in case of "!useRevisions"
03935       // we're only given one chance to try the above calculated initial partition & increment
03936       // where the answer for specified insertionTime should be.
03937       // See the details at the implementation of the CdbRooRoMetaDataR::findByInsertion()
03938       // method.
03939       //
03940       // Here is a pseudo-graphical representation of this process:
03941       //
03942       //           <validity time>
03943       //                   |
03944       //                   |
03945       // ..................|..............................................
03946       // :Partition M      |                                             :
03947       // : ................|............................................ :
03948       // : :Increment MAX  |                                           : :
03949       // : :               |                              ============ : :
03950       // : :               |                         ================= : :
03951       // : + + + + + + + + X + + + + + + + + + + + + + + + + + + + + + + +  Rev.M/insertion time
03952       // : :               |                   ======================= : :
03953       // : :               |              ============================ : :
03954       // : :               |        ================================== : :
03955       // : ................|............................................ :
03956       // : ................|............................................ :
03957       // : :Increment 0    |                                           : :
03958       // : + + + + + + + + X + + + + + + + + + + + + + + + + + + + + + + +  Rev.Final
03959       // : :               |                     ===================== : :
03960       // : :               |                 ========================= : :
03961       // : ................|............................................ :
03962       // ..................|..............................................
03963       //                   |
03964       // ..................|............................
03965       // :Partition L      |                           :
03966       // : ................|.......................... :
03967       // : :Increment MAX  |                         : :
03968       // : + + + + + + + + X + + + + + + + + + + + + + +  Rev.Final
03969       // : :               |     =================== : :
03970       // : :               | ======================= : :
03971       // : :               X======================== : :
03972       // : :         =============================== : :
03973       // : ........................................... :
03974       // ...............................................
03975       //
03976       // This algorithm can be optimized in the future by caching all the relevant
03977       // information in the virtual memory of an application to avoid expensive
03978       // operations with peristsent store.
03979       //
03980       // NOT IMPLEMENTED: Will be implemented after the special failure test will
03981       //                  be done.
03982       //
03983       // == CALCULATING THE VISIBLE VALIDITY INTERVAL OF FOUND OBJECT ==
03984       //
03985       // The basic idea is that the visible validity interval is the shortest interval
03986       // of any of the following validity intervals met by the above described
03987       // algorithm:
03988       //
03989       // - the validity range of any partition explored
03990       // - the validity range of any failed as CdbStatus::NotFound attempts
03991       //   to find desired object at any MetaData object of partitions & increments explored
03992       // - the visibke validity for a successfully found object
03993       //
03994       // IMPORTANT: This algorithm needs thorough testing before deploying it.
03995 
03996         CdbRooRoCellR pCell = persistentPartitionPtr->cell( );
03997 
03998         theBeginOfVisiblePeriod = pCell.beginValidity( );
03999         theEndOfVisiblePeriod   = pCell.endValidity  ( );
04000 
04001         assert( theBeginOfVisiblePeriod < theEndOfVisiblePeriod );
04002 
04003       // Begin the algorithm...
04004 
04005         bool isFirstPath = true;
04006 
04007         do {
04008 
04009 /**************************************************************************/
04010 if( CdbEnvironment::getDebugMode( ) != 0 )
04011     cout << debugStr << endl
04012          << "{" << endl
04013          << "    isFirstPath : " << ( isFirstPath ? "Yes" : "No" ) << endl
04014          << "}" << endl;
04015 /**************************************************************************/
04016 
04017             if( !isFirstPath ) {
04018 
04019               // Reload <partition>
04020               //
04021               // NOTE: We're going to check if the partion is closed. If so if its
04022               //       upper "insertion" time boundry is strictly above the condition
04023               //       creation time. Otherwise we just quit here since no MetaData
04024               //       for the recently created condition should exist in his partition.
04025 
04026                 if( CdbStatus::Success != findNextPartition( theValidityTime,
04027                                                              persistentPartitionPtr )) {
04028                     break;
04029                 }
04030 
04031 /***************************************************************/
04032 if( CdbEnvironment::getDebugMode( ) != 0 )
04033     cout << debugStr << endl
04034          << "{" << endl
04035          << "    Found next partition ID=" << persistentPartitionPtr->id( ) << endl
04036          << "}" << endl;
04037 /***************************************************************/
04038 
04039                 if( persistentPartitionPtr->isClosed( )) {
04040 
04041                     CdbRooRoCellR pCell = persistentPartitionPtr->cell( );
04042 
04043                     if( pCell.endInsertion( ) <= creationTime ) {
04044 
04045 /***************************************************************/
04046 if( CdbEnvironment::getDebugMode( ) != 0 )
04047     cout << debugStr << endl
04048          << "{" << endl
04049          << "    The just found partition is already 'closed' and its upper 'insertion'" << endl
04050          << "    time limit is older than the creation time of the current condition." << endl
04051          << "    So no object has been found." << endl
04052          << "        creationTime       : " << creationTime << endl
04053          << "        pCell.endInsertion : " << pCell.endInsertion( ) << endl
04054          << "}" << endl;
04055 /***************************************************************/
04056 
04057                         result = CdbStatus::NotFound;
04058                         break;
04059                     }
04060                 }
04061 
04062               // ...and <increment>
04063               //
04064               // NOTE: We're going to recalculate the first and last increment numbers
04065               //       of the partition taking into accound the condition creation time.
04066 
04067                 {
04068                     UShort_t numIncrements = persistentPartitionPtr->numIncrements( );
04069                     assert( numIncrements > 0 );
04070 
04071 /*******************************************************************************************************************/
04072 if( CdbEnvironment::getDebugMode( ) != 0 )
04073     cout << debugStr << endl
04074          << "{" << endl
04075          << "    num increments : " << numIncrements << " at partition ID=" << persistentPartitionPtr->id( ) << endl
04076          << "}" << endl;
04077 /*******************************************************************************************************************/
04078 
04079                   // Find the first increment first
04080 
04081                     bool found  = false;
04082                     bool failed = true;
04083 
04084                     for( UShort_t i = 0; i < numIncrements; ++i ) {
04085 
04086                         CdbRooRoIncrementR iVal;
04087                         if( CdbStatus::Success != persistentPartitionPtr->increment( i,
04088                                                                                      iVal )) {
04089                             cerr << errorStr << endl
04090                                  << "    Failed to find the increment #" << i << " at the partition #" << persistentPartitionPtr->id( ) << endl
04091                                  << "    The current federation may not be properly initialized/loaded." << endl;
04092                             break;
04093                         }
04094 
04095 /*********************************************************/
04096 if( CdbEnvironment::getDebugMode( ) != 0 )
04097     cout << debugStr << endl
04098          << "{" << endl
04099          << "    creation time : " << creationTime << endl
04100          << "    iVal.end      : " << iVal.end( ) << endl
04101          << "}" << endl;
04102 /*********************************************************/
04103 
04104                         if( creationTime < iVal.end( )) {
04105 
04106                             firstIncrement = i;
04107 
04108                             found  = true;
04109                             failed = false;
04110 
04111                             break;
04112                         }
04113                     }
04114                     if( failed ) {
04115                         break;
04116                     }
04117                     if( !found ) {
04118                         result = CdbStatus::NotFound;
04119                         break;
04120                     }
04121 
04122                   // The last increment is alway the biggest one since we're
04123                   // already below the revision/insertion time
04124 
04125                     lastIncrement = numIncrements - 1;
04126                 }
04127 
04128 /******************************************************************/
04129 if( CdbEnvironment::getDebugMode( ) != 0 )
04130     cout << debugStr << endl
04131          << "{" << endl
04132          << "    next firstIncrement : " << firstIncrement << endl
04133          << "         lastIncrement  : " << lastIncrement  << endl
04134          << "}" << endl;
04135 /******************************************************************/
04136 
04137               // Narrow down the visible interval to the partition limits
04138 
04139                 pCell = persistentPartitionPtr->cell( );
04140 
04141                 if( pCell.beginValidity( ) > theBeginOfVisiblePeriod ) theBeginOfVisiblePeriod = pCell.beginValidity( );
04142                 if( pCell.endValidity  ( ) < theEndOfVisiblePeriod   ) theEndOfVisiblePeriod   = pCell.endValidity  ( );
04143 
04144                 assert( theBeginOfVisiblePeriod < theEndOfVisiblePeriod );
04145             }
04146 
04147             bool isBreaking  = false;
04148 
04149             for( int i = lastIncrement; i >= firstIncrement; --i ) {
04150 
04151               // Find out the meta-data object.
04152 
04153                 CdbCPtr< CdbRooRoMetaDataR > mdPtr;
04154 
04155                 if( CdbStatus::Success != CdbRooRoFileUtils::instance( ).findMetaData( mdPtr,
04156                                                                                        _physicalAddress.local,                     // theConditionId
04157                                                                                        true,                                       // isPartitionableFlag
04158                                                                                        persistentPartitionPtr->id( ),              // thePartitionId
04159                                                                                        _persistentConditionPtr->clusterId( ),      // theClusterId
04160                                                                                        i,                                          // theIncrementId
04161                                                                                        persistentPartitionPtr->originId( ))) {     // theOriginId (of the partition)
04162                     cerr << errorStr << endl
04163                          << "    Failed to find a MetaData object." << endl
04164                          << "        CONDITION 'PHYSICAL' ADDRESS : " << _physicalAddress << endl
04165                          << "        IS PARTITIONABLE             : " << "Yes" << endl
04166                          << "        PARTITION ID                 : " << persistentPartitionPtr->id( ) << endl
04167                          << "        CLUSTER   ID                 : " << _persistentConditionPtr->clusterId( ) << endl
04168                          << "        INCREMENT ID                 : " << i << endl
04169                          << "        PARTITION'S ORIGIN ID        : " << persistentPartitionPtr->originId( ) << endl;
04170 
04171                     isBreaking = true;
04172                     break;
04173                 }
04174 
04175               // If this is not the very first step in the <partition> & <increment> loop
04176               // then we need to switch to the "final" revision of the just found metadata object.
04177               //
04178               // NOTE: The "final" revision of a metadata object is the one corresponding
04179               //       to its most recent "modification" time.
04180               //
04181               //       @see CdbRooRoMetaDataR::modified()
04182 
04183                 if( isFirstPath && ( i == lastIncrement )) {
04184                     ;
04185                 } else {
04186                     rId = mdPtr->modified( );
04187                 }
04188 
04189               // Try finding the persistent object in the meta-data object of
04190               // the current increment.
04191               //
04192               // NOTE: We do only one attemp for "useRevisions == false".
04193 
04194                 BdbTime beginOfVisiblePeriod( 0 );
04195                 BdbTime endOfVisiblePeriod  ( 0 );
04196 
04197                 if( useRevisions ) {
04198 
04199 /*************************************************************************************************/
04200 if( CdbEnvironment::getDebugMode( ) != 0 )
04201     cout << debugStr << endl
04202          << "{" << endl
04203          << "    Find by revision" << endl
04204          << "       next    curent increment number : " << i << endl
04205          << "               rId                     : " << rId << endl
04206          << "               theValidityTime         : " << theValidityTime << endl
04207          << "}" << endl;
04208 /*************************************************************************************************/
04209 
04210                     result = mdPtr->findByRevision( rId,
04211                                                     theValidityTime,
04212                                                     theOriginalInterval,
04213                                                     beginOfVisiblePeriod,
04214                                                     endOfVisiblePeriod );
04215 
04216 /************************************************/
04217 if( CdbEnvironment::getDebugMode( ) != 0 )
04218     cout << debugStr << endl
04219          << "{" << endl
04220          << "    result : " << result << endl
04221          << "}" << endl;
04222 /************************************************/
04223 
04224                     if( beginOfVisiblePeriod > theBeginOfVisiblePeriod ) theBeginOfVisiblePeriod = beginOfVisiblePeriod;
04225                     if( endOfVisiblePeriod   < theEndOfVisiblePeriod   ) theEndOfVisiblePeriod   = endOfVisiblePeriod;
04226 
04227                     assert( theBeginOfVisiblePeriod < theEndOfVisiblePeriod );
04228 
04229                     if( CdbStatus::NotFound != result ) {
04230 
04231                       // The duration of this object begins with its insertion time up
04232                       // to +Infinity
04233 
04234                         theBeginOfDurationPeriod = theOriginalInterval.inserted( );
04235                         theEndOfDurationPeriod   = BdbTime::plusInfinity;
04236 
04237                       // No matter if it's success or anything else except "NotFound".
04238 
04239                         isBreaking = true;
04240                         break;
04241                     }
04242 
04243                 } else {
04244 
04245                     result = mdPtr->findByInsertion( rId,
04246                                                      theValidityTime,
04247                                                      theOriginalInterval,
04248                                                      theBeginOfDurationPeriod,
04249                                                      theEndOfDurationPeriod );
04250 
04251                   // Special situation when an 'original' interval becomes the 'visible' one
04252 
04253                     theBeginOfVisiblePeriod = theOriginalInterval.begin( );
04254                     theEndOfVisiblePeriod   = theOriginalInterval.end  ( );
04255 
04256                   // No more attempts.
04257 
04258                     isBreaking = true;
04259                     break;
04260                 }
04261             }
04262             if( isBreaking ) break;
04263 
04264             isFirstPath = false;
04265 
04266         } while( true );    // Should be broken by the logic above.
04267 
04268     } while( false );
04269 
04270     return result;
04271 }
04272 
04273 CdbStatus
04274 CdbRooRoCondition::doFindObject( const CdbRevisionPolicy& thePolicy,
04275                                  const BdbTime&           theValidityTime,
04276                                  const BdbTime&           theInsertionTime,
04277                                  CdbRooRoOiR&             theOriginalInterval, 
04278                                  BdbTime&                 theBeginOfVisiblePeriod,
04279                                  BdbTime&                 theEndOfVisiblePeriod,
04280                                  BdbTime&                 theBeginOfDurationPeriod,
04281                                  BdbTime&                 theEndOfDurationPeriod ) const
04282 {
04283     const char* debugStr = "CdbRooRoCondition::doFindObject()";
04284     const char* errorStr = "CdbRooRoCondition::doFindObject() -- ERROR";
04285 
04286     CdbStatus result = CdbStatus::Error;
04287 
04288     do {
04289 
04290       // Make sure this is a proper use of the algorithm. Just in case...
04291 
04292         assert( !_persistentConditionPtr->isPartitionable( ));
04293 
04294       // Verify parameters and extract revision to begin with
04295 
04296         bool    useRevisions = thePolicy.useRevision( );
04297         BdbTime rId          = thePolicy.revisionId( );
04298 
04299         if( useRevisions ) {
04300 
04301             ;   // Nothing more to say
04302 
04303         } else if( BdbTime::plusInfinity == theInsertionTime ) {
04304 
04305             useRevisions = true;                    // Need this for the topmost revision
04306             rId          = BdbTime::plusInfinity;   // TOPMOST revision
04307 
04308         } else {
04309 
04310             rId = theInsertionTime;     // Still, no revisions
04311         }
04312 
04313       // Set up some initial "visible" validity period. This window will be corrected
04314       // by the condition lookup algorithm.
04315 
04316         theBeginOfVisiblePeriod = BdbTime::minusInfinity;
04317         theEndOfVisiblePeriod   = BdbTime::plusInfinity;
04318 
04319       // Get the condition creation time.
04320       //
04321       // IMPORTANT NOTE:
04322       //
04323       //     We would need this information to see which increments (MetaData)
04324       //     to include into the search,
04325       //     The reason why we're doing this check is that conditions
04326       //     may be created (put into a cluster) when the correspodning clusters
04327       //     already have more than 1 increment. Therefore some earlier increments
04328       //     may just not have any MetaData fore newer conditions.
04329 
04330         BdbTime creationTime = _persistentConditionPtr->created( );
04331 
04332         if( rId < creationTime ) {
04333             cerr << errorStr << endl
04334                  << "    Specified revision identifier / insertion time is older" << endl
04335                  << "    than the time when the condition was created." << endl
04336                  << "    The current view may be inproperly configured for the condition." << endl
04337                  << "        REVISION ID / INSERTION TIME : " << rId << endl
04338                  << "        CONDITION CREATION TIME      : " << creationTime << endl
04339                  << "        CONDITION NAME               : \"" << name( ) << "\"" << endl
04340                  << "        PARENT FOLDER NAME           : \"" << parent( )->name( ) << "\"" << endl
04341                  << "        VIEW NAME                    : \"" << parent( )->parentView( )->name( ) << "\"" << endl;
04342             break;
04343         }
04344 
04345       // Find the increments range for specified revision time.
04346 
04347         UShort_t firstIncrement = 0;
04348         UShort_t lastIncrement  = 0;
04349         {
04350           // Find out a the cluster the condition belongs to.
04351 
04352             CdbCPtr< CdbRooRoRClusterR > persistentClusterPtr;
04353             {
04354               // Find out the owner registry the cluster is supposed to be.
04355 
04356                 CdbCPtr< CdbRooRoRegistry > conditionOwnerRegistryPtr;
04357                 {
04358                     if( _localRegistryPtr->originId( ) == _physicalAddress.origin ) {
04359                         conditionOwnerRegistryPtr = _localRegistryPtr;
04360 
04361                     } else if( _masterRegistryPtr->originId( ) == _physicalAddress.origin ) {
04362                         conditionOwnerRegistryPtr = _masterRegistryPtr;
04363 
04364                     } else {
04365                         if( CdbStatus::Success != CdbRooRoRegistry::findByOrigin( conditionOwnerRegistryPtr,
04366                                                                                   _physicalAddress.origin )) {
04367                             cerr << errorStr << endl
04368                                  << "    Registry for specified origin ID #" << _physicalAddress.origin << " not found." << endl;
04369                             break;
04370                         }
04371                     }
04372                 }
04373 
04374               // Proceed to the cluster in question
04375 
04376                 if( CdbStatus::Success != conditionOwnerRegistryPtr->clusterCollection( )->find( _persistentConditionPtr->clusterId( ),
04377                                                                                                  persistentClusterPtr )) {
04378                     cerr << errorStr << endl
04379                          << "    Cluster with ID #" << _persistentConditionPtr->clusterId( ) << " not found" << endl
04380                          << "    at the collection with the origin ID #" << _physicalAddress.origin << endl;
04381                     break;
04382                 }
04383             }
04384 
04385             UShort_t numIncrements = persistentClusterPtr->numIncrements( );
04386             assert( numIncrements > 0 );
04387 
04388           // Find the very first increment including the creation time
04389           // of the condition.
04390 
04391             {
04392                 bool failed = true;
04393 
04394                 for( UShort_t i = 0; i < numIncrements; ++i ) {
04395 
04396                     CdbRooRoIncrementR iVal;
04397                     if( CdbStatus::Success != persistentClusterPtr->increment( i,
04398                                                                                iVal )) {
04399                         break;
04400                     }
04401                     if( creationTime < iVal.end( )) {
04402 
04403                         firstIncrement = i;
04404 
04405                         failed = false;
04406                         break;
04407                     }
04408                 }
04409                 if( failed ) {
04410                     cerr << errorStr << endl
04411                          << "    Failed to find the smallest increment number for the condition." << endl
04412                          << "    The current federation may not be properly initialized/loaded." << endl;
04413                     break;
04414                 }
04415             }
04416 
04417           // Find the very last increment including specified revision
04418           //
04419           // NOTE: This search begins with the above found very first
04420           //       increment number.
04421 
04422             if( BdbTime::plusInfinity == rId ) {
04423                 lastIncrement = numIncrements - 1;
04424             } else {
04425 
04426                 bool failed = true;
04427 
04428                 for( UShort_t i = firstIncrement; i < numIncrements; ++i ) {
04429 
04430                     CdbRooRoIncrementR iVal;
04431                     if( CdbStatus::Success != persistentClusterPtr->increment( i,
04432                                                                                iVal )) {
04433                         break;
04434                     }
04435                     if(( rId >= iVal.begin( )) && ( rId <  iVal.end( ))) {
04436 
04437                         lastIncrement = i;
04438 
04439                         failed = false;
04440                         break;
04441                     }
04442                 }
04443                 if( failed ) {
04444                     cerr << errorStr << endl
04445                          << "    Failed to find the biggest increment number for the condition." << endl
04446                          << "    The current federation may not be properly initialized/loaded." << endl;
04447                     break;
04448                 }
04449             }
04450 /***********************************************************/
04451 if( CdbEnvironment::getDebugMode( ) != 0 )
04452     cout << debugStr << endl
04453          << "{" << endl
04454          << "    creationTime   : " << creationTime   << endl
04455          << "    firstIncrement : " << firstIncrement << endl
04456          << "    lastIncrement  : " << lastIncrement  << endl
04457          << "    numIncrements  : " << numIncrements  << endl
04458          << "}" << endl;
04459 /***********************************************************/
04460         }
04461 
04462       // Now we're ready to begin seraching for condition objects through
04463       // the sequence of increments. The search begins with the specified revision
04464       // of the found increment and it will proceed down to final revisions
04465       // of previous increments until either the desired interval is found or the smallest
04466       // avaialble for this condition increment of the stack is met.
04467       //
04468       // NOTE: This algorithm is used for both states of the "useRevisions" flag
04469       //       calculated above. The only difference is that in case of "!useRevisions"
04470       //       we're only given one chance to try the above calculated increment
04471       //       where the answer for specified insertionTime should be.
04472       //       See the details at the implementation of the CdbRooRoMetaDataR::findByInsertion()
04473       //       method.
04474       //
04475       // Here is a pseudo-graphical representation of this process:
04476       //
04477       //           <validity time>
04478       //                   |
04479       //   ................|....................................................
04480       //   :Increment N    |                                                   :
04481       //   :               |                              ==================== :
04482       //   :               |                         ========================= :
04483       //   + + + + + + + + X + + + + + + + + + + + + + + + + + + + + + + + + + +  Rev.M/insertion time
04484       //   :               |                   =============================== :
04485       //   :               |              ==================================== :
04486       //   :               |        ========================================== :
04487       //   ................|....................................................
04488       //                   |
04489       //   ................|....................................................
04490       //   :Increment N-1  |                                                   :
04491       //   + + + + + + + + X + + + + + + + + + + + + + + + + + + + + + + + + + +  Rev.Final
04492       //   :               |     ============================================= :
04493       //   :               | ================================================= :
04494       //   :             ==X================================================== :
04495       //   :         ========================================================= :
04496       //   .....................................................................
04497       //
04498       // This algorithm can be optimized in the future by caching all the relevant
04499       // information in the virtual memory of an application to avoid expensive
04500       // operations with peristsent store.
04501       //
04502       // NOT IMPLEMENTED: Will be implemented after the special failure test will
04503       //                  be done.
04504 
04505         for( int i = lastIncrement; i >= firstIncrement; --i ) {
04506 
04507           // Find out the meta-data object.
04508 
04509             CdbCPtr< CdbRooRoMetaDataR > mdPtr;
04510 
04511             if( CdbStatus::Success != CdbRooRoFileUtils::instance( ).findMetaData( mdPtr,
04512                                                                                    _physicalAddress.local,                 // theConditionId
04513                                                                                    false,                                  // isPartitionableFlag
04514                                                                                    0,                                      // thePartitionId
04515                                                                                    _persistentConditionPtr->clusterId( ),  // theClusterId
04516                                                                                    i,                                      // theIncrementId
04517                                                                                    _physicalAddress.origin )) {            // theOriginId
04518                 cerr << errorStr << endl
04519                      << "    Failed to find a MetaData object." << endl
04520                      << "        CONDITION 'PHYSICAL' ADDRESS : " << _physicalAddress << endl
04521                      << "        IS PARTITIONABLE             : " << "No" << endl
04522                      << "        PARTITION ID                 : " << 0 << endl
04523                      << "        CLUSTER   ID                 : " << _persistentConditionPtr->clusterId( ) << endl
04524                      << "        INCREMENT ID                 : " << i << endl;
04525                 break;
04526             }
04527 
04528           // If this is not the very first step in the loop then we need to switch
04529           // to the "final" revision of the just found metadata object.
04530           //
04531           // NOTE: The "final" revision of a metadata object is the one corresponding
04532           //       to its most recent "modification" time.
04533           //
04534           //       @see CdbRooRoMetaDataR::modified()
04535 
04536             if( i != lastIncrement ) rId = mdPtr->modified( );
04537 
04538           // Try finding the persistent object in the meta-data object of
04539           // the current increment.
04540           //
04541           // NOTE: We do only one attemp for "useRevisions == false".
04542 
04543             if( useRevisions ) {
04544 
04545               // The explicit "visible" validity interval correction at this level of
04546               // the object mining algorithm may be needed when "diving" into metadata-s
04547               // beneath an upper one.
04548 
04549                 BdbTime beginOfVisiblePeriod = BdbTime( 0 );        // Just to have an initialized value
04550                 BdbTime endOfVisiblePeriod   = BdbTime( 0 );        // -//-
04551 
04552                 result = mdPtr->findByRevision( rId,
04553                                                 theValidityTime,
04554                                                 theOriginalInterval,
04555                                                 beginOfVisiblePeriod,
04556                                                 endOfVisiblePeriod );
04557 
04558                 if( beginOfVisiblePeriod > theBeginOfVisiblePeriod ) theBeginOfVisiblePeriod = beginOfVisiblePeriod;
04559                 if( endOfVisiblePeriod   < theEndOfVisiblePeriod   ) theEndOfVisiblePeriod   = endOfVisiblePeriod;
04560 
04561                 if( CdbStatus::NotFound != result ) {
04562 
04563                   // The duration of this object begins with its insertion time up
04564                   // to +Infinity
04565 
04566                     theBeginOfDurationPeriod = theOriginalInterval.inserted( );
04567                     theEndOfDurationPeriod   = BdbTime::plusInfinity;
04568 
04569                   // No matter if it's success or anything else except "NotFound".
04570 
04571                     break;
04572                 }
04573 
04574             } else {
04575 
04576                 result = mdPtr->findByInsertion( rId,
04577                                                  theValidityTime,
04578                                                  theOriginalInterval,
04579                                                  theBeginOfDurationPeriod,
04580                                                  theEndOfDurationPeriod );
04581 
04582               // Special situation when an 'original' interval becomes the 'visible' one
04583 
04584                 theBeginOfVisiblePeriod = theOriginalInterval.begin( );
04585                 theEndOfVisiblePeriod   = theOriginalInterval.end  ( );
04586 
04587               // No more attempts.
04588 
04589                 break;
04590             }
04591         }
04592 
04593     } while( false );
04594 
04595     return result;
04596 }
04597 
04598 namespace {
04599 
04600     std::string
04601     fullPathName( const CdbRooRoCondition* theConditionPtr )
04602     {
04603         if( 0 == theConditionPtr ) return std::string( "" );
04604 
04605       // Note, that a condition found by its 'physical' address or name does not
04606       // have a valid "full path", which would only make sense in a view.
04607  
04608         if( theConditionPtr->parent( ).isNull( )) return std::string( "" );
04609  
04610       // Proceed for conditions found through a view
04611  
04612         CdbPathName result( theConditionPtr->name( ));
04613  
04614         CdbFolderPtr parentFolder = theConditionPtr->parent( );
04615         while( !parentFolder.isNull( )) {
04616             result = CdbPathName( parentFolder->name( )) + result;
04617             parentFolder = parentFolder->parentFolder( );
04618         }
04619         return result.toString( );
04620     }
04621 
04622     CdbStatus
04623     findMetaData( std::vector< CdbCPtr< CdbRooRoMetaDataR > >& theVectorOfPtrs,
04624                   const CdbCPtr< CdbRooRoRegistry >&           theMasterRegistryPtr,
04625                   const CdbCPtr< CdbRooRoRegistry >&           theLocalRegistryPtr,
04626                   const CdbId&                                 theExtendedConditionId,
04627                   UShort_t                                     thePartitionId,
04628                   bool                                         allIncrementsFlag,
04629                   bool                                         recentIncrementFlag,
04630                   UShort_t                                     theIncrementNumber )
04631     {
04632         const char* errorStr = "CdbRooRoCondition::findMetaData() -- ERROR";
04633 
04634         CdbStatus result = CdbStatus::Error;
04635         do {
04636 
04637           // Make sure the procedure is called with correct set of parameters
04638 
04639             assert( !theMasterRegistryPtr.isNull( ));
04640             assert( !theLocalRegistryPtr.isNull( ));
04641             assert( theMasterRegistryPtr->isMaster( ));
04642 
04643             UShort_t originId    = theExtendedConditionId.origin;
04644             UShort_t conditionId = theExtendedConditionId.local;
04645 
04646           // Find out which registry hosts the condition
04647 
04648             CdbCPtr< CdbRooRoRegistry > conditionOwnerRegistryPtr;
04649             {
04650                 if( theLocalRegistryPtr->originId( ) == originId ) {
04651                     conditionOwnerRegistryPtr = theLocalRegistryPtr;
04652 
04653                 } else if( theMasterRegistryPtr->originId( ) == originId ) {
04654                     conditionOwnerRegistryPtr = theMasterRegistryPtr;
04655 
04656                 } else {
04657                     if( CdbStatus::Success != CdbRooRoRegistry::findByOrigin( conditionOwnerRegistryPtr,
04658                                                                               originId )) {
04659                         cerr << errorStr << endl
04660                              << "    Registry for specified origin ID #" << originId << " not found." << endl;
04661                         break;
04662                     }
04663                 }
04664             }
04665 
04666           // Find specified condition in the collection.
04667 
04668             CdbCPtr< CdbRooRoConditionR > persistentConditionPtr;
04669 
04670             if( CdbStatus::Success != conditionOwnerRegistryPtr->conditionCollection( )->find( conditionId,
04671                                                                                                persistentConditionPtr )) {
04672                 cerr << errorStr << endl
04673                      << "    Condition with ID #" << conditionId << " not found" << endl
04674                      << "    at the collection with the origin ID #" << originId << endl;
04675                 break;
04676             }
04677 
04678           // Get the characteristics of the condition
04679           // Currently there are two of them:
04680           //
04681           // - its creation time. We would need this information
04682           //   when looking for a subset of increments including or newer
04683           //   than that time. The reason is that conditions could be created
04684           //   later on when a number of increments for a cluster/partition may
04685           //   already exist.
04686           //
04687           // - its "partitionable" property. This will tell us which (of two)
04688           //   groups of clusters we should use. Partitionable conditions
04689           //   go into a separate set of clusters.
04690 
04691             BdbTime creationTime        = persistentConditionPtr->created( );
04692             bool    isPartitionableFlag = persistentConditionPtr->isPartitionable( );
04693 
04694             CdbCPtr< CdbRooRoPartitionR > persistentPartitionPtr;
04695 
04696             if( isPartitionableFlag ) {
04697 
04698               // Use master to get general information about the partition
04699 
04700                 if( CdbStatus::Success != theMasterRegistryPtr->partitionsLayout( )->find( thePartitionId,
04701                                                                                            persistentPartitionPtr )) {
04702                     cerr << errorStr << endl
04703                          << "    Partition with ID #" << thePartitionId << " not found" << endl
04704                          << "    at the master collection." << endl;
04705                     break;
04706                 }
04707 
04708               // Check if this partition is available
04709 
04710                 if( theLocalRegistryPtr->originId( ) == persistentPartitionPtr->originId( )) {
04711 
04712                   // Switch to the actual partition object if the current database
04713                   // is not the master one and if the partition belongs to the current database.
04714                   // Then the current (local) database is the ultimate source of information.
04715 
04716                     if( theLocalRegistryPtr->originId( ) != theMasterRegistryPtr->originId( )) {
04717 
04718                         if( CdbStatus::Success != theLocalRegistryPtr->partitionsLayout( )->find( thePartitionId,
04719                                                                                                   persistentPartitionPtr )) {
04720                             cerr << errorStr << endl
04721                                  << "    Partition with ID #" << thePartitionId << " not found" << endl
04722                                  << "    at the local (non-master) collection." << endl;
04723                             break;
04724                         }
04725                     }
04726                 }
04727                 if( !persistentPartitionPtr->isInstantiated( )) {
04728                     cerr << errorStr << endl
04729                          << "    Partition with ID #" << thePartitionId << " is not instantiated." << endl
04730                          << "    No MetaData containers should exist for this condition yet." << endl;
04731                     break;
04732                 }
04733             }
04734 
04735           // Get the range of increments for the condition/partition
04736           //
04737           // NOTE: We're using the condition creation time to determine the first
04738           //       increment inclusing this time. We do it because a condition may
04739           //       be created when a number of increments already exist in the cluster.
04740 
04741             UShort_t firstIncrement = 0;
04742             UShort_t lastIncrement  = 0;
04743             {
04744                 bool failed = false;
04745 
04746                 UShort_t numIncrements = 0;
04747 
04748                 if( isPartitionableFlag ) {
04749 
04750                     numIncrements = persistentPartitionPtr->numIncrements( );
04751                     for( UShort_t i = 0; i < numIncrements; ++i ) {
04752 
04753                         CdbRooRoIncrementR iVal;
04754                         if( CdbStatus::Success != persistentPartitionPtr->increment( i,
04755                                                                                      iVal )) {
04756                             failed = true;
04757                             break;
04758                         }
04759                         if( creationTime < iVal.end( )) {
04760                             firstIncrement = i;
04761                             break;
04762                         }
04763                     }
04764                     if( failed ) break;
04765 
04766                 } else {
04767 
04768                     CdbCPtr< CdbRooRoRClusterR > persistentClusterPtr;
04769 
04770                     if( CdbStatus::Success != conditionOwnerRegistryPtr->clusterCollection( )->find( persistentConditionPtr->clusterId( ),
04771                                                                                                      persistentClusterPtr )) {
04772                         cerr << errorStr << endl
04773                              << "    Cluster with ID #" << persistentConditionPtr->clusterId( ) << " not found" << endl
04774                              << "    at the collection with the origin ID #" << originId << endl;
04775                         break;
04776                     }
04777 
04778                     numIncrements = persistentClusterPtr->numIncrements( );
04779                     for( UShort_t i = 0; i < numIncrements; ++i ) {
04780 
04781                         CdbRooRoIncrementR iVal;
04782                         if( CdbStatus::Success != persistentClusterPtr->increment( i,
04783                                                                                    iVal )) {
04784                             failed = true;
04785                             break;
04786                         }
04787                         if( creationTime < iVal.end( )) {
04788                             firstIncrement = i;
04789                             break;
04790                         }
04791                     }
04792                     if( failed ) break;
04793 
04794                 }
04795                 if( numIncrements < 1 ) {
04796                     assert( 0 );
04797                     break;
04798                 }
04799                 lastIncrement = numIncrements - 1;
04800             }
04801 
04802           // Find metadata for specified increment(s)
04803           //
04804           // NOTE: Watch for the origin ID used in the look up operations. For 'REGULAR' conditions
04805           //       it's going to be the owner of the condition, meanwhile for the 'PARTITIONABLE'
04806           //       ones it will be an owner of the specified partition.
04807 
04808             UShort_t lookupOriginId = ( isPartitionableFlag ? persistentPartitionPtr->originId( ) : originId );
04809 
04810             std::vector< CdbCPtr< CdbRooRoMetaDataR > > vectorOfPtrs;
04811 
04812             CdbCPtr< CdbRooRoMetaDataR > mdPtr;
04813 
04814             if( allIncrementsFlag ) {
04815 
04816                 bool failed = false;
04817                 {
04818                     for( UShort_t i = firstIncrement; i <= lastIncrement; ++i ) {
04819 
04820                         if( CdbStatus::Success != CdbRooRoFileUtils::instance( ).findMetaData( mdPtr,
04821                                                                                                conditionId,
04822                                                                                                isPartitionableFlag,
04823                                                                                                thePartitionId,
04824                                                                                                persistentConditionPtr->clusterId( ),
04825                                                                                                i,
04826                                                                                                lookupOriginId )) {
04827 
04828                             cerr << errorStr << endl
04829                                  << "    Failed to find a MetaData object for increment #" << i << endl;
04830 
04831                             failed = true;
04832                             break;
04833                         }
04834                         vectorOfPtrs.push_back( mdPtr );
04835                     }
04836                 }
04837                 if( failed ) break;
04838 
04839             } else {
04840 
04841                 if( recentIncrementFlag ) {
04842 
04843                     if( CdbStatus::Success != CdbRooRoFileUtils::instance( ).findMetaData( mdPtr,
04844                                                                                            conditionId,
04845                                                                                            isPartitionableFlag,
04846                                                                                            thePartitionId,
04847                                                                                            persistentConditionPtr->clusterId( ),
04848                                                                                            lastIncrement,
04849                                                                                            lookupOriginId )) {
04850 
04851                         cerr << errorStr << endl
04852                              << "    Failed to find a MetaData object for recent increment #" << lastIncrement << endl;
04853                         break;
04854                     }
04855                     vectorOfPtrs.push_back( mdPtr );
04856 
04857                 } else {
04858 
04859                     if( theIncrementNumber > lastIncrement ) {
04860                         cerr << errorStr << endl
04861                              << "    Passed increment number is not valid." << endl
04862                              << "        PASSED NUMBER:       " << theIncrementNumber << endl
04863                              << "        MAX.POSSIBLE NUMBER: " << lastIncrement << endl;
04864                         break;
04865                     }
04866                     if( CdbStatus::Success != CdbRooRoFileUtils::instance( ).findMetaData( mdPtr,
04867                                                                                            conditionId,
04868                                                                                            isPartitionableFlag,
04869                                                                                            thePartitionId,
04870                                                                                            persistentConditionPtr->clusterId( ),
04871                                                                                            theIncrementNumber,
04872                                                                                            originId )) {
04873                         cerr << errorStr << endl
04874                              << "    Failed to find a MetaData object for specified increment #" << theIncrementNumber << endl;
04875                         break;
04876                     }
04877                     vectorOfPtrs.push_back( mdPtr );
04878                 }
04879             }
04880 
04881           // Done
04882 
04883             theVectorOfPtrs = vectorOfPtrs;
04884             result          = CdbStatus::Success;
04885 
04886         } while( false );
04887 
04888         return result;
04889     }
04890 
04891   ////////////////////////////////////
04892   // End Of The Anonymous Namespace //
04893   ////////////////////////////////////
04894 
04895 }
04896 
04897 /////////////////
04898 // End Of File //
04899 /////////////////

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