]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix a problem where an SQLITE_BUSY in the checkpoint code was being treated as an...
authordan <dan@noemail.net>
Fri, 4 Jun 2010 10:37:05 +0000 (10:37 +0000)
committerdan <dan@noemail.net>
Fri, 4 Jun 2010 10:37:05 +0000 (10:37 +0000)
FossilOrigin-Name: 02c4040ce2b4c970b3dee09f7c9ad5a2a3a9aa49

manifest
manifest.uuid
src/test_vfs.c
src/wal.c
test/wal3.test
test/walfault.test

index 1f70a29a674f30f469e0bbbdc4af83e7ab992eb6..564725623de39c1ccea6b1bfd43ceedfbffa3e63 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sanother\sproblem\sin\stest_vfs.c.
-D 2010-06-03T19:10:09
+C Fix\sa\sproblem\swhere\san\sSQLITE_BUSY\sin\sthe\scheckpoint\scode\swas\sbeing\streated\sas\san\sIO\serror\s(abandoning,\sinstead\sof\sjust\slimiting,\sthe\scheckpoint).
+D 2010-06-04T10:37:06
 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
 F Makefile.in a5cad1f8f3e021356bfcc6c77dc16f6f1952bbc3
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -207,7 +207,7 @@ F src/test_schema.c 8c06ef9ddb240c7a0fcd31bc221a6a2aade58bf0
 F src/test_server.c bbba05c144b5fc4b52ff650a4328027b3fa5fcc6
 F src/test_tclvar.c f4dc67d5f780707210d6bb0eb6016a431c04c7fa
 F src/test_thread.c aa9919c885a1fe53eafc73492f0898ee6c0a0726
-F src/test_vfs.c 0f0242f29584537845cf0e0dfc04ece0b357b857
+F src/test_vfs.c 6203bc7d88a95a093ceb2c372252317b3154b315
 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
 F src/tokenize.c 25ceb0f0a746ea1d0f9553787f3f0a56853cfaeb
 F src/trigger.c 8927588cb9e6d47f933b53bfe74200fbb504100d
@@ -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 be73c9a8a3027a7bba1229dc09890927b992da45
+F src/wal.c 453811af926fe12eacea41b4ea02ee1a2d2f004b
 F src/wal.h 4ace25262452d17e7d3ec970c89ee17794004008
 F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
 F src/where.c 75fee9e255b62f773fcadd1d1f25b6f63ac7a356
@@ -763,13 +763,13 @@ F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8
 F test/vtab_shared.test 0eff9ce4f19facbe0a3e693f6c14b80711a4222d
 F test/wal.test bfec61450b47cdf09f7d2269f9e9967683b8b0fc
 F test/wal2.test 1dcbbe59ab662bebb859bb1ede83143f8a39814e
-F test/wal3.test cac89168c8f8a8679f1fb5234624d5699a84b2f0
+F test/wal3.test 535867201f4e5eccc459dbfdbb43e1b9555fd30a
 F test/wal_common.tcl 3e953ae60919281688ea73e4d0aa0e1bc94becd9
 F test/walbak.test e7650a26eb4b8abeca9b145b1af1e63026dde432
 F test/walcksum.test 4efa8fb88c32bed8288ea4385a9cc113a5c8f0bf
 F test/walcrash.test f6d5fb2bb108876f04848720a488065d9deef69f
 F test/walcrash2.test 14585ad1a2c85da2de721caa3b4deeea55213008
-F test/walfault.test 0cd672eb059d98ef07714f64371fd7d4d1ebb642
+F test/walfault.test 4c412eae947aea5f58d5c616a4d8740f034e49d1
 F test/walhook.test 67e675127f4acb72f061a12667ce6e5460b06b78
 F test/walmode.test 6ca9d710cc9f6545b913abcded6d6b0b15641048
 F test/walslow.test d21625e2e99e11c032ce949e8a94661576548933
