Changes to btree.c in support of coverage testing. (CVS 6913)

FossilOrigin-Name: 4cf23e9e860bd6245344884ec84f487fdf36f86f
This commit is contained in:
drh 2009-07-21 11:52:34 +00:00
parent cd09c53d7f
commit c314dc7996
3 changed files with 75 additions and 69 deletions

View File

@ -1,5 +1,5 @@
C Reverse\sthe\sorder\sof\stwo\sconditionals\sin\sa\stest\sin\sorder\sto\sachieve\scoverage\nof\sthem\sboth.\s\sAlso:\sclarifications\sto\scomments\sin\sbtree.c.\s(CVS\s6912)
D 2009-07-20T19:30:01
C Changes\sto\sbtree.c\sin\ssupport\sof\scoverage\stesting.\s(CVS\s6913)
D 2009-07-21T11:52:35
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
F Makefile.in df9359da7a726ccb67a45db905c5447d5c00c6ef
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@ -106,7 +106,7 @@ F src/auth.c 802a9439dfa0b8c208b10055cba400e82ef18025
F src/backup.c 6f1c2d9862c8a3feb7739dfcca02c1f5352e37f3
F src/bitvec.c cfbf6af5b0ababb4f06ed3e75c616dadaf47fcbd
F src/btmutex.c 0f43a75bb5b8147b386e8e1c3e71ba734e3863b7
F src/btree.c 123dd6ab71226ee9c41d6658fd11b2f7bed73f44
F src/btree.c d5dde31b5743d90cee35071f4828ff38bdf90199
F src/btree.h e53a10fd31d16c60a86f03c9467a6f470aa3683b
F src/btreeInt.h 1c86297e69380f6577e7ae67452597dd8d5c2705
F src/build.c 867028ee9f63f7bc8eb8d4a720bb98cf9b9a12b4
@ -741,7 +741,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
F tool/vdbe-compress.tcl 672f81d693a03f80f5ae60bfefacd8a349e76746
P 7dcf2a78727ce448d9d26bd6e2e23b553456ec54
R ee81aff6c227cadf19a47a764a1a15d2
P a159e9d24708dfe6c5a98d220e39f3b1b2a3d281
R 1cd0f279a79b2344821cde6c251ba1a6
U drh
Z f9f7c95bd23663f1ba6a8b648cb1cde3
Z b3b11d19f04a316773edec9a04d19c25

View File

@ -1 +1 @@
a159e9d24708dfe6c5a98d220e39f3b1b2a3d281
4cf23e9e860bd6245344884ec84f487fdf36f86f

View File

