sl@0: # 2007 September 10 sl@0: # sl@0: # The author disclaims copyright to this source code. In place of sl@0: # a legal notice, here is a blessing: sl@0: # sl@0: # May you do good and not evil. sl@0: # May you find forgiveness for yourself and forgive others. sl@0: # May you share freely, never taking more than you give. sl@0: # sl@0: #*********************************************************************** sl@0: # sl@0: # This test attempts to deadlock SQLite in shared-cache mode. sl@0: # sl@0: # sl@0: # $Id: thread002.test,v 1.3 2008/07/12 14:52:20 drh Exp $ sl@0: sl@0: set testdir [file dirname $argv0] sl@0: sl@0: source $testdir/tester.tcl sl@0: source $testdir/thread_common.tcl sl@0: if {[info commands sqlthread] eq ""} { sl@0: finish_test sl@0: return sl@0: } sl@0: ifcapable !attach { sl@0: finish_test sl@0: return sl@0: } sl@0: sl@0: db close sl@0: sqlite3_enable_shared_cache 1 sl@0: sl@0: set ::NTHREAD 10 sl@0: sl@0: do_test thread002.1 { sl@0: # Create 3 databases with identical schemas: sl@0: for {set ii 0} {$ii < 3} {incr ii} { sl@0: file delete -force test${ii}.db sl@0: sqlite3 db test${ii}.db sl@0: execsql { sl@0: CREATE TABLE t1(k, v); sl@0: CREATE INDEX t1_i ON t1(v); sl@0: INSERT INTO t1(v) VALUES(1.0); sl@0: } sl@0: db close sl@0: } sl@0: } {} sl@0: sl@0: set thread_program { sl@0: set ::DB [sqlite3_open test.db] sl@0: for {set ii 1} {$ii <= 3} {incr ii} { sl@0: set T [lindex $order [expr $ii-1]] sl@0: execsql "ATTACH 'test${T}.db' AS aux${ii}" sl@0: } sl@0: sl@0: for {set ii 0} {$ii < 100} {incr ii} { sl@0: execsql { SELECT * FROM aux1.t1 } sl@0: execsql { INSERT INTO aux1.t1(v) SELECT sum(v) FROM aux2.t1 } sl@0: sl@0: execsql { SELECT * FROM aux2.t1 } sl@0: execsql { INSERT INTO aux2.t1(v) SELECT sum(v) FROM aux3.t1 } sl@0: sl@0: execsql { SELECT * FROM aux3.t1 } sl@0: execsql { INSERT INTO aux3.t1(v) SELECT sum(v) FROM aux1.t1 } sl@0: sl@0: execsql { CREATE TABLE aux1.t2(a,b) } sl@0: execsql { DROP TABLE aux1.t2 } sl@0: sl@0: # if {($ii%10)==0} {puts -nonewline . ; flush stdout} sl@0: puts -nonewline . ; flush stdout sl@0: } sl@0: sl@0: sqlite3_close $::DB sl@0: list OK sl@0: } sl@0: sl@0: set order_list [list {0 1 2} {0 2 1} {1 0 2} {1 2 0} {2 0 1} {2 1 0}] sl@0: sl@0: array unset finished sl@0: for {set ii 0} {$ii < $::NTHREAD} {incr ii} { sl@0: set order [lindex $order_list [expr $ii%6]] sl@0: thread_spawn finished($ii) $thread_procs "set order {$order}" $thread_program sl@0: } sl@0: sl@0: # Wait for all threads to finish, then check they all returned "OK". sl@0: # sl@0: for {set i 0} {$i < $::NTHREAD} {incr i} { sl@0: if {![info exists finished($i)]} { sl@0: vwait finished($i) sl@0: } sl@0: do_test thread001.2.$i { sl@0: set ::finished($i) sl@0: } OK sl@0: } sl@0: sl@0: # Check all three databases are Ok. sl@0: for {set ii 0} {$ii < 3} {incr ii} { sl@0: do_test thread002.3.$ii { sl@0: sqlite3 db test${ii}.db sl@0: set res [list \ sl@0: [execsql {SELECT count(*) FROM t1}] \ sl@0: [execsql {PRAGMA integrity_check}] \ sl@0: ] sl@0: db close sl@0: set res sl@0: } [list [expr 1 + $::NTHREAD*100] ok] sl@0: } sl@0: sl@0: finish_test