]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix a problem that occurs when one process causes the log-summary file to grow and...
authordan <dan@noemail.net>
Tue, 27 Apr 2010 05:42:32 +0000 (05:42 +0000)
committerdan <dan@noemail.net>
Tue, 27 Apr 2010 05:42:32 +0000 (05:42 +0000)
FossilOrigin-Name: b51a5f8bc660616aa264025dd7ad4bdab458814b

manifest
manifest.uuid
src/wal.c
test/lock2.test
test/lock_common.tcl
test/permutations.test
test/savepoint6.test
test/wal.test

index 74ed04bf37f093598c5bf9dc04b971879b14b548..d538e7c77be6af1f5dc799bab5fb71bfa7b178e7 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,8 +1,5 @@
------BEGIN PGP SIGNED MESSAGE-----
-Hash: SHA1
-
-C Merge\sin\srecent\schanges\sfrom\sthe\strunk
-D 2010-04-27T01:56:22
+C Fix\sa\sproblem\sthat\soccurs\swhen\sone\sprocess\scauses\sthe\slog-summary\sfile\sto\sgrow\sand\sthen\sa\ssecond\sprocess\sattempts\sto\sread\sthe\sdatabase.
+D 2010-04-27T05:42:32
 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
 F Makefile.in d83a0ffef3dcbfb08b410a6c6dd6c009ec9167fb
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -224,7 +221,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 ce03bdd759c7b949188c0b75c46777fe0f7f105e
+F src/wal.c 26d2a7028cc4af995e657431e2dbcea0aac63784
 F src/wal.h 812101dd76610401fbcd44114e7e8b7ce0224645
 F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
 F src/where.c faadd9c2bf08868e5135192b44e0d753e363a885
@@ -476,13 +473,13 @@ F test/limit.test 2db7b3b34fb925b8e847d583d2eb67531d0ce67e
 F test/loadext.test 0393ce12d9616aa87597dd0ec88181de181f6db0
 F test/loadext2.test 0bcaeb4d81cd5b6e883fdfea3c1bdbe1f173cbca
 F test/lock.test 842e80b6be816c79525a20b098cca066989feed7
-F test/lock2.test ec208a5f394d92affaf599fde3f374361657d0ff
+F test/lock2.test 64ba8f1c7709abf91287d564984a6b8c5209e755
 F test/lock3.test f271375930711ae044080f4fe6d6eda930870d00
 F test/lock4.test f4f36271aa5ae1da449646bf43c7341f6b2b4c4e
 F test/lock5.test 6b1f78f09ad1522843dad571b76b321e6f439bf7
 F test/lock6.test 862aa71e97b288d6b3f92ba3313f51bd0b003776
 F test/lock7.test 64006c84c1c616657e237c7ad6532b765611cf64
-F test/lock_common.tcl 58aa21f38c28223cc1107b5b2c9d7d61aa428e79
+F test/lock_common.tcl ebc5b9a238d6d9f08a8433e52bdbc67d1478e774
 F test/lookaside.test 1dd350dc6dff015c47c07fcc5a727a72fc5bae02
 F test/main.test 2be2352ac77ac5b238c6337a5469aeeef57677e6
 F test/make-where7.tcl 05c16b5d4f5d6512881dfec560cb793915932ef9
@@ -535,7 +532,7 @@ F test/pageropt.test 3ee6578891baaca967f0bd349e4abfa736229e1a
 F test/pagesize.test 76aa9f23ecb0741a4ed9d2e16c5fa82671f28efb
 F test/pcache.test eebc4420b37cb07733ae9b6e99c9da7c40dd6d58
 F test/pcache2.test 0d85f2ab6963aee28c671d4c71bec038c00a1d16
-F test/permutations.test 0730dc6c028b620a15c38a0a7d07238da088ecd3
+F test/permutations.test 894a6df3c4394194f84feea8520580dad1b71280
 F test/pragma.test 6960f9efbce476f70ba9ee2171daf5042f9e3d8a
 F test/pragma2.test 5364893491b9231dd170e3459bfc2e2342658b47
 F test/printf.test 05970cde31b1a9f54bd75af60597be75a5c54fea
@@ -556,7 +553,7 @@ F test/savepoint2.test 9b8543940572a2f01a18298c3135ad0c9f4f67d7
 F test/savepoint3.test e328085853b14898d78ceea00dfe7db18bb6a9ec
 F test/savepoint4.test c8f8159ade6d2acd9128be61e1230f1c1edc6cc0
 F test/savepoint5.test 0735db177e0ebbaedc39812c8d065075d563c4fd
