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

CdbBdbSPagedVarrayP.cc

Go to the documentation of this file.
00001 // File and Version Information:
00002 //      $Id: CdbBdbSPagedVarrayP.cc,v 1.6 2004/08/06 05:54:25 bartoldu Exp $
00003 
00004 /// The implementation file for the CdbBdbSPagedVarrayP class
00005 /**
00006   * @see CdbBdbSPagedVarrayP
00007   */
00008 
00009 #include "BaBar/BaBar.hh"
00010 
00011 #if !defined(OO_DDL_TRANSLATION)
00012 #include "CdbBdbShared/CdbBdbSPagedVarrayP.hh"
00013 #endif // OO_DDL_TRANSLATION
00014 
00015 #include "BdbApplication/BdbDomain.hh"
00016 
00017 #include <assert.h>
00018 using std::endl;
00019 using std::ostream;
00020 
00021 template< typename E >
00022 CdbBdbSPagedVarrayP<E>::CdbBdbSPagedVarrayP( d_ULong theInitialSize,
00023                                              d_ULong theNumPerLeaf,
00024                                              d_ULong theNumPerDirectory ) :
00025     _numPerLeaf(theNumPerLeaf),
00026     _numPerDirectory(theNumPerDirectory),
00027     _numLevels(0),
00028     _size(theInitialSize),
00029     _leafNode(0),
00030     _directoryNode(0)
00031 {
00032   // Set up default configuration parameters of the array
00033   // if the corresponding parameters were omitted.
00034 
00035     if( ! _numPerLeaf )      _numPerLeaf      = defaultNumPerLeaf( );
00036     if( ! _numPerDirectory ) _numPerDirectory = defaultNumPerDirectory( );
00037 
00038   // Allocate specified number of elements.
00039 
00040     _numLevels = calculateNumLevels( theInitialSize );
00041     if( _numLevels ) {
00042         _directoryNode = new( ooThis( )) CdbBdbSDirectoryNodeP<E>( _numLevels );
00043         _directoryNode->resize( theInitialSize,
00044                                 _numPerLeaf,
00045                                 _numPerDirectory );
00046     } else {
00047         _leafNode = new( ooThis( )) CdbBdbSLeafNodeP<E>( theInitialSize );
00048     }
00049 }
00050 
00051 template< typename E >
00052 CdbBdbSPagedVarrayP<E>::~CdbBdbSPagedVarrayP( ) 
00053 {
00054   // Destroy all the nodes (recursive)
00055 
00056     if( ! BdbIsNull( _leafNode ))      BdbDelete( _leafNode );
00057     if( ! BdbIsNull( _directoryNode )) BdbDelete( _directoryNode );
00058 }
00059 
00060 template< typename E >
00061 d_ULong
00062 CdbBdbSPagedVarrayP<E>::size( ) const
00063 {
00064     return _size;
00065 }
00066 
00067 template< typename E >
00068 BdbStatus
00069 CdbBdbSPagedVarrayP<E>::resize( d_ULong theNewSize )
00070 {
00071     if( theNewSize == _size ) return BdbcSuccess;
00072 
00073     ooUpdate( );
00074 
00075     BdbStatus result = BdbcError;
00076     {
00077         d_ULong newNumLevels = calculateNumLevels( theNewSize );
00078 
00079         if( theNewSize < _size ) {
00080             if( _numLevels == 0 ) {
00081                 result = _leafNode->resize( theNewSize,
00082                                             _numPerLeaf,
00083                                             _numPerDirectory );
00084             } else {
00085                 result = _directoryNode->resize( theNewSize,
00086                                                  _numPerLeaf,
00087                                                  _numPerDirectory );
00088                 if( BdbcSuccess == result ) {
00089 
00090                     if( newNumLevels == _numLevels ) {
00091 
00092                       // Nothing else to do. The previous call to resize to the initial
00093                       // directory node has done everything.
00094 
00095                         ;
00096 
00097                     } else {
00098 
00099                       // Find the "least sufficient" node in the tree of nodes.
00100                       // We're going to promote this node and reconnect it directly
00101                       // to the current node (either as a leaf or as a directory node).
00102 
00103                         BdbRef(CdbBdbSNodeP<E>) prevNode = _directoryNode;
00104                         BdbRef(CdbBdbSNodeP<E>) node     = ((const BdbRef(CdbBdbSDirectoryNodeP<E>)&) prevNode)->_nodes[0];
00105 
00106                         for( d_ULong i = 1; i < _numLevels - newNumLevels; ++i ) {
00107                             prevNode = node;
00108                             node     = ((const BdbRef(CdbBdbSDirectoryNodeP<E>)&) prevNode)->_nodes[0];
00109                         }
00110 
00111                       // Destroy the old tree of nodes except the found sub-branch
00112                       // (this is why we put 0 instead of its reference).
00113 
00114                         ((const BdbRef(CdbBdbSDirectoryNodeP<E>)&) prevNode)->_nodes[0] = 0;
00115                         BdbDelete( _directoryNode );
00116                         _directoryNode = 0;
00117 
00118                       // Connect the found node where it's appropriate
00119 
00120                         if( newNumLevels ) _directoryNode = (const BdbRef(CdbBdbSDirectoryNodeP<E>)&) node;
00121                         else               _leafNode      = (const BdbRef(CdbBdbSLeafNodeP<E>)&)      node;
00122                     }
00123                 }
00124             }
00125 
00126         } else {
00127 
00128             if( newNumLevels == 0 ) {
00129                 result = _leafNode->resize( theNewSize,
00130                                             _numPerLeaf,
00131                                             _numPerDirectory );
00132             } else {
00133 
00134                 if( newNumLevels == _numLevels ) {
00135                     result = _directoryNode->resize( theNewSize,
00136                                                      _numPerLeaf,
00137                                                      _numPerDirectory );
00138                 } else {
00139 
00140                   // Most complicated scenario - the current tree must grow
00141                   // in levels. We're going to reuse the current (either Leaf or Directory)
00142                   // node in the new tree.
00143 
00144                     BdbRef(CdbBdbSDirectoryNodeP<E>) newDirectoryNode = new( ooThis( )) CdbBdbSDirectoryNodeP<E>( newNumLevels );
00145                     if( _numLevels ) {
00146                         result = newDirectoryNode->resize( theNewSize,
00147                                                            _numPerLeaf,
00148                                                            _numPerDirectory,
00149                                                            _directoryNode );
00150                         if( BdbcSuccess == result ) {
00151                             _directoryNode = newDirectoryNode;
00152                         }
00153                     } else {
00154                         result = newDirectoryNode->resize( theNewSize,
00155                                                            _numPerLeaf,
00156                                                            _numPerDirectory,
00157                                                            _leafNode );
00158                         if( BdbcSuccess == result ) {
00159                             _leafNode      = 0;
00160                             _directoryNode = newDirectoryNode;
00161                         }
00162                     }
00163                 }
00164             }
00165         }
00166         if( BdbcSuccess == result ) {
00167             _numLevels = newNumLevels;
00168             _size      = theNewSize;
00169         }
00170     }
00171     return result;
00172 }
00173 
00174 /*
00175  * ATTENTION: Using virtual memory references is unsafe in persistent world
00176  *            since the (Objectivity) cache is out of our control.
00177  *            It's true for both read and write operations.
00178  *
00179  *            This is why we use two explicit (read/write) operations with values
00180  *            instead of this subscript operator. The only reason we still have
00181  *            this operator here is to attract attention to this problem.
00182  *
00183 template< typename E >
00184 E&
00185 CdbBdbSPagedVarrayP<E>::operator[]( d_ULong theIndex )
00186 {
00187     assert( theIndex < _size );
00188 
00189     if( ! _numLevels )
00190         return _leafNode->_data[theIndex];
00191 
00192     return _directoryNode->elementAt( theIndex,
00193                                       _numPerLeaf,
00194                                       _numPerDirectory );
00195 }
00196 */
00197 
00198 template< typename E >
00199 void
00200 CdbBdbSPagedVarrayP<E>::setElementAt( d_ULong  theIndex,
00201                                       const E& value )
00202 {
00203     assert( theIndex < _size );
00204 
00205     BdbRef( CdbBdbSNodeP<E> ) nodeRef;
00206     if( _numLevels ) nodeRef = _directoryNode;
00207     else             nodeRef = _leafNode;
00208 
00209     nodeRef->setElementAt( theIndex,
00210                            value,
00211                            _numPerLeaf,
00212                            _numPerDirectory );
00213 }
00214 
00215 template< typename E >
00216 E
00217 CdbBdbSPagedVarrayP<E>::elementAt( d_ULong theIndex ) const
00218 {
00219     assert( theIndex < _size );
00220 
00221     BdbRef( CdbBdbSNodeP<E> ) nodeRef;
00222     if( _numLevels ) nodeRef = _directoryNode;
00223     else             nodeRef = _leafNode;
00224 
00225     return nodeRef->elementAt( theIndex,
00226                                _numPerLeaf,
00227                                _numPerDirectory );
00228 }
00229 
00230 template< typename E >
00231 void
00232 CdbBdbSPagedVarrayP<E>::dump( ostream& o,
00233                               bool     dumpContentsFlag ) const
00234 {
00235     o << ooThis( ).sprint( ) << " : <PAGED V-ARRAY>" << endl
00236       << "  numPerLeaf      = " << _numPerLeaf << endl
00237       << "  numPerDirectory = " << _numPerDirectory << endl
00238       << "  numLevels       = " << _numLevels << endl
00239       << "  size            = " << _size << endl
00240       << "  leafNode        = " << _leafNode.sprint( ) << endl
00241       << "  directoryNode   = " << _directoryNode.sprint( ) << endl
00242       << "    ";
00243 
00244     if( _numLevels ) _directoryNode->dump( 4, o, dumpContentsFlag );
00245     else             _leafNode->dump     ( 4, o, dumpContentsFlag );
00246 }
00247 
00248 template< typename E >
00249 d_ULong
00250 CdbBdbSPagedVarrayP<E>::calculateNumLevels( d_ULong theSize ) const
00251 {
00252     if( theSize <= _numPerLeaf ) return 0;
00253 
00254     d_ULong result = 0;
00255     {
00256         d_ULong numPerNode = _numPerLeaf;
00257         do {
00258             ++result;
00259             numPerNode = numPerNode * _numPerDirectory;
00260         } while(( theSize - 1 ) / numPerNode ); // -1 is needed to avoid one extra step
00261     }
00262     return result;
00263 }
00264 
00265 template< typename E >
00266 d_ULong
00267 CdbBdbSPagedVarrayP<E>::defaultNumPerLeaf( ) const
00268 {
00269     ooHandle(ooFDObj) fdH;
00270     fdH = BdbApplicationOrDomain::activeInstance()->fd( );
00271 
00272     assert( ! BdbIsNull( fdH ));
00273 
00274   // We're going to use the default constructor to measure the size
00275   // of type "E" to avoid a compilation problem with "typedef E" from
00276   // a template class.
00277   //
00278   // NOTE: This constructor must be valid and w/o side effects!!!
00279 
00280     E e;
00281     d_ULong eSize = sizeof( e );
00282 
00283   // We're assuming that ooVArray overhead does not exceed 256 bytes per page.
00284 
00285     return ( fdH.pageSize( ) - 256 ) / eSize;
00286 }
00287 
00288 template< typename E >
00289 d_ULong
00290 CdbBdbSPagedVarrayP<E>::defaultNumPerDirectory( ) const
00291 {
00292     ooHandle(ooFDObj) fdH;
00293     fdH = BdbApplicationOrDomain::activeInstance()->fd( );
00294 
00295     assert( ! BdbIsNull( fdH ));
00296 
00297   // We're going to use the default constructor to measure the size
00298   // of type "ooRef(CdbBdbSNodeP<E>)" to avoid a compilation problem with
00299   // "typedef ooRef(CdbBdbSNodeP<E>)" from a template class.
00300   //
00301   // NOTE: This constructor must be valid and w/o side effects!!!
00302 
00303     ooRef(CdbBdbSNodeP<E>) nH;
00304     d_ULong nSize = sizeof( nH );
00305 
00306   // We're assuming that ooVArray overhead does not exceed 256 bytes per page.
00307 
00308     return ( fdH.pageSize( ) - 256 ) / nSize;
00309 }
00310 
00311 /////////////////
00312 // End Of File //
00313 /////////////////

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