diff --git a/manifest b/manifest index 0c00b8c4ac..76222c9340 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improved\stest\scoverage\son\sinsert.c.\s(CVS\s2210) -D 2005-01-14T01:22:01 +C Experimental\spatch\sto\sbalance()\s(use\s-DSQLITE_BALANCE_QUICK).\s(CVS\s2211) +D 2005-01-14T13:50:12 F Makefile.in 6ce51dde6a8fe82fc12f20dec750572f6a19f56a F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457 F README a01693e454a00cc117967e3f9fdab2d4d52e9bc1 @@ -29,7 +29,7 @@ F sqlite3.def dbaeb20c153e1d366e8f421b55a573f5dfc00863 F sqlite3.pc.in 985b9bf34192a549d7d370e0f0b6b34a4f61369a F src/attach.c e49d09dad9f5f9fb10b4b0c1be5a70ae4c45e689 F src/auth.c 3b81f2a42f48a62c2c9c9b0eda31a157c681edea -F src/btree.c bd2fd7fed9cc1ec84e70fe9f01dfcb474b53bbe5 +F src/btree.c 1a351402dbbf5cc5f8ecf1b338f8da20c073c46e F src/btree.h 74d19cf40ab49fd69abe9e4e12a6c321ad86c497 F src/build.c af1296e8a21a406b4f4c4f1e1365e075071219f3 F src/cursor.c f883813759742068890b1f699335872bfa8fdf41 @@ -139,7 +139,7 @@ F test/insert2.test 0bb50ff999e35a21549d8ee5dc44db8ac24d31a7 F test/insert3.test 421f6017ad268fcdba0b8ab56a2dff7265d3cf23 F test/interrupt.test 5b4d8389e6cf2d01b94f87cfd02d9df1073bfb2d F test/intpkey.test b57cf5236fde1bd8cbc1388fa0c91908f6fd9194 -F test/ioerr.test 259bef101273a8e7b16d004018ee5a7873a26889 +F test/ioerr.test fe51bacd7ffb83b9a0b70eceee3608dfd36371f6 F test/join.test ea8c77b9fbc377fe553cdb5ce5f1bd72021dca5d F test/join2.test c97e4c5aa65dea462145529e58212a709b4722b8 F test/join3.test 67dc0d7c8dab3fff25796d0f3c3fd9c999aeded3 @@ -269,7 +269,7 @@ F www/tclsqlite.tcl e73f8f8e5f20e8277619433f7970060ab01088fc F www/vdbe.tcl 095f106d93875c94b47367384ebc870517431618 F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0 F www/whentouse.tcl c3b50d3ac31c54be2a1af9b488a89d22f1e6e746 -P 6e905270a933fd4c99f6db6707ed79166f6484ee -R b0f921b0cc4246465f13a208b372d988 -U drh -Z 0f466f7cb587c20134aa5d2e4fe7cd6a +P c772f75166d55192132e732e8a0ddda5926f00f2 +R a2176157e002acaa6ba57b3b04bf35d8 +U danielk1977 +Z be978985848951cc4077641a9406e5b8 diff --git a/manifest.uuid b/manifest.uuid index 64846c6ed1..0a9619bf96 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c772f75166d55192132e732e8a0ddda5926f00f2 \ No newline at end of file +c550d80c25ec88fceb20acabd00c21faa2d552f5 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 6c9c98b5e4..c21e2e1909 100644 --- a/src/btree.c +++ b/src/btree.c @@ -9,7 +9,7 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* -** $Id: btree.c,v 1.231 2005/01/12 07:15:05 danielk1977 Exp $ +** $Id: btree.c,v 1.232 2005/01/14 13:50:12 danielk1977 Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to @@ -3556,7 +3556,57 @@ static void assemblePage( #define NB (NN*2+1) /* Total pages involved in the balance */ /* Forward reference */ -static int balance(MemPage*); +static int balance(MemPage*, int); + +static int balance_quick(MemPage *pPage, MemPage *pParent){ + int rc; + MemPage *pNew; + Pgno pgnoNew; + u8 *pCell; + int szCell; + CellInfo info; + + u8 parentCell[64]; /* How big should this be? */ + int parentIdx = pParent->nCell; + int parentSize; + + /* Allocate a new page. Insert the overflow cell from pPage + ** into it. Then remove the overflow cell from pPage. + */ + rc = allocatePage(pPage->pBt, &pNew, &pgnoNew, 0, 0); + if( rc!=SQLITE_OK ){ + return rc; + } + pCell = pPage->aOvfl[0].pCell; + szCell = cellSizePtr(pPage, pCell); + zeroPage(pNew, pPage->aData[0]); + assemblePage(pNew, 1, &pCell, &szCell); + pPage->nOverflow = 0; + + /* pPage is currently the right-child of pParent. Change this + ** so that the right-child is the new page allocated above and + ** pPage is the next-to-right child. Then balance() the parent + ** page, in case it is now overfull. + */ + parseCellPtr(pPage, findCell(pPage, pPage->nCell-1), &info); + rc = fillInCell(pParent, parentCell, 0, info.nKey, 0, 0, &parentSize); + if( rc!=SQLITE_OK ){ + return SQLITE_OK; + } + assert( parentSize<64 ); + rc = insertCell(pParent, parentIdx, parentCell, parentSize, 0, 4); + if( rc!=SQLITE_OK ){ + return SQLITE_OK; + } + put4byte(findOverflowCell(pParent,parentIdx), pPage->pgno); + put4byte(&pParent->aData[pParent->hdrOffset+8], pgnoNew); + + pNew->pParent = pParent; + sqlite3pager_ref(pParent->aData); + + releasePage(pNew); + return balance(pParent, 0); +} /* ** This routine redistributes Cells on pPage and up to NN*2 siblings @@ -3630,6 +3680,18 @@ static int balance_nonroot(MemPage *pPage){ assert( pParent ); TRACE(("BALANCE: begin page %d child of %d\n", pPage->pgno, pParent->pgno)); +#ifdef SQLITE_BALANCE_QUICK + if( pPage->leaf && + pPage->intKey && + pPage->leafData && + pPage->nOverflow==1 && + pPage->aOvfl[0].idx==pPage->nCell && + get4byte(&pParent->aData[pParent->hdrOffset+8])==pPage->pgno + ){ + return balance_quick(pPage, pParent); + } +#endif + /* ** Allocate space for memory structures */ @@ -3995,7 +4057,7 @@ static int balance_nonroot(MemPage *pPage){ assert( pParent->isInit ); /* assert( pPage->isInit ); // No! pPage might have been added to freelist */ /* pageIntegrity(pPage); // No! pPage might have been added to freelist */ - rc = balance(pParent); + rc = balance(pParent, 0); /* ** Cleanup before returning. @@ -4154,7 +4216,7 @@ static int balance_deeper(MemPage *pPage){ ** Decide if the page pPage needs to be balanced. If balancing is ** required, call the appropriate balancing routine. */ -static int balance(MemPage *pPage){ +static int balance(MemPage *pPage, int insert){ int rc = SQLITE_OK; if( pPage->pParent==0 ){ if( pPage->nOverflow>0 ){ @@ -4164,7 +4226,8 @@ static int balance(MemPage *pPage){ rc = balance_shallower(pPage); } }else{ - if( pPage->nOverflow>0 || pPage->nFree>pPage->pBt->usableSize*2/3 ){ + if( pPage->nOverflow>0 || + (!insert && pPage->nFree>pPage->pBt->usableSize*2/3) ){ rc = balance_nonroot(pPage); } } @@ -4268,7 +4331,7 @@ int sqlite3BtreeInsert( } rc = insertCell(pPage, pCur->idx, newCell, szNew, 0, 0); if( rc!=SQLITE_OK ) goto end_insert; - rc = balance(pPage); + rc = balance(pPage, 1); /* sqlite3BtreePageDump(pCur->pBt, pCur->pgnoRoot, 1); */ /* fflush(stdout); */ if( rc==SQLITE_OK ){ @@ -4354,17 +4417,17 @@ int sqlite3BtreeDelete(BtCursor *pCur){ rc = insertCell(pPage, pCur->idx, pNext-4, szNext+4, tempCell, 0); if( rc!=SQLITE_OK ) return rc; put4byte(findOverflowCell(pPage, pCur->idx), pgnoChild); - rc = balance(pPage); + rc = balance(pPage, 0); sqliteFree(tempCell); if( rc ) return rc; dropCell(leafCur.pPage, leafCur.idx, szNext); - rc = balance(leafCur.pPage); + rc = balance(leafCur.pPage, 0); releaseTempCursor(&leafCur); }else{ TRACE(("DELETE: table=%d delete from leaf %d\n", pCur->pgnoRoot, pPage->pgno)); dropCell(pPage, pCur->idx, cellSizePtr(pPage, pCell)); - rc = balance(pPage); + rc = balance(pPage, 0); } moveToRoot(pCur); return rc; @@ -5281,6 +5344,11 @@ char *sqlite3BtreeIntegrityCheck(Btree *pBt, int *aRoot, int nRoot){ return 0; } sCheck.anRef = sqliteMallocRaw( (sCheck.nPage+1)*sizeof(sCheck.anRef[0]) ); + if( !sCheck.anRef ){ + unlockBtreeIfUnused(pBt); + return sqlite3MPrintf("Unable to malloc %d bytes", + (sCheck.nPage+1)*sizeof(sCheck.anRef[0])); + } for(i=0; i<=sCheck.nPage; i++){ sCheck.anRef[i] = 0; } i = PENDING_BYTE_PAGE(pBt); if( i<=sCheck.nPage ){ diff --git a/test/ioerr.test b/test/ioerr.test index 6d277d07cb..489643c8ca 100644 --- a/test/ioerr.test +++ b/test/ioerr.test @@ -15,7 +15,7 @@ # The tests in this file use special facilities that are only # available in the SQLite test fixture. # -# $Id: ioerr.test,v 1.12 2005/01/13 11:07:54 danielk1977 Exp $ +# $Id: ioerr.test,v 1.13 2005/01/14 13:50:13 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -232,7 +232,7 @@ do_ioerr_test 5 -sqlprep { # Test IO errors when replaying two hot journals from a 2-file # transaction. This test only runs on UNIX. -if {$tcl_platform(platform)=="unix"} { +if {$tcl_platform(platform)=="unix" && [file exists ./crashtest]} { do_ioerr_test 6 -tclprep { set rc [crashsql 2 test2.db-journal { ATTACH 'test2.db' as aux;