From: dan Date: Mon, 24 Aug 2015 06:43:25 +0000 (+0000) Subject: Fix another problem involving unlocked transactions and wal-file restarts. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=654a96536703cbd0e49548f27c5aa6b8c3c80673;p=thirdparty%2Fsqlite.git Fix another problem involving unlocked transactions and wal-file restarts. FossilOrigin-Name: 4460764ea8fc948fe02f0a09476857839b3aa1ae --- diff --git a/manifest b/manifest index 1778b94253..1285f64e76 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sproblem\sto\sdo\swith\sdetecting\sunlocked\stransaction\sconflicts\sif\sanother\sclient\srestarts\sthe\swal\swhile\sthe\stransaction\sis\srunning. -D 2015-08-22T20:32:39.272 +C Fix\sanother\sproblem\sinvolving\sunlocked\stransactions\sand\swal-file\srestarts. +D 2015-08-24T06:43:25.273 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in e2218eb228374422969de7b1680eda6864affcef F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -324,7 +324,7 @@ F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa F src/os_unix.c 388c023582b17890f10c980b30ec1922b471753b F src/os_win.c 40b3af7a47eb1107d0d69e592bec345a3b7b798a F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca -F src/pager.c 951b7bae30fcbc2a2d380fa68f8bc68286ae0760 +F src/pager.c a952e4b4c2e85e1588df5972688de9b6c989dbdd F src/pager.h 1e7b0fc3846b71bd95b4b3300820d756895cb4ef F src/parse.y e9accdb2cb1795f75f478e7ce89e17b19d7d4da7 F src/pcache.c cde06aa50962595e412d497e22fd2e07878ba1f0 @@ -411,8 +411,8 @@ F src/vdbesort.c f5009e7a35e3065635d8918b9a31f498a499976b F src/vdbetrace.c 8befe829faff6d9e6f6e4dee5a7d3f85cc85f1a0 F src/vtab.c d31174e4c8f592febab3fa7f69e18320b4fd657a F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb -F src/wal.c 4c69d27ed7ec7006008d8309dc5c9ab742273c12 -F src/wal.h a701096b9bf5761b8c5f4b07082249e1950afc9a +F src/wal.c b8811f666d785820437d95386c12b85951418c50 +F src/wal.h 903ef67e17f8b466dc7cfc4186fc23e80be10ff8 F src/walker.c 2e14d17f592d176b6dc879c33fbdec4fbccaa2ba F src/where.c 66518a14a1238611aa0744d6980b6b7f544f4816 F src/whereInt.h 880a8599226ac1c00203490d934f3ed79b292572 @@ -1229,7 +1229,7 @@ F test/unique2.test 41e7f83c6827605991160a31380148a9fc5f1339 F test/unixexcl.test cd6c765f75e50e8e2c2ba763149e5d340ea19825 F test/unlocked.test d143a871bd874311d4e5c98ce458218ca6b579fd F test/unlocked2.test aaa42a08052a146466220b6c3a062ff3c4776ad6 -F test/unlocked3.test 06173e406a8c1a550448f79329ed4c3311905062 +F test/unlocked3.test 1bc4e3ad8693302639e50b4833a527807ee4863b F test/unordered.test ca7adce0419e4ca0c50f039885e76ed2c531eda8 F test/update.test 6c68446b8a0a33d522a7c72b320934596a2d7d32 F test/uri.test 23662b7b61958b0f0e47082de7d06341ccf85d5b @@ -1381,7 +1381,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 ed0a31be726e60115a5dd73d4ed580201b400ab7 -R 4d5e4d57de949c83b8660752ea3918ee +P e3968b256282d8c0a87c26667b1ba02faf7a5a17 +R 616e25ded22fb9d47c944cb40768f03a U dan -Z 75094882a86841f2760b97ee8543ae22 +Z 4efd00eba0478d425d47255076a7c364 diff --git a/manifest.uuid b/manifest.uuid index c18cc52736..75583c940a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e3968b256282d8c0a87c26667b1ba02faf7a5a17 \ No newline at end of file +4460764ea8fc948fe02f0a09476857839b3aa1ae \ No newline at end of file diff --git a/src/pager.c b/src/pager.c index c55db40150..c2344e3747 100644 --- a/src/pager.c +++ b/src/pager.c @@ -6129,8 +6129,10 @@ int sqlite3PagerUpgradeSnapshot(Pager *pPager, DbPage *pPage1){ u32 iFrame = 0; assert( pPager->pWal && pPager->pAllRead ); - sqlite3WalUpgradeSnapshot(pPager->pWal); - rc = sqlite3WalFindFrame(pPager->pWal, 1, &iFrame); + rc = sqlite3WalUpgradeSnapshot(pPager->pWal); + if( rc==SQLITE_OK ){ + rc = sqlite3WalFindFrame(pPager->pWal, 1, &iFrame); + } if( rc==SQLITE_OK ){ rc = readDbPage(pPage1, iFrame); } diff --git a/src/wal.c b/src/wal.c index fcf5a15044..d43f939f00 100644 --- a/src/wal.c +++ b/src/wal.c @@ -2667,9 +2667,44 @@ int sqlite3WalLockForCommit(Wal *pWal, PgHdr *pPage1, Bitvec *pAllRead){ return rc; } -void sqlite3WalUpgradeSnapshot(Wal *pWal){ +/* +** This function is called by a writer that has a read-lock on aReadmark[0] +** (pWal->readLock==0). This function relinquishes that lock and takes a +** lock on a different aReadmark[] slot. +** +** SQLITE_OK is returned if successful, or an SQLite error code otherwise. +*/ +static int walUpgradeReadlock(Wal *pWal){ + int cnt; + int rc; + assert( pWal->writeLock && pWal->readLock==0 ); + walUnlockShared(pWal, WAL_READ_LOCK(0)); + pWal->readLock = -1; + cnt = 0; + do{ + int notUsed; + rc = walTryBeginRead(pWal, ¬Used, 1, ++cnt); + }while( rc==WAL_RETRY ); + assert( (rc&0xff)!=SQLITE_BUSY ); /* BUSY not possible when useWal==1 */ + testcase( (rc&0xff)==SQLITE_IOERR ); + testcase( rc==SQLITE_PROTOCOL ); + testcase( rc==SQLITE_OK ); + return rc; +} + +int sqlite3WalUpgradeSnapshot(Wal *pWal){ + int rc = SQLITE_OK; assert( pWal->writeLock ); memcpy(&pWal->hdr, (void*)walIndexHdr(pWal), sizeof(WalIndexHdr)); + + /* If this client has its read-lock on slot aReadmark[0] and the entire + ** wal has not been checkpointed, switch it to a different slot. Otherwise + ** any reads performed between now and committing the transaction will + ** read from the old snapshot - not the one just upgraded to. */ + if( pWal->readLock==0 && pWal->hdr.mxFrame!=walCkptInfo(pWal)->nBackfill ){ + rc = walUpgradeReadlock(pWal); + } + return rc; } /* @@ -2789,7 +2824,6 @@ int sqlite3WalSavepointUndo(Wal *pWal, u32 *aWalData){ */ static int walRestartLog(Wal *pWal){ int rc = SQLITE_OK; - int cnt; if( pWal->readLock==0 ){ volatile WalCkptInfo *pInfo = walCkptInfo(pWal); @@ -2814,17 +2848,16 @@ static int walRestartLog(Wal *pWal){ return rc; } } - walUnlockShared(pWal, WAL_READ_LOCK(0)); - pWal->readLock = -1; - cnt = 0; - do{ - int notUsed; - rc = walTryBeginRead(pWal, ¬Used, 1, ++cnt); - }while( rc==WAL_RETRY ); - assert( (rc&0xff)!=SQLITE_BUSY ); /* BUSY not possible when useWal==1 */ - testcase( (rc&0xff)==SQLITE_IOERR ); - testcase( rc==SQLITE_PROTOCOL ); - testcase( rc==SQLITE_OK ); + + /* Regardless of whether or not the wal file was restarted, change the + ** read-lock held by this client to a slot other than aReadmark[0]. + ** Clients with a lock on aReadmark[0] read from the database file + ** only - never from the wal file. This means that if a writer holding + ** a lock on aReadmark[0] were to commit a transaction but not close the + ** read-transaction, subsequent read operations would read directly from + ** the database file - ignoring the new pages just appended + ** to the wal file. */ + rc = walUpgradeReadlock(pWal); } return rc; } diff --git a/src/wal.h b/src/wal.h index 0609eded27..35ffe4d38c 100644 --- a/src/wal.h +++ b/src/wal.h @@ -127,7 +127,7 @@ int sqlite3WalExclusiveMode(Wal *pWal, int op); int sqlite3WalHeapMemory(Wal *pWal); int sqlite3WalLockForCommit(Wal *pWal, PgHdr *pPg, Bitvec *pRead); -void sqlite3WalUpgradeSnapshot(Wal *pWal); +int sqlite3WalUpgradeSnapshot(Wal *pWal); #ifdef SQLITE_ENABLE_ZIPVFS /* If the WAL file is not empty, return the number of bytes of content diff --git a/test/unlocked3.test b/test/unlocked3.test index b4deaf9a92..9cde078833 100644 --- a/test/unlocked3.test +++ b/test/unlocked3.test @@ -94,9 +94,8 @@ foreach {tn oplist} { 6 {1iii 2iii 3iii 4iii} 7 {1di 2id 3iii 4ddd} 8 {1iii 2iii 3iii 4iii} - + 9 {1D 2II} } { - # 9 {1D 2II} if {[string range $oplist 0 0]=="-"} { reset_db create_schema @@ -119,7 +118,6 @@ foreach {tn oplist} { } {ok} foreach db $DBLIST { - if {$db=="db2"} breakpoint $db close } }