mirror of
https://github.com/berkeleydb/libdb.git
synced 2024-11-16 17:16:25 +00:00
180 lines
4.2 KiB
Text
180 lines
4.2 KiB
Text
#
|
|
# 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 file implements regression tests for exclusive transactions. In
|
|
# BDB exclusive transactions do not block the entire database, but force
|
|
# non-exclusive transactions to abort if there is ever deadlock. If two
|
|
# exclusive transactions are created at the same time then one will block
|
|
# the other until it completes.
|
|
#
|
|
|
|
set testdir [file dirname $argv0]/../../lang/sql/sqlite/test
|
|
|
|
source $testdir/../../../../test/sql/bdb_util.tcl
|
|
if {[run_thread_tests]==0} { finish_test ; return }
|
|
|
|
sqlite3 db test.db -fullmutex 1
|
|
|
|
do_test bdb_exclusive.1.0 {
|
|
db eval {
|
|
CREATE TABLE t1(a);
|
|
CREATE TABLE t2(a);
|
|
}
|
|
} {}
|
|
|
|
# Create deadlock between an exclusive and non-exclusive
|
|
# transactions
|
|
set exclusive_test2 {
|
|
set key ""
|
|
if {[sqlite -has-codec]} {
|
|
set key "xyzzy"
|
|
}
|
|
set ::DB [sqlthread open test.db $key]
|
|
set rc [
|
|
for {set i 0} {$i < 100} {incr i} {
|
|
do_test e1.$i {
|
|
execsql { BEGIN EXCLUSIVE }
|
|
} {SQLITE_OK}
|
|
do_test e2.$i {
|
|
execsql { INSERT INTO t2 VALUES(2) }
|
|
} {SQLITE_OK}
|
|
do_test e3.$i {
|
|
execsql { INSERT INTO t1 VALUES(2) }
|
|
} {SQLITE_OK}
|
|
do_test e4.$i {
|
|
execsql { COMMIT }
|
|
} {SQLITE_OK}
|
|
}
|
|
]
|
|
sqlite3_close $::DB
|
|
set rc
|
|
}
|
|
|
|
set nonexclusive_test2 {
|
|
set key ""
|
|
if {[sqlite -has-codec]} {
|
|
set key "xyzzy"
|
|
}
|
|
set ::DB [sqlthread open test.db $key]
|
|
set rc [
|
|
for {set i 0} {$i < 100} {incr i} {
|
|
do_test n1.$i {
|
|
execsql { BEGIN }
|
|
} {SQLITE_OK}
|
|
do_test n2.$i {
|
|
set res [ execsql {INSERT INTO t1 VALUES(2) } ]
|
|
if {$res eq "SQLITE_LOCKED" || $res eq "SQLITE_BUSY"} {
|
|
execsql { ROLLBACK }
|
|
execsql { BEGIN }
|
|
set res SQLITE_OK
|
|
}
|
|
set res
|
|
} {SQLITE_OK}
|
|
do_test n3.$i {
|
|
set res [ execsql {INSERT INTO t2 VALUES(2) } ]
|
|
if {$res eq "SQLITE_LOCKED" || $res eq "SQLITE_BUSY"} {
|
|
execsql { ROLLBACK }
|
|
execsql { BEGIN }
|
|
set res SQLITE_OK
|
|
}
|
|
set res
|
|
} {SQLITE_OK}
|
|
do_test n4.$i {
|
|
execsql { ROLLBACK }
|
|
} {SQLITE_OK}
|
|
}
|
|
]
|
|
sqlite3_close $::DB
|
|
set rc
|
|
}
|
|
|
|
# Check that deadlock cannot occur between two exclusive
|
|
# transactions
|
|
set exclusive1_test3 {
|
|
set key ""
|
|
if {[sqlite -has-codec]} {
|
|
set key "xyzzy"
|
|
}
|
|
set ::DB [sqlthread open test.db $key]
|
|
set rc [
|
|
for {set i 0} {$i < 100} {incr i} {
|
|
do_test 1e1.$i {
|
|
execsql { BEGIN EXCLUSIVE }
|
|
} {SQLITE_OK}
|
|
do_test 1e2.$i {
|
|
execsql { INSERT INTO t2 VALUES(2) }
|
|
} {SQLITE_OK}
|
|
do_test 1e3.$i {
|
|
execsql { INSERT INTO t1 VALUES(2) }
|
|
} {SQLITE_OK}
|
|
do_test 1e4.$i {
|
|
execsql { COMMIT }
|
|
} {SQLITE_OK}
|
|
}
|
|
]
|
|
sqlite3_close $::DB
|
|
set rc
|
|
}
|
|
|
|
set exclusive2_test3 {
|
|
set key ""
|
|
if {[sqlite -has-codec]} {
|
|
set key "xyzzy"
|
|
}
|
|
set ::DB [sqlthread open test.db $key]
|
|
set rc [
|
|
for {set i 0} {$i < 100} {incr i} {
|
|
do_test 2e1.$i {
|
|
execsql { BEGIN EXCLUSIVE }
|
|
} {SQLITE_OK}
|
|
do_test 2e2.$i {
|
|
execsql { INSERT INTO t1 VALUES(2) }
|
|
} {SQLITE_OK}
|
|
do_test 2e3.$i {
|
|
execsql { INSERT INTO t2 VALUES(2) }
|
|
} {SQLITE_OK}
|
|
do_test 2e4.$i {
|
|
execsql { COMMIT }
|
|
} {SQLITE_OK}
|
|
}
|
|
]
|
|
sqlite3_close $::DB
|
|
set rc
|
|
}
|
|
|
|
# Start the exclusive and non-exclusive threads
|
|
#
|
|
array unset finished
|
|
thread_spawn finished(0) "" $bdb_thread_procs $exclusive_test2
|
|
thread_spawn finished(1) "" $bdb_thread_procs $nonexclusive_test2
|
|
|
|
for {set i 0} {$i < 2} {incr i} {
|
|
if {![info exists finished($i)]} {
|
|
vwait finished($i)
|
|
}
|
|
do_test exclusive_nonexclusive.2.$i {
|
|
set ::finished($i)
|
|
} {}
|
|
}
|
|
|
|
# Start the two exclusive threads
|
|
#
|
|
array unset finished
|
|
thread_spawn finished(0) "" $bdb_thread_procs $exclusive1_test3
|
|
thread_spawn finished(1) "" $bdb_thread_procs $exclusive2_test3
|
|
|
|
for {set i 0} {$i < 2} {incr i} {
|
|
if {![info exists finished($i)]} {
|
|
vwait finished($i)
|
|
}
|
|
do_test exclusive_exclusive.3.$i {
|
|
set ::finished($i)
|
|
} {}
|
|
}
|
|
|
|
db close
|
|
|
|
finish_test
|