]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add another test file to help verify thread-safety. (CVS 4419)
authordanielk1977 <danielk1977@noemail.net>
Mon, 10 Sep 2007 10:53:01 +0000 (10:53 +0000)
committerdanielk1977 <danielk1977@noemail.net>
Mon, 10 Sep 2007 10:53:01 +0000 (10:53 +0000)
FossilOrigin-Name: c758cc1d885b4528c0b0ef6382119f20956d4816

manifest
manifest.uuid
src/test_thread.c
test/quick.test
test/thread002.test [new file with mode: 0644]
test/thread_common.tcl

index 06cdbe521ff4ef71f3801e0fb7fd1219069b22a2..9031bcf2df1ac48977c725a82c7d0764207b266b 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Enhance\sthread001.test\sagain,\sthis\stime\sto\salso\stest\sin\sshared-cache\smode.\s(CVS\s4418)
-D 2007-09-10T07:35:47
+C Add\sanother\stest\sfile\sto\shelp\sverify\sthread-safety.\s(CVS\s4419)
+D 2007-09-10T10:53:02
 F Makefile.in cbfb898945536a8f9ea8b897e1586dd1fdbcc5db
 F Makefile.linux-gcc 65241babba6faf1152bf86574477baab19190499
 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
@@ -156,7 +156,7 @@ F src/test_md5.c 34599caee5b1c73dcf86ca31f55846fab8c19ef7
 F src/test_schema.c 12c9de7661d6294eec2d57afbb52e2af1128084f
 F src/test_server.c 1020673fc02ba5bbfa5dc96ded9f54f0f3744d38
 F src/test_tclvar.c b2d1115e4d489179d3f029e765211b2ad527ba59
-F src/test_thread.c cbd7ba2cb295df9c9a8e848a8886c8d0f318de27
+F src/test_thread.c a98d69cae883e53d3686fc25889a5fa5f51439f8
 F src/tokenize.c 67e42600ab34f976f2b1288c499ad6c98d652f0e
 F src/trigger.c 724a77d54609a33bde90618934fbeddfcc729a10
 F src/update.c e89b980b443d44b68bfc0b1746cdb6308e049ac9
@@ -388,7 +388,7 @@ F test/pragma2.test bb5aa7be00dae2c381fcc782358048a33c955793
 F test/printf.test 6bf1a86c6a1e45536f72d782bf44c8e3c76510f8
 F test/progress.test 5b075c3c790c7b2a61419bc199db87aaf48b8301 x
 F test/ptrchng.test 1c712dd6516e1377471744fa765e41c79a357da6
-F test/quick.test 88844a19f6d9dc5c990e01c7dd611d33d022a1c1
+F test/quick.test bedc5696abff22532b6df7da2b073254b15e53b7
 F test/quote.test 215897dbe8de1a6f701265836d6601cc6ed103e6
 F test/rdonly.test b34db316525440d3b42c32e83942c02c37d28ef0
 F test/reindex.test 38b138abe36bf9a08c791ed44d9f76cd6b97b78b
@@ -426,9 +426,10 @@ F test/tclsqlite.test a868898e3350246be7ea132621dc25f9835b3030
 F test/temptable.test c36f3e5a94507abb64f7ba23deeb4e1a8a8c3821
 F test/tester.tcl 913a808f05b0aed2fbb16481a423b1a5a118bdf0
 F test/thread001.test 8fbd9559da0bbdc273e00318c7fd66c162020af7
+F test/thread002.test 1b886bc4cb396e2bba94be8996f159b2b5b605bc
 F test/thread1.test 776c9e459b75ba905193b351926ac4019b049f35
 F test/thread2.test 6d7b30102d600f51b4055ee3a5a19228799049fb
-F test/thread_common.tcl 95b11a3f42df7cba82e0c8feb8a70d339aaad4cb
+F test/thread_common.tcl 8a9d7a4500dfdbbd36679c977831b62c130b76b1
 F test/threadtest1.c 6029d9c5567db28e6dc908a0c63099c3ba6c383b
 F test/threadtest2.c ace893054fa134af3fc8d6e7cfecddb8e3acefb9
 F test/tkt1435.test f8c52c41de6e5ca02f1845f3a46e18e25cadac00
@@ -574,7 +575,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
 F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
-P 6ee2b8ffc4310c8e329f634f3ade058b33c53a2a
-R 59e1b6472478b1b0d4fb7b3646b47885
+P 54f87899033ddd892bfd3a16310f64fb42d807ae
+R d80f0142f0a5e23af45dc05a2499fc1e
 U danielk1977