@ -9,7 +9,7 @@
** May you share freely, never taking more than you give.
**
*************************************************************************
** $Id: btree.c,v 1.693 2009/07/20 19:30:01 drh Exp $
** $Id: btree.c,v 1.694 2009/07/21 11:52:35 drh Exp $
**
** This file implements a external (disk-based) database using BTrees.
** See the header comment on "btreeInt.h" for additional information.
@ -1128,6 +1128,7 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
assert( nByte>=0 ); /* Minimum cell size is 4 */
assert( pPage->nFree>=nByte );
assert( pPage->nOverflow==0 );
assert( nByte<pPage->pBt->usableSize-8 );
nFrag = data[hdr+7];
assert( pPage->cellOffset == hdr + 12 - 4*pPage->leaf );
@ -1184,10 +1185,14 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
/* Allocate memory from the gap in between the cell pointer array
** and the cell content area.
** and the cell content area. The btreeInitPage() call has already
** validated the freelist. Given that the freelist is valid, there
** is no way that the allocation can extend off the end of the page.
** The assert() below verifies the previous sentence.
*/
top -= nByte;
put2byte(&data[hdr+5], top);
assert( top+nByte <= pPage->pBt->usableSize );
*pIdx = top;
return SQLITE_OK;
}
@ -4960,8 +4965,10 @@ freepage_out:
releasePage(pTrunk);
return rc;
}
static int freePage(MemPage *pPage){
return freePage2(pPage->pBt, pPage, pPage->pgno);
static void freePage(MemPage *pPage, int *pRC){
if( (*pRC)==SQLITE_OK ){
*pRC = freePage2(pPage->pBt, pPage, pPage->pgno);
}
}
/*
@ -5184,6 +5191,7 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){
u8 *data; /* pPage->aData */
u8 *ptr; /* Used to move bytes around within data[] */
int rc; /* The return code */
int hdr; /* Beginning of the header. 0 most pages. 100 page 1 */
if( *pRC ) return;
@ -5194,8 +5202,10 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){
data = pPage->aData;
ptr = &data[pPage->cellOffset + 2*idx];
pc = get2byte(ptr);
if( (pc<pPage->hdrOffset+6+pPage->childPtrSize)
|| (pc+sz>pPage->pBt->usableSize) ){
hdr = pPage->hdrOffset;
testcase( pc==get2byte(&data[hdr+5]) );
testcase( pc+sz==pPage->pBt->usableSize );
if( pc < get2byte(&data[hdr+5]) || pc+sz > pPage->pBt->usableSize ){
*pRC = SQLITE_CORRUPT_BKPT;
return;
}
@ -5209,7 +5219,7 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){
ptr[1] = ptr[3];
}
pPage->nCell--;
put2byte(&data[pPage->hdrOffset+3], pPage->nCell);
put2byte(&data[hdr+3], pPage->nCell);
pPage->nFree += 2;
}
@ -5281,11 +5291,10 @@ static void insertCell(
ins = cellOffset + 2*i;
rc = allocateSpace(pPage, sz, &idx);
if( rc ){ *pRC = rc; return; }
assert( idx>=end+2 );
if( idx+sz > pPage->pBt->usableSize ){
*pRC = SQLITE_CORRUPT_BKPT;
return;
}
/* The allocateSpace() routine guarantees the following two properties
** if it returns success */
assert( idx >= end+2 );
assert( idx+sz <= pPage->pBt->usableSize );
pPage->nCell++;
pPage->nFree -= (u16)(2 + sz);
memcpy(&data[idx+nSkip], pCell+nSkip, sz-nSkip);
@ -5372,7 +5381,7 @@ static void assemblePage(
** tree, in other words, when the new entry will become the largest
** entry in the tree.
**
** Instead of trying balance the 3 right-most leaf pages, just add
** Instead of trying to balance the 3 right-most leaf pages, just add
** a new page to the right-hand side and put the one new entry in
** that page. This leaves the right side of the tree somewhat
** unbalanced. But odds are that we will be inserting new entries
@ -5399,7 +5408,7 @@ static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){
assert( sqlite3PagerIswriteable(pParent->pDbPage) );
assert( pPage->nOverflow==1 );
if( pPage->nCell<=0 ) return SQLITE_CORRUPT_BKPT;
if( NEVER(pPage->nCell<=0) ) return SQLITE_CORRUPT_BKPT;
/* Allocate a new page. This page will become the right-sibling of
** pPage. Make the parent page writable, so that the new divider cell
@ -5528,37 +5537,40 @@ static int ptrmapCheckPages(MemPage **apPage, int nPage){
** 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 = ) btreeInitPage(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);
static void copyNodeContent(MemPage *pFrom, MemPage *pTo, int *pRC){
if( (*pRC)==SQLITE_OK ){
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);
TESTONLY(int rc;)
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 = ) btreeInitPage(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 ){
*pRC = setChildPtrmaps(pTo);
}
}
return rc;
}
/*
@ -5927,7 +5939,7 @@ static int balance_nonroot(
/* Free any old pages that were not reused as new pages.
*/
while( i<nOld ){
rc = freePage(apOld[i]);
freePage(apOld[i], &rc);
if( rc ) goto balance_cleanup;
releasePage(apOld[i]);
apOld[i] = 0;
@ -6075,9 +6087,8 @@ static int balance_nonroot(
assert( apNew[0]->nFree ==
(get2byte(&apNew[0]->aData[5])-apNew[0]->cellOffset-apNew[0]->nCell*2)
);
if( SQLITE_OK==(rc = copyNodeContent(apNew[0], pParent)) ){
rc = freePage(apNew[0]);
}
copyNodeContent(apNew[0], pParent, &rc);
freePage(apNew[0], &rc);
}else if( ISAUTOVACUUM ){
/* Fix the pointer-map entries for all the cells that were shifted around.
** There are several different types of pointer-map entries that need to
@ -6117,7 +6128,7 @@ static int balance_nonroot(
int iOverflow = (nOverflow ? pOld->aOvfl[0].idx : -1);
j = 0; /* Current 'old' sibling page */
k = 0; /* Current 'new' sibling page */
for(i=0; i<nCell && rc==SQLITE_OK; i++){
for(i=0; i<nCell; i++){
int isDivider = 0;
while( i==iNextOld ){
/* Cell i is the cell immediately following the last cell on old
@ -6239,11 +6250,9 @@ static int balance_deeper(MemPage *pRoot, MemPage **ppChild){
rc = sqlite3PagerWrite(pRoot->pDbPage);
if( rc==SQLITE_OK ){
rc = allocateBtreePage(pBt,&pChild,&pgnoChild,pRoot->pgno,0);
if( rc==SQLITE_OK ){
rc = copyNodeContent(pRoot, pChild);
if( ISAUTOVACUUM ){
ptrmapPut(pBt, pgnoChild, PTRMAP_BTREE, pRoot->pgno, &rc);
}
copyNodeContent(pRoot, pChild, &rc);
if( ISAUTOVACUUM ){
ptrmapPut(pBt, pgnoChild, PTRMAP_BTREE, pRoot->pgno, &rc);
}
}
if( rc ){
@ -6846,7 +6855,7 @@ static int clearDatabasePage(
*pnChange += pPage->nCell;
}
if( freePageFlag ){
rc = freePage(pPage);
freePage(pPage, &rc);
}else if( (rc = sqlite3PagerWrite(pPage->pDbPage))==0 ){
zeroPage(pPage, pPage->aData[0] | PTF_LEAF);
}
@ -6941,7 +6950,7 @@ static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){
if( iTable>1 ){
#ifdef SQLITE_OMIT_AUTOVACUUM
rc = freePage(pPage);
freePage(pPage, &rc);
releasePage(pPage);
#else
if( pBt->autoVacuum ){
@ -6952,7 +6961,7 @@ static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){
/* If the table being dropped is the table with the largest root-page
** number in the database, put the root page on the free list.
*/
rc = freePage(pPage);
freePage(pPage, &rc);
releasePage(pPage);
if( rc!=SQLITE_OK ){
return rc;
@ -6974,10 +6983,7 @@ static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){
return rc;
}
rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0);
if( rc!=SQLITE_OK ){
return rc;
}
rc = freePage(pMove);
freePage(pMove, &rc);
releasePage(pMove);
if( rc!=SQLITE_OK ){
return rc;
@ -6999,7 +7005,7 @@ static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){
rc = sqlite3BtreeUpdateMeta(p, 4, maxRootPgno);
}else{
rc = freePage(pPage);
freePage(pPage, &rc);
releasePage(pPage);
}
#endif