]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Call balance_shallower() from balance_nonroot() instead of from balance(). This simpl...
authordanielk1977 <danielk1977@noemail.net>
Tue, 23 Jun 2009 15:43:39 +0000 (15:43 +0000)
committerdanielk1977 <danielk1977@noemail.net>
Tue, 23 Jun 2009 15:43:39 +0000 (15:43 +0000)
FossilOrigin-Name: da9893e23caf89090c8b6563cb5f88d7dbf7c260

manifest
manifest.uuid
src/btree.c

index e823d8d4558563d07feec1869a3ae0992ed7584e..208960f7b2de91a2f771bd0e4f26a8bbb0ece414 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Update\sthe\sconfigure\sscript\sfor\sversion\s3.6.16\s(CVS\s6804)
-D 2009-06-23T14:39:53
+C Call\sbalance_shallower()\sfrom\sbalance_nonroot()\sinstead\sof\sfrom\sbalance().\sThis\ssimplifies\scoverage\stesting\sa\sbit.\s(CVS\s6805)
+D 2009-06-23T15:43:40
 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
 F Makefile.in 8b8fb7823264331210cddf103831816c286ba446
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -106,7 +106,7 @@ F src/auth.c 98db07c2088455797678eb1031f42d4d94d18a71
 F src/backup.c ff50af53184a5fd7bdee4d620b5dabef74717c79
 F src/bitvec.c 0ef0651714728055d43de7a4cdd95e703fac0119
 F src/btmutex.c 9b899c0d8df3bd68f527b0afe03088321b696d3c
-F src/btree.c 732191303402ec6ab0dd7062d07a4bb6a6c51c0c
+F src/btree.c 13e33e85103c19b114ce1cfdedd2d3e2647de290
 F src/btree.h f70b694e8c163227369a66863b01fbff9009f323
 F src/btreeInt.h 7267e965e34314aa2bddbdde268b31e1034eda9c
 F src/build.c e98868af6a04c8d7191c39fd05c69da34a8d9c68
@@ -737,7 +737,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
 F tool/vdbe-compress.tcl 672f81d693a03f80f5ae60bfefacd8a349e76746
-P 207c4a02ba4dd950948367c91b4a73209d62da41
-R b922ac03d2a566045ccf7938c02d6e2d
-U drh
-Z 86414292e77851f843aee830f2b6b2fd
+P b614e554f7ebaef9cb1718b617e020e532568bbb
+R 21b91543d4279dc39963961cdf36484b
+U danielk1977
+Z 3fbc90fe51d8a097f9b06b0d67881dff
index 5041d95e71a8cd2f5b5f1268181eeee0f76eb216..8911e3e3d87ef88fd4c60fa1feb9a505c04cb285 100644 (file)
@@ -1 +1 @@
-b614e554f7ebaef9cb1718b617e020e532568bbb
\ No newline at end of file
+da9893e23caf89090c8b6563cb5f88d7dbf7c260
\ No newline at end of file
index 2cecde08c7dc64a57203caf693d48d4865479038..d4e64a33639d30d333e5700dcd170bbe54c1c10e 100644 (file)
@@ -9,7 +9,7 @@
 **    May you share freely, never taking more than you give.
 **
 *************************************************************************
-** $Id: btree.c,v 1.639 2009/06/23 11:22:29 danielk1977 Exp $
+** $Id: btree.c,v 1.640 2009/06/23 15:43:40 danielk1977 Exp $
 **
 ** This file implements a external (disk-based) database using BTrees.
 ** See the header comment on "btreeInt.h" for additional information.
@@ -5338,6 +5338,96 @@ static int ptrmapCheckPages(MemPage **apPage, int nPage){
 }
 #endif
 