-F test/savepoint6.test 30f5c068d7aceacbf9bd6a7df1c99f34b2fc2723
+F test/savepoint6.test bdc653c5c08328c84a74471b5b23fd483b919dfe
 F test/schema.test 8f7999be894260f151adf15c2c7540f1c6d6a481
 F test/schema2.test 906408621ea881fdb496d878b1822572a34e32c5
 F test/securedel.test 328d2921c0ca49bdd3352e516b0377fc07143254
@@ -761,7 +758,7 @@ F test/vtabE.test 7c4693638d7797ce2eda17af74292b97e705cc61
 F test/vtab_alter.test 9e374885248f69e251bdaacf480b04a197f125e5
 F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8
 F test/vtab_shared.test 0eff9ce4f19facbe0a3e693f6c14b80711a4222d
-F test/wal.test b5d5fe1b3171eefb25355758e0dc689096bc1f87
+F test/wal.test fbf7a911b35eb9b09a84eee4020e9e4c8b148d6f
 F test/walbak.test f6fde9a5f59d0c697cb1f4af7876178c2f69a7ba
 F test/walcrash.test f022cee7eb7baa5fb898726120a6a4073dd831d1
 F test/walhook.test 76a559e262f0715c470bade4a8d8333035f8ee47
@@ -811,14 +808,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P 30d0134454734fd9335896372c30a903e9adcc64 ca9d86baf70f210d331ce93102177c8005c494cb
-R b0a15978d17250dbff5ca26f38578573
-U drh
-Z 50883e064ff8d31e35ff6084caafc75f
------BEGIN PGP SIGNATURE-----
-Version: GnuPG v1.4.6 (GNU/Linux)
-
-iD8DBQFL1kRKoxKgR168RlERAhGtAJ0ZNNVfZUQ2rD2DR5znbRsfpO0FrQCeMGjZ
-bgsVZnQebWJklqCayCQA1Cc=
-=MFJQ
------END PGP SIGNATURE-----
+P 7a0ac682c3bffcb345321fe97434563350ac90f9
+R 8f311e98676985c9f340b1e7e337c8e4
+U dan
+Z 70973fdb159f8a0ed7dee7d674e22de0
index e84e36275cb83e7acbed9b4d4764433387febd18..f9a7784eff21c3454c30a8c72e8e2b5062e640fa 100644 (file)
@@ -1 +1 @@
-7a0ac682c3bffcb345321fe97434563350ac90f9
\ No newline at end of file
+b51a5f8bc660616aa264025dd7ad4bdab458814b
\ No newline at end of file
index 8c6878a1a497891ab167d42cff8f04210008d6cb..14ee78d9f1de838b2bc3b1bb0a3b27056fc72724 100644 (file)
--- a/src/wal.c
+++ b/src/wal.c
@@ -592,6 +592,22 @@ static int logSummaryMap(LogSummary *pSummary, int nByte){
   return SQLITE_OK;
 }
 
+/*
+** The log-summary file is already mapped to pSummary->aData[], but the
+** mapping needs to be resized. Unmap and remap the file so that the mapping 
+** is at least nByte bytes in size, or the size of the entire file if it 
+** is larger than nByte bytes.
+*/
+static int logSummaryRemap(LogSummary *pSummary, int nByte){
+  int rc;
+  sqlite3_mutex_enter(pSummary->mutex);
+  munmap(pSummary->aData, pSummary->nData*4);
+  pSummary->aData = 0;
+  rc = logSummaryMap(pSummary, nByte);
+  sqlite3_mutex_leave(pSummary->mutex);
+  return rc;
+}
+
 /*
 ** Return the index in the LogSummary.aData array that corresponds to 
 ** frame iFrame. The log-summary file consists of a header, followed by
@@ -613,18 +629,18 @@ static int logSummaryEntry(u32 iFrame){
 ** the previous call), but that restriction is not enforced or asserted
 ** here.
 */
