1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-07 02:42:48 +03:00

Call balance_shallower() from balance_nonroot() instead of from balance(). This simplifies coverage testing a bit. (CVS 6805)

FossilOrigin-Name: da9893e23caf89090c8b6563cb5f88d7dbf7c260
This commit is contained in:
danielk1977
2009-06-23 15:43:39 +00:00
parent 5c91b64e0d
commit cd581a7eff
3 changed files with 112 additions and 128 deletions

View File

@@ -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

View File

@@ -1 +1 @@
b614e554f7ebaef9cb1718b617e020e532568bbb
da9893e23caf89090c8b6563cb5f88d7dbf7c260

View 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