+/*
+** This function is used to copy the contents of the b-tree node stored 
+** on page pFrom to page pTo. If page pFrom was not a leaf page, then
+** the pointer-map entries for each child page are updated so that the
+** parent page stored in the pointer map is page pTo. If pFrom contained
+** any cells with overflow page pointers, then the corresponding pointer
+** map entries are also updated so that the parent page is page pTo.
+**
+** If pFrom is currently carrying any overflow cells (entries in the
+** MemPage.aOvfl[] array), they are not copied to pTo. 
+**
+** Before returning, page pTo is reinitialized using sqlite3BtreeInitPage().
+**
+** The performance of this function is not critical. It is only used by 
+** the balance_shallower() and balance_deeper() procedures, neither of
+** which are called often under normal circumstances.
+*/
+static int copyNodeContent(MemPage *pFrom, MemPage *pTo){
+  BtShared * const pBt = pFrom->pBt;
+  u8 * const aFrom = pFrom->aData;
+  u8 * const aTo = pTo->aData;
+  int const iFromHdr = pFrom->hdrOffset;
+  int const iToHdr = ((pTo->pgno==1) ? 100 : 0);
+  int rc = SQLITE_OK;
+  int iData;
+
+  assert( pFrom->isInit );
+  assert( pFrom->nFree>=iToHdr );
+  assert( get2byte(&aFrom[iFromHdr+5])<=pBt->usableSize );
+
+  /* Copy the b-tree node content from page pFrom to page pTo. */
+  iData = get2byte(&aFrom[iFromHdr+5]);
+  memcpy(&aTo[iData], &aFrom[iData], pBt->usableSize-iData);
+  memcpy(&aTo[iToHdr], &aFrom[iFromHdr], pFrom->cellOffset + 2*pFrom->nCell);
+
+  /* Reinitialize page pTo so that the contents of the MemPage structure
+  ** match the new data. The initialization of pTo "cannot" fail, as the
+  ** data copied from pFrom is known to be valid.  */
+  pTo->isInit = 0;
+  TESTONLY(rc = ) sqlite3BtreeInitPage(pTo);
+  assert( rc==SQLITE_OK );
+
+  /* If this is an auto-vacuum database, update the pointer-map entries
+  ** for any b-tree or overflow pages that pTo now contains the pointers to. */
+  if( ISAUTOVACUUM ){
+    rc = setChildPtrmaps(pTo);
+  }
+  return rc;
+}
+
+/*
+** This routine is called on the root page of a btree when the root
+** page contains no cells. This is an opportunity to make the tree
+** shallower by one level.
+*/
+static int balance_shallower(MemPage *pRoot, MemPage *pChild){
+  /* The root page is empty but has one child.  Transfer the
+  ** information from that one child into the root page if it 
+  ** will fit.  This reduces the depth of the tree by one.
+  **
+  ** If the root page is page 1, it has less space available than
+  ** its child (due to the 100 byte header that occurs at the beginning
+  ** of the database fle), so it might not be able to hold all of the 
+  ** information currently contained in the child.  If this is the 
+  ** case, then do not do the transfer.  Leave page 1 empty except
+  ** for the right-pointer to the child page.  The child page becomes
+  ** the virtual root of the tree.
+  */
+  int rc = SQLITE_OK;                        /* Return code */
+  int const hdr = pRoot->hdrOffset;          /* Offset of root page header */
+
+  assert( sqlite3_mutex_held(pRoot->pBt->mutex) );
+  assert( pRoot->nCell==0 );
+  assert( pChild->pgno==get4byte(&pRoot->aData[pRoot->hdrOffset+8]) );
+  assert( hdr==0 || pRoot->pgno==1 );
+
+  if( pChild->nFree>=hdr ){
+    if( hdr ){
+      rc = defragmentPage(pChild);
+    }
+    if( rc==SQLITE_OK ){
+      rc = copyNodeContent(pChild, pRoot);
+    }
+    if( rc==SQLITE_OK ){
+      rc = freePage(pChild);
+    }
+  }
+
+  return rc;
+}
 
 /*
 ** This routine redistributes cells on the iParentIdx'th child of pParent
@@ -5382,7 +5472,8 @@ static int ptrmapCheckPages(MemPage **apPage, int nPage){
 static int balance_nonroot(
   MemPage *pParent,               /* Parent page of siblings being balanced */
   int iParentIdx,                 /* Index of "the page" in pParent */
