]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Backport the SQLITE_PROTOCOL fix and the extra defensive measure to version
authordrh <drh@noemail.net>
Sun, 20 Feb 2011 03:11:27 +0000 (03:11 +0000)
committerdrh <drh@noemail.net>
Sun, 20 Feb 2011 03:11:27 +0000 (03:11 +0000)
3.7.4.

FossilOrigin-Name: bcc22c4b800e1f5b5619193890548d2a6bc19280

manifest
manifest.uuid
src/wal.c

index 6f9e0497037c87264d3cecd7299f20796dab01da..6e326189e4ed3d89b6c7b26657010dc9343a861e 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,8 +1,8 @@
 -----BEGIN PGP SIGNED MESSAGE-----
 Hash: SHA1
 
-C Version\s3.7.4\srelease\scandidate\s4
-D 2010-12-07T20:14:09
+C Backport\sthe\sSQLITE_PROTOCOL\sfix\sand\sthe\sextra\sdefensive\smeasure\sto\sversion\n3.7.4.
+D 2011-02-20T03:11:27.935
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 4547616ad2286053af6ccccefa242dc925e49bf0
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -240,7 +240,7 @@ F src/vdbeblob.c 18955f0ee6b133cd08e1592010cb9a6b11e9984c
 F src/vdbemem.c 411649a35686f54268ccabeda175322c4697f5a6
 F src/vdbetrace.c 864cef96919323482ebd9986f2132435115e9cc2
 F src/vtab.c b297e8fa656ab5e66244ab15680d68db0adbec30
-F src/wal.c f26b8d297bd11cb792e609917f9d4c6718ac8e0e
+F src/wal.c 20a07fb265abeae6d7a1908e9f7c50f2584a2dfa
 F src/wal.h c1aac6593a0b02b15dc625987e619edeab39292e
 F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
 F src/where.c fa22d45b2577c77146f2e894d58011d472d64103
@@ -897,14 +897,18 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P fe441df9ba447d97571e919099846efa3ec87427
-R 6bbeb99b0a61f7ea1af21c5b74072ff6
+P a586a4deeb25330037a49df295b36aaf624d0f45
+R d771e0380dc80bd4c14fcbb1ae00b759
+T *bgcolor * #ffd0c0
+T *branch * branch-3.7.4
+T *sym-branch-3.7.4 *
+T -sym-trunk *
 U drh
-Z 584aed3667b20c0c4d105810047e9fd4
+Z af96b97a7d73ec7f5853e8cfa091cc04
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.6 (GNU/Linux)
 
-iD8DBQFM/pWUoxKgR168RlERAuOQAJ9BLHxhysfzWC+psYkAVcf2xDsyTgCeIRqp
-FF5a9ESJ6yucR80Re9sEWmU=
-=ZPd3
+iD8DBQFNYIZkoxKgR168RlERAmtNAJwL9JL9iqNlElhdUnfzKoR8DfDpoACcD2V8
+Ukcg1He63egBJnFmVWmm6mY=
+=ngBz
 -----END PGP SIGNATURE-----
index 420ef50389d7babd536076eb4d3b070ae32a15b4..cf1815f9da06cce906a4ea336c4b483288e169ef 100644 (file)
@@ -1 +1 @@
-a586a4deeb25330037a49df295b36aaf624d0f45
\ No newline at end of file
+bcc22c4b800e1f5b5619193890548d2a6bc19280
\ No newline at end of file
index 3b217908b77335ffbdc8fd93e703d88dcad57f70..92d79513ddc6c0324b549094619fc493293fb130 100644 (file)
--- a/src/wal.c
+++ b/src/wal.c
@@ -1916,10 +1916,31 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
 
   assert( pWal->readLock<0 );     /* Not currently locked */
 
