From 51f0b6d568df407b92ce9363b5dfb03f3b3be1f0 Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 22 Feb 2013 20:16:34 +0000 Subject: [PATCH 01/10] Avoid moving pages more than once in an incremental vacuum operation. FossilOrigin-Name: c3939d249119b47bd57baa11a5ed7cc6014fc795 --- manifest | 17 +++--- manifest.uuid | 2 +- src/btree.c | 145 +++++++++++++++++++++++++++++++------------------- 3 files changed, 102 insertions(+), 62 deletions(-) diff --git a/manifest b/manifest index b598aeddd6..d14f19c439 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C On\sMinix,\sdisable\sthe\s".timer"\scommand\sin\sthe\sshell\sin\sorder\sto\savoid\ncalling\sgetrusage(). -D 2013-02-20T00:54:21.855 +C Avoid\smoving\spages\smore\sthan\sonce\sin\san\sincremental\svacuum\soperation. +D 2013-02-22T20:16:34.273 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in a48faa9e7dd7d556d84f5456eabe5825dd8a6282 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -121,7 +121,7 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c 32e35a3a4ea55b45c0e5f74eeb793aec71491517 F src/bitvec.c 26675fe8e431dc555e6f2d0e11e651d172234aa1 F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 -F src/btree.c 7a80e4a67f32a2494c383a28a495bf3bd71cc230 +F src/btree.c 960274cb93c1d85e82bd106094e0890d89434ab8 F src/btree.h 3ad7964d6c5b1c7bff569aab6adfa075f8bf06cd F src/btreeInt.h 4e5c2bd0f9b36b2a815a6d84f771a61a65830621 F src/build.c 73ca65f32938e4e0d94e831b61b5749b211b79be @@ -1034,7 +1034,10 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P 06bd91305ed6752315c5224be5f89e87cafa6687 -R 14c0fedf89f00b14b7845aeac312ffca -U drh -Z 673b617e6189db9a51be1e6b0160e6d4 +P 9bd9bd9cab8c804c1a51d472199459176044a633 +R d336ad839cab7fc86035cb53790f3fce +T *branch * incr-vacuum-opt +T *sym-incr-vacuum-opt * +T -sym-trunk * +U dan +Z cd58f1fbd68ec5de5d0f48d285a49284 diff --git a/manifest.uuid b/manifest.uuid index 029dba568e..6676236222 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9bd9bd9cab8c804c1a51d472199459176044a633 \ No newline at end of file +c3939d249119b47bd57baa11a5ed7cc6014fc795 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index bb64e643b0..de22559968 100644 --- a/src/btree.c +++ b/src/btree.c @@ -2909,26 +2909,28 @@ static int relocatePage( /* Forward declaration required by incrVacuumStep(). */ static int allocateBtreePage(BtShared *, MemPage **, Pgno *, Pgno, u8); +#define BTALLOC_ANY 0 /* Allocate any page */ +#define BTALLOC_EXACT 1 /* Allocate exact page if possible */ +#define BTALLOC_LE 2 /* Allocate any page <= the parameter */ /* -** Perform a single step of an incremental-vacuum. If successful, -** return SQLITE_OK. If there is no work to do (and therefore no -** point in calling this function again), return SQLITE_DONE. +** Perform a single step of an incremental-vacuum. If successful, return +** SQLITE_OK. If there is no work to do (and therefore no point in +** calling this function again), return SQLITE_DONE. Or, if an error +** occurs, return some other error code. ** -** More specificly, this function attempts to re-organize the -** database so that the last page of the file currently in use -** is no longer in use. +** More specificly, this function attempts to re-organize the database so +** that the last page of the file currently in use is no longer in use. ** -** If the nFin parameter is non-zero, this function assumes -** that the caller will keep calling incrVacuumStep() until -** it returns SQLITE_DONE or an error, and that nFin is the -** number of pages the database file will contain after this -** process is complete. If nFin is zero, it is assumed that -** incrVacuumStep() will be called a finite amount of times -** which may or may not empty the freelist. A full autovacuum -** has nFin>0. A "PRAGMA incremental_vacuum" has nFin==0. +** Parameter nFin is the number of pages that this database would contain +** were this function called until it returns SQLITE_DONE. +** +** If the bCommit parameter is non-zero, this function assumes that the +** caller will keep calling incrVacuumStep() until it returns SQLITE_DONE +** or an error. bCommit is passed true for an auto-vacuum-on-commmit +** operation, or false for an incremental vacuum. */ -static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg){ +static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg, int bCommit){ Pgno nFreeList; /* Number of pages still on the free-list */ int rc; @@ -2953,15 +2955,15 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg){ } if( eType==PTRMAP_FREEPAGE ){ - if( nFin==0 ){ + if( bCommit==0 ){ /* Remove the page from the files free-list. This is not required - ** if nFin is non-zero. In that case, the free-list will be + ** if bCommit is non-zero. In that case, the free-list will be ** truncated to zero after this function returns, so it doesn't ** matter if it still contains some garbage entries. */ Pgno iFreePg; MemPage *pFreePg; - rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, iLastPg, 1); + rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, iLastPg, BTALLOC_EXACT); if( rc!=SQLITE_OK ){ return rc; } @@ -2971,28 +2973,34 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg){ } else { Pgno iFreePg; /* Index of free page to move pLastPg to */ MemPage *pLastPg; + u8 eMode = BTALLOC_ANY; /* Mode parameter for allocateBtreePage() */ + Pgno iNear = 0; /* nearby parameter for allocateBtreePage() */ rc = btreeGetPage(pBt, iLastPg, &pLastPg, 0); if( rc!=SQLITE_OK ){ return rc; } - /* If nFin is zero, this loop runs exactly once and page pLastPg + /* If bCommit is zero, this loop runs exactly once and page pLastPg ** is swapped with the first free page pulled off the free list. ** - ** On the other hand, if nFin is greater than zero, then keep + ** On the other hand, if bCommit is greater than zero, then keep ** looping until a free-page located within the first nFin pages ** of the file is found. */ + if( bCommit==0 ){ + eMode = BTALLOC_LE; + iNear = nFin; + } do { MemPage *pFreePg; - rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, 0, 0); + rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, iNear, eMode); if( rc!=SQLITE_OK ){ releasePage(pLastPg); return rc; } releasePage(pFreePg); - }while( nFin!=0 && iFreePg>nFin ); + }while( bCommit && iFreePg>nFin ); assert( iFreePgpDbPage); @@ -3006,7 +3014,7 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg){ } } - if( nFin==0 ){ + if( bCommit==0 ){ iLastPg--; while( iLastPg==PENDING_BYTE_PAGE(pBt)||PTRMAP_ISPAGE(pBt, iLastPg) ){ if( PTRMAP_ISPAGE(pBt, iLastPg) ){ @@ -3029,6 +3037,30 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg){ return SQLITE_OK; } +/* +** The database opened by the first argument is an auto-vacuum database +** nOrig pages in size containing nFree free pages. Return the expected +** size of the database in pages following an auto-vacuum operation. +*/ +static Pgno finalDbSize(BtShared *pBt, Pgno nOrig, Pgno nFree){ + int nEntry; /* Number of entries on one ptrmap page */ + Pgno nPtrmap; /* Number of PtrMap pages to be freed */ + Pgno nFin; /* Return value */ + + nEntry = pBt->usableSize/5; + nPtrmap = (nFree-nOrig+PTRMAP_PAGENO(pBt, nOrig)+nEntry)/nEntry; + nFin = nOrig - nFree - nPtrmap; + if( nOrig>PENDING_BYTE_PAGE(pBt) && nFinnOrig ) return SQLITE_CORRUPT_BKPT; + + return nFin; +} + /* ** A write-transaction must be opened before calling this function. ** It performs a single unit of work towards an incremental vacuum. @@ -3046,11 +3078,19 @@ int sqlite3BtreeIncrVacuum(Btree *p){ if( !pBt->autoVacuum ){ rc = SQLITE_DONE; }else{ - invalidateAllOverflowCache(pBt); - rc = incrVacuumStep(pBt, 0, btreePagecount(pBt)); - if( rc==SQLITE_OK ){ - rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); - put4byte(&pBt->pPage1->aData[28], pBt->nPage); + Pgno nOrig = btreePagecount(pBt); + Pgno nFree = get4byte(&pBt->pPage1->aData[36]); + Pgno nFin = finalDbSize(pBt, nOrig, nFree); + + if( nFinpPage1->pDbPage); + put4byte(&pBt->pPage1->aData[28], pBt->nPage); + } + }else{ + rc = SQLITE_DONE; } } sqlite3BtreeLeave(p); @@ -3077,9 +3117,7 @@ static int autoVacuumCommit(BtShared *pBt){ if( !pBt->incrVacuum ){ Pgno nFin; /* Number of pages in database after autovacuuming */ Pgno nFree; /* Number of pages on the freelist initially */ - Pgno nPtrmap; /* Number of PtrMap pages to be freed */ Pgno iFree; /* The next page to be freed */ - int nEntry; /* Number of entries on one ptrmap page */ Pgno nOrig; /* Database size before freeing */ nOrig = btreePagecount(pBt); @@ -3092,19 +3130,11 @@ static int autoVacuumCommit(BtShared *pBt){ } nFree = get4byte(&pBt->pPage1->aData[36]); - nEntry = pBt->usableSize/5; - nPtrmap = (nFree-nOrig+PTRMAP_PAGENO(pBt, nOrig)+nEntry)/nEntry; - nFin = nOrig - nFree - nPtrmap; - if( nOrig>PENDING_BYTE_PAGE(pBt) && nFinnOrig ) return SQLITE_CORRUPT_BKPT; for(iFree=nOrig; iFree>nFin && rc==SQLITE_OK; iFree--){ - rc = incrVacuumStep(pBt, nFin, iFree); + rc = incrVacuumStep(pBt, nFin, iFree, 1); } if( (rc==SQLITE_DONE || rc==SQLITE_OK) && nFree>0 ){ rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); @@ -4867,7 +4897,7 @@ static int allocateBtreePage( MemPage **ppPage, Pgno *pPgno, Pgno nearby, - u8 exact + u8 eMode ){ MemPage *pPage1; int rc; @@ -4895,16 +4925,19 @@ static int allocateBtreePage( ** the entire-list will be searched for that page. */ #ifndef SQLITE_OMIT_AUTOVACUUM - if( exact && nearby<=mxPage ){ - u8 eType; - assert( nearby>0 ); - assert( pBt->autoVacuum ); - rc = ptrmapGet(pBt, nearby, &eType, 0); - if( rc ) return rc; - if( eType==PTRMAP_FREEPAGE ){ - searchList = 1; + if( eMode==BTALLOC_EXACT ){ + if( nearby<=mxPage ){ + u8 eType; + assert( nearby>0 ); + assert( pBt->autoVacuum ); + rc = ptrmapGet(pBt, nearby, &eType, 0); + if( rc ) return rc; + if( eType==PTRMAP_FREEPAGE ){ + searchList = 1; + } } - *pPgno = nearby; + }else if( eMode==BTALLOC_LE ){ + searchList = 1; } #endif @@ -4959,11 +4992,13 @@ static int allocateBtreePage( rc = SQLITE_CORRUPT_BKPT; goto end_allocate_page; #ifndef SQLITE_OMIT_AUTOVACUUM - }else if( searchList && nearby==iTrunk ){ + }else if( searchList + && (nearby==iTrunk || (iTrunkpDbPage); @@ -5047,7 +5082,9 @@ static int allocateBtreePage( goto end_allocate_page; } testcase( iPage==mxPage ); - if( !searchList || iPage==nearby ){ + if( !searchList + || (iPage==nearby || (iPage Date: Fri, 22 Feb 2013 20:57:47 +0000 Subject: [PATCH 02/10] Fix a problem with the previous commit. FossilOrigin-Name: 720a3ceafc35b81936ed2eb1f07a7187d104f0a0 --- manifest | 15 ++++++--------- manifest.uuid | 2 +- src/btree.c | 24 +++++++++++++++++------- 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/manifest b/manifest index d14f19c439..ff7dff0ba5 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Avoid\smoving\spages\smore\sthan\sonce\sin\san\sincremental\svacuum\soperation. -D 2013-02-22T20:16:34.273 +C Fix\sa\sproblem\swith\sthe\sprevious\scommit. +D 2013-02-22T20:57:47.269 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in a48faa9e7dd7d556d84f5456eabe5825dd8a6282 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -121,7 +121,7 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c 32e35a3a4ea55b45c0e5f74eeb793aec71491517 F src/bitvec.c 26675fe8e431dc555e6f2d0e11e651d172234aa1 F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 -F src/btree.c 960274cb93c1d85e82bd106094e0890d89434ab8 +F src/btree.c 76f063ffd70aba11b3f4701d216c157e1a81b51d F src/btree.h 3ad7964d6c5b1c7bff569aab6adfa075f8bf06cd F src/btreeInt.h 4e5c2bd0f9b36b2a815a6d84f771a61a65830621 F src/build.c 73ca65f32938e4e0d94e831b61b5749b211b79be @@ -1034,10 +1034,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P 9bd9bd9cab8c804c1a51d472199459176044a633 -R d336ad839cab7fc86035cb53790f3fce -T *branch * incr-vacuum-opt -T *sym-incr-vacuum-opt * -T -sym-trunk * +P c3939d249119b47bd57baa11a5ed7cc6014fc795 +R f58494bafc2bb0d7737cf9b62d925506 U dan -Z cd58f1fbd68ec5de5d0f48d285a49284 +Z 7eeaf98ba8f2d987bdc515914ba34037 diff --git a/manifest.uuid b/manifest.uuid index 6676236222..6accd36d88 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c3939d249119b47bd57baa11a5ed7cc6014fc795 \ No newline at end of file +720a3ceafc35b81936ed2eb1f07a7187d104f0a0 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index de22559968..b3a907c5ab 100644 --- a/src/btree.c +++ b/src/btree.c @@ -5061,14 +5061,24 @@ static int allocateBtreePage( unsigned char *aData = pTrunk->aData; if( nearby>0 ){ u32 i; - int dist; closest = 0; - dist = sqlite3AbsInt32(get4byte(&aData[8]) - nearby); - for(i=1; i Date: Sat, 23 Feb 2013 16:40:46 +0000 Subject: [PATCH 03/10] If a rollback mode transaction reduces the size of the database file, avoid actually truncating the file until after the transaction has been committed (but before the db has been unlocked). This means pages that are removed from the database by truncating the file need not be journalled. FossilOrigin-Name: b73847f17b7ae1298dfc52de6c4c4bc809bc77a3 --- manifest | 20 +++++++------- manifest.uuid | 2 +- src/backup.c | 17 ++++++++++-- src/btree.c | 59 +++++++++++++++++++++++------------------ src/btreeInt.h | 1 + src/pager.c | 67 ++++++++++++++++++----------------------------- test/tkt3762.test | 4 +-- 7 files changed, 89 insertions(+), 81 deletions(-) diff --git a/manifest b/manifest index ff7dff0ba5..a4147e0d00 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sproblem\swith\sthe\sprevious\scommit. -D 2013-02-22T20:57:47.269 +C If\sa\srollback\smode\stransaction\sreduces\sthe\ssize\sof\sthe\sdatabase\sfile,\savoid\sactually\struncating\sthe\sfile\suntil\safter\sthe\stransaction\shas\sbeen\scommitted\s(but\sbefore\sthe\sdb\shas\sbeen\sunlocked).\sThis\smeans\spages\sthat\sare\sremoved\sfrom\sthe\sdatabase\sby\struncating\sthe\sfile\sneed\snot\sbe\sjournalled. +D 2013-02-23T16:40:46.526 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in a48faa9e7dd7d556d84f5456eabe5825dd8a6282 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -118,12 +118,12 @@ F src/alter.c f8db986c03eb0bfb221523fc9bbb9d0b70de3168 F src/analyze.c 7553068d21e32a57fc33ab6b2393fc8c1ba41410 F src/attach.c ea5247f240e2c08afd608e9beb380814b86655e1 F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 -F src/backup.c 32e35a3a4ea55b45c0e5f74eeb793aec71491517 +F src/backup.c 0b8d2108a10ada00e642525921960b0c27451955 F src/bitvec.c 26675fe8e431dc555e6f2d0e11e651d172234aa1 F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 -F src/btree.c 76f063ffd70aba11b3f4701d216c157e1a81b51d +F src/btree.c f021a7f59fd340577c2f9b7d6e951576af335cfb F src/btree.h 3ad7964d6c5b1c7bff569aab6adfa075f8bf06cd -F src/btreeInt.h 4e5c2bd0f9b36b2a815a6d84f771a61a65830621 +F src/btreeInt.h eecc84f02375b2bb7a44abbcbbe3747dde73edb2 F src/build.c 73ca65f32938e4e0d94e831b61b5749b211b79be F src/callback.c d7e46f40c3cf53c43550b7da7a1d0479910b62cc F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac @@ -162,7 +162,7 @@ F src/os.h 027491c77d2404c0a678bb3fb06286f331eb9b57 F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04 F src/os_unix.c dfdc04b126f7b05dcb2e2cc5c1262f98acbb49d9 F src/os_win.c eabd00b813577d36bd66271cb08dd64ea0589dac -F src/pager.c 4092c907222cfd451c74fe6bd2fd64b342f7190f +F src/pager.c 0dbf5ff5d5d7d3a21fcab82e9e4d129b6fe6314f F src/pager.h 1109a06578ec5574dc2c74cf8d9f69daf36fe3e0 F src/parse.y 5d5e12772845805fdfeb889163516b84fbb9ae95 F src/pcache.c f8043b433a57aba85384a531e3937a804432a346 @@ -871,7 +871,7 @@ F test/tkt3718.test 3b59dcb5c4e7754dacd91e7fd353a61492cc402a F test/tkt3731.test 0c5f4cbffe102d43c3b2188af91a9e36348f974b F test/tkt3757.test 10cd679a88675c880533083fc79ac04324525595 F test/tkt3761.test b95ea9c98f21cf91325f18a984887e62caceab33 -F test/tkt3762.test 2a9f3b03df44ec49ec0cfa8d5da6574c2a7853df +F test/tkt3762.test 4d439ff7abdc8d9323150269d182c37c2d514576 F test/tkt3773.test 7bca904d2a647a6a4a291bd86d7fd7c73855b789 F test/tkt3791.test a6624b9a80b216a26cf473607f42f3e51898c267 F test/tkt3793.test d90ffd75c52413908d15e1c44fc2ea9c80fcc449 @@ -1034,7 +1034,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P c3939d249119b47bd57baa11a5ed7cc6014fc795 -R f58494bafc2bb0d7737cf9b62d925506 +P 720a3ceafc35b81936ed2eb1f07a7187d104f0a0 +R 2fcb8a3a4c948e70b98e89248d0d9b21 U dan -Z 7eeaf98ba8f2d987bdc515914ba34037 +Z 61c42a3e0f1600d37d1de1cf170b2233 diff --git a/manifest.uuid b/manifest.uuid index 6accd36d88..5875324cc6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -720a3ceafc35b81936ed2eb1f07a7187d104f0a0 \ No newline at end of file +b73847f17b7ae1298dfc52de6c4c4bc809bc77a3 \ No newline at end of file diff --git a/src/backup.c b/src/backup.c index d3614b88c3..89e0f00e66 100644 --- a/src/backup.c +++ b/src/backup.c @@ -462,7 +462,6 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){ nDestTruncate = nSrcPage * (pgszSrc/pgszDest); } assert( nDestTruncate>0 ); - sqlite3PagerTruncateImage(pDestPager, nDestTruncate); if( pgszSrc=PENDING_BYTE && iSize<=PENDING_BYTE+pgszDest )); - /* This call ensures that all data required to recreate the original + /* This block ensures that all data required to recreate the original ** database has been stored in the journal for pDestPager and the ** journal synced to disk. So at this point we may safely modify ** the database file in any way, knowing that if a power failure ** occurs, the original database will be reconstructed from the ** journal file. */ + sqlite3PagerPagecount(pDestPager, &nDstPage); + for(iPg=nDestTruncate; rc==SQLITE_OK && iPg<=(Pgno)nDstPage; iPg++){ + if( iPg!=PENDING_BYTE_PAGE(p->pDest->pBt) ){ + DbPage *pPg; + rc = sqlite3PagerGet(pDestPager, iPg, &pPg); + if( rc==SQLITE_OK ){ + rc = sqlite3PagerWrite(pPg); + sqlite3PagerUnref(pPg); + } + } + } rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 1); /* Write the extra pages and truncate the database file as required */ @@ -519,6 +531,7 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){ rc = sqlite3PagerSync(pDestPager); } }else{ + sqlite3PagerTruncateImage(pDestPager, nDestTruncate); rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 0); } diff --git a/src/btree.c b/src/btree.c index b3a907c5ab..89f7acdb5e 100644 --- a/src/btree.c +++ b/src/btree.c @@ -2595,6 +2595,7 @@ int sqlite3BtreeBeginTrans(Btree *p, int wrflag){ if( p->inTrans==TRANS_WRITE || (p->inTrans==TRANS_READ && !wrflag) ){ goto trans_begun; } + assert( pBt->bDoTruncate==0 ); /* Write transactions are not possible on a read-only database */ if( (pBt->btsFlags & BTS_READ_ONLY)!=0 && wrflag ){ @@ -3003,10 +3004,7 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg, int bCommit){ }while( bCommit && iFreePg>nFin ); assert( iFreePgpDbPage); - if( rc==SQLITE_OK ){ - rc = relocatePage(pBt, pLastPg, eType, iPtrPage, iFreePg, nFin!=0); - } + rc = relocatePage(pBt, pLastPg, eType, iPtrPage, iFreePg, nFin!=0); releasePage(pLastPg); if( rc!=SQLITE_OK ){ return rc; @@ -3015,23 +3013,10 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg, int bCommit){ } if( bCommit==0 ){ - iLastPg--; - while( iLastPg==PENDING_BYTE_PAGE(pBt)||PTRMAP_ISPAGE(pBt, iLastPg) ){ - if( PTRMAP_ISPAGE(pBt, iLastPg) ){ - MemPage *pPg; - rc = btreeGetPage(pBt, iLastPg, &pPg, 0); - if( rc!=SQLITE_OK ){ - return rc; - } - rc = sqlite3PagerWrite(pPg->pDbPage); - releasePage(pPg); - if( rc!=SQLITE_OK ){ - return rc; - } - } + do { iLastPg--; - } - sqlite3PagerTruncateImage(pBt->pPager, iLastPg); + }while( iLastPg==PENDING_BYTE_PAGE(pBt) || PTRMAP_ISPAGE(pBt, iLastPg) ); + pBt->bDoTruncate = 1; pBt->nPage = iLastPg; } return SQLITE_OK; @@ -3141,7 +3126,7 @@ static int autoVacuumCommit(BtShared *pBt){ put4byte(&pBt->pPage1->aData[32], 0); put4byte(&pBt->pPage1->aData[36], 0); put4byte(&pBt->pPage1->aData[28], nFin); - sqlite3PagerTruncateImage(pBt->pPager, nFin); + pBt->bDoTruncate = 1; pBt->nPage = nFin; } if( rc!=SQLITE_OK ){ @@ -3196,6 +3181,9 @@ int sqlite3BtreeCommitPhaseOne(Btree *p, const char *zMaster){ return rc; } } + if( pBt->bDoTruncate ){ + sqlite3PagerTruncateImage(pBt->pPager, pBt->nPage); + } #endif rc = sqlite3PagerCommitPhaseOne(pBt->pPager, zMaster, 0); sqlite3BtreeLeave(p); @@ -3211,6 +3199,9 @@ static void btreeEndTransaction(Btree *p){ BtShared *pBt = p->pBt; assert( sqlite3BtreeHoldsMutex(p) ); +#ifndef SQLITE_OMIT_AUTOVACUUM + pBt->bDoTruncate = 0; +#endif btreeClearHasContent(pBt); if( p->inTrans>TRANS_NONE && p->db->activeVdbeCnt>1 ){ /* If there are other active statements that belong to this database @@ -5121,8 +5112,26 @@ static int allocateBtreePage( pPrevTrunk = 0; }while( searchList ); }else{ - /* There are no pages on the freelist, so create a new page at the - ** end of the file */ + /* There are no pages on the freelist, so append a new page to the + ** database image. + ** + ** Normally, new pages allocated by this block can be requested from the + ** pager layer with the 'no-content' flag set. This prevents the pager + ** from trying to read the pages content from disk. However, if the + ** current transaction has already run one or more incremental-vacuum + ** steps, then the page we are about to allocate may contain content + ** that is required in the event of a rollback. In this case, do + ** not set the no-content flag. This causes the pager to load and journal + ** the current page content before overwriting it. + ** + ** Note that the pager will not actually attempt to load or journal + ** content for any page that really does lie past the end of the database + ** file on disk. So the effects of disabling the no-content optimization + ** here are confined to those pages that lie between the end of the + ** database image and the end of the database file. + */ + int bNoContent = (0==pBt->bDoTruncate); + rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); if( rc ) return rc; pBt->nPage++; @@ -5137,7 +5146,7 @@ static int allocateBtreePage( MemPage *pPg = 0; TRACE(("ALLOCATE: %d from end of file (pointer-map page)\n", pBt->nPage)); assert( pBt->nPage!=PENDING_BYTE_PAGE(pBt) ); - rc = btreeGetPage(pBt, pBt->nPage, &pPg, 1); + rc = btreeGetPage(pBt, pBt->nPage, &pPg, bNoContent); if( rc==SQLITE_OK ){ rc = sqlite3PagerWrite(pPg->pDbPage); releasePage(pPg); @@ -5151,7 +5160,7 @@ static int allocateBtreePage( *pPgno = pBt->nPage; assert( *pPgno!=PENDING_BYTE_PAGE(pBt) ); - rc = btreeGetPage(pBt, *pPgno, ppPage, 1); + rc = btreeGetPage(pBt, *pPgno, ppPage, bNoContent); if( rc ) return rc; rc = sqlite3PagerWrite((*ppPage)->pDbPage); if( rc!=SQLITE_OK ){ diff --git a/src/btreeInt.h b/src/btreeInt.h index b157decec7..ce3c5493f8 100644 --- a/src/btreeInt.h +++ b/src/btreeInt.h @@ -411,6 +411,7 @@ struct BtShared { #ifndef SQLITE_OMIT_AUTOVACUUM u8 autoVacuum; /* True if auto-vacuum is enabled */ u8 incrVacuum; /* True if incr-vacuum is enabled */ + u8 bDoTruncate; /* True to truncate db on commit */ #endif u8 inTransaction; /* Transaction state */ u8 max1bytePayload; /* Maximum first byte of cell for a 1-byte payload */ diff --git a/src/pager.c b/src/pager.c index 5879cf760a..863368f591 100644 --- a/src/pager.c +++ b/src/pager.c @@ -1838,6 +1838,8 @@ static int pager_error(Pager *pPager, int rc){ return rc; } +static int pager_truncate(Pager *pPager, Pgno nPage); + /* ** This routine ends a transaction. A transaction is usually ended by ** either a COMMIT or a ROLLBACK operation. This routine may be called @@ -1891,7 +1893,7 @@ static int pager_error(Pager *pPager, int rc){ ** to the first error encountered (the journal finalization one) is ** returned. */ -static int pager_end_transaction(Pager *pPager, int hasMaster){ +static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){ int rc = SQLITE_OK; /* Error code from journal finalization operation */ int rc2 = SQLITE_OK; /* Error code from db file unlock operation */ @@ -1977,7 +1979,17 @@ static int pager_end_transaction(Pager *pPager, int hasMaster){ */ rc2 = sqlite3WalEndWriteTransaction(pPager->pWal); assert( rc2==SQLITE_OK ); + }else if( rc==SQLITE_OK && bCommit && pPager->dbFileSize>pPager->dbSize ){ + /* This branch is taken when committing a transaction in rollback-journal + ** mode if the database file on disk is larger than the database image. + ** At this point the journal has been finalized and the transaction + ** successfully committed, but the EXCLUSIVE lock is still held on the + ** file. So it is safe to truncate the database file to its minimum + ** required size. */ + assert( pPager->eLock==EXCLUSIVE_LOCK ); + rc = pager_truncate(pPager, pPager->dbSize); } + if( !pPager->exclusiveMode && (!pagerUseWal(pPager) || sqlite3WalExclusiveMode(pPager->pWal, 0)) ){ @@ -2016,7 +2028,7 @@ static void pagerUnlockAndRollback(Pager *pPager){ sqlite3EndBenignMalloc(); }else if( !pPager->exclusiveMode ){ assert( pPager->eState==PAGER_READER ); - pager_end_transaction(pPager, 0); + pager_end_transaction(pPager, 0, 0); } } pager_unlock(pPager); @@ -2791,7 +2803,7 @@ end_playback: rc = sqlite3PagerSync(pPager); } if( rc==SQLITE_OK ){ - rc = pager_end_transaction(pPager, zMaster[0]!='\0'); + rc = pager_end_transaction(pPager, zMaster[0]!='\0', 0); testcase( rc!=SQLITE_OK ); } if( rc==SQLITE_OK && zMaster[0] && res ){ @@ -5885,36 +5897,6 @@ int sqlite3PagerCommitPhaseOne( #endif if( rc!=SQLITE_OK ) goto commit_phase_one_exit; - /* If this transaction has made the database smaller, then all pages - ** being discarded by the truncation must be written to the journal - ** file. - ** - ** Before reading the pages with page numbers larger than the - ** current value of Pager.dbSize, set dbSize back to the value - ** that it took at the start of the transaction. Otherwise, the - ** calls to sqlite3PagerGet() return zeroed pages instead of - ** reading data from the database file. - */ - if( pPager->dbSizedbOrigSize - && pPager->journalMode!=PAGER_JOURNALMODE_OFF - ){ - Pgno i; /* Iterator variable */ - const Pgno iSkip = PAGER_MJ_PGNO(pPager); /* Pending lock page */ - const Pgno dbSize = pPager->dbSize; /* Database image size */ - pPager->dbSize = pPager->dbOrigSize; - for( i=dbSize+1; i<=pPager->dbOrigSize; i++ ){ - if( !sqlite3BitvecTest(pPager->pInJournal, i) && i!=iSkip ){ - PgHdr *pPage; /* Page to journal */ - rc = sqlite3PagerGet(pPager, i, &pPage); - if( rc!=SQLITE_OK ) goto commit_phase_one_exit; - rc = sqlite3PagerWrite(pPage); - sqlite3PagerUnref(pPage); - if( rc!=SQLITE_OK ) goto commit_phase_one_exit; - } - } - pPager->dbSize = dbSize; - } - /* Write the master journal name into the journal file. If a master ** journal file name has already been written to the journal file, ** or if zMaster is NULL (no master journal), then this call is a no-op. @@ -5942,11 +5924,14 @@ int sqlite3PagerCommitPhaseOne( goto commit_phase_one_exit; } sqlite3PcacheCleanAll(pPager->pPCache); - - /* If the file on disk is not the same size as the database image, - ** then use pager_truncate to grow or shrink the file here. - */ - if( pPager->dbSize!=pPager->dbFileSize ){ + + /* If the file on disk is smaller than the database image, use + ** pager_truncate to grow the file here. This can happen if the database + ** image was extended as part of the current transaction and then the + ** last page in the db image moved to the free-list. In this case the + ** last page is never written out to disk, leaving the database file + ** undersized. Fix this now if it is the case. */ + if( pPager->dbSize>pPager->dbFileSize ){ Pgno nNew = pPager->dbSize - (pPager->dbSize==PAGER_MJ_PGNO(pPager)); assert( pPager->eState==PAGER_WRITER_DBMOD ); rc = pager_truncate(pPager, nNew); @@ -6019,7 +6004,7 @@ int sqlite3PagerCommitPhaseTwo(Pager *pPager){ } PAGERTRACE(("COMMIT %d\n", PAGERID(pPager))); - rc = pager_end_transaction(pPager, pPager->setMaster); + rc = pager_end_transaction(pPager, pPager->setMaster, 1); return pager_error(pPager, rc); } @@ -6064,11 +6049,11 @@ int sqlite3PagerRollback(Pager *pPager){ if( pagerUseWal(pPager) ){ int rc2; rc = sqlite3PagerSavepoint(pPager, SAVEPOINT_ROLLBACK, -1); - rc2 = pager_end_transaction(pPager, pPager->setMaster); + rc2 = pager_end_transaction(pPager, pPager->setMaster, 0); if( rc==SQLITE_OK ) rc = rc2; }else if( !isOpen(pPager->jfd) || pPager->eState==PAGER_WRITER_LOCKED ){ int eState = pPager->eState; - rc = pager_end_transaction(pPager, 0); + rc = pager_end_transaction(pPager, 0, 0); if( !MEMDB && eState>PAGER_WRITER_LOCKED ){ /* This can happen using journal_mode=off. Move the pager to the error ** state to indicate that the contents of the cache may not be trusted. diff --git a/test/tkt3762.test b/test/tkt3762.test index c24041c96e..424b1e6487 100644 --- a/test/tkt3762.test +++ b/test/tkt3762.test @@ -10,8 +10,8 @@ #*********************************************************************** # # Ticket #3762: Make sure that an incremental vacuum that reduces the -# size of the database file such that a pointer-map page is elemented -# can be correctly rolled back. +# size of the database file such that if a pointer-map page is eliminated +# it can be correctly rolled back. # # That ticket #3762 has been fixed has already been verified by the # savepoint6.test test script. But this script is simplier and a From 87ade19eb91f1c71a21e89c6b8f8a680a034aa8e Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 23 Feb 2013 17:49:16 +0000 Subject: [PATCH 04/10] Fix off-by-one bug in [c3939d2491] uncovered by th3. FossilOrigin-Name: 66f9faa9a969d004486ee38d492fb3eda6cdebab --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/btree.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index a4147e0d00..d869216321 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C If\sa\srollback\smode\stransaction\sreduces\sthe\ssize\sof\sthe\sdatabase\sfile,\savoid\sactually\struncating\sthe\sfile\suntil\safter\sthe\stransaction\shas\sbeen\scommitted\s(but\sbefore\sthe\sdb\shas\sbeen\sunlocked).\sThis\smeans\spages\sthat\sare\sremoved\sfrom\sthe\sdatabase\sby\struncating\sthe\sfile\sneed\snot\sbe\sjournalled. -D 2013-02-23T16:40:46.526 +C Fix\soff-by-one\sbug\sin\s[c3939d2491]\suncovered\sby\sth3. +D 2013-02-23T17:49:16.450 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in a48faa9e7dd7d556d84f5456eabe5825dd8a6282 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -121,7 +121,7 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c 0b8d2108a10ada00e642525921960b0c27451955 F src/bitvec.c 26675fe8e431dc555e6f2d0e11e651d172234aa1 F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 -F src/btree.c f021a7f59fd340577c2f9b7d6e951576af335cfb +F src/btree.c bcd64dff70af19e3a166853b7b728887cd4cc975 F src/btree.h 3ad7964d6c5b1c7bff569aab6adfa075f8bf06cd F src/btreeInt.h eecc84f02375b2bb7a44abbcbbe3747dde73edb2 F src/build.c 73ca65f32938e4e0d94e831b61b5749b211b79be @@ -1034,7 +1034,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P 720a3ceafc35b81936ed2eb1f07a7187d104f0a0 -R 2fcb8a3a4c948e70b98e89248d0d9b21 +P b73847f17b7ae1298dfc52de6c4c4bc809bc77a3 +R 34a70e559a11e4b7cf3c06168257f235 U dan -Z 61c42a3e0f1600d37d1de1cf170b2233 +Z 1b7c8c9ddd8f5c22095277131689ae60 diff --git a/manifest.uuid b/manifest.uuid index 5875324cc6..bda95df179 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b73847f17b7ae1298dfc52de6c4c4bc809bc77a3 \ No newline at end of file +66f9faa9a969d004486ee38d492fb3eda6cdebab \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 89f7acdb5e..b46b32ffca 100644 --- a/src/btree.c +++ b/src/btree.c @@ -5056,7 +5056,7 @@ static int allocateBtreePage( if( eMode==BTALLOC_LE ){ for(i=0; i Date: Sat, 23 Feb 2013 18:58:11 +0000 Subject: [PATCH 05/10] Enhancements to test scripts. No code changes. FossilOrigin-Name: ccab94c10d54e585de918bbf82dec188287d93b2 --- manifest | 16 ++++---- manifest.uuid | 2 +- src/test_vfs.c | 32 ++++++++------- test/incrvacuum_ioerr.test | 4 +- test/tester.tcl | 83 +++++++++++++++++++++++--------------- 5 files changed, 78 insertions(+), 59 deletions(-) diff --git a/manifest b/manifest index d869216321..9a1539d2ca 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\soff-by-one\sbug\sin\s[c3939d2491]\suncovered\sby\sth3. -D 2013-02-23T17:49:16.450 +C Enhancements\sto\stest\sscripts.\sNo\scode\schanges. +D 2013-02-23T18:58:11.423 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in a48faa9e7dd7d556d84f5456eabe5825dd8a6282 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -229,7 +229,7 @@ F src/test_superlock.c 2b97936ca127d13962c3605dbc9a4ef269c424cd F src/test_syscall.c a992d8c80ea91fbf21fb2dd570db40e77dd7e6ae F src/test_tclvar.c f4dc67d5f780707210d6bb0eb6016a431c04c7fa F src/test_thread.c e286f2173563f2a1747c24bcda6b9d030bf4f4e4 -F src/test_vfs.c c6260ef238c1142c8f8bd402db02216afd182ae3 +F src/test_vfs.c fb16b2d9938cf0c1afc5a423b55b952fcc024275 F src/test_vfstrace.c 34b544e80ba7fb77be15395a609c669df2e660a2 F src/test_wholenumber.c 3d2b9ed1505c40ad5c5ca2ad16ae7a289d6cc251 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 @@ -534,7 +534,7 @@ F test/incrblob_err.test d2562d2771ebffd4b3af89ef64c140dd44371597 F test/incrblobfault.test 917c0292224c64a56ef7215fd633a3a82f805be0 F test/incrvacuum.test d2a6ddf5e429720b5fe502766af747915ccf6c32 F test/incrvacuum2.test 379eeb8740b0ef60c372c439ad4cbea20b34bb9b -F test/incrvacuum_ioerr.test 22f208d01c528403240e05beecc41dc98ed01637 +F test/incrvacuum_ioerr.test 293f2714571255539c8c789da2f7de4ec3f7101e F test/index.test b5429732b3b983fa810e3ac867d7ca85dae35097 F test/index2.test ee83c6b5e3173a3d7137140d945d9a5d4fdfb9d6 F test/index3.test 423a25c789fc8cc51aaf2a4370bbdde2d9e9eed7 @@ -752,7 +752,7 @@ F test/tclsqlite.test 37a61c2da7e3bfe3b8c1a2867199f6b860df5d43 F test/tempdb.test 19d0f66e2e3eeffd68661a11c83ba5e6ace9128c F test/temptable.test 51edd31c65ed1560dd600b1796e8325df96318e2 F test/temptrigger.test 26670ed7a39cf2296a7f0a9e0a1d7bdb7abe936d -F test/tester.tcl 0560b09498876da7714fff680c5d892b9228862f +F test/tester.tcl 2918ebca150b67ca25b1682f8ecd857af77fab05 F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5 F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58 F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7 @@ -1034,7 +1034,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P b73847f17b7ae1298dfc52de6c4c4bc809bc77a3 -R 34a70e559a11e4b7cf3c06168257f235 +P 66f9faa9a969d004486ee38d492fb3eda6cdebab +R 87b39f8ba9e2866ed1adab1a9b990f83 U dan -Z 1b7c8c9ddd8f5c22095277131689ae60 +Z c23ef7906674057cc290bb43146b99c4 diff --git a/manifest.uuid b/manifest.uuid index bda95df179..265b085615 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -66f9faa9a969d004486ee38d492fb3eda6cdebab \ No newline at end of file +ccab94c10d54e585de918bbf82dec188287d93b2 \ No newline at end of file diff --git a/src/test_vfs.c b/src/test_vfs.c index 93c556b56e..933de99515 100644 --- a/src/test_vfs.c +++ b/src/test_vfs.c @@ -265,7 +265,8 @@ static void tvfsExecTcl( const char *zMethod, Tcl_Obj *arg1, Tcl_Obj *arg2, - Tcl_Obj *arg3 + Tcl_Obj *arg3, + Tcl_Obj *arg4 ){ int rc; /* Return code from Tcl_EvalObj() */ Tcl_Obj *pEval; @@ -282,6 +283,7 @@ static void tvfsExecTcl( if( arg1 ) Tcl_ListObjAppendElement(p->interp, pEval, arg1); if( arg2 ) Tcl_ListObjAppendElement(p->interp, pEval, arg2); if( arg3 ) Tcl_ListObjAppendElement(p->interp, pEval, arg3); + if( arg4 ) Tcl_ListObjAppendElement(p->interp, pEval, arg4); rc = Tcl_EvalObjEx(p->interp, pEval, TCL_EVAL_GLOBAL); if( rc!=TCL_OK ){ @@ -302,7 +304,7 @@ static int tvfsClose(sqlite3_file *pFile){ if( p->pScript && p->mask&TESTVFS_CLOSE_MASK ){ tvfsExecTcl(p, "xClose", - Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0 + Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0, 0 ); } @@ -333,7 +335,7 @@ static int tvfsRead( Testvfs *p = (Testvfs *)pFd->pVfs->pAppData; if( p->pScript && p->mask&TESTVFS_READ_MASK ){ tvfsExecTcl(p, "xRead", - Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0 + Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0, 0 ); tvfsResultCode(p, &rc); } @@ -362,7 +364,7 @@ static int tvfsWrite( if( p->pScript && p->mask&TESTVFS_WRITE_MASK ){ tvfsExecTcl(p, "xWrite", Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, - Tcl_NewWideIntObj(iOfst) + Tcl_NewWideIntObj(iOfst), Tcl_NewIntObj(iAmt) ); tvfsResultCode(p, &rc); } @@ -390,7 +392,7 @@ static int tvfsTruncate(sqlite3_file *pFile, sqlite_int64 size){ if( p->pScript && p->mask&TESTVFS_TRUNCATE_MASK ){ tvfsExecTcl(p, "xTruncate", - Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0 + Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0, 0 ); tvfsResultCode(p, &rc); } @@ -431,7 +433,7 @@ static int tvfsSync(sqlite3_file *pFile, int flags){ tvfsExecTcl(p, "xSync", Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, - Tcl_NewStringObj(zFlags, -1) + Tcl_NewStringObj(zFlags, -1), 0 ); tvfsResultCode(p, &rc); } @@ -578,7 +580,7 @@ static int tvfsOpen( z += strlen(z) + 1; } } - tvfsExecTcl(p, "xOpen", Tcl_NewStringObj(pFd->zFilename, -1), pArg, 0); + tvfsExecTcl(p, "xOpen", Tcl_NewStringObj(pFd->zFilename, -1), pArg, 0, 0); Tcl_DecrRefCount(pArg); if( tvfsResultCode(p, &rc) ){ if( rc!=SQLITE_OK ) return rc; @@ -635,7 +637,7 @@ static int tvfsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ if( p->pScript && p->mask&TESTVFS_DELETE_MASK ){ tvfsExecTcl(p, "xDelete", - Tcl_NewStringObj(zPath, -1), Tcl_NewIntObj(dirSync), 0 + Tcl_NewStringObj(zPath, -1), Tcl_NewIntObj(dirSync), 0, 0 ); tvfsResultCode(p, &rc); } @@ -663,7 +665,7 @@ static int tvfsAccess( if( flags==SQLITE_ACCESS_READWRITE ) zArg = "SQLITE_ACCESS_READWRITE"; if( flags==SQLITE_ACCESS_READ ) zArg = "SQLITE_ACCESS_READ"; tvfsExecTcl(p, "xAccess", - Tcl_NewStringObj(zPath, -1), Tcl_NewStringObj(zArg, -1), 0 + Tcl_NewStringObj(zPath, -1), Tcl_NewStringObj(zArg, -1), 0, 0 ); if( tvfsResultCode(p, &rc) ){ if( rc!=SQLITE_OK ) return rc; @@ -691,7 +693,7 @@ static int tvfsFullPathname( Testvfs *p = (Testvfs *)pVfs->pAppData; if( p->pScript && p->mask&TESTVFS_FULLPATHNAME_MASK ){ int rc; - tvfsExecTcl(p, "xFullPathname", Tcl_NewStringObj(zPath, -1), 0, 0); + tvfsExecTcl(p, "xFullPathname", Tcl_NewStringObj(zPath, -1), 0, 0, 0); if( tvfsResultCode(p, &rc) ){ if( rc!=SQLITE_OK ) return rc; } @@ -771,7 +773,7 @@ static int tvfsShmOpen(sqlite3_file *pFile){ */ Tcl_ResetResult(p->interp); if( p->pScript && p->mask&TESTVFS_SHMOPEN_MASK ){ - tvfsExecTcl(p, "xShmOpen", Tcl_NewStringObj(pFd->zFilename, -1), 0, 0); + tvfsExecTcl(p, "xShmOpen", Tcl_NewStringObj(pFd->zFilename, -1), 0, 0, 0); if( tvfsResultCode(p, &rc) ){ if( rc!=SQLITE_OK ) return rc; } @@ -841,7 +843,7 @@ static int tvfsShmMap( Tcl_ListObjAppendElement(p->interp, pArg, Tcl_NewIntObj(pgsz)); Tcl_ListObjAppendElement(p->interp, pArg, Tcl_NewIntObj(isWrite)); tvfsExecTcl(p, "xShmMap", - Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, pArg + Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, pArg, 0 ); tvfsResultCode(p, &rc); Tcl_DecrRefCount(pArg); @@ -891,7 +893,7 @@ static int tvfsShmLock( } tvfsExecTcl(p, "xShmLock", Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, - Tcl_NewStringObj(zLock, -1) + Tcl_NewStringObj(zLock, -1), 0 ); tvfsResultCode(p, &rc); } @@ -937,7 +939,7 @@ static void tvfsShmBarrier(sqlite3_file *pFile){ if( p->pScript && p->mask&TESTVFS_SHMBARRIER_MASK ){ tvfsExecTcl(p, "xShmBarrier", - Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0 + Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0, 0 ); } } @@ -961,7 +963,7 @@ static int tvfsShmUnmap( if( p->pScript && p->mask&TESTVFS_SHMCLOSE_MASK ){ tvfsExecTcl(p, "xShmUnmap", - Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0 + Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0, 0 ); tvfsResultCode(p, &rc); } diff --git a/test/incrvacuum_ioerr.test b/test/incrvacuum_ioerr.test index 946925d7dc..aecb6f8747 100644 --- a/test/incrvacuum_ioerr.test +++ b/test/incrvacuum_ioerr.test @@ -139,8 +139,8 @@ ifcapable shared_cache { # Figure out how big the database is and how many free pages it # has before running incremental-vacuum. # - set nPage [expr {[file size test.db]/1024}] set nFree [execsql {pragma freelist_count} db1] + set nPage [execsql {pragma page_count} db1] # Now run incremental-vacuum to vacuum 5 pages from the db file. # The iTest'th I/O call is set to fail. @@ -158,7 +158,7 @@ ifcapable shared_cache { set ::sqlite_io_error_hardhit 0 set nFree2 [execsql {pragma freelist_count} db1] - set nPage2 [expr {[file size test.db]/1024}] + set nPage2 [execsql {pragma page_count} db1] do_test incrvacuum-ioerr-4.$iTest.2 { set shrink [expr {$nPage-$nPage2}] diff --git a/test/tester.tcl b/test/tester.tcl index a7e6c99580..f360840789 100644 --- a/test/tester.tcl +++ b/test/tester.tcl @@ -1118,6 +1118,25 @@ proc crashsql {args} { lappend r $msg } +proc run_ioerr_prep {} { + set ::sqlite_io_error_pending 0 + catch {db close} + catch {db2 close} + catch {forcedelete test.db} + catch {forcedelete test.db-journal} + catch {forcedelete test2.db} + catch {forcedelete test2.db-journal} + set ::DB [sqlite3 db test.db; sqlite3_connection_pointer db] + sqlite3_extended_result_codes $::DB $::ioerropts(-erc) + if {[info exists ::ioerropts(-tclprep)]} { + eval $::ioerropts(-tclprep) + } + if {[info exists ::ioerropts(-sqlprep)]} { + execsql $::ioerropts(-sqlprep) + } + expr 0 +} + # Usage: do_ioerr_test # # This proc is used to implement test cases that check that IO errors @@ -1150,10 +1169,26 @@ proc do_ioerr_test {testname args} { # TEMPORARY: For 3.5.9, disable testing of extended result codes. There are # a couple of obscure IO errors that do not return them. set ::ioerropts(-erc) 0 + + # Create a single TCL script from the TCL and SQL specified + # as the body of the test. + set ::ioerrorbody {} + if {[info exists ::ioerropts(-tclbody)]} { + append ::ioerrorbody "$::ioerropts(-tclbody)\n" + } + if {[info exists ::ioerropts(-sqlbody)]} { + append ::ioerrorbody "db eval {$::ioerropts(-sqlbody)}" + } + + save_prng_state + if {$::ioerropts(-cksum)} { + run_ioerr_prep + eval $::ioerrorbody + set ::goodcksum [cksum] + } set ::go 1 #reset_prng_state - save_prng_state for {set n $::ioerropts(-start)} {$::go} {incr n} { set ::TN $n incr ::ioerropts(-count) -1 @@ -1170,27 +1205,12 @@ proc do_ioerr_test {testname args} { # Delete the files test.db and test2.db, then execute the TCL and # SQL (in that order) to prepare for the test case. do_test $testname.$n.1 { - set ::sqlite_io_error_pending 0 - catch {db close} - catch {db2 close} - catch {forcedelete test.db} - catch {forcedelete test.db-journal} - catch {forcedelete test2.db} - catch {forcedelete test2.db-journal} - set ::DB [sqlite3 db test.db; sqlite3_connection_pointer db] - sqlite3_extended_result_codes $::DB $::ioerropts(-erc) - if {[info exists ::ioerropts(-tclprep)]} { - eval $::ioerropts(-tclprep) - } - if {[info exists ::ioerropts(-sqlprep)]} { - execsql $::ioerropts(-sqlprep) - } - expr 0 + run_ioerr_prep } {0} # Read the 'checksum' of the database. if {$::ioerropts(-cksum)} { - set checksum [cksum] + set ::checksum [cksum] } # Set the Nth IO error to fail. @@ -1198,20 +1218,10 @@ proc do_ioerr_test {testname args} { set ::sqlite_io_error_persist $::ioerropts(-persist) set ::sqlite_io_error_pending $n }] $n - - # Create a single TCL script from the TCL and SQL specified - # as the body of the test. - set ::ioerrorbody {} - if {[info exists ::ioerropts(-tclbody)]} { - append ::ioerrorbody "$::ioerropts(-tclbody)\n" - } - if {[info exists ::ioerropts(-sqlbody)]} { - append ::ioerrorbody "db eval {$::ioerropts(-sqlbody)}" - } - # Execute the TCL Script created in the above block. If - # there are at least N IO operations performed by SQLite as - # a result of the script, the Nth will fail. + # Execute the TCL script created for the body of this test. If + # at least N IO operations performed by SQLite as a result of + # the script, the Nth will fail. do_test $testname.$n.3 { set ::sqlite_io_error_hit 0 set ::sqlite_io_error_hardhit 0 @@ -1315,8 +1325,15 @@ proc do_ioerr_test {testname args} { catch {db close} catch {db2 close} set ::DB [sqlite3 db test.db; sqlite3_connection_pointer db] - cksum - } $checksum + set nowcksum [cksum] + set res [expr {$nowcksum==$::checksum || $nowcksum==$::goodcksum}] + if {$res==0} { + puts "now=$nowcksum" + puts "the=$::checksum" + puts "fwd=$::goodcksum" + } + set res + } 1 } set ::sqlite_io_error_hardhit 0 From 22d27300476e8e14ef35e0935eae4333eb259e01 Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 23 Feb 2013 19:11:47 +0000 Subject: [PATCH 06/10] Fix a cut-and-paste bug causing the library to fail to report database corruption in a few cases. FossilOrigin-Name: f921df59560d536f5b80eef8c995cbe3ff591bae --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/btree.c | 1 - 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 9a1539d2ca..4bdfea20f9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhancements\sto\stest\sscripts.\sNo\scode\schanges. -D 2013-02-23T18:58:11.423 +C Fix\sa\scut-and-paste\sbug\scausing\sthe\slibrary\sto\sfail\sto\sreport\sdatabase\scorruption\sin\sa\sfew\scases. +D 2013-02-23T19:11:47.930 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in a48faa9e7dd7d556d84f5456eabe5825dd8a6282 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -121,7 +121,7 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c 0b8d2108a10ada00e642525921960b0c27451955 F src/bitvec.c 26675fe8e431dc555e6f2d0e11e651d172234aa1 F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 -F src/btree.c bcd64dff70af19e3a166853b7b728887cd4cc975 +F src/btree.c 02ab112a16517321d64660e84e0ccc06ef5f43c7 F src/btree.h 3ad7964d6c5b1c7bff569aab6adfa075f8bf06cd F src/btreeInt.h eecc84f02375b2bb7a44abbcbbe3747dde73edb2 F src/build.c 73ca65f32938e4e0d94e831b61b5749b211b79be @@ -1034,7 +1034,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P 66f9faa9a969d004486ee38d492fb3eda6cdebab -R 87b39f8ba9e2866ed1adab1a9b990f83 +P ccab94c10d54e585de918bbf82dec188287d93b2 +R e25f1782ace53b239780abd0cb855692 U dan -Z c23ef7906674057cc290bb43146b99c4 +Z 0e49116a8cea889274c349c3b9506a7e diff --git a/manifest.uuid b/manifest.uuid index 265b085615..f96d46f468 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ccab94c10d54e585de918bbf82dec188287d93b2 \ No newline at end of file +f921df59560d536f5b80eef8c995cbe3ff591bae \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index b46b32ffca..5952aa3a55 100644 --- a/src/btree.c +++ b/src/btree.c @@ -3041,7 +3041,6 @@ static Pgno finalDbSize(BtShared *pBt, Pgno nOrig, Pgno nFree){ while( PTRMAP_ISPAGE(pBt, nFin) || nFin==PENDING_BYTE_PAGE(pBt) ){ nFin--; } - if( nFin>nOrig ) return SQLITE_CORRUPT_BKPT; return nFin; } From e0b605917e23a5106f7000e9d3e3786cf700787a Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 23 Feb 2013 19:43:47 +0000 Subject: [PATCH 07/10] Fix a case in the incremental vacuum code where database corruption was going unreported. FossilOrigin-Name: 4cd30c72629a7f44b18026a70103aa0bb8a3b959 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/btree.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 4bdfea20f9..034f22ed52 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\scut-and-paste\sbug\scausing\sthe\slibrary\sto\sfail\sto\sreport\sdatabase\scorruption\sin\sa\sfew\scases. -D 2013-02-23T19:11:47.930 +C Fix\sa\scase\sin\sthe\sincremental\svacuum\scode\swhere\sdatabase\scorruption\swas\sgoing\sunreported. +D 2013-02-23T19:43:47.508 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in a48faa9e7dd7d556d84f5456eabe5825dd8a6282 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -121,7 +121,7 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c 0b8d2108a10ada00e642525921960b0c27451955 F src/bitvec.c 26675fe8e431dc555e6f2d0e11e651d172234aa1 F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 -F src/btree.c 02ab112a16517321d64660e84e0ccc06ef5f43c7 +F src/btree.c b84e2ac3b4ed5a4eb1b186c9c37eef53b635bc7f F src/btree.h 3ad7964d6c5b1c7bff569aab6adfa075f8bf06cd F src/btreeInt.h eecc84f02375b2bb7a44abbcbbe3747dde73edb2 F src/build.c 73ca65f32938e4e0d94e831b61b5749b211b79be @@ -1034,7 +1034,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P ccab94c10d54e585de918bbf82dec188287d93b2 -R e25f1782ace53b239780abd0cb855692 +P f921df59560d536f5b80eef8c995cbe3ff591bae +R 1c3862ad49b71ee257cac1e86a276cf3 U dan -Z 0e49116a8cea889274c349c3b9506a7e +Z 0b46646dde77425bfb67d915fec16418 diff --git a/manifest.uuid b/manifest.uuid index f96d46f468..78f73b491f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f921df59560d536f5b80eef8c995cbe3ff591bae \ No newline at end of file +4cd30c72629a7f44b18026a70103aa0bb8a3b959 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 5952aa3a55..6c6d0b953b 100644 --- a/src/btree.c +++ b/src/btree.c @@ -3066,7 +3066,7 @@ int sqlite3BtreeIncrVacuum(Btree *p){ Pgno nFree = get4byte(&pBt->pPage1->aData[36]); Pgno nFin = finalDbSize(pBt, nOrig, nFree); - if( nFin0 ){ invalidateAllOverflowCache(pBt); rc = incrVacuumStep(pBt, nFin, nOrig, 0); if( rc==SQLITE_OK ){ From 9138471141dc1bd40db0430d17a612bfb5759a95 Mon Sep 17 00:00:00 2001 From: dan Date: Sun, 24 Feb 2013 11:50:43 +0000 Subject: [PATCH 08/10] Fix a case where database corruption may cause an assert() to fail. FossilOrigin-Name: ba33bb059ed4f4547da2880dbc8bd827c06fae34 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/btree.c | 4 +++- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 034f22ed52..04965dd758 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\scase\sin\sthe\sincremental\svacuum\scode\swhere\sdatabase\scorruption\swas\sgoing\sunreported. -D 2013-02-23T19:43:47.508 +C Fix\sa\scase\swhere\sdatabase\scorruption\smay\scause\san\sassert()\sto\sfail. +D 2013-02-24T11:50:43.950 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in a48faa9e7dd7d556d84f5456eabe5825dd8a6282 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -121,7 +121,7 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c 0b8d2108a10ada00e642525921960b0c27451955 F src/bitvec.c 26675fe8e431dc555e6f2d0e11e651d172234aa1 F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 -F src/btree.c b84e2ac3b4ed5a4eb1b186c9c37eef53b635bc7f +F src/btree.c cbad71970cfadfa342fc137ca5e319f98b2d0da1 F src/btree.h 3ad7964d6c5b1c7bff569aab6adfa075f8bf06cd F src/btreeInt.h eecc84f02375b2bb7a44abbcbbe3747dde73edb2 F src/build.c 73ca65f32938e4e0d94e831b61b5749b211b79be @@ -1034,7 +1034,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P f921df59560d536f5b80eef8c995cbe3ff591bae -R 1c3862ad49b71ee257cac1e86a276cf3 +P 4cd30c72629a7f44b18026a70103aa0bb8a3b959 +R 4b714cf37fc577e9e0a95ce1f9383dd9 U dan -Z 0b46646dde77425bfb67d915fec16418 +Z 57f0815a503efb202bba1a714e0db419 diff --git a/manifest.uuid b/manifest.uuid index 78f73b491f..801adee734 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4cd30c72629a7f44b18026a70103aa0bb8a3b959 \ No newline at end of file +ba33bb059ed4f4547da2880dbc8bd827c06fae34 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 6c6d0b953b..84bafb9e73 100644 --- a/src/btree.c +++ b/src/btree.c @@ -3066,7 +3066,9 @@ int sqlite3BtreeIncrVacuum(Btree *p){ Pgno nFree = get4byte(&pBt->pPage1->aData[36]); Pgno nFin = finalDbSize(pBt, nOrig, nFree); - if( nFree>0 ){ + if( nOrig0 ){ invalidateAllOverflowCache(pBt); rc = incrVacuumStep(pBt, nFin, nOrig, 0); if( rc==SQLITE_OK ){ From 896f99e942225edaf1fc40a0d04beace6f1bb835 Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 25 Feb 2013 07:12:40 +0000 Subject: [PATCH 09/10] Catch a dropped error code in backup.c. FossilOrigin-Name: ac8ca3ecee4d81bf522b330033e5d85638063670 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/backup.c | 4 +++- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 04965dd758..cf75f0f4f9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\scase\swhere\sdatabase\scorruption\smay\scause\san\sassert()\sto\sfail. -D 2013-02-24T11:50:43.950 +C Catch\sa\sdropped\serror\scode\sin\sbackup.c. +D 2013-02-25T07:12:40.512 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in a48faa9e7dd7d556d84f5456eabe5825dd8a6282 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -118,7 +118,7 @@ F src/alter.c f8db986c03eb0bfb221523fc9bbb9d0b70de3168 F src/analyze.c 7553068d21e32a57fc33ab6b2393fc8c1ba41410 F src/attach.c ea5247f240e2c08afd608e9beb380814b86655e1 F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 -F src/backup.c 0b8d2108a10ada00e642525921960b0c27451955 +F src/backup.c b2cac9f7993f3f9588827b824b1501d0c820fa68 F src/bitvec.c 26675fe8e431dc555e6f2d0e11e651d172234aa1 F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 F src/btree.c cbad71970cfadfa342fc137ca5e319f98b2d0da1 @@ -1034,7 +1034,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P 4cd30c72629a7f44b18026a70103aa0bb8a3b959 -R 4b714cf37fc577e9e0a95ce1f9383dd9 +P ba33bb059ed4f4547da2880dbc8bd827c06fae34 +R 2d999113323b8a278783fe6edad2f381 U dan -Z 57f0815a503efb202bba1a714e0db419 +Z 36585c74ecb2f209e8dc6af8304c9567 diff --git a/manifest.uuid b/manifest.uuid index 801adee734..1e72101c48 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ba33bb059ed4f4547da2880dbc8bd827c06fae34 \ No newline at end of file +ac8ca3ecee4d81bf522b330033e5d85638063670 \ No newline at end of file diff --git a/src/backup.c b/src/backup.c index 89e0f00e66..71a8a1a3e7 100644 --- a/src/backup.c +++ b/src/backup.c @@ -504,7 +504,9 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){ } } } - rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 1); + if( rc==SQLITE_OK ){ + rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 1); + } /* Write the extra pages and truncate the database file as required */ iEnd = MIN(PENDING_BYTE + pgszDest, iSize); From 295fc442b50042644870cfd41d99619512eb2172 Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 25 Feb 2013 12:06:55 +0000 Subject: [PATCH 10/10] Add test file incrvacuum3.test. No code changes. FossilOrigin-Name: bf57534188e044fb341315bfc05b7927e66a04e0 --- manifest | 11 ++-- manifest.uuid | 2 +- test/incrvacuum3.test | 137 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 144 insertions(+), 6 deletions(-) create mode 100644 test/incrvacuum3.test diff --git a/manifest b/manifest index cf75f0f4f9..f11324d902 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Catch\sa\sdropped\serror\scode\sin\sbackup.c. -D 2013-02-25T07:12:40.512 +C Add\stest\sfile\sincrvacuum3.test.\sNo\scode\schanges. +D 2013-02-25T12:06:55.032 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in a48faa9e7dd7d556d84f5456eabe5825dd8a6282 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -534,6 +534,7 @@ F test/incrblob_err.test d2562d2771ebffd4b3af89ef64c140dd44371597 F test/incrblobfault.test 917c0292224c64a56ef7215fd633a3a82f805be0 F test/incrvacuum.test d2a6ddf5e429720b5fe502766af747915ccf6c32 F test/incrvacuum2.test 379eeb8740b0ef60c372c439ad4cbea20b34bb9b +F test/incrvacuum3.test 1159ec2b3e7bafbde5718867bc7328ba58863313 F test/incrvacuum_ioerr.test 293f2714571255539c8c789da2f7de4ec3f7101e F test/index.test b5429732b3b983fa810e3ac867d7ca85dae35097 F test/index2.test ee83c6b5e3173a3d7137140d945d9a5d4fdfb9d6 @@ -1034,7 +1035,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P ba33bb059ed4f4547da2880dbc8bd827c06fae34 -R 2d999113323b8a278783fe6edad2f381 +P ac8ca3ecee4d81bf522b330033e5d85638063670 +R 4eb400824b32ad5749b8b0c556f7d2a9 U dan -Z 36585c74ecb2f209e8dc6af8304c9567 +Z 4b0cde4b14de44a514d78f31b4dd5809 diff --git a/manifest.uuid b/manifest.uuid index 1e72101c48..3341d99e0a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ac8ca3ecee4d81bf522b330033e5d85638063670 \ No newline at end of file +bf57534188e044fb341315bfc05b7927e66a04e0 \ No newline at end of file diff --git a/test/incrvacuum3.test b/test/incrvacuum3.test new file mode 100644 index 0000000000..ed2d47139e --- /dev/null +++ b/test/incrvacuum3.test @@ -0,0 +1,137 @@ +# 2013 Feb 25 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# This file implements regression tests for the SQLite library, focusing +# on the incremental vacuum feature. +# +# The tests in this file were added at the same time as optimizations +# were made to: +# +# * Truncate the database after a rollback mode commit, and +# +# * Avoid moving pages to locations from which they may need to be moved +# a second time if an incremental-vacuum proccess is allowed to vacuum +# the entire database. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix incrvacuum3 + +# If this build of the library does not support auto-vacuum, omit this +# whole file. +ifcapable {!autovacuum || !pragma} { + finish_test + return +} + +proc check_on_disk {} { + + # Copy the files for database "test.db" to "test2.db". + forcedelete test2.db test2.db-journal test2.db-wal + forcecopy test.db test2.db + if {[file exists test.db-journal]} { + forcecopy test.db-journal test2.db-journal + } + if {[file exists test.db-wal]} { + forcecopy test.db-wal test2.db-wal + } + + # Open "test2.db" and check it is Ok. + sqlite3 dbcheck test2.db + set ret [dbcheck eval { PRAGMA integrity_check }] + dbcheck close + set ret +} + +# Run these tests once in rollback journal mode, and once in wal mode. +# +foreach {T jrnl_mode} { + 1 delete + 2 wal +} { + catch { db close } + forcedelete test.db test.db-journal test.db-wal + sqlite3 db test.db + db eval { + PRAGMA cache_size = 5; + PRAGMA page_size = 1024; + PRAGMA auto_vacuum = 2; + } + db eval "PRAGMA journal_mode = $jrnl_mode" + + foreach {tn sql} { + 1 { + CREATE TABLE t1(x UNIQUE); + INSERT INTO t1 VALUES(randomblob(400)); + INSERT INTO t1 VALUES(randomblob(400)); + INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 4 + INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 8 + INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 16 + INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 32 + INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 64 + INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 128 + INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 256 + } + + 2 { + DELETE FROM t1 WHERE rowid%8; + } + + 3 { + BEGIN; + PRAGMA incremental_vacuum = 100; + INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 64 + INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 128 + INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 256 + ROLLBACK; + } + + 4 { + BEGIN; + SAVEPOINT one; + PRAGMA incremental_vacuum = 100; + SAVEPOINT two; + INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 64 + INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 128 + INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 256 + } + + 5 { ROLLBACK to two } + + 6 { ROLLBACK to one } + + 7 { + INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 64 + PRAGMA incremental_vacuum = 1000; + INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 128 + INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 256 + ROLLBACK; + } + + 8 { + BEGIN; + INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 64 + PRAGMA incremental_vacuum = 1000; + INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 128 + COMMIT; + } + } { + do_execsql_test $T.1.$tn.1 $sql + do_execsql_test $T.1.$tn.2 {PRAGMA integrity_check} ok + do_test $T.1.$tn.3 { check_on_disk } ok + } + + do_execsql_test $T.1.x.1 { PRAGMA freelist_count } 0 + do_execsql_test $T.1.x.2 { SELECT count(*) FROM t1 } 128 +} + +finish_test +