Bdb packages | Design docs | Source docs | Guidelines | Recent releases

Search | Site Map .

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

/BdbCond/BdbDatabase.cc

Go to the documentation of this file.
00001 //-----------------------------------------------------------------------------
00002 //
00003 // File and Version Information:
00004 //      $Id: BdbDatabase.cc,v 1.128 2002/07/07 18:27:10 gapon Exp $
00005 //
00006 // Description:
00007 //      Class BdbDatabase
00008 //
00009 // Environment:
00010 //      Software developed for the BaBar Detector at the SLAC B-Factory.
00011 //
00012 // Author List:
00013 //      J. Ohnemus                  Original Author
00014 //      Igor A. Gaponenko           Further modifications
00015 //
00016 // Copyright Information:
00017 //      Copyright (C) 1994, 1995    Lawrence Berkeley Laboratory
00018 //
00019 //-----------------------------------------------------------------------------
00020 
00021 // -------------------------
00022 // -- This Class's Header --
00023 // -------------------------
00024 
00025 #include "BdbCond/BdbDatabase.hh"
00026 
00027 // -------------------------
00028 // -- Objectivity Headers --
00029 // -------------------------
00030 
00031 #include <ooIndex.h>
00032 
00033 // ---------------
00034 // -- C Headers --
00035 // ---------------
00036 
00037 extern "C" {
00038 #include <assert.h>
00039 #include <ctype.h>
00040 #include <stddef.h>
00041 #include <stdio.h>
00042 #include <stdlib.h>
00043 #include <string.h>
00044 }
00045 
00046 // -----------------
00047 // -- C++ Headers --
00048 // -----------------
00049 
00050 #include <iostream.h>
00051 #include <algorithm>
00052 #include <string>
00053 using std::string;
00054 #include <vector>
00055 using std::vector;
00056 
00057 // ---------------------------------
00058 // -- Collaborating Class Headers --
00059 // ---------------------------------
00060 
00061 #include "BdbApplication/BdbCondSingleton.hh"
00062 #include "BdbApplication/BdbDomain.hh"
00063 #include "BdbApplication/BdbDebug.hh"
00064 #include "BdbAccess/BdbAuth.hh"
00065 #include "BdbClustering/BdbCondClusteringHint.hh"
00066 #include "BdbCond/BdbConditions.hh"
00067 #include "BdbCond/BdbCondErrors.hh"
00068 #include "BdbCond/BdbInterval.hh"
00069 #include "BdbCond/BdbIntervalGene.hh"
00070 #include "BdbCond/BdbObject.hh"
00071 #include "BdbCond/BdbString.hh"
00072 #include "BdbCond/BdbCondStoreTime.hh"
00073 #include "BdbCond/BdbCondStoreInterval.hh"
00074 #include "BdbCond/BdbCondDirectAccessor.hh"
00075 #include "BdbTime/BdbTime.hh"
00076 #include "ErrLogger/ErrLog.hh"
00077 
00078 // --------------------------------------------------------------------------
00079 // -- Local Macros, Typedefs, Structures, Unions, and Forward Declarations --
00080 // --------------------------------------------------------------------------
00081 
00082 static const char  rcsid[] = "$Id: BdbDatabase.cc,v 1.128 2002/07/07 18:27:10 gapon Exp $";
00083  
00084 static const char* Zero = "00000";
00085 
00086 bool
00087 BdbDatabase::_staticMembersAreInitialized = false;
00088 
00089 BdbTime
00090 BdbDatabase::_truncateOverrideTime = BdbTime::plusInfinity;
00091 
00092 BdbCondAccessor*
00093 BdbDatabase::_defaultAccessor = new BdbCondDirectAccessor( );
00094 
00095 BdbCondAccessor*
00096 BdbDatabase::_accessor = _defaultAccessor;
00097 
00098 // --------------------
00099 // -- Static methods --
00100 // --------------------
00101 
00102 void
00103 BdbDatabase::intializeStaticMembers( )
00104 {
00105     if ( _staticMembersAreInitialized ) return;
00106     _staticMembersAreInitialized = true;
00107 
00108     _truncateOverrideTime = BdbTime::plusInfinity;
00109 }
00110 
00111 BdbTime
00112 BdbDatabase::setTruncateOverrideTime( const BdbTime& theNewTruncateOverrideTime )
00113 {
00114     const char* infoString = "BdbDatabase::setTruncateOverrideTime() -- INFO";
00115 
00116     intializeStaticMembers( );
00117 
00118     BdbTime theOldTruncateOverrideTime;
00119 
00120     theOldTruncateOverrideTime = _truncateOverrideTime;
00121     _truncateOverrideTime      = theNewTruncateOverrideTime;
00122 
00123     ErrMsg(routine) << infoString << endl
00124                     << "    The new overload for the truncate time: " << theNewTruncateOverrideTime << endl
00125                     << "    The old one was:                        " << theOldTruncateOverrideTime << endmsg;
00126 
00127     return theOldTruncateOverrideTime;
00128 }
00129 
00130 BdbTime
00131 BdbDatabase::getTruncateOverrideTime( )
00132 {
00133     intializeStaticMembers( );
00134     return _truncateOverrideTime;
00135 }
00136 
00137 const BdbCondAccessor*
00138 BdbDatabase::getAccessor( )
00139 {
00140   // Return a (const) pointer to the current instance of the accessor
00141   // or just null pointer if this is the default accessor.
00142   //
00143   // NOTE: The basic idea is to protect the default accessor from being
00144   //       accidentally deleted by clients' code.
00145 
00146     if( _accessor == _defaultAccessor ) return 0;
00147 
00148     return _accessor;
00149 }
00150 
00151 BdbCondAccessor*
00152 BdbDatabase::setAccessor( BdbCondAccessor* theAccessor )
00153 {
00154   // Remember the current accessor or just null pointer if this is
00155   // the default accessor.
00156   //
00157   // NOTE: The basic idea is to protect the default accessor from being
00158   //       accidentally deleted by clients' code.
00159 
00160     BdbCondAccessor* previousAccessor = 0;
00161     if( _accessor != _defaultAccessor ) previousAccessor = _accessor;
00162 
00163   // Modifying the default accessor can be disabled if the corresponding
00164   // environment variable is set.
00165 
00166     if( 0 == getenv( "BDBCOND_USE_DEFAULT_ACCESSOR" )) {
00167 
00168       // Send "reset" signal to the current accessor before to change it
00169       // for the new one. This is done in order to clear the background context (if required)
00170       // associated with this accessor.
00171 
00172         _accessor->reset( );
00173 
00174       // Replace the current accessor with the new one, or with the default on
00175       // if null value were passed as a parameter.
00176 
00177         if( 0 == theAccessor ) _accessor = _defaultAccessor;
00178         else                   _accessor = theAccessor;
00179     }
00180 
00181     return previousAccessor;
00182 }
00183 
00184 BdbCondAccessor*
00185 BdbDatabase::setDefaultAccessor( )
00186 {
00187     return setAccessor( _defaultAccessor );
00188 }
00189 
00190 // ------------------
00191 // -- Constructors --
00192 // ------------------
00193 
00194 BdbDatabase::BdbDatabase( ) :
00195     _myHint(0),
00196     BdbCondDatabaseBase( ),
00197     _authLevelIsSet(false),
00198     _intervalCacheH(0)
00199 {
00200     intializeStaticMembers( );
00201 
00202   // Set the internal data members which are not managed through
00203   // the internal cache.
00204 
00205   // The following operation is deffered until a very first request for
00206   // for the "updated" hint is done.
00207   //
00208   //    _myHint       = new BdbCondClusteringHint( *(BdbConditions::instance( )), 0 );
00209 
00210     _revisionPath = BdbCondPath::instance( );
00211 }
00212 
00213 BdbDatabase::BdbDatabase( const char* theTLA ) :
00214     _myHint(0),
00215     BdbCondDatabaseBase( theTLA ),
00216     _authLevelIsSet(false),
00217     _intervalCacheH(0)
00218 {
00219     intializeStaticMembers( );
00220 
00221   // Set the internal data members which are not managed through
00222   // the internal cache.
00223 
00224   // The following operation is deffered until a very first request for
00225   // for the "updated" hint is done.
00226   //
00227   //    _myHint       = new BdbCondClusteringHint( *(BdbConditions::instance( )), theTLA );
00228 
00229     _revisionPath = BdbCondPath::instance( );
00230 }
00231 
00232 // ----------------
00233 // -- Destructor --
00234 // ----------------
00235 
00236 BdbDatabase::~BdbDatabase( )
00237 {
00238     delete _myHint;
00239 }
00240  
00241 // ---------------
00242 // -- Operators --
00243 // ---------------
00244 
00245 BdbDatabase&
00246 BdbDatabase::operator = ( const BdbDatabase& theDB ) 
00247 {
00248     if ( this == &theDB ) {
00249         return *this;
00250     }
00251 
00252   // Invoke base class assignment operator
00253 
00254     BdbCondDatabaseBase::operator = ( theDB );
00255 
00256   // Add assignment for derived class data members
00257 
00258     _myHint         = theDB._myHint;
00259     _authLevelIsSet = theDB._authLevelIsSet;
00260     _revisionPath   = theDB._revisionPath;
00261     _intervalCacheH = theDB._intervalCacheH;
00262 
00263     return *this;
00264 }
00265 
00266 // ----------------------
00267 // -- Member Functions --
00268 // ----------------------
00269 
00270 BdbStatus
00271 BdbDatabase::store( const BdbHandle(BdbObject)& theObjectH,
00272                     const char*                 theContainerName,
00273                     const BdbTime&              theBeginTime,
00274                     d_ULong                     theTag )
00275 {
00276     const char* errorString = "BdbDatabase::store() -- ERROR";
00277 
00278     BdbStatus status;
00279 
00280     assert ( 0 != theContainerName );
00281 
00282     COUT1 << "CONDSTORE1: detector=" << subsystemTLA( ) << " container=" << theContainerName << " begin_time=" << theBeginTime << endl;
00283 
00284   // Ensure the proper context to be set.
00285 
00286     if ( ! verifyIndexMode( ))               return BdbcError;
00287     if ( ! setAuthLevel( theContainerName )) return BdbcError;
00288 
00289   // Try to locate this interval container.
00290 
00291     BdbHandle(BdbContObj) intervalContH;
00292     if ( BdbcSuccess != findIntervalCont( intervalContH, theContainerName )) {
00293 
00294       // Create new container and store the object in there.
00295 
00296         return  createIntervalCont( theContainerName,
00297                                     theObjectH,
00298                                     theBeginTime,
00299                                     BdbTime::plusInfinity,
00300                                     theTag );
00301 
00302     }
00303 
00304   // Put a record into the History. We do this in advance, because creating
00305   // a new interval is not generally an atomic operations. If it fails
00306   // somewhere in the middle we would know what exactly we were trying
00307   // to do.
00308 
00309     historyStore( rcsid, theObjectH, theBeginTime, BdbTime::plusInfinity, theTag );
00310 
00311   // Locate the FIRST and the LAST intervals.
00312 
00313     BdbHandle(BdbIntervalR) firstIntervalH;
00314     BdbHandle(BdbIntervalR) lastIntervalH;
00315 
00316     firstIntervalH.lookupObj( intervalContH, "FirstInterval", BdbcUpdate  );
00317     if ( BdbIsNull(firstIntervalH)) {
00318         ErrMsg(error) << errorString << endl
00319                       << "    Can not find FIRST interval." << endl
00320                       << "    The container may have incorrect internal structure." << endl
00321                       << "        DETECTOR  -> " << subsystemTLA( ) << endl
00322                       << "        CONTAINER -> " << theContainerName << endmsg;
00323         return BdbcError;
00324     }
00325 
00326     lastIntervalH.lookupObj( intervalContH, "LastInterval", BdbcUpdate  );
00327     if ( BdbIsNull(lastIntervalH)) {
00328         ErrMsg(error) << errorString << endl
00329                       << "    Can not find LAST interval." << endl
00330                       << "    The container may have incorrect internal structure." << endl
00331                       << "        DETECTOR  -> " << subsystemTLA( ) << endl
00332                       << "        CONTAINER -> " << theContainerName << endmsg;
00333         return BdbcError;
00334     }
00335 
00336   // Modify the FIRST interval
00337 
00338     if ( theBeginTime < firstIntervalH->getEndTime( )) {
00339 
00340         if ( theBeginTime == BdbTime::minusInfinity ) {
00341 
00342           // Well. We have interval with both ends open: -oo..+oo
00343           // Update the first interval until its very end.
00344 
00345             status = updateFirstInterval( theObjectH,
00346                                           firstIntervalH,
00347                                           firstIntervalH->getEndTime( ),
00348                                           theTag );
00349             if ( BdbcSuccess != status ) {
00350                 return status;
00351             }
00352 
00353         } else {
00354 
00355          // Cut the first interval until its very end.
00356 
00357             status = cutFirstInterval( theObjectH,
00358                                        firstIntervalH,
00359                                        theBeginTime,
00360                                        firstIntervalH->getEndTime( ),
00361                                        theTag );
00362 
00363             if ( BdbcSuccess != status ) {
00364                 return status;
00365             }
00366 
00367         }
00368 
00369       // Use recursive call to the current function to store
00370       // the rest of the interval
00371 
00372         return store( theObjectH,
00373                       theContainerName,
00374                       firstIntervalH->getEndTime( ),
00375                       theTag );
00376 
00377     } else {
00378 
00379       // Modify the LAST interval.
00380 
00381         if ( theBeginTime > lastIntervalH->getBeginTime( )) {
00382 
00383           // append interval to end of list
00384 
00385             return appendIntervalR( theObjectH,
00386                                     lastIntervalH,
00387                                     theBeginTime,
00388                                     theTag );
00389 
00390         } else if ( theBeginTime == lastIntervalH->getBeginTime( )) {
00391 
00392           // update the last interval if it pointed out to a NULL calibration
00393           // object only
00394 
00395             return updateLastInterval( theObjectH,
00396                                        lastIntervalH,
00397                                        theTag );
00398 
00399         } else {
00400 
00401          // version an interval in the middle of the list
00402 
00403             version( 0,
00404                      theObjectH,
00405                      theBeginTime,
00406                      theTag );
00407         }
00408     }
00409 
00410     return BdbcSuccess;
00411 }
00412 
00413 BdbStatus
00414 BdbDatabase::store( const BdbHandle(BdbObject)& theObjectH,
00415                     const char*                 theContainerName,
00416                     const BdbTime&              theBeginTime,
00417                     const BdbTime&              theEndTime,
00418                     d_ULong                     theTag )
00419 {
00420     const char* errorString = "BdbDatabase::store() -- ERROR.";
00421 
00422   // Check if we have an open ended interval on the right.
00423 
00424     if ( BdbTime::plusInfinity == theEndTime ) {
00425 
00426         return store( theObjectH,
00427                       theContainerName,
00428                       theBeginTime,
00429                       theTag );
00430     }
00431 
00432   // Proceed with a regular procedure.
00433 
00434     BdbStatus status;
00435 
00436     assert ( 0 != theContainerName );
00437     assert ( theBeginTime < theEndTime );
00438 
00439     COUT1 << "CONDSTORE2: detector=" << subsystemTLA( ) << " container=" << theContainerName << " begin_time=" << theBeginTime << " end_time=" << theEndTime << endl;
00440 
00441   // Ensure the proper context to be set.
00442 
00443     if ( ! verifyIndexMode( ))               return BdbcError;
00444     if ( ! setAuthLevel( theContainerName )) return BdbcError;
00445 
00446   // Try to locate this interval container.
00447 
00448     BdbHandle(BdbContObj) intervalContH;
00449     if ( BdbcSuccess != findIntervalCont( intervalContH, theContainerName )) {
00450 
00451       // Create new container and store the object in there.
00452 
00453         return  createIntervalCont( theContainerName,
00454                                     theObjectH,
00455                                     theBeginTime,
00456                                     theEndTime,
00457                                     theTag );
00458 
00459     }
00460 
00461   // Put a record into the History. We do this in advance, because creating
00462   // a new interval is not generally an atomic operations. If it fails
00463   // somewhere in the middle we would know what exactly we were trying
00464   // to do.
00465 
00466     historyStore( rcsid, theObjectH, theBeginTime, theEndTime, theTag );
00467 
00468   // Locate the FIRST and the LAST intervals.
00469 
00470     BdbHandle(BdbIntervalR) firstIntervalH;
00471     BdbHandle(BdbIntervalR) lastIntervalH;
00472 
00473     firstIntervalH.lookupObj( intervalContH, "FirstInterval", BdbcUpdate  );
00474     if ( BdbIsNull(firstIntervalH)) {
00475         ErrMsg(error) << errorString << endl
00476                       << "    Can not find FIRST interval." << endl
00477                       << "    The container may have incorrect internal structure." << endl
00478                       << "        DETECTOR  -> " << subsystemTLA( ) << endl
00479                       << "        CONTAINER -> " << theContainerName << endmsg;
00480         return BdbcError;
00481     }
00482 
00483     lastIntervalH.lookupObj( intervalContH, "LastInterval", BdbcUpdate  );
00484     if ( BdbIsNull(lastIntervalH)) {
00485         ErrMsg(error) << errorString << endl
00486                       << "    Can not find LAST interval." << endl
00487                       << "    The container may have incorrect internal structure." << endl
00488                       << "        DETECTOR  -> " << subsystemTLA( ) << endl
00489                       << "        CONTAINER -> " << theContainerName << endmsg;
00490         return BdbcError;
00491     }
00492 
00493   // Modify the FIRST interval
00494 
00495     if ( theBeginTime < firstIntervalH->getEndTime( )) {
00496 
00497         if ( theBeginTime == BdbTime::minusInfinity ) {
00498 
00499             if ( theEndTime >= firstIntervalH->getEndTime( )) {
00500 
00501               // Update the first interval until its very end.
00502 
00503                 status = updateFirstInterval( theObjectH,
00504                                               firstIntervalH,
00505                                               firstIntervalH->getEndTime( ),
00506                                               theTag );
00507 
00508                 if ( BdbcSuccess != status ) {
00509                     return status;
00510                 }
00511 
00512             } else {
00513 
00514               // Update the first interval until the specified end time.
00515               // And then immediatelly return.
00516 
00517                 return updateFirstInterval( theObjectH,
00518                                             firstIntervalH,
00519                                             theEndTime,
00520                                             theTag );
00521             }
00522 
00523         } else {
00524 
00525             if ( theEndTime >= firstIntervalH->getEndTime( )) {
00526 
00527              // Cut the first interval until its very end.
00528 
00529                 status = cutFirstInterval( theObjectH,
00530                                            firstIntervalH,
00531                                            theBeginTime,
00532                                            firstIntervalH->getEndTime( ),
00533                                            theTag );
00534 
00535                 if ( BdbcSuccess != status ) {
00536                     return status;
00537                 }
00538 
00539 
00540             } else {
00541 
00542               // Cut the first interval until the specified end time.
00543               // And then immediatelly return.
00544 
00545                 return cutFirstInterval( theObjectH,
00546                                          firstIntervalH,
00547                                          theBeginTime,
00548                                          theEndTime,
00549                                          theTag );
00550             }
00551         }
00552 
00553       // Use recursive call to the current function to store
00554       // the rest of the interval if the original interval
00555       // goes beyong the first interval.
00556 
00557         if ( theEndTime > firstIntervalH->getEndTime( )) {
00558 
00559             return store( theObjectH,
00560                           theContainerName,
00561                           firstIntervalH->getEndTime( ),
00562                           theEndTime,
00563                           theTag );
00564         }
00565 
00566     } else {
00567 
00568       // Modify the LAST interval.
00569 
00570         if ( theBeginTime > lastIntervalH->getBeginTime( )) {
00571 
00572           // append interval to end of list
00573 
00574             return appendIntervalR( theObjectH,
00575                                     lastIntervalH,
00576                                     theBeginTime,
00577                                     theEndTime,
00578                                     theTag );
00579 
00580         } else if ( theBeginTime == lastIntervalH->getBeginTime( )) {
00581 
00582           // Cut the last interval onto 2 interval: one with closed ends, another
00583           // - with open right end. Version the first interval if it has non-NULL
00584           // pointer to a calibration object.
00585 
00586             return cutLastInterval( theObjectH,
00587                                     lastIntervalH,
00588                                     theBeginTime,
00589                                     theEndTime,
00590                                     theTag );
00591 
00592         } else {
00593 
00594           // version an interval in the middle of the list 
00595 
00596             version( 0,
00597                      theObjectH,
00598                      theBeginTime,
00599                      theEndTime,
00600                      theTag );
00601         }
00602     }
00603     
00604     return BdbcSuccess;
00605 }
00606 
00607 BdbStatus
00608 BdbDatabase::store( const BdbHandle(BdbObject)& theObjectH,
00609                     const char*                 theContainerName,
00610                     const BdbIntervalBase&      theInterval,
00611                     d_ULong                     theTag )
00612 {
00613     BdbTime theBeginTime = theInterval.getBeginTime( );
00614     BdbTime theEndTime   = theInterval.getEndTime( );
00615 
00616     return store( theObjectH, theContainerName, theBeginTime, theEndTime, theTag );
00617 }
00618 
00619 BdbStatus
00620 BdbDatabase::storeAndTruncate( const BdbHandle(BdbObject)& theObjectH,
00621                                const char*                 theContainerName,
00622                                const BdbTime&              theInsertTime,
00623                                const BdbTime&              theExplicitTruncateTime,
00624                                d_ULong                     theTag )
00625 {
00626     const char* errorString   = "BdbDatabase::storeAndTruncate() -- ERROR.";
00627     const char* warningString = "BdbDatabase::storeAndTruncate() -- WARNINIG.";
00628 
00629   // This is "tree points" interface, where the third point is ment
00630   // to be "plus infinity".
00631 
00632     BdbStatus status;
00633 
00634     assert ( 0 != theContainerName );
00635     assert ( theInsertTime <= theExplicitTruncateTime );
00636     assert ( theExplicitTruncateTime < BdbTime::plusInfinity );
00637 
00638   // Override the explicitly specified truncate time if the override time
00639   // is set (it's not equal to +oo).
00640   // Otherwise just use the explicit one.
00641 
00642     BdbTime theTruncateTime = theExplicitTruncateTime;
00643 
00644     if ( BdbTime::plusInfinity != _truncateOverrideTime ) {
00645 
00646       // Perform more checks on the value of this time.
00647 
00648         if ( _truncateOverrideTime < theInsertTime ) {
00649             ErrMsg(error) << errorString << endl
00650                           << "    This is an incorrect use of the storeAndTruncate() method" << endl
00651                           << "    because the overriden value for the truncation time is less" << endl
00652                           << "    than the store (insertion) time." << endl
00653                           << "        DETECTOR  -> " << subsystemTLA( ) << endl
00654                           << "        CONTAINER -> " << theContainerName << endl
00655                             << "            INSERT TIME:             " << theInsertTime << endl
00656                             << "            EXPLICIT TRUNCATE TIME:  " << theExplicitTruncateTime << endl
00657                             << "            OVERRIDEN TRUNCATE TIME: " << _truncateOverrideTime << endmsg; 
00658             return BdbcError;
00659         }
00660         if ( _truncateOverrideTime < theExplicitTruncateTime ) {
00661             ErrMsg(routine) << warningString << endl
00662                             << "    This is a suspicious use of the storeAndTruncate() method" << endl
00663                             << "    because the overriden value for the truncation time is less" << endl
00664                             << "    than explicitly specified truncate time." << endl
00665                             << "        DETECTOR  -> " << subsystemTLA( ) << endl
00666                             << "        CONTAINER -> " << theContainerName << endl
00667                             << "            INSERT TIME:             " << theInsertTime << endl
00668                             << "            EXPLICIT TRUNCATE TIME:  " << theExplicitTruncateTime << endl
00669                             << "            OVERRIDEN TRUNCATE TIME: " << _truncateOverrideTime << endmsg;
00670         }
00671 
00672       // And finally replace the truncate time by the the overriden value.
00673       // More check will be done later on.
00674 
00675         theTruncateTime = _truncateOverrideTime;
00676     }
00677 
00678   // If the insert time is equal to the truncate time
00679   // then we just proceed with the "regular" open-ended ::store().
00680 
00681     if( theInsertTime == theTruncateTime ) {
00682 
00683         return store( theObjectH,
00684                       theContainerName,
00685                       theInsertTime,
00686                       theTag );
00687     }
00688 
00689     COUT1 << "CONDSTOREANDTRUNCATE: detector=" << subsystemTLA( ) << " container=" << theContainerName << " store_time=" << theInsertTime << " explicit_truncate_time=" << theExplicitTruncateTime << " truncate_time=" << theTruncateTime << endl;
00690 
00691   // Ensure the proper context to be set.
00692 
00693     if ( ! verifyIndexMode( ))               return BdbcError;
00694     if ( ! setAuthLevel( theContainerName )) return BdbcError;
00695 
00696   // Try to locate this interval container.
00697 
00698     BdbHandle(BdbContObj) intervalContH;
00699     if ( BdbcSuccess != findIntervalCont( intervalContH, theContainerName )) {
00700 
00701       // Create new container and store the object in there.
00702       //
00703       // NOTE: Unlike in case of a regular close-ended store this function
00704       //       would initialize the new interval container using the open-ended
00705       //       pattern. This is becase for the "store & truncate" the new object
00706       //       would last "forever".
00707 
00708         return  createIntervalCont( theContainerName,
00709                                     theObjectH,
00710                                     theInsertTime,
00711                                     BdbTime::plusInfinity,
00712                                     theTag );
00713 
00714     }
00715 
00716   // Locate the FIRST and the LAST intervals.
00717 
00718     BdbHandle(BdbIntervalR) firstIntervalH;
00719     BdbHandle(BdbIntervalR) lastIntervalH;
00720 
00721     firstIntervalH.lookupObj( intervalContH, "FirstInterval", BdbcUpdate  );
00722     if ( BdbIsNull(firstIntervalH)) {
00723         ErrMsg(error) << errorString << endl
00724                       << "    Can not find FIRST interval." << endl
00725                       << "    The container may have incorrect internal structure." << endl
00726                       << "        DETECTOR  -> " << subsystemTLA( ) << endl
00727                       << "        CONTAINER -> " << theContainerName << endmsg;
00728         return BdbcError;
00729     }
00730 
00731     lastIntervalH.lookupObj( intervalContH, "LastInterval", BdbcUpdate  );
00732     if ( BdbIsNull(lastIntervalH)) {
00733         ErrMsg(error) << errorString << endl
00734                       << "    Can not find LAST interval." << endl
00735                       << "    The container may have incorrect internal structure." << endl
00736                       << "        DETECTOR  -> " << subsystemTLA( ) << endl
00737                       << "        CONTAINER -> " << theContainerName << endmsg;
00738         return BdbcError;
00739     }
00740 
00741 /************************ DISABLED CODE ****************************
00742  *                                                                 *
00743  * The following check has been disabled in order to allow client  *
00744  * to cross the border of the LAST interval when using the current *
00745  * method.                                                         *
00746  *                                                                 *
00747  *******************************************************************
00748 
00749   // More check on the parameters.
00750   // They both must be either in a middle of intervals timeline or within
00751   // the last interval.
00752   //
00753   // NOTE: This checking is done only when a truncate time is strictly past
00754   //       the beginning of the LAST interval.
00755 
00756     if (( theInsertTime   < lastIntervalH->beginTime( )) &&
00757         ( theTruncateTime > lastIntervalH->beginTime( ))) {
00758         ErrMsg(error) << errorString << endl
00759                       << "    This is an incorrect use of the storeAndTruncate() method" << endl
00760                       << "    because both the store (insertion) and truncation (which is possibly overriden)" << endl
00761                       << "    times must be either inside or outside existing LAST interval." << endl
00762                       << "        DETECTOR  -> " << subsystemTLA( ) << endl
00763                       << "        CONTAINER -> " << theContainerName << endl
00764                       << "            INSERT TIME:             " << theInsertTime << endl
00765                       << "            EXPLICIT TRUNCATE TIME:  " << theExplicitTruncateTime << endl
00766                       << "            OVERRIDEN TRUNCATE TIME: " << _truncateOverrideTime << endmsg;
00767         return BdbcError;
00768     }
00769 */
00770 
00771   // Put a record into the History. We do this in advance, because creating
00772   // a new interval is not generally an atomic operations. If it fails
00773   // somewhere in the middle we would know what exactly we were trying
00774   // to do.
00775 
00776     historyTStore( rcsid, theObjectH, theInsertTime, theTruncateTime, theTag );
00777 
00778   // Modify the First interval
00779 
00780     if ( theInsertTime < firstIntervalH->getEndTime( )) {
00781 
00782         if ( theInsertTime == BdbTime::minusInfinity ) {
00783 
00784             if ( theTruncateTime >= firstIntervalH->getEndTime( )) {
00785 
00786               // Update the first interval until its very end.
00787 
00788                 status = updateFirstInterval( theObjectH,
00789                                               firstIntervalH,
00790                                               firstIntervalH->getEndTime( ),
00791                                               theTag );
00792 
00793                 if ( BdbcSuccess != status ) {
00794                     return status;
00795                 }
00796 
00797             } else {
00798 
00799               // Update the first interval until the specified truncate time.
00800               // And then immediatelly return.
00801 
00802                 return updateFirstInterval( theObjectH,
00803                                             firstIntervalH,
00804                                             theTruncateTime,
00805                                             theTag );
00806             }
00807 
00808         } else {
00809 
00810            if ( theTruncateTime >= firstIntervalH->getEndTime( )) {
00811 
00812              // Cut the first interval until its very end.
00813 
00814                 status = cutFirstInterval( theObjectH,
00815                                            firstIntervalH,
00816                                            theInsertTime,
00817                                            firstIntervalH->getEndTime( ),
00818                                            theTag );
00819 
00820                 if ( BdbcSuccess != status ) {
00821                     return status;
00822                 }
00823 
00824 
00825             } else {
00826 
00827               // Cut the first interval until the specified truncate time.
00828               // And then immediatelly return.
00829 
00830                 return cutFirstInterval( theObjectH,
00831                                          firstIntervalH,
00832                                          theInsertTime,
00833                                          theTruncateTime,
00834                                          theTag );
00835             }
00836         }
00837 
00838       // Use recursive call to the current function to store
00839       // the rest of the interval if the original interval
00840       // goes beyong the first interval.
00841 
00842         if ( theTruncateTime > firstIntervalH->getEndTime( )) {
00843 
00844             return storeAndTruncate( theObjectH,
00845                                      theContainerName,
00846                                      firstIntervalH->getEndTime( ),
00847                                      theTruncateTime,
00848                                      theTag );
00849         }
00850 
00851     } else {
00852 
00853       // Choose one of the possible scenarios depending on a place
00854       // where the new interval is going to.
00855 
00856         if ( theInsertTime < lastIntervalH->getBeginTime( )) {
00857 
00858             BdbTime theVersionTime = BdbTime( );    // This time would be common for all the objects
00859                                                     // in the vectors.
00860 
00861             if ( theTruncateTime <= lastIntervalH->getBeginTime( )) {
00862 
00863               // version an interval in the middle of the list
00864 
00865 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
00866  * The following code has been replaced by the call to the "::versionVector()" method
00867  * for the sake of efficency.
00868  *
00869  *               version( 0,
00870  *                        theObjectH,
00871  *                        theInsertTime,
00872  *                        theTruncateTime,
00873  *                        theTag );
00874  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
00875  */
00876                 return versionVector( theObjectH,
00877                                       theInsertTime,
00878                                       theTruncateTime,
00879                                       theVersionTime,
00880                                       theTag );
00881             } else {
00882 
00883               // version the first part of an interval in the middle of the list
00884 
00885 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
00886  * The following code has been replaced by the call to the "::versionVector()" method
00887  * for the sake of efficency.
00888  *
00889  *               version( 0,
00890  *                        theObjectH,
00891  *                        theInsertTime,
00892  *                        lastIntervalH->getBeginTime( ),
00893  *                        theTag );
00894  */
00895                 status = versionVector( theObjectH,
00896                                         theInsertTime,
00897                                         lastIntervalH->getBeginTime( ),
00898                                         theVersionTime,
00899                                         theTag );
00900                 if ( BdbcSuccess != status ) return status;
00901 
00902               // "regular" insert and truncate of the second part of specified
00903               // interval at the beginning of the last interval.
00904 
00905                 return truncateLastInterval( theObjectH,
00906                                              lastIntervalH,
00907                                              lastIntervalH->getBeginTime( ),
00908                                              theTruncateTime,
00909                                              theTag );
00910             }
00911 
00912         } else {
00913 
00914           // "regular" insert and truncate of the whole interval in the middle
00915           // of the last interval.
00916 
00917             return truncateLastInterval( theObjectH,
00918                                          lastIntervalH,
00919                                          theInsertTime,
00920                                          theTruncateTime,
00921                                          theTag );
00922         }
00923     }
00924 
00925     return BdbcSuccess;
00926 }
00927 
00928 BdbStatus
00929 BdbDatabase::storeVector( const vector<BdbCondStoreTime>& theVector,
00930                           const char*                                 theContainerName )
00931 {
00932     const char* errorString = "BdbDatabase::storeVector() -- ERROR.";
00933 
00934     BdbStatus status;
00935     BdbTime   theVersionTime = BdbTime( );  // This time would be common for all the objects
00936                                             // in the vector.
00937     BdbHandle(BdbObject) theObjectH;
00938     BdbRef(BdbObject)    theObjectRef;
00939 
00940     BdbTime theBeginTime;
00941     BdbTime theEndTime;
00942 
00943     BdbIntervalBase theIntervalBase;
00944 
00945     BdbHandle(BdbIntervalR) theIntervalH;
00946     BdbHandle(BdbIntervalR) theFirstIntervalH;
00947     BdbHandle(BdbIntervalR) theLastIntervalH;
00948     BdbHandle(BdbIntervalR) theOldIntervalH;
00949     BdbHandle(BdbIntervalR) theNewIntervalH;
00950 
00951     BdbHandle(BdbCondRevision) baselineRevisionH;
00952 
00953     assert( 0 != theContainerName );
00954 
00955     COUT1 << "CONDSTOREVECTOR: detector=" << subsystemTLA( ) << " container=" << theContainerName << " entries=" << theVector.size( ) << endl;
00956 
00957   // Verify the contents of the specified vector.
00958 
00959     status = verifyStoreVector( theVector );
00960     if( BdbcSuccess != status ) {
00961         return status;
00962     }
00963 
00964   // Ensure the proper context to be set.
00965 
00966     if ( ! verifyIndexMode( ))               return BdbcError;
00967     if ( ! setAuthLevel( theContainerName )) return BdbcError;
00968 
00969   // Try to locate this interval container.
00970 
00971     BdbHandle(BdbContObj) intervalContH;
00972     if( BdbcSuccess != findIntervalCont( intervalContH, theContainerName )) {
00973 
00974 
00975       // Create and initialize the interval container and store the whole vector as
00976       // a plain sequence of intervals.
00977       //
00978       // The algorithm:
00979       //
00980       //    1. Take the first two elements from the vector and use their limits
00981       //       to initialize the container.
00982       //
00983       //            NOTE: We assume that the first object is not equal to null.
00984       //
00985       //    2. Take the next elements one-by one and append them to the next interval
00986       //       using the standard methods.
00987 
00988         theObjectH   = theVector[0].getObject( );
00989         theBeginTime = theVector[0].getTime( );
00990         theEndTime   = theVector[1].getTime( );
00991 
00992         status = createIntervalCont( theContainerName,
00993                                      theObjectH,
00994                                      theBeginTime,
00995                                      theEndTime,
00996                                      0,
00997                                      theVersionTime );
00998         if ( BdbcSuccess != status ) {
00999             return status;
01000         }
01001 
01002       // Get the container handle and proceed loading elements of the vector
01003       // into there.
01004 
01005         getIntervalContH( intervalContH );
01006 
01007         int entries = theVector.size( );
01008         for( int i = 1; i < (entries - 1); i++ ) {
01009 
01010             theObjectH   = theVector[i].getObject( );
01011             theBeginTime = theVector[i].getTime( );
01012             theEndTime   = theVector[i+1].getTime( );
01013 
01014             theLastIntervalH.lookupObj( intervalContH, "LastInterval", BdbcUpdate );
01015             if( BdbIsNull(theLastIntervalH)) {
01016                 ErrMsg(error) << errorString << endl
01017                               << "    Failed to locate the LAST interval." << endl
01018                               << "    The container may be inproperly created and/or initialized." << endl
01019                               << "        DETECTOR  -> " << subsystemTLA( ) << endl
01020                               << "        CONTAINER -> " << theContainerName << endmsg;
01021                 return BdbcError;
01022             }
01023 
01024           // Cut last interval.
01025           //
01026           //    NOTE: We always use "cutLastInterval", but not "appendIntervalR"
01027           //          because each new interval starts from the very beginning
01028           //          of the LAST one.
01029 
01030             status = cutLastInterval( theObjectH,
01031                                       theLastIntervalH,
01032                                       theBeginTime,
01033                                       theEndTime,
01034                                       0,
01035                                       theVersionTime );
01036             if( BdbcSuccess != status ) {
01037                 ErrMsg(error) << errorString << endl
01038                               << "    Failed to cut the LAST interval." << endl
01039                               << "        DETECTOR  -> " << subsystemTLA( ) << endl
01040                               << "        CONTAINER  -> " << theContainerName << endl
01041                               << "            BEGIN_TIME -> " << theBeginTime << endl
01042                               << "            END_TIME   -> " << theEndTime << endmsg;
01043                 return status;
01044             }
01045         }
01046 
01047       // Put a record into the History.
01048 
01049         historyStoreVector( rcsid, theVector );
01050 
01051         return BdbcSuccess;
01052     }
01053 
01054   // Get the current BASELINE revision. We would need this revision when creating new
01055   // intervals later.
01056 
01057     getBaselineRevisionH( baselineRevisionH );
01058 
01059   // Put a record into the History. We do this in advance, because creating
01060   // a new interval is not generally an atomic operations. If it fails
01061   // somewhere in the middle we would know what exactly we were trying
01062   // to do.
01063 
01064     historyStoreVector( rcsid, theVector );
01065 
01066   // Fetch an interval where the first time from the input
01067   // vector falls into.
01068   //
01069   //    NOTE: If this is the first interval and if this interval has zero
01070   //          length [-oo,-oo) then just skip this interval and proceed to
01071   //          the next one.
01072 
01073     theBeginTime = theVector[0].getTime( );
01074 
01075     findInterval( theIntervalH, theBeginTime, 0 );
01076     if( BdbIsNull(theIntervalH)) {
01077         ErrMsg(error) << errorString << endl
01078                       << "    Failed to find a TOPMOST interval matching specified validity time." << endl
01079                       << "        DETECTOR  -> " << subsystemTLA( ) << endl
01080                       << "        CONTAINER -> " << theContainerName << endl
01081                       << "            TIME      -> " << theBeginTime << endmsg;
01082         return BdbcError;
01083     }
01084     if(( BdbTime::minusInfinity == theIntervalH->getBeginTime( )) &&
01085        ( BdbTime::minusInfinity == theIntervalH->getEndTime( ))) {
01086 
01087         theIntervalH->getTopNext( theIntervalH );
01088     }
01089 
01090   // Get the handle for the FIRST & LAST intervals. We will use these handles to verify
01091   // if a special processing is needed.
01092 
01093     theFirstIntervalH.lookupObj( intervalContH, "FirstInterval", BdbcUpdate );
01094     if( BdbIsNull(theFirstIntervalH)) {
01095         ErrMsg(error) << errorString << endl
01096                       << "    Failed to locate the FIRST interval." << endl
01097                       << "    The container may be inproperly created and/or initialized." << endl
01098                       << "        DETECTOR  -> " << subsystemTLA( ) << endl
01099                       << "        CONTAINER -> " << theContainerName << endmsg;
01100         return BdbcError;
01101     }
01102 
01103     theLastIntervalH.lookupObj( intervalContH, "LastInterval", BdbcUpdate );
01104     if( BdbIsNull(theLastIntervalH)) {
01105         ErrMsg(error) << errorString << endl
01106                       << "    Failed to locate the LAST interval." << endl
01107                       << "    The container may be inproperly created and/or initialized." << endl
01108                       << "        DETECTOR  -> " << subsystemTLA( ) << endl
01109                       << "        CONTAINER -> " << theContainerName << endmsg;
01110         return BdbcError;
01111     }
01112 
01113   // Translate the input vector of times into a vector of intervals. The intervals
01114   // will be continious in the validity time.
01115   // The resulting intervals will be aligned to the borders of existing intervals.
01116   //
01117   //    NOTE: The value of the starting interval handle could be modifyied
01118   //          by this recursive algorithm.
01119   //
01120   //    NOTE: The handles of both FIRST and LAST intervals may be used by
01121   //          the building algorithm.
01122 
01123     vector<BdbCondStoreInterval>  theIntervalVector;
01124 
01125     status = buildTopStoreVector( theVector,
01126                                   theFirstIntervalH,
01127                                   theLastIntervalH,
01128                                   theIntervalH,
01129                                   theIntervalVector );
01130     if( BdbcSuccess != status ) {
01131         return status;
01132     }
01133 
01134   // Process the resulting intervals vector, by taking each interval description from
01135   // there one-by-one and applying these intrervals to the existing structure.
01136 
01137     int entries = theIntervalVector.size( );
01138     for( int i = 0; i < entries; i++ ) {
01139 
01140         theObjectH = theIntervalVector[i].getObject( );
01141         theIntervalVector[i].getInterval( theIntervalBase );
01142         theIntervalVector[i].getExistingInterval( theOldIntervalH );
01143 
01144         theBeginTime = theIntervalBase.getBeginTime( );
01145         theEndTime   = theIntervalBase.getEndTime( );
01146 
01147       // Check if we are trying to modify the FIRST interval.
01148       // In this case a new interval may not be aligned to the border
01149       // of the existing intervals.
01150 
01151         if( theOldIntervalH == theFirstIntervalH ) {
01152 
01153           // The further actions depend on where the new interval begins
01154           // and ends.
01155 
01156             if( BdbTime::minusInfinity == theBeginTime ) {
01157 
01158               // The new interval begins on -oo.
01159 
01160                 if( theFirstIntervalH->getEndTime( ) != theEndTime ) {
01161 
01162                   // The new interval covers just a part of the FIRST interval
01163                   // starting from the very beginning.
01164                   // Now we are going to create a new FIRST interval, update it
01165                   // with new data.
01166                   // This would leave the rest of the former FIRST interval as is
01167                   // with the same OID, thus making the rest of the translated
01168                   // interval vector valid.
01169 
01170                     theOldIntervalH->setBeginTime( theEndTime );
01171                     theNewIntervalH = new( intervalContH ) BdbIntervalR( theOldIntervalH->getObject( ),
01172                                                                          BdbTime::minusInfinity,
01173                                                                          theEndTime,
01174                                                                          0 );
01175                     theNewIntervalH->setVersionTime( theOldIntervalH->getVersionTime( ));
01176                     theNewIntervalH->setRevision( baselineRevisionH );
01177 
01178                     theNewIntervalH->setBaselineNext( theOldIntervalH );
01179                     theOldIntervalH->setBaselinePrevious( theNewIntervalH );
01180 
01181                     theNewIntervalH->setTopNext( theOldIntervalH );
01182                     theOldIntervalH->setTopPrevious( theNewIntervalH );
01183 
01184                     theOldIntervalH.unnameObj(  intervalContH );
01185                     theNewIntervalH.nameObj( intervalContH, "FirstInterval" );
01186 
01187                   // Now we will also modify the current value for the FIRST
01188                   // interval handle which we used for comparision.
01189 
01190                     theFirstIntervalH = theNewIntervalH;
01191 
01192                 }
01193 
01194               // New we are guarantied that the new interval completelly covers
01195               // the FIRST interval.
01196               // So now we are going just to update this interval.
01197 
01198                 updateFirstInterval( theObjectH, theFirstIntervalH, theEndTime, 0, theVersionTime );
01199 
01200             } else {
01201 
01202               // The new interval does not begin in -oo.
01203 
01204               // Cut the first interval right here where the new one begins.
01205               // This would create a new FIRST interval with different OID,
01206               // thus leaving all existing definitions in the interval vector
01207               // to be valid.
01208 
01209                 theOldIntervalH->setBeginTime( theBeginTime );
01210                 theNewIntervalH = new( intervalContH ) BdbIntervalR( theOldIntervalH->getObject( ),
01211                                                                      BdbTime::minusInfinity,
01212                                                                      theBeginTime,
01213                                                                           0 );
01214                 theNewIntervalH->setVersionTime( theOldIntervalH->getVersionTime( ));
01215                 theNewIntervalH->setRevision( baselineRevisionH );
01216 
01217                 theNewIntervalH->setBaselineNext( theOldIntervalH );
01218                 theOldIntervalH->setBaselinePrevious( theNewIntervalH );
01219 
01220                 theNewIntervalH->setTopNext( theOldIntervalH );
01221                 theOldIntervalH->setTopPrevious( theNewIntervalH );
01222 
01223                 theOldIntervalH.unnameObj( intervalContH );
01224                 theNewIntervalH.nameObj( intervalContH, "FirstInterval" );
01225 
01226               // Now we will also modify the current value for the FIRST
01227               // interval handle which we used for comparision.
01228 
01229                 theFirstIntervalH = theNewIntervalH;
01230 
01231               // And finally - add the version to the ex-FIRST interval,
01232               // which is now the second one.
01233               //
01234               // NOTE: This operation is safe since we are guarantied that
01235               //       the end time of the new version to be added will never
01236               //       fall into the last interval and will never span the end
01237               //       border of existing interval to be versioned.
01238 
01239                 addVectorVersion( theOldIntervalH, theObjectH, theBeginTime, theEndTime, theVersionTime  );
01240 
01241             }
01242 
01243         } else if( theOldIntervalH == theLastIntervalH ) {
01244 
01245           // The new interval falls into existing LAST interval. In this case
01246           // we jsut follow the same scenario we were using when initializing a newly
01247           // created interval container with a vector of values.
01248           // This means that each new interval will be trivially "updated" or "cutted"
01249           // (depending on when the new interval ends).
01250           //
01251           // Replace the object in the existing last interval
01252           // if the new one ends in +oo.
01253 
01254             for( int j = i; j < entries; j++ ) {
01255 
01256                 theObjectH = theIntervalVector[j].getObject( );
01257                 theIntervalVector[j].getInterval( theIntervalBase );
01258                 theIntervalVector[j].getExistingInterval( theOldIntervalH );
01259 
01260                 theBeginTime = theIntervalBase.getBeginTime( );
01261                 theEndTime   = theIntervalBase.getEndTime( );
01262 
01263               // Update the reference to the LAST interval.
01264 
01265                 theLastIntervalH.lookupObj( intervalContH, "LastInterval", BdbcUpdate );
01266                 if( BdbIsNull(theLastIntervalH)) {
01267                     ErrMsg(error) << errorString << endl
01268                                   << "    Failed to locate the LAST interval." << endl
01269                                   << "    The container may be inproperly created and/or initialized." << endl
01270                                   << "        DETECTOR  -> " << subsystemTLA( ) << endl
01271                                   << "        CONTAINER -> " << theContainerName << endmsg;
01272                     return BdbcError;
01273                 }
01274 
01275               // Use the object reference from the last interval if the new one
01276               // is equal to zero.
01277 
01278                 if( BdbIsNull(theObjectH)) {
01279                     theLastIntervalH->getObject( theObjectRef );
01280                     theObjectH = theObjectRef;
01281                 }
01282 
01283               // Cut/append last interval.
01284 
01285                 if ( theBeginTime == theLastIntervalH->getBeginTime( )) {
01286 
01287                     status = cutLastInterval( theObjectH,
01288                                               theLastIntervalH,
01289                                               theBeginTime,
01290                                               theEndTime,
01291                                               0,
01292                                               theVersionTime );
01293                 } else {
01294 
01295                     status = appendIntervalR( theObjectH,
01296                                               theLastIntervalH,
01297                                               theBeginTime,
01298                                               theEndTime,
01299                                               0,
01300                                               theVersionTime );
01301                 }
01302                 if( BdbcSuccess != status ) {
01303                     ErrMsg(error) << errorString << endl
01304                                   << "    Failed to cut/append LAST interval." << endl
01305                                   << "        DETECTOR  -> " << subsystemTLA( ) << endl
01306                                   << "        CONTAINER  -> " << theContainerName << endl
01307                                   << "            BEGIN_TIME -> " << theBeginTime << endl
01308                                   << "            END_TIME   -> " << theEndTime << endmsg;
01309                     return BdbcError;
01310                 }
01311             }
01312 
01313           // Just break the outer loop since we've processed
01314           // the remaining elements from the list.
01315 
01316             break;
01317 
01318         } else {
01319 
01320       // Now we are adding an interval somewhere in the middle of the list. This procedure
01321       // is quite routine given the prepared contents of the vector.
01322 
01323            addVectorVersion( theOldIntervalH, theObjectH, theBeginTime, theEndTime, theVersionTime );
01324         }
01325     }
01326 
01327     return BdbcSuccess;
01328 }
01329 
01330 BdbStatus
01331 BdbDatabase::verifyStoreVector( const vector<BdbCondStoreTime>& theVector )
01332 {
01333     const char* errorString = "BdbDatabase::verifyStoreVector() -- ERROR.";
01334 
01335   // The vector must have at least 2 elements.
01336 
01337     int entries = theVector.size( );
01338 
01339     if( entries < 2 ) {
01340         ErrMsg(error) << errorString << endl
01341                       << "    The vector containes less than 2 elements." << endmsg;
01342         return BdbcError;
01343     }
01344 
01345   // The first element must NOT contain the NULL reference.
01346 
01347     BdbRef(BdbObject) theObjectRef;
01348 
01349     theObjectRef = theVector[0].getObject( );
01350     if( BdbIsNull(theObjectRef)) {
01351         ErrMsg(error) << errorString << endl
01352                       << "    The first element of the vector must NOT contain a NULL reference." << endmsg;
01353         return BdbcError;
01354     }
01355 
01356   // The last element must contain the NULL reference.
01357 
01358     theObjectRef = theVector[entries-1].getObject( );
01359     if( ! BdbIsNull(theObjectRef)) {
01360         ErrMsg(error) << errorString << endl
01361                       << "    The last element of the vector must contain a NULL reference." << endmsg;
01362         return BdbcError;
01363     }
01364 
01365   // The should be no NULL gaps between the elements
01366 
01367     for( int i = 0; i < entries; i++ ) {
01368         if( i > 0 ) {
01369             if( theVector[i].getTime( ) <= theVector[i-1].getTime( )) {
01370                 ErrMsg(error) << errorString << endl
01371                               << "    The NULL gaps in the validity time are not allowed" << endl
01372                               << "    in the vector." << endl
01373                               << "    This rule is broken for the element #" << i << endmsg;
01374                 return BdbcError;
01375             }
01376         }
01377     }
01378 
01379     return BdbcSuccess;
01380 }
01381 
01382 BdbStatus
01383 BdbDatabase::buildTopStoreVector( const vector<BdbCondStoreTime>& theVectorIn,
01384                                   const BdbHandle(BdbIntervalR)&              theFirstIntervalH,
01385                                   const BdbHandle(BdbIntervalR)&              theLastIntervalH,
01386                                   const BdbHandle(BdbIntervalR)&              theStartIntervalH,
01387                                   vector<BdbCondStoreInterval>&  theVectorOut )
01388 {
01389     const char* errorString = "BdbDatabase::buildTopStoreVector() -- ERROR.";
01390 
01391     BdbRef(BdbObject)       theObjectRef;
01392     BdbTime                 theBeginTime;
01393     BdbTime                 theEndTime;
01394     BdbHandle(BdbIntervalR) theIntervalH;
01395     BdbHandle(BdbIntervalR) thePreviousIntervalH;
01396 
01397     theIntervalH = theStartIntervalH;
01398 
01399     theVectorOut.clear( );
01400 
01401   // Optional alignment in the beginning.
01402   //
01403   //    NOTE: The FIRST & LAST intervals are always excluded.
01404 
01405     theBeginTime = theVectorIn[0].getTime( );
01406     theEndTime   = theVectorIn[1].getTime( );
01407 
01408     if(( theIntervalH != theFirstIntervalH ) &&
01409        ( theIntervalH != theLastIntervalH ) &&
01410        ( theBeginTime > theIntervalH->getBeginTime( ))) {
01411 
01412       // Insert a "pad" interval at the very beginning if the new interval begins
01413       // later then the existing one.
01414       //
01415       //  +----------------- theIntervalH->getBeginTime( )
01416       //  |
01417       //  |   theBeginTime
01418       //  V        v
01419       //  +........+--------
01420       //  :   pad  :  new
01421       //  +========+========
01422       //  :     existing
01423       //  +=================
01424       //
01425       // NOTE: we are padding the interval with NULL reference.
01426       //
01427 
01428         theVectorOut.push_back( BdbCondStoreInterval( BdbIntervalBase( theIntervalH->getBeginTime( ),
01429                                                                     theBeginTime ),
01430                                                    theIntervalH,
01431                                                    0 ));
01432     }
01433 
01434   // Continue processing the rest of the vector (including the very first interval).
01435 
01436     int entries = theVectorIn.size( );
01437     for( int i = 0; i < ( entries - 1 ); i++ ) {
01438 
01439         theObjectRef = theVectorIn[i].getObject( );
01440         theBeginTime = theVectorIn[i].getTime( );
01441         theEndTime   = theVectorIn[i+1].getTime( );
01442 
01443         if( theEndTime < theIntervalH->getEndTime( )) {
01444 
01445           // Introduce the regular interval ending with the end of
01446           // of the new interval.
01447           //
01448           //    theBeginTime
01449           //         |
01450           //         |     theEndTime 
01451           //         v         v
01452           //         +---------+
01453           //         :   new   :
01454           //  =======+=========+======
01455           //           existing
01456           //  ========================
01457 
01458             theVectorOut.push_back( BdbCondStoreInterval( BdbIntervalBase( theBeginTime,
01459                                                                         theEndTime ),
01460                                                        theIntervalH,
01461                                                        theObjectRef ));
01462         } else {
01463 
01464           // Introduce the regular interval ending with the end of
01465           // of the existing interval.
01466           //
01467           //    theBeginTime
01468           //         v
01469           //         +--------------
01470           //         :   new
01471           //  =======+=========+====
01472           //          existing :
01473           //  =================+====
01474           //                   ^
01475           //                   |
01476           //                   +------- theIntervalH->getEndTime( )
01477 
01478             theVectorOut.push_back( BdbCondStoreInterval( BdbIntervalBase( theBeginTime,
01479                                                                         theIntervalH->getEndTime( )),
01480                                                        theIntervalH,
01481                                                        theObjectRef ));
01482 
01483           // Advance a pointer to the next existing interval.
01484           //
01485           //    NOTE: The previous interval is saved in a special variable.
01486 
01487             thePreviousIntervalH = theIntervalH;
01488             thePreviousIntervalH->getTopNext( theIntervalH );
01489 
01490             if(( ! BdbIsNull(theIntervalH)) &&
01491                ( theEndTime >= theIntervalH->getEndTime( ))) {
01492 
01493               // The new interval lasts after the end of the existing interval.
01494 
01495               // Include all the "internal" existing intervals into an outout vector.
01496               // These interval lay completelly inside the new input interval.
01497 
01498                 while(( ! BdbIsNull(theIntervalH)) &&
01499                       ( theEndTime >= theIntervalH->getEndTime( ))) {
01500 
01501                   // Introduce the whole existing interval.
01502                   //
01503                   //  --------------------
01504                   //           new
01505                   //  ====+==========+====
01506                   //      : existing :
01507                   //  ====+==========+====
01508                   //      ^          ^
01509                   //      |          |
01510                   //      |          +------- theIntervalH->getEndTime( )
01511                   //      |
01512                   //      +----- theIntervalH->getBeginTime( )
01513 
01514                     theVectorOut.push_back( BdbCondStoreInterval( BdbIntervalBase( theIntervalH->getBeginTime( ),
01515                                                                                 theIntervalH->getEndTime( )),
01516                                                            theIntervalH,
01517                                                            theObjectRef ));
01518                     thePreviousIntervalH = theIntervalH;
01519                     thePreviousIntervalH->getTopNext( theIntervalH );
01520                 }
01521             }
01522 
01523           // Check if the rest of the current existing interval was not
01524           // completelly covered by the new one.
01525           // If so then just complete it.
01526 
01527             if(( ! BdbIsNull(theIntervalH)) &&
01528                ( theEndTime > theIntervalH->getBeginTime( )) &&
01529                ( theEndTime < theIntervalH->getEndTime( ))) {
01530 
01531               // Introduce the beginning of the existing interval.
01532               //
01533               //             theEndTime 
01534               //                 v
01535               //  ---------------+
01536               //           new   :
01537               //  ====+===============
01538               //      : existing
01539               //  ====+===============
01540               //      ^
01541               //      |
01542               //      |
01543               //      |
01544               //      +----- theIntervalH->getBeginTime( )
01545 
01546                 theVectorOut.push_back( BdbCondStoreInterval( BdbIntervalBase( theIntervalH->getBeginTime( ),
01547                                                                             theEndTime ),
01548                                                        theIntervalH,
01549                                                        theObjectRef ));
01550             }
01551         }
01552     }
01553 
01554   // Optional alignment in the end.
01555   //
01556   //    NOTE: The LAST interval is always excluded.
01557 
01558     if(( ! BdbIsNull(theIntervalH)) &&
01559        ( theIntervalH != theLastIntervalH )) {
01560 
01561         theEndTime = theVectorIn[entries-1].getTime( );
01562 
01563         if(( theEndTime > theIntervalH->getBeginTime( )) &&
01564            ( theEndTime < theIntervalH->getEndTime( ))) {
01565 
01566           // Introduce the "pad" interval on the right side of the last
01567           // new interval.
01568           //
01569           //                   +------- theIntervalH->getEndTime( )
01570           //       theEndTime  |
01571           //           v       v
01572           //  ---------+.......+
01573           //      new  :  pad  :
01574           //  =========+=======+
01575           //        existing   :
01576           //  =================+
01577           //
01578           // NOTE: we are padding the interval with NULL reference.
01579           //
01580 
01581 
01582             theVectorOut.push_back( BdbCondStoreInterval( BdbIntervalBase( theEndTime,
01583                                                                         theIntervalH->getEndTime( )),
01584                                                        theIntervalH,
01585                                                        0 ));
01586         }
01587     }
01588 
01589     return BdbcSuccess;
01590 }
01591 
01592 void
01593 BdbDatabase::addVectorVersion( BdbHandle(BdbIntervalR)&       theOldIntervalH,
01594                                const BdbHandle(BdbObject)&    theObjectH,
01595                                const BdbTime&                 theBeginTime,
01596                                const BdbTime&                 theEndTime,
01597                                const BdbTime&                 theVersionTime,
01598                                d_ULong                        theTag )
01599 {
01600     BdbHandle(BdbIntervalR) theNewIntervalH;
01601     BdbHandle(BdbIntervalR) thePreviousIntervalH;
01602     BdbHandle(BdbIntervalR) theNextIntervalH;
01603 
01604   // The further operation depends both on the previous context of
01605   // the operation (whether we are are starting creating new versions
01606   // or we are just continuing this) and on the number of versions
01607   // for specified interval.
01608 
01609     if( theOldIntervalH->getBeginTime( ) == theBeginTime ) {
01610 
01611       // We are about to begin creating versions of the interval.
01612 
01613         if( theOldIntervalH->getEndTime( ) == theEndTime ) {
01614 
01615           // The only version.
01616 
01617             theOldIntervalH.setVersStatus( oocLinearVers );
01618             createRevisedTopVersion( theOldIntervalH, theNewIntervalH );
01619             theOldIntervalH.setVersStatus( oocNoVers );
01620 
01621           // Tune the TOPMOST links
01622 
01623             theOldIntervalH->getTopPrevious( thePreviousIntervalH );
01624             theOldIntervalH->getTopNext(     theNextIntervalH );
01625             theOldIntervalH->setTopPrevious( 0 );
01626             theOldIntervalH->setTopNext(     0 );
01627 
01628         } else {
01629 
01630           // The first version.
01631 
01632             theOldIntervalH.setVersStatus( oocBranchVers );
01633             createRevisedTopVersion( theOldIntervalH, theNewIntervalH );
01634 
01635           // Modify the TOPMOST links. Since this is the first interval
01636           // in a sequence of (at least two) versions then we will store
01637           // the reference to the newely created version in the existing
01638           // interval.
01639 
01640             theOldIntervalH->getTopPrevious( thePreviousIntervalH );
01641             theOldIntervalH->getTopNext(     theNextIntervalH );
01642             theOldIntervalH->setTopPrevious( 0 );
01643             theOldIntervalH->setTopNext(     theNewIntervalH );         // Will use this to create next version.
01644         }
01645 
01646     } else {
01647 
01648       // We continue creating the versions.
01649 
01650         if( theOldIntervalH->getEndTime( ) == theEndTime ) {
01651 
01652           // The last version.
01653 
01654             createRevisedTopVersion( theOldIntervalH, theNewIntervalH );
01655             theOldIntervalH.setVersStatus( oocNoVers );
01656 
01657           // Modify the TOPMOST links. Now we take the previous & next links
01658           // from the previously created version of the existing interval.
01659           // The handle of the previous version is located through the next link
01660           // of the exising interval.
01661           // Then we just reset this "back" link to zero since we are not
01662           // going to use it anymore.
01663 
01664             theOldIntervalH->getTopNext(      thePreviousIntervalH );
01665             theOldIntervalH->setTopNext(      0 );                      // This is not needed anymore.
01666             thePreviousIntervalH->getTopNext( theNextIntervalH );
01667 
01668         } else {
01669 
01670           // The intermediate version.
01671 
01672             createRevisedTopVersion( theOldIntervalH, theNewIntervalH );
01673 
01674           // Modify the TOPMOST links. Now we take the previous & next links
01675           // from the previously created version of the existing interval.
01676           // The handle of the previous version is located through the next link
01677           // of the exising interval.
01678           // Then we just replace the value of this "back" link with the value
01679           // of the newly created interval (version).
01680 
01681             theOldIntervalH->getTopNext(      thePreviousIntervalH );
01682             theOldIntervalH->setTopNext(      theNewIntervalH );        // Will use this to create next version.
01683             thePreviousIntervalH->getTopNext( theNextIntervalH );
01684 
01685         }
01686     }
01687 
01688   // Now we known the previous and next intervals in the TOPMOST chain. So we can
01689   // modify these links as needed. This procedure is irrelevant to the position
01690   // of the nexly created version.
01691 
01692     thePreviousIntervalH->setTopNext( theNewIntervalH );
01693     theNewIntervalH->setTopPrevious(  thePreviousIntervalH );
01694     theNewIntervalH->setTopNext(      theNextIntervalH );
01695     theNextIntervalH->setTopPrevious( theNewIntervalH );
01696 
01697   // Set the validity limits of the new interval.
01698 
01699     theNewIntervalH->setBeginTime( theBeginTime );
01700     theNewIntervalH->setEndTime( theEndTime );
01701 
01702   // Set the proper object, version time and tag into a new interval.
01703   //
01704   // NOTE: We use an object handle, the version time and the tag from the existing
01705   //       interval if the NULL handle is being passed as a parameter.
01706 
01707     if( BdbIsNull(theObjectH)) {
01708 
01709         BdbHandle(BdbObject) theOldObjectH;
01710         BdbRef(BdbObject)    theOldObjectRef;
01711 
01712         theOldIntervalH->getObject( theOldObjectRef );
01713         theOldObjectH = theOldObjectRef;
01714 
01715         theNewIntervalH->setObject( theOldObjectH );
01716         theNewIntervalH->setVersionTime( theOldIntervalH->getVersionTime( ));
01717         theNewIntervalH->setTag( theOldIntervalH->getTag( ));
01718     } else {
01719         theNewIntervalH->setObject( theObjectH );
01720         theNewIntervalH->setVersionTime( theVersionTime );
01721         theNewIntervalH->setTag( theTag );
01722     }
01723 
01724 /**********************************************************************************
01725  ** THIS CODE IS DISABLED FOR TWO REASONS:
01726  **
01727  **   1. It's just not required any more given the current implementation
01728  **      of the low-level interval creation procedures:
01729  **
01730  **          createVersion()
01731  **          createRevisedTopVersion()
01732  **
01733  **   2. It may reset the "reviseAfterStore" revision connection of the newely
01734  **      created version if this feature is turned on for this particular
01735  **      interval container.
01736  **
01737  ** // Explicitly set the NULL revision id in order to avoid
01738  ** // duplicating this ID from the existing interval (this is how the used here
01739  ** // intervals creation technique works).
01740  **
01741  **    theNewIntervalH->setRevision( 0 );
01742  **
01743  **********************************************************************************
01744  **/
01745 
01746   // Name new interval in the genealogy tree.
01747 
01748     nameVersion( theOldIntervalH, theNewIntervalH );
01749 }
01750 
01751 BdbStatus
01752 BdbDatabase::fetch( BdbHandle(BdbObject)& theObjectH,
01753                     const char*           theContainerName,
01754                     const BdbTime&        theTime,
01755                     d_ULong               theTag ) 
01756 {
01757     COUT1 << "CONDFETCH1: detector=" << subsystemTLA( ) << " container=" << theContainerName << " fetch_time=" << theTime << endl;
01758 
01759     return findObject( theObjectH, theContainerName, theTime, theTag );
01760 }
01761 
01762 BdbStatus
01763 BdbDatabase::fetch( BdbHandle(BdbObject)& theObjectH,    
01764                     BdbIntervalBase&      theValidityInterval,
01765                     const char*           theContainerName,  
01766                     const BdbTime&        theTime,             
01767                     d_ULong               theTag )
01768 {
01769     assert( 0 != theContainerName );
01770 
01771     COUT1 << "CONDFETCH2: detector=" << subsystemTLA( ) << " container=" << theContainerName << " fetch_time=" << theTime << endl;
01772 
01773   // Ask accessor to find specified object.
01774   //
01775   // NOTE: This way to get a condition differs from the regular "fetch" since
01776   //       it's directly talking to the accessor.
01777   //       Nevertheless the correct class cache is set by the accessor.
01778 
01779     BdbTime theVersionTime;     // We're not using this, but the acccessor's method requires
01780                                 // a parameter of this type to be passed in.
01781 
01782     return _accessor->findObject( this,
01783                                   theObjectH,
01784                                   theValidityInterval,
01785                                   theVersionTime,
01786                                   theContainerName,
01787                                   theTime );
01788 }
01789 
01790 BdbStatus
01791 BdbDatabase::fetch( BdbHandle(BdbObject)& theObjectH,    
01792                     BdbIntervalBase&      theValidityInterval,
01793                     BdbTime&              theVersionTime,
01794                     const char*           theContainerName,  
01795                     const BdbTime&        theTime,             
01796                     d_ULong               theTag )
01797 {
01798     assert( 0 != theContainerName );
01799 
01800     COUT1 << "CONDFETCH3: detector=" << subsystemTLA( ) << " container=" << theContainerName << " fetch_time=" << theTime << endl;
01801 
01802   // Ask accessor to find specified object.
01803   //
01804   // NOTE: This way to get a condition differs from the regular "fetch" since
01805   //       it's directly talking to the accessor.
01806   //       Nevertheless the correct class cache is set by the accessor.
01807 
01808     return _accessor->findObject( this,
01809                                   theObjectH,
01810                                   theValidityInterval,
01811                                   theVersionTime,
01812                                   theContainerName,
01813                                   theTime );
01814 }
01815 
01816 BdbStatus
01817 BdbDatabase::remove( const char*    theContainerName,
01818                      const BdbTime& theTime )
01819 {
01820     const char* errorString = "BdbDatabase::remove() -- ERROR.";
01821 
01822     assert( 0 != theContainerName );
01823 
01824     COUT1 << "CONDREMOVE: detector=" << subsystemTLA( ) << " container=" << theContainerName << " remove_time=" << theTime << endl;
01825 
01826     ErrMsg(error) << errorString << endl
01827                   << "    Not implemented yet." << endmsg;
01828     return BdbcError;
01829 }
01830 
01831 BdbStatus
01832 BdbDatabase::split( const char*    theContainerName,
01833                     const BdbTime& theTime )
01834 {
01835     const char* errorString = "BdbDatabase::split() -- ERROR.";
01836 
01837     BdbStatus status = BdbcError;
01838 
01839     assert ( 0 != theContainerName );
01840     assert ( BdbTime::minusInfinity != theTime);
01841     assert ( BdbTime::plusInfinity  != theTime);
01842 
01843     COUT1 << "CONDSPLIT: detector=" << subsystemTLA( ) << " container=" << theContainerName << " split_time=" << theTime << endl;
01844 
01845   // Ensure the proper context to be set.
01846 
01847     if ( ! verifyIndexMode( ))               return BdbcError;
01848     if ( ! setAuthLevel( theContainerName )) return BdbcError;
01849 
01850   // Find the baseline interval corresponding to specified time.
01851 
01852     BdbHandle(BdbIntervalR) theOldIntervalH;
01853 
01854     status = getBaselineInterval( theOldIntervalH, theContainerName, theTime );
01855     if (( BdbcSuccess != status ) || BdbIsNull(theOldIntervalH)) {
01856         ErrMsg(error) << errorString << endl
01857                       << "    Failed to locate a baseline interval corresponding to specified time: " << theTime << endl
01858                       << "        DETECTOR  -> " << subsystemTLA( ) << endl
01859                       << "        CONTSINRE -> " << theContainerName << endmsg;
01860         return BdbcError;
01861     }
01862 
01863   // Check if the split time is not equal to the borders of the interval.
01864   // If so then we just return OK.
01865 
01866     if (( theOldIntervalH->getBeginTime( ) == theTime ) ||
01867         ( theOldIntervalH->getEndTime( )   == theTime )) {
01868         return BdbcSuccess;
01869     }
01870 
01871   // Now we decide on a particular split method. Depending on the complexity
01872   // of intervals structure at the split point we have two options:
01873   //
01874   //    1. Split a baseline interval only (including the FIRST and LAST intervals).
01875   //       This is actually the most simple case.
01876   //    2. Split a whole vertical tree of intervals (this would exclude "by definition"
01877   //       both the FIRST and LAST intervals).
01878   //
01879   // NOTE: Although these two operations have something in common (splitting a baseline
01880   //       interval) we still do them separatevly in order to make algorithm more clear.
01881 
01882     if ( theOldIntervalH->exist_geneObj( )) {
01883 
01884         status = splitIntervalsTree( theContainerName,
01885                                      theOldIntervalH,
01886                                      theTime );
01887     } else {
01888 
01889         status = splitBaselineInterval( theOldIntervalH,
01890                                         theTime );
01891     }
01892 
01893   // Put a record into the History even if the result of splitting was
01894   // not successfull.
01895 
01896     historySplit( rcsid, theTime, 0 );
01897 
01898     return status;
01899 }
01900 
01901 BdbStatus
01902 BdbDatabase::findObject( BdbHandle(BdbObject)& theObjectH,
01903                          const char*           theContainerName,
01904                          const BdbTime&        theTime,
01905                          d_ULong               theTag )
01906 {
01907   // NOTE: This operation is deffered to the accessor object.
01908   //
01909   //       Hoever the cache will still be corrcetly updated.
01910 
01911     BdbStatus status;
01912 
01913     assert( 0 != theContainerName );
01914 
01915     COUT1 << "CONDFINDOBJECT: detector=" << subsystemTLA( ) << " container=" << theContainerName << " find_time=" << theTime << endl;
01916 
01917   // Ask accessor to locate specified interval.
01918 
01919     return _accessor->findObject( this,
01920                                   theObjectH,
01921                                   theContainerName,
01922                                   theTime );
01923 }
01924 
01925 BdbStatus 
01926 BdbDatabase::findInterval( BdbHandle(BdbInterval)& theBdbIntervalH,
01927                            const char*             theContainerName,
01928                            const BdbTime&          theTime,
01929                            d_ULong                 theTag ) 
01930 {
01931   // NOTE: This operation can either be ended up in this call (if
01932   //       the cache is OK) or be further deffered to the accessor object.
01933   //
01934   //       In the recent case the cache is updated by the result
01935   //       obtained from the accessor.
01936 
01937     BdbStatus status;
01938 
01939     assert( 0 != theContainerName );
01940 
01941     COUT1 << "CONDFINDINTERVAL: detector=" << subsystemTLA( ) << " container=" << theContainerName << " find_time=" << theTime << endl;
01942 
01943     theBdbIntervalH = 0;
01944 
01945   // Try I: Check if the current cache has what we want.
01946 
01947     if ( isValidCacheForContainer( theContainerName ) &&
01948          ( ! BdbIsNull(_intervalCacheH))              &&
01949          _intervalCacheH->inInterval( theTime )) {
01950 
01951       // Return cached interval
01952 
01953         theBdbIntervalH = _intervalCacheH;
01954 
01955         return BdbcSuccess;
01956     }
01957 
01958   // Try II: Ask accessor to locate specified interval.
01959 
01960     status = _accessor->findInterval( this,
01961                                       theBdbIntervalH,
01962                                       theContainerName,
01963                                       theTime );
01964     if ( BdbcSuccess == status ) {
01965         _intervalCacheH = theBdbIntervalH;      // Update the cached interval.
01966     }
01967 
01968     return status;
01969 }
01970 
01971 BdbStatus  
01972 BdbDatabase::firstInterval( BdbHandle(BdbInterval)& theIntervalH,
01973                             const char*             theContainerName )
01974 {
01975   // NOTE: This operation is deffered to the accessor object.
01976   //
01977   //       The internal cache is not considered as a source of the result
01978   //       at all. However it is updated by the result obtained from
01979   //       the accessor.
01980 
01981     BdbStatus status;
01982 
01983   // Ask accessor to locate specified interval.
01984 
01985     status = _accessor->firstInterval( this,
01986                                        theIntervalH,
01987                                        theContainerName );
01988     if ( BdbcSuccess == status ) {
01989         _intervalCacheH = theIntervalH;         // Update the cached interval.
01990     }
01991 
01992     return status;
01993 }
01994 
01995 BdbStatus 
01996 BdbDatabase::lastInterval( BdbHandle(BdbInterval)& theIntervalH,
01997                            const char*             theContainerName ) 
01998 {
01999   // NOTE: This operation is deffered to the accessor object.
02000   //
02001   //       The internal cache is not considered as a source of the result
02002   //       at all. However it is updated by the result obtained from
02003   //       the accessor.
02004 
02005     BdbStatus status;
02006 
02007   // Ask accessor to locate specified interval.
02008 
02009     status = _accessor->lastInterval( this,
02010                                       theIntervalH,
02011                                       theContainerName );
02012     if ( BdbcSuccess == status ) {
02013         _intervalCacheH = theIntervalH;         // Update the cached interval.
02014     }
02015 
02016     return status;
02017 }
02018 
02019 /*** In the old implementation of the algorithm there was
02020  *** the different semantics of the "version time" which ment
02021  *** the time when the interval was actually created (default constructor
02022  *** of BdbTime()).
02023  ***
02024  *** The new implementation is assuming that the "version time"
02025  *** is the property of the BdbObject(), or to be more precise,
02026  *** the time when the object was passed through ::store()
02027  *** interface.
02028  ***
02029  *** Therefore the new algorithm does not use the version time at all.
02030  *** This is less efficient, but it's compensated by a fact that
02031  *** this particular algorithm will be used less frequently then
02032  *** the "regular" revision-aware algorithm.
02033  ***/
02034 
02035 BdbStatus 
02036 BdbDatabase::findTopInterval( BdbHandle(BdbInterval)& theBdbIntervalH,
02037                               BdbItr(BdbInterval)&    theIntervalItr ) 
02038 {
02039     const char* errorString = "BdbDatabase::findTopInterval() -- ERROR.";
02040 
02041   // Return the topmost interval using genealogy links
02042   // between intervals in a vertical tree.
02043 
02044     theBdbIntervalH = NULL;
02045 
02046     while ( theIntervalItr.next( )) {
02047 
02048         if ( BdbIsNull(theBdbIntervalH)) {
02049             theBdbIntervalH = theIntervalItr;
02050         } else {
02051 
02052             int compareResult = verticalCompare( theIntervalItr, theBdbIntervalH );
02053 
02054             switch ( compareResult ) {
02055 
02056             case -1:
02057 
02058               // The next interval pointed out through the iterator
02059               // sits lower then the current one. So we just ignore it.
02060 
02061                 break;
02062 
02063             case 0:
02064 
02065               // The next interval pointed out through the iterator
02066               // is equal to the current one. So we just ignore it.
02067 
02068                 break;
02069 
02070             case 1:
02071 
02072               // Replace the current interval with the new one
02073 
02074                 theBdbIntervalH = theIntervalItr;
02075 
02076                 break;
02077 
02078             default:
02079 
02080                 ErrMsg(error) << errorString << endl
02081                               << "    The inconsistent contents of the interval container was found" << endl
02082                               << "        DETECTOR  -> " << subsystemTLA( ) << endl
02083                               << "        CONTAINER -> " << containerName( ) << endmsg;
02084                 return BdbcError;
02085 
02086             }
02087         }
02088     }
02089 
02090     _intervalCacheH = theBdbIntervalH;
02091 
02092     return BdbcSuccess;
02093 }
02094 
02095 BdbStatus
02096 BdbDatabase::findRevisedInterval( BdbHandle(BdbInterval)& theIntervalH,
02097                                   BdbItr(BdbInterval)&    theIntervalItr,
02098                                   d_ULong                 theRevisionId )
02099 {
02100     const char* errorString = "BdbDatabase::findRevisedInterval() -- error.";
02101 
02102   // This algorithm is not as efficient as it could be.
02103   // The first improvement could be to put a chain/stack of base revisions
02104   // for a specified revision into a cache.
02105 
02106     BdbStatus status = BdbcError;
02107     BdbHandle(BdbIntervalR)    theNextIntervalH;
02108     BdbHandle(BdbCondRevision) theRevisionH;
02109     vector<BdbHandle(BdbInterval)> intervals;
02110     vector<d_ULong>                intervals_revisions;
02111     vector<d_ULong>                revisions;
02112     d_ULong intervals_size;
02113     d_ULong revisions_size;
02114 
02115   // Build an array of non-revised intervals
02116 
02117     while ( theIntervalItr.next()) {
02118 
02119         theNextIntervalH = (BdbHandle(BdbIntervalR)&) theIntervalItr;
02120         theNextIntervalH->getRevision( theRevisionH );
02121 
02122         if ( ! BdbIsNull(theRevisionH)) {
02123             intervals.push_back( theIntervalItr );
02124             intervals_revisions.push_back( theRevisionH->id( ));
02125         }
02126     }
02127     intervals_size = intervals.size( );
02128     if ( 0 == intervals_size ) {
02129         ErrMsg(error) << errorString << endl
02130                       << "    Inconsistent contents of the interval container was detected." << endl
02131                       << "    Baseline interval probably does not exist." << endl
02132                       << "        DETECTOR  -> " << subsystemTLA( ) << endl
02133                       << "        CONTAINER -> " << containerName( ) << endmsg;
02134         return BdbcError;
02135     }
02136 
02137   // Obtain a stack of underlying revisions for a specific revision ID.
02138 
02139     status = getRevisionStack( revisions, theRevisionId );
02140     if ( BdbcSuccess != status ) {
02141         ErrMsg(error) << errorString << endl
02142                       << "    Failed to get a stack of revisions in the container." << endl
02143                       << "    The container may have incorrect internal structure." << endl
02144                       << "        DETECTOR  -> " << subsystemTLA( ) << endl
02145                       << "        CONTAINER -> " << containerName( ) << endmsg;
02146         return status;
02147     }
02148     revisions_size = revisions.size( );
02149     if ( 0 == revisions_size) {
02150         ErrMsg(error) << errorString << endl
02151                       << "    A stack of revisions is empty for a revision: " << theRevisionId << endl
02152                       << "    The container may have incorrect internal structure." << endl
02153                       << "        DETECTOR  -> " << subsystemTLA( ) << endl
02154                       << "        CONTAINER -> " << containerName( ) << endmsg;
02155         return BdbcError;
02156     }
02157 
02158   // Iterate through the lists of both intervals and revisions
02159   // and locate the "best" interval match for a specified revision.
02160   //
02161   //    NOTE:   We must be able to match at least baseline
02162   //            revision.
02163 
02164     for ( d_ULong i = 0; i < revisions_size; i++ ) {
02165         for ( d_ULong j = 0; j < intervals_size; j++ ) {
02166             if ( revisions[i] == intervals_revisions[j] ) {
02167                 theIntervalH = intervals[j];
02168                 return BdbcSuccess;
02169             }
02170         }
02171     }
02172 
02173     ErrMsg(error) << errorString << endl
02174                   << "    An interval matching revision: " << theRevisionId << " was not found in the containert." << endl
02175                   << "    The container may have incorrect internal structure." << endl
02176                   << "        DETECTOR  -> " << subsystemTLA( ) << endl
02177                   << "        CONTAINER -> " << containerName( ) << endmsg;
02178 
02179     return BdbcError;
02180 }
02181 
02182 BdbRefAny
02183 BdbDatabase::updatedHint( ) 
02184 {
02185   // Instantiate the clustering hint object at a very first call
02186   // for the hint. Then obtain the hint itself.
02187 
02188     if ( 0 == _myHint ) {
02189         _myHint = new BdbCondClusteringHint( *(BdbConditions::instance( )), subsystemTLA( ));
02190     }
02191     return _myHint->updatedHint( );
02192 }
02193 
02194 ////////////////////////
02195 // Revision interface //
02196 ////////////////////////
02197 
02198 // -----------------------------------------------------------------------
02199 // ***********************************************************************
02200 //
02201 // ::getUnassignedList()
02202 //
02203 //      DESCRIPTION:
02204 //
02205 //          This function returns a sorted list of intervals
02206 //          being in the stack for specified BdbTime or BdbIntervalBase.
02207 //          This functions provides a subset of ::getList() intervals
02208 //          which do not belong to any revision.
02209 //
02210 //          The intervals are sorted according to their version.
02211 //          The first interval has a lowest version.
02212 //
02213 //      PARAMETERS:
02214 //
02215 //          theList             a list of intervals to be returned.
02216 //
02217 //          theContainerName    no comments.
02218 //
02219 //          theTime             no comments.
02220 //
02221 //          theInterval         an alternative way to specify theTime.
02222 //                              The interval beginning time is used only.
02223 //
02224 //      RETURN:
02225 //
02226 //          BdbcSuccess     means success.
02227 //
02228 //          BdbcError       means any error.
02229 //
02230 // ***********************************************************************
02231 // -----------------------------------------------------------------------
02232 
02233 
02234 BdbStatus
02235 BdbDatabase::getUnassignedList( vector<BdbHandle(BdbInterval)>& theList,
02236                                 const char*                                  theContainerName,
02237                                 const BdbTime&                               theTime )
02238 {
02239     BdbStatus status = BdbcError;
02240 
02241     assert( 0 != theContainerName );
02242 
02243     vector<BdbHandle(BdbInterval)> theTmpList;
02244 
02245   // Get the complete sorted list.
02246 
02247     status = getList( theTmpList, theContainerName, theTime );
02248     if( BdbcSuccess != status ) return status;
02249 
02250   // Exclude intervals which already belong to any revision.
02251 
02252     BdbHandle(BdbIntervalR)    theIntervalH;
02253     BdbHandle(BdbCondRevision) theRevisionH;
02254 
02255     theList.clear( );
02256 
02257     int entries = theTmpList.size( );
02258 
02259     for( int i = 0; i < entries; i++ ) {
02260 
02261         theIntervalH = (BdbHandle(BdbIntervalR)&) theTmpList[i];
02262         theIntervalH->getRevision( theRevisionH );
02263 
02264         if( BdbIsNull(theRevisionH)) {
02265             theList.push_back( theIntervalH );
02266         }
02267     }
02268 
02269     return BdbcSuccess;
02270 } 
02271 
02272 // -----------------------------------------------------------------------
02273 // ***********************************************************************
02274 //
02275 // ::getList()
02276 //
02277 //      DESCRIPTION:
02278 //
02279 //          This function returns a sorted list of all intervals
02280 //          being in the stack for specified BdbTime or BdbIntervalBase.
02281 //
02282 //          The intervals are sorted according to their version.
02283 //          The first interval should have the lowest version,
02284 //          corresponding to the BASELINE revision.
02285 //
02286 //      PARAMETERS:
02287 //
02288 //          theList             a list of intervals to be returned.
02289 //
02290 //          theContainerName    no comments.
02291 //
02292 //          theTime             no comments.
02293 //
02294 //          theInterval         an alternative way to specify theTime.
02295 //                              The interval beginning time is used only.
02296 //
02297 //      RETURN:
02298 //
02299 //          BdbcSuccess     means success.
02300 //
02301 //          BdbcError       means any error.
02302 //
02303 // ***********************************************************************
02304 // -----------------------------------------------------------------------
02305 
02306 
02307 BdbStatus
02308 BdbDatabase::getList( vector<BdbHandle(BdbInterval)>& theList,
02309                       const char*                                  theContainerName,
02310                       const BdbTime&                               theTime )
02311 {
02312     const char* errorString = "BdbDatabase::getList() -- ERROR.";
02313 
02314     BdbStatus status;
02315 
02316     assert( 0 != theContainerName );
02317 
02318   // Reset the previous contents of the list (if any)
02319 
02320     theList.clear( );
02321 
02322   // Find specified container. Reload cache if nessesary.
02323 
02324     BdbHandle(BdbContObj) intervalContainerH;
02325 
02326     status = findIntervalCont( intervalContainerH, theContainerName );
02327     if (( BdbcSuccess != status ) || BdbIsNull(intervalContainerH)) {
02328         ErrMsg(error) << errorString << endl
02329                       << "    Failed to locate specified interval container." << endl
02330                       << "        DETECTOR  -> " << subsystemTLA( ) << endl
02331                       << "        CONTAINER -> " << theContainerName << endmsg;
02332         return status;
02333     }
02334 
02335   // check the first interval
02336 
02337     BdbHandle(BdbInterval) theFirstIntervalH;
02338 
02339     status = firstInterval( theFirstIntervalH, theContainerName );
02340     if ( BdbcSuccess != status ) return status;
02341     if ( theFirstIntervalH->inInterval( theTime )) {
02342         theList.push_back( theFirstIntervalH );
02343         return BdbcSuccess;
02344     }
02345 
02346   // check the last interval
02347 
02348     BdbHandle(BdbInterval) theLastIntervalH;
02349 
02350     status = lastInterval( theLastIntervalH, theContainerName );
02351 
02352     if ( BdbcSuccess != status ) return status;
02353     if ( theLastIntervalH->inInterval( theTime )) {
02354         theList.push_back( theLastIntervalH );
02355         return BdbcSuccess;
02356     }
02357 
02358   // look up the interval
02359 
02360     d_ULong gmtTheTime = theTime.getGmtSec( );
02361 
02362     ooLookupKey lookupKey( ooTypeN(BdbInterval), 2 );
02363               
02364     ooLessThanEqualLookupField lessThanEqual( ooTypeN(BdbInterval),
02365                                               "_beginTime._gmtSec",
02366                                               & gmtTheTime );
02367     lookupKey.addField( lessThanEqual );
02368 
02369     ooGreaterThanLookupField greaterThan( ooTypeN(BdbInterval),
02370                                           "_endTime._gmtSec",
02371                                           & gmtTheTime );
02372     lookupKey.addField( greaterThan );
02373 
02374     BdbItr(BdbInterval) BdbIntervalItr;
02375     BdbIntervalItr.scan( intervalContainerH, lookupKey, BdbcRead );
02376 
02377   // Copy all found intervals into the array.
02378   //
02379   //   NOTE: The order of intervals in the array is upredictable.
02380   //         They do not nessesarily go in a chronological order.
02381 
02382     while ( BdbIntervalItr.next( )) {
02383         theList.push_back( BdbIntervalItr );
02384     }
02385 
02386   // Sort intervals in the list in order to make a BASELINE interval
02387   // to go first, and an interval with the highest version -- last.
02388 
02389     status = sortIntervalsList( theList );
02390     if( BdbcSuccess != status ) return status;
02391 
02392     return BdbcSuccess;
02393 }
02394 
02395 // -----------------------------------------------------------------------
02396 // ***********************************************************************
02397 //
02398 // ::getUnassignedList()
02399 //
02400 //      DESCRIPTION:
02401 //
02402 //          This function returns a list of unassigned intervals
02403 //          being withing specified borders of validity and versioning
02404 //          time limits.
02405 //
02406 //          The intervals to be returned in the list are to be completelly
02407 //          within the specified validity range.
02408 //
02409 //          The intervals are guaranteed not to be in the same stack
02410 //          of a same version tree. If so happens then a special conflict
02411 //          resolving parameter is used.
02412 //
02413 //          Two strategies are now supperted:
02414 //
02415 //              RECENT      provides the most recent (in version time)
02416 //                          interval will go into the output list.
02417 //
02418 //              EARLIEST    the most earliest (in version time)
02419 //                          interval will go into the output list.
02420 //
02421 //      PARAMETERS:
02422 //
02423 //          theOutputList           a list of intervals to be returned.
02424 //
02425 //          theContainerName        no comments.
02426 //
02427 //          theBeginValidityTime    no comments.
02428 //
02429 //          theEndValidityTime      no comments.
02430 //
02431 //          theBeginVersionTime     no comments.
02432 //
02433 //          theEndVersionTime       no comments (not including this time)
02434 //
02435 //          theValidityInterval     an alternative way to specify
02436 //                                  the validity interval limits.
02437 //
02438 //          theVersionInterval      an alternative way to specify
02439 //                                  the version interval limits.
02440 //
02441 //          theStrategy             this is a conflict resolution parameter.
02442 //                                  It's used when two or more intervals
02443 //                                  being within the same version tree
02444 //                                  are met.
02445 //
02446 //      RETURN:
02447 //
02448 //          BdbcSuccess     means success.
02449 //
02450 //          BdbcError       means any error.
02451 //
02452 // ***********************************************************************
02453 // -----------------------------------------------------------------------
02454 
02455 BdbStatus
02456 BdbDatabase::getUnassignedList( vector<BdbHandle(BdbInterval)>& theOutputList,
02457                                 const char*                                  theContainerName,
02458                                 const BdbTime&                               theBeginValidityTime,
02459                                 const BdbTime&                               theEndValidityTime,
02460                                 const BdbTime&                               theBeginVersionTime,
02461                                 const BdbTime&                               theEndVersionTime,
02462                                 const SelectionStrategyType                  theStrategy )
02463 {
02464     const char* errorString = "BdbDatabase::getUnassignedList() -- ERROR.";
02465 
02466     BdbStatus status;
02467 
02468     assert( 0 != theContainerName );
02469     assert( theBeginValidityTime < theEndValidityTime );
02470     assert( theBeginVersionTime  < theEndVersionTime );
02471 
02472   // Reset the previous contents of the list (if any)
02473 
02474     theOutputList.clear( );
02475 
02476   // Find specified container. Reload cache if nessesary.
02477 
02478     BdbHandle(BdbContObj) intervalContainerH;
02479 
02480     status = findIntervalCont( intervalContainerH, theContainerName );
02481     if (( BdbcSuccess != status ) || BdbIsNull(intervalContainerH)) {
02482         ErrMsg(error) << errorString << endl
02483                       << "    Failed to locate specified interval container." << endl
02484                       << "        DETECTOR  -> " << subsystemTLA( ) << endl
02485                       << "        CONTAINER -> " << theContainerName << endmsg;
02486         return status;
02487     }
02488 
02489   // Get the baseline intervals for the begin and end validity times.
02490   //
02491   // NOTE: If the end time is "+Infinity" then we set the last baseline
02492   //       interval to null value. This will be used later to determine
02493   //       the end of the loop condition.
02494 
02495     BdbHandle(BdbIntervalR) theBeginBaselineH;
02496 
02497     status = getBaselineInterval( theBeginBaselineH,
02498                                   theContainerName,
02499                                   theBeginValidityTime );
02500     if ( BdbcSuccess != status ) {
02501         ErrMsg(error) << errorString << endl
02502                       << "    Failed to locate baseline interval for: " << theBeginValidityTime << endl
02503                       << "        DETECTOR  -> " << subsystemTLA( ) << endl
02504                       << "        CONTAINER -> " << theContainerName << endmsg;
02505         return status;
02506     }
02507 
02508     BdbHandle(BdbIntervalR) theEndBaselineH;
02509 
02510     if( BdbTime::plusInfinity == theEndValidityTime ) {
02511         theEndBaselineH = 0;
02512     } else {
02513         status = getBaselineInterval( theEndBaselineH,
02514                                       theContainerName,
02515                                       theEndValidityTime );
02516         if ( BdbcSuccess != status ) {
02517             ErrMsg(error) << errorString << endl
02518                           << "    Failed to locate baseline interval for: " << theEndValidityTime << endl
02519                           << "        DETECTOR  -> " << subsystemTLA( ) << endl
02520                           << "        CONTAINER -> " << theContainerName << endmsg;
02521             return status;
02522         }
02523     }
02524 
02525   // Get a baseline interval which is "next" to the end baseline interval.
02526   // This interval will be used as a delimiter in the gorizontal search.
02527   //
02528   // NOTE: we just set this value to null value if the previous search for
02529   //       the last baseline interval gave us null value.
02530 
02531     BdbHandle(BdbIntervalR) theEndBaselineNextH;
02532 
02533     if( BdbIsNull(theEndBaselineH)) {
02534         theEndBaselineNextH = 0;
02535     } else {
02536         theEndBaselineH->getBaselineNext( theEndBaselineNextH );
02537     }
02538 
02539   // Traverse the baseline intervals horizontally from the begin baseline
02540   // interval to the end baseline interval and locate all the unassigned
02541   // intervals within specified range of the version time.
02542 
02543     vector<BdbHandle(BdbInterval)> theList;
02544     vector<BdbHandle(BdbInterval)> theTmpList;
02545 
02546     int numTmpBranches;
02547 
02548     BdbHandle(BdbIntervalR) theBaselineNextH;
02549     BdbHandle(BdbIntervalR) theBaselineH;
02550     BdbHandle(BdbIntervalR) theIntervalH;
02551 
02552     theBaselineH = theBeginBaselineH;
02553 
02554     do {
02555 
02556       // Get a versioning tree of unassigned intervals
02557       // growing from the current baseline interval.
02558 
02559         status = getUnassignedTree( theTmpList,
02560                                     numTmpBranches,
02561                                     theContainerName,
02562                                     theBaselineH->getBeginTime( ));
02563         if ( BdbcSuccess != status ) {
02564             ErrMsg(error) << errorString << endl
02565                           << "    Failed to get a tree of intervals for: " << theBaselineH->getBeginTime( ) << endl
02566                           << "        DETECTOR  -> " << subsystemTLA( ) << endl
02567                           << "        CONTAINER -> " << theContainerName << endmsg;
02568             return status;
02569         }
02570 
02571       // Process the tree. Just skip this step over
02572       // if the tree was empty.
02573 
02574         int firstElement  = theList.size( );
02575         int numTmpEntries = theTmpList.size( );
02576 
02577         for ( int i = 0; i < numTmpEntries; i++ ) {
02578 
02579           // Check for the a branch delimiter (NULL handle).
02580 
02581             if ( BdbIsNull(theTmpList[i])) {
02582                 continue;
02583             }
02584 
02585           // Check if the interval is completelly withing the required
02586           // validity limits.
02587 
02588             if ( ! ((( theBeginValidityTime <= theTmpList[i]->getBeginTime( )) &&
02589                      ( theEndValidityTime   >= theTmpList[i]->getEndTime( ))))) {
02590                 continue;
02591             }
02592 
02593           // Check if the interval is completelly withing the required
02594           // validity limits.
02595 
02596             if ( ! ((( theBeginVersionTime <= theTmpList[i]->getVersionTime( )) &&
02597                      ( theEndVersionTime   >  theTmpList[i]->getVersionTime( ))))) {
02598                 continue;
02599             }
02600 
02601           // Check a list of already existing intervals if there is one
02602           // which is in the same vertical stack. Then leave an interval
02603           // which complies to the specified selection policy.
02604           // Replacing elements are substituted by a NULL handle.
02605           // Later these handles will be removed from the list.
02606 
02607 
02608             bool overlappingWasNotDetected = true;
02609             bool appendOverlappedInterval  = false;
02610 
02611             int numEntries = theList.size( );
02612 
02613             for ( int j = firstElement; j < numEntries; j++ ) {
02614 
02615               // Just ignore any NULL handles which could appear here
02616               // from the previous checking.
02617 
02618                 if ( BdbIsNull(theList[j])) {
02619                     continue;
02620                 }
02621 
02622               // Ignore input interval if it's already in the output list.
02623 
02624                 if( theTmpList[i] == theList[j] ) {
02625                     continue;
02626                 }
02627 
02628               // Check if the intervals are on the vertical stack.
02629 
02630                 if ( theTmpList[i]->inInterval( *(theList[j])) ||
02631                      theList[j]->inInterval( *(theTmpList[i]))) {
02632 
02633                   // Well. Now we have two overlapping intervals. We have to leave
02634                   // just one of them.
02635 
02636                     overlappingWasNotDetected = false;
02637 
02638                   // The method is generally defined by the specified strategy
02639                   // and is based on the value of the version time.
02640                   //
02641                   // In case If both of them have the same version time
02642                   // the ambiguity is being resolved in the following way: an interval
02643                   // which is on the top or on the bottom (depending on the required strategy)
02644                   // will be chosen.
02645                   //
02646                   //    NOTE:   The checking method is sligtly optimized.
02647                   //            First it tries to use the validity borders.
02648                   //            And later if the ambiguity is still unresolved
02649                   //            (because the itervals have the same validity width)
02650                   //            then the genealogy information is involved into
02651                   //            the process.
02652 
02653                     switch ( theStrategy ) {
02654 
02655                     case EARLIEST:
02656 
02657                         if ( theTmpList[i]->getVersionTime() < theList[j]->getVersionTime( )) {
02658 
02659                           // Existing element is more recent.
02660 
02661                             theList[j] = NULL;
02662                             appendOverlappedInterval = true;
02663 
02664                         } else if( theTmpList[i]->getVersionTime() == theList[j]->getVersionTime( )) {
02665 
02666                           // Ambiguity.
02667 
02668                             if ( theTmpList[i]->inInterval( *(theList[j]))) {
02669 
02670                                 if ( theList[j]->inInterval( *(theTmpList[i]))) {
02671 
02672                                   // The worst case of ambiguity -- we have two
02673                                   // intervals with the same version time and the width.
02674                                   // The only way to resolve this would be to use
02675                                   // genealogy information.
02676 
02677                                     int comparisonResult = verticalCompare( theList[j], theTmpList[i] );
02678 
02679                                     switch ( comparisonResult ) {
02680 
02681                                     case 1:
02682 
02683                                         theList[j] = NULL;
02684                                         appendOverlappedInterval = true;
02685 
02686                                         break;
02687 
02688                                     case -1:
02689 
02690                                         break;
02691 
02692                                     default:
02693 
02694                                         ErrMsg(error) << errorString << endl
02695                                                       << "    Unexpected internal error #1." << endl
02696                                                       << "        DETECTOR  -> " << subsystemTLA( ) << endl
02697                                                       << "        CONTAINER -> " << theContainerName << endmsg;
02698                                         return BdbcError;
02699                                     }
02700 
02701                                 } else {
02702 
02703                                   // Existing interval is more narrow in width then the new one.
02704 
02705                                     theList[j] = NULL;
02706                                     appendOverlappedInterval = true;
02707 
02708                                 }
02709                             }
02710                         }
02711 
02712                         break;
02713 
02714                     case RECENT:
02715 
02716                         if ( theTmpList[i]->getVersionTime() > theList[j]->getVersionTime( )) {
02717 
02718                           // Existing element is earlier.
02719 
02720                             theList[j] = NULL;
02721                             appendOverlappedInterval = true;
02722 
02723                         } else if( theTmpList[i]->getVersionTime() == theList[j]->getVersionTime( )) {
02724 
02725                           // Ambiguity.
02726 
02727                             if ( theList[j]->inInterval( *(theTmpList[i]))) {
02728 
02729                                 if ( theTmpList[i]->inInterval( *(theList[j]))) {
02730 
02731                                   // The worst case of ambiguity -- we have two
02732                                   // intervals with the same version time and the width.
02733                                   // The only way to resolve this would be to use
02734                                   // genealogy information.
02735 
02736                                     int comparisonResult = verticalCompare( theList[j], theTmpList[i] );
02737 
02738                                     switch ( comparisonResult ) {
02739 
02740                                     case 1:
02741 
02742                                         break;
02743 
02744                                     case -1:
02745 
02746                                         theList[j] = NULL;
02747                                         appendOverlappedInterval = true;
02748 
02749                                         break;
02750 
02751                                     default:
02752 
02753                                         ErrMsg(error) << errorString << endl
02754                                                       << "    Unexpected internal error #2." << endl
02755                                                       << "        DETECTOR  -> " << subsystemTLA( ) << endl
02756                                                       << "        CONTAINER -> " << theContainerName << endmsg;
02757                                         return BdbcError;
02758                                     }
02759 
02760                                 } else {
02761 
02762                                   // Existing interval is more narrow in width then the new one.
02763 
02764                                     theList[j] = NULL;
02765                                     appendOverlappedInterval = true;
02766 
02767                                 }
02768                             }
02769                         }
02770 
02771                         break;
02772                     }
02773                 }
02774             }
02775 
02776           // Check if found that we need to append the new interval by
02777           // the end of the output list.
02778 
02779             if ( overlappingWasNotDetected || appendOverlappedInterval ) {
02780                 theList.push_back( theTmpList[i] );
02781             }
02782         }
02783 
02784       // Advance the current baseline handle to the next
02785       // baseline interval.
02786 
02787         theBaselineH->getBaselineNext( theBaselineNextH );
02788         theBaselineH = theBaselineNextH;
02789 
02790       // Repeat if the previously processed interval was not the "lastInterval"
02791       // and if we've not reached the "wall" (an interval which is out of current
02792       // validity scope).
02793 
02794     } while (( ! BdbIsNull(theBaselineH)) && ( theBaselineH != theEndBaselineNextH ));
02795 
02796   // Copy non-NULL handles from the temporary list into
02797   // the output one.
02798 
02799     int entries = theList.size( );
02800 
02801     for ( int i = 0; i < entries; i++ ) {
02802         if ( ! BdbIsNull(theList[i])) {
02803             theOutputList.push_back( theList[i] );
02804         }
02805     }
02806 
02807     return BdbcSuccess;
02808 }
02809 
02810 // -----------------------------------------------------------------------
02811 // ***********************************************************************
02812 //
02813 // ::getRevisionList()
02814 //
02815 //      DESCRIPTION:
02816 //
02817 //          This function returns a sequential list of all intervals
02818 //          covering the specified revision withing specified time limits.
02819 //
02820 //          The list includes intervals which cover the revision
02821 //          either directly or indirectly (through a concept
02822 //          of "base" revision).
02823 //
02824 //          If the container does not contain any revision information
02825 //          (so called "old" persistent schema) then the "topmost"
02826 //          intervals are only included into the list.
02827 //
02828 //          The limits are included into the list.
02829 //          If the limits are not specified -- the list starts from
02830 //          the "FirstInterval" and ends up with the "LastInterval".
02831 //
02832 //      PARAMETERS:
02833 //
02834 //          theList             a list of intervals to be returned.
02835 //
02836 //          theContainerName    no comments.
02837 //
02838 //          theBeginTime        no comments
02839 //
02840 //          theEndTime          no comments
02841 //
02842 //          theInterval         an alternative way to specify theTime.
02843 //                              The interval beginning time is used only.
02844 //
02845 //          theRevisionId       no comments.
02846 //
02847 //      RETURN:
02848 //
02849 //          BdbcSuccess     means success.
02850 //
02851 //          BdbcError       means any error.
02852 //
02853 // ***********************************************************************
02854 // -----------------------------------------------------------------------
02855 
02856 
02857 BdbStatus
02858 BdbDatabase::getRevisionList( vector<BdbHandle(BdbInterval)>& theList,
02859                               const char*                                  theContainerName,
02860                               const BdbTime&                               theBeginTime,
02861                               const BdbTime&                               theEndTime,
02862                               d_ULong                                      theRevisionId )
02863 {
02864     const char* errorString = "BdbDatabase::getRevisionList() -- ERROR.";
02865 
02866     BdbStatus status;
02867 
02868   // Currently this procedure is implemented for the baseline
02869   // revision only
02870 
02871     assert( BdbCondRevision::BASELINE == theRevisionId );
02872     assert( 0 != theContainerName );
02873 
02874   // Reset the previous contents of the list (if any)
02875 
02876     theList.clear( );
02877 
02878   // Find specified container. Reload cache if nessesary.
02879 
02880     BdbHandle(BdbContObj) intervalContH;
02881 
02882     status = findIntervalCont( intervalContH, theContainerName );
02883     if (( BdbcSuccess != status ) || BdbIsNull(intervalContH)) {
02884         ErrMsg(error) << errorString << endl
02885                       << "    Failed to locate specified interval container." << endl
02886                       << "        DETECTOR  -> " << subsystemTLA( ) << endl
02887                       << "        CONTAINER -> " << theContainerName << endmsg;
02888         return status;
02889     }
02890 
02891   // check the first interval in the list
02892 
02893     BdbHandle(BdbInterval) theFirstIntervalH;
02894 
02895     if ( theBeginTime == BdbTime::minusInfinity ) {
02896 
02897         status = firstInterval( theFirstIntervalH,
02898                                 theContainerName );
02899 
02900     } else {
02901 
02902         status = getBaselineInterval( theFirstIntervalH,
02903                                       theContainerName,
02904                                       theBeginTime );
02905     }
02906 
02907     if (( BdbcSuccess != status ) || BdbIsNull(theFirstIntervalH)) {
02908         ErrMsg(error) << errorString << endl
02909                       << "    Failed to locate an interval corresponding to beginTime = " << theBeginTime << endl
02910                       << "        DETECTOR  -> " << subsystemTLA( ) << endl
02911                       << "        CONTAINER -> " << theContainerName << endmsg;
02912         return BdbcError;
02913     }
02914 
02915   // check the last interval in the list
02916 
02917     BdbHandle(BdbInterval) theLastIntervalH;
02918 
02919     if ( theEndTime == BdbTime::plusInfinity ) {
02920 
02921         status = lastInterval( theLastIntervalH,
02922                                theContainerName );
02923 
02924     } else {
02925 
02926         status = getBaselineInterval( theLastIntervalH,
02927                                       theContainerName,
02928                                       theEndTime );
02929     }
02930 
02931     if ( ( BdbcSuccess != status ) || BdbIsNull(theLastIntervalH)) {
02932         ErrMsg(error) << errorString << endl
02933                       << "    Failed to locate an interval corresponding to beginTime = " << theEndTime << endl
02934                       << "        DETECTOR  -> " << subsystemTLA( ) << endl
02935                       << "        CONTAINER -> " << theContainerName << endmsg;
02936         return BdbcError;
02937     }
02938 
02939   // Go through baseline list from the FirstInterval
02940   // until the LastInterval.
02941 
02942     theList.push_back( theFirstIntervalH );
02943 
02944     BdbHandle(BdbIntervalR) theIntervalH;
02945     BdbHandle(BdbIntervalR) theNextIntervalH;
02946 
02947     ((BdbHandle(BdbIntervalR)&) theFirstIntervalH)->getBaselineNext( theNextIntervalH );
02948 
02949     while ( theNextIntervalH != theLastIntervalH ) {
02950 
02951         theList.push_back( theNextIntervalH );
02952 
02953         ((BdbHandle(BdbIntervalR)&) theNextIntervalH)->getBaselineNext( theIntervalH );
02954 
02955         if ( BdbIsNull(theIntervalH)) {
02956             ErrMsg(error) << errorString << endl
02957                           << "    Unexpected end of linked list of intervals was met." << endl
02958                           << "        DETECTOR  -> " << subsystemTLA( ) << endl
02959                           << "        CONTAINER -> " << theContainerName << endmsg;
02960             return BdbcError;
02961         }
02962         theNextIntervalH = theIntervalH;
02963     }
02964 
02965     theList.push_back( theLastIntervalH );
02966 
02967     return BdbcSuccess;
02968 }
02969 
02970 // -----------------------------------------------------------------------
02971 // ***********************************************************************
02972 //
02973 // ::getTree()
02974 //
02975 //      DESCRIPTION:
02976 //
02977 //          This function returns a list of all intervals
02978 //          being in the vertical version tree for specified BdbTime
02979 //          or BdbIntervalBase.
02980 //
02981 //          The version tree is presented as a sequnce of sub-list
02982 //          separated by NULL persistent handle (positivly checked
02983 //          with BdbIsNull() macro.
02984 //
02985 //          Each sub-list in the tree is a unique vertical stack
02986 //          or a branch of intervals going from the BASELINE interval
02987 //          up to the end node in the end node in the branch.
02988 //
02989 //
02990 //          The sub-lists go in the following order: they always start from
02991 //          left-side intervals (the begin time of the baseline interval)
02992 //          and end at the right-side intervals (the end time of the baseline
02993 //          interval).
02994 //
02995 //      NOTE:
02996 //
02997 //          The algorithm implemented in this function makes use
02998 //          a stack based, recursive algorithm to locate all posible paths
02999 //          in the tree.
03000 //
03001 //      PARAMETERS:
03002 //
03003 //          theList             a list of intervals to be returned.
03004 //
03005 //          theContainerName    no comments.
03006 //
03007 //          theTime             no comments.
03008 //
03009 //          theInterval         an alternative way to specify theTime.
03010 //                              The interval beginning time is used only.
03011 //
03012 //      RETURN:
03013 //
03014 //          BdbcSuccess     means success.
03015 //
03016 //          BdbcError       means any error.
03017 //
03018 // ***********************************************************************
03019 // -----------------------------------------------------------------------
03020 
03021 BdbStatus
03022 BdbDatabase::getTree( vector<BdbHandle(BdbInterval)>& theList,
03023                       int&                                         numBranches,
03024                       const char*                                  theContainerName,
03025                       const BdbTime&                               theTime )
03026 {
03027     BdbStatus status;
03028 
03029     assert( 0 != theContainerName );
03030 
03031   // Locate a baseline interval to begin with.
03032 
03033     BdbHandle(BdbInterval) theBaselineIntervalH;
03034 
03035     status = getBaselineInterval( theBaselineIntervalH,
03036                                   theContainerName,
03037                                   theTime );
03038     if ( BdbcSuccess != status ) return status;
03039 
03040   // The following vector is used as a current stack.
03041   // The stack is built by traversing the version tree.
03042   // Each time the last node in the tree is reached -- the complete stack
03043   // contents is copied into ouput vector.
03044 
03045     vector<BdbHandle(BdbInterval)> theStack;
03046 
03047   // Start traversing the vertical pathes gough "through" the baseline
03048   // intervals to the end nodes.
03049   // Put a baseline interval into the stack.
03050 
03051     theList.clear( );
03052     numBranches = 0;
03053 
03054     theStack.push_back( theBaselineIntervalH );
03055 
03056     nextTreeNode( theList,
03057                   theStack,
03058                   numBranches );
03059 
03060     return BdbcSuccess;
03061 }
03062 
03063 void
03064 BdbDatabase::nextTreeNode( vector<BdbHandle(BdbInterval)>& theList,
03065                            vector<BdbHandle(BdbInterval)>& theStack,
03066                            int&                                         numBranches )
03067 {
03068     BdbItr(BdbPersObj)     theIntervalItr;
03069     BdbHandle(BdbInterval) theIntervalH;
03070     BdbHandle(BdbInterval) theNextIntervalH;
03071 
03072     int numElements = theStack.size( );
03073 
03074   // Locate the current element == the last element in the stack.
03075 
03076     theIntervalH = theStack[numElements-1];
03077     theIntervalH->nextVers( theIntervalItr );
03078 
03079     int numSubBranches = 0;
03080 
03081     while ( theIntervalItr.next( )) {
03082 
03083         theNextIntervalH = (BdbHandle(BdbInterval)&) theIntervalItr;
03084         theStack.push_back( theNextIntervalH );
03085 
03086         nextTreeNode( theList,
03087                       theStack,
03088                       numBranches );
03089 
03090         //Why do we need the & here????? ryd
03091         theStack.erase( &theNextIntervalH );
03092         
03093         numSubBranches++;
03094     }
03095 
03096   // If there were no any "next" intervals -- the current node was
03097   // was the last one.
03098   // Therefore -- we copy the whole stack contents into output vector.
03099   // If this is not the first branch in the tree -- insert a NULL
03100   // handle at the beginning.
03101 
03102     if ( ! numSubBranches ) {
03103 
03104         if ( numBranches ) {
03105             theList.push_back( NULL );
03106         }
03107 
03108         for ( int i = 0; i < numElements; i++ ) {
03109             theList.push_back( theStack[i] );
03110         }
03111 
03112         numBranches++;
03113     }
03114 
03115     return;
03116 }
03117 
03118 // -----------------------------------------------------------------------
03119 // ***********************************************************************
03120 //
03121 // ::getUnassignedTree()
03122 //
03123 //      DESCRIPTION:
03124 //
03125 //          This function does the same as :getTree() function does
03126 //          except that all returned intervals are to be unassigned.
03127 //
03128 //          All the "empty" btanches are reduced.
03129 //          So that the actual number of branches returned corresponds
03130 //          to the non-empty branches.
03131 //
03132 //      PARAMETERS:
03133 //
03134 //          theList             a list of intervals to be returned.
03135 //
03136 //          theContainerName    no comments.
03137 //
03138 //          theTime             no comments.
03139 //
03140 //          theInterval         an alternative way to specify theTime.
03141 //                              The interval beginning time is used only.
03142 //
03143 //      RETURN:
03144 //
03145 //          BdbcSuccess     means success.
03146 //
03147 //          BdbcError       means any error.
03148 //
03149 // ***********************************************************************
03150 // -----------------------------------------------------------------------
03151 
03152 BdbStatus
03153 BdbDatabase::getUnassignedTree( vector<BdbHandle(BdbInterval)>& theList,
03154                                 int&                                         numBranches,
03155                                 const char*                                  theContainerName,
03156                                 const BdbTime&                               theTime )
03157 {
03158     BdbStatus status;
03159 
03160     assert( 0 != theContainerName );
03161 
03162   // First we get an original tree into a temporary vector.
03163 
03164     vector<BdbHandle(BdbInterval)> theTmpList;
03165     int numTmpBranches;
03166 
03167     status = getTree( theTmpList,
03168                       numTmpBranches,
03169                       theContainerName,
03170                       theTime );
03171     if ( BdbcSuccess != status ) {
03172         return status;
03173     }
03174 
03175   // Reduce the tree by detecting and copying just unassigned elements
03176   // into the output list.
03177 
03178     BdbHandle(BdbCondRevision) theRevisionH;
03179 
03180     theList.clear( );
03181     numBranches = 0;
03182 
03183     int numCollected = 0;
03184     int numEntries = theTmpList.size( );
03185 
03186     for ( int i = 0; i < numEntries; i++ ) {
03187 
03188         if ( ! BdbIsNull(theTmpList[i])) {
03189 
03190             ((BdbHandle(BdbIntervalR)&) theTmpList[i])->getRevision( theRevisionH );
03191 
03192             if ( BdbIsNull(theRevisionH)) {
03193 
03194               // Well. This is what we are hunting for.
03195 
03196                 theList.push_back( theTmpList[i] );
03197 
03198                 if ( 0 == numCollected ) {
03199                     ++numBranches;
03200                 }
03201                 ++numCollected;
03202             }
03203 
03204         } else {
03205 
03206           // Append a NULL object by the end of each completed branch
03207           // even if this is the last (or only) branch in the reduced tree.
03208           // Later we will eliminate this object if needed.
03209 
03210             if ( 0 != numCollected ) {
03211                 numCollected = 0;
03212                 theList.push_back( NULL );
03213             }
03214         }
03215     }
03216 
03217   // Eliminate the last NULL object in output list if any.
03218 
03219     numEntries = theList.size( );
03220 
03221     if (( numEntries > 0 ) && ( BdbIsNull(theList[numEntries-1]))) {
03222       //why do we need the & here??? ryd
03223         theList.erase( &theList.back() );
03224     }
03225 
03226     return BdbcSuccess;
03227 }
03228 
03229 // -----------------------------------------------------------------------
03230 // ***********************************************************************
03231 //
03232 // ::getBaselineInterval()
03233 //
03234 //      DESCRIPTION:
03235 //
03236 //          This function locates a bottom-most (baseline) interval
03237 //          for specified BdbTime or BdbIntervalBase.
03238 //
03239 //      PARAMETERS:
03240 //
03241 //          theIntervalH        no comments.
03242 //
03243 //          theContainerName    no comments.
03244 //
03245 //          theTime             no comments.
03246 //
03247 //      RETURN:
03248 //
03249 //          BdbcSuccess     means success.
03250 //
03251 //          BdbcError       means any error.
03252 //
03253 // ***********************************************************************
03254 // -----------------------------------------------------------------------
03255 
03256 
03257 BdbStatus
03258 BdbDatabase::getBaselineInterval( BdbHandle(BdbInterval)& theIntervalH,
03259                                   const char*             theContainerName,
03260                                   const BdbTime&          theTime )
03261 {
03262     const char* errorString = "BdbDatabase::getBaselineInterval() -- ERROR.";
03263 
03264     BdbStatus status;
03265 
03266     assert( 0 != theContainerName );
03267 
03268     theIntervalH = 0;
03269 
03270   // Trivial optimization: check the FIRST or the LAST intervals.
03271   // This optimization will also properly initialize internal cache.
03272 
03273     status = firstInterval( theIntervalH, theContainerName );
03274     if ( BdbcSuccess != status )              return status;
03275     if ( theIntervalH->inInterval( theTime )) return BdbcSuccess;
03276 
03277     status = lastInterval( theIntervalH, theContainerName );
03278     if ( BdbcSuccess != status )              return status;
03279     if ( theIntervalH->inInterval( theTime )) return BdbcSuccess;
03280 
03281   // Get a sorted stack of intervals for a specified time.
03282 
03283     vector<BdbHandle(BdbInterval)> theList;
03284 
03285     status = getList( theList,
03286                       theContainerName,
03287                       theTime );
03288     if ( BdbcSuccess != status ) return status;
03289 
03290   // Check the contents of the returned list.
03291   // The first element of the list must be a baseline one.
03292 
03293     if ( 0 == theList.size( )) {
03294         ErrMsg(error) << errorString << endl
03295                       << "    There is no intervals for specified BdbTime:" << theTime << endl
03296                       << "    The container is probably corrupted." << endl
03297                       << "        DETECTOR  -> " << subsystemTLA( ) << endl
03298                       << "        CONTAINER -> " << theContainerName << endmsg;
03299         return BdbcError;
03300     }
03301     theIntervalH = theList[0];
03302 
03303     BdbHandle(BdbCondRevision) theRevisionH;
03304     ((BdbHandle(BdbIntervalR)&) theIntervalH)->getRevision( theRevisionH );
03305 
03306     if ( BdbIsNull(theRevisionH)) {
03307         ErrMsg(error) << errorString << endl
03308                       << "    Failed to obtain a revision for a baseline interval." << endl
03309                       << "    The container is probably corrupted." << endl
03310                       << "        DETECTOR  -> " << subsystemTLA( ) << endl
03311                       << "        CONTAINER -> " << theContainerName << endmsg;
03312         return BdbcError;
03313     }
03314 
03315     if ( BdbCondRevision::BASELINE != theRevisionH->id( )) {
03316         ErrMsg(error) << errorString << endl
03317                       << "    The topmost element of the version stack" << endl
03318                       << "    has wrong revision ID: " << theRevisionH->id( ) << endl
03319                       << "    The container is probably corrupted." << endl
03320                       << "        DETECTOR  -> " << subsystemTLA( ) << endl
03321                       << "        CONTAINER -> " << theContainerName << endmsg;
03322         return BdbcError;
03323     }
03324 
03325     return BdbcSuccess;
03326 }
03327 
03328 // -----------------------------------------------------------------------
03329 // ***********************************************************************
03330 //
03331 // ::getTopmostInterval()
03332 //
03333 //      DESCRIPTION:
03334 //
03335 //          This function locates a topmost interval
03336 //          for specified BdbTime or BdbIntervalBase.
03337 //
03338 //      PARAMETERS:
03339 //
03340 //          theIntervalH        no comments.
03341 //
03342 //          theContainerName    no comments.
03343 //
03344 //          theTime             no comments.
03345 //
03346 //      RETURN:
03347 //
03348 //          BdbcSuccess     means success.
03349 //
03350 //          BdbcError       means any error.
03351 //
03352 // ***********************************************************************
03353 // -----------------------------------------------------------------------
03354 
03355 BdbStatus
03356 BdbDatabase::getTopmostInterval( BdbHandle(BdbInterval)& theIntervalH,
03357                                  const char*             theContainerName,
03358                                  const BdbTime&          theTime )
03359 {
03360     const char* errorString = "BdbDatabase::getTopmostInterval() -- ERROR.";
03361 
03362     BdbStatus status;
03363 
03364     assert( 0 != theContainerName );
03365 
03366     theIntervalH = 0;
03367 
03368   // Trivial optimization: check the FIRST or the LAST intervals.
03369   // This optimization will also properly initialize internal cache.
03370 
03371     status = firstInterval( theIntervalH, theContainerName );
03372     if ( BdbcSuccess != status )              return status;
03373     if ( theIntervalH->inInterval( theTime )) return BdbcSuccess;
03374 
03375     status = lastInterval( theIntervalH, theContainerName );
03376     if ( BdbcSuccess != status )              return status;
03377     if ( theIntervalH->inInterval( theTime )) return BdbcSuccess;
03378 
03379   // Get a handle to the interval container
03380 
03381     BdbHandle(BdbContObj) intervalContainerH;
03382     getIntervalContH( intervalContainerH );
03383 
03384   // Initialize the iterator for a vertical stack of intervals.
03385 
03386     d_ULong gmtTheTime = theTime.getGmtSec( );
03387 
03388     ooLookupKey lookupKey( ooTypeN(BdbInterval), 2 );
03389               
03390     ooLessThanEqualLookupField lessThanEqual( ooTypeN(BdbInterval),
03391                                               "_beginTime._gmtSec",
03392                                               & gmtTheTime );
03393     lookupKey.addField( lessThanEqual );
03394 
03395     ooGreaterThanLookupField greaterThan( ooTypeN(BdbInterval),
03396                                           "_endTime._gmtSec",
03397                                           & gmtTheTime );
03398     lookupKey.addField( greaterThan );
03399 
03400     BdbItr(BdbInterval) theIntervalItr;
03401     theIntervalItr.scan( intervalContainerH, lookupKey, BdbcRead );
03402 
03403   // Ignore any revision informationand locate the TOPMOST interval
03404   // in the stack.
03405 
03406     return findTopInterval( theIntervalH,
03407                             theIntervalItr );
03408 }
03409 
03410 // -----------------------------------------------------------------------
03411 // ***********************************************************************
03412 //
03413 // ::getRevisedInterval()
03414 //
03415 //      DESCRIPTION:
03416 //
03417 //          This function locates an interval
03418 //          for specified BdbTime and revision ID.
03419 //
03420 //          If there is not an interval with specified revision ID
03421 //          in a vertical stack then an interval with direct or indirect
03422 //          base revision ID is taken.
03423 //
03424 //      PARAMETERS:
03425 //
03426 //          theIntervalH        no comments.
03427 //
03428 //          theContainerName    no comments.
03429 //
03430 //          theTime             no comments.
03431 //
03432 //          theRevisionId       no comments.
03433 //
03434 //      RETURN:
03435 //
03436 //          BdbcSuccess     means success.
03437 //
03438 //          BdbcError       means any error.
03439 //
03440 // ***********************************************************************
03441 // -----------------------------------------------------------------------
03442 
03443 BdbStatus
03444 BdbDatabase::getRevisedInterval( BdbHandle(BdbInterval)& theIntervalH,
03445                                  const char*             theContainerName,
03446                                  const BdbTime&          theTime,
03447                                  d_ULong                 theRevisionId )
03448 {
03449     const char* errorString = "BdbDatabase::getRevisedInterval() -- ERROR.";
03450 
03451     BdbStatus status;
03452 
03453     assert( 0 != theContainerName );
03454 
03455     theIntervalH = 0;
03456 
03457   // A small optimization for BASELINE revision.
03458 
03459     if( BdbCondRevision::BASELINE == theRevisionId ) {
03460 
03461         return getBaselineInterval( theIntervalH,
03462                                     theContainerName,
03463                                     theTime );
03464     }
03465 
03466   // The following operation are executed within an exception-like loop.
03467 
03468     bool theLoopFailed = true;
03469 
03470     while ( true ) {
03471 
03472       // get a handle to the interval container
03473 
03474         BdbHandle(BdbContObj) intervalContH;
03475 
03476         status = findIntervalCont( intervalContH, theContainerName );
03477         if (( BdbcSuccess != status ) || BdbIsNull(intervalContH)) {
03478             ErrMsg(error) << errorString << endl
03479                           << "    Failed to locate the interval container." << endl
03480                           << "        DETECTOR  -> " << subsystemTLA( ) << endl
03481                           << "        CONTAINER -> " << theContainerName << endmsg;
03482             return BdbcError;
03483         }
03484 
03485       // Trivial optimization for the FIRST and the LAST intervals. It will also
03486       // initialize the internal cache.
03487 
03488         status = firstInterval( theIntervalH, theContainerName );
03489         if ( BdbcSuccess != status )              return status;
03490         if ( theIntervalH->inInterval( theTime )) return BdbcSuccess;
03491 
03492         status = lastInterval( theIntervalH, theContainerName );
03493         if ( BdbcSuccess != status )              return status;
03494         if ( theIntervalH->inInterval( theTime )) return BdbcSuccess;
03495 
03496       // Get the cached registry.
03497 
03498         BdbHandle(BdbCondRegistry) registryH;
03499         getRegistryH( registryH );
03500 
03501       // Get a stack of revisions for specified revision (including
03502       // this revision itself.
03503 
03504         vector<d_ULong> theRevisionStack;
03505 
03506         BdbHandle(BdbCondRevision) theRevisionH;
03507         BdbHandle(BdbCondRevision) theBaseRevisionH;
03508 
03509         registryH->getRevision( theRevisionH, theRevisionId );
03510         if ( BdbIsNull( theRevisionH )) {
03511             ErrMsg(error) << errorString << endl
03512                           << "    Specified revision does not exist." << endmsg;
03513             break;
03514         }
03515 
03516         do {
03517             theRevisionStack.push_back( theRevisionH->id( ));
03518             theRevisionH->getBaseRevision( theBaseRevisionH );
03519             theRevisionH = theBaseRevisionH;
03520         } while ( ! BdbIsNull( theRevisionH ));
03521 
03522       // Check the contents of the revision stack. It must contain
03523       // at list 2 elements (the revision itself and the BASELINE revision's ID.
03524       // The first element of the stack must be the revision itself.
03525       // The last element in the stack must be the BASELINE revision.
03526 
03527         int entriesInRevisionStack = theRevisionStack.size( );
03528 
03529         if (( entriesInRevisionStack < 2 ) ||
03530             ( theRevisionId != theRevisionStack[0] ) ||
03531             ( BdbCondRevision::BASELINE != theRevisionStack[entriesInRevisionStack-1] )) {
03532             ErrMsg(error) << errorString << endl
03533                           << "    The wrong base revision for a specified revision." << endl
03534                           << "    The interval contaioner may have incorrect internal structure." << endmsg;
03535             break;
03536         }
03537 
03538       // Get a vertical stack of intervals for a specified time.
03539       //
03540       // NOTE: We assume that the list is sorted, and the first
03541       //       interval in the list is a BASELINE one.
03542 
03543         vector<BdbHandle(BdbInterval)> theList;
03544 
03545         status = getList( theList, theContainerName, theTime );
03546         if (( BdbcSuccess != status ) || ( 0 == theList.size( ))) {
03547             ErrMsg(error) << errorString << endl
03548                           << "    Failed to get vertical stack of intervals for BdbTime = " << theTime << endmsg;
03549             break;
03550         }
03551 
03552         int entriesInIntervalsList = theList.size( );
03553 
03554       // Locate the best candidate in the list starting from the beginning
03555       // of the revisions stack. The first element in this stack should be
03556       // the revision passed as a parameter to this procedure, the last element
03557       // should be BASELINE revision.
03558       //
03559       // NOTE: The "best" candidate is defined as an interval which is either directly
03560       //       connected to the specified revision or has the biggest revision ID
03561       //       in between this revision ID and BASELINE revision ID (=0).
03562 
03563         theIntervalH = NULL;
03564 
03565         for ( int i = 0; i < entriesInRevisionStack; i++ ) {
03566 
03567             for ( int j = (entriesInIntervalsList-1); j >= 0; j-- ) {
03568 
03569                 ((BdbHandle(BdbIntervalR)&) theList[j])->getRevision( theRevisionH );
03570 
03571                 if ( ! BdbIsNull( theRevisionH )) {
03572 
03573                     if ( theRevisionH->id( ) == theRevisionStack[i] ) {
03574                         theIntervalH = theList[j];
03575                         break;
03576                     }
03577                 }
03578             }
03579             if ( ! BdbIsNull(theIntervalH)) break;
03580         }
03581 
03582         if ( BdbIsNull(theIntervalH)) {
03583             ErrMsg(error) << errorString << endl
03584                           << "    No match has been found between a stack of intervals and a stack of revisions." << endl
03585                           << "    The interval container may have inconsistent or corrupted structure." << endmsg;
03586             break;
03587         }
03588 
03589         theLoopFailed = false;
03590         break;
03591     }
03592     if ( theLoopFailed ) {
03593 
03594         ErrMsg(error) << "        DETECTOR  -> " << subsystemTLA( ) << endl
03595                       << "        CONTAINER -> " << theContainerName << endl
03596                       << "            REVISION ID -> " << theRevisionId << endmsg;
03597 
03598         return BdbcError;
03599     }
03600 
03601     return BdbcSuccess;
03602 }
03603 
03604 // -----------------------------------------------------------------------
03605 // ***********************************************************************
03606 //
03607 // ::createRevision()
03608 // ::updateRevision()
03609 //
03610 //      DESCRIPTION:
03611 //
03612 //          These functions take a list of the specified intervals
03613 //          and put them into a specified (by ID) revision.
03614 //
03615 //          The difference between them is that ::createRevision()
03616 //          allocates a new revision ID each time it's called.
03617 //
03618 //          The intervals from the input list are checked to satisfy
03619 //          several requirements.
03620 //
03621 //          When all of the requirements are met -- then, and only then,
03622 //          a new revision is being allocated and created or updated
03623 //          dpending on which method was called.
03624 //
03625 //          The ::createRevision() returns a created revision ID.
03626 //
03627 //          This algorithm checks if specified interval is or is already
03628 //          a member of an existing revision:
03629 //
03630 //              - if it's the same revision as specified one -- then there
03631 //                nothing to do with this interval.
03632 //              - if the interval belongs to another revision -- then a copy
03633 //                revision -- then nothing to do.
03634 //
03635 //      PARAMETERS:
03636 //
03637 //          theList             a list of intervals to be included into
03638 //                              specified revision.
03639 //                              The order of entries in the list does
03640 //                              not play any role.
03641 //
03642 //          theContainerName    no comments.
03643 //
03644 //          theRevisionId       a revision ID to use or return. The meaning
03645 //                              and the direction of this parameter depends
03646 //                              on which specific method is called.
03647 //
03648 //          theBaseRevisionId   a base revision ID which is used when
03649 //                              a specified above revision is created.
03650 //                              Is ignored if the revision already exist.
03651 //
03652 //          theSite             an optional argument specifying a site
03653 //                              where the revision is originated.
03654 //                              Is ignored if the revision already exist.
03655 //
03656 //          theDescription      an optional argument dscribing specified
03657 //                              revision.
03658 //                              Is ignored if the revision already exist.
03659 //
03660 //      RETURN:
03661 //
03662 //          BdbcSuccess     means success.
03663 //
03664 //          BdbcError       means any error.
03665 //
03666 // ***********************************************************************
03667 // -----------------------------------------------------------------------
03668 
03669 BdbStatus
03670 BdbDatabase::createRevision( vector<BdbHandle(BdbInterval)>& theList,
03671                              const char*                                  theContainerName,
03672                              d_ULong&                                     theRevisionId,
03673                              d_ULong                                      theBaseRevisionId,
03674                              const char*                                  theSite,
03675                              const char*                                  theDescr )
03676 {
03677     const char* errorString = "BdbDatabase::createRevision() -- ERROR.";
03678 
03679     BdbStatus status;
03680 
03681     assert ( 0 != theContainerName );
03682 
03683   // Ensure the proper context to be set.
03684 
03685     if ( ! verifyIndexMode( ))               return BdbcError;
03686     if ( ! setAuthLevel( theContainerName )) return BdbcError;
03687 
03688   // Perform the following operation in the exception-like loop.
03689 
03690     bool theLoopFailed = true;
03691 
03692     while ( true ) {
03693 
03694       // Allocate the new revision ID.
03695       // This would also initialize the internal cache.
03696 
03697         theRevisionId = getNextAvailableRevisionId( theContainerName );
03698         if ( BdbCondRevision::ILLEGAL == theRevisionId ) {
03699             ErrMsg(error) << errorString << endl
03700                           << "    Failed to allocate a new revision ID" << endmsg;
03701             break;
03702         }
03703 
03704       // Get the cached registry.
03705 
03706         BdbHandle(BdbCondRegistry) registryH;
03707         getRegistryH( registryH );
03708 
03709       // The revision should not exist.
03710 
03711         BdbHandle(BdbCondRevision) theRevisionH;
03712         registryH->getRevision( theRevisionH, theRevisionId );
03713         if( ! BdbIsNull( theRevisionH )) {
03714             ErrMsg(error) << errorString << endl
03715                           << "    Specified revision ID = " << theRevisionId << " already exist." << endmsg;
03716             break;
03717         }
03718 
03719       // The base revision should already exist.
03720 
03721         BdbHandle(BdbCondRevision) theBaseRevisionH;
03722         registryH->getRevision( theBaseRevisionH, theBaseRevisionId );
03723         if( BdbIsNull( theBaseRevisionH )) {
03724             ErrMsg(error) << errorString << endl
03725                           << "    Specified base revision ID = " << theBaseRevisionId << " does not exist." << endmsg;
03726             break;
03727         }
03728 
03729       // Verify the list of intervals.
03730 
03731         status = verifyIntervals( theList, theContainerName, theRevisionId );
03732         if ( BdbcSuccess != status ) {
03733             ErrMsg(error) << errorString << endl
03734                           << "    Failed to verify the quality of passed intervals." << endmsg;
03735             break;
03736         }
03737 
03738       // Get the cached container handle.
03739 
03740         BdbHandle(BdbContObj) intervalContH;
03741         getIntervalContH( intervalContH );
03742 
03743       // Create a revision.
03744       // Set a base revision for it.
03745       // Add new revision to the registry.
03746 
03747         const char* theCreationSite = theSite;
03748         if( theCreationSite == (char*) 0 ) {
03749             theCreationSite = getenv( "BFSITE" );
03750             if( theCreationSite == (char*) 0 ) {
03751                 theCreationSite = "unknown";
03752             }
03753         }
03754 
03755         theRevisionH = new( intervalContH ) BdbCondRevision( theRevisionId,
03756                                                              BdbTime( ),
03757                                                              theCreationSite,
03758                                                              theDescr );
03759         status = theRevisionH->setBaseRevision( theBaseRevisionH );
03760         if( BdbcSuccess != status ) {
03761             ErrMsg(error) << errorString << endl
03762                           << "    Failed to set a base revision for a newly created revision." << endmsg;
03763             break;
03764         }
03765 
03766         registryH->addRevision( theRevisionH );
03767 
03768       // Put a record into the History.
03769 
03770         historyRCreate( rcsid,
03771                         theList,
03772                         theBaseRevisionId,
03773                         theRevisionId,
03774                         theCreationSite,
03775                         theDescr );
03776 
03777       // Include the intervals into revision.
03778 
03779         includeIntoRevision( theList, theRevisionH );
03780 
03781         theLoopFailed = false;
03782         break;
03783     }
03784     if ( theLoopFailed ) {
03785 
03786         ErrMsg(error) << "        DETECTOR  -> " << subsystemTLA( ) << endl
03787                       << "        CONTAINER -> " << theContainerName << endmsg;
03788         return BdbcError;
03789     }
03790 
03791     return BdbcSuccess;
03792 }
03793 
03794 BdbStatus
03795 BdbDatabase::updateRevision( vector<BdbHandle(BdbInterval)>& theList,
03796                              const char*                                  theContainerName,
03797                              d_ULong                                      theRevisionId )
03798 {
03799     const char* errorString = "BdbDatabase::updateRevision() -- ERROR.";
03800 
03801     BdbStatus status;
03802 
03803     assert ( 0 != theContainerName );
03804     assert ( theRevisionId > BdbCondRevision::BASELINE );
03805 
03806   // Ensure the proper context to be set.
03807 
03808     if ( ! verifyIndexMode( ))               return BdbcError;
03809     if ( ! setAuthLevel( theContainerName )) return BdbcError;
03810 
03811   // Perform the following operation in the exception-like loop.
03812 
03813     bool theLoopFailed = true;
03814 
03815     while ( true ) {
03816 
03817       // Verify the list of intervals.
03818       // This will also initialize the cache.
03819 
03820         status = verifyIntervals( theList, theContainerName, theRevisionId );
03821         if ( BdbcSuccess != status ) {
03822             ErrMsg(error) << errorString << endl
03823                           << "    Failed to verify the quality of passed intervals." << endmsg;
03824             break;
03825         }
03826 
03827       // Get the cached registry.
03828 
03829         BdbHandle(BdbCondRegistry) registryH;
03830         getRegistryH( registryH );
03831 
03832       // The revision should already exist.
03833 
03834         BdbHandle(BdbCondRevision) theRevisionH;
03835 
03836         registryH->getRevision( theRevisionH, theRevisionId );
03837         if( BdbIsNull( theRevisionH )) {
03838             ErrMsg(error) << errorString << endl
03839                           << "    Specified revision ID = " << theRevisionId << " does not exist." << endmsg;
03840             break;
03841         }
03842 
03843       // Put a record into the History.
03844 
03845         historyRUpdate( rcsid,
03846                         theList,
03847                         theRevisionId );
03848 
03849       // Include the intervals into revision.
03850 
03851         includeIntoRevision( theList, theRevisionH );
03852 
03853         theLoopFailed = false;
03854         break;
03855     }
03856     if ( theLoopFailed ) {
03857 
03858         ErrMsg(error) << "        DETECTOR  -> " << subsystemTLA( ) << endl
03859                       << "        CONTAINER -> " << theContainerName << endmsg;
03860         return BdbcError;
03861     }
03862 
03863     return BdbcSuccess;
03864 }
03865 
03866 // -----------------------------------------------------------------------
03867 // ***********************************************************************
03868 //
03869 // ::deleteRevision()
03870 //
03871 //      DESCRIPTION:
03872 //
03873 //          These function deletes the specified (by ID) revision from
03874 //          a container.
03875 //
03876 //          The revision can be deleted when all of the followinig
03877 //          requrements are met:
03878 //
03879 //              - a user poseses a group privelege to write into containers
03880 //                of a detector where the specified containers belongs to;
03881 //
03882 //              - it's not the BASELINE revision (ID = 0);
03883 //
03884 //              - the specified revision does not have dependent (or "child")
03885 //                revisions using it as their base.
03886 //
03887 //          When the operation is finished then the revision description object
03888 //          is removed from the interval container and all the directly
03889 //          connected intervals become "unassigned" ones (i.e. being disconnected
03890 //          from any particular revision).
03891 //
03892 //          No record is placed into the History of the container.
03893 //
03894 //      PARAMETERS:
03895 //
03896 //          theContainerName    no comments.
03897 //
03898 //          theRevisionId       a revision ID.
03899 //
03900 //      RETURN:
03901 //
03902 //          BdbcSuccess     means success.
03903 //
03904 //          BdbcError       means any error.
03905 //
03906 // ***********************************************************************
03907 // -----------------------------------------------------------------------
03908 
03909 BdbStatus
03910 BdbDatabase::deleteRevision( const char* theContainerName,
03911                              d_ULong&    theRevisionId )
03912 {
03913     const char* errorString = "BdbDatabase::deleteRevision() -- ERROR.";
03914 
03915     BdbStatus status;
03916 
03917     assert ( 0 != theContainerName );
03918 
03919   // Ensure the proper context to be set.
03920 
03921     if ( ! verifyIndexMode( ))               return BdbcError;
03922     if ( ! setAuthLevel( theContainerName )) return BdbcError;
03923 
03924   // Perform the following operation in the exception-like loop.
03925 
03926     bool theLoopFailed = true;
03927 
03928     while ( true ) {
03929 
03930       // The BASELINE revision can't be deleted in this way.
03931 
03932         if( BdbCondRevision::BASELINE == theRevisionId ) {
03933             ErrMsg(error) << errorString << endl
03934                           << "    An attempt to delete the BASELINE revision has been detected." << endl
03935                           << "    This revision can never be deleted." << endmsg;
03936             break;
03937         }
03938 
03939       // Locate the registry for specified revision
03940 
03941         BdbHandle(BdbCondRegistry) theRegistryH;
03942 
03943         status = findRegistry( theRegistryH, theContainerName );
03944         if(( BdbcSuccess != status ) || BdbIsNull(theRegistryH)) {
03945              ErrMsg(error) << errorString << endl
03946                           << "    Failed to locate Registry n the container." << endmsg;
03947             break;
03948         }
03949 
03950       // The revision should exist.
03951 
03952         BdbHandle(BdbCondRevision) theRevisionH;
03953 
03954         theRegistryH->getRevision( theRevisionH, theRevisionId );
03955         if( BdbIsNull(theRevisionH)) {
03956             ErrMsg(error) << errorString << endl
03957                           << "    Specified revision does not exist." << endmsg;
03958             break;
03959         }
03960 
03961       // The revision should not have any dependent revisions using it as
03962       // their base revision.
03963 
03964         BdbItr(BdbCondRevision) theItr;
03965 
03966         theRevisionH->setDependentItr( theItr );
03967         while( theItr.next( )) {
03968             ErrMsg(error) << errorString << endl
03969                           << "    The revision can't be deleted since it's being used as base revision" << endl
03970                           << "    by other revisions. Removing this revision would make the internal" << endl
03971                           << "    structure of the container inconsistent." << endmsg;
03972             break;
03973         }
03974 
03975       // Put a record into the History.
03976 
03977         historyRDelete( rcsid,
03978                         theRevisionId );
03979 
03980       // Delete revision object.
03981 
03982         BdbDelete(theRevisionH);
03983 
03984         theLoopFailed = false;
03985         break;
03986     }
03987     if ( theLoopFailed ) {
03988 
03989         ErrMsg(error) << "        DETECTOR    -> " << subsystemTLA( )  << endl
03990                       << "        CONTAINER   -> " << theContainerName << endl
03991                       << "        REVISION ID -> " << theRevisionId    <<endmsg;
03992         return BdbcError;
03993     }
03994 
03995     return BdbcSuccess;
03996 }
03997 
03998 d_ULong
03999 BdbDatabase::getMostRecentRevisionId( const char* theContainerName )
04000 {
04001     d_ULong result = BdbCondRevision::ILLEGAL;
04002 
04003     const char* errorString = "BdbDatabase::getMostRecentRevisionId() -- ERROR.";
04004 
04005     BdbStatus status;
04006 
04007     assert ( 0 != theContainerName );
04008 
04009   // Continue the sequence of operations within a exception-like loop.
04010 
04011     bool theLoopFailed = true;
04012 
04013     while( true ) {
04014 
04015       // Find Registry
04016 
04017         BdbHandle(BdbCondRegistry) theRegistry;
04018         status = findRegistry( theRegistry, theContainerName );
04019         if ( BdbcSuccess != status ) {
04020             ErrMsg(error) << errorString << endl
04021                           << "    Failed to locate Registry in this container." << endmsg;
04022             break;
04023         }
04024 
04025       // Iterate through the list of revisions and locate the one with
04026       // biggest number.
04027       // Later we will increment this number by one and return to a caller.
04028 
04029         BdbItr(BdbCondRevision) theItr;
04030         theRegistry->setRevisionItr( theItr );
04031 
04032         result = BdbCondRevision::BASELINE;
04033 
04034         while ( theItr.next( )) {
04035 
04036             int id = theItr->id( );
04037             if( id > result ) {
04038                 result = id;
04039             }
04040         }
04041 
04042         theLoopFailed = false;
04043         break;
04044     }
04045     if ( theLoopFailed ) {
04046 
04047         ErrMsg(error) << "        DETECTOR  -> " << subsystemTLA( ) << endl
04048                       << "        CONTAINER -> " << theContainerName << endmsg;
04049         return BdbCondRevision::ILLEGAL;
04050 
04051     }
04052 
04053     return result;
04054 }
04055 
04056 d_ULong
04057 BdbDatabase::getNextAvailableRevisionId( const char* theContainerName )
04058 {
04059     d_ULong result;
04060 
04061     const char* errorString = "BdbDatabase::getNextAvailableRevisionId() -- ERROR.";
04062 
04063     assert ( 0 != theContainerName );
04064 
04065     result = getMostRecentRevisionId( theContainerName );
04066     if( BdbCondRevision::ILLEGAL == result ) {
04067         ErrMsg(error) << errorString << endl
04068                       << "    Failed to get the most recent revision ID." << endl
04069                       << "        DETECTOR  -> " << subsystemTLA( ) << endl
04070                       << "        CONTAINER -> " << theContainerName << endmsg;
04071         return result;
04072     } else {
04073         result++;
04074     }
04075 
04076     return result;
04077 }
04078 
04079 bool
04080 BdbDatabase::setAuthLevel( const char* theContainerName )
04081 {
04082     BdbStatus status;
04083 
04084   // Check if the previous context is going to change.
04085 
04086     if( ! isValidCacheForContainer( theContainerName )) {
04087         _authLevelIsSet = false;
04088     }
04089 
04090   // Switch the Authorization context.
04091 
04092     if( ! _authLevelIsSet ) {
04093 
04094       // First of all we are trying to check if the Authorization system
04095       // would allow us to write into a detector area of specified
04096       // interval container (which may be different from the one used
04097       // during database opening if the USER AREA is used from specified
04098       // interval conatiner).
04099 
04100         if ( ! verifyAuthLevelOnly( theContainerName )) return false;
04101 
04102       // Check if current container is WRITE-locked. The base class
04103       // should have this information.
04104 
04105         if ( isWriteLocked( theContainerName )) {
04106             ErrMsg(error) << "BdbDatabase::setAuthLevel() -- ERROR." << endl
04107                           << "    The container is WRITE-locked for current federation." << endl
04108                           << "        DETECTOR  -> " << subsystemTLA( ) << endl
04109                           << "        CONTAINER -> " << theContainerName << endmsg;
04110             return false;
04111         }
04112 
04113         _authLevelIsSet = true;
04114     }
04115 
04116     return true;
04117 }
04118 
04119 bool
04120 BdbDatabase::verifyAuthLevelOnly( const char* theContainerName )
04121 {
04122     BdbStatus status;
04123 
04124   // Check with the Authorization system if this detector is available
04125   // for modifications to current user.
04126   //
04127   // NOTE: We are using a translated detector name because, depending on
04128   //       the contents of the REVISION PATH, this particular container
04129   //       may be located in the USER AREA, which is in different detector.
04130 
04131     string theCorrectedSubsystemName = correctedSubsystemName( theContainerName );
04132 
04133     BdbConditions* theApp = BdbConditions::instance( );
04134     status = theApp->setAuthLevel( BdbDomain::Group,
04135                                    theCorrectedSubsystemName.c_str() );
04136     if( BdbcSuccess != status ) {
04137         ErrMsg(error) << "BdbDatabase::verifyAuthLevelOnly() -- ERROR." << endl
04138                       << "    Failed to set the Authorization level." << endl
04139                       << "        DETECTOR  -> " << subsystemTLA( ) << endl
04140                       << "        CONTAINER -> " << theContainerName << endmsg;
04141         return false;
04142     }
04143 
04144     return true;
04145 }
04146 
04147 bool
04148 BdbDatabase::verifyIndexMode( )
04149 {    
04150     if( oocSensitive != BdbApplicationOrDomain::activeInstance( )->indexMode( )) {
04151         ErrMsg(error) << "BdbDatabase::verifyIndexMode() -- error." << endl
04152                       << "    Wrong transaction mode was detected." << endl
04153                       << "    This will prevent the correct versioning of the BdbInterval objects." << endl
04154                       << "    Please, check if the following environment variable: OO_INDEX_MODE" << endl
04155                       << "    is set to 1 before to run your application." << endmsg;
04156         return false;
04157     }
04158 
04159     return true;
04160 }
04161 
04162 /*** The old algorithm has been replaced due to changed semantics
04163  *** of the "version time". Now this time is bound to the time,
04164  *** when BdbObject passed through the ::store() interface,
04165  *** rather then a version of an interval is created.
04166  ***
04167  *** Here is the modified algorithm using the genealogy
04168  *** information in order to locate the tompost interval.
04169  ***/
04170 
04171 BdbStatus 
04172 BdbDatabase::findInterval( BdbHandle(BdbIntervalR)& theBdbIntervalH,
04173                            const BdbTime&           theTime,
04174                            d_ULong                  theTag )
04175 {
04176   // Get the cached container handle.
04177 
04178     BdbHandle(BdbContObj) intervalContH;
04179     getIntervalContH( intervalContH );
04180 
04181   // Setup the vertical iterator.
04182 
04183     d_ULong gmtTheTime = theTime.getGmtSec( );
04184 
04185     ooLookupKey lookupKey( ooTypeN(BdbInterval), 2 );
04186 
04187     ooLessThanEqualLookupField lessThanEqual( ooTypeN(BdbInterval),
04188                                               "_beginTime._gmtSec",
04189                                               & gmtTheTime );
04190     lookupKey.addField( lessThanEqual );
04191     
04192     ooGreaterThanLookupField greaterThan( ooTypeN(BdbInterval),
04193                                           "_endTime._gmtSec",
04194                                           & gmtTheTime );
04195     lookupKey.addField( greaterThan );
04196 
04197     BdbItr(BdbInterval) BdbIntervalItr;
04198     BdbIntervalItr.scan( intervalContH, lookupKey, BdbcRead );
04199 
04200   // return the topmost interval using genealogy information
04201 
04202     return findTopInterval( theBdbIntervalH,
04203                             BdbIntervalItr );
04204 }
04205 
04206 BdbStatus
04207 BdbDatabase::versionVector( const BdbHandle(BdbObject)& theNewObjectH,
04208                             const BdbTime&              theBeginVectorTime,
04209                             const BdbTime&              theEndVectorTime,
04210                             const BdbTime&              theVersionTime,
04211                             d_ULong                     theTag )
04212 {
04213     const char* errorString = "BdbDatabase::versionVector() -- ERROR.";
04214 
04215     BdbStatus status;
04216 
04217   // Build a vector of two elements only.
04218 
04219     vector<BdbCondStoreTime> theVector;
04220 
04221     theVector.push_back( BdbCondStoreTime( theBeginVectorTime, theNewObjectH ));
04222     theVector.push_back( BdbCondStoreTime( theEndVectorTime,   0 ));
04223 
04224     std::sort(theVector.begin(),theVector.end());
04225 
04226   // Fetch an interval where the first time falls into.
04227   //
04228   //    NOTE: If this is the first interval and if this interval has zero
04229   //          length [-oo,-oo) then just skip this interval and proceed to
04230   //          the next one.
04231 
04232     BdbHandle(BdbIntervalR) theIntervalH;
04233     findInterval( theIntervalH, theBeginVectorTime, 0 );
04234     if( BdbIsNull(theIntervalH)) {
04235         ErrMsg(error) << errorString << endl
04236                       << "    Failed to find a TOPMOST interval matching specified validity time." << endl
04237                       << "        DETECTOR  -> " << subsystemTLA( ) << endl
04238                       << "        CONTAINER -> " << containerName( ) << endl
04239                       << "        TIME      -> " << theBeginVectorTime << endmsg;
04240         return BdbcError;
04241     }
04242     if(( BdbTime::minusInfinity == theIntervalH->getBeginTime( )) &&
04243        ( BdbTime::minusInfinity == theIntervalH->getEndTime( ))) {
04244 
04245         theIntervalH->getTopNext( theIntervalH );
04246     }
04247 
04248   // Get the handle for the FIRST & LAST intervals. We will use these handles to verify
04249   // if a special processing is needed.
04250 
04251     BdbHandle(BdbContObj) theIntervalContH;
04252     getIntervalContH( theIntervalContH );
04253 
04254     BdbHandle(BdbIntervalR) theFirstIntervalH;
04255     theFirstIntervalH.lookupObj( theIntervalContH, "FirstInterval", BdbcUpdate );
04256     if( BdbIsNull(theFirstIntervalH)) {
04257         ErrMsg(error) << errorString << endl
04258                       << "    Failed to locate the FIRST interval." << endl
04259                       << "    The container may be inproperly created and/or initialized." << endl
04260                       << "        DETECTOR  -> " << subsystemTLA( ) << endl
04261                       << "        CONTAINER -> " << containerName( ) << endmsg;
04262         return BdbcError;
04263     }
04264 
04265     BdbHandle(BdbIntervalR) theLastIntervalH;
04266     theLastIntervalH.lookupObj( theIntervalContH, "LastInterval", BdbcUpdate );
04267     if( BdbIsNull(theLastIntervalH)) {
04268         ErrMsg(error) << errorString << endl
04269                       << "    Failed to locate the LAST interval." << endl
04270                       << "    The container may be inproperly created and/or initialized." << endl
04271                       << "        DETECTOR  -> " << subsystemTLA( ) << endl
04272                       << "        CONTAINER -> " << containerName( ) << endmsg;
04273         return BdbcError;
04274     }
04275 
04276   // Translate the input vector of times into a vector of intervals. The intervals
04277   // will be continious in the validity time.
04278   // The resulting intervals will be aligned to the borders of existing intervals.
04279   //
04280   //    NOTE: The value of the starting interval handle could be modifyied
04281   //          by this recursive algorithm.
04282   //
04283   //    NOTE: The handles of both FIRST and LAST intervals may be used by
04284   //          the building algorithm.
04285 
04286     vector<BdbCondStoreInterval> theIntervalVector;
04287 
04288     status = buildTopStoreVector( theVector,
04289                                   theFirstIntervalH,
04290                                   theLastIntervalH,
04291                                   theIntervalH,
04292                                   theIntervalVector );
04293     if( BdbcSuccess != status ) {
04294         return status;
04295     }
04296 
04297   // Process the resulting intervals vector, by taking each interval description from
04298   // there one-by-one and applying these intrervals to the existing structure.
04299   // NOTE: This algoeithm assumes that we are processing
04300 
04301     BdbHandle(BdbIntervalR) theOldIntervalH;
04302     BdbHandle(BdbObject)    theObjectH;
04303 
04304     BdbIntervalBase theIntervalBase;
04305 
04306     BdbTime theBeginTime;
04307     BdbTime theEndTime;
04308 
04309     int entries = theIntervalVector.size( );
04310     for( int i = 0; i < entries; i++ ) {
04311 
04312         theObjectH = theIntervalVector[i].getObject( );
04313         theIntervalVector[i].getInterval( theIntervalBase );
04314         theIntervalVector[i].getExistingInterval( theOldIntervalH );
04315 
04316         theBeginTime = theIntervalBase.getBeginTime( );
04317         theEndTime   = theIntervalBase.getEndTime( );
04318 
04319       // Check if we are trying to modify the FIRST interval.
04320       // In this case a new interval may not be aligned to the border
04321       // of the existing intervals.
04322 
04323         if(( theOldIntervalH == theFirstIntervalH ) ||
04324            ( theOldIntervalH == theLastIntervalH )) {
04325 
04326             ErrMsg(error) << errorString << endl
04327                           << "    The inproper use of this method. Neither the FIRST nor the LAST" << endl
04328                           << "    interval can not be included into the operation." << endl
04329                           << "        DETECTOR   -> " << subsystemTLA( ) << endl
04330                           << "        CONTAINER  -> " << containerName( ) << endl
04331                           << "        BEGIN TIME -> " << theBeginVectorTime << endl
04332                           << "        END   TIME -> " << theEndVectorTime << endmsg;
04333             return BdbcError;
04334 
04335         }
04336 
04337       // Now we are adding an interval somewhere in the middle of the list. This procedure
04338       // is quite routine given the prepared contents of the vector.
04339 
04340        addVectorVersion( theOldIntervalH,
04341                          theObjectH,
04342                          theBeginTime,
04343                          theEndTime,
04344                          theVersionTime,
04345                          theTag );
04346     }
04347 
04348     return BdbcSuccess;
04349 }
04350 
04351 void 
04352 BdbDatabase::version( const BdbHandle(BdbCondRevision)& theRevisionH,
04353                       const BdbHandle(BdbObject)&       theNewObjectH,
04354                       const BdbTime&                    theBeginTime,
04355                       d_ULong                           theTag )
04356 {
04357     BdbHandle(BdbIntervalR) theIntervalH;
04358 
04359     theIntervalH = 0;
04360 
04361   // Get the cached container handle.
04362 
04363     BdbHandle(BdbContObj) intervalContH;
04364     getIntervalContH( intervalContH );
04365 
04366   // Find the TOPMOST interval.
04367 
04368     if ( BdbcSuccess != findInterval( theIntervalH, theBeginTime, theTag )) return;
04369 
04370   // chose linear or branch versioning for this interval
04371 
04372     if ( theBeginTime == theIntervalH->getBeginTime( )) {
04373 
04374       // create one linear version
04375 
04376         version1( theRevisionH,
04377                   theIntervalH,
04378                   theNewObjectH,
04379                   theTag );
04380 
04381     } else {
04382 
04383       // create two branch versions, the right interval gets the new object
04384 
04385         version2R( theRevisionH,
04386                    theIntervalH,
04387                    theNewObjectH,
04388                    theBeginTime,
04389                    theTag );
04390     }
04391 
04392     BdbHandle(BdbIntervalR) lastIntervalH;
04393     lastIntervalH.lookupObj( intervalContH, "LastInterval" );
04394 
04395   // Find the topmost interval again, coz' the previous one is below and
04396   // has NULL topmost pointers.
04397 
04398     findInterval( theIntervalH, theBeginTime, theTag );
04399     theIntervalH->getTopNext( theIntervalH );
04400       
04401     while ( ! BdbIsNull(theIntervalH)) {
04402 
04403         if ( theIntervalH == lastIntervalH ) {
04404 
04405             updateLastInterval( theNewObjectH,
04406                                 lastIntervalH,
04407                                 theTag );
04408             break;
04409 
04410         } else {
04411 
04412           // 1 : 1 linear version
04413 
04414             version1( theRevisionH,
04415                       theIntervalH,
04416                       theNewObjectH,
04417                       theTag );
04418 
04419           // Find the topmost interval again, coz' the previous one is below and
04420           // has NULL topmost pointers.
04421           // This is the only case when we continue traversing the topmost list.
04422 
04423             findInterval( theIntervalH, theIntervalH->getBeginTime( ), theTag );
04424             theIntervalH->getTopNext( theIntervalH );
04425         }
04426     }
04427 }
04428 
04429 
04430 void 
04431 BdbDatabase::version( const BdbHandle(BdbCondRevision)& theRevisionH,
04432                       const BdbHandle(BdbObject)&       theNewObjectH,
04433                       const BdbTime&                    theBeginTime,
04434                       const BdbTime&                    theEndTime,
04435                       d_ULong                           theTag,
04436                       const BdbTime&                    theVersionTime )
04437 {
04438     BdbHandle(BdbIntervalR) theIntervalH;
04439 
04440     theIntervalH = 0;
04441 
04442   // Get the cached container handle.
04443 
04444     BdbHandle(BdbContObj) intervalContH;
04445     getIntervalContH( intervalContH );
04446 
04447   // Find the TOPMOST interval.
04448 
04449     if ( BdbcSuccess != findInterval( theIntervalH, theBeginTime, theTag )) return;
04450 
04451     if ( theEndTime < theIntervalH->getEndTime( )) {
04452 
04453         if ( theBeginTime == theIntervalH->getBeginTime( )) {
04454 
04455           // 2L : 2 branch versions, left branch has new calibration object
04456 
04457             version2L( theRevisionH,
04458                        theIntervalH,
04459                        theNewObjectH,
04460                        theEndTime,
04461                        theTag,
04462                        theVersionTime );
04463 
04464         } else {
04465 
04466           // 3M : 3 branch versions, middle branch has new calibration object
04467 
04468             version3M( theRevisionH,
04469                        theIntervalH,
04470                        theNewObjectH,
04471                        theBeginTime,
04472                        theEndTime,
04473                        theTag,
04474                        theVersionTime );
04475         }
04476 
04477     } else {
04478 
04479         if ( theBeginTime == theIntervalH->getBeginTime( )) {
04480 
04481           // 1 : 1 linear version
04482 
04483             version1( theRevisionH,
04484                       theIntervalH,
04485                       theNewObjectH,
04486                       theTag,
04487                       theVersionTime );
04488 
04489         } else {
04490 
04491           // 2R : 2 branch versions, right branch has new calibration object
04492 
04493             version2R( theRevisionH,
04494                        theIntervalH,
04495                        theNewObjectH,
04496                        theBeginTime,
04497                        theTag,
04498                        theVersionTime );
04499         }
04500 
04501         BdbHandle(BdbIntervalR) lastIntervalH;
04502         lastIntervalH.lookupObj( intervalContH, "LastInterval" );
04503 
04504       // Find the topmost interval again, coz' the previous one is below and
04505       // has NULL topmost pointers.
04506 
04507         findInterval( theIntervalH, theBeginTime, theTag );
04508         theIntervalH->getTopNext( theIntervalH );
04509       
04510         while (( ! BdbIsNull( theIntervalH )) && ( theEndTime > theIntervalH->getBeginTime( ))) {
04511 
04512             if ( theEndTime < theIntervalH->getEndTime( )) {
04513 
04514                 if ( theIntervalH == lastIntervalH ) {
04515 
04516                     cutLastInterval( theNewObjectH,
04517                                      lastIntervalH, 
04518                                      theBeginTime,
04519                                      theEndTime,
04520                                      theTag );
04521 
04522                 } else {
04523 
04524                   // 2L : 2 branch versions, left branch has new calibration object
04525 
04526                     version2L( theRevisionH,
04527                                theIntervalH,
04528                                theNewObjectH,
04529                                theEndTime,
04530                                theTag,
04531                                theVersionTime);
04532                 }
04533                 break;
04534 
04535             } else {
04536 
04537                 if ( theIntervalH == lastIntervalH ) {
04538 
04539                     updateLastInterval( theNewObjectH,
04540                                         lastIntervalH,
04541                                         theTag );
04542                     break;
04543 
04544                 } else {
04545 
04546                   // 1 : 1 linear version
04547 
04548                     version1( theRevisionH,
04549                               theIntervalH,
04550                               theNewObjectH,
04551                               theTag,
04552                               theVersionTime );
04553 
04554                     if ( theEndTime == theIntervalH->getEndTime( )) {
04555 
04556                         break;
04557 
04558                     } else {
04559 
04560                       // Find the topmost interval again, coz' the previous one is below and
04561                       // has NULL topmost pointers.
04562                       // This is the only case when we continue traversing the topmost list.
04563 
04564                         findInterval( theIntervalH, theIntervalH->getBeginTime( ), theTag );
04565                         theIntervalH->getTopNext( theIntervalH );
04566                     }
04567                 }
04568             }
04569         }
04570     }
04571 }
04572 
04573 
04574 void 
04575 BdbDatabase::version1( const BdbHandle(BdbCondRevision)& theRevisionH,
04576                        const BdbHandle(BdbIntervalR)&    theIntervalH,
04577                        const BdbHandle(BdbObject)&       theNewObjectH,
04578                        d_ULong                           theTag,
04579                        const BdbTime&                    theVersionTime )
04580 {
04581   //---------------------------------------------------------------------------
04582   // Create one linear version of the interval object,
04583   // put the new calibration object into the versioned interval. 
04584   //
04585   // theBeginTime and theEndTime are equal to the begin and end times of theIntervalH
04586   //---------------------------------------------------------------------------
04587   
04588   // create a new linear version of the interval object
04589 
04590     BdbHandle(BdbIntervalR) newIntervalH;
04591 
04592     theIntervalH.setVersStatus( oocLinearVers );
04593     createRevisedTopVersion( theIntervalH, newIntervalH );
04594     theIntervalH.setVersStatus( oocNoVers );
04595 
04596   // insert the new versioned interval into the doubly linked list
04597 
04598   // get the next and previous intervals in the doubly linked list
04599 
04600     BdbHandle(BdbIntervalR) theNextIntervalH;
04601     theIntervalH->getTopNext( theNextIntervalH );
04602 
04603     BdbHandle(BdbIntervalR) thePreviousIntervalH;
04604     theIntervalH->getTopPrevious( thePreviousIntervalH );
04605 
04606     if ( thePreviousIntervalH != NULL ) {
04607         thePreviousIntervalH->setTopNext( newIntervalH );
04608     }
04609 
04610     newIntervalH->setTopPrevious( thePreviousIntervalH );
04611     newIntervalH->setTopNext( theNextIntervalH );
04612 
04613     if ( theNextIntervalH != NULL ) {
04614         theNextIntervalH->setTopPrevious( newIntervalH );
04615     }
04616 
04617   // Nullify the next and previous links of the interval which is below
04618   // the new one now, since it's not on the top anymore.
04619 
04620     theIntervalH->setTopPrevious( NULL );
04621     theIntervalH->setTopNext( NULL );
04622      
04623   // put the new calibration object into the versioned interval
04624 
04625     newIntervalH->setObject( theNewObjectH );
04626     newIntervalH->setTag( theTag );
04627 
04628   // set version time for the TOP interval
04629 
04630     if ( theVersionTime == BdbTime::minusInfinity ) {
04631         newIntervalH->setVersionTime( BdbTime( ));
04632     } else {
04633         newIntervalH->setVersionTime( theVersionTime );
04634     }
04635 
04636   // connect interval to specified revision if required
04637 
04638     if ( ! BdbIsNull(theRevisionH)) {
04639         newIntervalH->setRevision( theRevisionH );
04640     }
04641 
04642   // name the interval objects
04643 
04644     nameVersion( theIntervalH, newIntervalH );
04645 }
04646 
04647 
04648 void 
04649 BdbDatabase::version2L( const BdbHandle(BdbCondRevision)& theRevisionH,
04650                         const BdbHandle(BdbIntervalR)&    theIntervalH,
04651                         const BdbHandle(BdbObject)&       theNewObjectH,
04652                         const BdbTime&                    theEndTime,
04653                         d_ULong                           theTag,
04654                         const BdbTime&                    theVersionTime )
04655 {
04656 
04657   //---------------------------------------------------------------------------
04658   // Create two branch versions,
04659   // put the new calibration object into the left interval,
04660   // copy the original calibration object into the right interval.
04661   //
04662   // theBeginTime equals the begin time of theIntervalH
04663   //---------------------------------------------------------------------------
04664 
04665   // create 2 branch versions
04666 
04667     BdbHandle(BdbIntervalR) leftIntervalH;
04668     BdbHandle(BdbIntervalR) rightIntervalH;
04669 
04670     theIntervalH.setVersStatus( oocBranchVers );
04671     createRevisedTopVersion( theIntervalH, leftIntervalH );
04672     createRevisedTopVersion( theIntervalH, rightIntervalH );
04673     theIntervalH.setVersStatus( oocNoVers );
04674 
04675   // insert the two versioned intervals into the doubly linked list
04676 
04677   // get the next and previous intervals in the doubly linked list
04678 
04679     BdbHandle(BdbIntervalR) theNextIntervalH;
04680     theIntervalH->getTopNext( theNextIntervalH );
04681     
04682     BdbHandle(BdbIntervalR) thePreviousIntervalH;
04683     theIntervalH->getTopPrevious( thePreviousIntervalH );
04684 
04685     if ( thePreviousIntervalH != NULL ) {
04686         thePreviousIntervalH->setTopNext( leftIntervalH );
04687     }
04688     leftIntervalH->setTopNext(  rightIntervalH   );
04689     rightIntervalH->setTopNext( theNextIntervalH );
04690 
04691     if ( theNextIntervalH != NULL ) {
04692         theNextIntervalH->setTopPrevious( rightIntervalH );
04693     }
04694     rightIntervalH->setTopPrevious( leftIntervalH );
04695     leftIntervalH->setTopPrevious( thePreviousIntervalH );
04696 
04697   // Nullify the next and previous links of the interval which is below
04698   // the new one now, since it's not on the top anymore.
04699 
04700     theIntervalH->setTopPrevious( NULL );
04701     theIntervalH->setTopNext( NULL );
04702    
04703   // set end time of left interval to theEndTime
04704 
04705     leftIntervalH->setEndTime( theEndTime );
04706 
04707   // set begin time of right interval to theEndTime
04708 
04709     rightIntervalH->setBeginTime( theEndTime );
04710 
04711   // put the new calibration object into the left interval object
04712 
04713     leftIntervalH->setObject( theNewObjectH );
04714     leftIntervalH->setTag( theTag );
04715 
04716   // set version time for the LEFT interval only
04717 
04718     if ( theVersionTime == BdbTime::minusInfinity ) {
04719         leftIntervalH->setVersionTime( BdbTime( ));
04720     } else {
04721         leftIntervalH->setVersionTime( theVersionTime );
04722     }
04723 
04724   // connect LEFT interval to specified revision if required
04725 
04726     if ( ! BdbIsNull(theRevisionH)) {
04727         leftIntervalH->setRevision( theRevisionH );
04728     }
04729 
04730   // name the interval objects
04731 
04732     nameVersion( theIntervalH, leftIntervalH );
04733     nameVersion( theIntervalH, rightIntervalH );
04734 }
04735 
04736 
04737 void 
04738 BdbDatabase::version2R( const BdbHandle(BdbCondRevision)& theRevisionH,
04739                         const BdbHandle(BdbIntervalR)&    theIntervalH,
04740                         const BdbHandle(BdbObject)&       theNewObjectH,
04741                         const BdbTime&                    theBeginTime,
04742                         d_ULong                           theTag,
04743                         const BdbTime&                    theVersionTime )
04744 {
04745   //---------------------------------------------------------------------------
04746   // Create two branch versions, 
04747   // put the new calibration object into the right interval,
04748   // copy the original calibration object into the left interval.
04749   //
04750   // theEndTime equals the end time of theIntervalH
04751   //---------------------------------------------------------------------------
04752 
04753   // First, create 2 branch versions
04754 
04755     BdbHandle(BdbIntervalR) leftIntervalH;
04756     BdbHandle(BdbIntervalR) rightIntervalH;
04757 
04758     theIntervalH.setVersStatus( oocBranchVers );
04759     createRevisedTopVersion( theIntervalH, leftIntervalH );
04760     createRevisedTopVersion( theIntervalH, rightIntervalH );
04761     theIntervalH.setVersStatus( oocNoVers );
04762 
04763   // insert the two versioned intervals into the doubly linked list
04764 
04765   // get the next and previous intervals in the doubly linked list
04766 
04767     BdbHandle(BdbIntervalR) theNextIntervalH;
04768     theIntervalH->getTopNext( theNextIntervalH );
04769 
04770     BdbHandle(BdbIntervalR) thePreviousIntervalH;
04771     theIntervalH->getTopPrevious( thePreviousIntervalH );
04772 
04773     if ( thePreviousIntervalH != NULL ) {
04774         thePreviousIntervalH->setTopNext( leftIntervalH );
04775     }
04776 
04777     leftIntervalH->setTopNext(  rightIntervalH   );
04778     rightIntervalH->setTopNext( theNextIntervalH );
04779       
04780     if ( theNextIntervalH != NULL ) {
04781         theNextIntervalH->setTopPrevious( rightIntervalH );
04782     }
04783     rightIntervalH->setTopPrevious( leftIntervalH        );
04784     leftIntervalH->setTopPrevious(  thePreviousIntervalH );
04785       
04786   // Nullify the next and previous links of the interval which is below
04787   // the new one now, since it's not on the top anymore.
04788 
04789     theIntervalH->setTopPrevious( NULL );
04790     theIntervalH->setTopNext( NULL );
04791    
04792   // set end time of left interval to theBeginTime
04793 
04794     leftIntervalH->setEndTime( theBeginTime );
04795 
04796   // set begin time of right interval to theBeginTime
04797 
04798     rightIntervalH->setBeginTime( theBeginTime );
04799    
04800   // put the new calibration object into the right interval object
04801 
04802     rightIntervalH->setObject( theNewObjectH );
04803     rightIntervalH->setTag( theTag );
04804 
04805   // set version time for the RIGHT interval only
04806 
04807     if ( theVersionTime == BdbTime::minusInfinity ) {
04808         rightIntervalH->setVersionTime( BdbTime( ));
04809     } else {
04810         rightIntervalH->setVersionTime( theVersionTime );
04811     }
04812 
04813   // connect RIGHT interval to specified revision if required
04814 
04815     if ( ! BdbIsNull(theRevisionH)) {
04816         rightIntervalH->setRevision( theRevisionH );
04817     }
04818 
04819   // name the interval objects
04820 
04821     nameVersion( theIntervalH, leftIntervalH );
04822     nameVersion( theIntervalH, rightIntervalH );
04823 }
04824 
04825 void 
04826 BdbDatabase::version3M( const BdbHandle(BdbCondRevision)& theRevisionH,
04827                         const BdbHandle(BdbIntervalR)&    theIntervalH,
04828                         const BdbHandle(BdbObject)&       theNewObjectH,
04829                         const BdbTime&                    theBeginTime,
04830                         const BdbTime&                    theEndTime,
04831                         d_ULong                           theTag,
04832                         const BdbTime&                    theVersionTime )
04833 {
04834   //---------------------------------------------------------------------------
04835   // Create three branch versions,
04836   // put the new calibration object into the middle interval,
04837   // copy the original calibration object into the left and right intervals.
04838   //
04839   // theBeginTime and theEndTime are contained within theIntervalH
04840   //---------------------------------------------------------------------------
04841 
04842   // First, create 3 branch versions of the interval
04843 
04844     BdbHandle(BdbIntervalR) leftIntervalH;
04845     BdbHandle(BdbIntervalR) middleIntervalH;
04846     BdbHandle(BdbIntervalR) rightIntervalH;
04847 
04848     theIntervalH.setVersStatus( oocBranchVers );
04849     createRevisedTopVersion( theIntervalH, leftIntervalH );
04850     createRevisedTopVersion( theIntervalH, middleIntervalH );
04851     createRevisedTopVersion( theIntervalH, rightIntervalH );
04852     theIntervalH.setVersStatus( oocNoVers );
04853 
04854   // insert the three versioned intervals into the doubly linked list
04855 
04856   // get the next and previous intervals in the doubly linked list
04857 
04858     BdbHandle(BdbIntervalR) theNextIntervalH;
04859     theIntervalH->getTopNext( theNextIntervalH );
04860 
04861     BdbHandle(BdbIntervalR) thePreviousIntervalH;
04862     theIntervalH->getTopPrevious( thePreviousIntervalH );
04863 
04864     if ( thePreviousIntervalH != NULL ) {
04865         thePreviousIntervalH->setTopNext( leftIntervalH );
04866     }
04867     leftIntervalH->setTopNext( middleIntervalH );
04868     middleIntervalH->setTopNext( rightIntervalH );
04869     rightIntervalH->setTopNext(theNextIntervalH );
04870 
04871     if ( theNextIntervalH != NULL ) {
04872         theNextIntervalH->setTopPrevious( rightIntervalH );
04873     }
04874     rightIntervalH->setTopPrevious( middleIntervalH );
04875     middleIntervalH->setTopPrevious( leftIntervalH );
04876     leftIntervalH->setTopPrevious( thePreviousIntervalH );
04877 
04878   // Nullify the next and previous links of the interval which is below
04879   // the new one now, since it's not on the top anymore.
04880 
04881     theIntervalH->setTopPrevious( NULL );
04882     theIntervalH->setTopNext( NULL );
04883    
04884   // set end time of left interval to theBeginTime
04885 
04886     leftIntervalH->setEndTime( theBeginTime );
04887 
04888     middleIntervalH->setBeginTime( theBeginTime );
04889     middleIntervalH->setEndTime(     theEndTime );
04890 
04891   // set begin time of right interval to theEndTime
04892 
04893     rightIntervalH->setBeginTime( theEndTime );
04894    
04895   // put the new calibration object into the middle interval object
04896 
04897     middleIntervalH->setObject( theNewObjectH );
04898     middleIntervalH->setTag( theTag );
04899 
04900   // set version time for the MIDDLE interval only
04901 
04902     if ( theVersionTime == BdbTime::minusInfinity ) {
04903         middleIntervalH->setVersionTime( BdbTime( ));
04904     } else {
04905         middleIntervalH->setVersionTime( theVersionTime );
04906     }
04907 
04908   // connect MIDDLE interval to specified revision if required
04909 
04910     if ( ! BdbIsNull(theRevisionH)) {
04911         middleIntervalH->setRevision( theRevisionH );
04912     }
04913 
04914   // name the interval objects
04915 
04916     nameVersion( theIntervalH, leftIntervalH );
04917     nameVersion( theIntervalH, middleIntervalH );
04918     nameVersion( theIntervalH, rightIntervalH );
04919 }
04920 
04921 
04922 BdbStatus
04923 BdbDatabase::updateFirstInterval( const BdbHandle(BdbObject)&    theObjectH,
04924                                   const BdbHandle(BdbIntervalR)& firstIntervalH,
04925                                   const BdbTime&                 theEndTime,
04926                                   d_ULong                        theTag,
04927                                   const BdbTime&                 theVersionTime )
04928 {
04929     assert( theEndTime <= firstIntervalH->getEndTime( ));
04930 
04931   // Does new interval covers the whole FIRST interval?
04932 
04933     if ( theEndTime == firstIntervalH->getEndTime( )) {
04934 
04935       // It does. Then just replace some information and quit.
04936 
04937         firstIntervalH->setObject( theObjectH );
04938         firstIntervalH->setTag( theTag );
04939 
04940       // modify the version time
04941 
04942         if( BdbTime::minusInfinity == theVersionTime ) {
04943             firstIntervalH->setVersionTime( BdbTime( ));
04944         } else {
04945             firstIntervalH->setVersionTime( theVersionTime );
04946         }
04947 
04948         return BdbcSuccess;
04949     }
04950 
04951   // Get the cached container handle.
04952 
04953     BdbHandle(BdbContObj) intervalContH;
04954     getIntervalContH( intervalContH );
04955 
04956   // Get the cached BASELINE revision.
04957 
04958     BdbHandle(BdbCondRevision) baselineRevisionH;
04959     getBaselineRevisionH( baselineRevisionH );
04960 
04961   // Create new first interval at the very beginning.
04962 
04963     BdbHandle(BdbIntervalR) newFirstIntervalH;
04964     newFirstIntervalH = new( intervalContH ) BdbIntervalR( theObjectH,
04965                                                            BdbTime::minusInfinity,
04966                                                            theEndTime );
04967     newFirstIntervalH->setRevision( baselineRevisionH );
04968 
04969   // reset begin time of the current first interval
04970 
04971     firstIntervalH->setBeginTime( theEndTime );
04972 
04973   // insert new first interval at the beginning of BASELINE doubly linked list
04974 
04975     newFirstIntervalH->setBaselineNext( firstIntervalH );
04976     firstIntervalH->setBaselinePrevious( newFirstIntervalH );
04977 
04978   // insert new firstst interval at the beginning of TOP doubly linked list
04979 
04980     newFirstIntervalH->setTopNext( firstIntervalH );
04981     firstIntervalH->setTopPrevious( newFirstIntervalH );
04982 
04983   // modify the version time
04984 
04985     if( BdbTime::minusInfinity == theVersionTime ) {
04986         newFirstIntervalH->setVersionTime( BdbTime( ));
04987     } else {
04988         newFirstIntervalH->setVersionTime( theVersionTime );
04989     }
04990 
04991   // rename the first interval
04992 
04993     firstIntervalH.unnameObj(  intervalContH );
04994     newFirstIntervalH.nameObj( intervalContH, "FirstInterval" );
04995 
04996     return BdbcSuccess;
04997 }
04998 
04999 BdbStatus
05000 BdbDatabase::cutFirstInterval( const BdbHandle(BdbObject)&    theObjectH,
05001                                const BdbHandle(BdbIntervalR)& firstIntervalH,
05002                                const BdbTime&                 theBeginTime,
05003                                const BdbTime&                 theEndTime,
05004                                d_ULong                        theTag,
05005                                const BdbTime&                 theVersionTime )
05006 {
05007     assert( theBeginTime < theEndTime );
05008     assert( theEndTime <= firstIntervalH->getEndTime( ));
05009 
05010   // If the new interval starts from the minus infinity
05011   // then we go to update the first interval.
05012 
05013     if ( theBeginTime == BdbTime::minusInfinity ) {
05014 
05015         return updateFirstInterval( theObjectH,
05016                                     firstIntervalH,
05017                                     theEndTime,
05018                                     theTag,
05019                                     theVersionTime );
05020     }
05021 
05022   // Get the cached container handle.
05023 
05024     BdbHandle(BdbContObj) intervalContH;
05025     getIntervalContH( intervalContH );
05026 
05027   // Get the cached BASELINE revision.
05028 
05029     BdbHandle(BdbCondRevision) baselineRevisionH;
05030     getBaselineRevisionH( baselineRevisionH );
05031 
05032   // Create new first interval at the very beginning.
05033   // This interval will derive everything from its predesessor.
05034 
05035     BdbHandle(BdbIntervalR) newFirstIntervalH;
05036     newFirstIntervalH = new( intervalContH ) BdbIntervalR( firstIntervalH->getObject( ),
05037                                                            BdbTime::minusInfinity,
05038                                                            theBeginTime );
05039 
05040     newFirstIntervalH->setRevision( baselineRevisionH );
05041     newFirstIntervalH->setVersionTime( firstIntervalH->getVersionTime( ));
05042     newFirstIntervalH->setTag( firstIntervalH->getTag( ));
05043 
05044   // reset begin time of the current first interval
05045 
05046     firstIntervalH->setBeginTime( theBeginTime );
05047 
05048   // insert new first interval at the beginning of BASELINE doubly linked list
05049 
05050     newFirstIntervalH->setBaselineNext( firstIntervalH );
05051     firstIntervalH->setBaselinePrevious( newFirstIntervalH );
05052 
05053   // insert new firstst interval at the beginning of TOP doubly linked list
05054 
05055     newFirstIntervalH->setTopNext( firstIntervalH );
05056     firstIntervalH->setTopPrevious( newFirstIntervalH );
05057 
05058   // rename the first interval
05059 
05060     firstIntervalH.unnameObj(  intervalContH );
05061     newFirstIntervalH.nameObj( intervalContH, "FirstInterval" );
05062 
05063   // version the old/current first interval as a regular interval
05064   // in the middle of the list.
05065 
05066     version( NULL,
05067              theObjectH,
05068              theBeginTime,
05069              theEndTime,
05070              theTag,
05071              theVersionTime );
05072 
05073     return BdbcSuccess;
05074 }
05075 
05076 BdbStatus
05077 BdbDatabase::updateLastInterval( const BdbHandle(BdbObject)&    theObjectH,
05078                                  const BdbHandle(BdbIntervalR)& lastIntervalH,
05079                                  d_ULong                        theTag,
05080                                  const BdbTime&                 theVersionTime  )
05081 {
05082   // replace object reference in the last interval
05083 
05084     lastIntervalH->setObject( theObjectH );
05085     lastIntervalH->setTag( theTag );
05086 
05087   // modify the version time
05088 
05089     if( BdbTime::minusInfinity == theVersionTime ) {
05090         lastIntervalH->setVersionTime( BdbTime( ));
05091     } else {
05092         lastIntervalH->setVersionTime( theVersionTime );
05093     }
05094 
05095     return BdbcSuccess;
05096 }
05097 
05098 BdbStatus
05099 BdbDatabase::cutLastInterval( const BdbHandle(BdbObject)&     theObjectH,
05100                               const BdbHandle(BdbIntervalR)&  lastIntervalH,
05101                               const BdbTime&                  theBeginTime,
05102                               const BdbTime&                  theEndTime,
05103                               d_ULong                         theTag,
05104                               const BdbTime&                  theVersionTime )
05105 {
05106     assert ( theEndTime > theBeginTime );
05107 
05108     if ( theEndTime == BdbTime::plusInfinity ) {
05109 
05110         return updateLastInterval( theObjectH,
05111                                    lastIntervalH,
05112                                    theTag,
05113                                    theVersionTime );
05114     } else {
05115 
05116   // Get the cached container handle.
05117 
05118     BdbHandle(BdbContObj) intervalContH;
05119     getIntervalContH( intervalContH );
05120 
05121   // Get the cached BASELINE revision.
05122 
05123     BdbHandle(BdbCondRevision) baselineRevisionH;
05124     getBaselineRevisionH( baselineRevisionH );
05125 
05126       // create a new last interval in a BASELINE revision
05127 
05128         BdbHandle(BdbIntervalR) newLastIntervalH;
05129         newLastIntervalH = new( intervalContH ) BdbIntervalR( NULL,
05130                                                               theEndTime,
05131                                                               BdbTime::plusInfinity );
05132 
05133         newLastIntervalH->setRevision( baselineRevisionH );
05134 
05135       // reset end time of the current last interval
05136 
05137         lastIntervalH->setEndTime( theEndTime );
05138   
05139       // append new last interval to end of BASELINE doubly linked list
05140 
05141         lastIntervalH->setBaselineNext( newLastIntervalH );
05142         newLastIntervalH->setBaselinePrevious( lastIntervalH );
05143 
05144       // append new last interval to end of TOP doubly linked list
05145 
05146         lastIntervalH->setTopNext( newLastIntervalH );
05147         newLastIntervalH->setTopPrevious( lastIntervalH );
05148 
05149       // rename the last interval
05150 
05151         lastIntervalH.unnameObj(  intervalContH );
05152         newLastIntervalH.nameObj( intervalContH, "LastInterval" );
05153 
05154       // And finally - create a linear version of the old (shortened) last interval
05155       // We do it here since the version should be created within an established
05156       // structure of horizontal links.
05157 
05158         version1( NULL, lastIntervalH, theObjectH, theTag, theVersionTime );
05159     }
05160     
05161     return BdbcSuccess;
05162 }
05163 
05164 BdbStatus
05165 BdbDatabase::truncateLastInterval( const BdbHandle(BdbObject)&    theObjectH,
05166                                    const BdbHandle(BdbIntervalR)& lastIntervalH,
05167                                    const BdbTime&                 theInsertTime,
05168                                    const BdbTime&                 theTruncateTime,
05169                                    d_ULong                        theTag )
05170 {
05171     BdbStatus status = BdbcError;
05172 
05173   // the only difference of this algorithm from the ::cutLastInterval() and ::appendIntervalR()
05174   // is that this one sets a BdbObject pointer of the new LastInterval to the one
05175   // specified by current parameter.
05176 
05177     assert ( theTruncateTime > theInsertTime );
05178     assert ( theTruncateTime != BdbTime::plusInfinity );
05179 
05180   // call an insertion method depending on whether the insert time
05181   // starts with the beginning of existing last interval.
05182 
05183     if ( theInsertTime == lastIntervalH->getBeginTime( )) {
05184 
05185         status = cutLastInterval( theObjectH,
05186                                   lastIntervalH,
05187                                   theInsertTime,
05188                                   theTruncateTime,
05189                                   theTag );
05190     } else {
05191 
05192         status = appendIntervalR( theObjectH,
05193                                   lastIntervalH,
05194                                   theInsertTime,
05195                                   theTruncateTime,
05196                                   theTag );
05197     }
05198     if ( BdbcSuccess != status ) {
05199         return status;
05200     }
05201 
05202   // Get the cached container handle.
05203 
05204     BdbHandle(BdbContObj) intervalContH;
05205     getIntervalContH( intervalContH );
05206 
05207   // locate new last interval and substitute a BdbObject pointer to
05208   // the new object.
05209 
05210     BdbHandle(BdbIntervalR) newLastIntervalH;
05211     newLastIntervalH.lookupObj( intervalContH, "LastInterval"  );
05212 
05213     newLastIntervalH->setObject( theObjectH );
05214 
05215     return BdbcSuccess;
05216 }
05217 
05218 BdbStatus
05219 BdbDatabase::appendIntervalR( const BdbHandle(BdbObject)&    theObjectH,
05220                               const BdbHandle(BdbIntervalR)& lastIntervalH,
05221                               const BdbTime&                 theBeginTime,
05222                               d_ULong                        theTag,
05223                               const BdbTime&                 theVersionTime )
05224 {
05225   // Implement the "revision"-aware algorithm.
05226   // In particular this algorithm assumes no versions
05227   // for the last interval.
05228 
05229     assert( theBeginTime > lastIntervalH->getBeginTime( )) ;
05230 
05231   // Get the cached container handle.
05232 
05233     BdbHandle(BdbContObj) intervalContH;
05234     getIntervalContH( intervalContH );
05235 
05236   // Get the cached BASELINE revision.
05237 
05238     BdbHandle(BdbCondRevision) baselineRevisionH;
05239     getBaselineRevisionH( baselineRevisionH );
05240 
05241   // append interval to end of list
05242 
05243   // reset end time of the current last interval.
05244 
05245     lastIntervalH->setEndTime( theBeginTime );
05246 
05247   // create the new LAST interval
05248 
05249     BdbHandle(BdbIntervalR) newLastIntervalH;
05250     newLastIntervalH = new( intervalContH ) BdbIntervalR( theObjectH,
05251                                                           theBeginTime,
05252                                                           BdbTime::plusInfinity,
05253                                                           theTag );
05254     newLastIntervalH->setRevision( baselineRevisionH );
05255 
05256   // Append new interval to end of BASELINE doubly linked list.
05257 
05258     lastIntervalH->setBaselineNext( newLastIntervalH );
05259     newLastIntervalH->setBaselinePrevious( lastIntervalH );
05260 
05261   // Append new interval by end of TOP doubly linked list.
05262 
05263     lastIntervalH->set_next( newLastIntervalH );
05264     newLastIntervalH->set_previous( lastIntervalH );
05265 
05266   // Explicitly set the version time if required.
05267 
05268     if( BdbTime::minusInfinity != theVersionTime ) {
05269         newLastIntervalH->setVersionTime( theVersionTime );
05270     }
05271 
05272   // rename the last interval
05273 
05274     lastIntervalH.unnameObj(  intervalContH );
05275     newLastIntervalH.nameObj( intervalContH, "LastInterval" );
05276 
05277     return BdbcSuccess;
05278 }
05279 
05280 
05281 BdbStatus
05282 BdbDatabase::appendIntervalR( const BdbHandle(BdbObject)&    theObjectH,
05283                               const BdbHandle(BdbIntervalR)& lastIntervalH,
05284                               const BdbTime&                 theBeginTime,
05285                               const BdbTime&                 theEndTime,
05286                               d_ULong                        theTag,
05287                               const BdbTime&                 theVersionTime )
05288 {
05289   // Implement the "revision"-aware algorithm.
05290   // In particular this algorithm assumes no versions
05291   // for the last interval.
05292 
05293     assert( theBeginTime > lastIntervalH->getBeginTime( )) ;
05294 
05295   // append interval to end of list
05296 
05297     if ( theEndTime == BdbTime::plusInfinity ) {
05298         return appendIntervalR( theObjectH, lastIntervalH, theBeginTime, theTag, theVersionTime );
05299     } else {
05300 
05301       // Get the cached container handle.
05302 
05303         BdbHandle(BdbContObj) intervalContH;
05304         getIntervalContH( intervalContH );
05305 
05306       // Get the cached BASELINE revision.
05307 
05308         BdbHandle(BdbCondRevision) baselineRevisionH;
05309         getBaselineRevisionH( baselineRevisionH );
05310 
05311       // reset end time of the current last interval
05312 
05313         lastIntervalH->setEndTime( theBeginTime );
05314 
05315       // Create the new interval with the same time limits as a new interval,
05316       // but pointing to the last interval's object.
05317       // Later we will version this interval with a new object.
05318 
05319         BdbHandle( BdbIntervalR ) newIntervalH;
05320         newIntervalH = new( intervalContH ) BdbIntervalR( lastIntervalH->getObject( ),
05321                                                           theBeginTime,
05322                                                           theEndTime,
05323                                                           theTag );
05324         newIntervalH->setVersionTime( lastIntervalH->getVersionTime( ));
05325         newIntervalH->setRevision( baselineRevisionH );
05326 
05327       // create the new last interval
05328 
05329         BdbHandle(BdbIntervalR) newLastIntervalH;
05330         newLastIntervalH = new( intervalContH ) BdbIntervalR( 0,
05331                                                               theEndTime,
05332                                                               BdbTime::plusInfinity );
05333         newLastIntervalH->setRevision( baselineRevisionH );
05334 
05335       // insert new interval and new last interval into BASELINE doubly linked list
05336 
05337         lastIntervalH->setBaselineNext( newIntervalH );
05338         newIntervalH->setBaselinePrevious( lastIntervalH );
05339         newIntervalH->setBaselineNext( newLastIntervalH );
05340         newLastIntervalH->setBaselinePrevious( newIntervalH );
05341 
05342       // insert new interval and new last interval into TOP doubly linked list
05343 
05344         lastIntervalH->setTopNext( newIntervalH );
05345         newIntervalH->setTopPrevious( lastIntervalH );
05346         newIntervalH->setTopNext( newLastIntervalH );
05347         newLastIntervalH->setTopPrevious( newIntervalH );
05348 
05349       // rename the last interval
05350 
05351         lastIntervalH.unnameObj(  intervalContH );
05352         newLastIntervalH.nameObj( intervalContH, "LastInterval" );
05353 
05354       // And finally - create a linear version of the new interval
05355       // created in between a previous interval and a new last interval.
05356       // We do it here since the version should be created within an established
05357       // structure.
05358 
05359         version1( 0, newIntervalH, theObjectH, theTag, theVersionTime );
05360     }
05361 
05362     return BdbcSuccess;
05363 }
05364 
05365 
05366 void
05367 BdbDatabase::createVersion( const BdbHandle(BdbIntervalR)& theOldIntervalH,
05368                             BdbHandle(BdbIntervalR)&       theNewIntervalH )
05369 {
05370 
05371   // Replace the following code:
05372   //
05373   //   theOldIntervalH.close( );
05374   //   theNewIntervalH = theOldIntervalH;
05375   //   theNewIntervalH.update( );
05376   //   theNewIntervalH.setVersStatus( oocNoVers );
05377   //
05378   // With more efficient functional equivalent.
05379   //
05380   //    NOTE: a) The newly created interval would automatically
05381   //             get "oocNoVers" status.
05382   //          b) The versioning status of the old interval must be maintained
05383   //             by the callers code, since this is out of scope of this
05384   //             method's code.
05385 
05386     theNewIntervalH = new( theOldIntervalH ) BdbIntervalR( theOldIntervalH->getObject( ),
05387                                                            theOldIntervalH->getBeginTime( ),
05388                                                            theOldIntervalH->getEndTime( ),
05389                                                            theOldIntervalH->getTag( ));
05390     theOldIntervalH->add_nextVers( theNewIntervalH );
05391 }
05392 
05393 
05394 void
05395 BdbDatabase::createRevisedTopVersion( const BdbHandle(BdbIntervalR)& theOldIntervalH,
05396                                       BdbHandle(BdbIntervalR)&       theNewIntervalH )
05397 {
05398 
05399   // Create new version as usual.
05400 
05401     createVersion( theOldIntervalH, theNewIntervalH );
05402 
05403   // Connect interval to a revision (which may be empty of course).
05404 
05405     theNewIntervalH->setRevision( reviseAfterStoreRevisionH( ));
05406 }
05407 
05408 
05409 void 
05410 BdbDatabase::nameVersion( const BdbHandle(BdbInterval)& theOriginalIntervalH,
05411                           const BdbHandle(BdbInterval)& theIntervalH )
05412 {
05413     BdbHandle(BdbIntervalGene) theGeneH;
05414     string                  theOriginalIntervalName;
05415 
05416   // Get the Genealogy object and a previous version name.
05417   // Name the original (BASELINE) interval if required.
05418 
05419     if ( theOriginalIntervalH->exist_geneObj( )) {
05420 
05421       // Reuse already existing Genealogy object.
05422 
05423         theGeneH = (const BdbHandle(BdbIntervalGene)&) theOriginalIntervalH->geneObj( );
05424         theOriginalIntervalName = string( theGeneH->getVersionName( ));
05425 
05426     } else {
05427 
05428       // Get the cached container handle. We will use it as a clustering hint
05429       // for the newely created Genealogy object.
05430 
05431         BdbHandle(BdbContObj) theIntervalContH;
05432         getIntervalContH( theIntervalContH );
05433 
05434       // Create a genealogy object.
05435 
05436         theGeneH = new( theIntervalContH ) BdbIntervalGene( );
05437 
05438         theGeneH->set_defaultVers( theOriginalIntervalH );
05439         theGeneH->add_allVers( theOriginalIntervalH );
05440       
05441         theOriginalIntervalName = string( theGeneH->getVersionName( ));
05442         theOriginalIntervalH.nameObj( theGeneH, theOriginalIntervalName.c_str() );
05443     }
05444 
05445   // Add new interval to the genealogy.
05446 
05447     theGeneH->add_allVers( theIntervalH );
05448 
05449   // Increment the version number and name the new version.
05450 
05451     char* theNewIntervalName = upDateVersionName( theOriginalIntervalName.c_str() );
05452 
05453     theIntervalH.nameObj( theGeneH, theNewIntervalName );
05454     theGeneH->setVersionName( theNewIntervalName );
05455 
05456     delete [] theNewIntervalName;
05457 }
05458 
05459 char*
05460 BdbDatabase::upDateVersionName( const char* oldName ) const
05461 {
05462 
05463   //-----------------------------------------------------------------------------
05464   //
05465   //   This function takes the current version name and returns
05466   //   the name for the next version.
05467   //
05468   //   Input:  char* oldName    : the name of the present version
05469   //
05470   //   Output: char* newName    : the name of the next version
05471   //
05472   //   The version name is assumed to have the form sd
05473   //   where s denotes a string of alphabetic characters
05474   //   and d denotes a string of numerical characters.
05475   //
05476   //   Example:
05477   //             if   char* oldName = "V1"
05478   //             then char* newName = "V2"
05479   //
05480   //-----------------------------------------------------------------------------
05481 
05482     assert( NULL != oldName );
05483 
05484     char* theName = new char[ strlen(oldName) + 1 ];
05485     strcpy( theName, oldName );
05486 
05487   // Decompose theName as theName = prefixName + theDigits 
05488 
05489   // Get theDigits
05490 
05491     char* str = strpbrk( theName, "0123456789" );
05492     if ( str == (char*) 0 ) {
05493 
05494         ErrMsg(warning) << "BdbDatabase::upDateVersionName() -- warning." << endl
05495                         << "    Version name has no digits, use " << Zero << " as default digits" << endmsg;
05496 
05497         str = new char[ strlen( Zero ) + 1 ];
05498         strcpy( str, Zero );
05499     }
05500 
05501     char* theDigits = new char[ strlen(str) + 1 ];
05502     strcpy( theDigits, str );
05503 
05504   // Get prefixName
05505 
05506     str = strtok( theName, "0123456789" );
05507     char* prefixName = new char[ strlen(str) + 1 ];
05508     strcpy( prefixName, str );
05509 
05510   // Convert char digits to int digits
05511 
05512     int intDigits = atoi( theDigits ); 
05513     intDigits++;
05514 
05515   // Convert int digits to char digits
05516 
05517     char string[16];
05518     sprintf( string, "%i", intDigits );
05519 
05520     char* newDigits = new char[ strlen( string ) + 1 ];
05521     strcpy( newDigits, string );
05522     
05523   // Put the pieces back together
05524 
05525     char* newName = new char[  strlen( prefixName ) + strlen( newDigits ) + 1 ];
05526     strcpy( newName, prefixName );
05527     strcat( newName, newDigits  );
05528 
05529     delete [] theName;
05530     delete [] theDigits;
05531     delete [] prefixName;
05532     delete [] newDigits;
05533 
05534     return newName;
05535 }
05536 
05537 int
05538 BdbDatabase::verticalCompare( const BdbHandle(BdbInterval)& theLeftIntervalH,
05539                               const BdbHandle(BdbInterval)& theRightIntervalH )
05540 {
05541     BdbHandle(BdbInterval) thePrevIntervalH;
05542     BdbHandle(BdbInterval) thePrevPrevIntervalH;
05543 
05544     assert( ! BdbIsNull(theLeftIntervalH));
05545     assert( ! BdbIsNull(theRightIntervalH));
05546 
05547   // 0: The same interval.
05548 
05549     if ( theLeftIntervalH == theRightIntervalH ) {
05550         return 0;
05551     }
05552 
05553   // 0: Intervals from different trees.
05554 
05555     if ( ! ( theLeftIntervalH->inInterval( *theRightIntervalH ) ||
05556              theRightIntervalH->inInterval( *theLeftIntervalH ))) {
05557         return 0;
05558     }
05559 
05560   // -1: The left interval is lower (closer to a baseline one)
05561   //     then the right one.
05562 
05563     theRightIntervalH->prevVers( thePrevIntervalH );
05564     while( ! BdbIsNull(thePrevIntervalH)) {
05565 
05566         if ( thePrevIntervalH == theLeftIntervalH ) {
05567             return -1;
05568         }
05569         
05570         thePrevIntervalH->prevVers( thePrevPrevIntervalH );
05571         thePrevIntervalH = thePrevPrevIntervalH;
05572     }
05573 
05574   // 1: The left interval is upper than the right one.
05575 
05576     theLeftIntervalH->prevVers( thePrevIntervalH );
05577     while( ! BdbIsNull(thePrevIntervalH)) {
05578 
05579         if ( thePrevIntervalH == theRightIntervalH ) {
05580             return 1;
05581         }
05582         
05583         thePrevIntervalH->prevVers( thePrevPrevIntervalH );
05584         thePrevIntervalH = thePrevPrevIntervalH;
05585     }
05586 
05587   // 0: The database structure has been corrupted or there is an attempt
05588   //    to compare intervals from different containers.
05589 
05590     return 0;
05591 }
05592 
05593 BdbStatus
05594 BdbDatabase::verifyIntervals( vector<BdbHandle(BdbInterval)>& theList,
05595                               const char*                                  theContainerName,
05596                               d_ULong                                      theRevisionId )
05597 {
05598     const char* errorString = "BdbDatabase::verifyIntervals() -- ERROR.";
05599 
05600     BdbStatus status;
05601 
05602   // Perform the following action in an exception-like loop.
05603 
05604     bool theOuterLoopFailed = true;
05605 
05606     while( true ) {
05607 
05608       // Find specified container. Reload cache if nessesary.
05609 
05610         BdbHandle(BdbContObj) intervalContH;
05611 
05612         status = findIntervalCont( intervalContH, theContainerName );
05613         if (( BdbcSuccess != status ) || BdbIsNull(intervalContH)) {
05614             ErrMsg(error) << errorString << endl
05615                           << "    Failed to locate specified interval container." << endmsg;
05616             break;
05617         }
05618 
05619       // Load the FIRST and LAST intervals.
05620 
05621         BdbHandle(BdbInterval) theFirstIntervalH;
05622 
05623         status = firstInterval( theFirstIntervalH, theContainerName );
05624         if ( BdbcSuccess != status ) return status;
05625 
05626         BdbHandle(BdbInterval) theLastIntervalH;
05627 
05628         status = lastInterval( theLastIntervalH, theContainerName );
05629         if ( BdbcSuccess != status ) return status;
05630 
05631       // Perform a quality checking of the intervals in the list.
05632       //
05633       //   1. Check if all intervals in the list belong to specified container.
05634       //   2. Check for the class of elements (we expect BdbIntervalR).
05635       //   3. Check that elements do not correspond neither FIRST nor LAST intervals.
05636       //   4. Check if there is not "revision duplicates" on the vertical stack of intervals
05637       //   5. Check if there is not "revision duplicates" between in supplied intervals
05638       //      list by checking "previous-next" dependancies between them.
05639 
05640         bool theInnerLoopFailed = false;
05641 
05642         for( int i = 0; i < theList.size( ); i++ ) {
05643 
05644           // - - - -
05645           // Test: 1
05646           // - - - -
05647  
05648             if( intervalContH != theList[i].containedIn( )) {
05649                 ErrMsg(error) << errorString << endl
05650                               << "    A wrong interval handle is found in the list." << endl
05651                               << "    The interval does not belong to the container: " << theContainerName << endl
05652                               << "    Element of theList[" << i << "] = " << getOID( theList[i] ) << endmsg;
05653                 theInnerLoopFailed = true;
05654                 break;
05655             }
05656 
05657           // - - - -
05658           // Test: 2
05659           // - - - -
05660 
05661             if( ooTypeN( BdbIntervalR ) != theList[i].typeN( )) {
05662                 ErrMsg(error) << errorString << endl
05663                               << "    A wrong interval handle is found in the list." << endl
05664                               << "    The interval has unexpected class \"" << theList[i].typeName( ) << "\"" << endl
05665                               << "    instead of \"BdbIntervalR\"" << endl
05666                               << "    Element of theList[" << i << "] = " << getOID( theList[i] ) << endmsg;
05667                 theInnerLoopFailed = true;
05668                 break;
05669             }
05670 
05671           // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
05672           // Test: 3: check that elements do not correspond neither FIRST nor LAST intervals
05673           // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
05674 
05675             if( theFirstIntervalH == theList[i]) {
05676                 ErrMsg(error) << errorString << endl
05677                               << "    The FIRST interval is found in the list." << endl
05678                               << "    Operation is not allowed for this interval." << endl
05679                               << "    Element of theList[" << i << "] = " << getOID( theList[i] ) << endmsg;
05680                 theInnerLoopFailed = true;
05681                 break;
05682             }
05683 
05684             if( theLastIntervalH == theList[i]) {
05685                 ErrMsg(error) << errorString << endl
05686                               << "    The LAST interval is found in the list." << endl
05687                               << "    Operation is not allowed for this interval." << endl
05688                               << "    Element of theList[" << i << "] = " << getOID( theList[i] ) << endmsg;
05689                 theInnerLoopFailed = true;
05690                 break;
05691             }
05692 
05693           // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
05694           // Test: 4: locate revision duplicate(s) on the same vertical stack
05695           // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
05696 
05697             vector<BdbHandle(BdbIntervalR)> theIntervalVector;
05698 
05699             status = getRevisedIntervalsInSubTree( theIntervalVector,
05700                                                    (const BdbHandle(BdbIntervalR)&) theList[i],
05701                                                    theRevisionId );
05702             if( BdbcSuccess != status ) {
05703                 return status;
05704             }
05705 
05706             if( theIntervalVector.size( )) {
05707                 ErrMsg(error) << errorString << endl
05708                               << "    An interval(s) from the same revision were found in the vertical" << endl
05709                               << "    hierarchy of versions. Including another interval into the same" << endl
05710                               << "    revision will create ambiguity." << endl
05711                               << "    Element of theList[" << i << "] = " << getOID( theList[i] ) << endmsg;
05712                 theInnerLoopFailed = true;
05713                 break;
05714             }
05715 
05716           // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
05717           //   5. Check if there is not "revision duplicates" between in supplied intervals
05718           //      list by checking "previous-next" dependancies between them.
05719           // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
05720 
05721             vector<BdbHandle(BdbInterval)> theBoundIntervalsVector;
05722 
05723             status = getBoundIntervalsInSubTree( theBoundIntervalsVector,
05724                                                  theList,
05725                                                  theList[i] );
05726             if( BdbcSuccess != status ) {
05727                 return status;
05728             }
05729 
05730             if( theBoundIntervalsVector.size( )) {
05731                 ErrMsg(error) << errorString << endl
05732                               << "    The interval(s) from the same vertical hierarchy of versions" << endl
05733                               << "    willing to go into the same revision were found in the input list." << endl
05734                               << "    Including these intervals into the same revision will create ambiguity." << endl
05735                               << "    Element of theList[" << i << "] = " << getOID( theList[i] ) << endmsg;
05736                 theInnerLoopFailed = true;
05737                 break;
05738             }
05739 
05740         }
05741 
05742         theOuterLoopFailed = theInnerLoopFailed;
05743         break;
05744     }
05745     if ( theOuterLoopFailed ) {
05746 
05747         ErrMsg(error) << "    DETECTOR  -> " << subsystemTLA( ) << endl
05748                       << "    CONTAINER -> " << theContainerName << endmsg;
05749         return BdbcError;
05750     }
05751 
05752     return BdbcSuccess;
05753 }
05754 
05755 void
05756 BdbDatabase::includeIntoRevision( vector<BdbHandle(BdbInterval)>& theList,
05757                                   const BdbHandle(BdbCondRevision)&            theRevisionH )
05758 {
05759 
05760   // Go through the list and set a proper revision for the elements.
05761   // This algorithm has two different inplementations depending on wheather
05762   // an interval is or is not a member of a revision.
05763   //
05764   //   1. If it's not - just include it into a revision.
05765   //   2. If it's a member - then put a version of this interval
05766   //      on a top of the stack. This is based on using of an extended
05767   //      versioning algorithm which accepts a revision handle and
05768   //      specific versioning time.
05769   //
05770   //        NOTE:   If the interval is already a member of specified
05771   //                revision -- then nothing to do.
05772   //
05773   // This algorithm will also ignore any duplicates in the input list.
05774   // A duplicate is an interval which is met twice or more times in the list.
05775 
05776 
05777     int entries = theList.size( );
05778 
05779     for( int i = 0; i < entries; i++ ) {
05780 
05781         BdbHandle(BdbIntervalR) theIntervalH;
05782         theIntervalH = (BdbHandle(BdbIntervalR)&) theList[i];
05783 
05784       // Ignore duplicates
05785 
05786         bool aDuplicateFound = false;
05787 
05788         for( int j = 0; j < i; j++ ) {
05789             if( theList[j] == theList[i] ) {
05790                 aDuplicateFound = true;
05791                 break;
05792             }
05793         }
05794         if( aDuplicateFound ) {
05795             continue;
05796         }
05797 
05798       // Go further...
05799 
05800         BdbHandle(BdbCondRevision) theOldRevisionH;
05801         theIntervalH->getRevision( theOldRevisionH );
05802 
05803         if( BdbIsNull( theOldRevisionH )) {
05804             theIntervalH->setRevision( theRevisionH );
05805         } else {
05806 
05807             if( theRevisionH != theOldRevisionH ) {
05808  
05809                 version( theRevisionH,
05810                          theIntervalH->getObject( ),
05811                          theIntervalH->getBeginTime( ),
05812                          theIntervalH->getEndTime( ),
05813                          theIntervalH->getTag( ),
05814                          theIntervalH->getVersionTime( ));
05815             }
05816         }
05817     }
05818 
05819     return;
05820 }
05821 
05822 BdbStatus
05823 BdbDatabase::getRevisionStack( vector<d_ULong>& theRevisionStack,
05824                                d_ULong                       theRevisionId )
05825 {
05826   // Reset a stack
05827 
05828     theRevisionStack.clear( );
05829 
05830   // Get a cached handle for REgistry.
05831 
05832     BdbHandle(BdbCondRegistry) registryH;
05833     getRegistryH( registryH );
05834 
05835   // Locate a persistent record for specified revision
05836 
05837     BdbItr(BdbCondRevision)    theRevisionItr;
05838     BdbHandle(BdbCondRevision) theRevisionH;
05839 
05840     registryH->setRevisionItr( theRevisionItr );
05841 
05842     bool revisionIsFound = false;
05843 
05844     while ( theRevisionItr.next( )) {
05845         if ( theRevisionId == theRevisionItr->id( )) {
05846 
05847             theRevisionH = theRevisionItr;
05848             revisionIsFound = true;
05849 
05850             break;
05851         }
05852     }
05853     if ( ! revisionIsFound ) {
05854 
05855         ErrMsg(error) << "BdbDatabase::getRevisionStack() -- error." << endl
05856                       << "    Specified revision was not found." << endmsg;
05857 
05858         return BdbcError;
05859     }
05860 
05861   // Put specified revision itself onto the top of the stack
05862 
05863     theRevisionStack.push_back( theRevisionId );
05864 
05865   // Traverse through "base" revisions path of this particular
05866   // revision and all their base revisions and record the corresponding
05867   // revisions id-s into supplied stack object.
05868 
05869     BdbHandle(BdbCondRevision) theBaseRevisionH;
05870 
05871     theRevisionH->getBaseRevision( theBaseRevisionH );
05872 
05873     while ( ! BdbIsNull( theBaseRevisionH )) {
05874 
05875         theRevisionH = theBaseRevisionH;
05876 
05877         theRevisionStack.push_back( theRevisionH->id( ));
05878 
05879         theRevisionH->getBaseRevision( theBaseRevisionH );
05880     }
05881 
05882     return BdbcSuccess;
05883 }
05884 
05885 // -----------------------------------------------------------------------
05886 // ***********************************************************************
05887 //
05888 // ::getRevisedIntervalsInSubTree()
05889 //
05890 //      DESCRIPTION:
05891 //
05892 //          Locate all possible intervals belonging to specified revision
05893 //          in a versioning sub-tree.
05894 //
05895 //          The sub-tree includes specified interval, a list of previous
05896 //          intervals, and a sub-tree of the next intervals.
05897 //
05898 //      PARAMETERS:
05899 //
05900 //          theIntervalVector   a list of intervals matching specified
05901 //                              revision is returned here. Has 0 entries
05902 //                              if nothing were found.
05903 //                              The order of entries in the list is not
05904 //                              defined.
05905 //
05906 //          theIntervalH        an interval which specifies a start point
05907 //                              in the sub-tree.
05908 //
05909 //          theRevisionId       a revision ID to look for.
05910 //
05911 //      RETURN:
05912 //
05913 //          BdbcSuccess     means success, even if nothing were found.
05914 //
05915 //          BdbcError       means any error. The vector will contain
05916 //                          entries which were successfully found before
05917 //                          an error had occured.
05918 //
05919 // ***********************************************************************
05920 // -----------------------------------------------------------------------
05921 
05922 BdbStatus
05923 BdbDatabase::getRevisedIntervalsInSubTree( vector<BdbHandle(BdbIntervalR)>&  theIntervalVector,
05924                                            const BdbHandle(BdbIntervalR)&                 theIntervalH,
05925                                            d_ULong                                        theRevisionId )
05926 {
05927     BdbStatus status = BdbcError;
05928 
05929   // Reset a stack
05930 
05931     theIntervalVector.clear( );
05932 
05933   // Traverse a list of previous intervals.
05934 
05935     BdbHandle(BdbIntervalR)    thePrevPrevIntervalH;
05936     BdbHandle(BdbIntervalR)    thePrevIntervalH;
05937     BdbHandle(BdbCondRevision) theRevisionH;
05938 
05939     theIntervalH->prevVers( thePrevIntervalH );
05940     while( ! BdbIsNull(thePrevIntervalH)) {
05941 
05942       // Check revision ID of the next interval.
05943 
05944         thePrevIntervalH->getRevision( theRevisionH );
05945 
05946         if( ! BdbIsNull(theRevisionH)) {
05947             if( theRevisionId == theRevisionH->id( )) {
05948                 theIntervalVector.push_back( thePrevIntervalH );
05949             }
05950         }
05951 
05952       // Go deeper to the next previous version.
05953 
05954         thePrevIntervalH->prevVers( thePrevPrevIntervalH );
05955         thePrevIntervalH = thePrevPrevIntervalH;
05956     }
05957 
05958   // Traverse a tree of next intervals.
05959   // This is recursive algorithm.
05960 
05961     status = getNextRevisedIntervals( theIntervalVector,
05962                                       theIntervalH,
05963                                       theRevisionId );
05964     if( BdbcSuccess != status ) {
05965         return status;
05966     }
05967 
05968     return BdbcSuccess;
05969 }
05970 
05971 // -----------------------------------------------------------------------
05972 // ***********************************************************************
05973 //
05974 // ::getBoundIntervalsInSubTree()
05975 //
05976 //      DESCRIPTION:
05977 //
05978 //          Check the if specified interval has any "bound" intervals
05979 //          in a specified list of intervals.
05980 //
05981 //          "Bound intervals" are those intervals that are in the same
05982 //          vertical versioning tree.
05983 //
05984 //          This checking is always done from the "top-most" to
05985 //          the "bottom-most" interval in two
05986 //          passes. I the first path the check is done for a specified
05987 //          interval agains every element in the list. In the second
05988 //          path the check is done for each list's elemen against
05989 //          the specified interval.
05990 //
05991 //
05992 //      PARAMETERS:
05993 //
05994 //          theIntervalVector   a list of intervals being bound to
05995 //                              specified interval is returned here.
05996 //                              The list has 0 entries if nothing were found.
05997 //                              The order of entries in the list is not
05998 //                              defined.
05999 //
06000 //          theList             a list of intervals to be checked.
06001 //
06002 //          theIntervalH        an interval which is ment to be checked
06003 //                              against a specified list of intervals.
06004 //
06005 //      RETURN:
06006 //
06007 //          BdbcSuccess     means success, even if nothing were found.
06008 //
06009 //          BdbcError       means any error. The vector will contain
06010 //                          entries which were successfully found before
06011 //                          an error had occured.
06012 //
06013 // ***********************************************************************
06014 // -----------------------------------------------------------------------
06015 
06016 BdbStatus
06017 BdbDatabase::getBoundIntervalsInSubTree( vector<BdbHandle(BdbInterval)>&       theIntervalVector,
06018                                          const vector<BdbHandle(BdbInterval)>& theList,
06019                                          const BdbHandle(BdbInterval)&                      theIntervalH )
06020 {
06021     BdbStatus status = BdbcError;
06022     int i;
06023     int numEntries = theList.size( );
06024 
06025   // Reset a stack
06026 
06027     theIntervalVector.clear( );
06028 
06029   // PATH I: Check all the "previous" intervals of the specified
06030   //         interval against all elements in the list.
06031 
06032     BdbHandle(BdbInterval) thePrevPrevIntervalH;
06033     BdbHandle(BdbInterval) thePrevIntervalH;
06034 
06035     theIntervalH->prevVers( thePrevIntervalH );
06036     while( ! BdbIsNull(thePrevIntervalH)) {
06037 
06038         for( i = 0; i < numEntries; i++ ) {
06039             if( thePrevIntervalH == theList[i] ) {
06040                 theIntervalVector.push_back( theList[i] );
06041             }
06042         }
06043 
06044       // Go deeper to the next previous version.
06045 
06046         thePrevIntervalH->prevVers( thePrevPrevIntervalH );
06047         thePrevIntervalH = thePrevPrevIntervalH;
06048     }
06049 
06050   // PATH II: Check all the "previous" intervals of each interval from
06051   //          the input list against the specified interval.
06052 
06053     for( i = 0; i < numEntries; i++ ) {
06054 
06055         theList[i]->prevVers( thePrevIntervalH );
06056         while( ! BdbIsNull(thePrevIntervalH)) {
06057             if( thePrevIntervalH == theIntervalH ) {
06058                 theIntervalVector.push_back( theList[i] );
06059             }
06060 
06061           // Go deeper to the next previous version.
06062 
06063             thePrevIntervalH->prevVers( thePrevPrevIntervalH );
06064             thePrevIntervalH = thePrevPrevIntervalH;
06065         }
06066     }
06067 
06068     return BdbcSuccess;
06069 }
06070 
06071 // -----------------------------------------------------------------------
06072 // ***********************************************************************
06073 //
06074 // ::getNextRevisedIntervals()
06075 //
06076 //      DESCRIPTION:
06077 //
06078 //          Locate all possible intervals belonging to specified revision
06079 //          in higher versions above specified interval.
06080 //
06081 //          The newly found intervals are appended to the vector.
06082 //
06083 //          This is recursive algorithm.
06084 //
06085 //      PARAMETERS:
06086 //
06087 //          theIntervalVector   a list of intervals matching specified
06088 //                              revision is returned here. Has 0 entries
06089 //                              if nothing were found.
06090 //                              The order of entries in the list is not
06091 //                              defined.
06092 //
06093 //          theIntervalH        an interval which specifies a start point
06094 //                              to locate version.
06095 //
06096 //          theRevisionId       a revision ID to look for.
06097 //
06098 //      RETURN:
06099 //
06100 //          BdbcSuccess     means success, even if nothing were found.
06101 //
06102 //          BdbcError       means any error. The vector will contain
06103 //                          entries which were successfully found before
06104 //                          an error had occured.
06105 //
06106 // ***********************************************************************
06107 // -----------------------------------------------------------------------
06108 
06109 BdbStatus
06110 BdbDatabase::getNextRevisedIntervals( vector<BdbHandle(BdbIntervalR)>& theIntervalVector,
06111                                       const BdbHandle(BdbIntervalR)&                theIntervalH,
06112                                       d_ULong                                       theRevisionId )
06113 {
06114     BdbStatus status = BdbcError;
06115 
06116     BdbHandle(BdbIntervalR)    theNextIntervalH;
06117     BdbItr(BdbPersObj)         nextItr;
06118     BdbHandle(BdbCondRevision) theRevisionH;
06119 
06120     theIntervalH->nextVers( nextItr );
06121     while( nextItr.next( )) {
06122 
06123       // Check revision ID of the next interval.
06124 
06125         theNextIntervalH = (BdbHandle(BdbIntervalR)&) nextItr;
06126         theNextIntervalH->getRevision( theRevisionH );
06127 
06128         if( ! BdbIsNull(theRevisionH)) {
06129             if( theRevisionId == theRevisionH->id( )) {
06130                 theIntervalVector.push_back( theNextIntervalH );
06131             }
06132         }
06133 
06134       // Check all the next versions (if any) of this interval.
06135 
06136         status = getNextRevisedIntervals( theIntervalVector,
06137                                           theNextIntervalH,
06138                                           theRevisionId );
06139         if( BdbcSuccess != status ) {
06140             return status;
06141         }
06142     }
06143 
06144     return BdbcSuccess;
06145 }
06146 
06147 // -----------------------------------------------------------------------
06148 // ***********************************************************************
06149 //
06150 // ::sortIntervalsList()
06151 //
06152 //      DESCRIPTION:
06153 //
06154 //          Sorts the intervals "in place" according to their
06155 //          version. The interval with the lowest version comes first.
06156 //
06157 //      PARAMETERS:
06158 //
06159 //          theList     a list of intervals to be sorted.
06160 //
06161 //      RETURN:
06162 //
06163 //          BdbcSuccess     when done.
06164 //          BdbcError       when a "circular" dependancy is met in the
06165 //                          versions tree. Means a fatal error.
06166 //
06167 // ***********************************************************************
06168 // -----------------------------------------------------------------------
06169 
06170 BdbStatus
06171 BdbDatabase::sortIntervalsList( vector<BdbHandle(BdbInterval)>& theList )
06172 {
06173     vector<BdbHandle(BdbInterval)> theTmpList;
06174     BdbHandle(BdbInterval) theIntervalH;
06175     BdbHandle(BdbInterval) thePrevIntervalH;
06176 
06177   // The algorithm of finding the "bottom-most" element in the list
06178   // is repeaed as meny times as many elements in the original list.
06179 
06180     int originalNumber = theList.size( );
06181  
06182     for( int i = 0; i < originalNumber; i++ ) {
06183 
06184       // Locate an element which is the "bottom-most" in the list.
06185       // The "found" variable is used to eascape further searching when
06186       // such a "bottom" element is found.
06187 
06188         bool found = false;
06189         int  currentNumber = theList.size( );
06190 
06191         for( int j = 0; j < currentNumber; j++ ) {
06192 
06193           // Check if the current indexed interval has not any of
06194           // other intervals in the list in the "previous" dependency list.
06195           // When we found such an interval then 
06196 
06197             bool hasDependents = false;
06198 
06199             theIntervalH = theList[j];
06200             theIntervalH->prevVers( thePrevIntervalH );
06201 
06202             while( ! BdbIsNull(thePrevIntervalH)) {
06203 
06204               // Find dependents in the whole list except ourself.
06205 
06206                 for( int k = 0; k < currentNumber; k++ ) {
06207                     if( thePrevIntervalH == theList[k] ) {
06208                         if( j != k ) {
06209                             hasDependents = true;
06210                             break;
06211                         }
06212                     }
06213                 }
06214 
06215               // Well. The attempt faild -- this is not the "bottom-most"
06216               // element -- will continue searching.
06217 
06218                 if( hasDependents ) {
06219                     break;
06220                 }
06221 
06222               // Go one step down to the next previous interval.
06223 
06224                 theIntervalH = thePrevIntervalH;
06225                 theIntervalH->prevVers( thePrevIntervalH );
06226             }
06227 
06228           // If current indexed element does not have any dependents
06229           // the (1) include into another list and (2) exclude it from
06230           // the original list.
06231 
06232             if( ! hasDependents ) {
06233                 theTmpList.push_back( theList[j] );
06234                 theList.erase(std::find(theList.begin(),theList.end(),theList[j]));
06235                 found = true;
06236                 break;
06237             }
06238         }
06239 
06240       // Absence of the "bottom-most" element means a circular
06241       // dependency between the elements.
06242 
06243         if( ! found ) {
06244             ErrMsg(error) << "BdbDatabase::sortIntervalsList() -- ERROR." << endl
06245                           << "    The circular dependency has been detected between versions" << endl
06246                           << "    in the same interval tree." << endl
06247                           << "    A persistent container might be badly corrupted." << endl
06248                           << "        DETECTOR  -> " << subsystemTLA( ) << endl
06249                           << "        CONTAINER -> " << containerName( ) << endmsg;
06250             return BdbcError;
06251         }
06252     }
06253 
06254   // Here we expect the original list to be empty. If not -- there is
06255   // something wrong, either with the algorithm itself or with the persistent
06256   // data structures.
06257 
06258     if( theList.size( )) {
06259         ErrMsg(error) << "BdbDatabase::sortIntervalsList() -- ERROR." << endl
06260                       << "    The sorting algorithm failed for internal error." << endl
06261                       << "    A persistent container might be corrupted." << endl
06262                       << "        DETECTOR  -> " << subsystemTLA( ) << endl
06263                       << "        CONTAINER -> " << containerName( ) << endmsg;
06264         return BdbcError;
06265     }
06266 
06267   // Just make a copy of the temporary vector to the input (now empty)
06268   // vector.
06269 
06270     theList = theTmpList;
06271 
06272     return BdbcSuccess;
06273 }
06274 
06275 const char*
06276 BdbDatabase::getOID( const BdbHandle(BdbPersObj)& thePersObjH )
06277 {
06278     static char buf[255];
06279 
06280     ooId id = thePersObjH;
06281     
06282     int db   = id.get_DB();
06283     int cont = id.get_OC();
06284     int page = id.get_page();
06285     int slot = id.get_slot();
06286     
06287     sprintf( buf, "#%d-%d-%d-%d", db, cont, page, slot );
06288 
06289     return buf;
06290 }
06291 
06292 /** This function is ment to reset the internal cache of the current object
06293  ** when a base class resets their local cache.
06294  **/
06295 
06296 void
06297 BdbDatabase::resetCacheHandler( )
06298 {
06299     _intervalCacheH = 0;
06300 }
06301 
06302 void
06303 BdbDatabase::setIntervalCache( const BdbHandle(BdbInterval)& theIntervalH )
06304 {
06305     _intervalCacheH = theIntervalH;
06306 }
06307 
06308 BdbStatus
06309 BdbDatabase::splitBaselineInterval( BdbHandle(BdbIntervalR)& theOldIntervalH,
06310                                     const BdbTime&           theTime )
06311 {
06312     const char* errorString = "BdbDatabase::splitBaselineInterval() -- ERROR.";
06313 
06314     BdbStatus status;
06315 
06316   // Now we will split the baseline interval. This procedure would be different for
06317   // the FIRST, LAST, an interval in the middle, and the ONLY interval.
06318 
06319     BdbHandle(BdbIntervalR) theNewIntervalH;
06320 
06321     BdbHandle(BdbIntervalR) theTopNextIntervalH;
06322     BdbHandle(BdbIntervalR) theBaselineNextIntervalH;
06323 
06324     theOldIntervalH->getTopNext( theTopNextIntervalH );
06325     theOldIntervalH->getBaselineNext( theBaselineNextIntervalH );
06326 
06327   // Create the new interval on the right side of the existing interval.
06328 
06329     theNewIntervalH = new( theOldIntervalH ) BdbIntervalR( theOldIntervalH->getObject( ),
06330                                                            theTime,
06331                                                            theOldIntervalH->getEndTime( ),
06332                                                            theOldIntervalH->getTag( ));
06333     theOldIntervalH->setEndTime( theTime );
06334 
06335   // Tune the links
06336 
06337     theOldIntervalH->setTopNext( theNewIntervalH );
06338     theOldIntervalH->setBaselineNext( theNewIntervalH );
06339 
06340     theNewIntervalH->setTopPrevious( theOldIntervalH );
06341     theNewIntervalH->setBaselinePrevious( theOldIntervalH );
06342 
06343     theNewIntervalH->setTopNext( theTopNextIntervalH );
06344     theNewIntervalH->setBaselineNext( theBaselineNextIntervalH );
06345 
06346     if ( ! BdbIsNull(theTopNextIntervalH)) {
06347         theTopNextIntervalH->setTopPrevious( theNewIntervalH );
06348     }
06349     if ( ! BdbIsNull(theBaselineNextIntervalH)) {
06350         theBaselineNextIntervalH->setBaselinePrevious( theNewIntervalH );
06351     }
06352 
06353   // Special tuning for the last interval - set its name in
06354   // in the container scope.
06355 
06356     BdbHandle(BdbContObj) intervalContH;
06357     getIntervalContH( intervalContH );
06358 
06359     if ( BdbTime::plusInfinity == theNewIntervalH->getEndTime( )) {
06360         theOldIntervalH.unnameObj( intervalContH );
06361         theNewIntervalH.nameObj( intervalContH, "LastInterval" );
06362     }
06363 
06364   // And finally we make some commont settings to the newely created interval.
06365 
06366     theNewIntervalH->setVersionTime( theOldIntervalH->getVersionTime( ));
06367 
06368     BdbHandle(BdbCondRevision) theRevisionH;
06369     theOldIntervalH->getRevision( theRevisionH );
06370     theNewIntervalH->setRevision( theRevisionH );
06371 
06372     return BdbcSuccess;
06373 }
06374 
06375 BdbStatus
06376 BdbDatabase::splitIntervalsTree( const char*              theContainerName,
06377                                  BdbHandle(BdbIntervalR)& theOldIntervalH,
06378                                  const BdbTime&           theTime )
06379 {
06380     const char* errorString = "BdbDatabase::splitIntervalsTree() -- ERROR.";
06381 
06382     BdbStatus status;
06383 
06384     BdbHandle(BdbIntervalR) theLeftBaselineIntervalH;
06385     BdbHandle(BdbIntervalR) theRightBaselineIntervalH;
06386 
06387   // Get the adjacent topmost interval ("DesiredH") left to the beginning
06388   // of the current old interval ("theOldIntervalH"). Since the current old interval
06389   // is the baseline one then we will locate desired interval via the "IntermediateTopH"
06390   // interval at the beginning of the current baseline interval.
06391   //
06392   //                  ............................................
06393   //                  :                                          :
06394   //          (3:getTopPrevious)                                 :
06395   //                  :            +-----------------            :
06396   //                  V            | theTopIntervalH   (2:getTopmostInterval)
06397   //      -------------------------+-----------------            :
06398   //       theTopPreviousIntervalH | - - -                       :
06399   // ------------------------------+------------------           :
06400   //                - - -          | theOldIntervalH             :
06401   // ------------------------------+------------------           :
06402   //                               V                             :
06403   //                               :                             :
06404   //                       (1:getBeginTime())                    :
06405   //                               :                             :
06406   //                               ...............................
06407   //
06408   // NOTE: This procedure should be called before any other new intervals
06409   //       are created in the container. The problem is with Objectivity's
06410   //       indexing. This index knows nothing about our intentions.
06411 
06412     BdbHandle(BdbIntervalR) theTopPreviousIntervalH;
06413     BdbHandle(BdbIntervalR) theTopIntervalH;
06414 
06415     status = getTopmostInterval( theTopIntervalH,
06416                                  theContainerName,
06417                                  theOldIntervalH->getBeginTime( ));
06418     if( BdbcSuccess != status ) {
06419         ErrMsg(error) << errorString << endl
06420                       << "    Failed to locate a topmost interval interval at: " << theOldIntervalH->getBeginTime( ) << endl
06421                       << "        DETECTOR  -> " << subsystemTLA( ) << endl
06422                       << "        CONTAINER -> " << theContainerName << endmsg;
06423         return BdbcError;
06424     }
06425     theTopIntervalH->getTopPrevious( theTopPreviousIntervalH );
06426 
06427   // Get adjucent baseline intervals for the old interval.
06428 
06429     BdbHandle(BdbIntervalR) theBaselinePreviousIntervalH;
06430     BdbHandle(BdbIntervalR) theBaselineNextIntervalH;
06431 
06432     theOldIntervalH->getBaselinePrevious( theBaselinePreviousIntervalH );
06433     theOldIntervalH->getBaselineNext( theBaselineNextIntervalH );
06434 
06435   // Get baseline revision.
06436 
06437     BdbHandle(BdbCondRevision) theRevisionH;
06438 
06439     theOldIntervalH->getRevision( theRevisionH );
06440 
06441   // Split the specified old interval into two copies. Connect these copies
06442   // to each other in a regular way as two sequential baseline intervals.
06443   //
06444   // NOTE: We do not delete the old interval and its version tree and its
06445   //       genealogy object because we will use this stuff to produce
06446   //       the left and right sub-trees under the newely created intervals.
06447 
06448   // Previous<->Left...
06449 
06450     theLeftBaselineIntervalH = new( theOldIntervalH ) BdbIntervalR( theOldIntervalH->getObject( ),
06451                                                                     theOldIntervalH->getBeginTime( ),
06452                                                                     theTime,
06453                                                                     theOldIntervalH->getTag( ));
06454 
06455     theLeftBaselineIntervalH->setVersionTime( theOldIntervalH->getVersionTime( ));
06456     theLeftBaselineIntervalH->setRevision( theRevisionH );
06457 
06458     theBaselinePreviousIntervalH->setBaselineNext( theLeftBaselineIntervalH );
06459     theLeftBaselineIntervalH->setBaselinePrevious( theBaselinePreviousIntervalH );
06460 
06461   // Right<->Next...
06462 
06463     theRightBaselineIntervalH = new( theOldIntervalH ) BdbIntervalR( theOldIntervalH->getObject( ),
06464                                                                      theTime,
06465                                                                      theOldIntervalH->getEndTime( ),
06466                                                                      theOldIntervalH->getTag( ));
06467 
06468     theRightBaselineIntervalH->setVersionTime( theOldIntervalH->getVersionTime( ));
06469     theRightBaselineIntervalH->setRevision( theRevisionH );
06470 
06471     theRightBaselineIntervalH->setBaselineNext( theBaselineNextIntervalH );
06472     theBaselineNextIntervalH->setBaselinePrevious( theRightBaselineIntervalH );
06473 
06474   // Left <-> Right...
06475 
06476     theLeftBaselineIntervalH->setBaselineNext( theRightBaselineIntervalH );
06477     theRightBaselineIntervalH->setBaselinePrevious( theLeftBaselineIntervalH );
06478 
06479   // Create limited subtrees above the newely created intervals using the whole
06480   // sub-tree of the old one.
06481 
06482     status = copyLimitedSubTree( theOldIntervalH,
06483                                  theOldIntervalH->getBeginTime( ),
06484                                  theTime,
06485                                  theLeftBaselineIntervalH );
06486     if( BdbcSuccess != status ) {
06487         ErrMsg(error) << errorString << endl
06488                       << "    Failed to copy the left sub-tree of the split interval." << endmsg;
06489         return BdbcError;
06490     }
06491     status = copyLimitedSubTree( theOldIntervalH,
06492                                  theTime,
06493                                  theOldIntervalH->getEndTime( ),
06494                                  theRightBaselineIntervalH );
06495     if( BdbcSuccess != status ) {
06496         ErrMsg(error) << errorString << endl
06497                       << "    Failed to copy the right sub-tree of the split interval." << endmsg;
06498         return BdbcError;
06499     }
06500 
06501   // Draw the topmost linked list over the new intervals trees.
06502   // This would also include binding with the previous and the next intervals
06503   // of the old interval.
06504   // This operation is done in 3 steps:
06505   //
06506   //    1. the border before the left fragnment.
06507   //    2. the border between the left and right fragnments.
06508   //    3. the border after the rightfragnment.
06509   //
06510   // IMPORTANT NOTE: In all these steps we are using the same
06511   //    interval "theTopPreviousIntervalH" as a link to the previous topmost interval.
06512   //    Due to a way the "::linkTopIntervalsInSubTree()" method works, the value
06513   //    of this back link is always modified upon the completion of the method.
06514 
06515     status = linkTopIntervalsInSubTree( theLeftBaselineIntervalH,
06516                                         theTopPreviousIntervalH );
06517     if( BdbcSuccess != status ) {
06518         ErrMsg(error) << errorString << endl
06519                       << "    Failed to draw the topmost line before the split interval." << endmsg;
06520         return BdbcError;
06521     }
06522     status = linkTopIntervalsInSubTree( theRightBaselineIntervalH,
06523                                         theTopPreviousIntervalH );
06524     if( BdbcSuccess != status ) {
06525         ErrMsg(error) << errorString << endl
06526                       << "    Failed to draw the topmost line between fragments of the split interval." << endmsg;
06527         return BdbcError;
06528     }
06529     status = linkTopIntervalsInSubTree( theBaselineNextIntervalH,
06530                                         theTopPreviousIntervalH );
06531     if( BdbcSuccess != status ) {
06532         ErrMsg(error) << errorString << endl
06533                       << "    Failed to draw the topmost line after the split interval." << endmsg;
06534         return BdbcError;
06535     }
06536 
06537   // And finally delete the old intervals together with its version tree
06538   // and the genealogy object (note tha last parameter set to "true").
06539 
06540     deleteIntervalsInSubTree( theOldIntervalH, true );
06541 
06542     return BdbcSuccess;
06543 }
06544 
06545 
06546 /** Copy a subtree of intervals, limited by the left and right borders
06547  ** in validity time, assuming that the passed intervals already exist.
06548  **/
06549 
06550 BdbStatus
06551 BdbDatabase::copyLimitedSubTree( const BdbHandle(BdbIntervalR)& theInIntervalH,
06552                                  const BdbTime&                 theLeftBorderTime,
06553                                  const BdbTime&                 theRightBorderTime,
06554                                  BdbHandle(BdbIntervalR)&       theOutIntervalH )
06555 {
06556     const char* errorString = "BdbDatabase::copyLimitedSubTree() -- error.";
06557 
06558     BdbStatus status = BdbcError;
06559     
06560     int i;
06561 
06562   // Get sub-trees (if any).
06563 
06564     vector<BdbHandle(BdbIntervalR)> theInNextIntervalH;
06565     BdbItr(BdbPersObj)                           theItr;
06566     BdbHandle(BdbIntervalR)                      theIntervalH;
06567 
06568     theInIntervalH->nextVers( theItr );
06569     while( theItr.next( )) {
06570         theIntervalH = (BdbHandle(BdbIntervalR)&) theItr;
06571         if( ! ((( theLeftBorderTime  <= theIntervalH->beginTime( )) &&
06572                 ( theRightBorderTime <= theIntervalH->beginTime( )))
06573                                      ||
06574                (( theLeftBorderTime  >= theIntervalH->endTime(   )) &&
06575                 ( theRightBorderTime >= theIntervalH->endTime(   ))))) {
06576             theInNextIntervalH.push_back( theIntervalH );
06577         }
06578     }
06579 
06580   // Create duplicate sub-trees in the output container if at least one
06581   // sub-tree was found in the input one.
06582 
06583     int numSubTrees = theInNextIntervalH.size( );
06584 
06585     if( numSubTrees > 0 ) {
06586 
06587       // Enable linear/branch versioning on the original interval object.
06588 
06589         if( numSubTrees == 1 ) {
06590             theOutIntervalH.setVersStatus( oocLinearVers );
06591         } else {
06592             theOutIntervalH.setVersStatus( oocBranchVers );
06593         }
06594 
06595       // Create and name as many linear/branch version(s) for the output interval
06596       // as it were found for the input interval.
06597 
06598         BdbHandle(BdbIntervalR)                      theOutNewIntervalH;
06599         vector<BdbHandle(BdbIntervalR)> theOutNextIntervalH;
06600 
06601         for( i = 0; i < numSubTrees; i++ ) {
06602             createVersion( theOutIntervalH, theOutNewIntervalH );
06603             nameVersion( theOutIntervalH, theOutNewIntervalH );
06604             theOutNextIntervalH.push_back( theOutNewIntervalH );
06605         }
06606 
06607       // Disable versioning of the current interval.
06608 
06609         theOutIntervalH.setVersStatus( oocNoVers );
06610 
06611       // Copy information from the input intervals into the output ones.
06612       //
06613       // Truncate the very first and very last interval in the list
06614       // if the validity limits were specified for this method.
06615       //
06616       // NOTE: We do not copy the TOP and BASELINE navigation links
06617       //       because they would be invalid in the new context.
06618 
06619         BdbHandle(BdbCondRevision) theRevisionH;
06620 
06621         for( i = 0; i < numSubTrees; i++ ) {
06622 
06623           // Copy the basic characteristics.
06624 
06625             theOutNextIntervalH[i]->setObject(      theInNextIntervalH[i]->getObject( ));
06626             theOutNextIntervalH[i]->setBeginTime(   theInNextIntervalH[i]->getBeginTime( ));
06627             theOutNextIntervalH[i]->setEndTime(     theInNextIntervalH[i]->getEndTime( ));
06628             theOutNextIntervalH[i]->setVersionTime( theInNextIntervalH[i]->getVersionTime( ));
06629             theOutNextIntervalH[i]->setTag(         theInNextIntervalH[i]->getTag( ));
06630 
06631           // Copy the revision information.
06632 
06633             theInNextIntervalH[i]->getRevision( theRevisionH );
06634             theOutNextIntervalH[i]->setRevision( theRevisionH );
06635 
06636           // Truncate the first and last intervals (if needed).
06637 
06638             if(( 0 == i ) &&
06639                ( theOutNextIntervalH[i]->beginTime( ) < theLeftBorderTime )) {
06640                 theOutNextIntervalH[i]->setBeginTime( theLeftBorderTime );
06641             }
06642             if((( numSubTrees - 1 ) == i ) &&
06643                ( theOutNextIntervalH[i]->endTime( ) > theRightBorderTime )) {
06644                 theOutNextIntervalH[i]->setEndTime( theRightBorderTime );
06645             }
06646         }
06647 
06648       // Proceed along the version tree.
06649 
06650         for( i = 0; i < numSubTrees; i++ ) {
06651 
06652             status = copyLimitedSubTree( theInNextIntervalH[i],
06653                                          theLeftBorderTime,
06654                                          theRightBorderTime,
06655                                          theOutNextIntervalH[i] );
06656             if( BdbcSuccess != status ) {
06657                 return status;
06658             }
06659         }
06660     }
06661 
06662     return BdbcSuccess;
06663 }
06664 
06665 BdbStatus
06666 BdbDatabase::linkTopIntervalsInSubTree( const BdbHandle(BdbIntervalR)& theIntervalH,
06667                                         BdbHandle(BdbIntervalR)&       thePreviousIntervalH )
06668 {
06669     const char* errorString = "BdbDatabase::linkTopIntervalsInSubTree() -- error.";
06670 
06671     BdbStatus status = BdbcError;
06672 
06673   // This check will prevent us from accidental crashing.
06674 
06675     if( BdbIsNull( theIntervalH ) || BdbIsNull( thePreviousIntervalH )) {
06676         ErrMsg(error) << errorString << endl
06677                       << "    NULL handles have been detected." << endl
06678                       << "    The output container may have incorrect internal structure." << endmsg;
06679         return BdbcError;
06680     }
06681 
06682   // Iterate over sub-tree(s) (if amy).
06683 
06684     bool subTreeFound = false;
06685 
06686     BdbItr(BdbPersObj) theItr;
06687 
06688     theIntervalH->nextVers( theItr );
06689     while( theItr.next( )) {
06690 
06691         status = linkTopIntervalsInSubTree( (BdbHandle(BdbIntervalR)&) theItr,
06692                                             thePreviousIntervalH );
06693         if( BdbcSuccess != status ) {
06694             return status;
06695         }
06696 
06697         subTreeFound = true;
06698     }
06699 
06700   // If the subtree was not found this means that the current interval
06701   // is the TOPMOST one and must be included into the list.
06702 
06703     if ( ! subTreeFound ) {
06704 
06705         thePreviousIntervalH->setTopNext( theIntervalH );
06706         theIntervalH->setTopPrevious( thePreviousIntervalH );
06707 
06708         thePreviousIntervalH = theIntervalH;
06709     }
06710 
06711     return BdbcSuccess;
06712 }
06713 
06714 
06715 void
06716 BdbDatabase::deleteIntervalsInSubTree( BdbHandle(BdbIntervalR)& theIntervalH,
06717                                        bool                     deleteGeneObject )
06718 {
06719   // First of all we propagate recursively along the branches (if any)
06720   // and delete intervals there.
06721 
06722     BdbItr(BdbPersObj) theItr;
06723 
06724     if( theIntervalH->exist_geneObj( )) {
06725         theIntervalH->nextVers( theItr );
06726         while( theItr.next( )) {
06727             deleteIntervalsInSubTree((BdbHandle(BdbIntervalR)&) theItr );
06728         }
06729     }
06730 
06731   // Then we delete the genealogy object if required.
06732 
06733     if( deleteGeneObject && theIntervalH->exist_geneObj( )) {
06734 
06735         BdbHandle(BdbIntervalGene) theGeneObjH;
06736         theGeneObjH = (const BdbHandle(BdbIntervalGene)&) theIntervalH->geneObj( );
06737 
06738         BdbDelete(theGeneObjH);
06739     }
06740 
06741   // And finally we delete current interval itself.
06742 
06743     BdbDelete( theIntervalH );
06744 
06745     return;
06746 }
06747 
06748 /////////////////
06749 // End Of File //
06750 /////////////////

 


BaBar Public Site | SLAC | News | Links | Who's Who | Contact Us

Page Owner: Jacek Becla
Last Update: October 04, 2002