-  /* Take steps to avoid spinning forever if there is a protocol error. */
+  /* Take steps to avoid spinning forever if there is a protocol error.
+  **
+  ** Circumstances that cause a RETRY should only last for the briefest
+  ** instances of time.  No I/O or other system calls are done while the
+  ** locks are held, so the locks should not be held for very long. But 
+  ** if we are unlucky, another process that is holding a lock might get
+  ** paged out or take a page-fault that is time-consuming to resolve, 
+  ** during the few nanoseconds that it is holding the lock.  In that case,
+  ** it might take longer than normal for the lock to free.
+  **
+  ** After 5 RETRYs, we begin calling sqlite3OsSleep().  The first few
+  ** calls to sqlite3OsSleep() have a delay of 1 microsecond.  Really this
+  ** is more of a scheduler yield than an actual delay.  But on the 10th
+  ** an subsequent retries, the delays start becoming longer and longer, 
+  ** so that on the 100th (and last) RETRY we delay for 21 milliseconds.
+  ** The total delay time before giving up is less than 1 second.
+  */
   if( cnt>5 ){
-    if( cnt>100 ) return SQLITE_PROTOCOL;
-    sqlite3OsSleep(pWal->pVfs, 1);
+    int nDelay = 1;                      /* Pause time in microseconds */
+    if( cnt>100 ){
+      VVA_ONLY( pWal->lockError = 1; )
+      return SQLITE_PROTOCOL;
+    }
+    if( cnt>=10 ) nDelay = (cnt-9)*238;  /* Max delay 21ms. Total delay 996ms */
+    sqlite3OsSleep(pWal->pVfs, nDelay);
   }
 
   if( !useWal ){
@@ -2001,22 +2022,9 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
       mxI = i;
     }
   }
-  if( mxI==0 ){
-    /* If we get here, it means that all of the aReadMark[] entries between
-    ** 1 and WAL_NREADER-1 are zero.  Try to initialize aReadMark[1] to
-    ** be mxFrame, then retry.
-    */
-    rc = walLockExclusive(pWal, WAL_READ_LOCK(1), 1);
-    if( rc==SQLITE_OK ){
-      pInfo->aReadMark[1] = pWal->hdr.mxFrame;
-      walUnlockExclusive(pWal, WAL_READ_LOCK(1), 1);
-      rc = WAL_RETRY;
-    }else if( rc==SQLITE_BUSY ){
-      rc = WAL_RETRY;
-    }
-    return rc;
-  }else{
-    if( mxReadMark < pWal->hdr.mxFrame ){
+  /* There was once an "if" here. The extra "{" is to preserve indentation. */
+  {
+    if( mxReadMark < pWal->hdr.mxFrame || mxI==0 ){
       for(i=1; i<WAL_NREADER; i++){
         rc = walLockExclusive(pWal, WAL_READ_LOCK(i), 1);
         if( rc==SQLITE_OK ){
@@ -2029,6 +2037,10 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
         }
       }
     }
+    if( mxI==0 ){
+      assert( rc==SQLITE_BUSY );
+      return WAL_RETRY;
+    }
 
     rc = walLockShared(pWal, WAL_READ_LOCK(mxI));
     if( rc ){
@@ -2089,6 +2101,10 @@ int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
   do{
     rc = walTryBeginRead(pWal, pChanged, 0, ++cnt);
   }while( rc==WAL_RETRY );
+  testcase( (rc&0xff)==SQLITE_BUSY );
+  testcase( (rc&0xff)==SQLITE_IOERR );
+  testcase( rc==SQLITE_PROTOCOL );
+  testcase( rc==SQLITE_OK );
   return rc;
 }
 
@@ -2406,6 +2422,8 @@ static int walRestartLog(Wal *pWal){
     volatile WalCkptInfo *pInfo = walCkptInfo(pWal);
     assert( pInfo->nBackfill==pWal->hdr.mxFrame );
     if( pInfo->nBackfill>0 ){
+      u32 salt1;
+      sqlite3_randomness(4, &salt1);
       rc = walLockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1);
       if( rc==SQLITE_OK ){
         /* If all readers are using WAL_READ_LOCK(0) (in other words if no
@@ -2423,7 +2441,7 @@ static int walRestartLog(Wal *pWal){
         pWal->nCkpt++;
         pWal->hdr.mxFrame = 0;
         sqlite3Put4byte((u8*)&aSalt[0], 1 + sqlite3Get4byte((u8*)&aSalt[0]));
-        sqlite3_randomness(4, &aSalt[1]);
+        aSalt[1] = salt1;
         walIndexWriteHdr(pWal);
         pInfo->nBackfill = 0;
         for(i=1; i<WAL_NREADER; i++) pInfo->aReadMark[i] = READMARK_NOT_USED;
@@ -2440,6 +2458,10 @@ static int walRestartLog(Wal *pWal){
       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;
 }