1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
|
# 2018 December 6
#
# 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.
#
#***********************************************************************
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix shmlock
ifcapable !wal {finish_test ; return }
sqlite3 db2 test.db
sqlite3 db3 test.db
do_execsql_test 1.0 {
PRAGMA journal_mode = wal;
CREATE TABLE t1(a, b);
INSERT INTO t1 VALUES(1, 2);
} {wal}
do_test 1.1 { execsql { SELECT * FROM t1 } db2 } {1 2}
do_test 1.2 { execsql { SELECT * FROM t1 } db3 } {1 2}
foreach {tn dbhandle cmd res} {
1 db {shared lock 7 1} OK
2 db2 {exclusive lock 7 1} BUSY
3 db {shared unlock 7 1} OK
4 db2 {exclusive lock 7 1} OK
5 db {shared lock 7 1} BUSY
6 db {exclusive lock 7 1} BUSY
7 db2 {exclusive unlock 7 1} OK
8 db {exclusive lock 0 8} OK
9 db {exclusive unlock 0 8} OK
10 db2 {exclusive lock 0 8} OK
11 db2 {exclusive unlock 0 8} OK
12 db {shared lock 0 1} OK
13 db2 {shared lock 0 1} OK
14 db3 {shared lock 0 1} OK
15 db3 {shared unlock 0 1} OK
16 db3 {exclusive lock 0 1} BUSY
17 db2 {shared unlock 0 1} OK
18 db3 {exclusive lock 0 1} BUSY
19 db {shared unlock 0 1} OK
20 db3 {exclusive lock 0 1} OK
21 db3 {exclusive unlock 0 1} OK
22 db {shared lock 3 1} OK
23 db2 {exclusive lock 2 2} BUSY
24 db {shared lock 2 1} OK
25 db2 {exclusive lock 0 5} BUSY
26 db2 {exclusive lock 0 4} BUSY
27 db2 {exclusive lock 0 3} BUSY
28 db {shared unlock 3 1} OK
29 db2 {exclusive lock 2 2} BUSY
28 db {shared unlock 2 1} OK
29 db2 {exclusive lock 2 2} OK
29 db2 {exclusive unlock 2 2} OK
} {
do_test 1.3.$tn [list vfs_shmlock $dbhandle main {*}$cmd] "SQLITE_$res"
}
db close
db2 close
db3 close
if {[permutation]=="unix-excl"} {
do_test 2.0 {
for {set i 0} {$i < 256} {incr i} {
sqlite3 db$i test.db
execsql { SELECT * FROM t1 } db$i
}
for {set i 0} {$i < 255} {incr i} {
set rc [vfs_shmlock db$i main shared lock 4 1]
if {$rc != "SQLITE_OK"} { error $rc }
}
vfs_shmlock db255 main shared lock 4 1
} {SQLITE_BUSY}
do_test 2.1 { vfs_shmlock db255 main exclusive lock 4 1 } SQLITE_BUSY
do_test 2.2 { vfs_shmlock db0 main shared unlock 4 1 } SQLITE_OK
do_test 2.3 { vfs_shmlock db255 main shared lock 4 1 } SQLITE_OK
do_test 2.4 { vfs_shmlock db255 main shared unlock 4 1 } SQLITE_OK
do_test 2.5 { vfs_shmlock db255 main exclusive lock 4 1 } SQLITE_BUSY
do_test 2.6 {
for {set i 1} {$i < 255} {incr i} {
set rc [vfs_shmlock db255 main exclusive lock 4 1]
if {$rc != "SQLITE_BUSY"} { error $rc }
set rc [vfs_shmlock db$i main shared unlock 4 1]
if {$rc != "SQLITE_OK"} { error $rc }
}
vfs_shmlock db255 main exclusive lock 4 1
} {SQLITE_OK}
vfs_shmlock db255 main exclusive unlock 4 1
for {set i 0} {$i < 256} {incr i} {
db$i close
}
}
sqlite3 db0 test.db
sqlite3 db1 test.db
do_test 3.1 { execsql { SELECT * FROM t1 } db0 } {1 2}
do_test 3.2 { execsql { SELECT * FROM t1 } db1 } {1 2}
if {$tcl_platform(os) eq "Windows NT"} {
set isWindows 1
} else {
set isWindows 0
}
set L(0) {n n n n n n n n}
set L(1) {n n n n n n n n}
proc random_lock_test {idx} {
global L
set iSlot [expr int(rand()*8)]
if {[expr int(rand()*2)]} {
# Unlock operation
if {[lindex $L($idx) $iSlot]!="n"} {
vfs_shmlock db$idx main [lindex $L($idx) $iSlot] unlock $iSlot 1
lset L($idx) $iSlot n
}
} else {
# Lock operation
if {[lindex $L($idx) $iSlot]=="n"} {
set locktype [lindex {e s} [expr int(rand()*2)]]
set n 1
if {$locktype=="e"} {
for {set l $iSlot} {$l<8 && [lindex $L($idx) $l]=="n"} {incr l} {}
set n [expr int(rand()*($l-$iSlot))+1]
# The LockFile() and UnlockFile() apis on windows require that
# every unlock correspond exactly to a prior lock. Hence, we cannot
# lock arbitrary ranges in this test on windows.
if {$::isWindows} {set n 1}
# puts "iSlot=$iSlot l=$l L=$L($idx)"
# puts "$iSlot $n"
}
set res [vfs_shmlock db$idx main $locktype lock $iSlot $n]
set bBusy 0
for {set i $iSlot} {$i<($iSlot+$n)} {incr i} {
set other [lindex $L([expr ($idx+1)%2]) $i]
if {($other!="n" && $locktype=="e")||($other=="e" && $locktype=="s")} {
if {$res != "SQLITE_BUSY"} { error "BUSY not detected" }
set bBusy 1
break
}
}
if {$bBusy==0} {
if {$res != "SQLITE_OK"} { error "BUSY false-positive" }
for {set i $iSlot} {$i<($iSlot+$n)} {incr i} {
lset L($idx) $i $locktype
}
}
}
}
}
set nStep 100000
for {set i 0} {$i < $nStep} {incr i} {
random_lock_test 0
random_lock_test 1
}
db0 close
db1 close
finish_test
|