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

CdbBdbSAbsBtree.cc

Go to the documentation of this file.
00001 // File and Version Information:
00002 //      $Id: CdbBdbSAbsBtree.cc,v 1.6 2004/08/06 05:54:24 bartoldu Exp $
00003 
00004 /// Implementation file for the CdbBdbSAbsBtree class
00005 /**
00006   * @see CdbBdbSAbsBtree
00007   */
00008 
00009 #include "BaBar/BaBar.hh"
00010 
00011 #if !defined(OO_DDL_TRANSLATION)
00012 #include "CdbBdbShared/CdbBdbSAbsBtree.hh"
00013 #endif // OO_DDL_TRANSLATION
00014 
00015 #include <assert.h>
00016 using std::endl;
00017 using std::ostream;
00018 
00019 template< class K,
00020           class FCP,
00021           class ORDER >
00022 CdbBdbSAbsBtree<K,FCP,ORDER>::CdbBdbSAbsBtree( )
00023 { }
00024 
00025 template< class K,
00026           class FCP,
00027           class ORDER >
00028 CdbBdbSAbsBtree<K,FCP,ORDER>::~CdbBdbSAbsBtree( )
00029 { }
00030 
00031 template< class K,
00032           class FCP,
00033           class ORDER >
00034 void
00035 CdbBdbSAbsBtree<K,FCP,ORDER>::dump( ostream& o ) const
00036 {
00037     dump( o, root( ), 0 );
00038 }
00039 
00040 template< class K,
00041           class FCP,
00042           class ORDER >
00043 void
00044 CdbBdbSAbsBtree<K,FCP,ORDER>::insert( const K& key )
00045 {
00046     if( ! search( key )) {
00047 
00048         d_ULong node = searchLeafForInsert( root( ), key );
00049         if( readNode( node ).n < 2*N ) {
00050 
00051             insertKeyOnly( node, key );
00052 
00053         } else {
00054 
00055             d_ULong parent = readNode( node ).parent;
00056 
00057           // Insert new element into a temporary array (has one more element
00058           // than allowed.
00059 
00060             K tmp[2*N+1];
00061             {
00062                 tmp[2*N] = key;     // By default - just append. This may be overwriten
00063                                     // by the loop below if the element needs to be inserted.
00064 
00065                 CdbBdbSBtreeNode<K,ORDER> nodeValue = readNode( node );
00066                 {
00067                     K* iKeyPtr = &( nodeValue.key[0] );
00068                     K* oKeyPtr = &(           tmp[0] );
00069 
00070                     for( unsigned int i = 0; i < 2*N; ++i ) {
00071                         if( key < *iKeyPtr ) {
00072 
00073                           // Insert the key, copy the tail and break.
00074 
00075                             *(oKeyPtr++) = key;
00076                             for( unsigned int j = i; j < 2*N; ++j ) *(oKeyPtr++) = *(iKeyPtr++);
00077 
00078                             break;
00079 
00080                         } else {
00081                             *(oKeyPtr++) = *(iKeyPtr++);
00082                         }
00083                     }
00084                 }
00085             }
00086 
00087           // Split the leaf only and promote the middle element up.
00088 
00089             d_ULong                   nLeft      = allocate( parent );
00090             CdbBdbSBtreeNode<K,ORDER> nLeftValue = readNode( nLeft );
00091             {
00092                 nLeftValue.n = N;
00093                 for( unsigned int i = 0; i < N; ++i ) nLeftValue.key[i] = tmp[i];
00094             }
00095             updateNode( nLeft, nLeftValue );
00096 
00097             d_ULong                   nRight      = allocate( parent );
00098             CdbBdbSBtreeNode<K,ORDER> nRightValue = readNode( nRight );
00099             {
00100                 nRightValue.n = N;
00101                 for( unsigned int i = 0; i < N; ++i ) nRightValue.key[i] = tmp[N+1+i];
00102             }
00103             updateNode( nRight, nRightValue );
00104 
00105           // The further scenario depends on which node we're going to split.
00106           // If it's the root node itself (which may happen if we're just filled
00107           // it up then we will split it by making it a non-leaf node.
00108           //
00109           // Otherwise we'll propagate this operation to a parent of
00110           // the current node
00111 
00112             if( parent ) {
00113 
00114               // Propagate operation up to the parent.
00115 
00116                 if( readNode( parent ).n < 2*N ) {
00117 
00118                     insertNoSplit( parent,
00119                                    tmp[N],
00120                                    node,
00121                                    nLeft,
00122                                    nRight );
00123                 } else {
00124 
00125                     insertAndSplit( parent,
00126                                     tmp[N],
00127                                     node,
00128                                     nLeft,
00129                                     nRight );
00130                 }
00131                 release( node );
00132 
00133             } else {
00134 
00135               // Promote the leaf root node onto a non-leaf one.
00136 
00137                 CdbBdbSBtreeNode<K,ORDER> nodeValue = readNode( node );
00138                 {
00139                     nodeValue.isLeaf = false;
00140                     nodeValue.n      = 1;
00141 
00142                     nodeValue.key[0] = tmp[N];
00143 
00144                     nodeValue.child[0] = nLeft;
00145                     nodeValue.child[1] = nRight;
00146                 }
00147                 updateNode( node, nodeValue );
00148 
00149                 CdbBdbSBtreeNode<K,ORDER> nLeftValue = readNode( nLeft );
00150                 {
00151                     nLeftValue.parent = node;
00152                 }
00153                 updateNode( nLeft, nLeftValue );
00154 
00155                 CdbBdbSBtreeNode<K,ORDER> nRightValue = readNode( nRight );
00156                 {
00157                     nRightValue.parent = node;
00158                 }
00159                 updateNode( nRight, nRightValue );
00160             }
00161         }
00162     }
00163 }
00164 
00165 template< class K,
00166           class FCP,
00167           class ORDER >
00168 void
00169 CdbBdbSAbsBtree<K,FCP,ORDER>::remove( const K& key )
00170 {
00171     d_ULong node = doSearch( root( ), key );
00172     if( node ) {
00173 
00174         if( readNode( node ).isLeaf ) {
00175 
00176             removeFromLeaf( node, key );
00177             return;
00178 
00179         } else {
00180 
00181           // To removing from a non-leaf node we need to swap this key
00182           // with an appropriate (next) key in a leaf node below.
00183           // Then we just do removal from the leaf node.
00184 
00185             CdbBdbSBtreeNode<K,ORDER> nodeValue = readNode( node );
00186 
00187             for( unsigned int i = 0; i < nodeValue.n; ++i ) {
00188                 if( key == nodeValue.key[i] ) {
00189 
00190                   // Find an appropriate leaf node for swapping.
00191 
00192                     d_ULong                   leafNode      = nodeValue.child[i+1];
00193                     CdbBdbSBtreeNode<K,ORDER> leafNodeValue = readNode( leafNode );
00194 
00195                     while( ! leafNodeValue.isLeaf ) {
00196                         leafNode      = leafNodeValue.child[0];
00197                         leafNodeValue = readNode( leafNode );
00198                     }
00199 
00200                   // Swap the keys
00201                   //
00202                   // NOTE: We must be careful with the actual values of the keys
00203                   //       because the comparision of the keys may be based on a subset
00204                   //       of information held by the corresponding objects.
00205 
00206                     K tmp = nodeValue.key[i];
00207 
00208                     nodeValue.key[i]     = leafNodeValue.key[0];
00209                     leafNodeValue.key[0] = tmp;
00210 
00211                     updateNode( node,     nodeValue );
00212                     updateNode( leafNode, leafNodeValue );
00213 
00214                   // Go and remove the key from the leaf.
00215 
00216                     removeFromLeaf( leafNode, key );
00217                     return;
00218                 }
00219             }
00220         }
00221         assert( 0 );    // B-tree corruption. Failed to remove a key.
00222     }
00223 }
00224 
00225 template< class K,
00226           class FCP,
00227           class ORDER >
00228 bool
00229 CdbBdbSAbsBtree<K,FCP,ORDER>::search( const K& key ) const
00230 {
00231     return 0 != doSearch( root( ),
00232                           key );
00233 }
00234 
00235 template< class K,
00236           class FCP,
00237           class ORDER >
00238 bool
00239 CdbBdbSAbsBtree<K,FCP,ORDER>::search( const K& key,
00240                                       K&       result ) const
00241 {
00242     d_ULong node = doSearch( root( ),
00243                              key );
00244     if( node ) {
00245 
00246       // Search again for the key in the found node.
00247       //
00248       // NOTE: The search algorithm is a little bit inefficient
00249       //       in some sense because the presence of the target key
00250       //       has already been identified by the search algorithm
00251 
00252         CdbBdbSBtreeNode<K,ORDER> nodeValue = readNode( node );
00253 
00254         for( unsigned int i = 0; i < nodeValue.n; i++ ) {
00255             if( key == nodeValue.key[i] ) {
00256                 result = nodeValue.key[i];
00257                 return true;
00258             }
00259         }
00260         assert( 0 );    // B-tree corruption. Unexpected branch of execution.
00261     }
00262     return false;
00263 }
00264 
00265 template< class K,
00266           class FCP,
00267           class ORDER >
00268 bool
00269 CdbBdbSAbsBtree<K,FCP,ORDER>::fuzzySearch( const K& key,
00270                                            K&       result ) const
00271 {
00272     return 0 != doFuzzySearch( root( ),
00273                                key,
00274                                result );
00275 }
00276 
00277 template< class K,
00278           class FCP,
00279           class ORDER >
00280 void
00281 CdbBdbSAbsBtree<K,FCP,ORDER>::reset( )
00282 {
00283     reset( root( ));
00284 }
00285 
00286 template< class K,
00287           class FCP,
00288           class ORDER >
00289 CdbItr<K>
00290 CdbBdbSAbsBtree<K,FCP,ORDER>::iterator( ) const
00291 {
00292   // ATTENTION: This is not a memory leak - the created object
00293   //            will be destroyed by the iterator.
00294 
00295     return CdbItr<K>( new CdbBdbSAbsBtreeItr<K,FCP,ORDER>( this ));
00296 }
00297 
00298 template< class K,
00299           class FCP,
00300           class ORDER >
00301 void
00302 CdbBdbSAbsBtree<K,FCP,ORDER>::spaces( ostream&     o,
00303                                       unsigned int level ) const
00304 {
00305     for( int i = 0; i < 2*level; ++i ) o << ' ';
00306 }
00307 
00308 template< class K,
00309           class FCP,
00310           class ORDER >
00311 void
00312 CdbBdbSAbsBtree<K,FCP,ORDER>::dump( ostream&     o,
00313                                     d_ULong      node,
00314                                     unsigned int level ) const
00315 {
00316     CdbBdbSBtreeNode<K,ORDER> nodeValue = readNode( node );
00317 
00318     spaces( o, level );
00319 
00320     o << node << ": [ ";
00321     for( int i = 0; i < nodeValue.n; ++i ) o << nodeValue.key[i] << ' ';
00322     o << "] "<< "< " << nodeValue.parent << " :";
00323 
00324     if( nodeValue.isLeaf ) {
00325         o << " >" << endl;
00326     } else {
00327 
00328         for( int i = 0; i < nodeValue.n + 1; ++i ) o << " " << nodeValue.child[i];
00329         o << " >" << endl;
00330 
00331         for( int i = 0; i < nodeValue.n + 1; ++i ) dump( o, nodeValue.child[i], level + 1 );
00332     }
00333 }
00334 
00335 template< class K,
00336           class FCP,
00337           class ORDER >
00338 d_ULong
00339 CdbBdbSAbsBtree<K,FCP,ORDER>::doSearch( d_ULong  node,
00340                                         const K& key ) const
00341 {
00342   // The pointer must be valid and the node's occupancy must be non 0.
00343 
00344     if( node ) {
00345 
00346         CdbBdbSBtreeNode<K,ORDER> nodeValue = readNode( node );
00347         if( nodeValue.n ) {
00348 
00349           // Search for the key in the current node first.
00350 
00351             for( unsigned int i = 0; i < nodeValue.n; i++ )
00352                 if( key == nodeValue.key[i] ) return node;
00353 
00354           // If the children are present then proceed the search doesn the tree.
00355 
00356             if( ! nodeValue.isLeaf ) {
00357 
00358                 for( unsigned int i = 0; i < nodeValue.n; i++ )
00359                     if( key < nodeValue.key[i] ) return doSearch( nodeValue.child[i],
00360                                                                   key );
00361 
00362                 return doSearch( nodeValue.child[ nodeValue.n ],
00363                                  key );
00364             }
00365         }
00366     }
00367     return 0;
00368 }
00369 
00370 template< class K,
00371           class FCP,
00372           class ORDER >
00373 d_ULong
00374 CdbBdbSAbsBtree<K,FCP,ORDER>::doFuzzySearch( d_ULong  node,
00375                                              const K& key,
00376                                              K&       result ) const
00377 {
00378   // The pointer must be valid and the node's occupancy must be non 0.
00379 
00380     if( node ) {
00381 
00382         CdbBdbSBtreeNode<K,ORDER> nodeValue = readNode( node );
00383         if( nodeValue.n ) {
00384 
00385           // Search for an appropriate match in the current node first
00386           // using "fuzzy" comparision policy.
00387 
00388             for( unsigned int i = 0; i < nodeValue.n; i++ )
00389                 if( FCP::match( key,
00390                                 nodeValue.key[i] )) {
00391                     result = nodeValue.key[i];
00392                     return node;
00393                 }
00394 
00395           // If the children are present then proceed the search doesn the tree.
00396 
00397             if( ! nodeValue.isLeaf ) {
00398 
00399                 for( unsigned int i = 0; i < nodeValue.n; i++ )
00400                     if( key < nodeValue.key[i] ) return doFuzzySearch( nodeValue.child[i],
00401                                                                        key,
00402                                                                        result );
00403 
00404                 return doFuzzySearch( nodeValue.child[ nodeValue.n ],
00405                                       key,
00406                                       result );
00407             }
00408         }
00409     }
00410     return 0;
00411 }
00412 
00413 template< class K,
00414           class FCP,
00415           class ORDER >
00416 d_ULong
00417 CdbBdbSAbsBtree<K,FCP,ORDER>::searchLeafForInsert( d_ULong  node,
00418                                                    const K& key ) const
00419 {
00420     CdbBdbSBtreeNode<K,ORDER> nodeValue = readNode( node );
00421     if( nodeValue.isLeaf ) return node;
00422 
00423     for( unsigned int i = 0; i < nodeValue.n; i++ )
00424         if( key < nodeValue.key[i] ) return searchLeafForInsert( nodeValue.child[i],
00425                                                                  key );
00426 
00427     return searchLeafForInsert( nodeValue.child[ nodeValue.n ],
00428                                 key );
00429 }
00430 
00431 template< class K,
00432           class FCP,
00433           class ORDER >
00434 void
00435 CdbBdbSAbsBtree<K,FCP,ORDER>::insertKeyOnly( d_ULong  node,
00436                                              const K& key )
00437 {
00438   // Insert the key into a leaf node assuming that there is at least one place.
00439 
00440     CdbBdbSBtreeNode<K,ORDER> nodeValue = readNode( node );
00441     {
00442       // Check if new key needs to shift others.
00443 
00444         for( unsigned int i = 0; i < nodeValue.n; ++i )
00445             if( key < nodeValue.key[i] ) {
00446 
00447               // Shift one element right to have a room for the new key.
00448 
00449                 for( unsigned int j = nodeValue.n; j > i; --j )
00450                     nodeValue.key[j] = nodeValue.key[j-1];
00451 
00452                 nodeValue.key[i] = key;
00453                 ++( nodeValue.n );
00454 
00455                 updateNode( node, nodeValue );
00456 
00457                 return;
00458             }
00459 
00460       // Append by the end of the list.
00461 
00462         nodeValue.key[ ( nodeValue.n )++ ] = key;
00463     }
00464     updateNode( node, nodeValue );
00465 
00466     return;
00467 }
00468 
00469 template< class K,
00470           class FCP,
00471           class ORDER >
00472 void
00473 CdbBdbSAbsBtree<K,FCP,ORDER>::insertNoSplit( d_ULong  parent,
00474                                              const K& key,
00475                                              d_ULong  old,
00476                                              d_ULong  left,
00477                                              d_ULong  right )
00478 {
00479   // Insert new element into specified parent node. Also replace the old child with
00480   // a couple of new ones surrounding the newely inserted element.
00481 
00482     insertKeyOnly( parent, key );
00483 
00484   // Find the old child and replace it with new ones. Make a shift if needed
00485   // to have more room for the right child.
00486   //
00487   // NOTE: This operation assumes that the counter of the node's occupancy
00488   //       has already been incremented.
00489 
00490     CdbBdbSBtreeNode<K,ORDER> parentValue = readNode( parent );
00491     {
00492         for( unsigned int i = 0; i < parentValue.n; ++i ) {
00493             if( parentValue.child[i] == old ) {
00494 
00495               // Shift one element right to have a room for the new link.
00496 
00497                 for( unsigned int j = parentValue.n; j > i; --j ) parentValue.child[j] = parentValue.child[j-1];
00498 
00499                 parentValue.child[i]   = left;
00500                 parentValue.child[i+1] = right;
00501 
00502                 break;
00503             }
00504         }
00505     }
00506     updateNode( parent, parentValue );
00507 }
00508 
00509 template< class K,
00510           class FCP,
00511           class ORDER >
00512 void
00513 CdbBdbSAbsBtree<K,FCP,ORDER>::insertAndSplit( d_ULong  parent,
00514                                               const K& key,
00515                                               d_ULong  old,
00516                                               d_ULong  left,
00517                                               d_ULong  right )
00518 {
00519   // Insert new element into specified parent node. Also replace the old child with
00520   // a couple of new ones surrounding the newely inserted element.
00521   // Split the parent.
00522 
00523     CdbBdbSBtreeNode<K,ORDER> parentValue = readNode( parent );
00524     {
00525 
00526       // Insert new element into a temporary array (has one more element
00527       // than allowed.
00528 
00529         K tmp[2*N+1];
00530         {
00531             tmp[2*N] = key;     // By default - just append. This may be overwriten
00532                                 // by the loop below if the element needs to be inserted.
00533 
00534             K* iKeyPtr = &( parentValue.key[0] );
00535             K* oKeyPtr = &(             tmp[0] );
00536 
00537             for( unsigned int i = 0; i < 2*N; ++i ) {
00538                 if( key < *iKeyPtr ) {
00539 
00540                   // Insert the key, copy the tail and break.
00541 
00542                     *(oKeyPtr++) = key;
00543                     for( unsigned int j = i; j < 2*N; ++j ) *(oKeyPtr++) = *(iKeyPtr++);
00544 
00545                     break;
00546 
00547                 } else {
00548                     *(oKeyPtr++) = *(iKeyPtr++);
00549                 }
00550             }
00551         }
00552 
00553       // Replace old link with two new ones in a temporary array (has one more element
00554       // than allowed.
00555 
00556         d_ULong tmp_child[2*N+2];
00557         {
00558           // Just copy all links into a temporary array.
00559 
00560             for( unsigned int i = 0; i < 2*N+1; ++i ) {
00561                 tmp_child[i] = parentValue.child[i];
00562             }
00563 
00564           // Then insert new elements.
00565 
00566             for( unsigned int i = 0; i < 2*N+1; ++i ) {
00567                 if( tmp_child[i] == old ) {
00568 
00569                   // Shift one element right to have a room for the new link.
00570 
00571                     for( unsigned int j = 2*N+1; j > i; --j ) tmp_child[j] = tmp_child[j-1];
00572 
00573                     tmp_child[i]   = left;
00574                     tmp_child[i+1] = right;
00575 
00576                     break;
00577                 }
00578             }
00579         }
00580 
00581       // Split the parent and promote the middle element up.
00582 
00583         d_ULong                   parentOfParent      = parentValue.parent;
00584         CdbBdbSBtreeNode<K,ORDER> parentOfParentValue = readNode( parentOfParent );
00585 
00586         d_ULong                   nLeft      = allocate( parentOfParent );
00587         CdbBdbSBtreeNode<K,ORDER> nLeftValue = readNode( nLeft );
00588         {
00589             nLeftValue.isLeaf = false;
00590             nLeftValue.n      = N;
00591 
00592             for( unsigned int i = 0; i < N;   ++i ) nLeftValue.key[i] = tmp[i];
00593             for( unsigned int i = 0; i < N+1; ++i ) {
00594 
00595                 nLeftValue.child[i] = tmp_child[i];
00596 
00597                 CdbBdbSBtreeNode<K,ORDER> nLeftChildValue = readNode( nLeftValue.child[i] );
00598                 { nLeftChildValue.parent = nLeft; }
00599                 updateNode( nLeftValue.child[i], nLeftChildValue );
00600             }
00601         }
00602         updateNode( nLeft, nLeftValue );
00603 
00604         d_ULong                   nRight      = allocate( parentOfParent );
00605         CdbBdbSBtreeNode<K,ORDER> nRightValue = readNode( nRight );
00606         {
00607             nRightValue.isLeaf = false;
00608             nRightValue.n      = N;
00609 
00610             for( unsigned int i = 0; i < N;   ++i ) nRightValue.key[i] = tmp[N+1+i];
00611             for( unsigned int i = 0; i < N+1; ++i ) {
00612 
00613                 nRightValue.child[i] = tmp_child[N+1+i];
00614 
00615                 CdbBdbSBtreeNode<K,ORDER> nRightChildValue = readNode( nRightValue.child[i] );
00616                 { nRightChildValue.parent = nRight; }
00617                 updateNode( nRightValue.child[i], nRightChildValue );
00618             }
00619         }
00620         updateNode( nRight, nRightValue );
00621 
00622         if( parentOfParent ) {
00623 
00624           // Follow the split if the "parent of parent" is not a root node.
00625 
00626             if( parentOfParentValue.n < 2*N ) {
00627 
00628                 insertNoSplit( parentOfParent,
00629                                tmp[N],
00630                                parent,
00631                                nLeft,
00632                                nRight );
00633             } else {
00634 
00635                 insertAndSplit( parentOfParent,
00636                                 tmp[N],
00637                                 parent,
00638                                 nLeft,
00639                                 nRight );
00640             }
00641 
00642         } else {
00643 
00644           // Create new root.
00645 
00646             d_ULong                   newRoot      = allocate( );
00647             CdbBdbSBtreeNode<K,ORDER> newRootValue = readNode( newRoot );
00648             {
00649                 newRootValue.isLeaf = false;
00650                 newRootValue.n      = 1;
00651 
00652                 newRootValue.key[0] = tmp[N];
00653 
00654                 newRootValue.child[0] = nLeft;
00655                 newRootValue.child[1] = nRight;
00656 
00657                 CdbBdbSBtreeNode<K,ORDER> nLeftValue = readNode( nLeft );
00658                 { nLeftValue.parent = newRoot; }
00659                 updateNode( nLeft, nLeftValue );
00660 
00661                 CdbBdbSBtreeNode<K,ORDER> nRightValue = readNode( nRight );
00662                 { nRightValue.parent = newRoot; }
00663                 updateNode( nRight, nRightValue );
00664             }
00665             updateNode( newRoot, newRootValue );
00666 
00667             set_root( newRoot );
00668         }
00669     }
00670     release( parent );
00671 }
00672 
00673 template< class K,
00674           class FCP,
00675           class ORDER >
00676 void
00677 CdbBdbSAbsBtree<K,FCP,ORDER>::removeFromLeaf( d_ULong  node,
00678                                               const K& key )
00679 {
00680   // Remove element no mattter if less than allowed is left.
00681   // The subsequent rebalancing will correct this situation if needed.
00682 
00683     CdbBdbSBtreeNode<K,ORDER> nodeValue = readNode( node );
00684     {
00685         for( unsigned int i = 0; i < nodeValue.n; ++i ) {
00686             if( key == nodeValue.key[i] ) {
00687 
00688                 for( unsigned int j = i; j < nodeValue.n - 1; ++j )
00689                     nodeValue.key[j] = nodeValue.key[j+1];
00690 
00691                 --( nodeValue.n );
00692 
00693                 break;
00694             }
00695         }
00696     }
00697     updateNode( node, nodeValue );
00698 
00699   // If this is the root node then we are allowed
00700   // to remove all elements.
00701 
00702     if(( ! nodeValue.parent ) || ( nodeValue.n >= N )) {
00703 
00704       // No repalancing is needed.
00705 
00706         ;
00707 
00708     } else {
00709 
00710       // Go to rebalance the tree
00711 
00712         rebalance( node );
00713     }
00714 }
00715 
00716 template< class K,
00717           class FCP,
00718           class ORDER >
00719 void
00720 CdbBdbSAbsBtree<K,FCP,ORDER>::rebalance( d_ULong node )
00721 {
00722     d_ULong parent = readNode( node ).parent;
00723 
00724     assert( parent );   // B-tree corruption. Unexpected branch of execution.
00725 
00726  // Try simplest methods first.
00727 
00728     if( borrowFromLeft ( node )) return;
00729     if( borrowFromRight( node )) return;
00730 
00731   // Force joining with neighbors.
00732 
00733     join( node );
00734 
00735   // Check if previous has triggered "underflow" condition
00736   // at the parent.
00737 
00738     CdbBdbSBtreeNode<K,ORDER> parentValue = readNode( parent );
00739     if( parentValue.n < N ) {
00740 
00741       // The root node needs special processing.
00742 
00743         d_ULong parentOfParent = parentValue.parent;
00744         if( ! parentOfParent ) {
00745 
00746             if( 0 == parentValue.n ) {
00747 
00748                 d_ULong newRoot = parentValue.child[0];
00749                 {
00750                     CdbBdbSBtreeNode<K,ORDER> newRootValue = readNode( newRoot );
00751                     { newRootValue.parent = 0; }
00752                     updateNode( newRoot, newRootValue );
00753                 }
00754                 set_root( newRoot );
00755 
00756                 release( parent );
00757             }
00758 
00759         } else {
00760 
00761           // Proceed up with rebalancing of a regular "underflow"-ed
00762           // non-leaf node.
00763 
00764             rebalance( parent );
00765         }
00766     }
00767 }
00768 
00769 template< class K,
00770           class FCP,
00771           class ORDER >
00772 bool
00773 CdbBdbSAbsBtree<K,FCP,ORDER>::borrowFromLeft( d_ULong right )
00774 {
00775     d_ULong parent = readNode( right ).parent;
00776 
00777     assert( parent );   // B-tree corruption. Unexpected branch of execution.
00778 
00779     CdbBdbSBtreeNode<K,ORDER> parentValue = readNode( parent );
00780 
00781     for( unsigned int i = 0; i < parentValue.n + 1; ++i ) {
00782         if( right == parentValue.child[i] ) {
00783             if( i ) {
00784 
00785                 d_ULong left = parentValue.child[i-1];
00786 
00787               // Check if there is one extra key in _any_ left node of the current parent.
00788               //
00789               // NOTE: Effectivly what we're doing is a right shift for one key
00790               //       through the parent using as many nodes from the left
00791               //       as we have in our disposal.
00792               //
00793               // IMPLEMENTATION NOTE: This little optimization has to be studied
00794               //                      to prove the overall performance improvement
00795               //                      for the removal algorithm. What we expect
00796               //                      to gain by this optimization is to reduce
00797               //                      the chance for other (heavier) rebalancing
00798               //                      methods to be triggered.
00799 
00800                 if(( readNode( left ).n > N ) || borrowFromLeft( left )) {
00801 
00802                   // Re-read parent and left nodes since they might be modified as a result
00803                   // recursive borrowing from the left.
00804 
00805                     CdbBdbSBtreeNode<K,ORDER> parentValue = readNode( parent );
00806                     CdbBdbSBtreeNode<K,ORDER> leftValue   = readNode( left );
00807                     CdbBdbSBtreeNode<K,ORDER> rightValue  = readNode( right );
00808                     {
00809                       // Copy middle key from the parent and insert it as the left-most
00810                       // key of the right node to have enough (N) keys in there.
00811 
00812                         for( unsigned int j = rightValue.n; j > 0; --j ) {
00813                             rightValue.key[j] = rightValue.key[j-1];
00814                         }
00815                         rightValue.key[0] = parentValue.key[i-1];
00816                         ++( rightValue.n );
00817 
00818                       // Remove the right-most key from the left node and put it
00819                       // instead of the middle key of the parent.
00820 
00821                         parentValue.key[i-1] = leftValue.key[ --( leftValue.n ) ];
00822 
00823                       // Remove the right-most child from the left node and insert it
00824                       // as the left-most child of the right node to have N+1 children in here.
00825 
00826                         if( ! rightValue.isLeaf ) {
00827                             for( unsigned int j = rightValue.n; j > 0; --j ) {
00828                                 rightValue.child[j] = rightValue.child[j-1];
00829                             }
00830                             rightValue.child[0] = leftValue.child[ leftValue.n + 1 ];
00831 
00832                             CdbBdbSBtreeNode<K,ORDER> newLeftMostChild = readNode( rightValue.child[0] );
00833                             { newLeftMostChild.parent = right; }
00834                             updateNode( rightValue.child[0], newLeftMostChild );
00835                         }
00836                     }
00837                     updateNode( parent, parentValue );
00838                     updateNode( left,   leftValue   );
00839                     updateNode( right,  rightValue  );
00840 
00841                   // Success.
00842 
00843 //                    cout << "borrowFromLeft:" << endl;
00844 //                    dump( cout );
00845 
00846                     return true;
00847                 }
00848             }
00849         }
00850     }
00851     return false;
00852 }
00853 
00854 template< class K,
00855           class FCP,
00856           class ORDER >
00857 bool
00858 CdbBdbSAbsBtree<K,FCP,ORDER>::borrowFromRight( d_ULong left )
00859 {
00860     d_ULong parent = readNode( left ).parent;
00861 
00862     assert( parent );   // B-tree corruption. Unexpected branch of execution.
00863 
00864     CdbBdbSBtreeNode<K,ORDER> parentValue = readNode( parent );
00865 
00866     for( unsigned int i = 0; i < parentValue.n; ++i ) {
00867         if( left == parentValue.child[i] ) {
00868 
00869             d_ULong right = parentValue.child[i+1];
00870 
00871           // Check if there is one extra key in _any_ right node on the current parent.
00872           //
00873           // NOTE: Effectivly what we're doing is a right shift for one key
00874           //       through the parent using as many nodes from the right
00875           //       as we have in our disposal.
00876           //
00877           // IMPLEMENTATION NOTE: This little optimization has to be studied
00878           //                      to prove the overall performance improvement
00879           //                      for the removal algorithm. What we expect
00880           //                      to gain by this optimization is to reduce
00881           //                      the chance for other (heavier) rebalancing
00882           //                      methods to be triggered.
00883 
00884             if(( readNode( right ).n > N ) || borrowFromRight( right )) {
00885 
00886               // Re-read parent and right nodes since they might be modified as a result
00887               // recursive borrowing from the right.
00888 
00889                 CdbBdbSBtreeNode<K,ORDER> parentValue = readNode( parent );
00890                 CdbBdbSBtreeNode<K,ORDER> leftValue   = readNode( left );
00891                 CdbBdbSBtreeNode<K,ORDER> rightValue  = readNode( right );
00892                 {
00893 
00894                   // Copy middle key from the parent and append it as the right-most
00895                   // key in the left node to have enough (N) keys in there.
00896 
00897                     leftValue.key[ ( leftValue.n )++ ] = parentValue.key[i];
00898 
00899                   // Remove the left-most key from the right node and put it
00900                   // instead of the middle key of the parent.
00901 
00902                     parentValue.key[i] = rightValue.key[0];
00903 
00904                     --( rightValue.n );
00905                     for( unsigned int j = 0; j < rightValue.n; ++j ) {
00906                         rightValue.key[j] = rightValue.key[j+1];
00907                     }
00908 
00909                   // Remove the left-most child from the right node and append it
00910                   // as the right-most child of the left node to have N+1 children in here.
00911 
00912                     if( ! leftValue.isLeaf ) {
00913 
00914                         CdbBdbSBtreeNode<K,ORDER> newRightMostChild = readNode( rightValue.child[0] );
00915                         { newRightMostChild.parent = left; }
00916                         updateNode( rightValue.child[0], newRightMostChild );
00917 
00918                         leftValue.child[ leftValue.n ] = rightValue.child[0];
00919                         for( unsigned int j = 0; j < rightValue.n + 1; ++j ) {
00920                             rightValue.child[j] = rightValue.child[j+1];
00921                         }
00922                     }
00923                 }
00924                 updateNode( parent, parentValue );
00925                 updateNode( left,   leftValue   );
00926                 updateNode( right,  rightValue  );
00927 
00928               // Success.
00929 
00930                 return true;
00931             }
00932         }
00933     }
00934     return false;
00935 }
00936 
00937 template< class K,
00938           class FCP,
00939           class ORDER >
00940 void
00941 CdbBdbSAbsBtree<K,FCP,ORDER>::join( d_ULong node )
00942 {
00943     d_ULong parent = readNode( node ).parent;
00944 
00945     assert( parent );           // B-tree corruption. Unexpected branch of execution.
00946 
00947     CdbBdbSBtreeNode<K,ORDER> parentValue = readNode( parent );
00948     
00949     assert( parentValue.n );    // B-tree corruption. Unexpected branch of execution.
00950 
00951     for( unsigned int i = 0; i < parentValue.n + 1; ++i ) {
00952         if( node == parentValue.child[i] ) {
00953 
00954           // Try left leaf
00955 
00956             if( i ) {
00957 
00958                 d_ULong left = parentValue.child[i-1];
00959 
00960                 CdbBdbSBtreeNode<K,ORDER> leftValue = readNode( left );
00961                 CdbBdbSBtreeNode<K,ORDER> nodeValue = readNode( node );
00962 
00963                 if(( leftValue.n + 1 + nodeValue.n ) == 2*N ) {
00964 
00965                     unsigned int left_n_before = leftValue.n;
00966 
00967                   // Copy the middle key from the parent and append it as the right-most
00968                   // key of the left node.
00969 
00970                     leftValue.key[ ( leftValue.n )++ ] = parentValue.key[i-1];
00971 
00972                   // Copy remaining keys from the node and append them as right-most elements
00973                   // of the left node.
00974 
00975                     for( unsigned int j = 0; j < nodeValue.n; ++j )
00976                         leftValue.key[ ( leftValue.n )++ ] = nodeValue.key[j];
00977 
00978                   // Shrink the parent by one node. In fact we're going
00979                   // to make left shift operation.
00980 
00981                     for( unsigned int j = i; j < parentValue.n; ++j )
00982                         parentValue.key[j-1] = parentValue.key[j];
00983 
00984                     for( unsigned int j = i; j < parentValue.n; ++j )
00985                         parentValue.child[j] = parentValue.child[j+1];
00986 
00987                     --( parentValue.n );
00988                     
00989                   // Copy all the children of the current node and append them
00990                   // as the right-most children of the left node.
00991 
00992                     if( ! nodeValue.isLeaf ) {
00993                         for( unsigned int j = 0; j < nodeValue.n + 1; ++j ) {
00994 
00995                             CdbBdbSBtreeNode<K,ORDER> newRightMostChild = readNode( nodeValue.child[j] );
00996                             { newRightMostChild.parent = left; }
00997                             updateNode( nodeValue.child[j], newRightMostChild );
00998 
00999                             leftValue.child[++left_n_before] = nodeValue.child[j];
01000                         }
01001                     }
01002 
01003                     updateNode( parent, parentValue );
01004                     updateNode( left,   leftValue   );
01005                     updateNode( node,   nodeValue   );
01006 
01007                   // Destroy the emptied node.
01008 
01009                     release( node );
01010 
01011                   // Success.
01012 
01013                     return;
01014                 }
01015             }
01016 
01017           // Try right leaf
01018 
01019             if( i < parentValue.n ) {
01020 
01021                 d_ULong right = parentValue.child[i+1];
01022 
01023                 CdbBdbSBtreeNode<K,ORDER> nodeValue  = readNode( node );
01024                 CdbBdbSBtreeNode<K,ORDER> rightValue = readNode( right );
01025 
01026                 if(( nodeValue.n + 1 + rightValue.n ) == 2*N ) {
01027 
01028                     unsigned int node_n_before = nodeValue.n;
01029 
01030                   // Copy the middle key from the parent and append it as the right-most
01031                   // key of the current node.
01032 
01033                     nodeValue.key[ ( nodeValue.n )++ ] = parentValue.key[i];
01034 
01035                   // Copy keys from the right node and append them as right-most elements
01036                   // of the current node.
01037 
01038                     for( unsigned int j = 0; j < rightValue.n; ++j )
01039                         nodeValue.key[ ( nodeValue.n )++ ] = rightValue.key[j];
01040 
01041                   // Shrink the parent by one node. In fact we're going
01042                   // to make left shift operation.
01043 
01044                     --( parentValue.n );
01045 
01046                     for( unsigned int j = i; j < parentValue.n; ++j )
01047                         parentValue.key[j] = parentValue.key[j+1];
01048 
01049                     for( unsigned int j = i + 1; j < parentValue.n + 1; ++j )
01050                         parentValue.child[j] = parentValue.child[j+1];
01051                     
01052                   // Copy all the children of the right node and append them
01053                   // as the right-most children of the current node.
01054 
01055                     if( ! nodeValue.isLeaf ) {
01056                         for( unsigned int j = 0; j < rightValue.n + 1; ++j ) {
01057 
01058                             CdbBdbSBtreeNode<K,ORDER> newRightMostChild = readNode( rightValue.child[j] );
01059                             { newRightMostChild.parent = node; }
01060                             updateNode( rightValue.child[j], newRightMostChild );
01061 
01062                             nodeValue.child[++node_n_before] = rightValue.child[j];
01063                         }
01064                     }
01065 
01066                     updateNode( parent, parentValue );
01067                     updateNode( node,   nodeValue   );
01068                     updateNode( right,  rightValue  );
01069 
01070                   // Destroy the emptied node.
01071 
01072                     release( right );
01073 
01074                   // Success.
01075 
01076                     return;
01077                 }
01078             }
01079 
01080           // Both scenarios have failed.
01081 
01082             break;
01083         }
01084     }
01085     assert( 0 );    // B-tree corruption. Unexpected branch of execution.
01086 }
01087 
01088 template< class K,
01089           class FCP,
01090           class ORDER >
01091 void
01092 CdbBdbSAbsBtree<K,FCP,ORDER>::reset( d_ULong node )
01093 {
01094     CdbBdbSBtreeNode<K,ORDER> nodeValue = readNode( node );
01095     {
01096         if( ! nodeValue.isLeaf ) {
01097             for( int i = 0; i < nodeValue.n + 1; ++i ) {
01098                 reset  ( nodeValue.child[i] );
01099                 release( nodeValue.child[i] );
01100             }
01101             nodeValue.isLeaf = true;
01102         }
01103         nodeValue.n = 0;
01104     }
01105     updateNode( node, nodeValue );
01106 }
01107 
01108 /////////////////
01109 // End Of File //
01110 /////////////////

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