]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Make sure the wal-index reader detects an incorrect version number even if
authordrh <drh@noemail.net>
Thu, 24 Jun 2010 02:46:48 +0000 (02:46 +0000)
committerdrh <drh@noemail.net>
Thu, 24 Jun 2010 02:46:48 +0000 (02:46 +0000)
it had to hold a lock in order to read the wal-index.  Also, expand and enhance
various comments in wal.c.

FossilOrigin-Name: 2e6a462cebc05bfd4648d26dd5ae70b68844aa5f

manifest
manifest.uuid
src/wal.c

index 3396c68a2c16ba3536b74d6f78bb2ef723465b5e..53818fe472111bf5c3cd6b0d84bf3d7e6c81e6c0 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,8 +1,8 @@
 -----BEGIN PGP SIGNED MESSAGE-----
 Hash: SHA1
 
-C Fix\sand/or\simprove\scomments\sin\swal.c.\s\sNo\scode\schanges.
-D 2010-06-23T22:00:36
+C Make\ssure\sthe\swal-index\sreader\sdetects\san\sincorrect\sversion\snumber\seven\sif\nit\shad\sto\shold\sa\slock\sin\sorder\sto\sread\sthe\swal-index.\s\sAlso,\sexpand\sand\senhance\nvarious\scomments\sin\swal.c.
+D 2010-06-24T02:46:49
 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
 F Makefile.in a5cad1f8f3e021356bfcc6c77dc16f6f1952bbc3
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -229,7 +229,7 @@ F src/vdbeblob.c 258a6010ba7a82b72b327fb24c55790655689256
 F src/vdbemem.c 2a82f455f6ca6f78b59fb312f96054c04ae0ead1
 F src/vdbetrace.c 864cef96919323482ebd9986f2132435115e9cc2
 F src/vtab.c a0f8a40274e4261696ef57aa806de2776ab72cda
-F src/wal.c 51b5d2259d86a26125007d3d788da5a2a2715b1a
+F src/wal.c 40e6d0acde18a0d4796310db4d6382a12340388c
 F src/wal.h 4ace25262452d17e7d3ec970c89ee17794004008
 F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
 F src/where.c 1c895bef33d0dfc7ed90fb1f74120435d210ea56
@@ -828,14 +828,14 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P 3e9680c4c18140d083b24e05a21ea6792aef2487
-R 128d792d7f9b9a40582f4d46c120cca4
+P ee9991be082202c6637adb47affc777e7917be04
+R df56ab9f7222776abd3e8b42ef209701
 U drh
-Z 369983deae2c52862083f493477e4ceb
+Z 85f62e57e9c5554f99cfd3649411a9ff
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.6 (GNU/Linux)
 
-iD8DBQFMIoQHoxKgR168RlERAkTMAJ4y6IEC74XLF+DMxIuBS7Lmcv3IqQCeJXdd
-wPN5UVQx6y4hhnn2sGwnj/w=
-=O5UN
+iD8DBQFMIscdoxKgR168RlERAh1nAJ47gefagsKL4XohGBiiEgmsbUY6vgCfcfRz
+mTG8eTaypLtEv2BjR4hvPQw=
+=bshK
 -----END PGP SIGNATURE-----
