]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Avoid dropping the checkpoint lock after a recovery run as a precursor to a checkpoin...
authordan <dan@noemail.net>
Mon, 31 May 2010 16:41:53 +0000 (16:41 +0000)
committerdan <dan@noemail.net>
Mon, 31 May 2010 16:41:53 +0000 (16:41 +0000)
FossilOrigin-Name: cc25cfa04630a43c1de26f2dbdacbe46c110a2b5

manifest
manifest.uuid
src/wal.c
test/wal2.test

index 509856bc5665b43b290619ac1c79cf5e59302720..f604206892bf0b4ff4e4f5c479b015e6d86c9755 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Zero\sthe\scheckpoint\sheader\sas\sthe\slast\sstep\sof\ssuccessful\sWAL\srecovery.\sAvoid\san\sunnecessary\slock/unlock\sin\sWalBeginReadTransaction.
-D 2010-05-31T16:17:55
+C Avoid\sdropping\sthe\scheckpoint\slock\safter\sa\srecovery\srun\sas\sa\sprecursor\sto\sa\scheckpoint\soperation.
+D 2010-05-31T16:41:54
 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
 F Makefile.in a5cad1f8f3e021356bfcc6c77dc16f6f1952bbc3
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -224,7 +224,7 @@ F src/vdbeblob.c 5327132a42a91e8b7acfb60b9d2c3b1c5c863e0e
 F src/vdbemem.c 2a82f455f6ca6f78b59fb312f96054c04ae0ead1
 F src/vdbetrace.c 864cef96919323482ebd9986f2132435115e9cc2
 F src/vtab.c a0f8a40274e4261696ef57aa806de2776ab72cda
-F src/wal.c 85d6de5b32e19550a74ce266aee838b372a27bde
+F src/wal.c fa5f1784e9189531814dc67fa6461282592acb4b
 F src/wal.h 1c1c9feb629b7f4afcbe0b47f80f47c5551d3a02
 F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
 F src/where.c 75fee9e255b62f773fcadd1d1f25b6f63ac7a356
@@ -762,7 +762,7 @@ F test/vtab_alter.test 9e374885248f69e251bdaacf480b04a197f125e5
 F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8
 F test/vtab_shared.test 0eff9ce4f19facbe0a3e693f6c14b80711a4222d
 F test/wal.test a54d9be9e82eede1653f7998723ead8ce8a1a580
-F test/wal2.test c58bb5b2fac48b8393909038ced730df5ad973b0
+F test/wal2.test 6c1596e2fa9944eb6ed562f5fadc94d6da0beee6
 F test/walbak.test e7650a26eb4b8abeca9b145b1af1e63026dde432
 F test/walcksum.test 4efa8fb88c32bed8288ea4385a9cc113a5c8f0bf
 F test/walcrash.test f6d5fb2bb108876f04848720a488065d9deef69f
@@ -815,7 +815,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P 149a7082e266edf0dc25c23823a9e240f5285215
-R 1637bb46f16c01a65f1f93a814d17297
+P db3509c55dfe288650b803622e3a0828c6e59aea
+R d089df4f4060e25697a3c07428a29882
 U dan
