Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Infrastructure to make simulated I/O errors persistent instead of transient. (CVS 3689) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
1a53f531ecd51938fab37a59b7088d89 |
User & Date: | drh 2007-03-15 12:17:43.000 |
Context
2007-03-15
| ||
12:51 | Fix the pager so that it handles persistent I/O errors correctly. Update the testing infrastructure so that it tests for persistent I/O errors instead of just transient errors. (CVS 3690) (check-in: ea8507a796 user: drh tags: trunk) | |
12:17 | Infrastructure to make simulated I/O errors persistent instead of transient. (CVS 3689) (check-in: 1a53f531ec user: drh tags: trunk) | |
12:05 | Catch an IO error code that was being ignored in OP_RowData. (CVS 3688) (check-in: 760ebf8076 user: danielk1977 tags: trunk) | |
Changes
Changes to src/os_common.h.
︙ | ︙ | |||
86 87 88 89 90 91 92 93 94 95 96 | ** If we compile with the SQLITE_TEST macro set, then the following block ** of code will give us the ability to simulate a disk I/O error. This ** is used for testing the I/O recovery logic. */ #ifdef SQLITE_TEST int sqlite3_io_error_hit = 0; int sqlite3_io_error_pending = 0; int sqlite3_diskfull_pending = 0; int sqlite3_diskfull = 0; #define SimulateIOError(CODE) \ if( sqlite3_io_error_pending ) \ | > | > > | | 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | ** If we compile with the SQLITE_TEST macro set, then the following block ** of code will give us the ability to simulate a disk I/O error. This ** is used for testing the I/O recovery logic. */ #ifdef SQLITE_TEST int sqlite3_io_error_hit = 0; int sqlite3_io_error_pending = 0; int sqlite3_io_error_persist = 0; int sqlite3_diskfull_pending = 0; int sqlite3_diskfull = 0; #define SimulateIOError(CODE) \ if( sqlite3_io_error_pending ) \ if( sqlite3_io_error_pending-- == 1 \ || (sqlite3_io_error_persist && sqlite3_io_error_hit) ) \ { local_ioerr(); CODE; } static void local_ioerr(){ sqlite3_io_error_hit = 1; } #define SimulateDiskfullError(CODE) \ if( sqlite3_diskfull_pending ){ \ if( sqlite3_diskfull_pending == 1 ){ \ local_ioerr(); \ sqlite3_diskfull = 1; \ CODE; \ |
︙ | ︙ |
Changes to src/test2.c.
︙ | ︙ | |||
9 10 11 12 13 14 15 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** Code for testing the pager.c module in SQLite. This code ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** Code for testing the pager.c module in SQLite. This code ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** ** $Id: test2.c,v 1.40 2007/03/15 12:17:43 drh Exp $ */ #include "sqliteInt.h" #include "os.h" #include "pager.h" #include "tcl.h" #include <stdlib.h> #include <string.h> |
︙ | ︙ | |||
554 555 556 557 558 559 560 561 562 563 564 565 566 567 | } #endif /* ** Register commands with the TCL interpreter. */ int Sqlitetest2_Init(Tcl_Interp *interp){ extern int sqlite3_io_error_pending; extern int sqlite3_io_error_hit; extern int sqlite3_diskfull_pending; extern int sqlite3_diskfull; static struct { char *zName; Tcl_CmdProc *xProc; | > | 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 | } #endif /* ** Register commands with the TCL interpreter. */ int Sqlitetest2_Init(Tcl_Interp *interp){ extern int sqlite3_io_error_persist; extern int sqlite3_io_error_pending; extern int sqlite3_io_error_hit; extern int sqlite3_diskfull_pending; extern int sqlite3_diskfull; static struct { char *zName; Tcl_CmdProc *xProc; |
︙ | ︙ | |||
588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 | }; int i; for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); } Tcl_LinkVar(interp, "sqlite_io_error_pending", (char*)&sqlite3_io_error_pending, TCL_LINK_INT); Tcl_LinkVar(interp, "sqlite_io_error_hit", (char*)&sqlite3_io_error_hit, TCL_LINK_INT); Tcl_LinkVar(interp, "sqlite_diskfull_pending", (char*)&sqlite3_diskfull_pending, TCL_LINK_INT); Tcl_LinkVar(interp, "sqlite_diskfull", (char*)&sqlite3_diskfull, TCL_LINK_INT); Tcl_LinkVar(interp, "sqlite_pending_byte", (char*)&sqlite3_pending_byte, TCL_LINK_INT); Tcl_LinkVar(interp, "pager_pagesize", (char*)&test_pagesize, TCL_LINK_INT); return TCL_OK; } | > > | 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 | }; int i; for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); } Tcl_LinkVar(interp, "sqlite_io_error_pending", (char*)&sqlite3_io_error_pending, TCL_LINK_INT); Tcl_LinkVar(interp, "sqlite_io_error_persist", (char*)&sqlite3_io_error_persist, TCL_LINK_INT); Tcl_LinkVar(interp, "sqlite_io_error_hit", (char*)&sqlite3_io_error_hit, TCL_LINK_INT); Tcl_LinkVar(interp, "sqlite_diskfull_pending", (char*)&sqlite3_diskfull_pending, TCL_LINK_INT); Tcl_LinkVar(interp, "sqlite_diskfull", (char*)&sqlite3_diskfull, TCL_LINK_INT); Tcl_LinkVar(interp, "sqlite_pending_byte", (char*)&sqlite3_pending_byte, TCL_LINK_INT); Tcl_LinkVar(interp, "pager_pagesize", (char*)&test_pagesize, TCL_LINK_INT); return TCL_OK; } |
Changes to test/ioerr.test.
︙ | ︙ | |||
11 12 13 14 15 16 17 | # This file implements regression tests for SQLite library. The # focus of this file is testing for correct handling of I/O errors # such as writes failing because the disk is full. # # The tests in this file use special facilities that are only # available in the SQLite test fixture. # | | | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | # This file implements regression tests for SQLite library. The # focus of this file is testing for correct handling of I/O errors # such as writes failing because the disk is full. # # The tests in this file use special facilities that are only # available in the SQLite test fixture. # # $Id: ioerr.test,v 1.30 2007/03/15 12:17:43 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # If SQLITE_DEFAULT_AUTOVACUUM is set to true, then a simulated IO error # on the 8th IO operation in the SQL script below doesn't report an error. |
︙ | ︙ | |||
42 43 44 45 46 47 48 | INSERT INTO t1 VALUES(1,2,3); INSERT INTO t1 VALUES(4,5,6); COMMIT; SELECT * FROM t1; DELETE FROM t1 WHERE a<100; } -exclude [expr [string match [execsql {pragma auto_vacuum}] 1] ? 4 : 0] | < < < | 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | INSERT INTO t1 VALUES(1,2,3); INSERT INTO t1 VALUES(4,5,6); COMMIT; SELECT * FROM t1; DELETE FROM t1 WHERE a<100; } -exclude [expr [string match [execsql {pragma auto_vacuum}] 1] ? 4 : 0] # Test for IO errors during a VACUUM. # # The first IO call is excluded from the test. This call attempts to read # the file-header of the temporary database used by VACUUM. Since the # database doesn't exist at that point, the IO error is not detected. # # Additionally, if auto-vacuum is enabled, the 12th IO error is not |
︙ | ︙ | |||
255 256 257 258 259 260 261 262 263 | INSERT INTO t1 SELECT (a+500)%900, 'good string' FROM t1; }} msg if {$msg != "column a is not unique"} { error $msg } } finish_test | > > > > > > > > > | 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 | INSERT INTO t1 SELECT (a+500)%900, 'good string' FROM t1; }} msg if {$msg != "column a is not unique"} { error $msg } } # Assertion fault bug reported by alex dimitrov. # do_ioerr_test ioerr-11 -erc 1 -sqlprep { CREATE TABLE A(Id INTEGER, Name TEXT); INSERT INTO A(Id, Name) VALUES(1, 'Name'); } -sqlbody { UPDATE A SET Id = 2, Name = 'Name2' WHERE Id = 1; } finish_test |
Changes to test/tester.tcl.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2001 September 15 # # 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 some common TCL routines used for regression # testing the SQLite library # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 2001 September 15 # # 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 some common TCL routines used for regression # testing the SQLite library # # $Id: tester.tcl,v 1.73 2007/03/15 12:17:43 drh Exp $ # Make sure tclsqlite3 was compiled correctly. Abort now with an # error message if not. # if {[sqlite3 -tcl-uses-utf]} { if {"\u1234"=="u1234"} { puts stderr "***** BUILD PROBLEM *****" |
︙ | ︙ | |||
338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 | # # -tclprep TCL script to run to prepare test. # -sqlprep SQL script to run to prepare test. # -tclbody TCL script to run with IO error simulation. # -sqlbody TCL script to run with IO error simulation. # -exclude List of 'N' values not to test. # -erc Use extended result codes # -start Value of 'N' to begin with (default 1) # # -cksum Boolean. If true, test that the database does # not change during the execution of the test case. # proc do_ioerr_test {testname args} { set ::ioerropts(-start) 1 set ::ioerropts(-cksum) 0 set ::ioerropts(-erc) 0 set ::ioerropts(-count) 100000000 array set ::ioerropts $args set ::go 1 for {set n $::ioerropts(-start)} {$::go} {incr n} { incr ::ioerropts(-count) -1 if {$::ioerropts(-count)<0} break | > > | 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 | # # -tclprep TCL script to run to prepare test. # -sqlprep SQL script to run to prepare test. # -tclbody TCL script to run with IO error simulation. # -sqlbody TCL script to run with IO error simulation. # -exclude List of 'N' values not to test. # -erc Use extended result codes # -persist Make simulated I/O errors persistent # -start Value of 'N' to begin with (default 1) # # -cksum Boolean. If true, test that the database does # not change during the execution of the test case. # proc do_ioerr_test {testname args} { set ::ioerropts(-start) 1 set ::ioerropts(-cksum) 0 set ::ioerropts(-erc) 0 set ::ioerropts(-count) 100000000 set ::ioerropts(-persist) 1 array set ::ioerropts $args set ::go 1 for {set n $::ioerropts(-start)} {$::go} {incr n} { incr ::ioerropts(-count) -1 if {$::ioerropts(-count)<0} break |
︙ | ︙ | |||
388 389 390 391 392 393 394 395 396 397 398 399 400 401 | # Read the 'checksum' of the database. if {$::ioerropts(-cksum)} { set checksum [cksum] } # Set the Nth IO error to fail. do_test $testname.$n.2 [subst { set ::sqlite_io_error_pending $n }] $n # Create a single TCL script from the TCL and SQL specified # as the body of the test. set ::ioerrorbody {} if {[info exists ::ioerropts(-tclbody)]} { | > | 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 | # Read the 'checksum' of the database. if {$::ioerropts(-cksum)} { set checksum [cksum] } # Set the Nth IO error to fail. do_test $testname.$n.2 [subst { set ::sqlite_io_error_persist $::ioerropts(-persist) set ::sqlite_io_error_pending $n }] $n # Create a single TCL script from the TCL and SQL specified # as the body of the test. set ::ioerrorbody {} if {[info exists ::ioerropts(-tclbody)]} { |
︙ | ︙ |