-C Fix\stwo\sbugs\sthat\swere\scausing\slots\sof\stests\sto\sfail.\s(CVS\s1386)
-D 2004-05-16T11:57:28
+C Fix\sa\sbug\sin\sthe\sBTree\sbalancing\sroutine.\s(CVS\s1387)
+D 2004-05-16T16:24:37
F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
F sqlite.pc.in 30552343140c53304c2a658c080fbe810cd09ca2
F src/attach.c c315c58cb16fd6e913b3bfa6412aedecb4567fa5
F src/auth.c 5c2f0bea4729c98c2be3b69d6b466fc51448fe79
-F src/btree.c 05aefd3eec56690d9731bf090203b57d8ae4bf19
+F src/btree.c bf8d9592b66fb9ba89a5be13fd99a7d8b8a67d7f
F src/btree.h 6f51ad0ffebfba71295fcacdbe86007512200050
F src/btree_rb.c 9d7973e266ee6f9c61ce592f68742ce9cd5b10e5
F src/build.c fd37eda7100d2507c647df43f9f3ce56a2f59ab4
F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da
F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1
F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
-P a4af838f8d1b81ec6c8db97655c6876aca0738d9
-R a401956638c6d55c9de15d1b9c3564d6
-U danielk1977
-Z d5bacfd02a451c5d78cf0909159519e5
+P 5cba8a510c0aeae740db695e960c60e5f6c303f5
+R 25cd950de731900e925b6b5361c9fbb9
+U drh
+Z fd6768d10af70b66f5ace479a66938d7
** May you share freely, never taking more than you give.
**
*************************************************************************
-** $Id: btree.c,v 1.140 2004/05/15 00:29:24 drh Exp $
+** $Id: btree.c,v 1.141 2004/05/16 16:24:37 drh Exp $
**
** This file implements a external (disk-based) database using BTrees.
** For a detailed discussion of BTrees, refer to
assert( pPage->isInit );
assert( sqlite3pager_iswriteable(pPage->aData) );
pBt = pPage->pBt;
- if( !pPage->isOverfull && pPage->nFree<pBt->usableSize*2/3 && pPage->nCell>=2){
+ if( !pPage->isOverfull && pPage->nFree<pBt->usableSize*2/3
+ && pPage->nCell>=2){
relinkCellList(pPage);
return SQLITE_OK;
}
**
** If the siblings are on leaf pages, then the child pointers of the
** divider cells are stripped from the cells before they are copied
- ** into aSpace[]. In this wall, all cells in apCell[] are without
+ ** into aSpace[]. In this way, all cells in apCell[] are without
** child pointers. If siblings are not leaves, then all cell in
** apCell[] include child pointers. Either way, all cells in apCell[]
** are alike.
+ **
+ ** leafCorrection: 4 if pPage is a leaf. 0 if pPage is not a leaf.
+ ** leafData: 1 if pPage holds key+data and pParent holds only keys.
*/
nCell = 0;
leafCorrection = pPage->leaf*4;
if( i<nOld-1 ){
int sz = cellSize(pParent, apDiv[i]);
if( leafData ){
+ /* With the LEAFDATA flag, pParent cells hold only INTKEYs that
+ ** are duplicates of keys on the child pages. We need to remove
+ ** the divider cells from pParent, but the dividers cells are not
+ ** added to apCell[] because they are duplicates of child cells.
+ */
dropCell(pParent, nxDiv, sz);
}else{
u8 *pTemp;
** in apCell[] of the cell that divides page i from page i+1.
** cntNew[k] should equal nCell.
**
- ** This little patch of code is critical for keeping the tree
- ** balanced.
+ ** Values computed by this block:
+ **
+ ** k: The total number of sibling pages
+ ** szNew[i]: Spaced used on the i-th sibling page.
+ ** cntNew[i]: Index in apCell[] and szCell[] for the first cell to
+ ** the right of the i-th sibling page.
+ ** usableSpace: Number of bytes of space available on each sibling.
+ **
*/
usableSpace = pBt->usableSize - 10 + leafCorrection;
for(subtotal=k=i=0; i<nCell; i++){
szNew[k] = subtotal;
cntNew[k] = nCell;
k++;
+
+ /*
+ ** The packing computed by the previous block is biased toward the siblings
+ ** on the left side. The left siblings are always nearly full, while the
+ ** right-most sibling might be nearly empty. This block of code attempts
+ ** to adjust the packing of siblings to get a better balance.
+ **
+ ** This adjustment is more than an optimization. The packing above might
+ ** be so out of balance as to be illegal. For example, the right-most
+ ** sibling might be completely empty. This adjustment is not optional.
+ */
for(i=k-1; i>0; i--){
- while( szNew[i]<usableSpace/2 ){
+ int szRight = szNew[i]; /* Size of sibling on the right */
+ int szLeft = szNew[i-1]; /* Size of sibling on the left */
+ int r; /* Index of right-most cell in left sibling */
+ int d; /* Index of first cell to the left of right sibling */
+
+ r = cntNew[i-1] - 1;
+ d = r + 1 - leafData;
+ while( szRight==0 || szRight+szCell[d]<=szLeft-szCell[r] ){
+ szRight += szCell[d];
+ szLeft -= szCell[r];
cntNew[i-1]--;
- assert( cntNew[i-1]>0 );
- szNew[i] += szCell[cntNew[i-1]];
- szNew[i-1] -= szCell[cntNew[i-1]-1];
+ r = cntNew[i-1] - 1;
+ d = r + 1 - leafData;
}
+ szNew[i] = szRight;
+ szNew[i-1] = szLeft;
}
assert( cntNew[0]>0 );