]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix another problem involving unlocked transactions and wal-file restarts.
authordan <dan@noemail.net>
Mon, 24 Aug 2015 06:43:25 +0000 (06:43 +0000)
committerdan <dan@noemail.net>
Mon, 24 Aug 2015 06:43:25 +0000 (06:43 +0000)
FossilOrigin-Name: 4460764ea8fc948fe02f0a09476857839b3aa1ae

manifest
manifest.uuid
src/pager.c
src/wal.c
src/wal.h
test/unlocked3.test

index 1778b942535e1a9c730536948bfa6087d2428e62..1285f64e7633319e91b22de37f29c1bc90f283f4 100644 (file)
--- 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
index c18cc52736f4820f604f37d54a1bfc1373e0ad5d..75583c940a66bb8e89cbdd39a48ad22303e36f90 100644 (file)
@@ -1 +1 @@
-e3968b256282d8c0a87c26667b1ba02faf7a5a17
\ No newline at end of file
+4460764ea8fc948fe02f0a09476857839b3aa1ae
\ No newline at end of file
index c55db401508338fac3c64168c372f7e50d765bab..c2344e3747a53dc13312e96ba9d53cd007541451 100644 (file)
@@ -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);
   }
index fcf5a15044b58c214a1c3157f90c927df50735d6..d43f939f001dec4e28746a4489ed71bd22bedc64 100644 (file)
--- 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, &notUsed, 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, &notUsed, 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;
 }
index 0609eded27f22a94f76923177ee5d5fbefbd757e..35ffe4d38c79883f41161c0c834abd0f77eb76cf 100644 (file)
--- 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
index b4deaf9a92c65499627e3d3526626a047bdbaedc..9cde0788332b1e0370e05c20861616cb4982363b 100644 (file)
@@ -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 
   }
 }