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

CdbBdbSPartitionsLayoutP.cc

Go to the documentation of this file.
00001 // File and Version Information:
00002 //      $Id: CdbBdbSPartitionsLayoutP.cc,v 1.10 2004/08/06 05:54:25 bartoldu Exp $
00003 
00004 /// The implementation file for the CdbBdbSPartitionsLayoutP class
00005 /**
00006   * @see CdbBdbSPartitionsLayoutP
00007   */
00008 
00009 #include "BaBar/BaBar.hh"
00010 
00011 #include "CdbBdbShared/CdbBdbSPartitionsLayoutP.hh"
00012 
00013 #include "CdbBase/CdbEnvironment.hh"
00014 
00015 #include <iostream>
00016 #include <assert.h>
00017 #include <iomanip>
00018 
00019 #include <vector>
00020 #include <list>
00021 using std::cout;
00022 using std::endl;
00023 using std::ostream;
00024 using std::setfill;
00025 using std::setw;
00026 
00027 namespace {
00028 
00029 /////////////////////////////////
00030 // CdbBdbSPartitionIntervalItr //
00031 /////////////////////////////////
00032 
00033 class CdbBdbSPartitionIntervalItr : public CdbItr< CdbBdbSPartitionInterval >::InterfaceType {
00034 
00035 private:
00036 
00037     typedef CdbBdbSPartitionCell     Cell;
00038     typedef CdbBdbSPartitionInterval Interval;
00039 
00040     typedef std::vector<Cell>   Cells;
00041     typedef std::list<Interval> Intervals;
00042 
00043 private:
00044 
00045     CdbBdbSPartitionIntervalItr( );
00046 
00047     CdbBdbSPartitionIntervalItr& operator=( const CdbBdbSPartitionIntervalItr& theItr );
00048 
00049 protected:
00050 
00051     CdbBdbSPartitionIntervalItr( const CdbBdbSPartitionIntervalItr& theItr ) :
00052         _cells              (theItr._cells),
00053         _begin              (theItr._begin),
00054         _end                (theItr._end),
00055         _isValid            (theItr._isValid),
00056         _hasEverBeenAdvanced(theItr._hasEverBeenAdvanced),
00057         _valueIsBuilt       (theItr._valueIsBuilt),
00058         _values             (theItr._values),
00059         _currentValueItr    (theItr._currentValueItr),
00060         _currentValue       (theItr._currentValue)
00061     { }
00062 
00063 public:
00064 
00065     CdbBdbSPartitionIntervalItr( const Cells&   theCells,
00066                                  const BdbTime& theBeginValidityTime,
00067                                  const BdbTime& theEndValidityTime ) :
00068         _cells              (theCells),
00069         _begin              (theBeginValidityTime),
00070         _end                (theEndValidityTime),
00071         _isValid            (false),
00072         _hasEverBeenAdvanced(false),
00073         _valueIsBuilt       (false)
00074     {
00075         assert( theBeginValidityTime < theEndValidityTime );
00076     }
00077 
00078     virtual ~CdbBdbSPartitionIntervalItr( )
00079     { }
00080 
00081     virtual CdbStatus reset( )
00082     {
00083         _isValid             = false;
00084         _hasEverBeenAdvanced = false;
00085 
00086         return CdbStatus::Success;
00087     }
00088 
00089     void buildNextNode( Cells::iterator     theInCurrent,
00090                         Intervals::iterator theOutCenter,
00091                         const BdbTime&      theBeginTime,
00092                         const BdbTime&      theEndTime )
00093     {
00094         const char* debugStr = "CdbBdbSCondition::CdbBdbSPartitionIntervalItr::buildNextNode()";
00095 
00096         for( Cells::iterator i = theInCurrent; i != _cells.end( ); ++i ) {
00097 
00098 /**************************************************************/
00099 if( CdbEnvironment::getDebugMode( ) != 0 )
00100     cout << debugStr << endl
00101          << "{" << endl
00102          << "    (*i)            = " << (*i) << endl
00103          << "    (*theOutCenter) = " << (*theOutCenter) << endl
00104          << "}" << endl;
00105 /**************************************************************/
00106 
00107           // Get next cell as defined by the input index and see which
00108           // of the following scenarious we're at:
00109           //
00110           //      theBeginTime  theEndTime
00111           //           :            :
00112           //        [--)            :       skip
00113           //           :            [--)    skip
00114           //           [--)         :       (1) split into 2, (optionally) truncate on the left, then propage down on the right
00115           //           [------------)       (2) split into 1, (optionally) truncate on the left and on the right, and finish
00116           //           :  [------)  :       (3) split into 3, then propagate down on the left and then on the right
00117           //           :         [--)       (4) split into 2, (optionally) truncate on the right, then propagate down on the left
00118           //
00119           // NOTE: If this is a very first call to the method then the we're modifying
00120           //       the collection of values is slightly different than for the non-empty
00121           //       vector.
00122           //
00123           // IMPLEMENTATION NOTE: The following recursive algorithm is based on
00124           //                      an assumption that we're using STD <list>
00125           //                      to implement the collection values. Otherwise
00126           //                      the tricks with iterators may not work since positions
00127           //                      of elements as defined by iterators may change as we'll
00128           //                      be modifying the collection.
00129 
00130             Cell c = (*i);
00131 
00132           // Check if we need to skip
00133 
00134             if( c.cell.endValidity   <= theBeginTime ) continue;
00135             if( c.cell.beginValidity >= theEndTime   ) continue;
00136 
00137           // Truncate if needed
00138 
00139             BdbTime begin = c.cell.beginValidity;
00140             if( begin < theBeginTime )
00141                 begin = theBeginTime;
00142 
00143             BdbTime end = c.cell.endValidity;
00144             if( end > theEndTime )
00145                 end = theEndTime;
00146 
00147 /******************************************************************************************************/
00148 if( CdbEnvironment::getDebugMode( ) != 0 )
00149     cout << debugStr << endl
00150          << "{" << endl
00151          << "    begin        = " << setw( 10 ) << setfill( '0' ) << begin.getGmtSec( )        << endl
00152          << "    end          = " << setw( 10 ) << setfill( '0' ) << end.getGmtSec( )          << endl
00153          << "    theBeginTime = " << setw( 10 ) << setfill( '0' ) << theBeginTime.getGmtSec( ) << endl
00154          << "    theEndTime   = " << setw( 10 ) << setfill( '0' ) << theEndTime.getGmtSec( )   << endl
00155          << "}" << endl;
00156 /******************************************************************************************************/
00157 
00158             if(( begin == theBeginTime ) &&
00159                ( end   <  theEndTime )) {
00160 
00161 /******************************************/
00162 if( CdbEnvironment::getDebugMode( ) != 0 )
00163     cout << debugStr << endl
00164          << "{" << endl
00165          << "    -1-" << endl
00166          << "}" << endl;
00167 /******************************************/
00168 
00169               // -1-
00170 
00171                 Interval left( c.id, begin, end );
00172                 Interval right(      end,   theEndTime );
00173 
00174                 _values.insert( theOutCenter, left );
00175 
00176                 Intervals::iterator outRight = theOutCenter;
00177                 if( _values.end( ) == theOutCenter ) {
00178                     outRight = _values.insert( theOutCenter, right );
00179                 } else {
00180                     (*theOutCenter) = right;
00181                 }
00182                 Cells::iterator nextCell = i;
00183                 ++nextCell;
00184                 buildNextNode( nextCell, outRight, end, theEndTime );   // propagate RIGHT
00185 
00186                 return;
00187 
00188             } else if(( begin == theBeginTime ) &&
00189                       ( end   == theEndTime )) {
00190 
00191 /******************************************/
00192 if( CdbEnvironment::getDebugMode( ) != 0 )
00193     cout << debugStr << endl
00194          << "{" << endl
00195          << "    -2-" << endl
00196          << "}" << endl;
00197 /******************************************/
00198 
00199               // -2-
00200 
00201                 Interval center( c.id, begin, end );
00202 
00203                 if( _values.end( ) == theOutCenter )
00204                     _values.insert( theOutCenter, center );
00205                 else
00206                     (*theOutCenter) = center;
00207 
00208                 return;
00209 
00210             } else if(( begin > theBeginTime ) &&
00211                       ( end   < theEndTime )) {
00212 
00213 /******************************************/
00214 if( CdbEnvironment::getDebugMode( ) != 0 )
00215     cout << debugStr << endl
00216          << "{" << endl
00217          << "    -3-" << endl
00218          << "}" << endl;
00219 /******************************************/
00220 
00221               // -3-
00222 
00223                 Interval left  (       theBeginTime, begin );
00224                 Interval center( c.id, begin,        end );
00225                 Interval right (       end,          theEndTime );
00226 
00227                 Intervals::iterator outLeft = _values.insert( theOutCenter, left );
00228                 _values.insert( theOutCenter, center );
00229                 Intervals::iterator outRight = theOutCenter;
00230                 if( _values.end( ) == theOutCenter ) {
00231                     outRight = _values.insert( theOutCenter, right );
00232                 } else {
00233                     (*theOutCenter) = right;
00234                 }
00235                 Cells::iterator nextCell = i;
00236                 ++nextCell;
00237                 buildNextNode( nextCell, outLeft,  theBeginTime, begin );      // propagate LEFT
00238                 buildNextNode( nextCell, outRight, end,          theEndTime ); // propagate RIGHT
00239 
00240                 return;
00241 
00242             } else if(( begin >  theBeginTime ) &&
00243                       ( end   >= theEndTime )) {
00244 
00245 /******************************************/
00246 if( CdbEnvironment::getDebugMode( ) != 0 )
00247     cout << debugStr << endl
00248          << "{" << endl
00249          << "    -4-" << endl
00250          << "}" << endl;
00251 /******************************************/
00252 
00253               // -4-
00254 
00255                 Interval left(        theBeginTime, begin );
00256                 Interval right( c.id, begin,        end  );
00257 
00258                 Intervals::iterator outLeft = _values.insert( theOutCenter, left );
00259                 if( _values.end( ) == theOutCenter ) {
00260                     _values.insert( theOutCenter, right );
00261                 } else {
00262                     (*theOutCenter) = right;
00263                 }
00264                 Cells::iterator nextCell = i;
00265                 ++nextCell;
00266                 buildNextNode( nextCell, outLeft, theBeginTime, begin );   // propagate LEFT
00267 
00268                 return;
00269 
00270             } else {
00271                 assert( 0 );
00272             }
00273         }
00274 
00275       // If we got in here then we need to fiil up the whole interval with an invalid
00276       // element unless the previous call to this function has already done it.
00277 
00278         if( _values.end( ) == theOutCenter ) {
00279 
00280 /******************************************/
00281 if( CdbEnvironment::getDebugMode( ) != 0 )
00282     cout << debugStr << endl
00283          << "{" << endl
00284          << "    -default-" << endl
00285          << "}" << endl;
00286 /******************************************/
00287 
00288             _values.push_back( Interval( theBeginTime,
00289                                          theEndTime ));
00290         }
00291     }
00292 
00293     void buildVectorOfValues( )
00294     {
00295         if( !_valueIsBuilt ) {
00296             _valueIsBuilt = true;
00297 
00298             buildNextNode( _cells.begin( ),
00299                            _values.end( ),
00300                            _begin,
00301                            _end );
00302         }
00303         _currentValueItr = _values.begin( );
00304     }
00305 
00306     bool tryNext( )
00307     {
00308         bool result = _currentValueItr != _values.end( );
00309         if( result ) {
00310             _currentValue = *(_currentValueItr++);
00311         }
00312         return result;
00313     }
00314 
00315     virtual bool next( )
00316     {
00317         if( _hasEverBeenAdvanced ) {
00318 
00319             if( _isValid ) {
00320                 _isValid = tryNext( );
00321             } else {
00322 
00323               // stay in the BEYOND_LAST_ELEMENT state
00324                 ;
00325             }
00326 
00327         } else {
00328 
00329             buildVectorOfValues( );
00330 
00331             _hasEverBeenAdvanced = true;
00332             _isValid             = tryNext( );
00333         }
00334         return _isValid;
00335     }
00336 
00337     virtual ValueType value( )
00338     {
00339         if( !_isValid ) {
00340             assert( 0 );
00341         }
00342         return _currentValue;
00343     }
00344 
00345     virtual bool isValid( )
00346     {
00347         return _isValid;
00348     }
00349 
00350     virtual InterfaceType* clone( ) const
00351     {
00352         return new CdbBdbSPartitionIntervalItr( *this );
00353     }
00354 
00355 private:
00356 
00357     Cells _cells;
00358 
00359     BdbTime _begin;
00360     BdbTime _end;
00361 
00362     bool _isValid;
00363     bool _hasEverBeenAdvanced;
00364 
00365   // The output collection is built only once during the lifetime
00366   // of the iterator.
00367 
00368     bool _valueIsBuilt;
00369 
00370     Intervals           _values;
00371     Intervals::iterator _currentValueItr;
00372     Interval            _currentValue;
00373 };
00374 
00375 };
00376 
00377 //////////////////////////
00378 // CdbBdbSPartitionCell //
00379 //////////////////////////
00380 
00381 CdbBdbSPartitionCell::CdbBdbSPartitionCell( ) :
00382     cell(CdbBdbSCell( )),
00383     id(0),
00384     partition(0)
00385 { }
00386 
00387 CdbBdbSPartitionCell::CdbBdbSPartitionCell( const CdbBdbSCell&                     theCell,
00388                                             d_UShort                               theId,
00389                                             const BdbRef( CdbBdbSPartitionBaseP )& theRef ) :
00390     cell(theCell),
00391     id(theId),
00392     partition(theRef)
00393 { }
00394 
00395 CdbBdbSPartitionCell::CdbBdbSPartitionCell( const CdbBdbSPartitionCell& theOther ) :
00396     cell(theOther.cell),
00397     id(theOther.id),
00398     partition(theOther.partition)
00399 { }
00400 
00401 CdbBdbSPartitionCell::~CdbBdbSPartitionCell( )
00402 { }
00403 
00404 CdbBdbSPartitionCell&
00405 CdbBdbSPartitionCell::operator=( const CdbBdbSPartitionCell& theOther )
00406 {
00407     const_cast< CdbBdbSCell& >                    ( cell      ) = theOther.cell;
00408     const_cast< d_UShort& >                       ( id        ) = theOther.id;
00409     const_cast< BdbRef( CdbBdbSPartitionBaseP )& >( partition ) = theOther.partition;
00410     return *this;
00411 }
00412 
00413 void
00414 CdbBdbSPartitionCell::dump( ostream& o ) const
00415 {
00416     o << cell << endl
00417       << "ID        : " << id << endl
00418       << "PARTITION : " << partition.sprint( ) << endl;
00419 }
00420 
00421 //////////////////////////////
00422 // CdbBdbSPartitionInterval //
00423 //////////////////////////////
00424 
00425 CdbBdbSPartitionInterval::CdbBdbSPartitionInterval( const BdbTime& theBeginTime,
00426                                                     const BdbTime& theEndTime ) :
00427     isEmpty(true),
00428     begin  (theBeginTime),
00429     end    (theEndTime)
00430 { }
00431 
00432 CdbBdbSPartitionInterval::CdbBdbSPartitionInterval( d_UShort       theId,
00433                                                     const BdbTime& theBeginTime,
00434                                                     const BdbTime& theEndTime ) :
00435     isEmpty(false),
00436     id     (theId),
00437     begin  (theBeginTime),
00438     end    (theEndTime)
00439 { }
00440 
00441 CdbBdbSPartitionInterval::CdbBdbSPartitionInterval( const CdbBdbSPartitionInterval& theOther ) :
00442     isEmpty(theOther.isEmpty),
00443     id     (theOther.id),
00444     begin  (theOther.begin),
00445     end    (theOther.end)
00446 { }
00447 
00448 CdbBdbSPartitionInterval::~CdbBdbSPartitionInterval( )
00449 { }
00450 
00451 CdbBdbSPartitionInterval&
00452 CdbBdbSPartitionInterval::operator=( const CdbBdbSPartitionInterval& theOther )
00453 {
00454     if( this != &theOther ) {
00455         isEmpty = theOther.isEmpty;
00456         id      = theOther.id;
00457         begin   = theOther.begin;
00458         end     = theOther.end;
00459     }
00460     return *this;
00461 }
00462 
00463 void
00464 CdbBdbSPartitionInterval::dump( ostream& o ) const
00465 {
00466     o << "IS_EMPTY=" << ( isEmpty ? "Y" : "N" )
00467       << "  "
00468       << "BEGIN="
00469       << setw( 10 ) << setfill( '0' ) << begin.getGmtSec( )
00470       << "."
00471       << setw( 10 ) << setfill( '0' ) << begin.getGmtNsec( ) 
00472       << "  "
00473       << "END="
00474       << setw( 10 ) << setfill( '0' ) << end.getGmtSec( )
00475       << "."
00476       << setw( 10 ) << setfill( '0' ) << end.getGmtNsec( );
00477 
00478     if( !isEmpty ) {
00479       cout << "  "
00480            << "ID=" << id;
00481     }
00482 }
00483 
00484 //////////////////////////////
00485 // CdbBdbSPartitionsLayoutP //
00486 //////////////////////////////
00487 
00488 CdbBdbSPartitionsLayoutP::CdbBdbSPartitionsLayoutP( ) :
00489     _collectionP(0),
00490     _trivialIndexP(0),
00491     _complexIndexP(0)
00492 {
00493   // Note, we're not going to use names of partition objects in
00494   // the collection.
00495 
00496     bool useIdFlag   = true;
00497     bool useNameFlag = false;
00498 
00499     _collectionP = new( ooThis( )) CdbBdbSCollectionP( useIdFlag,
00500                                                        useNameFlag );
00501 
00502   // This is a trivial index for the persistent partition object. It's meant in here
00503   // to speed up lookup operations to avoid bringing the whole persistent partition
00504   // objects into the memory.
00505   //
00506   // Another reason to use this index is that actual partition objects may reside
00507   // in different containers. Therefore by using an extra inidex we may avoid locking
00508   // unnessesary containers.
00509   //
00510   // The index does not contain any elements by default.
00511 
00512     _trivialIndexP = new( ooThis( )) CdbBdbSPagedVarrayP< CdbBdbSPartitionCell >( );
00513 }
00514 
00515 CdbBdbSPartitionsLayoutP::~CdbBdbSPartitionsLayoutP( ) 
00516 {
00517   // Delete all the partition objects first
00518   // Then delete the collection itself.
00519 
00520     d_ULong num = _trivialIndexP->size( );
00521     for( d_ULong i = 0; i < num; ++i ) {
00522 
00523         CdbBdbSPartitionCell pCell = _trivialIndexP->elementAt( i );
00524         BdbDelete(pCell.partition);
00525     }
00526     BdbDelete(_collectionP);
00527 
00528   // ...and the trivial index
00529 
00530     BdbDelete(_trivialIndexP);
00531 
00532   // And never attempt to delete the optional index. This has to be done
00533   // by an application knowing about the actual persistent type (and it virtual
00534   // tables) of the corresponding index.
00535 
00536     if( ! BdbIsNull(_complexIndexP)) {
00537         cout << "CdbBdbSPartitionsLayoutP::~CdbBdbSPartitionsLayoutP( ) - WARNING!" << endl
00538              << "    The destructor has detected non-zero optional COMPLEX index. This index" << endl
00539              << "    can't be deleted by the current destructor. Use more recent implementation" << endl
00540              << "    for this kind of operation." << endl
00541              << "        INDEX OID: " << _complexIndexP.sprint( ) << endl;
00542     }
00543 }
00544 
00545 d_ULong
00546 CdbBdbSPartitionsLayoutP::numPartitions( ) const
00547 {
00548     return _collectionP->elements( );
00549 }
00550 
00551 CdbStatus
00552 CdbBdbSPartitionsLayoutP::insert( const BdbRef( CdbBdbSPartitionBaseP )& theRef )
00553 {
00554     const char* errorStr = "CdbBdbSPartitionsLayoutP::insert() - ERROR.";
00555 
00556     ooUpdate( );
00557 
00558     CdbStatus result = CdbStatus::Error;
00559     do {
00560 
00561       // Verify parameters.
00562 
00563         if( BdbIsNull(theRef)) {
00564             cout << errorStr << endl
00565                  << "    0-0-0-0 persistent reference passed where a pointer onto" << endl
00566                  << "    a partition object was expected." << endl;
00567             break;
00568         }
00569 
00570       // Check if there is no such partition in the layout.
00571 
00572         d_ULong id = theRef->id( );
00573 
00574         BdbRef( CdbBdbSPartitionBaseP ) ref;
00575 
00576         if( CdbStatus::Success == _collectionP->find( id,
00577                                                       ref )) {
00578             cout << errorStr << endl
00579                  << "    The Layout already has a registered partition with the same identifier." << endl
00580                  << "        ID: " << id << endl
00581                  << "        PASSED     PARTITION OID: " << theRef.sprint( ) << endl
00582                  << "        REGISTERED PARTITION OID: " << ref.sprint( ) << endl;
00583             break;
00584         }
00585 
00586       // Check if the cell of passed partition does not overlap with none of
00587       // the known partitions.
00588 
00589         CdbBdbSCell cell = theRef->cell( );
00590 
00591         bool overlap = false;
00592         {
00593             d_ULong num = _trivialIndexP->size( );
00594             for( d_ULong i = 0; i < num; ++i ) {
00595 
00596                 CdbBdbSPartitionCell pCell = _trivialIndexP->elementAt( i );
00597 
00598                 if( pCell.cell.overlap( cell )) {
00599                     overlap = true;
00600                     break;
00601                 }
00602             }
00603         }
00604         if( overlap ) {
00605             cout << errorStr << endl
00606                  << "    One of the registered with the Layout partitions overlaps with" << endl
00607                  << "    with the one passed at the 2-dimension space of the VALIDITY" << endl
00608                  << "    and INSERTION timelines." << endl;
00609             break;
00610         }
00611 
00612       // Add new partition to the collection and then - to the trivial index.
00613       //
00614       // NOTE: A failure to add into a trivial index will be followed by
00615       //       a proper "removal" operation to leave the Layout in the self-consistent
00616       //       state.
00617 
00618         if( CdbStatus::Success != _collectionP->insert( theRef )) {
00619             break;
00620         }
00621         d_ULong num = _trivialIndexP->size( );
00622         if( BdbcSuccess != _trivialIndexP->resize( num + 1 )) {
00623 
00624             cout << errorStr << endl
00625                  << "    Failed to resize the trivial index to make a room for a new partition." << endl
00626                  << "        CURRENT SIZE: " << num << endl;
00627 
00628             _collectionP->remove( id );
00629 
00630             break;
00631         }
00632         _trivialIndexP->setElementAt( num,
00633                                       CdbBdbSPartitionCell( cell,
00634                                                             id,
00635                                                             theRef ));
00636 
00637       // Done.
00638 
00639         result = CdbStatus::Success;
00640 
00641     } while( false );
00642 
00643     return result;
00644 }
00645 
00646 CdbStatus
00647 CdbBdbSPartitionsLayoutP::update( const BdbRef( CdbBdbSPartitionBaseP )& theNewRef )
00648 {
00649     const char* errorStr = "CdbBdbSPartitionsLayoutP::update() - ERROR.";
00650 
00651     ooUpdate( );
00652 
00653     CdbStatus result = CdbStatus::NotFound;
00654     do {
00655 
00656       // Verify parameters.
00657 
00658         if( BdbIsNull(theNewRef)) {
00659             cout << errorStr << endl
00660                  << "    0-0-0-0 persistent reference passed where a pointer onto" << endl
00661                  << "    a partition object was expected." << endl;
00662             break;
00663         }
00664 
00665       // Use trivial index to find the partition cell corresponding to
00666       // the old partition
00667 
00668         bool    updateIndexOnly = false;    // If the passed objecxt is known
00669         d_ULong oldCellIdx      = 0;        // Will need to replace with updated cell
00670         {
00671             const d_UShort pId = theNewRef->id( );
00672 
00673             CdbBdbSPartitionCell pCell;
00674 
00675             bool found = false;
00676 
00677             d_ULong num = _trivialIndexP->size( );
00678             for( d_ULong i = 0; i < num; ++i ) {
00679 
00680                 pCell = _trivialIndexP->elementAt( i );
00681                 if( pCell.id == pId ) {
00682 
00683                     oldCellIdx = i;
00684 
00685                     found = true;
00686                     break;
00687                 }
00688             }
00689             if( !found) break;
00690 
00691           // Check if the cell of passed partition is the same (except its upper border) 
00692           // than the one known to the local layout. The upper border of the passed
00693           // partition is allowed to be "closed".
00694 
00695             CdbBdbSCell newCell = theNewRef->cell( );
00696 
00697             if(( newCell.beginValidity  != pCell.cell.beginValidity )  ||
00698                ( newCell.endValidity    != pCell.cell.endValidity )    ||
00699                ( newCell.beginInsertion != pCell.cell.beginInsertion )) {
00700 
00701                 cout << errorStr << endl
00702                      << "    The validity/insertion cell occupied by the new partition passed" << endl
00703                      << "    to the procedure does not match the old one." << endl
00704                      << "        NEW ->" << endl
00705                      << newCell << endl
00706                      << "        OLD ->" << endl
00707                      << pCell.cell << endl;
00708 
00709                 result = CdbStatus::Error;
00710 
00711                 break;
00712             }
00713 
00714           // Also check if the found partition objects has the same OID.
00715           // If this is the case the we only need to update indexes.
00716 
00717             if( theNewRef == pCell.partition ) {
00718                 updateIndexOnly = true;
00719             }
00720         }
00721 
00722       // Replace old cell in the trivial index.
00723 
00724         _trivialIndexP->setElementAt( oldCellIdx,
00725                                       CdbBdbSPartitionCell( theNewRef->cell( ),
00726                                                             theNewRef->id( ),
00727                                                             theNewRef ));
00728 
00729       // Replace the partition object in the current Layout if needed.
00730 
00731         if( ! updateIndexOnly ) {
00732 
00733           // The following method will also physically destroy the partition object
00734           // corresponding to the passed identifier.
00735 
00736             if( CdbStatus::Success != _collectionP->remove( theNewRef->id( ))) {
00737 
00738                 cout << errorStr << endl
00739                      << "    Failed to remove old parition object out of the collection." << endl
00740                      << "        PARTITION ID: " << theNewRef->id( ) << endl;
00741 
00742                 result = CdbStatus::Error;
00743 
00744                 break;
00745             }
00746 
00747           // And insert
00748 
00749             if( CdbStatus::Success != _collectionP->insert( theNewRef )) {
00750 
00751                 cout << errorStr << endl
00752                      << "    Failed to insert new parition object into the collection." << endl
00753                      << "        PARTITION ID: " << theNewRef->id( ) << endl;
00754 
00755                 result = CdbStatus::Error;
00756 
00757                 break;
00758             }
00759         }
00760 
00761       // Done
00762 
00763         result = CdbStatus::Success;
00764 
00765     } while( false );
00766 
00767     return result;
00768 }
00769 
00770 CdbStatus
00771 CdbBdbSPartitionsLayoutP::find( d_UShort                         theId,
00772                                 BdbRef( CdbBdbSPartitionBaseP )& theRef ) const
00773 {
00774     return _collectionP->find( theId,
00775                                theRef );
00776 }
00777 
00778 CdbStatus
00779 CdbBdbSPartitionsLayoutP::find( const BdbTime&                   theValidityTime,
00780                                 const BdbTime&                   theInsertionTime,
00781                                 BdbRef( CdbBdbSPartitionBaseP )& theRef ) const
00782 {
00783     CdbStatus result = CdbStatus::NotFound;
00784     {
00785       // Use trivial index
00786 
00787         d_ULong num = _trivialIndexP->size( );
00788         for( d_ULong i = 0; i < num; ++i ) {
00789 
00790             CdbBdbSPartitionCell pCell = _trivialIndexP->elementAt( i );
00791 
00792             if( pCell.cell.in( theValidityTime,
00793                                theInsertionTime )) {
00794 
00795                 theRef = pCell.partition;
00796 
00797                 result = CdbStatus::Success;
00798                 break;
00799             }
00800         }
00801     }
00802     return result;
00803 }
00804 
00805 CdbStatus
00806 CdbBdbSPartitionsLayoutP::find( const BdbTime&                   theValidityTime,
00807                                 BdbRef( CdbBdbSPartitionBaseP )& theRef ) const
00808 {
00809     CdbStatus result = CdbStatus::NotFound;
00810     {
00811       // Use trivial index to find an "open" partition
00812 
00813         d_ULong num = _trivialIndexP->size( );
00814         if( num > 0 ) {
00815 
00816           // NOTE: That we're going from the most recently registered partition
00817           //       stored at the end of the list down to the one at a position 0.
00818           //       This is done since we expect that "open" partitions are located
00819           //       at the end of the index.
00820 
00821             int first = num - 1;
00822             assert( first >= 0 );       // We're are not expecting more than 10^31-1
00823                                         // partitions.
00824 
00825             for( int i = first; i >= 0; --i ) {
00826 
00827                 CdbBdbSPartitionCell pCell = _trivialIndexP->elementAt( i );
00828 
00829                 if( pCell.cell.inValidityRange( theValidityTime ) &&
00830                     ( BdbTime::plusInfinity == pCell.cell.endInsertion )) {
00831 
00832                     theRef = pCell.partition;
00833 
00834                     result = CdbStatus::Success;
00835                     break;
00836                 }
00837             }
00838         }
00839     }
00840     return result;
00841 }
00842 CdbStatus
00843 CdbBdbSPartitionsLayoutP::topmost( const BdbTime&                   theValidityTime,
00844                                    BdbRef( CdbBdbSPartitionBaseP )& theRef ) const
00845 {
00846     CdbStatus result = CdbStatus::NotFound;
00847     {
00848       // Use trivial index to find a "topmost" partition
00849 
00850         d_ULong num = _trivialIndexP->size( );
00851         if( num > 0 ) {
00852 
00853           // NOTE: That we're going from the most recently registered partition
00854           //       stored at the end of the list down to the one at a position 0.
00855           //       This is done since we expect that "topmost" partitions are located
00856           //       at the end of the index.
00857 
00858             int first = num - 1;
00859             assert( first >= 0 );       // We're are not expecting more than 10^31-1
00860                                         // partitions.
00861 
00862             for( int i = first; i >= 0; --i ) {
00863 
00864                 CdbBdbSPartitionCell pCell = _trivialIndexP->elementAt( i );
00865 
00866                 if( pCell.cell.inValidityRange( theValidityTime )) {
00867 
00868                     theRef = pCell.partition;
00869 
00870                     result = CdbStatus::Success;
00871                     break;
00872                 }
00873             }
00874         }
00875     }
00876     return result;
00877 }
00878 
00879 CdbStatus
00880 CdbBdbSPartitionsLayoutP::next( const BdbTime&                   theValidityTime,
00881                                 BdbRef( CdbBdbSPartitionBaseP )& theRef ) const
00882 {
00883     assert( !BdbIsNull(theRef));
00884 
00885     CdbStatus result = CdbStatus::NotFound;
00886     {
00887       // Use trivial index to find a "next" partition
00888 
00889       // NOTE: That we're going from the most recently registered partition
00890       //       stored at the end of the list down to the one at a position 0.
00891       //       This is done since we expect that "next" partitions are located
00892       //       at the end of the index.
00893 
00894         d_ULong num = _trivialIndexP->size( );
00895         if( num > 0 ) {
00896 
00897           // Find the specified partition first. The actual search will
00898           // go down from that partition.
00899 
00900             bool    idxIsFound = false;
00901             d_ULong idx = 0;
00902             {
00903                 int first = num - 1;
00904                 assert( first >=0 );      // We're are not expecting more than 10^31-1
00905                                             // partitions.
00906 
00907                 for( int i = first; i >= 0; --i ) {
00908 
00909                     CdbBdbSPartitionCell pCell = _trivialIndexP->elementAt( i );
00910 
00911                     if( theRef == pCell.partition ) {
00912                         idxIsFound = true;
00913                         idx        = i;
00914                         break;
00915                     }
00916                 }
00917             }
00918 
00919           // Proceed down the index till a partition containing the
00920           // the specified validity time is met.
00921 
00922             if( idxIsFound && ( 0 != idx )) {
00923 
00924                 int first = idx - 1;
00925                 assert( first >= 0 );       // We're are not expecting more than 10^31-1
00926                                             // partitions.
00927 
00928                 for( int i = first; i >= 0; --i ) {
00929 
00930                     CdbBdbSPartitionCell pCell = _trivialIndexP->elementAt( i );
00931 
00932                     if( pCell.cell.inValidityRange( theValidityTime )) {
00933 
00934                         theRef = pCell.partition;
00935 
00936                         result = CdbStatus::Success;
00937                         break;
00938                     }
00939                 }
00940             }
00941         }
00942     }
00943     return result;
00944 }
00945 
00946 CdbStatus
00947 CdbBdbSPartitionsLayoutP::close( d_UShort theId )
00948 {
00949     const char* fatalStr = "CdbBdbSPartitionsLayoutP::close() - FATAL ERROR.";
00950 
00951     ooUpdate( );
00952 
00953   // Find this partition in a collection first
00954 
00955     BdbRef( CdbBdbSPartitionBaseP ) ref;
00956 
00957     CdbStatus result = find( theId,
00958                              ref );
00959     if( CdbStatus::Success != result ) {
00960         return result;
00961     }
00962 
00963   // Find this partition in the trivial index then
00964 
00965     d_ULong foundIndex = 0;
00966     bool    indexWasFound = false;
00967     {
00968         d_ULong num = _trivialIndexP->size( );
00969         for( d_ULong i = 0; i < num; ++i ) {
00970 
00971             CdbBdbSPartitionCell pCell = _trivialIndexP->elementAt( i );
00972 
00973             if( theId == pCell.id ) {
00974 
00975                 if( ref != pCell.partition ) {
00976                     cout << fatalStr << endl
00977                          << "    The trivial index is not compatible with the collection of partitions." << endl;
00978                     assert( 0 );
00979 
00980                 } else {
00981                     foundIndex = i;
00982                     indexWasFound = true;
00983                 }
00984                 break;
00985             }
00986         }
00987     }
00988     if( ! indexWasFound ) {
00989 
00990         cout << fatalStr << endl
00991              << "    The trivial index is not compatible with the collection of partitions." << endl;
00992 
00993         assert( 0 );
00994 
00995         return CdbStatus::Error;
00996     }
00997 
00998   // And finally update the index
00999 
01000      _trivialIndexP->setElementAt( foundIndex,
01001                                    CdbBdbSPartitionCell( ref->cell( ),
01002                                                          theId,
01003                                                          ref ));
01004      return CdbStatus::Success;
01005 }
01006 
01007 CdbItr< d_UShort >
01008 CdbBdbSPartitionsLayoutP::iterator( ) const
01009 {
01010     return _collectionP->iterator_identifiers( );
01011 }
01012 
01013 CdbItr< CdbBdbSPartitionInterval >
01014 CdbBdbSPartitionsLayoutP::iterator( const BdbTime& theInsertionTime,
01015                                     const BdbTime& theBeginValidityTime,
01016                                     const BdbTime& theEndValidityTime ) const
01017 {
01018     const char* debugStr = "CdbBdbSPartitionsLayoutP::iterator()";
01019 
01020     assert( !BdbIsNull(_trivialIndexP));
01021 
01022   // Build a transient vector of cells and pass it down to the iterator
01023   //
01024   // NOTE: This vector will only contains a subset of
01025   //       elements satisfying the selection criteria
01026   //       explained in the description of this method
01027   //
01028   // NOTE: The vector will be sorted at reverse order
01029   //
01030   // @see CdbBdbSPartitionsLayoutP::iterator()
01031 
01032     const CdbBdbSCell iteratorCell( theBeginValidityTime,
01033                                     theEndValidityTime,
01034                                     BdbTime::minusInfinity, // The bottom of the iterator's limit
01035                                     theInsertionTime );
01036 
01037 /*****************************************/
01038 if( CdbEnvironment::getDebugMode( ) != 0 )
01039     cout << debugStr << endl
01040          << "{" << endl
01041          << "iteratorCell ->" << endl
01042          << iteratorCell << endl
01043          << "}" << endl;
01044 /*****************************************/
01045 
01046     std::vector<CdbBdbSPartitionCell> cells;
01047 
01048     d_ULong num = _trivialIndexP->size( );
01049     for( d_ULong i = 0; i < num; ++i ) {
01050         CdbBdbSPartitionCell pc = _trivialIndexP->elementAt( i );
01051 
01052 /*****************************************/
01053 if( CdbEnvironment::getDebugMode( ) != 0 )
01054     cout << debugStr << endl
01055          << "{" << endl
01056          << "pc.cell ->" << endl
01057          << pc.cell << endl
01058          << "}" << endl;
01059 /*****************************************/
01060 
01061         if( iteratorCell.overlap( pc.cell )) {
01062 /*****************************************/
01063 if( CdbEnvironment::getDebugMode( ) != 0 )
01064     cout << debugStr << endl
01065          << "{" << endl
01066          << "'pc.cell' overlaps with 'iteratorCell'" << endl
01067          << "}" << endl;
01068 /*****************************************/
01069             cells.insert( cells.begin( ),
01070                           pc );
01071         }
01072     }
01073 
01074   // ATTENTION: This is not a memory leak - the created object
01075   //            will be destroyed by the iterator.
01076 
01077     return CdbItr< CdbBdbSPartitionInterval >( new CdbBdbSPartitionIntervalItr( cells,
01078                                                                                 theBeginValidityTime,
01079                                                                                 theEndValidityTime ));
01080 }
01081 
01082 void
01083 CdbBdbSPartitionsLayoutP::dump( ostream& o ) const
01084 {
01085     o << "TRIVIAL INDEX: " << _trivialIndexP.sprint( ) << endl
01086       << "COMPLEX INDEX: " << _complexIndexP.sprint( ) << endl
01087       << endl;
01088 
01089     _collectionP->dump( o );
01090 }
01091 
01092 /////////////////
01093 // End Of File //
01094 /////////////////

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