From: dan Date: Fri, 21 Aug 2015 18:55:22 +0000 (+0000) Subject: When committing an UNLOCKED transaction, try to move pages allocated at the end of... X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=572a21c8e99373636abb5a76f019794bcc57c7a9;p=thirdparty%2Fsqlite.git When committing an UNLOCKED transaction, try to move pages allocated at the end of the file to free slots within the file (like an incremental-vacuum operation does). FossilOrigin-Name: 069679162d8d50e9731831e658aa58f280dbb3e7 --- diff --git a/manifest b/manifest index ed83b7c162..ce414f1bbb 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sproblem\swith\sUNLOCKED\stransactions\sthat\sfree\spages\sallocated\swithin\sthe\ssame\stransaction. -D 2015-08-21T17:57:16.096 +C When\scommitting\san\sUNLOCKED\stransaction,\stry\sto\smove\spages\sallocated\sat\sthe\send\sof\sthe\sfile\sto\sfree\sslots\swithin\sthe\sfile\s(like\san\sincremental-vacuum\soperation\sdoes). +D 2015-08-21T18:55:22.935 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 4f663b6b4954b9b1eb0e6f08387688a93b57542d F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -278,7 +278,7 @@ F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240 F src/backup.c 4d9134dc988a87838c06056c89c0e8c4700a0452 F src/bitvec.c d1f21d7d91690747881f03940584f4cc548c9d3d F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79 -F src/btree.c fca7884ea849190eff530f358f96c7304fcd2595 +F src/btree.c e455c3dbe8534aae357eab8ede1e280b6e838af0 F src/btree.h 00d4cdb747c4172a5566faf037116985dbbc377e F src/btreeInt.h 1f7258e1f35ba3cc2197f9019f523dd20d59a0d8 F src/build.c e47b6fffe14a28d9050e6747beebb01597d37542 @@ -1226,7 +1226,7 @@ F test/unique.test 93f8b2ef5ea51b9495f8d6493429b1fd0f465264 F test/unique2.test 41e7f83c6827605991160a31380148a9fc5f1339 F test/unixexcl.test cd6c765f75e50e8e2c2ba763149e5d340ea19825 F test/unlocked.test d143a871bd874311d4e5c98ce458218ca6b579fd -F test/unlocked2.test 4861218039ca2481613d7e6a999226185222c93a +F test/unlocked2.test 1e645e6f6808e4303f1766d8c615c22714f31541 F test/unordered.test ca7adce0419e4ca0c50f039885e76ed2c531eda8 F test/update.test 6c68446b8a0a33d522a7c72b320934596a2d7d32 F test/uri.test 23662b7b61958b0f0e47082de7d06341ccf85d5b @@ -1378,7 +1378,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P deaf3b18569025d8d168da29fae76142cfffe9e5 -R f09b37f1aebb9ccbb19d5d48d89374eb +P 227bb8a1815c4dc6084970f06b0a6bfccdff3fd2 +R 59f0ca349927e5f594c9b22ba4f42852 U dan -Z 1ea7f2e6e188cedc2dae0825d7ceb725 +Z 06941d0e9b57ce8c4c11e26554097e38 diff --git a/manifest.uuid b/manifest.uuid index 4ee4bbbd4b..167dab9ea2 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -227bb8a1815c4dc6084970f06b0a6bfccdff3fd2 \ No newline at end of file +069679162d8d50e9731831e658aa58f280dbb3e7 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 0bd34c7439..bf76254afe 100644 --- a/src/btree.c +++ b/src/btree.c @@ -3860,7 +3860,6 @@ static int btreeFixUnlocked(Btree *p){ BtreePtrmap *pMap = pBt->pMap; Pgno iTrunk = get4byte(&p1[32]); Pgno nPage = btreePagecount(pBt); - Pgno nOrig = pMap->iFirst-1; u32 nFree = get4byte(&p1[36]); assert( sqlite3PagerIsUnlocked(pPager) ); @@ -3891,10 +3890,12 @@ static int btreeFixUnlocked(Btree *p){ }; } - if( nHPageiFirst-1) ){ + /* The database consisted of (pMap->iFirst-1) pages when the current + ** unlocked transaction was opened. And an unlocked transaction may + ** not be executed on an auto-vacuum database - so the db should + ** not have shrunk since the transaction was opened. Therefore nHPage + ** should be set to (pMap->iFirst-1) or greater. */ rc = SQLITE_CORRUPT_BKPT; }else{ /* The current transaction allocated pages pMap->iFirst through @@ -3904,8 +3905,9 @@ static int btreeFixUnlocked(Btree *p){ */ Pgno iLast = MIN(nPage, nHPage); /* Last page to move */ Pgno iPg; + Pgno nCurrent; /* Current size of db */ - nFinal = MAX(nPage, nHPage); + nCurrent = MAX(nPage, nHPage); for(iPg=pMap->iFirst; iPg<=iLast && rc==SQLITE_OK; iPg++){ MemPage *pPg = 0; Pgno iNew; /* New page number for pPg */ @@ -3922,11 +3924,35 @@ static int btreeFixUnlocked(Btree *p){ btreeGetPage(pBt, iPg, &pPg, 0); assert( sqlite3PagerIswriteable(pPg->pDbPage) ); assert( sqlite3PagerPageRefcount(pPg->pDbPage)==1 ); - iNew = ++nFinal; + iNew = ++nCurrent; rc = relocatePage(pBt, pPg, pEntry->eType, pEntry->parent, iNew, 1); releasePageNotNull(pPg); } } + sqlite3PagerSetDbsize(pPager, nCurrent); + + nFree = get4byte(&p1[36]); + nFinal = MAX(nCurrent-nFree, nHPage); + + for(iPg=nFinal+1; rc==SQLITE_OK && iPgaPtr[iPg - pMap->iFirst]; + if( pEntry->eType==PTRMAP_FREEPAGE ){ + rc = allocateBtreePage(pBt, &pFree, &iNew, iPg, BTALLOC_EXACT); + releasePage(pFree); + }else{ + rc = allocateBtreePage(pBt, &pFree, &iNew, nFinal, BTALLOC_LE); + releasePage(pFree); + if( rc==SQLITE_OK ){ + MemPage *pPg = 0; + btreeGetPage(pBt, iPg, &pPg, 0); + rc = relocatePage(pBt, pPg, pEntry->eType, pEntry->parent,iNew,1); + } + } + } put4byte(&p1[28], nFinal); } } @@ -5784,9 +5810,7 @@ static int allocateBtreePage( Pgno mxPage; /* Total size of the database file */ assert( sqlite3_mutex_held(pBt->mutex) ); - assert( eMode==BTALLOC_ANY || (nearby>0 && ISAUTOVACUUM) - || (eMode==BTALLOC_EXACT && sqlite3PagerIsUnlocked(pBt->pPager)) - ); + assert( eMode==BTALLOC_ANY || (nearby>0 && REQUIRE_PTRMAP ) ); pPage1 = pBt->pPage1; mxPage = btreePagecount(pBt); /* EVIDENCE-OF: R-05119-02637 The 4-byte big-endian integer at offset 36 @@ -5831,12 +5855,9 @@ static int allocateBtreePage( }else{ searchList = 1; } - } -#ifndef SQLITE_OMIT_AUTOVACUUM - else if( eMode==BTALLOC_LE ){ + }else if( eMode==BTALLOC_LE ){ searchList = 1; } -#endif /* Decrement the free-list count by 1. Set iTrunk to the index of the ** first free-list trunk page. iPrevTrunk is initially 1. diff --git a/test/unlocked2.test b/test/unlocked2.test index 42742111c8..e5b102aa02 100644 --- a/test/unlocked2.test +++ b/test/unlocked2.test @@ -25,6 +25,7 @@ do_multiclient_test tn { CREATE TABLE t2(y); } } {wal} + do_test 1.$tn.5 { sql3 { PRAGMA integrity_check } } {ok} # Test that an UNLOCKED transaction that allocates/frees no pages does # not conflict with a transaction that does allocate pages. @@ -40,6 +41,7 @@ do_multiclient_test tn { COMMIT; } } {} + do_test 1.$tn.5 { sql3 { PRAGMA integrity_check } } {ok} # But that an UNLOCKED transaction does conflict with a transaction # that modifies the db schema. @@ -53,6 +55,7 @@ do_multiclient_test tn { } list [catch { sql1 COMMIT } msg] $msg } {1 {database is locked}} + do_test 1.$tn.5 { sql3 { PRAGMA integrity_check } } {ok} # Test that an UNLOCKED transaction that allocates at least one page # does not conflict with a transaction that allocates no pages. @@ -65,6 +68,7 @@ do_multiclient_test tn { sql2 { INSERT INTO t2 VALUES(8); } + breakpoint sql1 { COMMIT; }