mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-30 19:03:16 +03:00
Added support for proxy file locking style
Added pragma support for controlling proxy file locking Added file control access to last errno and proxy locking Added support for TMPDIR environment variable Extended unit tests to cover new proxy locking pragmas and file control features (CVS 5934) FossilOrigin-Name: b9bc36d3d5e35821ef69c0881a84c0afed253c9e
This commit is contained in:
@ -12,7 +12,7 @@
|
||||
# of these tests is exclusive access mode (i.e. the thing activated by
|
||||
# "PRAGMA locking_mode = EXCLUSIVE").
|
||||
#
|
||||
# $Id: exclusive.test,v 1.9 2008/09/24 14:03:43 danielk1977 Exp $
|
||||
# $Id: exclusive.test,v 1.10 2008/11/21 00:10:35 aswift Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@ -402,6 +402,17 @@ do_test exclusive-4.5 {
|
||||
db close
|
||||
sqlite db test.db
|
||||
|
||||
# if we're using proxy locks, we use 3 filedescriptors for a db
|
||||
# that is open but NOT writing changes, normally
|
||||
# sqlite uses 1 (proxy locking adds the conch and the local lock)
|
||||
set using_proxy 0
|
||||
foreach {name value} [array get env SQLITE_FORCE_PROXY_LOCKING] {
|
||||
set using_proxy $value
|
||||
}
|
||||
set extrafds 0
|
||||
if {$using_proxy!=0} {
|
||||
set extrafds 2
|
||||
}
|
||||
|
||||
do_test exclusive-5.0 {
|
||||
execsql {
|
||||
@ -414,6 +425,7 @@ do_test exclusive-5.0 {
|
||||
do_test exclusive-5.1 {
|
||||
# Three files are open: The db, journal and statement-journal.
|
||||
set sqlite_open_file_count
|
||||
expr $sqlite_open_file_count-$extrafds
|
||||
} {3}
|
||||
do_test exclusive-5.2 {
|
||||
execsql {
|
||||
@ -421,6 +433,7 @@ do_test exclusive-5.2 {
|
||||
}
|
||||
# One file open: the db.
|
||||
set sqlite_open_file_count
|
||||
expr $sqlite_open_file_count-$extrafds
|
||||
} {1}
|
||||
do_test exclusive-5.3 {
|
||||
execsql {
|
||||
@ -430,6 +443,7 @@ do_test exclusive-5.3 {
|
||||
}
|
||||
# Two files open: the db and journal.
|
||||
set sqlite_open_file_count
|
||||
expr $sqlite_open_file_count-$extrafds
|
||||
} {2}
|
||||
do_test exclusive-5.4 {
|
||||
execsql {
|
||||
@ -437,6 +451,7 @@ do_test exclusive-5.4 {
|
||||
}
|
||||
# Three files are open: The db, journal and statement-journal.
|
||||
set sqlite_open_file_count
|
||||
expr $sqlite_open_file_count-$extrafds
|
||||
} {3}
|
||||
do_test exclusive-5.5 {
|
||||
execsql {
|
||||
@ -444,6 +459,7 @@ do_test exclusive-5.5 {
|
||||
}
|
||||
# Three files are still open: The db, journal and statement-journal.
|
||||
set sqlite_open_file_count
|
||||
expr $sqlite_open_file_count-$extrafds
|
||||
} {3}
|
||||
do_test exclusive-5.6 {
|
||||
execsql {
|
||||
@ -454,6 +470,7 @@ do_test exclusive-5.6 {
|
||||
do_test exclusive-5.7 {
|
||||
# Just the db open.
|
||||
set sqlite_open_file_count
|
||||
expr $sqlite_open_file_count-$extrafds
|
||||
} {1}
|
||||
|
||||
finish_test
|
||||
|
@ -9,7 +9,7 @@
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# $Id: filectrl.test,v 1.1 2008/01/22 14:50:17 drh Exp $
|
||||
# $Id: filectrl.test,v 1.2 2008/11/21 00:10:35 aswift Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@ -27,5 +27,15 @@ do_test filectrl-1.3 {
|
||||
sqlite3 db :memory:
|
||||
file_control_test db
|
||||
} {}
|
||||
|
||||
do_test filectrl-1.4 {
|
||||
sqlite3 db test.db
|
||||
file_control_lasterrno_test db
|
||||
} {}
|
||||
do_test filectrl-1.5 {
|
||||
db close
|
||||
sqlite3 db test_control_lockproxy.db
|
||||
file_control_lockproxy_test db
|
||||
} {}
|
||||
db close
|
||||
file delete -force .test_control_lockproxy.db-conch test.proxy
|
||||
finish_test
|
||||
|
@ -11,7 +11,7 @@
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this script is database locks.
|
||||
#
|
||||
# $Id: lock5.test,v 1.3 2008/09/24 09:12:47 danielk1977 Exp $
|
||||
# $Id: lock5.test,v 1.4 2008/11/21 00:10:35 aswift Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@ -25,6 +25,16 @@ if {[catch {sqlite3 db test.db -vfs unix-none} msg]} {
|
||||
}
|
||||
db close
|
||||
|
||||
ifcapable lock_proxy_pragmas {
|
||||
set ::using_proxy 0
|
||||
foreach {name value} [array get env SQLITE_FORCE_PROXY_LOCKING] {
|
||||
set ::using_proxy $value
|
||||
}
|
||||
# Disable the proxy locking for these tests
|
||||
set env(SQLITE_FORCE_PROXY_LOCKING) "0"
|
||||
}
|
||||
|
||||
|
||||
do_test lock5-dotfile.1 {
|
||||
sqlite3 db test.db -vfs unix-dotfile
|
||||
execsql {
|
||||
@ -173,4 +183,8 @@ do_test lock5-flock.X {
|
||||
db2 close
|
||||
} {}
|
||||
|
||||
ifcapable lock_proxy_pragmas {
|
||||
set env(SQLITE_FORCE_PROXY_LOCKING) $::using_proxy
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
168
test/lock6.test
Normal file
168
test/lock6.test
Normal file
@ -0,0 +1,168 @@
|
||||
# 2008 October 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this script is database locks.
|
||||
#
|
||||
# $Id: lock6.test,v 1.1 2008/11/21 00:10:35 aswift Exp $
|
||||
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
# Launch another testfixture process to be controlled by this one. A
|
||||
# channel name is returned that may be passed as the first argument to proc
|
||||
# 'testfixture' to execute a command. The child testfixture process is shut
|
||||
# down by closing the channel.
|
||||
proc launch_testfixture {} {
|
||||
set prg [info nameofexec]
|
||||
if {$prg eq ""} {
|
||||
set prg [file join . testfixture]
|
||||
}
|
||||
set chan [open "|$prg tf_main2.tcl" r+]
|
||||
fconfigure $chan -buffering line
|
||||
return $chan
|
||||
}
|
||||
|
||||
# Execute a command in a child testfixture process, connected by two-way
|
||||
# channel $chan. Return the result of the command, or an error message.
|
||||
proc testfixture {chan cmd} {
|
||||
puts $chan $cmd
|
||||
puts $chan OVER
|
||||
set r ""
|
||||
while { 1 } {
|
||||
set line [gets $chan]
|
||||
if { $line == "OVER" } {
|
||||
return $r
|
||||
}
|
||||
append r $line
|
||||
}
|
||||
}
|
||||
|
||||
# Write the main loop for the child testfixture processes into file
|
||||
# tf_main2.tcl. The parent (this script) interacts with the child processes
|
||||
# via a two way pipe. The parent writes a script to the stdin of the child
|
||||
# process, followed by the word "OVER" on a line of its own. The child
|
||||
# process evaluates the script and writes the results to stdout, followed
|
||||
# by an "OVER" of its own.
|
||||
set f [open tf_main2.tcl w]
|
||||
puts $f {
|
||||
set l [open log w]
|
||||
set script ""
|
||||
while {![eof stdin]} {
|
||||
flush stdout
|
||||
set line [gets stdin]
|
||||
puts $l "READ $line"
|
||||
if { $line == "OVER" } {
|
||||
catch {eval $script} result
|
||||
puts $result
|
||||
puts $l "WRITE $result"
|
||||
puts OVER
|
||||
puts $l "WRITE OVER"
|
||||
flush stdout
|
||||
set script ""
|
||||
} else {
|
||||
append script $line
|
||||
append script " ; "
|
||||
}
|
||||
}
|
||||
close $l
|
||||
}
|
||||
close $f
|
||||
|
||||
|
||||
ifcapable lock_proxy_pragmas {
|
||||
set sqlite_hostid_num 1
|
||||
|
||||
set using_proxy 0
|
||||
foreach {name value} [array get env SQLITE_FORCE_PROXY_LOCKING] {
|
||||
set using_proxy $value
|
||||
}
|
||||
|
||||
# Test the lock_proxy_file pragmas.
|
||||
#
|
||||
set env(SQLITE_FORCE_PROXY_LOCKING) "1"
|
||||
|
||||
do_test lock6-1.1 {
|
||||
set ::tf1 [launch_testfixture]
|
||||
testfixture $::tf1 "set sqlite_pending_byte $::sqlite_pending_byte"
|
||||
testfixture $::tf1 {
|
||||
set sqlite_hostid_num 2
|
||||
sqlite3 db test.db -key xyzzy
|
||||
set lockpath [db eval {
|
||||
PRAGMA lock_proxy_file=":auto:";
|
||||
select * from sqlite_master;
|
||||
PRAGMA lock_proxy_file;
|
||||
}]
|
||||
string match "*test.db:auto:" $lockpath
|
||||
}
|
||||
} {1}
|
||||
|
||||
set sqlite_hostid_num 3
|
||||
do_test lock6-1.2 {
|
||||
execsql {pragma lock_status}
|
||||
} {main unlocked temp closed}
|
||||
|
||||
sqlite3_soft_heap_limit 0
|
||||
do_test lock6-1.3 {
|
||||
sqlite3 db test.db
|
||||
catchsql {
|
||||
select * from sqlite_master;
|
||||
}
|
||||
} {1 {database is locked}}
|
||||
|
||||
do_test lock6-1.4 {
|
||||
set lockpath [execsql {
|
||||
PRAGMA lock_proxy_file=":auto:";
|
||||
PRAGMA lock_proxy_file;
|
||||
} db]
|
||||
set lockpath
|
||||
} {{:auto: (not held)}}
|
||||
|
||||
do_test lock6-1.4.1 {
|
||||
catchsql {
|
||||
PRAGMA lock_proxy_file="notmine";
|
||||
select * from sqlite_master;
|
||||
} db
|
||||
} {1 {database is locked}}
|
||||
|
||||
do_test lock6-1.4.2 {
|
||||
execsql {
|
||||
PRAGMA lock_proxy_file;
|
||||
} db
|
||||
} {notmine}
|
||||
|
||||
do_test lock6-1.5 {
|
||||
testfixture $::tf1 {
|
||||
db eval {
|
||||
BEGIN;
|
||||
SELECT * FROM sqlite_master;
|
||||
}
|
||||
}
|
||||
} {}
|
||||
|
||||
catch {testfixture $::tf1 {db close}}
|
||||
|
||||
do_test lock6-1.6 {
|
||||
execsql {
|
||||
PRAGMA lock_proxy_file="mine";
|
||||
select * from sqlite_master;
|
||||
} db
|
||||
} {}
|
||||
|
||||
catch {close $::tf1}
|
||||
set env(SQLITE_FORCE_PROXY_LOCKING) $using_proxy
|
||||
set sqlite_hostid_num 0
|
||||
|
||||
sqlite3_soft_heap_limit $soft_limit
|
||||
|
||||
}
|
||||
|
||||
finish_test
|
@ -13,12 +13,23 @@
|
||||
# This file implements tests the ability of the library to open
|
||||
# many different databases at the same time without leaking memory.
|
||||
#
|
||||
# $Id: manydb.test,v 1.3 2006/01/11 01:08:34 drh Exp $
|
||||
# $Id: manydb.test,v 1.4 2008/11/21 00:10:35 aswift Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
set N 300
|
||||
# if we're using proxy locks, we use 5 filedescriptors for a db
|
||||
# that is open and in the middle of writing changes, normally
|
||||
# sqlite uses 3 (proxy locking adds the conch and the local lock)
|
||||
set using_proxy 0
|
||||
foreach {name value} [array get env SQLITE_FORCE_PROXY_LOCKING] {
|
||||
set using_proxy value
|
||||
}
|
||||
set num_fd_per_openwrite_db 3
|
||||
if {$using_proxy>0} {
|
||||
set num_fd_per_openwrite_db 5
|
||||
}
|
||||
|
||||
# First test how many file descriptors are available for use. To open a
|
||||
# database for writing SQLite requires 3 file descriptors (the database, the
|
||||
@ -35,7 +46,7 @@ foreach fd $filehandles {
|
||||
catch {
|
||||
file delete -force testfile.1
|
||||
}
|
||||
set N [expr $i / 3]
|
||||
set N [expr $i / $num_fd_per_openwrite_db]
|
||||
|
||||
# Create a bunch of random database names
|
||||
#
|
||||
|
133
test/pragma.test
133
test/pragma.test
@ -12,7 +12,7 @@
|
||||
#
|
||||
# This file implements tests for the PRAGMA command.
|
||||
#
|
||||
# $Id: pragma.test,v 1.69 2008/10/23 05:45:07 danielk1977 Exp $
|
||||
# $Id: pragma.test,v 1.70 2008/11/21 00:10:35 aswift Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@ -34,6 +34,7 @@ source $testdir/tester.tcl
|
||||
# pragma-14.*: Test the page_count pragma.
|
||||
# pragma-15.*: Test that the value set using the cache_size pragma is not
|
||||
# reset when the schema is reloaded.
|
||||
# pragma-16.*: Test proxy locking
|
||||
#
|
||||
|
||||
ifcapable !pragma {
|
||||
@ -1252,4 +1253,134 @@ sqlite3 dbX :memory:
|
||||
dbX eval {PRAGMA temp_store_directory = ""}
|
||||
dbX close
|
||||
|
||||
ifcapable lock_proxy_pragmas {
|
||||
set sqlite_hostid_num 1
|
||||
|
||||
set using_proxy 0
|
||||
foreach {name value} [array get env SQLITE_FORCE_PROXY_LOCKING] {
|
||||
set using_proxy $value
|
||||
}
|
||||
|
||||
# Test the lock_proxy_file pragmas.
|
||||
#
|
||||
db close
|
||||
set env(SQLITE_FORCE_PROXY_LOCKING) "0"
|
||||
|
||||
sqlite3 db test.db
|
||||
do_test pragma-16.1 {
|
||||
execsql {
|
||||
PRAGMA lock_proxy_file="mylittleproxy";
|
||||
select * from sqlite_master;
|
||||
}
|
||||
execsql {
|
||||
PRAGMA lock_proxy_file;
|
||||
}
|
||||
} {mylittleproxy}
|
||||
|
||||
do_test pragma-16.2 {
|
||||
sqlite3 db2 test.db
|
||||
execsql {
|
||||
PRAGMA lock_proxy_file="mylittleproxy";
|
||||
} db2
|
||||
} {}
|
||||
|
||||
db2 close
|
||||
do_test pragma-16.2.1 {
|
||||
sqlite3 db2 test.db
|
||||
execsql {
|
||||
PRAGMA lock_proxy_file=":auto:";
|
||||
select * from sqlite_master;
|
||||
} db2
|
||||
execsql {
|
||||
PRAGMA lock_proxy_file;
|
||||
} db2
|
||||
} {mylittleproxy}
|
||||
|
||||
db2 close
|
||||
do_test pragma-16.3 {
|
||||
sqlite3 db2 test.db
|
||||
execsql {
|
||||
PRAGMA lock_proxy_file="myotherproxy";
|
||||
} db2
|
||||
catchsql {
|
||||
select * from sqlite_master;
|
||||
} db2
|
||||
} {1 {database is locked}}
|
||||
|
||||
do_test pragma-16.4 {
|
||||
db2 close
|
||||
db close
|
||||
sqlite3 db2 test.db
|
||||
execsql {
|
||||
PRAGMA lock_proxy_file="myoriginalproxy";
|
||||
PRAGMA lock_proxy_file="myotherproxy";
|
||||
PRAGMA lock_proxy_file;
|
||||
} db2
|
||||
} {myotherproxy}
|
||||
|
||||
db2 close
|
||||
set env(SQLITE_FORCE_PROXY_LOCKING) "1"
|
||||
do_test pragma-16.5 {
|
||||
sqlite3 db2 test.db
|
||||
execsql {
|
||||
PRAGMA lock_proxy_file=":auto:";
|
||||
PRAGMA lock_proxy_file;
|
||||
} db2
|
||||
} {myotherproxy}
|
||||
|
||||
do_test pragma-16.6 {
|
||||
db2 close
|
||||
sqlite3 db2 test2.db
|
||||
set lockpath [execsql {
|
||||
PRAGMA lock_proxy_file=":auto:";
|
||||
PRAGMA lock_proxy_file;
|
||||
} db2]
|
||||
string match "*test2.db:auto:" $lockpath
|
||||
} {1}
|
||||
|
||||
set sqlite_hostid_num 2
|
||||
do_test pragma-16.7 {
|
||||
sqlite3 db test2.db
|
||||
execsql {
|
||||
PRAGMA lock_proxy_file=":auto:";
|
||||
}
|
||||
catchsql {
|
||||
select * from sqlite_master;
|
||||
}
|
||||
} {1 {database is locked}}
|
||||
db close
|
||||
|
||||
do_test pragma-16.8 {
|
||||
sqlite3 db test2.db
|
||||
catchsql {
|
||||
select * from sqlite_master;
|
||||
}
|
||||
} {1 {database is locked}}
|
||||
|
||||
db2 close
|
||||
do_test pragma-16.8.1 {
|
||||
execsql {
|
||||
PRAGMA lock_proxy_file="yetanotherproxy";
|
||||
PRAGMA lock_proxy_file;
|
||||
}
|
||||
} {yetanotherproxy}
|
||||
do_test pragma-16.8.2 {
|
||||
execsql {
|
||||
create table mine(x);
|
||||
}
|
||||
} {}
|
||||
|
||||
db close
|
||||
do_test pragma-16.9 {
|
||||
sqlite3 db proxytest.db
|
||||
set lockpath2 [execsql {
|
||||
PRAGMA lock_proxy_file=":auto:";
|
||||
PRAGMA lock_proxy_file;
|
||||
} db]
|
||||
string match "*proxytest.db:auto:" $lockpath2
|
||||
} {1}
|
||||
|
||||
set env(SQLITE_FORCE_PROXY_LOCKING) $using_proxy
|
||||
set sqlite_hostid_num 0
|
||||
}
|
||||
finish_test
|
||||
|
@ -9,7 +9,7 @@
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# $Id: shared.test,v 1.34 2008/07/12 14:52:20 drh Exp $
|
||||
# $Id: shared.test,v 1.35 2008/11/21 00:10:35 aswift Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@ -42,6 +42,20 @@ ifcapable autovacuum {
|
||||
}
|
||||
}
|
||||
|
||||
# if we're using proxy locks, we use 2 filedescriptors for a db
|
||||
# that is open but NOT yet locked, after a lock is taken we'll have 3,
|
||||
# normally sqlite uses 1 (proxy locking adds the conch and the local lock)
|
||||
set using_proxy 0
|
||||
foreach {name value} [array get env SQLITE_FORCE_PROXY_LOCKING] {
|
||||
set using_proxy $value
|
||||
}
|
||||
set extrafds_prelock 0
|
||||
set extrafds_postlock 0
|
||||
if {$using_proxy>0} {
|
||||
set extrafds_prelock 1
|
||||
set extrafds_postlock 2
|
||||
}
|
||||
|
||||
# $av is currently 0 if this loop iteration is to test with auto-vacuum turned
|
||||
# off, and 1 if it is turned on. Increment it so that (1 -> no auto-vacuum)
|
||||
# and (2 -> auto-vacuum). The sole reason for this is so that it looks nicer
|
||||
@ -74,6 +88,7 @@ do_test shared-$av.1.1 {
|
||||
# opened.
|
||||
sqlite3 db2 test.db
|
||||
set ::sqlite_open_file_count
|
||||
expr $sqlite_open_file_count-$extrafds_postlock
|
||||
} {1}
|
||||
do_test shared-$av.1.2 {
|
||||
# Add a table and a single row of data via the first connection.
|
||||
@ -154,6 +169,7 @@ do_test shared-$av.2.1 {
|
||||
sqlite3 db3 TEST.DB
|
||||
}
|
||||
set ::sqlite_open_file_count
|
||||
expr $sqlite_open_file_count-($extrafds_prelock+$extrafds_postlock)
|
||||
} {2}
|
||||
do_test shared-$av.2.2 {
|
||||
# Start read transactions on db and db2 (the shared pager cache). Ensure
|
||||
@ -284,14 +300,17 @@ sqlite3 db test.db
|
||||
sqlite3 db2 test2.db
|
||||
do_test shared-$av.4.1.1 {
|
||||
set sqlite_open_file_count
|
||||
expr $sqlite_open_file_count-($extrafds_prelock*2)
|
||||
} {2}
|
||||
do_test shared-$av.4.1.2 {
|
||||
execsql {ATTACH 'test2.db' AS test2}
|
||||
set sqlite_open_file_count
|
||||
expr $sqlite_open_file_count-($extrafds_postlock*2)
|
||||
} {2}
|
||||
do_test shared-$av.4.1.3 {
|
||||
execsql {ATTACH 'test.db' AS test} db2
|
||||
set sqlite_open_file_count
|
||||
expr $sqlite_open_file_count-($extrafds_postlock*2)
|
||||
} {2}
|
||||
|
||||
# Sanity check: Create a table in ./test.db via handle db, and test that handle
|
||||
|
@ -11,7 +11,7 @@
|
||||
# This file implements some common TCL routines used for regression
|
||||
# testing the SQLite library
|
||||
#
|
||||
# $Id: tester.tcl,v 1.134 2008/08/05 17:53:24 drh Exp $
|
||||
# $Id: tester.tcl,v 1.135 2008/11/21 00:10:35 aswift Exp $
|
||||
|
||||
#
|
||||
# What for user input before continuing. This gives an opportunity
|
||||
@ -659,6 +659,7 @@ proc do_ioerr_test {testname args} {
|
||||
do_test $testname.$n.1 {
|
||||
set ::sqlite_io_error_pending 0
|
||||
catch {db close}
|
||||
catch {db2 close}
|
||||
catch {file delete -force test.db}
|
||||
catch {file delete -force test.db-journal}
|
||||
catch {file delete -force test2.db}
|
||||
|
Reference in New Issue
Block a user