1bb5f18d2Sdrh# 2007 April 6 2bb5f18d2Sdrh# 3bb5f18d2Sdrh# The author disclaims copyright to this source code. In place of 4bb5f18d2Sdrh# a legal notice, here is a blessing: 5bb5f18d2Sdrh# 6bb5f18d2Sdrh# May you do good and not evil. 7bb5f18d2Sdrh# May you find forgiveness for yourself and forgive others. 8bb5f18d2Sdrh# May you share freely, never taking more than you give. 9bb5f18d2Sdrh# 10bb5f18d2Sdrh#*********************************************************************** 11bb5f18d2Sdrh# This file implements regression tests for SQLite library. The 12bb5f18d2Sdrh# focus of this script is database locks. 13bb5f18d2Sdrh# 14310bd20aSdrh# $Id: lock4.test,v 1.10 2009/05/06 00:52:41 drh Exp $ 15bb5f18d2Sdrh 16bb5f18d2Sdrh 17bb5f18d2Sdrhset testdir [file dirname $argv0] 18bb5f18d2Sdrhsource $testdir/tester.tcl 19bb5f18d2Sdrh 20*69aedc8dSdanif {[atomic_batch_write test.db]} { 21*69aedc8dSdan # This test uses two processes, one of which blocks until the other 22*69aedc8dSdan # creates a *-journal file. Which doesn't work if atomic writes are 23*69aedc8dSdan # available. 24*69aedc8dSdan finish_test 25*69aedc8dSdan return 26*69aedc8dSdan} 27*69aedc8dSdan 2868928b6cSdando_not_use_codec 2968928b6cSdan 30bb5f18d2Sdrh# Initialize the test.db database so that it is non-empty 31bb5f18d2Sdrh# 32bb5f18d2Sdrhdo_test lock4-1.1 { 331e9daa6aSdrh db eval { 341e9daa6aSdrh PRAGMA auto_vacuum=OFF; 351e9daa6aSdrh CREATE TABLE t1(x); 361e9daa6aSdrh } 37fda06befSmistachkin forcedelete test2.db test2.db-journal 38bb5f18d2Sdrh sqlite3 db2 test2.db 391e9daa6aSdrh db2 eval { 401e9daa6aSdrh PRAGMA auto_vacuum=OFF; 411e9daa6aSdrh CREATE TABLE t2(x) 421e9daa6aSdrh } 43bb5f18d2Sdrh db2 close 44bb5f18d2Sdrh list [file size test.db] [file size test2.db] 45bb5f18d2Sdrh} {2048 2048} 46bb5f18d2Sdrh 47bb5f18d2Sdrh# Create a script to drive a separate process that will 48bb5f18d2Sdrh# 49bb5f18d2Sdrh# 1. Create a second database test2.db 50bb5f18d2Sdrh# 2. Get an exclusive lock on test2.db 51bb5f18d2Sdrh# 3. Add an entry to test.db in table t1, waiting as necessary. 52bb5f18d2Sdrh# 4. Commit the change to test2.db. 53bb5f18d2Sdrh# 54bb5f18d2Sdrh# Meanwhile, this process will: 55bb5f18d2Sdrh# 56bb5f18d2Sdrh# A. Get an exclusive lock on test.db 57bb5f18d2Sdrh# B. Attempt to read from test2.db but get an SQLITE_BUSY error. 58bb5f18d2Sdrh# C. Commit the changes to test.db thus alloing the other process 59bb5f18d2Sdrh# to continue. 60bb5f18d2Sdrh# 61bb5f18d2Sdrhdo_test lock4-1.2 { 62d5fe8d6cSdanielk1977 63d5fe8d6cSdanielk1977 # Create a script for the second process to run. 64d5fe8d6cSdanielk1977 # 65bb5f18d2Sdrh set out [open test2-script.tcl w] 66c7a3bb94Sdrh puts $out "sqlite3_test_control_pending_byte [set sqlite_pending_byte]" 67bb5f18d2Sdrh puts $out { 68bb5f18d2Sdrh sqlite3 db2 test2.db 69bb5f18d2Sdrh db2 eval { 70bb5f18d2Sdrh BEGIN; 71bb5f18d2Sdrh INSERT INTO t2 VALUES(2); 72bb5f18d2Sdrh } 73bb5f18d2Sdrh sqlite3 db test.db 74bb5f18d2Sdrh db timeout 1000000 75bb5f18d2Sdrh db eval { 76bb5f18d2Sdrh INSERT INTO t1 VALUES(2); 77bb5f18d2Sdrh } 784ffb7b9aSdanielk1977 db close 79bb5f18d2Sdrh db2 eval COMMIT 80bb5f18d2Sdrh exit 81bb5f18d2Sdrh } 82bb5f18d2Sdrh close $out 83d5fe8d6cSdanielk1977 84d5fe8d6cSdanielk1977 # Begin a transaction on test.db. 85bb5f18d2Sdrh db eval { 86d5fe8d6cSdanielk1977 BEGIN EXCLUSIVE; 87bb5f18d2Sdrh INSERT INTO t1 VALUES(1); 88bb5f18d2Sdrh } 89d5fe8d6cSdanielk1977 90d5fe8d6cSdanielk1977 # Kick off the second process. 91bb5f18d2Sdrh exec [info nameofexec] ./test2-script.tcl & 92d5fe8d6cSdanielk1977 93d5fe8d6cSdanielk1977 # Wait until the second process has started its transaction on test2.db. 94bb5f18d2Sdrh while {![file exists test2.db-journal]} { 95bb5f18d2Sdrh after 10 96bb5f18d2Sdrh } 97d5fe8d6cSdanielk1977 98d5fe8d6cSdanielk1977 # Try to write to test2.db. We are locked out. 99bb5f18d2Sdrh sqlite3 db2 test2.db 100bb5f18d2Sdrh catchsql { 101bb5f18d2Sdrh INSERT INTO t2 VALUES(1) 102bb5f18d2Sdrh } db2 103bb5f18d2Sdrh} {1 {database is locked}} 104bb5f18d2Sdrhdo_test lock4-1.3 { 105bb5f18d2Sdrh db eval { 106bb5f18d2Sdrh COMMIT; 107bb5f18d2Sdrh } 108bb5f18d2Sdrh while {[file exists test2.db-journal]} { 109bb5f18d2Sdrh after 10 110bb5f18d2Sdrh } 111d5fe8d6cSdanielk1977 # The other process has committed its transaction on test2.db by 112d5fe8d6cSdanielk1977 # deleting the journal file. But it might retain the lock for a 113d5fe8d6cSdanielk1977 # fraction longer 114d5fe8d6cSdanielk1977 # 115310bd20aSdrh after 25 116bb5f18d2Sdrh db2 eval { 117bb5f18d2Sdrh SELECT * FROM t2 118bb5f18d2Sdrh } 119bb5f18d2Sdrh} {2} 120bb5f18d2Sdrh 121bb5f18d2Sdrh 122bb5f18d2Sdrhdo_test lock4-999.1 { 123bb5f18d2Sdrh rename db2 {} 124bb5f18d2Sdrh} {} 125bb5f18d2Sdrh 126bb5f18d2Sdrhfinish_test 127