xref: /sqlite-3.40.0/test/wal5.test (revision 82f52540)
1a58f26f9Sdan# 2010 April 13
2a58f26f9Sdan#
3a58f26f9Sdan# The author disclaims copyright to this source code.  In place of
4a58f26f9Sdan# a legal notice, here is a blessing:
5a58f26f9Sdan#
6a58f26f9Sdan#    May you do good and not evil.
7a58f26f9Sdan#    May you find forgiveness for yourself and forgive others.
8a58f26f9Sdan#    May you share freely, never taking more than you give.
9a58f26f9Sdan#
10a58f26f9Sdan#***********************************************************************
11a58f26f9Sdan# This file implements regression tests for SQLite library.  The
12a58f26f9Sdan# focus of this file is testing the operation of "blocking-checkpoint"
13a58f26f9Sdan# operations.
14a58f26f9Sdan#
15a58f26f9Sdan
16a58f26f9Sdanset testdir [file dirname $argv0]
17a58f26f9Sdansource $testdir/tester.tcl
18a58f26f9Sdansource $testdir/lock_common.tcl
19a58f26f9Sdansource $testdir/wal_common.tcl
20a58f26f9Sdanifcapable !wal {finish_test ; return }
217da56b4fSdrhdo_not_use_codec
22a58f26f9Sdan
23a58f26f9Sdanset testprefix wal5
24a58f26f9Sdan
25f2b8dd58Sdanproc db_page_count  {{file test.db}} { expr [file size $file] / 1024 }
26f2b8dd58Sdanproc wal_page_count {{file test.db}} { wal_frame_count ${file}-wal 1024 }
27f2b8dd58Sdan
28f2b8dd58Sdan
299c5e3680Sdan# A checkpoint may be requested either using the C API or by executing
309c5e3680Sdan# an SQL PRAGMA command. To test both methods, all tests in this file are
319c5e3680Sdan# run twice - once using each method to request checkpoints.
329c5e3680Sdan#
339c5e3680Sdanforeach {testprefix do_wal_checkpoint} {
34a58f26f9Sdan
359c5e3680Sdan  wal5-pragma {
369c5e3680Sdan    proc do_wal_checkpoint { dbhandle args } {
379c5e3680Sdan      array set a $args
389c5e3680Sdan      foreach key [array names a] {
399c5e3680Sdan        if {[lsearch {-mode -db} $key]<0} { error "unknown switch: $key" }
409c5e3680Sdan      }
419c5e3680Sdan
429c5e3680Sdan      set sql "PRAGMA "
439c5e3680Sdan      if {[info exists a(-db)]} { append sql "$a(-db)." }
449c5e3680Sdan      append sql "wal_checkpoint"
459c5e3680Sdan      if {[info exists a(-mode)]} { append sql " = $a(-mode)" }
469c5e3680Sdan
479c5e3680Sdan      uplevel [list $dbhandle eval $sql]
489c5e3680Sdan    }
499c5e3680Sdan  }
509c5e3680Sdan
519c5e3680Sdan  wal5-capi {
529c5e3680Sdan    proc do_wal_checkpoint { dbhandle args } {
539c5e3680Sdan      set a(-mode) passive
549c5e3680Sdan      array set a $args
559c5e3680Sdan      foreach key [array names a] {
569c5e3680Sdan        if {[lsearch {-mode -db} $key]<0} { error "unknown switch: $key" }
579c5e3680Sdan      }
589c5e3680Sdan
59f26a1549Sdan      set vals {restart full truncate}
60f26a1549Sdan      if {[lsearch -exact $vals $a(-mode)]<0} { set a(-mode) passive }
619c5e3680Sdan
629c5e3680Sdan      set cmd [list sqlite3_wal_checkpoint_v2 $dbhandle $a(-mode)]
639c5e3680Sdan      if {[info exists a(-db)]} { lappend sql $a(-db) }
649c5e3680Sdan
659c5e3680Sdan      uplevel $cmd
669c5e3680Sdan    }
679c5e3680Sdan  }
689c5e3680Sdan} {
699c5e3680Sdan
709c5e3680Sdan  eval $do_wal_checkpoint
719c5e3680Sdan
729c5e3680Sdan  do_multiclient_test tn {
73a58f26f9Sdan
74a58f26f9Sdan    set ::nBusyHandler 0
75a58f26f9Sdan    set ::busy_handler_script ""
76a58f26f9Sdan    proc busyhandler {n} {
77a58f26f9Sdan      incr ::nBusyHandler
78a58f26f9Sdan      eval $::busy_handler_script
79a58f26f9Sdan      return 0
80a58f26f9Sdan    }
81a58f26f9Sdan
82a58f26f9Sdan    proc reopen_all {} {
83a58f26f9Sdan      code1 {db close}
84a58f26f9Sdan      code2 {db2 close}
85a58f26f9Sdan      code3 {db3 close}
869c5e3680Sdan
87a58f26f9Sdan      code1 {sqlite3 db test.db}
88a58f26f9Sdan      code2 {sqlite3 db2 test.db}
89a58f26f9Sdan      code3 {sqlite3 db3 test.db}
909c5e3680Sdan
91a58f26f9Sdan      sql1  { PRAGMA synchronous = NORMAL }
92a58f26f9Sdan      code1 { db busy busyhandler }
93a58f26f9Sdan    }
94a58f26f9Sdan
95a58f26f9Sdan    do_test 1.$tn.1 {
96a58f26f9Sdan      reopen_all
97a58f26f9Sdan      sql1 {
98a58f26f9Sdan        PRAGMA page_size = 1024;
99a58f26f9Sdan        PRAGMA auto_vacuum = 0;
100a58f26f9Sdan        CREATE TABLE t1(x, y);
101a58f26f9Sdan        PRAGMA journal_mode = WAL;
102a58f26f9Sdan        INSERT INTO t1 VALUES(1, zeroblob(1200));
103a58f26f9Sdan        INSERT INTO t1 VALUES(2, zeroblob(1200));
104a58f26f9Sdan        INSERT INTO t1 VALUES(3, zeroblob(1200));
105a58f26f9Sdan      }
106a58f26f9Sdan      expr [file size test.db] / 1024
107a58f26f9Sdan    } {2}
108a58f26f9Sdan
109a58f26f9Sdan    # Have connection 2 grab a read-lock on the current snapshot.
110a58f26f9Sdan    do_test 1.$tn.2 { sql2 { BEGIN; SELECT x FROM t1 } } {1 2 3}
111a58f26f9Sdan
112a58f26f9Sdan    # Attempt a checkpoint.
113a58f26f9Sdan    do_test 1.$tn.3 {
1149c5e3680Sdan      code1 { do_wal_checkpoint db }
115a58f26f9Sdan      list [db_page_count] [wal_page_count]
116a58f26f9Sdan    } {5 9}
117a58f26f9Sdan
118a58f26f9Sdan    # Write to the db again. The log cannot wrap because of the lock still
119a58f26f9Sdan    # held by connection 2. The busy-handler has not yet been invoked.
120a58f26f9Sdan    do_test 1.$tn.4 {
121a58f26f9Sdan      sql1 { INSERT INTO t1 VALUES(4, zeroblob(1200)) }
122a58f26f9Sdan      list [db_page_count] [wal_page_count] $::nBusyHandler
123a58f26f9Sdan    } {5 12 0}
124a58f26f9Sdan
125a58f26f9Sdan    # Now do a blocking-checkpoint. Set the busy-handler up so that connection
126a58f26f9Sdan    # 2 releases its lock on the 6th invocation. The checkpointer should then
127a58f26f9Sdan    # proceed to checkpoint the entire log file. Next write should go to the
128a58f26f9Sdan    # start of the log file.
129a58f26f9Sdan    #
130a58f26f9Sdan    set ::busy_handler_script { if {$n==5} { sql2 COMMIT } }
131a58f26f9Sdan    do_test 1.$tn.5 {
1329c5e3680Sdan      code1 { do_wal_checkpoint db -mode restart }
133a58f26f9Sdan      list [db_page_count] [wal_page_count] $::nBusyHandler
134a58f26f9Sdan    } {6 12 6}
135a58f26f9Sdan    do_test 1.$tn.6 {
136a58f26f9Sdan      set ::nBusyHandler 0
137a58f26f9Sdan      sql1 { INSERT INTO t1 VALUES(5, zeroblob(1200)) }
138a58f26f9Sdan      list [db_page_count] [wal_page_count] $::nBusyHandler
139a58f26f9Sdan    } {6 12 0}
140a58f26f9Sdan
141a58f26f9Sdan    do_test 1.$tn.7 {
142a58f26f9Sdan      reopen_all
143a58f26f9Sdan      list [db_page_count] [wal_page_count] $::nBusyHandler
144*82f52540Sdrh    } [expr {[nonzero_reserved_bytes]?"/# # 0/":"7 0 0"}]
145a58f26f9Sdan
146a58f26f9Sdan    do_test 1.$tn.8  { sql2 { BEGIN ; SELECT x FROM t1 } } {1 2 3 4 5}
147a58f26f9Sdan    do_test 1.$tn.9  {
148a58f26f9Sdan      sql1 { INSERT INTO t1 VALUES(6, zeroblob(1200)) }
149a58f26f9Sdan      list [db_page_count] [wal_page_count] $::nBusyHandler
150*82f52540Sdrh    } [expr {[nonzero_reserved_bytes]?"/# # #/":"7 5 0"}]
151a58f26f9Sdan    do_test 1.$tn.10 { sql3 { BEGIN ; SELECT x FROM t1 } } {1 2 3 4 5 6}
152a58f26f9Sdan
153a58f26f9Sdan    set ::busy_handler_script {
154a58f26f9Sdan      if {$n==5} { sql2 COMMIT }
155a58f26f9Sdan      if {$n==6} { set ::db_file_size [db_page_count] }
156a58f26f9Sdan      if {$n==7} { sql3 COMMIT }
157a58f26f9Sdan    }
158a58f26f9Sdan    do_test 1.$tn.11 {
1599c5e3680Sdan      code1 { do_wal_checkpoint db -mode restart }
160a58f26f9Sdan      list [db_page_count] [wal_page_count] $::nBusyHandler
161*82f52540Sdrh    } [expr {[nonzero_reserved_bytes]?"/# # #/":"10 5 8"}]
162a58f26f9Sdan    do_test 1.$tn.12 { set ::db_file_size } 10
163a58f26f9Sdan  }
164a58f26f9Sdan
165f2b8dd58Sdan  #-------------------------------------------------------------------------
166f2b8dd58Sdan  # This block of tests explores checkpoint operations on more than one
167f2b8dd58Sdan  # database file.
168f2b8dd58Sdan  #
169f2b8dd58Sdan  proc setup_and_attach_aux {} {
170f2b8dd58Sdan    sql1 { ATTACH 'test.db2' AS aux }
171f2b8dd58Sdan    sql2 { ATTACH 'test.db2' AS aux }
172f2b8dd58Sdan    sql3 { ATTACH 'test.db2' AS aux }
173f2b8dd58Sdan    sql1 {
1747fa65fbfSdan      PRAGMA aux.auto_vacuum = 0;
1757fa65fbfSdan      PRAGMA main.auto_vacuum = 0;
176f2b8dd58Sdan      PRAGMA main.page_size=1024; PRAGMA main.journal_mode=WAL;
177f2b8dd58Sdan      PRAGMA aux.page_size=1024;  PRAGMA aux.journal_mode=WAL;
178f2b8dd58Sdan    }
179f2b8dd58Sdan  }
180f2b8dd58Sdan
181f2b8dd58Sdan  proc file_page_counts {} {
182f2b8dd58Sdan    list [db_page_count  test.db ] \
183f2b8dd58Sdan         [wal_page_count test.db ] \
184f2b8dd58Sdan         [db_page_count  test.db2] \
185f2b8dd58Sdan         [wal_page_count test.db2]
186f2b8dd58Sdan  }
187f2b8dd58Sdan
18808756372Sdan  # Test that executing "PRAGMA wal_checkpoint" checkpoints all attached
1899c5e3680Sdan  # databases, not just the main db.  In capi mode, check that this is
1909c5e3680Sdan  # true if a NULL pointer is passed to wal_checkpoint_v2() in place of a
1919c5e3680Sdan  # database name.
192f2b8dd58Sdan  do_multiclient_test tn {
193f2b8dd58Sdan    setup_and_attach_aux
194f2b8dd58Sdan    do_test 2.1.$tn.1 {
195f2b8dd58Sdan      sql1 {
196f2b8dd58Sdan        CREATE TABLE t1(a, b);
197f2b8dd58Sdan        INSERT INTO t1 VALUES(1, 2);
198f2b8dd58Sdan        CREATE TABLE aux.t2(a, b);
199f2b8dd58Sdan        INSERT INTO t2 VALUES(1, 2);
200f2b8dd58Sdan      }
201f2b8dd58Sdan    } {}
2020774bb59Sdan    do_test 2.2.$tn.2 { file_page_counts } {1 3 1 3}
2030774bb59Sdan    do_test 2.1.$tn.3 { code1 { do_wal_checkpoint db } } {0 3 3}
2040774bb59Sdan    do_test 2.1.$tn.4 { file_page_counts } {2 3 2 3}
205f2b8dd58Sdan  }
206f2b8dd58Sdan
207f2b8dd58Sdan  do_multiclient_test tn {
208f2b8dd58Sdan    setup_and_attach_aux
209f2b8dd58Sdan    do_test 2.2.$tn.1 {
210f2b8dd58Sdan      execsql {
211f2b8dd58Sdan        CREATE TABLE t1(a, b);
212f2b8dd58Sdan        INSERT INTO t1 VALUES(1, 2);
213f2b8dd58Sdan        CREATE TABLE aux.t2(a, b);
214f2b8dd58Sdan        INSERT INTO t2 VALUES(1, 2);
215f2b8dd58Sdan        INSERT INTO t2 VALUES(3, 4);
216f2b8dd58Sdan      }
217f2b8dd58Sdan    } {}
2180774bb59Sdan    do_test 2.2.$tn.2 { file_page_counts } {1 3 1 4}
219f2b8dd58Sdan    do_test 2.2.$tn.3 { sql2 { BEGIN; SELECT * FROM t1 } } {1 2}
2200774bb59Sdan    do_test 2.2.$tn.4 { code1 { do_wal_checkpoint db -mode restart } } {1 3 3}
2210774bb59Sdan    do_test 2.2.$tn.5 { file_page_counts } {2 3 2 4}
222f2b8dd58Sdan  }
223f2b8dd58Sdan
224f2b8dd58Sdan  do_multiclient_test tn {
225f2b8dd58Sdan    setup_and_attach_aux
226f2b8dd58Sdan    do_test 2.3.$tn.1 {
227f2b8dd58Sdan      execsql {
228f2b8dd58Sdan        CREATE TABLE t1(a, b);
229f2b8dd58Sdan        INSERT INTO t1 VALUES(1, 2);
230f2b8dd58Sdan        CREATE TABLE aux.t2(a, b);
231f2b8dd58Sdan        INSERT INTO t2 VALUES(1, 2);
232f2b8dd58Sdan      }
233f2b8dd58Sdan    } {}
2340774bb59Sdan    do_test 2.3.$tn.2 { file_page_counts } {1 3 1 3}
235f2b8dd58Sdan    do_test 2.3.$tn.3 { sql2 { BEGIN; SELECT * FROM t1 } } {1 2}
236f2b8dd58Sdan    do_test 2.3.$tn.4 { sql1 { INSERT INTO t1 VALUES(3, 4) } } {}
237f2b8dd58Sdan    do_test 2.3.$tn.5 { sql1 { INSERT INTO t2 VALUES(3, 4) } } {}
2380774bb59Sdan    do_test 2.3.$tn.6 { file_page_counts } {1 4 1 4}
2390774bb59Sdan    do_test 2.3.$tn.7 { code1 { do_wal_checkpoint db -mode full } } {1 4 3}
2407909e54aSdan
2417909e54aSdan    # The checkpoint above only writes page 1 of the db file. The other
2427909e54aSdan    # page (page 2) is locked by the read-transaction opened by the
2437909e54aSdan    # [sql2] commmand above. So normally, the db is 1 page in size here.
2447909e54aSdan    # However, in mmap() mode, the db is pre-allocated to 2 pages at the
2457909e54aSdan    # start of the checkpoint, even though page 2 cannot be written.
2460d0614bdSdrh    set nDb 2
2479b4c59faSdrh    if {[permutation]!="mmap"} {set nDb 1}
248188d4884Sdrh    ifcapable !mmap {set nDb 1}
2497909e54aSdan    do_test 2.3.$tn.8 { file_page_counts } [list $nDb 4 2 4]
250f2b8dd58Sdan  }
251f2b8dd58Sdan
25208756372Sdan  # Check that checkpoints block on the correct locks. And respond correctly
25308756372Sdan  # if they cannot obtain those locks. There are three locks that a checkpoint
25408756372Sdan  # may block on (in the following order):
25508756372Sdan  #
25608756372Sdan  #   1. The writer lock: FULL and RESTART checkpoints block until any writer
25708756372Sdan  #      process releases its lock.
25808756372Sdan  #
25908756372Sdan  #   2. Readers using part of the log file. FULL and RESTART checkpoints block
26008756372Sdan  #      until readers using part (but not all) of the log file have finished.
26108756372Sdan  #
26208756372Sdan  #   3. Readers using any of the log file. After copying data into the
26308756372Sdan  #      database file, RESTART checkpoints block until readers using any part
26408756372Sdan  #      of the log file have finished.
26508756372Sdan  #
26624cd616eSdan  # This test case involves running a checkpoint while there exist other
26724cd616eSdan  # processes holding all three types of locks.
26824cd616eSdan  #
26908756372Sdan  foreach {tn1 checkpoint busy_on ckpt_expected expected} {
2700774bb59Sdan    1   PASSIVE   -   {0 3 3}   -
2710774bb59Sdan    2   TYPO      -   {0 3 3}   -
27208756372Sdan
2730774bb59Sdan    3   FULL      -   {0 4 4}   2
2740774bb59Sdan    4   FULL      1   {1 3 3}   1
2750774bb59Sdan    5   FULL      2   {1 4 3}   2
2760774bb59Sdan    6   FULL      3   {0 4 4}   2
27708756372Sdan
2780774bb59Sdan    7   RESTART   -   {0 4 4}   3
2790774bb59Sdan    8   RESTART   1   {1 3 3}   1
2800774bb59Sdan    9   RESTART   2   {1 4 3}   2
2810774bb59Sdan    10  RESTART   3   {1 4 4}   3
28208756372Sdan
283f26a1549Sdan    11  TRUNCATE  -   {0 0 0}   3
284f26a1549Sdan    12  TRUNCATE  1   {1 3 3}   1
285f26a1549Sdan    13  TRUNCATE  2   {1 4 3}   2
286f26a1549Sdan    14  TRUNCATE  3   {1 4 4}   3
287f26a1549Sdan
28808756372Sdan  } {
28908756372Sdan    do_multiclient_test tn {
29008756372Sdan      setup_and_attach_aux
29108756372Sdan
29208756372Sdan      proc busyhandler {x} {
29308756372Sdan        set ::max_busyhandler $x
29408756372Sdan        if {$::busy_on!="-" && $x==$::busy_on} { return 1 }
29508756372Sdan        switch -- $x {
29608756372Sdan          1 { sql2 "COMMIT ; BEGIN ; SELECT * FROM t1" }
29708756372Sdan          2 { sql3 "COMMIT" }
29808756372Sdan          3 { sql2 "COMMIT" }
29908756372Sdan        }
30008756372Sdan        return 0
30108756372Sdan      }
30208756372Sdan      set ::max_busyhandler -
30308756372Sdan
30408756372Sdan      do_test 2.4.$tn1.$tn.1 {
30508756372Sdan        sql1 {
30608756372Sdan          CREATE TABLE t1(a, b);
30708756372Sdan          INSERT INTO t1 VALUES(1, 2);
30808756372Sdan        }
30908756372Sdan        sql2 { BEGIN; INSERT INTO t1 VALUES(3, 4) }
31008756372Sdan        sql3 { BEGIN; SELECT * FROM t1 }
31108756372Sdan      } {1 2}
31208756372Sdan
31308756372Sdan      do_test 2.4.$tn1.$tn.2 {
31408756372Sdan        code1 { db busy busyhandler }
3159c5e3680Sdan        code1 { do_wal_checkpoint db -mode [string tolower $checkpoint] }
31608756372Sdan      } $ckpt_expected
31708756372Sdan      do_test 2.4.$tn1.$tn.3 { set ::max_busyhandler } $expected
31808756372Sdan    }
31908756372Sdan  }
320f2b8dd58Sdan
321f2b8dd58Sdan
3229c5e3680Sdan  do_multiclient_test tn {
3239c5e3680Sdan
3249c5e3680Sdan    code1 $do_wal_checkpoint
3259c5e3680Sdan    code2 $do_wal_checkpoint
3269c5e3680Sdan    code3 $do_wal_checkpoint
3279c5e3680Sdan
3289c5e3680Sdan    do_test 3.$tn.1 {
3299c5e3680Sdan      sql1 {
3307fa65fbfSdan        PRAGMA auto_vacuum = 0;
3319c5e3680Sdan        PRAGMA journal_mode = WAL;
3329c5e3680Sdan        PRAGMA synchronous = normal;
3339c5e3680Sdan        CREATE TABLE t1(x, y);
3349c5e3680Sdan      }
3359c5e3680Sdan
3369c5e3680Sdan      sql2 { PRAGMA journal_mode }
3379c5e3680Sdan      sql3 { PRAGMA journal_mode }
3389c5e3680Sdan    } {wal}
3399c5e3680Sdan
3409c5e3680Sdan    do_test 3.$tn.2 { code2 { do_wal_checkpoint db2 } } {0 2 2}
3419c5e3680Sdan
3429c5e3680Sdan    do_test 3.$tn.3 { code2 { do_wal_checkpoint db2 } } {0 2 2}
3439c5e3680Sdan
3449c5e3680Sdan    do_test 3.$tn.4 { code3 { do_wal_checkpoint db3 } } {0 2 2}
3459c5e3680Sdan
3469c5e3680Sdan    code1 {db  close}
3479c5e3680Sdan    code2 {db2 close}
3489c5e3680Sdan    code3 {db3 close}
3499c5e3680Sdan
3509c5e3680Sdan    code1 {sqlite3 db  test.db}
3519c5e3680Sdan    code2 {sqlite3 db2 test.db}
3529c5e3680Sdan    code3 {sqlite3 db3 test.db}
3539c5e3680Sdan
3549c5e3680Sdan    do_test 3.$tn.5 { sql3 { PRAGMA journal_mode } } {wal}
3559c5e3680Sdan
3569c5e3680Sdan    do_test 3.$tn.6 { code3 { do_wal_checkpoint db3 } } {0 0 0}
3579c5e3680Sdan  }
358f26a1549Sdan
359f26a1549Sdan  # Test SQLITE_CHECKPOINT_TRUNCATE.
360f26a1549Sdan  #
361f26a1549Sdan  do_multiclient_test tn {
362f26a1549Sdan
363f26a1549Sdan    code1 $do_wal_checkpoint
364f26a1549Sdan    code2 $do_wal_checkpoint
365f26a1549Sdan    code3 $do_wal_checkpoint
366f26a1549Sdan
36762031584Sdan    do_test 4.$tn.1 {
368f26a1549Sdan      sql1 {
369f26a1549Sdan        PRAGMA page_size = 1024;
37062031584Sdan        PRAGMA auto_vacuum = 0;
371f26a1549Sdan        PRAGMA journal_mode = WAL;
372f26a1549Sdan        PRAGMA synchronous = normal;
373f26a1549Sdan        CREATE TABLE t1(x, y);
374f26a1549Sdan        CREATE INDEX i1 ON t1(x, y);
375f26a1549Sdan        INSERT INTO t1 VALUES(1, 2);
376f26a1549Sdan        INSERT INTO t1 VALUES(3, 4);
377f26a1549Sdan      }
378f26a1549Sdan      file size test.db-wal
379f26a1549Sdan    } [wal_file_size 8 1024]
380f26a1549Sdan
38162031584Sdan    do_test 4.$tn.2 { do_wal_checkpoint db -mode truncate } {0 0 0}
38262031584Sdan    do_test 4.$tn.3 { file size test.db-wal } 0
383f26a1549Sdan
38462031584Sdan    do_test 4.$tn.4 {
385f26a1549Sdan      sql2 { SELECT * FROM t1 }
386f26a1549Sdan    } {1 2 3 4}
387f26a1549Sdan
38862031584Sdan    do_test 4.$tn.5 {
389f26a1549Sdan      sql2 { INSERT INTO t1 VALUES('a', 'b') }
390f26a1549Sdan      file size test.db-wal
391f26a1549Sdan    } [wal_file_size 2 1024]
392f26a1549Sdan
393f26a1549Sdan  }
394976b0033Sdan
395976b0033Sdan  # Test that FULL, RESTART and TRUNCATE callbacks block on other clients
396976b0033Sdan  # and truncate the wal file as required even if the entire wal file has
397976b0033Sdan  # already been checkpointed when they are invoked.
398976b0033Sdan  #
399976b0033Sdan  do_multiclient_test tn {
400976b0033Sdan
401976b0033Sdan    code1 $do_wal_checkpoint
402976b0033Sdan    code2 $do_wal_checkpoint
403976b0033Sdan    code3 $do_wal_checkpoint
404976b0033Sdan
405976b0033Sdan    do_test 5.$tn.1 {
406976b0033Sdan      sql1 {
407976b0033Sdan        PRAGMA page_size = 1024;
408976b0033Sdan        PRAGMA auto_vacuum = 0;
409976b0033Sdan        PRAGMA journal_mode = WAL;
410976b0033Sdan        PRAGMA synchronous = normal;
411976b0033Sdan        CREATE TABLE t1(x, y);
412976b0033Sdan        CREATE INDEX i1 ON t1(x, y);
413976b0033Sdan        INSERT INTO t1 VALUES(1, 2);
414976b0033Sdan        INSERT INTO t1 VALUES(3, 4);
415976b0033Sdan        INSERT INTO t1 VALUES(5, 6);
416976b0033Sdan      }
417976b0033Sdan      file size test.db-wal
418976b0033Sdan    } [wal_file_size 10 1024]
419976b0033Sdan
420976b0033Sdan    do_test 5.$tn.2 {
421976b0033Sdan      sql2 { BEGIN; SELECT * FROM t1 }
422976b0033Sdan    } {1 2 3 4 5 6}
423976b0033Sdan
424976b0033Sdan    do_test 5.$tn.3 { do_wal_checkpoint db -mode passive } {0 10 10}
425976b0033Sdan
426976b0033Sdan    do_test 5.$tn.4 {
427976b0033Sdan      sql3 { BEGIN; INSERT INTO t1 VALUES(7, 8); }
428976b0033Sdan    } {}
429976b0033Sdan
430976b0033Sdan    do_test 5.$tn.5 { do_wal_checkpoint db -mode passive  } {0 10 10}
431976b0033Sdan    do_test 5.$tn.6 { do_wal_checkpoint db -mode full     } {1 10 10}
432976b0033Sdan
433976b0033Sdan    do_test 5.$tn.7 { sql3 { ROLLBACK } } {}
434976b0033Sdan
435976b0033Sdan    do_test 5.$tn.8 { do_wal_checkpoint db -mode full     } {0 10 10}
436976b0033Sdan    do_test 5.$tn.9 { do_wal_checkpoint db -mode truncate } {1 10 10}
437976b0033Sdan
438976b0033Sdan    do_test 5.$tn.10 {
439976b0033Sdan      file size test.db-wal
440976b0033Sdan    } [wal_file_size 10 1024]
441976b0033Sdan
442976b0033Sdan    proc xBusyHandler {n} { sql2 { COMMIT } ; return 0 }
443976b0033Sdan    db busy xBusyHandler
444976b0033Sdan
445976b0033Sdan    do_test 5.$tn.11 { do_wal_checkpoint db -mode truncate } {0 0 0}
446976b0033Sdan    do_test 5.$tn.12 { file size test.db-wal } 0
447976b0033Sdan
448976b0033Sdan    do_test 5.$tn.13 {
449976b0033Sdan      sql1 {
450976b0033Sdan        INSERT INTO t1 VALUES(7, 8);
451976b0033Sdan        INSERT INTO t1 VALUES(9, 10);
452976b0033Sdan        SELECT * FROM t1;
453976b0033Sdan      }
454976b0033Sdan    } {1 2 3 4 5 6 7 8 9 10}
455976b0033Sdan
456976b0033Sdan    do_test 5.$tn.14 {
457976b0033Sdan      sql2 { BEGIN; SELECT * FROM t1 }
458976b0033Sdan    } {1 2 3 4 5 6 7 8 9 10}
459976b0033Sdan
460976b0033Sdan    proc xBusyHandler {n} { return 1 }
461fdc2e6d3Smistachkin    do_test 5.$tn.15 { do_wal_checkpoint db -mode truncate } {1 4 4}
462fdc2e6d3Smistachkin    do_test 5.$tn.16 { file size test.db-wal } [wal_file_size 4 1024]
463976b0033Sdan
464fdc2e6d3Smistachkin    do_test 5.$tn.17 { do_wal_checkpoint db -mode restart } {1 4 4}
465976b0033Sdan
466976b0033Sdan    proc xBusyHandler {n} { sql2 { COMMIT } ; return 0 }
467976b0033Sdan    db busy xBusyHandler
468fdc2e6d3Smistachkin    do_test 5.$tn.18 { do_wal_checkpoint db -mode restart } {0 4 4}
469fdc2e6d3Smistachkin    do_test 5.$tn.19 { file size test.db-wal } [wal_file_size 4 1024]
470976b0033Sdan
471fdc2e6d3Smistachkin    do_test 5.$tn.20 { do_wal_checkpoint db -mode truncate } {0 0 0}
472fdc2e6d3Smistachkin    do_test 5.$tn.21 { file size test.db-wal } 0
473976b0033Sdan  }
474976b0033Sdan
4759c5e3680Sdan}
4769c5e3680Sdan
4779c5e3680Sdan
478a58f26f9Sdanfinish_test
479