1# 2014 December 04 2# 3# The author disclaims copyright to this source code. In place of 4# a legal notice, here is a blessing: 5# 6# May you do good and not evil. 7# May you find forgiveness for yourself and forgive others. 8# May you share freely, never taking more than you give. 9# 10#*********************************************************************** 11# 12 13set testdir [file dirname $argv0] 14source $testdir/tester.tcl 15source $testdir/wal_common.tcl 16set testprefix e_walauto 17 18# Do not run this test on OpenBSD, as it depends on read() and mmap both 19# accessing the same coherent view of the "test.db-shm" file. This doesn't 20# work on OpenBSD. 21# 22if {$tcl_platform(os) == "OpenBSD"} { 23 finish_test 24 return 25} 26 27proc read_nbackfill {} { 28 seek $::shmfd 96 29 binary scan [read $::shmfd 4] n nBackfill 30 set nBackfill 31} 32proc read_mxframe {} { 33 seek $::shmfd 16 34 binary scan [read $::shmfd 4] n mxFrame 35 set mxFrame 36} 37 38# Assuming that the main db for database handle 39# 40proc do_autocommit_threshold_test {tn value} { 41 42 set nBackfillSaved [read_nbackfill] 43 while {1} { 44 db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) } 45 if {[read_mxframe] >= $value} break 46 } 47 48 set nBackfillNew [read_nbackfill] 49 uplevel [list do_test $tn "expr $nBackfillNew > $nBackfillSaved" 1] 50} 51 52# EVIDENCE-OF: R-30135-06439 The wal_autocheckpoint pragma can be used 53# to invoke this interface from SQL. 54# 55# All tests in this file are run twice - once using the 56# sqlite3_wal_autocheckpoint() API, and once using "PRAGMA 57# wal_autocheckpoint". 58# 59foreach {tn code} { 60 1 { 61 proc autocheckpoint {db value} { 62 uplevel [list $db eval "PRAGMA wal_autocheckpoint = $value"] 63 } 64 } 65 66 2 { 67 proc autocheckpoint {db value} { 68 uplevel [list sqlite3_wal_autocheckpoint $db $value] 69 return $value 70 } 71 } 72} { 73 74 eval $code 75 76 reset_db 77 execsql { PRAGMA auto_vacuum = 0 } 78 do_execsql_test 1.$tn.0 { PRAGMA journal_mode = WAL } {wal} 79 do_execsql_test 1.$tn.1 { CREATE TABLE t1(a, b) } 80 set shmfd [open "test.db-shm" rb] 81 82 # EVIDENCE-OF: R-41531-51083 Every new database connection defaults to 83 # having the auto-checkpoint enabled with a threshold of 1000 or 84 # SQLITE_DEFAULT_WAL_AUTOCHECKPOINT pages. 85 # 86 do_autocommit_threshold_test 1.$tn.2 1000 87 db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) } 88 do_autocommit_threshold_test 1.$tn.3 1000 89 90 # EVIDENCE-OF: R-38128-34102 The sqlite3_wal_autocheckpoint(D,N) is a 91 # wrapper around sqlite3_wal_hook() that causes any database on database 92 # connection D to automatically checkpoint after committing a 93 # transaction if there are N or more frames in the write-ahead log file. 94 # 95 do_test 1.$tn.4 { 96 db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) } 97 autocheckpoint db 100 98 } {100} 99 do_autocommit_threshold_test 1.$tn.5 100 100 101 do_test 1.$tn.6 { 102 db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) } 103 autocheckpoint db 500 104 } {500} 105 do_autocommit_threshold_test 1.$tn.7 500 106 107 # EVIDENCE-OF: R-26993-43540 Passing zero or a negative value as the 108 # nFrame parameter disables automatic checkpoints entirely. 109 # 110 do_test 1.$tn.7 { 111 autocheckpoint db 0 ;# Set to zero 112 for {set i 0} {$i < 10000} {incr i} { 113 db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) } 114 } 115 expr {[file size test.db-wal] > (5 * 1024 * 1024)} 116 } 1 117 do_test 1.$tn.8 { 118 sqlite3_wal_checkpoint_v2 db truncate 119 file size test.db-wal 120 } 0 121 do_test 1.$tn.9 { 122 autocheckpoint db -4 ;# Set to a negative value 123 for {set i 0} {$i < 10000} {incr i} { 124 db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) } 125 } 126 expr {[file size test.db-wal] > (5 * 1024 * 1024)} 127 } 1 128 129 # EVIDENCE-OF: R-10203-42688 The callback registered by this function 130 # replaces any existing callback registered using sqlite3_wal_hook(). 131 # 132 set ::wal_hook_callback 0 133 proc wal_hook_callback {args} { incr ::wal_hook_callback ; return 0 } 134 do_test 1.$tn.10.1 { 135 db wal_hook wal_hook_callback 136 db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) } 137 db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) } 138 set ::wal_hook_callback 139 } 2 140 do_test 1.$tn.10.2 { 141 autocheckpoint db 100 142 db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) } 143 db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) } 144 set ::wal_hook_callback 145 } 2 146 147 # EVIDENCE-OF: R-17497-43474 Likewise, registering a callback using 148 # sqlite3_wal_hook() disables the automatic checkpoint mechanism 149 # configured by this function. 150 do_test 1.$tn.11.1 { 151 sqlite3_wal_checkpoint_v2 db truncate 152 file size test.db-wal 153 } 0 154 do_test 1.$tn.11.2 { 155 autocheckpoint db 100 156 for {set i 0} {$i < 1000} {incr i} { 157 db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) } 158 } 159 expr {[file size test.db-wal] < (1 * 1024 * 1024)} 160 } 1 161 do_test 1.$tn.11.3 { 162 db wal_hook wal_hook_callback 163 for {set i 0} {$i < 1000} {incr i} { 164 db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) } 165 } 166 expr {[file size test.db-wal] < (1 * 1024 * 1024)} 167 } 0 168 169 # EVIDENCE-OF: R-33080-59193 Checkpoints initiated by this mechanism 170 # are PASSIVE. 171 # 172 set ::busy_callback_count 0 173 proc busy_callback {args} { 174 incr ::busy_callback_count 175 return 0 176 } 177 do_test 1.$tn.12.1 { 178 sqlite3_wal_checkpoint_v2 db truncate 179 autocheckpoint db 100 180 db busy busy_callback 181 db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) } 182 db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) } 183 } {} 184 do_test 1.$tn.12.2 { 185 sqlite3 db2 test.db 186 db2 eval { BEGIN; SELECT * FROM t1 LIMIT 10; } 187 read_nbackfill 188 } {0} 189 do_test 1.$tn.12.3 { 190 for {set i 0} {$i < 1000} {incr i} { 191 db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) } 192 } 193 read_nbackfill 194 } {2} 195 do_test 1.$tn.12.4 { 196 set ::busy_callback_count 197 } {0} 198 db2 close 199 200 do_test 1.$tn.12.5 { 201 db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) } 202 read_nbackfill 203 } {1559} 204 205 db close 206 close $shmfd 207} 208 209finish_test 210