| OLD | NEW |
| 1 # 2008 May 12 | 1 # 2008 May 12 |
| 2 # | 2 # |
| 3 # The author disclaims copyright to this source code. In place of | 3 # The author disclaims copyright to this source code. In place of |
| 4 # a legal notice, here is a blessing: | 4 # a legal notice, here is a blessing: |
| 5 # | 5 # |
| 6 # May you do good and not evil. | 6 # May you do good and not evil. |
| 7 # May you find forgiveness for yourself and forgive others. | 7 # May you find forgiveness for yourself and forgive others. |
| 8 # May you share freely, never taking more than you give. | 8 # May you share freely, never taking more than you give. |
| 9 # | 9 # |
| 10 #*********************************************************************** | 10 #*********************************************************************** |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 84 execsql { pragma locking_mode=exclusive } | 84 execsql { pragma locking_mode=exclusive } |
| 85 set nRow [db one {SELECT count(*) FROM a}] | 85 set nRow [db one {SELECT count(*) FROM a}] |
| 86 | 86 |
| 87 # Dirty (at least) one of the pages in the cache. | 87 # Dirty (at least) one of the pages in the cache. |
| 88 do_test ioerr5-1.$locking_mode-$iFail.1 { | 88 do_test ioerr5-1.$locking_mode-$iFail.1 { |
| 89 execsql { | 89 execsql { |
| 90 BEGIN EXCLUSIVE; | 90 BEGIN EXCLUSIVE; |
| 91 INSERT INTO a VALUES(1, 'ABCDEFGHIJKLMNOP'); | 91 INSERT INTO a VALUES(1, 'ABCDEFGHIJKLMNOP'); |
| 92 } | 92 } |
| 93 } {} | 93 } {} |
| 94 |
| 95 # Open a read-only cursor on table "a". If the COMMIT below is |
| 96 # interrupted by a persistent IO error, the pager will transition to |
| 97 # PAGER_ERROR state. If there are no other read-only cursors open, |
| 98 # from there the pager immediately discards all cached data and |
| 99 # switches to PAGER_OPEN state. This read-only cursor stops that |
| 100 # from happening, leaving the pager stuck in PAGER_ERROR state. |
| 101 # |
| 102 set channel [db incrblob -readonly a Name [db last_insert_rowid]] |
| 94 | 103 |
| 95 # Now try to commit the transaction. Cause an IO error to occur | 104 # Now try to commit the transaction. Cause an IO error to occur |
| 96 # within this operation, which moves the pager into the error state. | 105 # within this operation, which moves the pager into the error state. |
| 97 # | 106 # |
| 98 set ::sqlite_io_error_persist 1 | 107 set ::sqlite_io_error_persist 1 |
| 99 set ::sqlite_io_error_pending $iFail | 108 set ::sqlite_io_error_pending $iFail |
| 100 do_test ioerr5-1.$locking_mode-$iFail.2 { | 109 do_test ioerr5-1.$locking_mode-$iFail.2 { |
| 101 set rc [catchsql {COMMIT}] | 110 set rc [catchsql {COMMIT}] |
| 102 list | 111 list |
| 103 } {} | 112 } {} |
| 104 set ::sqlite_io_error_hit 0 | 113 set ::sqlite_io_error_hit 0 |
| 105 set ::sqlite_io_error_persist 0 | 114 set ::sqlite_io_error_persist 0 |
| 106 set ::sqlite_io_error_pending 0 | 115 set ::sqlite_io_error_pending 0 |
| 107 | 116 |
| 108 # Read the contents of the database file into a Tcl variable. | 117 # Read the contents of the database file into a Tcl variable. |
| 109 # | 118 # |
| 110 set fd [open test.db] | 119 set fd [open test.db] |
| 111 fconfigure $fd -translation binary -encoding binary | 120 fconfigure $fd -translation binary -encoding binary |
| 112 set zDatabase [read $fd] | 121 set zDatabase [read $fd] |
| 113 close $fd | 122 close $fd |
| 114 | 123 |
| 115 # Set a very low soft-limit and then try to compile an SQL statement | 124 # Set a very low soft-limit and then try to compile an SQL statement |
| 116 # from UTF-16 text. To do this, SQLite will need to reclaim memory | 125 # from UTF-16 text. To do this, SQLite will need to reclaim memory |
| 117 # from the pager that is in error state. Including that associated | 126 # from the pager that is in error state. Including that associated |
| 118 # with the dirty page. | 127 # with the dirty page. |
| 119 # | 128 # |
| 120 do_test ioerr5-1.$locking_mode-$iFail.3 { | 129 do_test ioerr5-1.$locking_mode-$iFail.3 { |
| 121 set bt [btree_from_db db] | |
| 122 sqlite3_soft_heap_limit 1024 | 130 sqlite3_soft_heap_limit 1024 |
| 123 compilesql16 "SELECT 10" | 131 compilesql16 "SELECT 10" |
| 124 array set stats [btree_pager_stats $bt] | 132 } {SQLITE_OK} |
| 125 | 133 |
| 126 # If the pager made it all the way to PAGER_SYNCED state, then | 134 close $channel |
| 127 # both in-memory pages are clean. Following the calls to | |
| 128 # release_memory() that were made as part of the [compilesql16] | |
| 129 # above, there will be zero pages left in the cache. | |
| 130 # | |
| 131 # If the pager did not make it as far as PAGER_SYNCED, the two | |
| 132 # in memory pages are still dirty. So there will be 2 pages left | |
| 133 # in the cache following the release_memory() calls. | |
| 134 # | |
| 135 if {$stats(state)==5} { | |
| 136 set nPage 0 | |
| 137 } | |
| 138 expr {$stats(page)==$nPage} | |
| 139 } {1} | |
| 140 | 135 |
| 141 # Ensure that nothing was written to the database while reclaiming | 136 # Ensure that nothing was written to the database while reclaiming |
| 142 # memory from the pager in error state. | 137 # memory from the pager in error state. |
| 143 # | 138 # |
| 144 do_test ioerr5-1.$locking_mode-$iFail.4 { | 139 do_test ioerr5-1.$locking_mode-$iFail.4 { |
| 145 set fd [open test.db] | 140 set fd [open test.db] |
| 146 fconfigure $fd -translation binary -encoding binary | 141 fconfigure $fd -translation binary -encoding binary |
| 147 set zDatabase2 [read $fd] | 142 set zDatabase2 [read $fd] |
| 148 close $fd | 143 close $fd |
| 149 expr {$zDatabase eq $zDatabase2} | 144 expr {$zDatabase eq $zDatabase2} |
| 150 } {1} | 145 } {1} |
| 151 | 146 |
| 152 if {$rc eq [list 0 {}]} { | 147 if {$rc eq [list 0 {}]} { |
| 153 do_test ioerr5.1-$locking_mode-$iFail.3 { | 148 do_test ioerr5.1-$locking_mode-$iFail.3 { |
| 154 execsql { SELECT count(*) FROM a } | 149 execsql { SELECT count(*) FROM a } |
| 155 } [expr $nRow+1] | 150 } [expr $nRow+1] |
| 156 break | 151 break |
| 157 } | 152 } |
| 158 } | 153 } |
| 159 } | 154 } |
| 160 | 155 |
| 161 # Make sure this test script doesn't leave any files open. | 156 # Make sure this test script doesn't leave any files open. |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 212 do_test ioerr5-2.X { | 207 do_test ioerr5-2.X { |
| 213 catch { db close } | 208 catch { db close } |
| 214 catch { db2 close } | 209 catch { db2 close } |
| 215 set sqlite_open_file_count | 210 set sqlite_open_file_count |
| 216 } 0 | 211 } 0 |
| 217 | 212 |
| 218 sqlite3_enable_shared_cache $::enable_shared_cache | 213 sqlite3_enable_shared_cache $::enable_shared_cache |
| 219 sqlite3_soft_heap_limit $::soft_limit | 214 sqlite3_soft_heap_limit $::soft_limit |
| 220 | 215 |
| 221 finish_test | 216 finish_test |
| OLD | NEW |