From 6572c16ae1a1f554475c4993eb0c753a2c5cf8d9 Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 23 Apr 2016 14:55:28 +0000 Subject: [PATCH] Fix some problems to do with temp-file databases and recovering from IO and SQLITE_FULL errors. FossilOrigin-Name: 3d61da4a76af8c9c2a293df085f3ed5a7bb447df --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/pager.c | 26 +++++++++++++++----------- test/tempfault.test | 30 +++++++++++++++++++++++++----- 4 files changed, 49 insertions(+), 25 deletions(-) diff --git a/manifest b/manifest index 8a5fd27015..ec3e51504b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sa\sfunction\sprototype\sin\sorder\sto\sfix\sa\scompiler\swarning. -D 2016-04-21T15:24:46.372 +C Fix\ssome\sproblems\sto\sdo\swith\stemp-file\sdatabases\sand\srecovering\sfrom\sIO\sand\sSQLITE_FULL\serrors. +D 2016-04-23T14:55:28.020 F Makefile.in eba680121821b8a60940a81454316f47a341487a F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 71b8b16cf9393f68e2e2035486ca104872558836 @@ -362,7 +362,7 @@ F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa F src/os_unix.c d0b41a47eb5f0dc00e423a1723aadeab0e78c85f F src/os_win.c 1997a873bfc8296a701bd8e2df8c3d5da5afe956 F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca -F src/pager.c bb8c7ff706aa88e7c2ec9a6175a128c01bc3ae5f +F src/pager.c 4981dc6154ce111361a7cd35eaa26aadf8914ea3 F src/pager.h 329bdf078a4e0a3b35084534d58625d21fd03681 F src/parse.y 10eb2f3fb62341291528c7984498054731f9d31e F src/pcache.c b3230ecfc7f797063fbe167f2845da363e8f07f8 @@ -1109,7 +1109,7 @@ F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126 F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930 F test/tclsqlite.test e1306001a0ca92250b691ea6d3cecaca5b6342aa F test/tempdb.test bd92eba8f20e16a9136e434e20b280794de3cdb6 -F test/tempfault.test 0c80f23c651cf6452c27cacf09f4c2ee9527a912 +F test/tempfault.test 0c0d349c9a99bf5f374655742577f8712c647900 F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30 F test/temptable2.test e62783549be26283e1b3725f0de3309411be6c84 F test/temptrigger.test 8ec228b0db5d7ebc4ee9b458fc28cb9e7873f5e1 @@ -1484,7 +1484,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P cc28106e5c196c0a9678fbbd06f6afd49271a8e8 -R c97bc8da233adc2bbb054b217c885bd5 -U drh -Z fa8f1e96dc1996c819bff77f7b75b34d +P 49aec9718d61c9f12aed96f530128666c3b01c81 +R 98471ae1c4ed8f399ba91e3e119d0ef8 +U dan +Z 4115a15d29a4b7f5f76b2491e48cc4f1 diff --git a/manifest.uuid b/manifest.uuid index 31bd76e737..7b1996a745 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -49aec9718d61c9f12aed96f530128666c3b01c81 \ No newline at end of file +3d61da4a76af8c9c2a293df085f3ed5a7bb447df \ No newline at end of file diff --git a/src/pager.c b/src/pager.c index 41d3297e29..a749b8a6b3 100644 --- a/src/pager.c +++ b/src/pager.c @@ -1824,12 +1824,16 @@ static void pager_unlock(Pager *pPager){ ** This is because it is not possible to call pager_reset() on a temp ** file pager (as this may discard the only copy of some data). */ assert( pPager->errCode==SQLITE_OK || !MEMDB ); - if( pPager->tempFile==0 && pPager->errCode ){ - pager_reset(pPager); - pPager->changeCountDone = 0; - pPager->eState = PAGER_OPEN; - pPager->errCode = SQLITE_OK; + if( pPager->errCode ){ + if( pPager->tempFile==0 ){ + pager_reset(pPager); + pPager->changeCountDone = 0; + pPager->eState = PAGER_OPEN; + }else{ + pPager->eState = (isOpen(pPager->jfd) ? PAGER_OPEN : PAGER_READER); + } if( USEFETCH(pPager) ) sqlite3OsUnfetch(pPager->fd, 0, 0); + pPager->errCode = SQLITE_OK; } pPager->journalOff = 0; @@ -2319,7 +2323,7 @@ static int pager_playback_one_page( pPg = sqlite3PagerLookup(pPager, pgno); } assert( pPg || !MEMDB ); - assert( pPager->eState!=PAGER_OPEN || pPg==0 ); + assert( pPager->eState!=PAGER_OPEN || pPg==0 || pPager->tempFile ); PAGERTRACE(("PLAYBACK %d page %d hash(%08x) %s\n", PAGERID(pPager), pgno, pager_datahash(pPager->pageSize, (u8*)aData), (isMainJrnl?"main-journal":"sub-journal") @@ -5052,17 +5056,17 @@ int sqlite3PagerSharedLock(Pager *pPager){ /* This routine is only called from b-tree and only when there are no ** outstanding pages. This implies that the pager state should either ** be OPEN or READER. READER is only possible if the pager is or was in - ** exclusive access mode. - */ + ** exclusive access mode. */ assert( sqlite3PcacheRefCount(pPager->pPCache)==0 ); assert( assert_pager_state(pPager) ); - if( pPager->tempFile && pPager->errCode ) { return pPager->errCode; } assert( pPager->eState==PAGER_OPEN || pPager->eState==PAGER_READER ); + assert( pPager->errCode==SQLITE_OK ); if( !pagerUseWal(pPager) && pPager->eState==PAGER_OPEN ){ int bHotJournal = 1; /* True if there exists a hot journal-file */ assert( !MEMDB ); + assert( pPager->tempFile==0 || pPager->eLock==EXCLUSIVE_LOCK ); rc = pager_wait_on_lock(pPager, SHARED_LOCK); if( rc!=SQLITE_OK ){ @@ -5148,7 +5152,7 @@ int sqlite3PagerSharedLock(Pager *pPager){ assert( rc==SQLITE_OK ); rc = pagerSyncHotJournal(pPager); if( rc==SQLITE_OK ){ - rc = pager_playback(pPager, 1); + rc = pager_playback(pPager, !pPager->tempFile); pPager->eState = PAGER_OPEN; } }else if( !pPager->exclusiveMode ){ @@ -5244,7 +5248,7 @@ int sqlite3PagerSharedLock(Pager *pPager){ rc = pagerBeginReadTransaction(pPager); } - if( pPager->eState==PAGER_OPEN && rc==SQLITE_OK ){ + if( pPager->tempFile==0 && pPager->eState==PAGER_OPEN && rc==SQLITE_OK ){ rc = pagerPagecount(pPager, &pPager->dbSize); } diff --git a/test/tempfault.test b/test/tempfault.test index da1ae12375..4eae116a72 100644 --- a/test/tempfault.test +++ b/test/tempfault.test @@ -18,9 +18,9 @@ source $testdir/tester.tcl source $testdir/malloc_common.tcl set testprefix tempfault -sqlite3_memdebug_vfs_oom_test 0 +# sqlite3_memdebug_vfs_oom_test 0 -do_faultsim_test 1 -faults oom* -prep { +do_faultsim_test 1 -faults * -prep { sqlite3 db "" db eval { PRAGMA page_size = 1024; @@ -42,14 +42,14 @@ do_faultsim_test 1 -faults oom* -prep { faultsim_integrity_check } -do_faultsim_test 2 -faults oom* -prep { +do_faultsim_test 2 -faults * -prep { sqlite3 db "" db eval { PRAGMA page_size = 1024; PRAGMA cache_size = 10; CREATE TABLE t1(a, b); CREATE INDEX i1 ON t1(b, a); - WITH x(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<50) + WITH x(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<100) INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM x; } } -body { @@ -59,7 +59,27 @@ do_faultsim_test 2 -faults oom* -prep { faultsim_integrity_check db } -do_faultsim_test 3 -faults oom* -prep { +catch { db close } +do_faultsim_test 2.1 -faults * -prep { + if {[info commands db]==""} { + sqlite3 db "" + execsql { + PRAGMA page_size = 1024; + PRAGMA cache_size = 10; + CREATE TABLE t1(a, b); + CREATE INDEX i1 ON t1(b, a); + WITH x(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<100) + INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM x; + } + } +} -body { + execsql { UPDATE t1 SET a = randomblob(99) } +} -test { + faultsim_test_result {0 {}} + faultsim_integrity_check db +} + +do_faultsim_test 3 -faults * -prep { sqlite3 db "" db eval { PRAGMA page_size = 1024;