-static void logSummaryAppend(LogSummary *pSummary, u32 iFrame, u32 iPage){
+static int logSummaryAppend(LogSummary *pSummary, u32 iFrame, u32 iPage){
   u32 iSlot = logSummaryEntry(iFrame);
 
   while( (iSlot+128)>=pSummary->nData ){
+    int rc;
     int nByte = pSummary->nData*4 + LOGSUMMARY_MMAP_INCREMENT;
 
     /* Unmap and remap the log-summary file. */
-    sqlite3_mutex_enter(pSummary->mutex);
-    munmap(pSummary->aData, pSummary->nData*4);
-    pSummary->aData = 0;
-    logSummaryMap(pSummary, nByte);
-    sqlite3_mutex_leave(pSummary->mutex);
+    rc = logSummaryRemap(pSummary, nByte);
+    if( rc!=SQLITE_OK ){
+      return rc;
+    }
   }
 
   /* Set the log-summary entry itself */
@@ -649,6 +665,8 @@ static void logSummaryAppend(LogSummary *pSummary, u32 iFrame, u32 iPage){
     logMergesort8(aFrame, aTmp, aIndex, &nIndex);
     memset(&aIndex[nIndex], aIndex[nIndex-1], 256-nIndex);
   }
+
+  return SQLITE_OK;
 }
 
 
@@ -1496,6 +1514,16 @@ int sqlite3WalOpenSnapshot(Log *pLog, int *pChanged){
     if( rc!=SQLITE_OK ){
       /* An error occured while attempting log recovery. */
       sqlite3WalCloseSnapshot(pLog);
+    }else{
+      /* Check if the mapping needs to grow. */
+      LogSummary *pSummary = pLog->pSummary;
+
+      if( pLog->hdr.iLastPg 
+       && logSummaryEntry(pLog->hdr.iLastPg)>=pSummary->nData 
+      ){
+        rc = logSummaryRemap(pSummary, 0);
+        assert( rc || logSummaryEntry(pLog->hdr.iLastPg)<pSummary->nData );
+      }
     }
   }
   return rc;
@@ -1516,20 +1544,20 @@ void sqlite3WalCloseSnapshot(Log *pLog){
 ** Read a page from the log, if it is present. 
 */
 int sqlite3WalRead(Log *pLog, Pgno pgno, int *pInLog, u8 *pOut){
+  LogSummary *pSummary = pLog->pSummary;
   u32 iRead = 0;
   u32 *aData; 
   int iFrame = (pLog->hdr.iLastPg & 0xFFFFFF00);
 
   assert( pLog->isLocked );
-
-  sqlite3_mutex_enter(pLog->pSummary->mutex);
-  aData = pLog->pSummary->aData;
+  sqlite3_mutex_enter(pSummary->mutex);
 
   /* Do a linear search of the unindexed block of page-numbers (if any) 
   ** at the end of the log-summary. An alternative to this would be to
   ** build an index in private memory each time a read transaction is
   ** opened on a new snapshot.
   */
+  aData = pSummary->aData;
   if( pLog->hdr.iLastPg ){
     u32 *pi = &aData[logSummaryEntry(pLog->hdr.iLastPg)];
     u32 *piStop = pi - (pLog->hdr.iLastPg & 0xFF);
index 63319535d1f58cb1a2d000d228c47bccadb30f84..e4c5204714a64981841ce9d26e69be8e43697d18 100644 (file)
@@ -34,7 +34,6 @@ source $testdir/lock_common.tcl
 #
 do_test lock2-1.1 {
   set ::tf1 [launch_testfixture]
-  testfixture $::tf1 "sqlite3_test_control_pending_byte $::sqlite_pending_byte"
   testfixture $::tf1 {
     sqlite3 db test.db -key xyzzy
     db eval {select * from sqlite_master}
index 31c04e85355c36f8faef0383de22d5a3c9993378..a17de8a3da793ab74ccb62d8170164bef740f607 100644 (file)
@@ -24,6 +24,7 @@ proc launch_testfixture {} {
   }
   set chan [open "|$prg tf_main.tcl" r+]
   fconfigure $chan -buffering line
+  testfixture $chan "sqlite3_test_control_pending_byte $::sqlite_pending_byte"
   return $chan
 }
 
index e4c47a3650ad4bfac66e83a7b04120f4bc92af1e..f51cc84422314845539ac313d7379f7ebd6691e8 100644 (file)
@@ -758,6 +758,10 @@ if {[info commands register_demovfs] != ""} {
 
 run_tests "wal" -description {
   Run tests with journal_mode=WAL
+} -initialize {
+  set ::savepoint6_iterations 100
+} -shutdown {
+  unset -nocomplain ::savepoint6_iterations
 } -include {
   savepoint.test
   savepoint2.test
index 2b2bcc8e06569542c30c6f51764924d86d497fc6..7f60769c634cd397c695e7e178cd3bc905094721 100644 (file)
@@ -26,7 +26,9 @@ set DATABASE_SCHEMA {
     CREATE INDEX i2 ON t1(y);
 }
 
-set ::ITERATIONS 1000
+if {0==[info exists ::savepoint6_iterations]} {
+  set ::savepoint6_iterations 1000
+}
 
 #--------------------------------------------------------------------------
 # In memory database state.
@@ -257,7 +259,7 @@ foreach zSetup [list {
     checkdb
   } {ok}
   
-  for {set i 0} {$i < $::ITERATIONS} {incr i} {
+  for {set i 0} {$i < $::savepoint6_iterations} {incr i} {
     do_test savepoint6-$testname.$i.1 {
       savepoint_op
       checkdb
index d533f9e0c7829a7ff453e37ffeb3a5185f78ec2c..30586d5cb3e31177bbed323d10f1b28c11d05b04 100644 (file)
@@ -19,7 +19,7 @@ source $testdir/lock_common.tcl
 
 proc reopen_db {} {
   catch { db close }
-  file delete -force test.db test.db-wal
+  file delete -force test.db test.db-wal test.db-wal-summary
   sqlite3_wal db test.db
 }
 
@@ -249,12 +249,10 @@ do_test wal-4.5.2 {
   }
 } {32}
 do_test wal-4.5.3 {
-breakpoint
   execsql { ROLLBACK TO tr }
 } {}
 do_test wal-4.5.4 {
   set logsize [file size test.db-wal]
-breakpoint
   execsql {
       INSERT INTO t1 VALUES('x', 'y');
     RELEASE tr;
@@ -269,7 +267,6 @@ do_test wal-4.5.6 {
   file copy -force test.db test2.db
   file copy -force test.db-wal test2.db-wal
   sqlite3 db2 test2.db
-breakpoint
   execsql { SELECT count(*) FROM t2 ; SELECT count(*) FROM t1 } db2
 } {1 2}
 do_test wal-4.5.7 {
@@ -823,10 +820,11 @@ db close
 #-------------------------------------------------------------------------
 # Test large log summaries.
 #
-do_test wal-13.1 {
+set sqlite_walsummary_mmap_incr 64
+do_test wal-13.1.1 {
   list [file exists test.db] [file exists test.db-wal]
 } {1 0}
-do_test wal-13.2 {
+do_test wal-13.1.2 {
   set fd [open test.db-wal w]
   seek $fd [expr 200*1024*1024]
   puts $fd ""
@@ -834,25 +832,63 @@ do_test wal-13.2 {
   sqlite3 db test.db
   execsql { SELECT * FROM t2 }
 } {B 2}
-do_test wal-13.3 {
+do_test wal-13.1.3 {
   db close
   file exists test.db-wal
 } {0}
-do_test wal-13.4 {
+do_test wal-13.1.4 {
   sqlite3 db test.db
   execsql { SELECT count(*) FROM t2 }
 } {1}
-do_test wal-13.5 {
-  for {set i 0} {$i < 15} {incr i} {
+do_test wal-13.1.5 {
+  for {set i 0} {$i < 6} {incr i} {
     execsql { INSERT INTO t2 SELECT randomblob(400), randomblob(400) FROM t2 }
   }
   execsql { SELECT count(*) FROM t2 }
-} [expr int(pow(2, 15))]
-do_test wal-13.6 {
-  set sz [file size test.db-wal-summary]
-  expr {$sz<=(3*64*1024) && $sz>(2*64*1024)}
-} {1}
+} [expr int(pow(2, 6))]
+do_test wal-13.1.6 {
+  file size test.db-wal
+} [log_file_size 80 1024]
+
+foreach code [list {
+  set tn 2
+  proc buddy {tcl} { uplevel #0 $tcl }
+} {
+  set tn 3
+  set ::buddy [launch_testfixture]
+  proc buddy {tcl} { testfixture $::buddy $tcl }
+}] {
 
+  eval $code
+  reopen_db
+
+  do_test wal-13.$tn.0 {
+    buddy { sqlite3 db2 test.db }
+    execsql {
+      PRAGMA journal_mode = WAL;
+      CREATE TABLE t1(x);
+      INSERT INTO t1 SELECT randomblob(400);
+    }
+    execsql { SELECT count(*) FROM t1 }
+  } {1}
+
+  for {set ii 1} {$ii<16} {incr ii} {
+    do_test wal-13.$tn.$ii.a {
+      buddy { db2 eval { INSERT INTO t1 SELECT randomblob(400) FROM t1 } }
+      buddy { db2 eval { SELECT count(*) FROM t1 } }
+    } [expr (1<<$ii)]
+    do_test wal-13.$tn.$ii.b {
+      db eval { SELECT count(*) FROM t1 }
+    } [expr (1<<$ii)]
+    do_test wal-13.$tn.$ii.c {
+      db eval { SELECT count(*) FROM t1 }
+    } [expr (1<<$ii)]
+  }
+
+  catch { db2 close }
+  catch { close $::buddy }
+  db close
+}
 
 finish_test