-Z f03978abade17ec790e2c8c978d82d62
+Z d1aeb7bb16c21c3bfd6864755301855d
index 80f002b77cdbd75dc492e64eba05acee654d01df..544a86c9556be34ce10a9062b333df2ea79b355c 100644 (file)
@@ -1 +1 @@
-54f87899033ddd892bfd3a16310f64fb42d807ae
\ No newline at end of file
+c758cc1d885b4528c0b0ef6382119f20956d4816
\ No newline at end of file
index a6bbbd80e43027ecff521b02fcc6f2c596b695d7..4bfc6492d55180fe10a8cad186cae82941e3296c 100644 (file)
@@ -14,7 +14,7 @@
 ** test that sqlite3 database handles may be concurrently accessed by 
 ** multiple threads. Right now this only works on unix.
 **
-** $Id: test_thread.c,v 1.3 2007/09/10 06:23:54 danielk1977 Exp $
+** $Id: test_thread.c,v 1.4 2007/09/10 10:53:02 danielk1977 Exp $
 */
 
 #include "sqliteInt.h"
@@ -224,6 +224,12 @@ static int xBusy(void *pArg, int nBusy){
   return 1;             /* Try again... */
 }
 
+/*
+** sqlthread open
+**
+**     Open a database handle and return the string representation of
+**     the pointer value.
+*/
 static int sqlthread_open(
   ClientData clientData,
   Tcl_Interp *interp,
@@ -250,6 +256,24 @@ static int sqlthread_open(
 }
 
 
+/*
+** sqlthread open
+**
+**     Return the current thread-id (Tcl_GetCurrentThread()) cast to
+**     an integer.
+*/
+static int sqlthread_id(
+  ClientData clientData,
+  Tcl_Interp *interp,
+  int objc,
+  Tcl_Obj *CONST objv[]
+){
+  Tcl_ThreadId id = Tcl_GetCurrentThread();
+  Tcl_SetObjResult(interp, Tcl_NewIntObj((int)id));
+  return TCL_OK;
+}
+
+
 /*
 ** Dispatch routine for the sub-commands of [sqlthread].
 */
@@ -268,6 +292,7 @@ static int sqlthread_proc(
     {"parent", sqlthread_parent, 1, "SCRIPT"},
     {"spawn",  sqlthread_spawn,  2, "VARNAME SCRIPT"},
     {"open",   sqlthread_open,   1, "DBNAME"},
+    {"id",     sqlthread_id,     0, ""},
     {0, 0, 0}
   };
   struct SubCommand *pSub;
index 490a5283abfdaa2d9dcc801046e46db285734a58..6269f318e667ff77f872337430f5a980c8aed4cb 100644 (file)
@@ -6,7 +6,7 @@
 #***********************************************************************
 # This file runs all tests.
 #
-# $Id: quick.test,v 1.62 2007/08/23 16:27:21 danielk1977 Exp $
+# $Id: quick.test,v 1.63 2007/09/10 10:53:02 danielk1977 Exp $
 
 proc lshift {lvar} {
   upvar $lvar l
@@ -66,6 +66,9 @@ set EXCLUDE {
   speed2.test
   sqllimits1.test
 
+  thread001.test
+  thread002.test
+
   incrvacuum_ioerr.test
   autovacuum_crash.test
   btree8.test
diff --git a/test/thread002.test b/test/thread002.test
new file mode 100644 (file)
index 0000000..94141be
--- /dev/null
@@ -0,0 +1,105 @@
+# 2007 September 10
+#
+# The author disclaims copyright to this source code.  In place of
+# a legal notice, here is a blessing:
+#
+#    May you do good and not evil.
+#    May you find forgiveness for yourself and forgive others.
+#    May you share freely, never taking more than you give.
+#
+#***********************************************************************
+#
+#   This test attempts to deadlock SQLite in shared-cache mode.
+#     
+#
+# $Id: thread002.test,v 1.1 2007/09/10 10:53:02 danielk1977 Exp $
+
+set testdir [file dirname $argv0]
+
+source $testdir/tester.tcl
+source $testdir/thread_common.tcl
+if {[info commands sqlthread] eq ""} {
+  return
+}
+
+db close
+sqlite3_enable_shared_cache 1
+
+set ::NTHREAD 10
+
+do_test thread002.1 {
+  # Create 3 databases with identical schemas:
+  for {set ii 0} {$ii < 3} {incr ii} {
+    file delete -force test${ii}.db
+    sqlite3 db test${ii}.db
+    execsql {
+      CREATE TABLE t1(k, v);
+      CREATE INDEX t1_i ON t1(v);
+      INSERT INTO t1(v) VALUES(1.0);
+    }
+    db close
+  }
+} {}
+
+set thread_program {
+  set ::DB [sqlite3_open test.db]
+  for {set ii 1} {$ii <= 3} {incr ii} {
+    set T [lindex $order [expr $ii-1]]
+    execsql "ATTACH 'test${T}.db' AS aux${ii}"
+  }
+
+  for {set ii 0} {$ii < 100} {incr ii} {
+    execsql { SELECT * FROM aux1.t1 }
+    execsql { INSERT INTO aux1.t1(v) SELECT sum(v) FROM aux2.t1 }
+  
+    execsql { SELECT * FROM aux2.t1 }
+    execsql { INSERT INTO aux2.t1(v) SELECT sum(v) FROM aux3.t1 }
+  
+    execsql { SELECT * FROM aux3.t1 }
+    execsql { INSERT INTO aux3.t1(v) SELECT sum(v) FROM aux1.t1 }
+
+    execsql { CREATE TABLE aux1.t2(a,b) }
+    execsql { DROP TABLE aux1.t2 }
+
+    # if {($ii%10)==0} {puts -nonewline . ; flush stdout}
+    puts -nonewline . ; flush stdout
+  }
+
+  sqlite3_close $::DB
+  list OK
+}
+
+set order_list [list {0 1 2} {0 2 1} {1 0 2} {1 2 0} {2 0 1} {2 1 0}]
+
+array unset finished
+for {set ii 0} {$ii < $::NTHREAD} {incr ii} {
+  set order [lindex $order_list [expr $ii%6]]
+  thread_spawn finished($ii) $thread_procs "set order {$order}" $thread_program
+}
+
+# Wait for all threads to finish,  then check they all returned "OK".
+#
+for {set i 0} {$i < $::NTHREAD} {incr i} {
+  if {![info exists finished($i)]} {
+    vwait finished($i)
+  }
+  do_test thread001.2.$i {
+    set ::finished($i)
+  } OK
+}
+
+# Check all three databases are Ok.
+for {set ii 0} {$ii < 3} {incr ii} {
+  do_test thread002.3.$ii {
+    sqlite3 db test${ii}.db
+    set res [list                         \
+      [execsql {SELECT count(*) FROM t1}] \
+      [execsql {PRAGMA integrity_check}]  \
+    ]
+    db close
+    set res
+  } [list [expr 1 + $::NTHREAD*100] ok]
+}
+
+finish_test
+
index 92611b1daabfcf8cca633b1624956006dfb4c655..5e34b179b1582fb93fadef7b067a649270bedbbb 100644 (file)
@@ -9,7 +9,7 @@
 #
 #***********************************************************************
 #
-# $Id: thread_common.tcl,v 1.1 2007/09/10 07:35:47 danielk1977 Exp $
+# $Id: thread_common.tcl,v 1.2 2007/09/10 10:53:02 danielk1977 Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -23,8 +23,6 @@ if {[info commands sqlthread] eq ""} {
   return
 }
 
-set ::NTHREAD 10
-
 # The following script is sourced by every thread spawned using 
 # [sqlthread spawn]:
 set thread_procs {
@@ -34,17 +32,37 @@ set thread_procs {
   proc execsql {sql} {
 
     set rc SQLITE_LOCKED
-    while {$rc eq "SQLITE_LOCKED"} {
+    while {$rc eq "SQLITE_LOCKED" 
+        || $rc eq "SQLITE_BUSY" 
+        || $rc eq "SQLITE_SCHEMA"} {
       set res [list]
-      set ::STMT [sqlite3_prepare $::DB $sql -1 dummy_tail]
-      while {[set rc [sqlite3_step $::STMT]] eq "SQLITE_ROW"} {
-        for {set i 0} {$i < [sqlite3_column_count $::STMT]} {incr i} {
-          lappend res [sqlite3_column_text $::STMT 0]
+
+      set err [catch {
+        set ::STMT [sqlite3_prepare_v2 $::DB $sql -1 dummy_tail]
+      } msg]
+
+      if {$err == 0} {
+        while {[set rc [sqlite3_step $::STMT]] eq "SQLITE_ROW"} {
+          for {set i 0} {$i < [sqlite3_column_count $::STMT]} {incr i} {
+            lappend res [sqlite3_column_text $::STMT 0]
+          }
         }
+        set rc [sqlite3_finalize $::STMT]
+      } else {
+        if {[string first (6) $msg]} {
+          set rc SQLITE_LOCKED
+        } else {
+          set rc SQLITE_ERROR
+        }
+      }
+
+      if {[string first locked [sqlite3_errmsg $::DB]]>=0} {
+        set rc SQLITE_LOCKED
       }
 
-      set rc [sqlite3_finalize $::STMT]
-      if {$rc eq "SQLITE_LOCKED"} {
+      if {$rc eq "SQLITE_LOCKED" || $rc eq "SQLITE_BUSY"} {
+ #puts -nonewline "([sqlthread id] $rc)"
+ #flush stdout
         after 20
       }
     }