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

CdbSQLApiCondition.cc

Go to the documentation of this file.
00001 // File and Version Information:
00002 //      $Id: CdbSQLApiCondition.cc,v 1.3 2005/09/22 00:01:56 gapon Exp $
00003 
00004 /// The implementation of the CdbSQLApiCondition class.
00005 /**
00006   * @see CdbSQLApiCondition
00007   */
00008 #include "CdbSQL/CdbSQLApi.hh"
00009 #include "CdbSQL/CdbSQLApiCondition.hh"
00010 #include "CdbSQL/CdbSQLApiRevision.hh"
00011 #include "CdbSQL/CdbSQLOrigin.hh"
00012 #include "CdbSQL/CdbSQLPartition.hh"
00013 #include "CdbSQL/CdbSQLCondition.hh"
00014 #include "CdbSQL/CdbSQLRevision.hh"
00015 #include "CdbSQL/CdbSQLView.hh"
00016 #include "CdbSQL/CdbSQLFolder.hh"
00017 #include "CdbSQL/CdbSQLConditionAtFolder.hh"
00018 #include "CdbSQL/CdbSQLVisibleObject.hh"
00019 #include "CdbSQL/CdbSQLOriginalObject.hh"
00020 
00021 #include "CdbBase/CdbEnvironment.hh"
00022 #include "CdbBase/Cdb.hh"
00023 #include "CdbBase/CdbDatabase.hh"
00024 #include "CdbBase/CdbView.hh"
00025 #include "CdbBase/CdbFolder.hh"
00026 #include "CdbBase/CdbRevision.hh"
00027 #include "CdbBase/CdbRevisionPolicy.hh"
00028 #include "CdbBase/CdbConfigElement.hh"
00029 #include "CdbBase/CdbObject.hh"
00030 #include "CdbBase/CdbObjectFactoryBase.hh"
00031 #include "CdbBase/CdbItr.hh"
00032 #include "CdbBase/CdbId.hh"
00033 #include "CdbBase/CdbCompositeName.hh"
00034 #include "CdbBase/CdbTimeUtils.hh"
00035 #include "CdbBase/CdbDebugStream.hh"
00036 #include "CdbBase/CdbVectorAdapterItr.hh"
00037 #include "CdbBase/CdbSimpleVectorAdapterItr.hh"
00038 #include "CdbBase/CdbCompositeItr.hh"
00039 #include "CdbBase/CdbAdapterItr.hh"
00040 #include "CdbBase/CdbEmptyItr.hh"
00041 
00042 #include "BdbTime/BdbTime.hh"
00043 
00044 #include "ErrLogger/ErrLog.hh"
00045 
00046 #include <stdio.h>
00047 #include <assert.h>
00048 
00049 #include <vector>
00050 #include <stack>
00051 
00052 #include <iostream>
00053 using std::cout;
00054 using std::endl;
00055 
00056 namespace {
00057 
00058   ///////////////////////////////
00059   // Class: RevisionIdIterator //
00060   ///////////////////////////////
00061 
00062     class RevisionIdIterator : public CdbVectorAdapterItr< BdbTime, CdbCPtr<CdbSQLRevision> > {
00063 
00064     private:
00065 
00066         RevisionIdIterator( );
00067 
00068         RevisionIdIterator& operator=( const RevisionIdIterator& theItr );
00069 
00070     protected:
00071 
00072         RevisionIdIterator( const RevisionIdIterator& theItr ) :
00073             CdbVectorAdapterItr< BdbTime, CdbCPtr<CdbSQLRevision> >( theItr )
00074         { }
00075 
00076     public:
00077 
00078         RevisionIdIterator( const std::vector< CdbCPtr<CdbSQLRevision> >& theVectorOfRevisions ) :
00079             CdbVectorAdapterItr< BdbTime, CdbCPtr<CdbSQLRevision> >( theVectorOfRevisions )
00080         { }
00081 
00082         virtual ~RevisionIdIterator( )
00083         { }
00084 
00085         virtual CdbIItr< BdbTime >* clone( ) const
00086         {
00087             return new RevisionIdIterator( *this );
00088         }
00089 
00090     protected:
00091 
00092       /// User defined translation for the currently reffered value.
00093       /**
00094         * Implement the corresponding method defined in a base clas or an interface.
00095         *
00096         * @see class CdbVectorAdapterItr
00097         */
00098         virtual BdbTime toValue( const CdbCPtr<CdbSQLRevision>& theRevisionPtr ) const
00099         {
00100             return theRevisionPtr->id( );
00101         }
00102     };
00103 
00104   /////////////////////////////////
00105   // Class: RevisionNameIterator //
00106   /////////////////////////////////
00107 
00108     class RevisionNameIterator : public CdbVectorAdapterItr< const char*, CdbCPtr<CdbSQLRevision> > {
00109 
00110     private:
00111 
00112         RevisionNameIterator( );
00113 
00114         RevisionNameIterator& operator=( const RevisionNameIterator& theItr );
00115 
00116     protected:
00117 
00118         RevisionNameIterator( const RevisionNameIterator& theItr ) :
00119             CdbVectorAdapterItr< const char*, CdbCPtr<CdbSQLRevision> >( theItr ),
00120             _value(theItr._value)
00121         { }
00122 
00123     public:
00124 
00125         RevisionNameIterator( const std::vector< CdbCPtr<CdbSQLRevision> >& theVectorOfRevisions ) :
00126             CdbVectorAdapterItr< const char*, CdbCPtr<CdbSQLRevision> >( theVectorOfRevisions ),
00127             _value("")
00128         { }
00129 
00130         virtual ~RevisionNameIterator( )
00131         { }
00132 
00133       // Need to implement this operation since we have locally defined data members
00134 
00135         virtual CdbIItr< const char* >* clone( ) const
00136         {
00137             return new RevisionNameIterator( *this );
00138         }
00139 
00140     protected:
00141 
00142       /// User defined translation for the currently reffered value.
00143       /**
00144         * Implement the corresponding method defined in a base clas or an interface.
00145         *
00146         * @see class CdbVectorAdapterItr
00147         */
00148         virtual const char* toValue( const CdbCPtr<CdbSQLRevision>& theRevisionPtr ) const
00149         {
00150             _value = theRevisionPtr->name( );
00151             return _value.c_str( );
00152         }
00153 
00154     private:
00155 
00156       // Current value
00157       //
00158       // DESIGN NOTE: We must to have the one since the current iterator
00159       //              is supposed to return plain C string pointers. These pointers
00160       //              can't be obtained from temporary objects.
00161 
00162         mutable std::string _value; 
00163     };
00164 
00165   /////////////////////////////////////////////////
00166   // Class: PersistentToTransientIteratorAdapter //
00167   /////////////////////////////////////////////////
00168   //
00169   // Retranslate persistent visible objects into the transient CDB API ones
00170     
00171     class PersistentToTransientIteratorAdapter : public CdbAdapterItr< CdbObjectPtr,
00172                                                                        CdbCPtr<CdbSQLVisibleObject> > {
00173     private:
00174 
00175         PersistentToTransientIteratorAdapter( );
00176 
00177         PersistentToTransientIteratorAdapter& operator=( const PersistentToTransientIteratorAdapter& theItr );
00178 
00179     protected:
00180 
00181         PersistentToTransientIteratorAdapter( const PersistentToTransientIteratorAdapter& theItr ) :
00182             CdbAdapterItr< CdbObjectPtr,
00183                            CdbCPtr<CdbSQLVisibleObject> >( theItr ),
00184             _myParentPtr(theItr._myParentPtr)
00185         { }
00186 
00187     public:
00188 
00189       /// Normal constructor
00190 
00191 
00192         PersistentToTransientIteratorAdapter( CdbIItr< CdbCPtr<CdbSQLVisibleObject> >* theInputItrPtr,
00193                                               const CdbConditionPtr&                   theParentPtr ) :
00194             CdbAdapterItr< CdbObjectPtr,
00195                            CdbCPtr<CdbSQLVisibleObject> >( theInputItrPtr ),
00196             _myParentPtr(theParentPtr)
00197         { }
00198 
00199         virtual ~PersistentToTransientIteratorAdapter( )
00200         { }
00201 
00202         virtual CdbIItr< CdbObjectPtr >* clone( ) const
00203         {
00204             return new PersistentToTransientIteratorAdapter( *this );
00205         }
00206 
00207     protected:
00208 
00209         virtual CdbObjectPtr toValue( const CdbCPtr<CdbSQLVisibleObject>& thePersistentObjectPtr ) const
00210         {
00211             const char* fatalStr = "CdbSQLApiCondition::<anonymous>::PersistentToTransientIteratorAdapter::toValue() -- FATAL ERROR.";
00212 
00213             assert( !thePersistentObjectPtr.isNull( ));
00214 
00215           // Get to the top CDB API object at a level of CdbSQLApi. We need this object
00216           // in order to invoke the final object creator.
00217           //
00218           // @see CdbSQLApi::createObject()
00219 
00220             CdbCPtr<CdbSQLApi> ptr = (const CdbCPtr<CdbSQLApi>&)_myParentPtr->parentDatabase( )->parent( );
00221 
00222           // Construct the current value of the iterator and return with success.
00223 
00224             CdbObjectPtr result;
00225             CdbStatus status = ptr->createObject( result,
00226                                                   _myParentPtr,
00227                                                   thePersistentObjectPtr->begin( ),     // original validity begin
00228                                                   thePersistentObjectPtr->end( ),       // original validity end
00229                                                   thePersistentObjectPtr->begin( ),     // visible validity begin
00230                                                   thePersistentObjectPtr->end( ),       // visible validity end
00231                                                   thePersistentObjectPtr->stored( ),    // begin of the "duration" period
00232                                                   BdbTime::plusInfinity,                // end   of the "duration" period
00233                                                   thePersistentObjectPtr->stored( ),
00234                                                   thePersistentObjectPtr->id( ));
00235             if( CdbStatus::Success != status ) {
00236                 ErrMsg(fatal) << fatalStr << endl
00237                               << "    Failed to produce a metadata object for the found persistent object because" << endl
00238                               << "    of the following status: " << status << " returned by an object creator." << endmsg;
00239             }
00240             return result;
00241         }
00242 
00243         virtual bool isAccepted( const CdbCPtr<CdbSQLVisibleObject>& thePersistentObjectPtr ) const
00244         {
00245             assert( !thePersistentObjectPtr.isNull( ));
00246 
00247           // Skip non-valid objects
00248 
00249             return thePersistentObjectPtr->isValid( );
00250         }
00251 
00252     private:
00253 
00254         CdbConditionPtr _myParentPtr;
00255     };
00256 
00257   ////////////////////////////////////////
00258   // Class: VisibleObjectIteratorAdapter //
00259   ////////////////////////////////////////
00260   //
00261   // This class translate configuration elements of an input iterator into iterators
00262   // of visible objects. Each configuration elements maps into one output iterator.
00263 
00264     class VisibleObjectIteratorAdapter : public CdbAdapterItr< CdbObjectItr,
00265                                                                CdbConfigElement > {
00266     private:
00267 
00268         VisibleObjectIteratorAdapter( );
00269 
00270         VisibleObjectIteratorAdapter& operator=( const VisibleObjectIteratorAdapter& theItr );
00271 
00272     protected:
00273 
00274         VisibleObjectIteratorAdapter( const VisibleObjectIteratorAdapter& theItr ) :
00275             CdbAdapterItr< CdbObjectItr,
00276                            CdbConfigElement >( theItr ),
00277             _myConditionPtr(theItr._myConditionPtr),
00278             _myParentPtr   (theItr._myParentPtr),
00279             _beginTime     (theItr._beginTime),
00280             _endTime       (theItr._endTime)
00281         { }
00282 
00283     public:
00284 
00285       /// Normal constructor
00286 
00287 
00288         VisibleObjectIteratorAdapter( CdbIItr<CdbConfigElement>*      theInputItrPtr,
00289                                       const CdbCPtr<CdbSQLCondition>& theConditionPtr,
00290                                       const CdbConditionPtr&          theParentPtr,
00291                                       const BdbTime&                  theBeginTime = BdbTime::minusInfinity,
00292                                       const BdbTime&                  theEndTime   = BdbTime::plusInfinity ) :
00293             CdbAdapterItr< CdbObjectItr,
00294                            CdbConfigElement >( theInputItrPtr ),
00295             _myConditionPtr(theConditionPtr),
00296             _myParentPtr   (theParentPtr),
00297             _beginTime     (theBeginTime),
00298             _endTime       (theEndTime)
00299         { }
00300 
00301         virtual ~VisibleObjectIteratorAdapter( )
00302         { }
00303 
00304       // Need to implement this operation since we have locally defined data members
00305 
00306         virtual CdbIItr< CdbObjectItr >* clone( ) const
00307         {
00308             return new VisibleObjectIteratorAdapter( *this );
00309         }
00310 
00311     protected:
00312 
00313       /// User defined translation for the currently referred value.
00314       /**
00315         * This implements the corresponding method of the base class.
00316         *
00317         * IMPLEMENTATION NOTES:
00318         *
00319         *   - This method will use an input configuration element to find visible objects
00320         *   in a scope of the cached condition and produce an iterator of visible CDB API
00321         *   objects out of the found seqeunce.
00322         *
00323         *   - The cached [begin,end) validity timeline limits will also be taken into
00324         *   and account as follows:
00325         *
00326         *     o If the validity limit of the configuration elements is falling of the cached
00327         *     limits then an empty iterator will be returned.
00328         *
00329         *     o The visible validity limits of the output objects would also be properly
00330         *     adjusted should they cross either border.
00331         *
00332         *   - IMPORTANT: Since we're not allowed (according to teh current BaBar Computing/Programming
00333         *     policy) to use exceptions and since we have no mechanism to return a error
00334         *     status value up to a caller then the method will abort an application
00335         *     in case of any failure inside the method. This will also apply to an unsupported
00336         *     configuration passed as the method's parameter.
00337         *
00338         * @see CdbAdapterItr::toValue()
00339         */
00340         virtual CdbObjectItr toValue( const CdbConfigElement& theConfigElement ) const
00341         {
00342             const char* fatalStr = "<anonymous>::VisibleObjectIteratorAdapter::toValue() -- FATAL ERROR";
00343 
00344           // IMPLEMENTATION RESTRICTION:
00345           //
00346           //   The current implementation of the iterator does not allow browsing intervals
00347           //   based on the "do not use revision" revision policy. In fact, thsi type of access
00348           //   is not fully supported in the present implementation of CDB.
00349 
00350             if( !theConfigElement.policy.useRevision( ))
00351                 ErrMsg(fatal) << fatalStr << endl
00352                               << "    Unsupported revision policy has been detected in the current configuration" << endl
00353                               << "    of the condition." << endl
00354                               << "        CONDITION PATH: \"" << CdbCondition::fullPathName( _myParentPtr ) << "\"" << endmsg;
00355 
00356           // Check if we the element is outside the limits or if accessing a validity
00357           // interval covered by the configuration is allowed. If so then return an empty
00358           // iterator.
00359 
00360             if( !theConfigElement.accessIsAllowed  ||       // the view (at the configured interval) prohibits accessing objects
00361                 theConfigElement.begin >= _endTime ||       // the configuration interval begins after the desired period ends
00362                 theConfigElement.end   <= _beginTime ) {    // the configuration interval ends before the desired period begins
00363 
00364                 return CdbObjectItr( new CdbEmptyItr< CdbObjectPtr >( ));
00365             }
00366 
00367           // Find an overlapping interval between the desired validity interval and the one
00368           // in the passed configuration element.
00369 
00370             const BdbTime adjustedBeginTime = ( theConfigElement.begin > _beginTime ? theConfigElement.begin : _beginTime );
00371             const BdbTime adjustedEndTime   = ( theConfigElement.end   < _endTime   ? theConfigElement.end   : _endTime   );
00372 
00373             assert( adjustedBeginTime != adjustedEndTime ); // in case if we're having an implementation bug
00374 
00375           // Make a database query to get a list of persistent visible intervals for
00376           // the above determined "adjusted" period of the validity time.
00377 
00378             std::vector< CdbCPtr<CdbSQLVisibleObject> > objects;
00379 
00380             if( CdbStatus::Success != _myConditionPtr->visible_objects( objects,
00381                                                                         theConfigElement.policy.partitionId( ),
00382                                                                         theConfigElement.policy.revisionId( ),
00383                                                                         adjustedBeginTime,
00384                                                                         adjustedEndTime ))
00385                 ErrMsg(fatal) << fatalStr << endl
00386                               << "    Failed to obtain a list of visible object from the condition." << endl
00387                               << "        CONDITION PATH: \"" << CdbCondition::fullPathName( _myParentPtr ) << "\"" << endl
00388                               << "        PARTITION     : "   << theConfigElement.policy.partitionId( ) << endl
00389                               << "        REVISION      : "   << CdbTimeUtils::time2string( theConfigElement.policy.revisionId( )) << " : " << theConfigElement.policy.revisionId( ) << endl
00390                               << "        BEGIN TIME    : "   << CdbTimeUtils::time2string( adjustedBeginTime                    ) << " : " << adjustedBeginTime << endl
00391                               << "        END  TIME     : "   << CdbTimeUtils::time2string( adjustedEndTime                      ) << " : " << adjustedEndTime << endmsg;
00392 
00393           // Turn the found vector into an iterator of the same type of elements, then feed
00394           // the resulting iterator itself into an adapter for retranslation from visible
00395           // "persistent" objects into the "transient" ones.
00396           //
00397           // NOTE: We'll also sending the cached pointer onto the CDB API "owner" object which
00398           //       is needed to construct the transient CDB API objects.
00399 
00400             return CdbObjectItr( new PersistentToTransientIteratorAdapter( new CdbSimpleVectorAdapterItr< CdbCPtr<CdbSQLVisibleObject> >( objects ),
00401                                                                            _myParentPtr ));
00402         }
00403 
00404     private:
00405 
00406         CdbCPtr<CdbSQLCondition> _myConditionPtr;
00407         CdbConditionPtr          _myParentPtr;
00408 
00409         BdbTime _beginTime;
00410         BdbTime _endTime;
00411     };
00412 
00413   ///////////////////////////////////
00414   // Class: OriginalObjectIterator //
00415   ///////////////////////////////////
00416   //
00417   // Retranslate persistent original objects into the transient CDB API ones
00418 
00419     class OriginalObjectIterator : public CdbAdapterItr< CdbObjectPtr,
00420                                                          CdbCPtr<CdbSQLOriginalObject> > {
00421     private:
00422 
00423         OriginalObjectIterator( );
00424 
00425         OriginalObjectIterator& operator=( const OriginalObjectIterator& theItr );
00426 
00427     protected:
00428 
00429         OriginalObjectIterator( const OriginalObjectIterator& theItr ) :
00430             CdbAdapterItr< CdbObjectPtr,
00431                            CdbCPtr<CdbSQLOriginalObject> >( theItr ),
00432             _myParentPtr(theItr._myParentPtr)
00433         { }
00434 
00435     public:
00436 
00437       /// Normal constructor
00438 
00439         OriginalObjectIterator( CdbIItr< CdbCPtr<CdbSQLOriginalObject> >* theInputItrPtr,
00440                                 const CdbConditionPtr&                    theParentPtr ) :
00441             CdbAdapterItr< CdbObjectPtr,
00442                            CdbCPtr<CdbSQLOriginalObject> >( theInputItrPtr ),
00443             _myParentPtr(theParentPtr)
00444         { }
00445 
00446         virtual ~OriginalObjectIterator( )
00447         { }
00448 
00449         virtual CdbIItr< CdbObjectPtr >* clone( ) const
00450         {
00451             return new OriginalObjectIterator( *this );
00452         }
00453 
00454     protected:
00455 
00456         virtual CdbObjectPtr toValue( const CdbCPtr<CdbSQLOriginalObject>& thePersistentObjectPtr ) const
00457         {
00458             const char* fatalStr = "CdbSQLApiCondition::<anonymous>::OriginalObjectIterator::toValue() -- FATAL ERROR.";
00459 
00460             assert( !thePersistentObjectPtr.isNull( ));
00461 
00462           // Get to the top CDB API object at a level of CdbSQLApi. We need this object
00463           // in order to invoke the final object creator.
00464           //
00465           // @see CdbSQLApi::createObject()
00466 
00467             CdbCPtr<CdbSQLApi> ptr = (const CdbCPtr<CdbSQLApi>&)_myParentPtr->parentDatabase( )->parent( );
00468 
00469           // Construct the current value of the iterator and return with success.
00470 
00471             CdbObjectPtr result;
00472             CdbStatus status = ptr->createObject( result,
00473                                                   _myParentPtr,
00474                                                   thePersistentObjectPtr->begin( ),     // original validity begin
00475                                                   thePersistentObjectPtr->end( ),       // original validity end
00476                                                   thePersistentObjectPtr->begin( ),     // visible validity begin
00477                                                   thePersistentObjectPtr->end( ),       // visible validity end
00478                                                   thePersistentObjectPtr->stored( ),    // begin of the "duration" period
00479                                                   BdbTime::plusInfinity,                // end   of the "duration" period
00480                                                   thePersistentObjectPtr->stored( ),
00481                                                   thePersistentObjectPtr->id( ));
00482             if( CdbStatus::Success != status ) {
00483                 ErrMsg(fatal) << fatalStr << endl
00484                               << "    Failed to produce a metadata object for the found persistent object because" << endl
00485                               << "    of the following status: " << status << " returned by an object creator." << endmsg;
00486             }
00487             return result;
00488         }
00489 
00490     private:
00491 
00492         CdbConditionPtr _myParentPtr;
00493     };    
00494 }
00495 
00496 ////////////////////////////////////
00497 /// Class: CdbSQLApiCondition //
00498 ////////////////////////////////////
00499 
00500 CdbCondition*
00501 CdbSQLApiCondition::clone( ) const
00502 {
00503     return new CdbSQLApiCondition( *this );
00504 }
00505 
00506 CdbSQLApiCondition::CdbSQLApiCondition( const CdbFolderPtr&                     theFolderPtr,
00507                                         const CdbDatabasePtr&                   theDatabasePtr,
00508                                         const char*                             theName,
00509                                         const CdbCPtr<CdbSQLConditionAtFolder>& theConditionAtFolderPtr,
00510                                         const CdbCPtr<CdbSQLCondition>&         theConditionPtr,
00511                                         const CdbCPtr<CdbSQLOrigin>&            theMasterOriginPtr,
00512                                         const CdbCPtr<CdbSQLOrigin>&            theLocalOriginPtr ) :
00513     CdbCondition( theFolderPtr,
00514                   theDatabasePtr,
00515                   theName ),
00516     _myConditionAtFolderPtr(theConditionAtFolderPtr),
00517     _myConditionPtr        (theConditionPtr),
00518     _myMasterSQLOriginPtr  (theMasterOriginPtr),
00519     _myLocalSQLOriginPtr   (theLocalOriginPtr)
00520 {
00521     const char* fatalStr = "CdbSQLApiCondition::CdbSQLApiCondition() -- FATAL ERROR IN THE CONSTRUCTOR";
00522 
00523     if( theConditionPtr.isNull( ))
00524         ErrMsg(fatal) << fatalStr << endl
00525                       << "    A null pointer onto 'physical' condition object passed as a paremeter." << endmsg;
00526 
00527     if( theMasterOriginPtr.isNull( ))
00528         ErrMsg(fatal) << fatalStr << endl
00529                       << "    A null pointer onto the MASTER origin object passed as a paremeter." << endmsg;
00530 
00531     if( theLocalOriginPtr.isNull( ))
00532         ErrMsg(fatal) << fatalStr << endl
00533                       << "    A null pointer onto the local origin object passed as a paremeter." << endmsg;
00534 }
00535 
00536 CdbSQLApiCondition::CdbSQLApiCondition( const CdbSQLApiCondition& theCondition ) :
00537     CdbCondition( theCondition ),
00538     _myConditionAtFolderPtr(theCondition._myConditionAtFolderPtr),
00539     _myConditionPtr        (theCondition._myConditionPtr),
00540     _myMasterSQLOriginPtr  (theCondition._myMasterSQLOriginPtr),
00541     _myLocalSQLOriginPtr   (theCondition._myLocalSQLOriginPtr)
00542 { }
00543 
00544 CdbSQLApiCondition::~CdbSQLApiCondition( )
00545 { }
00546 
00547 std::string
00548 CdbSQLApiCondition::description( ) const
00549 {
00550     if( _myConditionAtFolderPtr.isNull( )) return _myConditionPtr->description( );
00551     return _myConditionAtFolderPtr->description( );
00552 }
00553 
00554 bool
00555 CdbSQLApiCondition::isPartitionable( ) const
00556 {
00557     return _myConditionPtr->isPartitionable( );
00558 }
00559 
00560 CdbCompositeName
00561 CdbSQLApiCondition::physicalName( ) const
00562 {
00563     return CdbCompositeName( _myConditionPtr->parent( )->name( ).c_str( ),
00564                              _myConditionPtr->name( ).c_str( ));
00565 }
00566 
00567 CdbId
00568 CdbSQLApiCondition::physicalId( ) const
00569 {
00570     return CdbId( _myConditionPtr->parent( )->id( ),
00571                   _myConditionPtr->id( ));
00572 }
00573 
00574 BdbTime
00575 CdbSQLApiCondition::created( ) const
00576 {
00577     return _myConditionPtr->created( );
00578 }
00579 
00580 BdbTime
00581 CdbSQLApiCondition::registered( ) const
00582 {
00583     if( _myConditionAtFolderPtr.isNull( )) return _myConditionPtr->created( );
00584     return _myConditionAtFolderPtr->created( );
00585 }
00586 
00587 BdbTime
00588 CdbSQLApiCondition::modified( ) const
00589 {
00590     const char* errorStr = "CdbSQLApiCondition::modified() -- ERROR";
00591 
00592     BdbTime result = BdbTime::minusInfinity;    // this default value means a failure of the algorithm
00593 
00594     do {
00595 
00596       /*
00597        * =================
00598        * EXECUTION PATH I: 'physical address' conditions only
00599        * =================
00600        *
00601        * This path is not currently implemented. A complicated algorithm to iterate
00602        * over a validity timeline of the "topmost" partitions would be needed for
00603        * PARTITIONABLE conditions. Things are trivial for REGULAR conditions though.
00604        * However to avoid an incomplete implementation of this part of the code let's just
00605        * postpone it as a whole.
00606        *
00607        * AN IDEA: Having a super-iterator composed of elementary iterators for individual
00608        *          "topmost" partitions would be a good idea. That would require to extend
00609        *          the API of P-Layout to deliver an iterator of "topmost" partitions. The
00610        *          one currently available does not respect non-instantiated partitions.
00611        */
00612 
00613         if( _myConditionAtFolderPtr.isNull( )) break;
00614 
00615       /*
00616        * ==================
00617        * EXECUTION PATH II: 'view/folder/config' conditions only
00618        * ==================
00619        *
00620        * HOW THIS ALGORITHM IS IMPLEMENTED:
00621        *
00622        *   The code below will iterate through the configuration intervals and depending
00623        *   on a configuration of an interval will either use the timestamp of the specified
00624        *   revision (for non-topmost revisions) or directly scan the condition/partition.
00625        *
00626        *   IMPORTANT:
00627        *
00628        *     The result delivered by the algorithm will depend on a particular configuration
00629        *     of the condition. In other words, in the current model of conditions, a value
00630        *     of the "modification timestamp" should be read in the context of "...from
00631        *     the point of view of the specified view...".
00632        */
00633 
00634         std::vector<CdbConfigElement> config_elements;
00635         if( CdbStatus::Success != _myConditionAtFolderPtr->config_elements( config_elements )) {
00636             ErrMsg(error) << errorStr << endl
00637                           << "    Failed to get a list of configuration elements for the current condition." << endl
00638                           << "        CONDITION NAME : \"" << _myConditionAtFolderPtr->name( ) << "\"." << endmsg;
00639             break;
00640         }
00641         unsigned int nElements = config_elements.size( );
00642 
00643         for( unsigned int iElement = 0; iElement < nElements; ++iElement ) {
00644 
00645             CdbConfigElement configElement = config_elements[iElement];
00646 /*
00647 cout << "CdbSQLApiCondition::modified( ) - CONFIG ELEMENT - " << iElement << "/" << nElements << " {" << endl
00648      << "  accessIsAllowed    : " << configElement.accessIsAllowed << endl
00649      << "  policy.useRevision : " << configElement.policy.useRevision( ) << endl
00650      << "  policy.revisionId  : " << CdbTimeUtils::time2string( configElement.policy.revisionId( )) << endl
00651      << "  policy.partitionId : " << configElement.policy.partitionId( ) << endl
00652      << "  begin              : " << CdbTimeUtils::time2string( configElement.begin ) << endl
00653      << "  end                : " << CdbTimeUtils::time2string( configElement.end ) << endl
00654      << "}" << endl;
00655 */
00656           // Skeep the found element if it tells us that the corresponding range of the validity
00657           // timeline is not accessible for the current application.
00658 
00659             if( !configElement.accessIsAllowed ) continue;
00660 
00661           // If we're supposed to use revisions and if this is not the 'topmost' one
00662           // then then we use that revision ID as the modification time.
00663 
00664             BdbTime modificationTime = BdbTime::minusInfinity;
00665             if( configElement.policy.useRevision( ) && ( BdbTime::plusInfinity != configElement.policy.revisionId( ))) {
00666                 modificationTime = configElement.policy.revisionId( );
00667             } else {
00668 
00669               // Otherwise we use the modification time of the condition at
00670               // the specified partition.
00671 
00672                 if( CdbStatus::Success != _myConditionPtr->modified( modificationTime,
00673                                                                      configElement.policy.partitionId( ))) {
00674 
00675                     ErrMsg(error) << errorStr << endl
00676                                   << "    Failed to get the modification of configuration elements for the current condition/partition." << endl
00677                                   << "        CONDITION NAME : \"" << _myConditionAtFolderPtr->name( ) << "\"" << endl
00678                                   << "        PARTITION      : " << configElement.policy.partitionId( ) << "." << endmsg;
00679                     break;
00680                 }
00681             }
00682             assert( BdbTime::minusInfinity != modificationTime );   // something is broken in the algorithm above
00683             assert( BdbTime::plusInfinity  != modificationTime );   // something is broken in the algorithm above
00684 
00685           // Check if the found time is newer than the one we have now.
00686 
00687             if( modificationTime > result ) result = modificationTime;
00688         }
00689 
00690       // Done.
00691 
00692     } while( false );
00693 
00694     return result;
00695 
00696 }
00697 
00698 CdbStatus
00699 CdbSQLApiCondition::findObject( CdbObjectPtr&  theObjectPtr,
00700                                 const BdbTime& theValidityTime,
00701                                 const BdbTime& theInsertionTime )
00702 {
00703     const char* errorStr = "CdbSQLApiCondition::findObject(validity,insertion) -- ERROR";
00704 
00705   /*
00706    * =================
00707    * EXECUTION PATH I: 'physical address' conditions only
00708    * =================
00709    *
00710    * If the condition is available by its 'physical address' only
00711    * then we don't have any asociation with views & folders, therefore no such things
00712    * as condition configurations are available. The "insertion" time will play a role
00713    * of the secondary (in addition to the validity time) key. Here are the rules
00714    * for different values of the insertion time and condition types
00715    *
00716    *   o if the insertion time is +Infinity then:
00717    *
00718    *     REGULAR       : the TOPMOST revision will always be used
00719    *
00720    *     PARTITIONABLE : the most recent revision of the "topmost" (at given validity time)
00721    *                     partition will be used. In case if this is an "open" partition
00722    *                     then its TOPMOST revision will be used.
00723    *
00724    *   o for any other values of the insertion time:
00725    *
00726    *     REGULAR       : the specified insertion time would be used
00727    *
00728    *     PARTITIONABLE : the specified insertion time would be used
00729    */
00730 
00731     if( _myConditionAtFolderPtr.isNull( )) {
00732 
00733       // The default constructor of the policy would assume that we're going
00734       // to use the actual insertion time rather than any explicitly found revision.
00735 
00736         CdbRevisionPolicy rPolicy;
00737 
00738         if( BdbTime::plusInfinity == theInsertionTime ) {
00739 
00740           // Okay, we need to find the most recent partition & revision
00741 
00742             if( _myConditionPtr->isPartitionable( )) {
00743 
00744               // Find an appropriate partition for the specified validity and insertion
00745               // timestamps.
00746               //
00747               // @see CdbSQLApiCondition::findInitialPartition()
00748 
00749                 CdbCPtr<CdbSQLPartition> partitionPtr;
00750 
00751                 if( CdbStatus::Success != findInitialPartition( partitionPtr,
00752                                                                 theValidityTime,
00753                                                                 theInsertionTime )) {
00754 
00755                     ErrMsg(error) << errorStr << endl
00756                                   << "    Failed to find an initial partition for the specified validity and insertion" << endl
00757                                   << "    for a condition found by its 'physical address'." << endl
00758                                   << "        PHYSICAL CONDITION ADDRESS : " << physicalId( ) << endl
00759                                   << "        VALIDITY TIME              : " << CdbTimeUtils::time2string( theValidityTime )  << " : " << theValidityTime  << endl
00760                                   << "        INSERTION TIME             : " << CdbTimeUtils::time2string( theInsertionTime ) << " : " << theInsertionTime << endmsg;
00761 
00762                     return CdbStatus::Error;
00763                 }
00764 
00765               // Find the most recent (can be "<topmost>" if the partition is in the "open"
00766               // state) revision in the partition.
00767 
00768                 BdbTime rId = BdbTime::minusInfinity;
00769 
00770                 if( CdbStatus::Success != _myConditionPtr->topmost_revision_id( rId,
00771                                                                                 partitionPtr->id( ))) {
00772 
00773                     ErrMsg(error) << errorStr << endl
00774                                   << "    Failed to find a topmost revision in the partition #" << partitionPtr->id( ) << " for a condition" << endl
00775                                   << "    found by its 'physical address'." << endl
00776                                   << "        PHYSICAL CONDITION ADDRESS : " << physicalId( ) << endmsg;
00777 
00778                     return CdbStatus::Error;
00779                 }
00780                 assert( BdbTime::minusInfinity != rId );    // check for a bug in the API
00781 
00782               // Use the just found revision and partition ids for PARTITIONABLE conditions.
00783 
00784                 rPolicy = CdbRevisionPolicy( rId, partitionPtr->id( ));
00785 
00786             } else {
00787 
00788               // Just use TOPMOST revision for REGULAR conditions.
00789 
00790                 rPolicy = CdbRevisionPolicy( BdbTime::plusInfinity, 0 );
00791             }
00792         }
00793 
00794       // Proceed with the policy driven search.
00795 
00796         return findObject( theObjectPtr,
00797                            rPolicy,
00798                            theValidityTime,
00799                            theInsertionTime );
00800     }
00801 
00802   /*
00803    * ==================
00804    * EXECUTION PATH II: 'view/folder/config' conditions only
00805    * ==================
00806    */
00807 
00808     CDB_DEBUG_STREAM
00809         << "CDB_FIND_OBJECT_1: condition=" << name( )
00810         << " validity_time=" << theValidityTime.getGmtSec( ) << "." << theValidityTime.getGmtNsec( )
00811         << " insertion_time=" << theInsertionTime.getGmtSec( ) << "." << theInsertionTime.getGmtNsec( ) << endl;
00812 
00813     theObjectPtr = 0;
00814 
00815     CdbStatus result = CdbStatus::Error;
00816 
00817     do {
00818 
00819       // Check if specified validity time is covered by the validity
00820       // interval of the current view.
00821 
00822         CdbCPtr<CdbSQLView> viewPtr = _myConditionAtFolderPtr->parent( )->parentView( );
00823         assert( !viewPtr.isNull( ));
00824 
00825         if(( theValidityTime <  viewPtr->begin( )) ||
00826            ( theValidityTime >= viewPtr->end  ( ))) {
00827 
00828             ErrMsg(error) << errorStr << endl
00829                           << "    Specified validity time does not fit into the validity range" << endl
00830                           << "    of the current view." << endl
00831                           << "        VIEW NAME:   \"" << viewPtr->name( ) << "\"" << endl
00832                           << "        PASSED TIME: " << theValidityTime << endmsg;
00833             break;
00834         }
00835 
00836       // All we need to do is to find out a revision policy ("configuration element")
00837       // for the condition.
00838 
00839         CdbConfigElement rConfigElement;
00840 
00841         if( CdbStatus::Success != _myConditionAtFolderPtr->find_config_element( rConfigElement,
00842                                                                                 theValidityTime )) {
00843 
00844             ErrMsg(error) << errorStr << endl
00845                           << "    Failed to find revision policy information for specified validity time" << endl
00846                           << "    at the condition description of the  the current view." << endl
00847                           << "    The view may be inproperly configured." << endl
00848                           << "        PASSED TIME:    " << theValidityTime << endl
00849                           << "        CONDITION NAME: \"" << name( ) << "\"" << endl
00850                           << "        VIEW NAME:      \"" << viewPtr->name( ) << "\"" << endmsg;
00851             break;
00852         }
00853         if( ! rConfigElement.accessIsAllowed ) {
00854             ErrMsg(error) << errorStr << endl
00855                           << "    The current view prohibits accessing conditions at specified" << endl
00856                           << "    point of the validity timeline." << endl
00857                           << "        VIEW NAME:   \"" << viewPtr->name( ) << "\"" << endl
00858                           << "        PASSED TIME: " << theValidityTime << endmsg;
00859             break;
00860         }
00861 
00862       // Given the found policy, propagate the call down to the next
00863       // method requiring explicit policy to be specified among
00864       // the method's parameters.
00865 
00866         CdbCPtr<CdbSQLVisibleObject> visibleObjectPtr;
00867 
00868         BdbTime beginOfVisiblePeriod  = BdbTime::plusInfinity;  // initially this value will be calculated by the doFindObject* methods
00869         BdbTime endOfVisiblePeriod    = BdbTime::plusInfinity;  // -/-
00870 
00871         BdbTime beginOfDurationPeriod = BdbTime::minusInfinity;
00872         BdbTime endOfDurationPeriod   = BdbTime::minusInfinity;
00873 
00874         if( _myConditionPtr->isPartitionable( )) {
00875 
00876             if( CdbStatus::Success != doFindObjectAtPartition( rConfigElement.policy,
00877                                                                theValidityTime,
00878                                                                theInsertionTime,
00879                                                                visibleObjectPtr, 
00880                                                                beginOfVisiblePeriod,
00881                                                                endOfVisiblePeriod,
00882                                                                beginOfDurationPeriod,
00883                                                                endOfDurationPeriod )) break;
00884 
00885         } else {
00886 
00887             if( CdbStatus::Success != doFindObject( rConfigElement.policy,
00888                                                     theValidityTime,
00889                                                     theInsertionTime,
00890                                                     visibleObjectPtr, 
00891                                                     beginOfVisiblePeriod,
00892                                                     endOfVisiblePeriod,
00893                                                     beginOfDurationPeriod,
00894                                                     endOfDurationPeriod )) break;
00895         }
00896 
00897       // Now we should check if the found visible validity interval must be
00898       // narrowed down to the limits enforced by the current policy interval.
00899 
00900         if( rConfigElement.begin > beginOfVisiblePeriod ) beginOfVisiblePeriod = rConfigElement.begin;
00901         if( rConfigElement.end   < endOfVisiblePeriod   ) endOfVisiblePeriod   = rConfigElement.end;
00902 
00903       // Create a transient object.
00904 
00905         CdbObjectPtr transientObjectPtr;
00906         {
00907           // Get to the top CDB API object at a level of CdbSQLApi. We need this object
00908           // in order to invoke the final object creator.
00909           //
00910           // @see CdbSQLApi::createObject()
00911 
00912             CdbCPtr<CdbSQLApi> ptr = (const CdbCPtr<CdbSQLApi>&)parentDatabase( )->parent( );
00913 
00914           // Construct the current value of the iterator and return with success.
00915 
00916             if( CdbStatus::Success != ptr->createObject( transientObjectPtr,
00917                                                          CdbConditionPtr( this->clone( )),
00918                                                          visibleObjectPtr->original_begin( ),
00919                                                          visibleObjectPtr->original_end( ),
00920                                                          beginOfVisiblePeriod,
00921                                                          endOfVisiblePeriod,
00922                                                          beginOfDurationPeriod,
00923                                                          endOfDurationPeriod,
00924                                                          visibleObjectPtr->stored( ),
00925                                                          visibleObjectPtr->id( ))) {
00926                 ErrMsg(error) << errorStr << endl
00927                               << "    Failed to produce a metadata object for the found persistent object." << endmsg;
00928                 break;
00929             }
00930         }
00931         theObjectPtr = transientObjectPtr;
00932 
00933      // Done
00934 
00935        result = CdbStatus::Success;
00936 
00937     } while( false );
00938 
00939     CDB_DEBUG_STREAM << "CDB_FIND_OBJECT_1: " << (theObjectPtr.isNull( ) ? "" : theObjectPtr->id( )) << endl;
00940 
00941     return result;
00942 }
00943 
00944 CdbStatus
00945 CdbSQLApiCondition::findObject( CdbObjectPtr&            theObjectPtr,
00946                                 const CdbRevisionPolicy& thePolicy,
00947                                 const BdbTime&           theValidityTime,
00948                                 const BdbTime&           theInsertionTime )
00949 {
00950     const char* errorStr = "CdbSQLApiCondition::findObject(policy,validity,insertion) -- ERROR";
00951 
00952     theObjectPtr = 0;
00953 
00954     CDB_DEBUG_STREAM
00955         << "CDB_FIND_OBJECT_2: condition=" << name( ) 
00956         << " validity_time=" << theValidityTime.getGmtSec( ) << "." << theValidityTime.getGmtNsec( ) 
00957         << " insertion_time=" << theInsertionTime.getGmtSec( ) << "." << theInsertionTime.getGmtNsec( ) << endl;
00958 
00959     CdbStatus result = CdbStatus::Error;
00960 
00961     do {
00962 
00963       // Given the found policy, propagate the call down to the next
00964       // method requiring explicit policy to be specified among
00965       // the method's parameters.
00966 
00967         CdbCPtr<CdbSQLVisibleObject> visibleObjectPtr;
00968 
00969         BdbTime beginOfVisiblePeriod  = BdbTime::plusInfinity;  // initially this value will be calculated by the doFindObject* methods
00970         BdbTime endOfVisiblePeriod    = BdbTime::plusInfinity;  // -/-
00971 
00972         BdbTime beginOfDurationPeriod = BdbTime::minusInfinity;
00973         BdbTime endOfDurationPeriod   = BdbTime::minusInfinity;
00974 
00975         if( _myConditionPtr->isPartitionable( )) {
00976 
00977             if( CdbStatus::Success != doFindObjectAtPartition( thePolicy,
00978                                                                theValidityTime,
00979                                                                theInsertionTime,
00980                                                                visibleObjectPtr,
00981                                                                beginOfVisiblePeriod,
00982                                                                endOfVisiblePeriod,
00983                                                                beginOfDurationPeriod,
00984                                                                endOfDurationPeriod )) break;
00985 
00986         } else {
00987 
00988             if( CdbStatus::Success != doFindObject( thePolicy,
00989                                                     theValidityTime,
00990                                                     theInsertionTime,
00991                                                     visibleObjectPtr, 
00992                                                     beginOfVisiblePeriod,
00993                                                     endOfVisiblePeriod,
00994                                                     beginOfDurationPeriod,
00995                                                     endOfDurationPeriod )) break;
00996         }
00997 
00998       // Note, in this case we're not going to narrow a visibility of the found object since
00999       // we're using an explicit (rather then the default, found at a view) one. It's up to
01000       // our client to interpret the found validity interval.
01001 
01002         ;
01003 
01004       // Create a transient object through the creator factory.
01005 
01006         CdbObjectPtr transientObjectPtr;
01007         {
01008           // Get to the top CDB API object at a level of CdbSQLApi. We need this object
01009           // in order to invoke the final object creator.
01010           //
01011           // @see CdbSQLApi::createObject()
01012 
01013             CdbCPtr<CdbSQLApi> ptr = (const CdbCPtr<CdbSQLApi>&)parentDatabase( )->parent( );
01014 
01015           // Construct the current value of the iterator and return with success.
01016 
01017             if( CdbStatus::Success != ptr->createObject( transientObjectPtr,
01018                                                          CdbConditionPtr( this->clone( )),
01019                                                          visibleObjectPtr->original_begin( ),
01020                                                          visibleObjectPtr->original_end( ),
01021                                                          beginOfVisiblePeriod,
01022                                                          endOfVisiblePeriod,
01023                                                          beginOfDurationPeriod,
01024                                                          endOfDurationPeriod,
01025                                                          visibleObjectPtr->stored( ),
01026                                                          visibleObjectPtr->id( ))) {
01027                 ErrMsg(error) << errorStr << endl
01028                               << "    Failed to produce a metadata object for the found persistent object." << endmsg;
01029                 break;
01030             }
01031         }
01032         theObjectPtr = transientObjectPtr;
01033 
01034      // Done
01035  
01036        result = CdbStatus::Success;
01037  
01038     } while( false );
01039  
01040     CDB_DEBUG_STREAM << "CDB_FIND_OBJECT_2: " << (theObjectPtr.isNull( ) ? "" : theObjectPtr->id( )) << endl;
01041 
01042     return result;
01043 }
01044 
01045 CdbStatus
01046 CdbSQLApiCondition::objectIterator( CdbObjectItr&  theItr,
01047                                     const BdbTime& theBeginValidity,
01048                                     const BdbTime& theEndValidity )
01049 {
01050     const char* errorStr = "CdbSQLApiCondition::objectIterator() -- ERROR";
01051 
01052   /*
01053    * =================
01054    * EXECUTION PATH I: 'physical address' conditions only
01055    * =================
01056    *
01057    * This path is not currently implemented. A complicated algorithm to iterate
01058    * over a validity timeline of the "topmost" partitions would be needed for
01059    * PARTITIONABLE conditions. Things are trivial for REGULAR conditions though.
01060    * However to avoid an incomplete implementation of this part of the code let's just
01061    * postpone it as a whole.
01062    *
01063    * AN IDEA: Having a super-iterator composed of elementary iterators for individual
01064    *          "topmost" partitions would be a good idea. That would require to extend
01065    *          the API of P-Layout to deliver an iterator of "topmost" partitions. The
01066    *          one currently available does not respect non-instantiated partitions.
01067    */
01068 
01069     if( _myConditionAtFolderPtr.isNull( )) return CdbStatus::NotImplemented;
01070 
01071   /*
01072    * ==================
01073    * EXECUTION PATH II: 'view/folder/config' conditions only
01074    * ==================
01075    */
01076 
01077     CdbStatus result = CdbStatus::Error;
01078 
01079   // Verify parameters
01080 
01081     if( theEndValidity <= theBeginValidity ) {
01082 
01083         ErrMsg(error) << errorStr << endl
01084                       << "    Invalid validity interval range passed to the method." << endl
01085                       << "    The end time should be greater or equal than the begin one." << endl
01086                       << "        PASSED BEGIN TIME : " << theBeginValidity << endl
01087                       << "        PASSED END   TIME : " << theEndValidity << endl
01088                       << "        CONDITION         : \"" << name( ) << "\"" << endmsg;
01089 
01090         return CdbStatus::IllegalParameters;
01091     }
01092 
01093     CdbCPtr<CdbSQLView> viewPtr = _myConditionAtFolderPtr->parent( )->parentView( );
01094 
01095     BdbTime minValidity = viewPtr->begin( );
01096     BdbTime maxValidity = viewPtr->end( );
01097 
01098     if(( theBeginValidity >= maxValidity ) || ( theEndValidity <= minValidity )) {
01099 
01100         ErrMsg(error) << errorStr << endl
01101                       << "    Invalid validity interval range passed to the method." << endl
01102                       << "    This interval does not fit into the validity range" << endl
01103                       << "    allowed by the current view." << endl
01104                       << "        PASSED BEGIN TIME : " << theBeginValidity << endl
01105                       << "        PASSED END   TIME : " << theEndValidity << endl
01106                       << "        VIEW'S BEGIN TIME : " << minValidity << endl
01107                       << "        VIEW'S END   TIME : " << maxValidity << endl
01108                       << "        VIEW              : \"" << parent( )->parentView( )->name( ) << "\"" << endl
01109                       << "        CONDITION         : \"" << name( ) << "\"" << endmsg;
01110 
01111         return CdbStatus::IllegalParameters;
01112     }
01113 
01114   // Make adjustments to the validity limits to narrow the interval if needed.
01115   // The resulting interval will be passed to the iterator
01116 
01117     if( theBeginValidity > minValidity ) minValidity = theBeginValidity;
01118     if( theEndValidity   < maxValidity ) maxValidity = theEndValidity;
01119 
01120   // Prepare a right configuration collection. This is going to be either
01121   // specific collection at the level of the condition, or the default one
01122   // at the level of the view.
01123   //
01124   // @see method CdbSQLConditionAtFolder::config_elements()
01125 
01126     std::vector<CdbConfigElement> configElements;
01127 
01128     if( CdbStatus::Success == ( result = _myConditionAtFolderPtr->config_elements( configElements ))) {
01129 
01130       // Okay, there is a local configuration for the condition
01131 
01132         ;
01133 
01134     } else  if( CdbStatus::NotFound == result ) {
01135 
01136       // Try the default one
01137 
01138         if( !viewPtr->hasDefaultConfig( )) {
01139 
01140             ErrMsg(error) << errorStr << endl
01141                           << "    No default configuration collection in the view." << endl
01142                           << "        VIEW              : \"" << parent( )->parentView( )->name( ) << "\"" << endl
01143                           << "        CONDITION         : \"" << name( ) << "\"" << endmsg;
01144 
01145             return CdbStatus::Error;
01146 
01147         }
01148         if( CdbStatus::Success != ( result = viewPtr->config_elements( configElements ))) {
01149 
01150             ErrMsg(error) << errorStr << endl
01151                           << "    Failed to get the default configuration collection from the view." << endl
01152                           << "        VIEW              : \"" << parent( )->parentView( )->name( ) << "\"" << endl
01153                           << "        CONDITION         : \"" << name( ) << "\"" << endmsg;
01154 
01155             return CdbStatus::Error;
01156         }
01157 
01158     } else {
01159 
01160         ErrMsg(error) << errorStr << endl
01161                       << "    Failed to get a local configuration collection for the condition in the view." << endl
01162                       << "        VIEW      : \"" << parent( )->parentView( )->name( ) << "\"" << endl
01163                       << "        CONDITION : \"" << name( ) << "\"" << endmsg;
01164 
01165         return CdbStatus::Error;
01166     }
01167 
01168   // Now construct the desired iterator using an iterator adapter retranslating
01169   // configuration elements into an iterator of transient CDB API object.
01170 
01171     theItr = CdbObjectItr( new CdbCompositeItr< CdbObjectItr::ValueType >( new VisibleObjectIteratorAdapter( new CdbSimpleVectorAdapterItr<CdbConfigElement>( configElements ),
01172                                                                                                              _myConditionPtr,
01173                                                                                                              CdbConditionPtr( this->clone( )),
01174                                                                                                              minValidity,
01175                                                                                                              maxValidity )));
01176   // Done
01177  
01178    return CdbStatus::Success;
01179 }
01180 
01181 CdbStatus
01182 CdbSQLApiCondition::objectIterator( CdbObjectItr&            theItr,
01183                                     const CdbRevisionPolicy& thePolicy,
01184                                     const BdbTime&           theBeginValidity,
01185                                     const BdbTime&           theEndValidity )
01186 {
01187     const char* errorStr = "CdbSQLApiCondition::objectIterator(policy) -- ERROR";
01188 
01189   // Verify parameters
01190 
01191     if( theEndValidity <= theBeginValidity ) {
01192 
01193         ErrMsg(error) << errorStr << endl
01194                       << "    Invalid validity interval range passed to the method." << endl
01195                       << "    The end time should be greater or equal than the begin one." << endl
01196                       << "        PASSED BEGIN TIME : " << theBeginValidity << endl
01197                       << "        PASSED END   TIME : " << theEndValidity << endl
01198                       << "        CONDITION         : \"" << name( ) << "\"" << endmsg;
01199 
01200         return CdbStatus::IllegalParameters;
01201     }
01202 
01203   // Prepare a collection of configuration elements made of a single record
01204   // constructed from the input policy and the validity limits.
01205 
01206     std::vector<CdbConfigElement> configElements;
01207 
01208     configElements.push_back( CdbConfigElement( thePolicy,
01209                                                 theBeginValidity,
01210                                                 theEndValidity ));
01211 
01212   // Now construct the desired iterator using an iterator adapter retranslating
01213   // configuration elements into an iterator of transient CDB API object.
01214 
01215     theItr = CdbObjectItr( new CdbCompositeItr< CdbObjectItr::ValueType >( new VisibleObjectIteratorAdapter( new CdbSimpleVectorAdapterItr<CdbConfigElement>( configElements ),
01216                                                                                                              _myConditionPtr,
01217                                                                                                              CdbConditionPtr( this->clone( )),
01218                                                                                                              theBeginValidity,
01219                                                                                                              theEndValidity )));
01220   // Done
01221  
01222     return CdbStatus::Success;
01223 }
01224 
01225 CdbStatus
01226 CdbSQLApiCondition::originalObjectIterator( CdbObjectItr&        theItr,
01227                                             const BdbTime&       theBeginInsertion,
01228                                             const BdbTime&       theEndInsertion,
01229                                             const unsigned short thePartitionId )
01230 {
01231     const char* errorStr = "CdbSQLApiCondition::originalObjectIterator() -- ERROR";
01232 
01233   // Verify parameters
01234 
01235     if( theBeginInsertion >= theEndInsertion ) {
01236 
01237         ErrMsg(error) << errorStr << endl
01238                       << "    Invalid 'insertion' interval range passed to the method." << endl
01239                       << "    The end time should be greater or equal than the begin one." << endl
01240                       << "        VIEW                : \"" << parent( )->parentView( )->name( ) << "\"" << endl
01241                       << "        CONDITION           : \"" << name( ) << "\"" << endl
01242                       << "        PARTITION           : " << thePartitionId << endl
01243                       << "        BEGIN INSERTIN TIME : " << CdbTimeUtils::time2string( theBeginInsertion ) << " : " << theBeginInsertion << endl
01244                       << "        END   INSERTIONTIME : " << CdbTimeUtils::time2string( theEndInsertion )   << " : " << theEndInsertion   << endmsg;
01245 
01246         return CdbStatus::IllegalParameters;
01247     }
01248 
01249   // Get a list of original objects in the specified scope
01250 
01251     std::vector< CdbCPtr<CdbSQLOriginalObject> > originalObjects;
01252 
01253     if( CdbStatus::Success != _myConditionPtr->original_objects( originalObjects,
01254                                                                  thePartitionId,
01255                                                                  theBeginInsertion,
01256                                                                  theEndInsertion )) {
01257         ErrMsg(error) << errorStr << endl
01258                       << "    Failed to get a list of original persistent objects for the condition in the view." << endl
01259                       << "        VIEW                : \"" << parent( )->parentView( )->name( ) << "\"" << endl
01260                       << "        CONDITION           : \"" << name( ) << "\"" << endl
01261                       << "        PARTITION           : " << thePartitionId << endl
01262                       << "        BEGIN INSERTIN TIME : " << CdbTimeUtils::time2string( theBeginInsertion ) << " : " << theBeginInsertion << endl
01263                       << "        END   INSERTIONTIME : " << CdbTimeUtils::time2string( theEndInsertion )   << " : " << theEndInsertion   << endmsg;
01264         return CdbStatus::Error;
01265     }
01266 
01267   // Now pick up the right iterator and let it to do the rest...
01268 
01269     theItr = CdbObjectItr( new OriginalObjectIterator( new CdbSimpleVectorAdapterItr< CdbCPtr<CdbSQLOriginalObject> >( originalObjects ),
01270                                                        CdbConditionPtr( this->clone( ))));
01271 
01272   // Done
01273 
01274    return CdbStatus::Success;
01275 }
01276 
01277 CdbStatus
01278 CdbSQLApiCondition::storeObject( CdbObjectFactoryBase& theObjectFactory,
01279                                  const BdbTime&        theBegin,
01280                                  const BdbTime&        theEnd,
01281                                  CdbObjectPtr&         theObjectPtr )
01282 {
01283     const char* errorStr = "CdbSQLApiCondition::storeObject() -- ERROR";
01284 
01285     CDB_DEBUG_STREAM
01286         << "CDB_STORE_OBJECT_1: condition=" << name( )
01287         << " begin_time=" << CdbTimeUtils::time2string( theBegin )
01288         << " end_time=" << CdbTimeUtils::time2string( theEnd ) << endl;
01289 
01290     CdbStatus result = CdbStatus::Error;
01291 
01292     theObjectPtr = 0;
01293 
01294     do {
01295 
01296       // Truncated end validity time for the new object.
01297       //
01298       // NOTES:
01299       //
01300       //    (1) This time can be truncated to the end of the current partition if this
01301       //        is a partitionable condition and if the end time does not fit into the
01302       //        same partition the begin time falls into.
01303       //
01304       //    (2) This time can be further truncated if the "truncate" parameter delivered
01305       //        by by CdbEnvironment is less than the adjusted end time. This rule applies
01306       //        for both 'regular' and 'partitionable' conditions.
01307       //
01308       //        NOTE: The resulting truncate time should not be less or equal to the begin
01309       //              time. Otherwise the current operation would fail.
01310 
01311         BdbTime truncatedEnd = theEnd;
01312 
01313       // Find & verify the partition if the current condition is the partitionable one.
01314       // We may also truncate the end time of the partition if required.
01315 
01316         CdbCPtr<CdbSQLPartition> partitionPtr;
01317 
01318         if( _myConditionPtr->isPartitionable( )) {
01319 
01320           // Find the partition
01321 
01322             if( CdbStatus::Success != _myLocalSQLOriginPtr->find_topmost_partition( partitionPtr, 
01323                                                                                     theBegin )) {
01324                 ErrMsg(error) << errorStr << "\n"
01325                               << "    Failed to locate an open partition for the begin time\n"
01326                               << "        BEGIN VALIDITY TIME: " << CdbTimeUtils::time2string( theBegin ) << " : " << theBegin << "\n"
01327                               << "        CONDITION NAME:      \"" << name( ) << "\"" << endmsg;
01328                 break;
01329             }
01330 
01331           // Verify the partition
01332 
01333             if( partitionPtr->isClosed( )) {
01334                 ErrMsg(error) << errorStr << "\n"
01335                               << "    The partition is closed for modifications.\n"
01336                               << "    Storing new objects in the closed partition is not allowed.\n"
01337                               << "        PARTITION ID:   " << partitionPtr->id( ) << "\n"
01338                               << "        CONDITION NAME: \"" << name( ) << "\"" << endmsg;
01339                 break;
01340             }
01341             if( !partitionPtr->isInstantiated( )) {
01342                 ErrMsg(error) << errorStr << "\n"
01343                               << "    The partition is not instantiated yet.\n"
01344                               << "    Storing new objects into a partition in this state is not allowed.\n"
01345                               << "        PARTITION ID:   " << partitionPtr->id( ) << "\n"
01346                               << "        CONDITION NAME: \"" << name( ) << "\"" << endmsg;
01347                 break;
01348             }
01349 
01350           // Truncate the end time if needed.
01351 
01352             CdbSQLCell cell = partitionPtr->cell( );
01353             if( truncatedEnd > cell.endValidity ) truncatedEnd = cell.endValidity;
01354         }
01355 
01356       // Now make another adjustment (for both 'regular' and 'partitionable' conditions)
01357       // to the end time if the corresponding restriction is required by CdbEnvironment.
01358 
01359         {
01360             BdbTime truncateTime = CdbEnvironment::getTruncateTime( );
01361             if( truncateTime  < truncatedEnd ) {
01362 
01363                 if( truncateTime <= theBegin ) {
01364                     ErrMsg(error) << errorStr << "\n"
01365                                   << "    Wrong value of the truncate time found in the job's environment.\n"
01366                                   << "    This time is not allwed to be less or equal to the begin time\n"
01367                                   << "    of stored objects. The job may be inproperly configured.\n"
01368                                   << "        TRUNCATE TIME: " << CdbTimeUtils::time2string( truncatedEnd ) << " : " << truncatedEnd << endmsg;
01369                     break;
01370                 }
01371                 truncatedEnd = truncateTime;
01372 
01373                 CDB_DEBUG_STREAM << "CDB_STORE_OBJECT_1: truncated_end_time=" << CdbTimeUtils::time2string( truncatedEnd ) << endl;
01374             }
01375         }
01376 
01377       // Check if the condition can be modified localy.
01378 
01379         if( _myConditionPtr->isPartitionable( )) {
01380             if( _myLocalSQLOriginPtr->id( ) != partitionPtr->originId( )) {
01381                 ErrMsg(error) << errorStr << "\n"
01382                               << "    The partition does not belong to current database. Therefore it can't\n"
01383                               << "    be used to store new objects locally.\n"
01384                               << "        PARTITION ID:   " << partitionPtr->id( ) << "\n"
01385                               << "        CONDITION NAME: \"" << name( ) << "\"" << endmsg;
01386                 break;
01387             }
01388         } else {
01389             if( _myLocalSQLOriginPtr->id( ) != _myConditionPtr->parent( )->id( )) {
01390                 ErrMsg(error) << errorStr << "\n"
01391                               << "    The condition does not belong to current database. Therefore it can't\n"
01392                               << "    be used to store new objects locally.\n"
01393                               << "        CONDITION NAME: \"" << name( ) << "\"" << endmsg;
01394                 break;
01395             }
01396         }
01397 
01398       // Get to the Top-Level API component and delegate the object creation and storing
01399       // to a specific implementation of that API component.
01400       //
01401       // NOTE: We're using the above calculated "truncated" end time.
01402 
01403         CdbSQLApi* topLevelApiPtr = dynamic_cast< CdbSQLApi* >( parentDatabase( )->parent( ).get( ));
01404         assert( 0 != topLevelApiPtr );
01405 
01406         if( CdbStatus::Success != topLevelApiPtr->storeObject( theObjectPtr,
01407                                                                theObjectFactory,
01408                                                                _myConditionPtr,
01409                                                                partitionPtr,
01410                                                                CdbConditionPtr( this->clone( )),
01411                                                                theBegin,
01412                                                                truncatedEnd )) break;
01413         assert( !theObjectPtr.isNull( ));
01414 
01415         CDB_DEBUG_STREAM << "CDB_STORE_OBJECT_1: " << theObjectPtr->id( ) << endl; 
01416 
01417       // Done
01418 
01419         result = CdbStatus::Success;
01420 
01421     } while( false );
01422 
01423     return result;
01424 }
01425 
01426 CdbStatus
01427 CdbSQLApiCondition::storeAndTruncateObject( CdbObjectFactoryBase& theObjectFactory,
01428                                             const BdbTime&        theStoreTime,
01429                                             const BdbTime&        theTruncateTime,
01430                                             CdbObjectPtr&         theObjectPtr )
01431 {
01432     return storeObject( theObjectFactory,
01433                         theStoreTime,
01434                         BdbTime::plusInfinity,
01435                         theObjectPtr );
01436 }
01437 
01438 CdbStatus
01439 CdbSQLApiCondition::split( const BdbTime& theTime )
01440 {
01441     ErrMsg(warning) << "CdbSQLApiCondition::split() -- WARNING.\n"
01442                     << "    The 'split interval' is the 'noop' operations in this\n"
01443                     << "    implementation of the API. This operation is only provided for backward\n"
01444                     << "    compatibility with the old condition database. Eventually it will be phased out." << endmsg;
01445 
01446     return CdbStatus::Success;
01447 }
01448 
01449 bool
01450 CdbSQLApiCondition::isValid( )
01451 {
01452     return true;
01453 }
01454 
01455 bool
01456 CdbSQLApiCondition::isOpen( )
01457 {
01458     return true;
01459 }
01460 
01461 CdbStatus
01462 CdbSQLApiCondition::open( )
01463 {
01464     return CdbStatus::Success;
01465 }
01466 
01467 CdbStatus
01468 CdbSQLApiCondition::close( )
01469 {
01470     return CdbStatus::Success;
01471 }
01472 
01473 CdbStatus
01474 CdbSQLApiCondition::findRevision( CdbRevisionPtr& thePtr,
01475                                   const BdbTime&  theId,
01476                                   unsigned short  thePartitionId )
01477 {
01478     CdbStatus result = CdbStatus::Error;
01479 
01480   // Find the persistent revision objects in a scope of the current condition/partition.
01481 
01482     CdbCPtr<CdbSQLRevision> persistentRevisionPtr;
01483 
01484     if( CdbStatus::Success != ( result = _myConditionPtr->find_revision( persistentRevisionPtr,
01485                                                                          theId,
01486                                                                          thePartitionId ))) {
01487         return result;
01488     }
01489 
01490   // Construct the transient revision object.
01491 
01492     thePtr = new CdbSQLApiRevision( CdbConditionPtr( this->clone( )),
01493                                     persistentRevisionPtr );
01494 
01495   // Done
01496 
01497     return CdbStatus::Success;
01498 }
01499 
01500 CdbStatus
01501 CdbSQLApiCondition::findRevision( CdbRevisionPtr& thePtr,
01502                                   const char*     theName,
01503                                   unsigned short  thePartitionId )
01504 {
01505     CdbStatus result = CdbStatus::Error;
01506 
01507   // Find the persistent revision objects in a scope of the current condition/partition.
01508 
01509     CdbCPtr<CdbSQLRevision> persistentRevisionPtr;
01510 
01511     if( CdbStatus::Success != ( result = _myConditionPtr->find_revision( persistentRevisionPtr,
01512                                                                          theName,
01513                                                                          thePartitionId ))) {
01514         return result;
01515     }
01516 
01517   // Construct the transient revision object.
01518 
01519     thePtr = new CdbSQLApiRevision( CdbConditionPtr( this->clone( )),
01520                                     persistentRevisionPtr );
01521 
01522   // Done
01523 
01524     return CdbStatus::Success;
01525 }
01526 
01527 CdbStatus
01528 CdbSQLApiCondition::revisionIdIterator( CdbItr<BdbTime>& theItr,
01529                                         unsigned short   thePartitionId )
01530 {
01531     const char* errorStr = "CdbSQLApiCondition::revisionIdIterator() -- ERROR";
01532 
01533     CdbStatus result = CdbStatus::Error;
01534 
01535   // Find all revision objects corresponding to current condition/partition.
01536 
01537     std::vector< CdbCPtr<CdbSQLRevision> > vectorOfRevisions;
01538 
01539     if( CdbStatus::Success != ( result = _myConditionPtr->revisions( vectorOfRevisions,
01540                                                                      thePartitionId ))) {
01541         ErrMsg(error) << errorStr << endl
01542                       << "    Failed to locate the MetaData objects for the current condition/partition." << endmsg;
01543         return result;
01544     }
01545 
01546   // Create the iterator out of the list.
01547 
01548     theItr = CdbItr<BdbTime>( new RevisionIdIterator( vectorOfRevisions ));
01549 
01550   // Done
01551 
01552     return CdbStatus::Success;
01553 }
01554 
01555 CdbStatus
01556 CdbSQLApiCondition::revisionNameIterator( CdbItr<const char*>& theItr,
01557                                           unsigned short       thePartitionId )
01558 {
01559     const char* errorStr = "CdbSQLApiCondition::revisionNameIterator() -- ERROR";
01560 
01561     CdbStatus result = CdbStatus::Error;
01562 
01563   // Find all revision objects corresponding to current condition/partition.
01564 
01565     std::vector< CdbCPtr<CdbSQLRevision> > vectorOfRevisions;
01566 
01567     if( CdbStatus::Success != ( result = _myConditionPtr->revisions( vectorOfRevisions,
01568                                                                      thePartitionId ))) {
01569         ErrMsg(error) << errorStr << endl
01570                       << "    Failed to locate the MetaData objects for the current condition/partition." << endmsg;
01571         return result;
01572     }
01573 
01574   // Create the iterator out of the list.
01575 
01576     theItr = CdbItr<const char*>( new RevisionNameIterator( vectorOfRevisions ));
01577 
01578   // Done
01579 
01580     return CdbStatus::Success;
01581 }
01582 
01583 CdbStatus
01584 CdbSQLApiCondition::createRevision( CdbRevisionPtr& thePtr,
01585                                     const BdbTime&  theId,
01586                                     const char*     theName,
01587                                     const char*     theDescription,
01588                                     unsigned short  thePartitionId )
01589 {
01590     return CdbStatus::NotImplemented;
01591 }
01592 
01593 CdbStatus
01594 CdbSQLApiCondition::historyEventIterator( CdbHistoryEventItr& theItr,
01595                                           const BdbTime&      theBeginTime,
01596                                           const BdbTime&      theEndTime,
01597                                           const char**        theEventsToSelect )
01598 {
01599     return CdbStatus::NotImplemented;
01600 }
01601 
01602 CdbStatus
01603 CdbSQLApiCondition::historyEventTypeIterator( CdbHistoryEventTypeItr& theItr )
01604 {
01605     return CdbStatus::NotImplemented;
01606 }
01607 
01608 CdbStatus
01609 CdbSQLApiCondition::findInitialPartition( CdbCPtr<CdbSQLPartition>& thePartitionPtr,
01610                                           const BdbTime&            theValidityTime,
01611                                           const BdbTime&            theInsertionTime ) const
01612 {
01613     const char* errorStr = "CdbSQLApiCondition::findInitialPartition() -- ERROR";
01614 
01615     CdbStatus result = CdbStatus::Error;
01616 
01617   // The partition location can be a two-stage process, First we look for general
01618   // partition information at the MASTER origin.
01619 
01620     if( BdbTime::plusInfinity == theInsertionTime ) {
01621 
01622         if( CdbStatus::Success != ( result = _myMasterSQLOriginPtr->find_topmost_partition( thePartitionPtr,
01623                                                                                             theValidityTime ))) {
01624             ErrMsg(error) << errorStr << endl
01625                           << "    Failed to find a 'topmost' partition for specified validity time" << endl
01626                           << "    at the master origin." << endl
01627                           << "        VALIDITY TIME: " << theValidityTime << endmsg;
01628             return result;
01629         }
01630 
01631     } else {
01632 
01633         if( CdbStatus::Success != ( result = _myMasterSQLOriginPtr->find_partition( thePartitionPtr,
01634                                                                                     theValidityTime,
01635                                                                                     theInsertionTime ))) {
01636             ErrMsg(error) << errorStr << endl
01637                           << "    Failed to find a partition at specified point of 2-D timespace" << endl
01638                           << "    at the master origin." << endl
01639                           << "        VALIDITY  TIME: " << theValidityTime << endl
01640                           << "        INSERTION TIME: " << theInsertionTime << endmsg;
01641             return result;
01642         }
01643     }
01644 
01645   // Then we need to verify if the found partition belongs to the local origin.
01646   // If so then we reload partition information from the local registry since this partition
01647   // is supposed to be modified locally.
01648 
01649     if(( _myLocalSQLOriginPtr->id( ) == thePartitionPtr->originId( )) &&
01650        ( _myLocalSQLOriginPtr->id( ) != _myMasterSQLOriginPtr->id( ))) {
01651 
01652         unsigned short partitionId = thePartitionPtr->id( );
01653 
01654         if( CdbStatus::Success != ( result = _myLocalSQLOriginPtr->find_partition( thePartitionPtr,
01655                                                                                    partitionId ))) {
01656             ErrMsg(error) << errorStr << endl
01657                           << "    Failed to locate a final partition with ID=" << partitionId << endl
01658                           << "    at the local database where it's supposed to belong to." << endl
01659                           << "    The local database may not be properly initialized/loaded." << endmsg;
01660             return result;
01661         }
01662     }
01663 
01664   // Done
01665 
01666     return CdbStatus::Success;
01667 }
01668 
01669 CdbStatus
01670 CdbSQLApiCondition::findNextPartition( CdbCPtr<CdbSQLPartition>& thePartitionPtr,
01671                                        const BdbTime&            theValidityTime ) const
01672 {
01673     const char* fatalStr = "CdbSQLApiCondition::findNextPartition() -- FATAL ERROR";
01674     const char* errorStr = "CdbSQLApiCondition::findNextPartition() -- ERROR";
01675 
01676   // Verify critical parameters
01677 
01678     if( thePartitionPtr.isNull( )) {
01679 
01680         ErrMsg(fatal) << fatalStr << endl
01681                       << "    Null pointer passed into the method where a valid partition" << endl
01682                       << "    object was expected. This is a fatal internal error indicating" << endl
01683                       << "    either a memory corruption or an inconsistency in a database." << endmsg;
01684 
01685         return CdbStatus::IllegalParameters;
01686     }
01687 
01688   // Proceed with the normal flow of the algorithm
01689 
01690     CdbStatus result = CdbStatus::Error;
01691 
01692   // The partition location can be a two-stage process, First we're trying
01693   // to locate the information about the next partition from the master registry.
01694 
01695     unsigned short prevPartitionId = thePartitionPtr->id( );
01696 
01697     if( CdbStatus::Success != ( result = _myMasterSQLOriginPtr->find_next_partition( thePartitionPtr,
01698                                                                                      theValidityTime ))) {
01699       // Issue a complain only if a real error (otehr than CdbStatus::NotFound)
01700       // has been met.
01701 
01702         if( CdbStatus::NotFound != result ) {
01703             ErrMsg(error) << errorStr << endl
01704                           << "    Failed to find a 'next' partition for specified validity time" << endl
01705                           << "    at the master registry." << endl
01706                           << "        VALIDITY TIME:       " << theValidityTime << endl
01707                           << "        PREVIOUS PARTITION: #" << prevPartitionId << endmsg;
01708         }
01709 
01710       // Quit anyway. Note, that the CdbStatus::NotFound status should be returned
01711       // to a caller unchanged.
01712 
01713         return result;
01714     }
01715 
01716   // Then we need to verify if the found partition belongs to the local registry.
01717   // If so then we reload partition information from the local registry since this partition
01718   // is supposed to be modified locally.
01719 
01720     if(( _myLocalSQLOriginPtr->id( ) == thePartitionPtr->originId( )) &&
01721        ( _myLocalSQLOriginPtr->id( ) != _myMasterSQLOriginPtr->id( ))) {
01722 
01723         unsigned short nextPartitionId = thePartitionPtr->id( );
01724 
01725         if( CdbStatus::Success != ( result = _myLocalSQLOriginPtr->find_partition( thePartitionPtr,
01726                                                                                    nextPartitionId ))) {
01727             ErrMsg(error) << errorStr << endl
01728                           << "    Failed to find a partition #" << nextPartitionId << " at the local registry." << endmsg;
01729             return result;
01730         }
01731     }
01732 
01733   // Done
01734 
01735     return CdbStatus::Success;
01736 }
01737 
01738 CdbStatus
01739 CdbSQLApiCondition::doFindObjectAtPartition( const CdbRevisionPolicy&      thePolicy,
01740                                              const BdbTime&                theValidityTime,
01741                                              const BdbTime&                theInsertionTime,
01742                                              CdbCPtr<CdbSQLVisibleObject>& theVisibleObjectPtr,
01743                                              BdbTime&                      theBeginOfVisiblePeriod,
01744                                              BdbTime&                      theEndOfVisiblePeriod,
01745                                              BdbTime&                      theBeginOfDurationPeriod,
01746                                              BdbTime&                      theEndOfDurationPeriod ) const
01747 {
01748     const char* debugStr = "CdbSQLApiCondition::doFindObjectAtPartition()";
01749     const char* errorStr = "CdbSQLApiCondition::doFindObjectAtPartition() -- ERROR";
01750     const char* fatalStr = "CdbSQLApiCondition::doFindObjectAtPartition() -- FATAL ERROR";
01751 
01752     CdbStatus status = CdbStatus::Error;
01753 
01754   // Make sure this is a proper use of the algorithm. Just in case...
01755 
01756     assert( _myConditionPtr->isPartitionable( ));
01757 
01758   // Verify parameters and extract revision to begin with
01759 
01760     bool    useRevisions = thePolicy.useRevision( );
01761     BdbTime rId          = thePolicy.revisionId( );
01762 
01763     if( useRevisions ) {
01764 
01765         ;   // Nothing more to say
01766 
01767     } else if( BdbTime::plusInfinity == theInsertionTime ) {
01768 
01769         useRevisions = true;                    // Need this for the topmost revision
01770         rId          = BdbTime::plusInfinity;   // TOPMOST revision
01771 
01772     } else {
01773 
01774         rId = theInsertionTime;     // Still, no revisions
01775     }
01776 
01777   // Get the condition creation time. We would need this information to skip
01778   // partitions closed before that time.
01779 
01780     BdbTime creationTime = _myConditionPtr->created( );
01781 
01782     if( rId < creationTime ) {
01783         ErrMsg(error) << errorStr << endl
01784                       << "    Specified revision identifier / insertion time is older" << endl
01785                       << "    than the time when the condition was created." << endl
01786                       << "    The current view may be inproperly configured for the condition." << endl
01787                       << "        REVISION ID / INSERTION TIME : " << rId << endl
01788                       << "        CONDITION CREATION TIME      : " << creationTime << endl
01789                       << "        CONDITION NAME               : \"" << name( ) << "\"" << endl
01790                       << "        PARENT FOLDER NAME           : \"" << parent( )->name( ) << "\"" << endl
01791                       << "        VIEW NAME                    : \"" << parent( )->parentView( )->name( ) << "\"" << endmsg;
01792 
01793         return CdbStatus::Error;
01794     }
01795 
01796   // Find the initial <partition> to begin with.
01797   //
01798   // NOTE: We're going to check if the partion is closed. If so then its
01799   //       upper "insertion" time boundry is strictly above the condition
01800   //       creation time. Otherwise we just quit here since no intervals
01801   //       for the recently created condition should exist in his partition.
01802 
01803     CdbCPtr<CdbSQLPartition> partitionPtr;
01804 
01805     if( CdbStatus::Success != ( status = findInitialPartition( partitionPtr,
01806                                                                theValidityTime,
01807                                                                rId ))) {
01808         return status;
01809     }
01810 
01811 /******************************************************************/
01812 if( CdbEnvironment::getDebugMode( ) != 0 )
01813     cout << debugStr << endl
01814          << "{" << endl
01815          << "    Found initial partition ID=" << partitionPtr->id( ) << endl
01816          << "}" << endl;
01817 /******************************************************************/
01818 
01819     if( partitionPtr->isClosed( )) {
01820         if( partitionPtr->endInsertion( ) <= creationTime ) {
01821 
01822 /***************************************************************/
01823 if( CdbEnvironment::getDebugMode( ) != 0 )
01824 cout << debugStr << endl
01825  << "{" << endl
01826  << "    The just found partition is already 'closed' and its upper 'insertion'" << endl
01827  << "    time limit is older than the creation time of the current condition." << endl
01828  << "    So no object has been found." << endl
01829  << "        creationTime                  : " << creationTime << endl
01830  << "        partitionPtr->endInsertion( ) : " << partitionPtr->endInsertion( ) << endl
01831  << "}" << endl;
01832 /***************************************************************/
01833 
01834             return CdbStatus::NotFound;
01835         }
01836     }
01837 
01838   // Now we're ready to begin seraching for condition objects through
01839   // the sequence of partitions.
01840   //
01841   // == ALGORITHM DESCRIPTION ==
01842   //
01843   //  (1) The search algorithm begins with the specified revision/insertion time
01844   //      of the initially found partition and it will proceed down
01845   //      to final revisions of previously created ("next") partitions until
01846   //      either the desired interval is found or the bottom of the partitions
01847   //      stack is met. The bottom is defined as the lowest partition including
01848   //      the condition's creation time.
01849   //
01850   //  (2) If the bottom of the initial partition is met and desired interval
01851   //      is still not found then we switch to the next partition below
01852   //      the initial one and proceed with the search begining with the final
01853   //      revision of that partition.
01854   //
01855   //  (3) We proceed with step (2) until either we find desired interval or
01856   //      we reach the bottom of the condition. Note, that definition of
01857   //      the "bottom" given at (1) above.
01858   //
01859   // This algorithm is used for both states of the "useRevisions" flag
01860   // calculated above. The only difference is that in case of "!useRevisions"
01861   // we're only given one chance to try the above calculated initial partition
01862   // where the answer for specified insertionTime should be.
01863   //
01864   // Here is a pseudo-graphical representation of this process:
01865   //
01866   //           <validity time>
01867   //                   |
01868   //                   |
01869   // ..................|............................................
01870   // :Partition M      |                                           :
01871   // :                 |                              ============ :
01872   // :                 |                         ================= :
01873   // + + + + + + + + + X + + + + + + + + + + + + + + + + + + + + + +  Rev.M/insertion time
01874   // :                 |                   ======================= :
01875   // :                 |              ============================ :
01876   // :                 |        ================================== :
01877   // ..................|............................................
01878   //                   |
01879   // ..................|..........................
01880   // :Partition L      |                         :
01881   // :                 |                         :
01882   // + + + + + + + + + X + + + + + + + + + + + + +  Rev.Final
01883   // :                 |     =================== :
01884   // :                 | ======================= :
01885   // :                 X======================== :
01886   // :           =============================== :
01887   // .............................................
01888   //
01889   // == CALCULATING THE VISIBLE VALIDITY INTERVAL OF FOUND OBJECT ==
01890   //
01891   // The basic idea is that the visible validity interval is the shortest interval
01892   // of any of the following validity intervals met by the above described
01893   // algorithm:
01894   //
01895   // - the validity range of any partition explored
01896   // - the validity range of any failed as CdbStatus::NotFound attempts
01897   //   to find desired object at any MetaData object of partitions & increments explored
01898   // - the visibke validity for a successfully found object
01899   //
01900   // IMPORTANT: This algorithm needs thorough testing before deploying it.
01901 
01902   // Set up initial visible validity limits to the partition's borders. The limits
01903   // may be adjusted by the object lookup algorithm.
01904 
01905     theBeginOfVisiblePeriod = partitionPtr->beginValidity( );
01906     theEndOfVisiblePeriod   = partitionPtr->endValidity( );
01907 
01908     assert( theBeginOfVisiblePeriod < theEndOfVisiblePeriod );
01909 
01910   // Begin the algorithm...
01911 
01912     bool isFirstPath = true;    // At first path we don't need to look for the 'topmost' revision
01913                                 // of an initial partition. The correct revisions is supposed
01914                                 // to be found above.
01915     do {
01916 
01917 /**************************************************************************/
01918 if( CdbEnvironment::getDebugMode( ) != 0 )
01919     cout << debugStr << endl
01920          << "{" << endl
01921          << "    isFirstPath : " << ( isFirstPath ? "Yes" : "No" ) << endl
01922          << "}" << endl;
01923 /**************************************************************************/
01924 
01925         if( !isFirstPath ) {
01926 
01927           // Reload <partition>
01928           //
01929           // NOTE: We're going to check if the partion is closed. If so if its
01930           //       upper "insertion" time boundry is strictly above the condition
01931           //       creation time. Otherwise we just quit here since no intervals
01932           //       for the recently created condition should exist in his partition.
01933 
01934             if( CdbStatus::Success != ( status = findNextPartition( partitionPtr,
01935                                                                     theValidityTime ))) {
01936                 return status;
01937             }
01938 
01939 /***************************************************************/
01940 if( CdbEnvironment::getDebugMode( ) != 0 )
01941     cout << debugStr << endl
01942          << "{" << endl
01943          << "    Found next partition ID=" << partitionPtr->id( ) << endl
01944          << "}" << endl;
01945 /***************************************************************/
01946 
01947             if( partitionPtr->isClosed( )) {
01948                 if( partitionPtr->endInsertion( ) <= creationTime ) {
01949 
01950 /***************************************************************/
01951 if( CdbEnvironment::getDebugMode( ) != 0 )
01952     cout << debugStr << endl
01953          << "{" << endl
01954          << "    The just found partition is already 'closed' and its upper 'insertion'" << endl
01955          << "    time limit is older than the creation time of the current condition." << endl
01956          << "    So no object has been found." << endl
01957          << "        creationTime                  : " << creationTime << endl
01958          << "        partitionPtr->endInsertion( ) : " << partitionPtr->endInsertion( ) << endl
01959          << "}" << endl;
01960 /***************************************************************/
01961 
01962                     return CdbStatus::NotFound;
01963                 }
01964             }
01965 
01966           // Narrow down the visible interval to the partition limits
01967 
01968             if( partitionPtr->beginValidity( ) > theBeginOfVisiblePeriod ) theBeginOfVisiblePeriod = partitionPtr->beginValidity( );
01969             if( partitionPtr->endValidity( )   < theEndOfVisiblePeriod   ) theEndOfVisiblePeriod   = partitionPtr->endValidity( );
01970 
01971             assert( theBeginOfVisiblePeriod < theEndOfVisiblePeriod );
01972         }
01973 
01974       // If this is not the very first step in the <partition> loop
01975       // then we need to switch to the "topmost" revision of the just switched partition.
01976       //
01977       // NOTES:
01978       //
01979       //   1.The 'topmost' means a revision with highest numeric identifier in
01980       //   the scope of the partition.
01981       //
01982       //   2.That for closed partitions of partitionable conditions the returned
01983       //     identifier can not be equal to +Infinity.
01984 
01985         if( isFirstPath ) {
01986             ;
01987         } else {
01988             if( CdbStatus::Success != ( status = _myConditionPtr->topmost_revision_id( rId,
01989                                                                                        partitionPtr->id( )))) {
01990                 ErrMsg(error) << errorStr << endl
01991                               << "    Failed to find the 'topmost' revision in a scope of the partition." << endl
01992                               << "        CONDITION NAME     : \"" << name( ) << "\"" << endl
01993                               << "        PARENT FOLDER NAME : \"" << parent( )->name( ) << "\"" << endl
01994                               << "        VIEW NAME          : \"" << parent( )->parentView( )->name( ) << "\"" << endl
01995                               << "        PARTITION ID       : "   << partitionPtr->id( ) << endmsg;
01996 
01997                 return status;
01998             }
01999         }
02000 
02001       // Try finding the persistent object in the current partition using
02002       // the requested method.
02003 
02004         if( useRevisions ) {
02005 
02006 /*************************************************************************************************/
02007 if( CdbEnvironment::getDebugMode( ) != 0 )
02008     cout << debugStr << endl
02009          << "{" << endl
02010          << "    Find by revision" << endl
02011          << "       next    curent partition number : " << partitionPtr->id( ) << endl
02012          << "               rId                     : " << rId << endl
02013          << "               theValidityTime         : " << CdbTimeUtils::time2string( theValidityTime) << " : " << theValidityTime << endl
02014          << "}" << endl;
02015 /*************************************************************************************************/
02016 
02017           // Find a visible validity interval in a scope of the current partition
02018           // using the current revision.
02019           //
02020           // IMPORTANT NOTE:
02021           //
02022           //   If the operation returns CdbStatus::NotFound then it still carries
02023           //   an important information about a "hole" corresponidng to non-found object.
02024           //   We may need to use this information to narrow down the further search in
02025           //   in the "next" (if any) partition.
02026 
02027             status = _myConditionPtr->find_visible_object( theVisibleObjectPtr,
02028                                                            theValidityTime,
02029                                                            partitionPtr->id( ),
02030                                                            rId );
02031 
02032 /************************************************/
02033 if( CdbEnvironment::getDebugMode( ) != 0 )
02034     cout << debugStr << endl
02035          << "{" << endl
02036          << "    status = _myConditionPtr->find_visible_object() : " << status << endl
02037          << "}" << endl;
02038 /************************************************/
02039 
02040             if(( CdbStatus::Success  == status ) ||
02041                ( CdbStatus::NotFound == status )) {
02042 
02043               // Must readjust the validity limits even if the object has not been found.
02044               // The search may proceed down to the "next" (old) partition within limits of
02045               // the "validity hole".
02046 
02047                 if( theVisibleObjectPtr->begin( ) > theBeginOfVisiblePeriod ) theBeginOfVisiblePeriod = theVisibleObjectPtr->begin( );
02048                 if( theVisibleObjectPtr->end( )   < theEndOfVisiblePeriod   ) theEndOfVisiblePeriod   = theVisibleObjectPtr->end( );
02049 
02050                 assert( theBeginOfVisiblePeriod < theEndOfVisiblePeriod );
02051 
02052                 if( CdbStatus::Success == status ) {
02053 
02054                   // The duration of this object begins with its insertion time up
02055                   // to +Infinity
02056 
02057                     theBeginOfDurationPeriod = theVisibleObjectPtr->stored( );
02058                     theEndOfDurationPeriod   = BdbTime::plusInfinity;
02059 
02060                     return CdbStatus::Success;
02061                 }
02062 
02063             } else {
02064 
02065                 ErrMsg(error) << errorStr << endl
02066                               << "    Failed to find an object by a revision." << endl
02067                               << "        CONDITION NAME     : \"" << name( ) << "\"" << endl
02068                               << "        PARENT FOLDER NAME : \"" << parent( )->name( ) << "\"" << endl
02069                               << "        VIEW NAME          : \"" << parent( )->parentView( )->name( ) << "\"" << endl
02070                               << "        PARTITION ID       : "   << partitionPtr->id( ) << endl
02071                               << "        VALIDITY TIME      : "   << CdbTimeUtils::time2string( theValidityTime ) << " : " << theValidityTime << endl
02072                               << "        REVISION ID        : "   << CdbTimeUtils::time2string( rId )             << " : " << rId << endmsg;
02073                 return status;
02074             }
02075 
02076         } else {
02077 
02078             ErrMsg(fatal) << fatalStr << endl
02079                           << "    Finding objects by an insertion time is not presently implemented." << endl
02080                           << "    Make sure that you're using an explicitly specified revision in a configuration" << endl
02081                           << "    of this condition." << endl
02082                           << "        CONDITION NAME     : \"" << name( ) << "\"" << endl
02083                           << "        PARENT FOLDER NAME : \"" << parent( )->name( ) << "\"" << endl
02084                           << "        VIEW NAME          : \"" << parent( )->parentView( )->name( ) << "\"" << endl
02085                           << "        PARTITION ID       : "   << partitionPtr->id( ) << endl
02086                           << "        INSERTION TIME     : "   << CdbTimeUtils::time2string( rId ) << " : " << rId << endmsg;
02087 
02088             return CdbStatus::Error;
02089         }
02090         isFirstPath = false;
02091 
02092     } while( true );    // Should be broken by the logic above.
02093 
02094     return CdbStatus::Error;
02095 }
02096 
02097 CdbStatus
02098 CdbSQLApiCondition::doFindObject( const CdbRevisionPolicy&      thePolicy,
02099                                   const BdbTime&                theValidityTime,
02100                                   const BdbTime&                theInsertionTime,
02101                                   CdbCPtr<CdbSQLVisibleObject>& theVisibleObjectPtr, 
02102                                   BdbTime&                      theBeginOfVisiblePeriod,
02103                                   BdbTime&                      theEndOfVisiblePeriod,
02104                                   BdbTime&                      theBeginOfDurationPeriod,
02105                                   BdbTime&                      theEndOfDurationPeriod ) const
02106 {
02107     const char* debugStr = "CdbSQLApiCondition::doFindObject()";
02108     const char* errorStr = "CdbSQLApiCondition::doFindObject() -- ERROR";
02109     const char* fatalStr = "CdbSQLApiCondition::doFindObject() -- FATAL ERROR";
02110 
02111     CdbStatus status = CdbStatus::Error;
02112 
02113   // Make sure this is a proper use of the algorithm. Just in case...
02114 
02115     assert( !_myConditionPtr->isPartitionable( ));
02116 
02117   // Verify parameters and extract revision to begin with
02118 
02119     bool    useRevisions = thePolicy.useRevision( );
02120     BdbTime rId          = thePolicy.revisionId( );
02121 
02122     if( useRevisions ) {
02123 
02124         ;   // Nothing more to say
02125 
02126     } else if( BdbTime::plusInfinity == theInsertionTime ) {
02127 
02128         useRevisions = true;                    // Need this for the topmost revision
02129         rId          = BdbTime::plusInfinity;   // TOPMOST revision
02130 
02131     } else {
02132 
02133         rId = theInsertionTime;     // Still, no revisions
02134     }
02135 
02136   // Set up some initial "visible" validity period. This window will be corrected
02137   // by the condition lookup algorithm.
02138 
02139     theBeginOfVisiblePeriod = BdbTime::minusInfinity;
02140     theEndOfVisiblePeriod   = BdbTime::plusInfinity;
02141 
02142   // Try finding the persistent object in the current partition using
02143   // the requested method.
02144 
02145     if( useRevisions ) {
02146 
02147 /*************************************************************************************************/
02148 if( CdbEnvironment::getDebugMode( ) != 0 )
02149     cout << debugStr << endl
02150          << "{" << endl
02151          << "    Find by revision" << endl
02152          << "               rId                     : " << rId << endl
02153          << "               theValidityTime         : " << CdbTimeUtils::time2string( theValidityTime) << " : " << theValidityTime << endl
02154          << "}" << endl;
02155 /*************************************************************************************************/
02156 
02157       // Find a visible validity interval using the current revision.
02158 
02159         if( CdbStatus::Success != ( status = _myConditionPtr->find_visible_object( theVisibleObjectPtr,
02160                                                                                    theValidityTime,
02161                                                                                    0,
02162                                                                                    rId ))) {
02163             ErrMsg(error) << errorStr << endl
02164                           << "    Failed to find an object by a revision." << endl
02165                           << "        CONDITION NAME     : \"" << name( ) << "\"" << endl
02166                           << "        PARENT FOLDER NAME : \"" << parent( )->name( ) << "\"" << endl
02167                           << "        VIEW NAME          : \"" << parent( )->parentView( )->name( ) << "\"" << endl
02168                           << "        VALIDITY TIME      : "   << CdbTimeUtils::time2string( theValidityTime ) << " : " << theValidityTime << endl
02169                           << "        REVISION ID        : "   << CdbTimeUtils::time2string( rId )             << " : " << rId << endmsg;
02170             return status;
02171         }
02172 
02173       // Must readjust the validity limits.
02174 
02175         if( theVisibleObjectPtr->begin( ) > theBeginOfVisiblePeriod ) theBeginOfVisiblePeriod = theVisibleObjectPtr->begin( );
02176         if( theVisibleObjectPtr->end( )   < theEndOfVisiblePeriod   ) theEndOfVisiblePeriod   = theVisibleObjectPtr->end( );
02177 
02178         assert( theBeginOfVisiblePeriod < theEndOfVisiblePeriod );
02179 
02180       // The duration of this object begins with its insertion time up
02181       // to +Infinity
02182 
02183         theBeginOfDurationPeriod = theVisibleObjectPtr->stored( );
02184         theEndOfDurationPeriod   = BdbTime::plusInfinity;
02185 
02186         return CdbStatus::Success;
02187             
02188     } else {
02189 
02190         ErrMsg(fatal) << fatalStr << endl
02191                       << "    Finding objects by an insertion time is not presently implemented." << endl
02192                       << "    Make sure that you're using an explicitly specified revision in a configuration" << endl
02193                       << "    of this condition." << endl
02194                       << "        CONDITION NAME     : \"" << name( ) << "\"" << endl
02195                       << "        PARENT FOLDER NAME : \"" << parent( )->name( ) << "\"" << endl
02196                       << "        VIEW NAME          : \"" << parent( )->parentView( )->name( ) << "\"" << endl
02197                       << "        INSERTION TIME     : "   << CdbTimeUtils::time2string( rId ) << " : " << rId << endmsg;
02198 
02199         return CdbStatus::Error;
02200     }
02201     return CdbStatus::Error;
02202 }
02203 
02204 /////////////////
02205 // End Of File //
02206 /////////////////

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