index cd54b0bdbcbf90ca2e67f541af645266cc536fa2..008fb60dc4ed045aea27b1793ee86aa841b612f9 100644 (file)
@@ -1 +1 @@
-ee9991be082202c6637adb47affc777e7917be04
\ No newline at end of file
+2e6a462cebc05bfd4648d26dd5ae70b68844aa5f
\ No newline at end of file
index bbd2546eb551a61f2171613b98014675a0ccb933..3f976329f62f5b045cb1963b7b7a1974f410ff94 100644 (file)
--- a/src/wal.c
+++ b/src/wal.c
@@ -1663,26 +1663,20 @@ int walIndexTryHdr(Wal *pWal, int *pChanged){
 
 /*
 ** Read the wal-index header from the wal-index and into pWal->hdr.
-** If the wal-header appears to be corrupt, try to recover the log
-** before returning.
+** If the wal-header appears to be corrupt, try to reconstruct the
+** wal-index from the WAL before returning.
 **
 ** Set *pChanged to 1 if the wal-index header value in pWal->hdr is
 ** changed by this opertion.  If pWal->hdr is unchanged, set *pChanged
 ** to 0.
 **
-** This routine also maps the wal-index content into memory and assigns
-** ownership of that mapping to the current thread.  In some implementations,
-** only one thread at a time can hold a mapping of the wal-index.  Hence,
-** the caller should strive to invoke walIndexUnmap() as soon as possible
-** after this routine returns.
-**
 ** If the wal-index header is successfully read, return SQLITE_OK. 
 ** Otherwise an SQLite error code.
 */
 static int walIndexReadHdr(Wal *pWal, int *pChanged){
   int rc;                         /* Return code */
   int badHdr;                     /* True if a header read failed */
-  volatile u32 *page0;
+  volatile u32 *page0;            /* Chunk of wal-index containing header */
 
   /* Ensure that page 0 of the wal-index (the page that contains the 
   ** wal-index header) is mapped. Return early if an error occurs here.
@@ -1697,12 +1691,9 @@ static int walIndexReadHdr(Wal *pWal, int *pChanged){
   /* If the first page of the wal-index has been mapped, try to read the
   ** wal-index header immediately, without holding any lock. This usually
   ** works, but may fail if the wal-index header is corrupt or currently 
-  ** being modified by another user.
+  ** being modified by another thread or process.
   */
   badHdr = (page0 ? walIndexTryHdr(pWal, pChanged) : 1);
-  if( badHdr==0 && pWal->hdr.iVersion!=WALINDEX_MAX_VERSION ){
-    rc = SQLITE_CANTOPEN_BKPT;
-  }
 
   /* If the first attempt failed, it might have been due to a race
   ** with a writer.  So get a WRITE lock and try again.
@@ -1725,6 +1716,14 @@ static int walIndexReadHdr(Wal *pWal, int *pChanged){
     walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
   }
 
+  /* If the header is read successfully, check the version number to make
+  ** sure the wal-index was not constructed with some future format that
+  ** this version of SQLite cannot understand.
+  */
+  if( badHdr==0 && pWal->hdr.iVersion!=WALINDEX_MAX_VERSION ){
+    rc = SQLITE_CANTOPEN_BKPT;
+  }
+
   return rc;
 }
 
@@ -1739,10 +1738,30 @@ static int walIndexReadHdr(Wal *pWal, int *pChanged){
 ** other transient condition.  When that happens, it returns WAL_RETRY to
 ** indicate to the caller that it is safe to retry immediately.
 **
-** On success return SQLITE_OK.  On a permantent failure (such an
+** On success return SQLITE_OK.  On a permanent failure (such an
 ** I/O error or an SQLITE_BUSY because another process is running
 ** recovery) return a positive error code.
 **
+** The useWal parameter is true to force the use of the WAL and disable
+** the case where the WAL is bypassed because it has been completely
+** checkpointed.  If useWal==0 then this routine calls walIndexReadHdr() 
+** to make a copy of the wal-index header into pWal->hdr.  If the 
+** wal-index header has changed, *pChanged is set to 1 (as an indication 
+** to the caller that the local paget cache is obsolete and needs to be 
+** flushed.)  When useWal==1, the wal-index header is assumed to already
+** be loaded and the pChanged parameter is unused.
+**
+** The caller must set the cnt parameter to the number of prior calls to
+** this routine during the current read attempt that returned WAL_RETRY.
+** This routine will start taking more aggressive measures to clear the
+** race conditions after multiple WAL_RETRY returns, and after an excessive
+** number of errors will ultimately return SQLITE_PROTOCOL.  The
+** SQLITE_PROTOCOL return indicates that some other process has gone rogue
+** and is not honoring the locking protocol.  There is a vanishingly small
+** chance that SQLITE_PROTOCOL could be returned because of a run of really
+** bad luck when there is lots of contention for the wal-index, but that
+** possibility is so small that it can be safely neglected, we believe.
+**
 ** On success, this routine obtains a read lock on 
 ** WAL_READ_LOCK(pWal->readLock).  The pWal->readLock integer is
 ** in the range 0 <= pWal->readLock < WAL_NREADER.  If pWal->readLock==(-1)
@@ -1752,6 +1771,8 @@ static int walIndexReadHdr(Wal *pWal, int *pChanged){
 ** use WAL frames up to and including pWal->hdr.mxFrame if pWal->readLock>0
 ** Or if pWal->readLock==0, then the reader will ignore the WAL
 ** completely and get all content directly from the database file.
+** If the useWal parameter is 1 then the WAL will never be ignored and
+** this routine will always set pWal->readLock>0 on success.
 ** When the read transaction is completed, the caller must release the
 ** lock on WAL_READ_LOCK(pWal->readLock) and set pWal->readLock to -1.
 **
@@ -1796,9 +1817,9 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
         rc = SQLITE_BUSY_RECOVERY;
       }
     }
-  }
-  if( rc!=SQLITE_OK ){
-    return rc;
+    if( rc!=SQLITE_OK ){
+      return rc;
+    }
   }
 
   pInfo = walCkptInfo(pWal);
@@ -1974,9 +1995,9 @@ int sqlite3WalRead(
 
   /* If the "last page" field of the wal-index header snapshot is 0, then
   ** no data will be read from the wal under any circumstances. Return early
-  ** in this case to avoid the walIndexMap/Unmap overhead.  Likewise, if
-  ** pWal->readLock==0, then the WAL is ignored by the reader so
-  ** return early, as if the WAL were empty.
+  ** in this case as an optimization.  Likewise, if pWal->readLock==0, 
+  ** then the WAL is ignored by the reader so return early, as if the 
+  ** WAL were empty.
   */
   if( iLast==0 || pWal->readLock==0 ){
     *pInWal = 0;
@@ -1987,7 +2008,7 @@ int sqlite3WalRead(
   ** pgno. Each iteration of the following for() loop searches one
   ** hash table (each hash table indexes up to HASHTABLE_NPAGE frames).
   **
-  ** This code may run concurrently to the code in walIndexAppend()
+  ** This code might run concurrently to the code in walIndexAppend()
   ** that adds entries to the wal-index (and possibly to this hash 
   ** table). This means the value just read from the hash 
   ** slot (aHash[iKey]) may have been added before or after the