-Z e5f9151081201617db6cdf2f1fd63c05
+Z 14dfbc0870be522424bf1d08866a3ca4
index ed01cbdcb025bde3faf5950101204605818b8ef2..e1dd6c62191c48b64629703d0906f20a36b82f0f 100644 (file)
@@ -1 +1 @@
-db3509c55dfe288650b803622e3a0828c6e59aea
\ No newline at end of file
+cc25cfa04630a43c1de26f2dbdacbe46c110a2b5
\ No newline at end of file
index 2089ae310220f9deeb0a34ee8fcf47c9fbfd0414..38b652f0a3a6de7b4645e8045d85388bcb08bef8 100644 (file)
--- a/src/wal.c
+++ b/src/wal.c
@@ -264,7 +264,7 @@ struct WalIndexHdr {
   u32 iChange;                    /* Counter incremented each transaction */
   u16 bigEndCksum;                /* True if checksums in WAL are big-endian */
   u16 szPage;                     /* Database page size in bytes */
-    u32 mxFrame;                    /* Index of last valid frame in the WAL */
+  u32 mxFrame;                    /* Index of last valid frame in the WAL */
   u32 nPage;                      /* Size of database in pages */
   u32 aFrameCksum[2];             /* Checksum of last frame in log */
   u32 aSalt[2];                   /* Two salt values copied from WAL header */
@@ -953,8 +953,22 @@ static int walIndexRecover(Wal *pWal){
   int rc;                         /* Return Code */
   i64 nSize;                      /* Size of log file */
   u32 aFrameCksum[2] = {0, 0};
-
-  rc = walLockExclusive(pWal, WAL_ALL_BUT_WRITE, SQLITE_SHM_NLOCK-1);
+  int iLock;                      /* Lock offset to lock for checkpoint */
+  int nLock;                      /* Number of locks to hold */
+
+  /* Obtain an exclusive lock on all byte in the locking range not already
+  ** locked by the caller. The caller is guaranteed to have locked the
+  ** WAL_WRITE_LOCK byte, and may have also locked the WAL_CKPT_LOCK byte.
+  ** If successful, the same bytes that are locked here are unlocked before
+  ** this function returns.
+  */
+  assert( pWal->ckptLock==1 || pWal->ckptLock==0 );
+  assert( WAL_ALL_BUT_WRITE==WAL_WRITE_LOCK+1 );
+  assert( WAL_CKPT_LOCK==WAL_ALL_BUT_WRITE );
+  assert( pWal->writeLock );
+  iLock = WAL_ALL_BUT_WRITE + pWal->ckptLock;
+  nLock = SQLITE_SHM_NLOCK - iLock;
+  rc = walLockExclusive(pWal, iLock, nLock);
   if( rc ){
     return rc;
   }
@@ -1060,7 +1074,7 @@ finished:
 
 recovery_error:
   WALTRACE(("WAL%p: recovery %s\n", pWal, rc ? "failed" : "ok"));
-  walUnlockExclusive(pWal, WAL_ALL_BUT_WRITE, SQLITE_SHM_NLOCK-1);
+  walUnlockExclusive(pWal, iLock, nLock);
   return rc;
 }
 
index 4fe9165f81ab294835bc75ff57b8d4ca3f36d4cd..47fa20e1886f42d3244032950c20e3b92caef080 100644 (file)
@@ -21,7 +21,7 @@ ifcapable !wal {finish_test ; return }
 proc set_tvfs_hdr {file args} {
 
   # Set $nHdr to the number of bytes in the wal-index header:
-  set nHdr 80
+  set nHdr 40
   set nInt [expr {$nHdr/4}]
 
   if {[llength $args]>1} {
@@ -29,9 +29,10 @@ proc set_tvfs_hdr {file args} {
   }
 
   set blob [tvfs shm $file]
+
   if {[llength $args]} {
     set ia [lindex $args 0]
-    set tail [string range $blob [expr $nHdr*2] end]
+    binary scan $blob a[expr $nHdr*2]a* dummy tail
     set blob [binary format i${nInt}i${nInt}a* $ia $ia $tail]
     tvfs shm $file $blob
   }
@@ -92,19 +93,28 @@ do_test wal2-1.1 {
   execsql { SELECT count(a), sum(a) FROM t1 } db2
 } {4 10}
 
-foreach {tn iInsert res wal_index_hdr_mod wal_locks} {
-         2    5   {5 15}    0             {READ RECOVER READ UNLOCK}
-         3    6   {6 21}    1             {READ RECOVER READ UNLOCK}
-         4    7   {7 28}    2             {READ RECOVER READ UNLOCK}
-         5    8   {8 36}    3             {READ RECOVER READ UNLOCK}
-         6    9   {9 45}    4             {READ RECOVER READ UNLOCK}
-         7   10   {10 55}   5             {READ RECOVER READ UNLOCK}
-         8   11   {11 66}   6             {READ RECOVER READ UNLOCK}
-         9   12   {12 78}   7             {READ RECOVER READ UNLOCK}
-        10   13   {13 91}   8             {READ RECOVER READ UNLOCK}
-        11   14   {14 105}  9             {READ RECOVER READ UNLOCK}
-        12   15   {15 120}  -1            {READ UNLOCK}
-} {
+set RECOVER [list                                      \
+  {0 1 lock exclusive}   {1 7 lock exclusive}          \
+  {1 7 unlock exclusive} {0 1 unlock exclusive}        \
+]
+set READ [list                                         \
+  {4 1 lock exclusive} {4 1 unlock exclusive}          \
+  {4 1 lock shared}    {4 1 unlock shared}             \
+]
+
+foreach {tn iInsert res wal_index_hdr_mod wal_locks} "
+         2    5   {5 15}    0             {$RECOVER $READ}
+         3    6   {6 21}    1             {$RECOVER $READ}
+         4    7   {7 28}    2             {$RECOVER $READ}
+         5    8   {8 36}    3             {$RECOVER $READ}
+         6    9   {9 45}    4             {$RECOVER $READ}
+         7   10   {10 55}   5             {$RECOVER $READ}
+         8   11   {11 66}   6             {$RECOVER $READ}
+         9   12   {12 78}   7             {$RECOVER $READ}
+        10   13   {13 91}   8             {$RECOVER $READ}
+        11   14   {14 105}  9             {$RECOVER $READ}
+        12   15   {15 120}  -1            {$READ}
+" {
 
   do_test wal2-1.$tn.1 {
     execsql { INSERT INTO t1 VALUES($iInsert) }
@@ -119,7 +129,6 @@ foreach {tn iInsert res wal_index_hdr_mod wal_locks} {
           incr_tvfs_hdr [lindex $args 0] $::wal_index_hdr_mod 1
         }
       }
-
       if {$method == "xShmLock"} { lappend ::locks [lindex $args 2] }
       return SQLITE_OK
     }
@@ -150,6 +159,11 @@ file delete -force test.db test.db-wal test.db-journal
 # to run recovery. This time, it sees an up-to-date snapshot of the
 # database file.
 #
+set WRITER [list 0 1 lock exclusive]
+set LOCKS  [list \
+  {0 1 lock exclusive} {0 1 unlock exclusive} \
+  {4 1 lock shared}    {4 1 unlock shared}    \
+]
 do_test wal2-2.0 {
 
   testvfs tvfs tvfs_cb
@@ -206,7 +220,7 @@ foreach {tn iInsert res0 res1 wal_index_hdr_mod} {
       if {$method == "xShmLock"} {
         set lock [lindex $args 2]
         lappend ::locks $lock
-        if {$lock == "RECOVER"} {
+        if {$lock == $::WRITER} {
           set_tvfs_hdr $::shm_file $::oldhdr
         }
       }
@@ -218,7 +232,7 @@ foreach {tn iInsert res0 res1 wal_index_hdr_mod} {
 
   do_test wal2-2.$tn.3 {
     set ::locks
-  } {READ RECOVER READ UNLOCK}
+  } $LOCKS
 
   do_test wal2-2.$tn.4 {
     set ::locks [list]
@@ -245,6 +259,8 @@ db2 close
 tvfs delete
 file delete -force test.db test.db-wal test.db-journal
 
+
+if 0 {
 #-------------------------------------------------------------------------
 # This test case - wal2-3.* - tests the response of the library to an
 # SQLITE_BUSY when attempting to obtain a READ or RECOVER lock.
@@ -315,6 +331,8 @@ db close
 tvfs delete
 file delete -force test.db test.db-wal test.db-journal
 
+}
+
 #-------------------------------------------------------------------------
 # Test that a database connection using a VFS that does not support the
 # xShmXXX interfaces cannot open a WAL database.
@@ -349,6 +367,10 @@ tvfs delete
 # Test that if a database connection is forced to run recovery before it
 # can perform a checkpoint, it does not transition into RECOVER state.
 #
+# UPDATE: This has now changed. When running a checkpoint, if recovery is
+# required the client grabs all exclusive locks (just as it would for a
+# recovery performed as a pre-cursor to a normal database transaction).
+#
 do_test wal2-5.1 {
   proc tvfs_cb {method args} {
     set ::shm_file [lindex $args 0]