-  u8 *aOvflSpace                  /* page-size bytes of space for parent ovfl */
+  u8 *aOvflSpace,                 /* page-size bytes of space for parent ovfl */
+  int isRoot                      /* True if pParent is a root-page */
 ){
   BtShared *pBt;               /* The whole database */
   int nCell = 0;               /* Number of cells in apCell[] */
@@ -5939,6 +6030,16 @@ static int balance_nonroot(
   assert( pParent->isInit );
   TRACE(("BALANCE: finished: old=%d new=%d cells=%d\n",
           nOld, nNew, nCell));
+
+  if( rc==SQLITE_OK && pParent->nCell==0 && isRoot ){
+    /* The root page of the b-tree now contains no cells. If the root-page 
+    ** is not also a leaf page, it will have a single child page. Call 
+    ** balance_shallower to attempt to copy the contents of the single
+    ** child-page into the root page (this may not be possible if the
+    ** root page is page 1).  */ 
+    assert( nNew==1 );
+    rc = balance_shallower(pParent, apNew[0]);
+  }
  
   /*
   ** Cleanup before returning.
@@ -5955,109 +6056,6 @@ balance_cleanup:
   return rc;
 }
 
-/*
-** This function is used to copy the contents of the b-tree node stored 
-** on page pFrom to page pTo. If page pFrom was not a leaf page, then
-** the pointer-map entries for each child page are updated so that the
-** parent page stored in the pointer map is page pTo. If pFrom contained
-** any cells with overflow page pointers, then the corresponding pointer
-** map entries are also updated so that the parent page is page pTo.
-**
-** If pFrom is currently carrying any overflow cells (entries in the
-** MemPage.aOvfl[] array), they are not copied to pTo. 
-**
-** Before returning, page pTo is reinitialized using sqlite3BtreeInitPage().
-**
-** The performance of this function is not critical. It is only used by 
-** the balance_shallower() and balance_deeper() procedures, neither of
-** which are called often under normal circumstances.
-*/
-static int copyNodeContent(MemPage *pFrom, MemPage *pTo){
-  BtShared * const pBt = pFrom->pBt;
-  u8 * const aFrom = pFrom->aData;
-  u8 * const aTo = pTo->aData;
-  int const iFromHdr = pFrom->hdrOffset;
-  int const iToHdr = ((pTo->pgno==1) ? 100 : 0);
-  int rc = SQLITE_OK;
-  int iData;
-
-  assert( pFrom->isInit );
-  assert( pFrom->nFree>=iToHdr );
-  assert( get2byte(&aFrom[iFromHdr+5])<=pBt->usableSize );
-
-  /* Copy the b-tree node content from page pFrom to page pTo. */
-  iData = get2byte(&aFrom[iFromHdr+5]);
-  memcpy(&aTo[iData], &aFrom[iData], pBt->usableSize-iData);
-  memcpy(&aTo[iToHdr], &aFrom[iFromHdr], pFrom->cellOffset + 2*pFrom->nCell);
-
-  /* Reinitialize page pTo so that the contents of the MemPage structure
-  ** match the new data. The initialization of pTo "cannot" fail, as the
-  ** data copied from pFrom is known to be valid.  */
-  pTo->isInit = 0;
-  TESTONLY(rc = ) sqlite3BtreeInitPage(pTo);
-  assert( rc==SQLITE_OK );
-
-  /* If this is an auto-vacuum database, update the pointer-map entries
-  ** for any b-tree or overflow pages that pTo now contains the pointers to. */
-  if( ISAUTOVACUUM ){
-    rc = setChildPtrmaps(pTo);
-  }
-  return rc;
-}
-
-/*
-** This routine is called on the root page of a btree when the root
-** page contains no cells. This is an opportunity to make the tree
-** shallower by one level.
-*/
-static int balance_shallower(MemPage *pRoot){
-  /* The root page is empty but has one child.  Transfer the
-  ** information from that one child into the root page if it 
-  ** will fit.  This reduces the depth of the tree by one.
-  **
-  ** If the root page is page 1, it has less space available than
-  ** its child (due to the 100 byte header that occurs at the beginning
-  ** of the database fle), so it might not be able to hold all of the 
-  ** information currently contained in the child.  If this is the 
-  ** case, then do not do the transfer.  Leave page 1 empty except
-  ** for the right-pointer to the child page.  The child page becomes
-  ** the virtual root of the tree.
-  */
-  int rc = SQLITE_OK;                        /* Return code */
-  int const hdr = pRoot->hdrOffset;          /* Offset of root page header */
-  MemPage *pChild;                           /* Only child of pRoot */
-  Pgno const pgnoChild = get4byte(&pRoot->aData[pRoot->hdrOffset+8]);
-  
-  assert( pRoot->nCell==0 );
-  assert( sqlite3_mutex_held(pRoot->pBt->mutex) );
-  assert( !pRoot->leaf );
-  assert( pgnoChild>0 );
-  assert( pgnoChild<=pagerPagecount(pRoot->pBt) );
-  assert( hdr==0 || pRoot->pgno==1 );
-  
-  rc = sqlite3BtreeGetPage(pRoot->pBt, pgnoChild, &pChild, 0);
-  if( rc==SQLITE_OK ){
-    if( pChild->nFree>=hdr ){
-      if( hdr ){
-        rc = defragmentPage(pChild);
-      }
-      if( rc==SQLITE_OK ){
-        rc = copyNodeContent(pChild, pRoot);
-      }
-      if( rc==SQLITE_OK ){
-        rc = freePage(pChild);
-      }
-    }else{
-      /* The child has more information that will fit on the root.
-      ** The tree is already balanced.  Do nothing. */
-      TRACE(("BALANCE: child %d will not fit on page 1\n", pChild->pgno));
-    }
-    releasePage(pChild);
-  }
-
-  return rc;
-}
-
 
 /*
 ** This function is called when the root page of a b-tree structure is
@@ -6126,7 +6124,6 @@ static int balance_deeper(MemPage *pRoot, MemPage **ppChild){
 ** routine. Balancing routines are:
 **
 **   balance_quick()
-**   balance_shallower()
 **   balance_deeper()
 **   balance_nonroot()
 **
@@ -6165,19 +6162,6 @@ static int balance(BtCursor *pCur){
         }
         VVA_ONLY( pCur->pagesShuffled = 1 );
       }else{
-        /* The root page of the b-tree is now empty. If the root-page is not
-        ** also a leaf page, it will have a single child page. Call 
-        ** balance_shallower to attempt to copy the contents of the single
-        ** child-page into the root page (this may not be possible if the
-        ** root page is page 1).
-        **
-        ** Whether or not this is possible , the tree is now balanced. 
-        ** Therefore is no next iteration of the do-loop.
-        */ 
-        if( pPage->nCell==0 && !pPage->leaf ){
-          rc = balance_shallower(pPage);
-          VVA_ONLY( pCur->pagesShuffled = 1 );
-        }
         break;
       }
     }else if( pPage->nOverflow==0 && pPage->nFree<=nMin ){
@@ -6231,7 +6215,7 @@ static int balance(BtCursor *pCur){
           ** pSpace buffer passed to the latter call to balance_nonroot().
           */
           u8 *pSpace = sqlite3PageMalloc(pCur->pBt->pageSize);
-          rc = balance_nonroot(pParent, iIdx, pSpace);
+          rc = balance_nonroot(pParent, iIdx, pSpace, iPage==1);
           if( pFree ){
             /* If pFree is not NULL, it points to the pSpace buffer used 
             ** by a previous call to balance_nonroot(). Its contents are