194e95ea4Sdan# 2018 December 6 294e95ea4Sdan# 394e95ea4Sdan# The author disclaims copyright to this source code. In place of 494e95ea4Sdan# a legal notice, here is a blessing: 594e95ea4Sdan# 694e95ea4Sdan# May you do good and not evil. 794e95ea4Sdan# May you find forgiveness for yourself and forgive others. 894e95ea4Sdan# May you share freely, never taking more than you give. 994e95ea4Sdan# 1094e95ea4Sdan#*********************************************************************** 1194e95ea4Sdan# 1294e95ea4Sdan 1394e95ea4Sdanset testdir [file dirname $argv0] 1494e95ea4Sdansource $testdir/tester.tcl 1594e95ea4Sdan 1694e95ea4Sdanset testprefix shmlock 1794e95ea4Sdan 1894e95ea4Sdanifcapable !wal {finish_test ; return } 1994e95ea4Sdan 2094e95ea4Sdansqlite3 db2 test.db 2194e95ea4Sdansqlite3 db3 test.db 2294e95ea4Sdan 2394e95ea4Sdando_execsql_test 1.0 { 2494e95ea4Sdan PRAGMA journal_mode = wal; 2594e95ea4Sdan CREATE TABLE t1(a, b); 2694e95ea4Sdan INSERT INTO t1 VALUES(1, 2); 2794e95ea4Sdan} {wal} 2894e95ea4Sdando_test 1.1 { execsql { SELECT * FROM t1 } db2 } {1 2} 2994e95ea4Sdando_test 1.2 { execsql { SELECT * FROM t1 } db3 } {1 2} 3094e95ea4Sdan 3194e95ea4Sdanforeach {tn dbhandle cmd res} { 3294e95ea4Sdan 1 db {shared lock 7 1} OK 3394e95ea4Sdan 2 db2 {exclusive lock 7 1} BUSY 3494e95ea4Sdan 3 db {shared unlock 7 1} OK 3594e95ea4Sdan 4 db2 {exclusive lock 7 1} OK 3694e95ea4Sdan 5 db {shared lock 7 1} BUSY 3794e95ea4Sdan 6 db {exclusive lock 7 1} BUSY 3894e95ea4Sdan 7 db2 {exclusive unlock 7 1} OK 3994e95ea4Sdan 4094e95ea4Sdan 8 db {exclusive lock 0 8} OK 4194e95ea4Sdan 9 db {exclusive unlock 0 8} OK 4294e95ea4Sdan 10 db2 {exclusive lock 0 8} OK 4394e95ea4Sdan 11 db2 {exclusive unlock 0 8} OK 4494e95ea4Sdan 4594e95ea4Sdan 12 db {shared lock 0 1} OK 4694e95ea4Sdan 13 db2 {shared lock 0 1} OK 4794e95ea4Sdan 14 db3 {shared lock 0 1} OK 4894e95ea4Sdan 15 db3 {shared unlock 0 1} OK 4994e95ea4Sdan 16 db3 {exclusive lock 0 1} BUSY 5094e95ea4Sdan 17 db2 {shared unlock 0 1} OK 5194e95ea4Sdan 18 db3 {exclusive lock 0 1} BUSY 5294e95ea4Sdan 19 db {shared unlock 0 1} OK 5394e95ea4Sdan 20 db3 {exclusive lock 0 1} OK 5494e95ea4Sdan 21 db3 {exclusive unlock 0 1} OK 5594e95ea4Sdan 5694e95ea4Sdan 22 db {shared lock 3 1} OK 5794e95ea4Sdan 23 db2 {exclusive lock 2 2} BUSY 5894e95ea4Sdan 24 db {shared lock 2 1} OK 5994e95ea4Sdan 25 db2 {exclusive lock 0 5} BUSY 6094e95ea4Sdan 26 db2 {exclusive lock 0 4} BUSY 6194e95ea4Sdan 27 db2 {exclusive lock 0 3} BUSY 6294e95ea4Sdan 28 db {shared unlock 3 1} OK 6394e95ea4Sdan 29 db2 {exclusive lock 2 2} BUSY 6494e95ea4Sdan 28 db {shared unlock 2 1} OK 6594e95ea4Sdan 29 db2 {exclusive lock 2 2} OK 6694e95ea4Sdan 29 db2 {exclusive unlock 2 2} OK 6794e95ea4Sdan} { 6894e95ea4Sdan do_test 1.3.$tn [list vfs_shmlock $dbhandle main {*}$cmd] "SQLITE_$res" 6994e95ea4Sdan} 7094e95ea4Sdan 7194e95ea4Sdandb close 7294e95ea4Sdandb2 close 7394e95ea4Sdandb3 close 7494e95ea4Sdan 7594e95ea4Sdanif {[permutation]=="unix-excl"} { 7694e95ea4Sdan do_test 2.0 { 7794e95ea4Sdan for {set i 0} {$i < 256} {incr i} { 7894e95ea4Sdan sqlite3 db$i test.db 7994e95ea4Sdan execsql { SELECT * FROM t1 } db$i 8094e95ea4Sdan } 8194e95ea4Sdan for {set i 0} {$i < 255} {incr i} { 8294e95ea4Sdan set rc [vfs_shmlock db$i main shared lock 4 1] 8394e95ea4Sdan if {$rc != "SQLITE_OK"} { error $rc } 8494e95ea4Sdan } 8594e95ea4Sdan 8694e95ea4Sdan vfs_shmlock db255 main shared lock 4 1 8794e95ea4Sdan } {SQLITE_BUSY} 8894e95ea4Sdan 8994e95ea4Sdan do_test 2.1 { vfs_shmlock db255 main exclusive lock 4 1 } SQLITE_BUSY 9094e95ea4Sdan do_test 2.2 { vfs_shmlock db0 main shared unlock 4 1 } SQLITE_OK 9194e95ea4Sdan do_test 2.3 { vfs_shmlock db255 main shared lock 4 1 } SQLITE_OK 9294e95ea4Sdan do_test 2.4 { vfs_shmlock db255 main shared unlock 4 1 } SQLITE_OK 9394e95ea4Sdan do_test 2.5 { vfs_shmlock db255 main exclusive lock 4 1 } SQLITE_BUSY 9494e95ea4Sdan 9594e95ea4Sdan do_test 2.6 { 9694e95ea4Sdan for {set i 1} {$i < 255} {incr i} { 9794e95ea4Sdan set rc [vfs_shmlock db255 main exclusive lock 4 1] 9894e95ea4Sdan if {$rc != "SQLITE_BUSY"} { error $rc } 9994e95ea4Sdan set rc [vfs_shmlock db$i main shared unlock 4 1] 10094e95ea4Sdan if {$rc != "SQLITE_OK"} { error $rc } 10194e95ea4Sdan } 10294e95ea4Sdan 10394e95ea4Sdan vfs_shmlock db255 main exclusive lock 4 1 10494e95ea4Sdan } {SQLITE_OK} 10594e95ea4Sdan 10694e95ea4Sdan vfs_shmlock db255 main exclusive unlock 4 1 10794e95ea4Sdan 10894e95ea4Sdan for {set i 0} {$i < 256} {incr i} { 10994e95ea4Sdan db$i close 11094e95ea4Sdan } 11194e95ea4Sdan} 11294e95ea4Sdan 11394e95ea4Sdansqlite3 db0 test.db 11494e95ea4Sdansqlite3 db1 test.db 11594e95ea4Sdando_test 3.1 { execsql { SELECT * FROM t1 } db0 } {1 2} 11694e95ea4Sdando_test 3.2 { execsql { SELECT * FROM t1 } db1 } {1 2} 117*94e02d9cSdrhif {$tcl_platform(platform)=="windows"} { 118*94e02d9cSdrh set isWindows 1 119*94e02d9cSdrh} else { 120*94e02d9cSdrh set isWindows 0 121*94e02d9cSdrh} 12294e95ea4Sdan 12394e95ea4Sdanset L(0) {n n n n n n n n} 12494e95ea4Sdanset L(1) {n n n n n n n n} 12594e95ea4Sdanproc random_lock_test {idx} { 12694e95ea4Sdan global L 12794e95ea4Sdan set iSlot [expr int(rand()*8)] 12894e95ea4Sdan if {[expr int(rand()*2)]} { 12994e95ea4Sdan # Unlock operation 13094e95ea4Sdan if {[lindex $L($idx) $iSlot]!="n"} { 13194e95ea4Sdan vfs_shmlock db$idx main [lindex $L($idx) $iSlot] unlock $iSlot 1 13294e95ea4Sdan lset L($idx) $iSlot n 13394e95ea4Sdan } 13494e95ea4Sdan } else { 13594e95ea4Sdan # Lock operation 13694e95ea4Sdan if {[lindex $L($idx) $iSlot]=="n"} { 13794e95ea4Sdan set locktype [lindex {e s} [expr int(rand()*2)]] 13894e95ea4Sdan set n 1 13994e95ea4Sdan if {$locktype=="e"} { 14094e95ea4Sdan for {set l $iSlot} {$l<8 && [lindex $L($idx) $l]=="n"} {incr l} {} 14194e95ea4Sdan set n [expr int(rand()*($l-$iSlot))+1] 142*94e02d9cSdrh # The LockFile() and UnlockFile() apis on windows require that 143*94e02d9cSdrh # every unlock correspond exactly to a prior lock. Hence, we cannot 144*94e02d9cSdrh # lock arbitrary ranges in this test on windows. 145*94e02d9cSdrh if {$::isWindows} {set n 1} 14694e95ea4Sdan # puts "iSlot=$iSlot l=$l L=$L($idx)" 14794e95ea4Sdan # puts "$iSlot $n" 14894e95ea4Sdan } 14994e95ea4Sdan set res [vfs_shmlock db$idx main $locktype lock $iSlot $n] 15094e95ea4Sdan 15194e95ea4Sdan set bBusy 0 15294e95ea4Sdan for {set i $iSlot} {$i<($iSlot+$n)} {incr i} { 15394e95ea4Sdan set other [lindex $L([expr ($idx+1)%2]) $i] 15494e95ea4Sdan if {($other!="n" && $locktype=="e")||($other=="e" && $locktype=="s")} { 15594e95ea4Sdan if {$res != "SQLITE_BUSY"} { error "BUSY not detected" } 15694e95ea4Sdan set bBusy 1 15794e95ea4Sdan break 15894e95ea4Sdan } 15994e95ea4Sdan } 16094e95ea4Sdan 16194e95ea4Sdan if {$bBusy==0} { 16294e95ea4Sdan if {$res != "SQLITE_OK"} { error "BUSY false-positive" } 16394e95ea4Sdan for {set i $iSlot} {$i<($iSlot+$n)} {incr i} { 16494e95ea4Sdan lset L($idx) $i $locktype 16594e95ea4Sdan } 16694e95ea4Sdan } 16794e95ea4Sdan } 16894e95ea4Sdan } 16994e95ea4Sdan} 17094e95ea4Sdan 17194e95ea4Sdanset nStep 100000 17294e95ea4Sdanfor {set i 0} {$i < $nStep} {incr i} { 17394e95ea4Sdan random_lock_test 0 17494e95ea4Sdan random_lock_test 1 17594e95ea4Sdan} 17694e95ea4Sdan 17794e95ea4Sdandb0 close 17894e95ea4Sdandb1 close 17994e95ea4Sdan 18094e95ea4Sdanfinish_test 181