@@ -817,7 +817,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P fcbf7cf189506e43fc2f0820aedffb195038d3a9
-R e093d2af0534cd33e5ed13655be56b08
+P df7d59899ceb2743764b0433cb68f4bc33f16344
+R 1a3cb251079fbc88fab0e8991c692f47
 U dan
-Z e9eec85577950a5d26e2b23744407a2d
+Z 13abdffaf01f3e682d39faa8c6e78666
index 43d840249cf8d4b4236adbe50cd576a7cbe55ac9..d2362e35a0e06272e4e3d51c0c07d2d3ec7a6613 100644 (file)
@@ -1 +1 @@
-df7d59899ceb2743764b0433cb68f4bc33f16344
\ No newline at end of file
+02c4040ce2b4c970b3dee09f7c9ad5a2a3a9aa49
\ No newline at end of file
index 1beeef47c87c2d726bde7147c70aae7b5148165e..05fa0096a569759ea30946a90b92c717e531c4c8 100644 (file)
@@ -596,7 +596,8 @@ static int tvfsShmGet(
 
   if( p->pScript && p->mask&TESTVFS_SHMGET_MASK ){
     tvfsExecTcl(p, "xShmGet", 
-        Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0
+        Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 
+        Tcl_NewIntObj(reqMapSize)
     );
     tvfsResultCode(p, &rc);
   }
index 25175d966a9334b182e878375cdca928c45e449d..5399dfda95db24c0149a80f311f71926c07b7595 100644 (file)
--- a/src/wal.c
+++ b/src/wal.c
@@ -1299,14 +1299,10 @@ static int walIteratorInit(Wal *pWal, WalIterator **pp){
   int i;                /* Iterator variable */
   int nFinal;           /* Number of unindexed entries */
   u8 *aTmp;             /* Temp space used by merge-sort */
-  int rc;               /* Return code of walIndexMap() */
   u8 *aSpace;           /* Surplus space on the end of the allocation */
 
   /* Make sure the wal-index is mapped into local memory */
-  rc = walIndexMap(pWal, walMappingSize(pWal->hdr.mxFrame));
-  if( rc!=SQLITE_OK ){
-    return rc;
-  }
+  assert( pWal->pWiData && pWal->szWIndex>=walMappingSize(pWal->hdr.mxFrame) );
 
   /* This routine only runs while holding SQLITE_SHM_CHECKPOINT.  No other
   ** thread is able to write to shared memory while this routine is
@@ -1360,7 +1356,6 @@ static void walIteratorFree(WalIterator *p){
   sqlite3_free(p);
 }
 
-
 /*
 ** Copy as much content as we can from the WAL back into the database file
 ** in response to an sqlite3_wal_checkpoint() request or the equivalent.
@@ -1411,14 +1406,13 @@ static int walCheckpoint(
   /* Allocate the iterator */
   rc = walIteratorInit(pWal, &pIter);
   if( rc!=SQLITE_OK || pWal->hdr.mxFrame==0 ){
-    walIteratorFree(pIter);
-    return rc;
+    goto walcheckpoint_out;
   }
 
   /*** TODO:  Move this test out to the caller.  Make it an assert() here ***/
   if( pWal->hdr.szPage!=nBuf ){
-    walIteratorFree(pIter);
-    return SQLITE_CORRUPT_BKPT;
+    rc = SQLITE_CORRUPT_BKPT;
+    goto walcheckpoint_out;
   }
 
   /* Compute in mxSafeFrame the index of the last frame of the WAL that is
@@ -1432,17 +1426,16 @@ static int walCheckpoint(
   assert( pInfo==walCkptInfo(pWal) );
   for(i=1; i<WAL_NREADER; i++){
     u32 y = pInfo->aReadMark[i];
-    if( y>0 && (mxSafeFrame==0 || mxSafeFrame>=y) ){
-      if( y<=pWal->hdr.mxFrame
-       && walLockExclusive(pWal, WAL_READ_LOCK(i), 1)==SQLITE_OK
-      ){
+    if( y>0 && mxSafeFrame>=y ){
+      assert( y<=pWal->hdr.mxFrame );
+      rc = walLockExclusive(pWal, WAL_READ_LOCK(i), 1);
+      if( rc==SQLITE_OK ){
         pInfo->aReadMark[i] = 0;
         walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
       }else if( rc==SQLITE_BUSY ){
         mxSafeFrame = y-1;
       }else{
-        walIteratorFree(pIter);
-        return rc;
+        goto walcheckpoint_out;
       }
     }
   }
@@ -1488,6 +1481,7 @@ static int walCheckpoint(
     rc = SQLITE_OK;
   }
 
+ walcheckpoint_out:
   walIteratorFree(pIter);
   return rc;
 }
index 2d2d8b39cb5d485197983c1658e92296c618de00..3ddfeaea6afb34597f2e5e22711a01d06622b21b 100644 (file)
@@ -109,5 +109,88 @@ for {set i 1} {$i < 20} {incr i} {
   db2 close
 }
 
+db close
+foreach code [list {
+  proc code2 {tcl} { uplevel #0 $tcl }
+  proc code3 {tcl} { uplevel #0 $tcl }
+  set tn singleproc
+} {
+  set ::code2_chan [launch_testfixture]
+  set ::code3_chan [launch_testfixture]
+  proc code2 {tcl} { testfixture $::code2_chan $tcl }
+  proc code3 {tcl} { testfixture $::code3_chan $tcl }
+  set tn multiproc
+}] {
+  file delete -force test.db test.db-wal test.db-journal
+  sqlite3 db test.db
+  eval $code
+
+  # Open connections [db2] and [db3]. Depending on which iteration this
+  # is, the connections may be created in this interpreter, or in 
+  # interpreters running in other OS processes. As such, the [db2] and [db3]
+  # commands should only be accessed within [code2] and [code3] blocks,
+  # respectively.
+  #
+  code2 { sqlite3 db2 test.db ; db2 eval { PRAGMA journal_mode = WAL } }
+  code3 { sqlite3 db3 test.db ; db3 eval { PRAGMA journal_mode = WAL } }
+
+  # Shorthand commands. Execute SQL using database connection [db], [db2] 
+  # or [db3]. Return the results.
+  #
+  proc sql  {sql} { db eval $sql }
+  proc sql2 {sql} { code2 [list db2 eval $sql] }
+  proc sql3 {sql} { code3 [list db3 eval $sql] }
+
+  do_test wal3-2.$tn.1 {
+    sql { 
+      PRAGMA page_size = 1024;
+      PRAGMA auto_vacuum = OFF; 
+      PRAGMA journal_mode = WAL;
+    }
+    sql {
+      CREATE TABLE t1(a, b);
+      INSERT INTO t1 VALUES(1, 'one');
+      BEGIN;
+        SELECT * FROM t1;
+    }
+  } {1 one}
+  do_test wal3-2.$tn.2 {
+    sql2 {
+      CREATE TABLE t2(a, b);
+      INSERT INTO t2 VALUES(2, 'two');
+      BEGIN;
+        SELECT * FROM t2;
+    }
+  } {2 two}
+  do_test wal3-2.$tn.3 {
+    sql3 {
+      CREATE TABLE t3(a, b);
+      INSERT INTO t3 VALUES(3, 'three');
+      BEGIN;
+        SELECT * FROM t3;
+    }
+  } {3 three}
+
+  # Try to checkpoint the database using [db]. It should be possible to
+  # checkpoint everything except the frames added by [db3] (checkpointing
+  # these frames would clobber the snapshot currently being used by [db2]).
+  #
+  do_test wal3-2.$tn.4 {
+    sql {
+      COMMIT;
+      PRAGMA wal_checkpoint;
+    }
+  } {}
+  do_test wal3-2.$tn.5 {
+    file size test.db
+  } [expr 3*1024]
+
+
+  catch { db close }
+  catch { code2 { db2 close } }
+  catch { code3 { db3 close } }
+  catch { close $::code2_chan }
+  catch { close $::code3_chan }
+}
 finish_test
 
index 28be17e52d29c00e321846ab1bc671ab722143d0..a0552021e18db85c7a6cfcfb715e3c77930f79b3 100644 (file)
@@ -16,6 +16,7 @@
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
 source $testdir/malloc_common.tcl
+source $testdir/lock_common.tcl
 
 ifcapable !wal {finish_test ; return }
 
@@ -321,82 +322,5 @@ do_faultsim_test walfault-9 -prep {
   if {$n != 1 && $n != 2} { error "Incorrect number of rows: $n" }
 }
 
-#-------------------------------------------------------------------------
-# When a database is checkpointed, SQLite does the following:
-#
-#   1. xShmLock(CHECKPOINT) to lock the WAL.
-#   2. xShmGet(-1) to get a mapping to read the wal-index header.
-#   3. If the mapping obtained in (2) is not large enough to cover the
-#      entire wal-index, call xShmGet(nReq) to get a larger mapping.
-#   4. Do the checkpoint.
-#   5. Release the lock and mapping.
-#
-# This test case tests the outcome of an IO error in step 2.
-#
-proc walfault_10_vfs_cb {method args} {
-  switch -- $::shm_state {
-    0 { return SQLITE_OK }
-    1 {
-      if {$method == "xShmGet"} {
-        set ::wal_index [tvfs shm [lindex $args 0]]
-        tvfs shm [lindex $args 0] [string range $::wal_index 0 65535]
-        set ::shm_state 2
-      }
-    }
-    2 {
-      if {$method == "xShmGet"} {
-        tvfs shm [lindex $args 0] $::wal_index
-        return SQLITE_IOERR
-      }
-    }
-  }
-  return SQLITE_OK
-}
-do_test walfault-10.1 {
-  set ::shm_state 0
-  testvfs tvfs 
-  tvfs script walfault_10_vfs_cb
-
-  sqlite3 db  test.db -vfs tvfs
-  sqlite3 db2 test.db -vfs tvfs
-
-  execsql {
-    PRAGMA journal_mode = WAL;
-    PRAGMA wal_autocheckpoint = 0;
-    CREATE TABLE t1(x);
-    INSERT INTO t1 VALUES(randomblob(900));
-  }
-} {wal 0}
-do_test walfault-10.2 {
-  execsql {
-    PRAGMA wal_autocheckpoint = 0;
-    BEGIN;
-      INSERT INTO t1 SELECT randomblob(900) FROM t1;    /* 2 */
-      INSERT INTO t1 SELECT randomblob(900) FROM t1;    /* 4 */
-      INSERT INTO t1 SELECT randomblob(900) FROM t1;    /* 8 */
-      INSERT INTO t1 SELECT randomblob(900) FROM t1;    /* 16 */
-      INSERT INTO t1 SELECT randomblob(900) FROM t1;    /* 32 */
-      INSERT INTO t1 SELECT randomblob(900) FROM t1;    /* 64 */
-      INSERT INTO t1 SELECT randomblob(900) FROM t1;    /* 128 */
-      INSERT INTO t1 SELECT randomblob(900) FROM t1;    /* 256 */
-      INSERT INTO t1 SELECT randomblob(900) FROM t1;    /* 512 */
-      INSERT INTO t1 SELECT randomblob(900) FROM t1;    /* 1024 */
-      INSERT INTO t1 SELECT randomblob(900) FROM t1;    /* 2048 */
-      INSERT INTO t1 SELECT randomblob(900) FROM t1;    /* 4096 */
-      INSERT INTO t1 SELECT randomblob(900) FROM t1;    /* 8192 */
-      INSERT INTO t1 SELECT randomblob(900) FROM t1;    /* 16384 */
-    COMMIT;
-  } db2
-} {0}
-do_test walfault-10.3 {
-  set ::shm_state 1
-  catchsql { PRAGMA wal_checkpoint } db2
-} {1 {disk I/O error}}
-set ::shm_state 0
-db close
-db2 close
-tvfs delete
-unset -nocomplain ::wal_index ::shm_state
-
 finish_test