From: dan Date: Mon, 23 Feb 2015 12:22:55 +0000 (+0000) Subject: Improve tests for resuming ota updates following power failures. Fix a problem reveal... X-Git-Tag: version-3.8.11~252^2~33 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=882b8e09746dcdbdd4a9cc2479bad25ae6ebc6ad;p=thirdparty%2Fsqlite.git Improve tests for resuming ota updates following power failures. Fix a problem revealed by the same. FossilOrigin-Name: 1cb675e5392f179516d8e7a52760922a6c7df4d0 --- diff --git a/ext/ota/otacrash.test b/ext/ota/otacrash.test index 50784f4e5a..9474a99152 100644 --- a/ext/ota/otacrash.test +++ b/ext/ota/otacrash.test @@ -36,35 +36,105 @@ do_execsql_test 1.0 { db_save_and_close -for {set i 0} {$i < 10} {incr i} { - forcedelete test.db2 test.db2-journal test.db test.db-oal test.db-wal +# Determine the number of steps in applying the ota update to the test +# target database created above. Set $::ota_num_steps accordingly +# +# Check that the same number of steps are required to apply the ota +# update using many calls to sqlite3ota_step() on a single ota handle +# as required to apply it using a series of ota handles, on each of +# which sqlite3ota_step() is called once. +# +do_test 1.1 { + db_restore + sqlite3ota ota test.db test.db2 + breakpoint + set nStep 0 + while {[ota step]=="SQLITE_OK"} { incr nStep } + ota close +} {SQLITE_DONE} +set ota_num_steps $nStep +do_test 1.2 { db_restore - do_test 2.$i.1 { - crashsql -file test.db2 -delay 3 -tclbody { + set nStep 0 + while {1} { + sqlite3ota ota test.db test.db2 + ota step + if {[ota close]=="SQLITE_DONE"} break + incr nStep + } + set nStep +} $ota_num_steps - sqlite3ota ota test.db file:test.db2?vfs=crash - ota step - ota close - sqlite3ota ota test.db file:test.db2?vfs=crash - ota step - ota step +# Run one or more tests using the target (test.db) and ota (test.db2) +# databases created above. As follows: +# +# 1. This process starts the ota update and calls sqlite3ota_step() +# $nPre times. Then closes the ota update handle. +# +# 2. A second process resumes the ota update and attempts to call +# sqlite3ota_step() $nStep times before closing the handle. A +# crash is simulated during each xSync() of file test.db2. +# +# 3. This process attempts to resume the ota update from whatever +# state it was left in by step (2). Test that it is successful +# in doing so and that the final target database is as expected. +# +# In total (nSync+1) tests are run, where nSync is the number of times +# xSync() is called on test.db2. +# +proc do_ota_crash_test {tn nPre nStep} { + + set script [subst -nocommands { + sqlite3ota ota test.db file:test.db2?vfs=crash + set i 0 + while {[set i] < $nStep} { + if {[ota step]!="SQLITE_OK"} break + incr i + } + ota close + }] + + set bDone 0 + for {set iDelay 1} {$bDone==0} {incr iDelay} { + forcedelete test.db2 test.db2-journal test.db test.db-oal test.db-wal + db_restore + + if {$nPre>0} { + sqlite3ota ota test.db file:test.db2 + set i 0 + for {set i 0} {$i < $nPre} {incr i} { + if {[ota step]!="SQLITE_OK"} break + } ota close - } {} - } {1 {child process exited abnormally}} + } + + set res [crashsql -file test.db2 -delay $iDelay -tclbody $script {}] + + set bDone 1 + if {$res == "1 {child process exited abnormally}"} { + set bDone 0 + } elseif {$res != "0 {}"} { + error "unexected catchsql result: $res" + } - do_test 2.$i.2 { sqlite3ota ota test.db test.db2 while {[ota step]=="SQLITE_OK"} {} ota close - } {SQLITE_DONE} - - sqlite3 db test.db - do_execsql_test 2.$i.3 { - SELECT * FROM t1; - } {1 2 100 7 8 9 10 11 12 13 14 15} - do_execsql_test 2.$i.4 { PRAGMA integrity_check } {ok} - db close + + sqlite3 db test.db + do_execsql_test $tn.delay=$iDelay { + SELECT * FROM t1; + PRAGMA integrity_check; + } {1 2 100 7 8 9 10 11 12 13 14 15 ok} + db close + } +} + +for {set nPre 0} {$nPre < $ota_num_steps} {incr nPre} { + for {set is 1} {$is <= ($ota_num_steps - $nPre)} {incr is} { + do_ota_crash_test 2.pre=$nPre.step=$is $nPre $is + } } finish_test diff --git a/ext/ota/sqlite3ota.c b/ext/ota/sqlite3ota.c index 07d941d048..d2f8d99ec8 100644 --- a/ext/ota/sqlite3ota.c +++ b/ext/ota/sqlite3ota.c @@ -2587,24 +2587,26 @@ sqlite3ota *sqlite3ota_open(const char *zTarget, const char *zOta){ } assert( p->rc!=SQLITE_OK || p->eStage!=0 ); - if( p->rc==SQLITE_OK - && (p->eStage==OTA_STAGE_OAL || p->eStage==OTA_STAGE_MOVE) - ){ - /* Check that this is not a wal mode database. If it is, it cannot - ** be updated. */ - if( p->pTargetFd->pWalFd ){ + if( p->rc==SQLITE_OK && p->pTargetFd->pWalFd ){ + if( p->eStage==OTA_STAGE_OAL ){ p->rc = SQLITE_ERROR; p->zErrmsg = sqlite3_mprintf("cannot update wal mode database"); + }else if( p->eStage==OTA_STAGE_MOVE ){ + p->eStage = OTA_STAGE_CKPT; + p->nStep = 0; } + } + if( p->rc==SQLITE_OK + && (p->eStage==OTA_STAGE_OAL || p->eStage==OTA_STAGE_MOVE) + && pState->eStage!=0 && p->pTargetFd->iCookie!=pState->iCookie + ){ /* At this point (pTargetFd->iCookie) contains the value of the ** change-counter cookie (the thing that gets incremented when a ** transaction is committed in rollback mode) currently stored on ** page 1 of the database file. */ - else if( pState->eStage!=0 && p->pTargetFd->iCookie!=pState->iCookie ){ - p->rc = SQLITE_BUSY; - p->zErrmsg = sqlite3_mprintf("database modified during ota update"); - } + p->rc = SQLITE_BUSY; + p->zErrmsg = sqlite3_mprintf("database modified during ota update"); } if( p->rc==SQLITE_OK ){ diff --git a/manifest b/manifest index 0f80d215b4..3e7fe6ced6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\ssome\sproblems\swith\sresuming\sota\supdates\sif\ssaving\sthe\sstate\sis\sinterrupted\sby\sa\spower\sfailure\sor\ssystem\scrash. -D 2015-02-21T20:08:25.212 +C Improve\stests\sfor\sresuming\sota\supdates\sfollowing\spower\sfailures.\sFix\sa\sproblem\srevealed\sby\sthe\ssame. +D 2015-02-23T12:22:55.407 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 6b9e7677829aa94b9f30949656e27312aefb9a46 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -135,10 +135,10 @@ F ext/ota/ota7.test 1fe2c5761705374530e29f70c39693076028221a F ext/ota/ota8.test cd70e63a0c29c45c0906692827deafa34638feda F ext/ota/ota9.test d3eee95dd836824d07a22e5efcdb7bf6e869358b F ext/ota/otaA.test ef4bfa8cfd4ed814ae86f7457b64aa2f18c90171 -F ext/ota/otacrash.test dc036d06dc711ffc4c359851258a2f9ab64135e5 +F ext/ota/otacrash.test a078d34e2edbcedac5f894e3e7d08d452a327007 F ext/ota/otafault.test 8c43586c2b96ca16bbce00b5d7e7d67316126db8 F ext/ota/otafault2.test fa202a98ca221faec318f3e5c5f39485b1256561 -F ext/ota/sqlite3ota.c 3ee4de29a1fec09e8923d39246b72e9b79ff50bc +F ext/ota/sqlite3ota.c 7949ecd5b100da558a073bc7800971e3da822fb2 F ext/ota/sqlite3ota.h 052d87068751810a9dfba1a48954271501bb728f F ext/ota/test_ota.c 9ec6ea945282f65f67f0e0468dad79a489818f44 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 @@ -1258,7 +1258,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 718fd8b673d6557dd0eaad03e6a3332b5490afbf -R 7a06fb426588c48f2ea734b4acf1f016 +P 6d5ed70d0dbabe9c2ab2f2dba47747d17d937781 +R 4c48a15e3fb052167c1c2cb6db2c19fe U dan -Z fe836bec0d39c3ec7b14b6776ea334a3 +Z 4ecb7af4e3b45df7793dc31c4cb806df diff --git a/manifest.uuid b/manifest.uuid index b39bfd65f9..2e369faa1b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6d5ed70d0dbabe9c2ab2f2dba47747d17d937781 \ No newline at end of file +1cb675e5392f179516d8e7a52760922a6c7df4d0 \ No newline at end of file