/ Check-in [3d61da4a]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Fix some problems to do with temp-file databases and recovering from IO and SQLITE_FULL errors.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | tempfiles-25
Files: files | file ages | folders
SHA1: 3d61da4a76af8c9c2a293df085f3ed5a7bb447df
User & Date: dan 2016-04-23 14:55:28
Context
2016-04-23
17:24
Fix a problem with mixing temp-files and mmap-mode. check-in: c80c5c62 user: dan tags: tempfiles-25
14:55
Fix some problems to do with temp-file databases and recovering from IO and SQLITE_FULL errors. check-in: 3d61da4a user: dan tags: tempfiles-25
2016-04-21
15:24
Add a function prototype in order to fix a compiler warning. check-in: 49aec971 user: drh tags: tempfiles-25
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/pager.c.

  1820   1820     ** it can safely move back to PAGER_OPEN state. This happens in both
  1821   1821     ** normal and exclusive-locking mode.
  1822   1822     **
  1823   1823     ** Exception: There is no way out of the error state for temp files.
  1824   1824     ** This is because it is not possible to call pager_reset() on a temp
  1825   1825     ** file pager (as this may discard the only copy of some data).  */
  1826   1826     assert( pPager->errCode==SQLITE_OK || !MEMDB );
  1827         -  if( pPager->tempFile==0 && pPager->errCode ){
  1828         -    pager_reset(pPager);
  1829         -    pPager->changeCountDone = 0;
  1830         -    pPager->eState = PAGER_OPEN;
  1831         -    pPager->errCode = SQLITE_OK;
         1827  +  if( pPager->errCode ){
         1828  +    if( pPager->tempFile==0 ){
         1829  +      pager_reset(pPager);
         1830  +      pPager->changeCountDone = 0;
         1831  +      pPager->eState = PAGER_OPEN;
         1832  +    }else{
         1833  +      pPager->eState = (isOpen(pPager->jfd) ? PAGER_OPEN : PAGER_READER);
         1834  +    }
  1832   1835       if( USEFETCH(pPager) ) sqlite3OsUnfetch(pPager->fd, 0, 0);
         1836  +    pPager->errCode = SQLITE_OK;
  1833   1837     }
  1834   1838   
  1835   1839     pPager->journalOff = 0;
  1836   1840     pPager->journalHdr = 0;
  1837   1841     pPager->setMaster = 0;
  1838   1842   }
  1839   1843   
................................................................................
  2315   2319     */
  2316   2320     if( pagerUseWal(pPager) ){
  2317   2321       pPg = 0;
  2318   2322     }else{
  2319   2323       pPg = sqlite3PagerLookup(pPager, pgno);
  2320   2324     }
  2321   2325     assert( pPg || !MEMDB );
  2322         -  assert( pPager->eState!=PAGER_OPEN || pPg==0 );
         2326  +  assert( pPager->eState!=PAGER_OPEN || pPg==0 || pPager->tempFile );
  2323   2327     PAGERTRACE(("PLAYBACK %d page %d hash(%08x) %s\n",
  2324   2328              PAGERID(pPager), pgno, pager_datahash(pPager->pageSize, (u8*)aData),
  2325   2329              (isMainJrnl?"main-journal":"sub-journal")
  2326   2330     ));
  2327   2331     if( isMainJrnl ){
  2328   2332       isSynced = pPager->noSync || (*pOffset <= pPager->journalHdr);
  2329   2333     }else{
................................................................................
  5048   5052   */
  5049   5053   int sqlite3PagerSharedLock(Pager *pPager){
  5050   5054     int rc = SQLITE_OK;                /* Return code */
  5051   5055   
  5052   5056     /* This routine is only called from b-tree and only when there are no
  5053   5057     ** outstanding pages. This implies that the pager state should either
  5054   5058     ** be OPEN or READER. READER is only possible if the pager is or was in 
  5055         -  ** exclusive access mode.
  5056         -  */
         5059  +  ** exclusive access mode.  */
  5057   5060     assert( sqlite3PcacheRefCount(pPager->pPCache)==0 );
  5058   5061     assert( assert_pager_state(pPager) );
  5059         -  if( pPager->tempFile && pPager->errCode ) { return pPager->errCode; }
  5060   5062     assert( pPager->eState==PAGER_OPEN || pPager->eState==PAGER_READER );
         5063  +  assert( pPager->errCode==SQLITE_OK );
  5061   5064   
  5062   5065     if( !pagerUseWal(pPager) && pPager->eState==PAGER_OPEN ){
  5063   5066       int bHotJournal = 1;          /* True if there exists a hot journal-file */
  5064   5067   
  5065   5068       assert( !MEMDB );
         5069  +    assert( pPager->tempFile==0 || pPager->eLock==EXCLUSIVE_LOCK );
  5066   5070   
  5067   5071       rc = pager_wait_on_lock(pPager, SHARED_LOCK);
  5068   5072       if( rc!=SQLITE_OK ){
  5069   5073         assert( pPager->eLock==NO_LOCK || pPager->eLock==UNKNOWN_LOCK );
  5070   5074         goto failed;
  5071   5075       }
  5072   5076   
................................................................................
  5144   5148         ** probably did not sync it and we are required to always sync
  5145   5149         ** the journal before playing it back.
  5146   5150         */
  5147   5151         if( isOpen(pPager->jfd) ){
  5148   5152           assert( rc==SQLITE_OK );
  5149   5153           rc = pagerSyncHotJournal(pPager);
  5150   5154           if( rc==SQLITE_OK ){
  5151         -          rc = pager_playback(pPager, 1);
         5155  +          rc = pager_playback(pPager, !pPager->tempFile);
  5152   5156             pPager->eState = PAGER_OPEN;
  5153   5157           }
  5154   5158         }else if( !pPager->exclusiveMode ){
  5155   5159           pagerUnlockDb(pPager, SHARED_LOCK);
  5156   5160         }
  5157   5161   
  5158   5162         if( rc!=SQLITE_OK ){
................................................................................
  5240   5244     }
  5241   5245   
  5242   5246     if( pagerUseWal(pPager) ){
  5243   5247       assert( rc==SQLITE_OK );
  5244   5248       rc = pagerBeginReadTransaction(pPager);
  5245   5249     }
  5246   5250   
  5247         -  if( pPager->eState==PAGER_OPEN && rc==SQLITE_OK ){
         5251  +  if( pPager->tempFile==0 && pPager->eState==PAGER_OPEN && rc==SQLITE_OK ){
  5248   5252       rc = pagerPagecount(pPager, &pPager->dbSize);
  5249   5253     }
  5250   5254   
  5251   5255    failed:
  5252   5256     if( rc!=SQLITE_OK ){
  5253   5257       assert( !MEMDB );
  5254   5258       pager_unlock(pPager);

Changes to test/tempfault.test.

    14     14   #
    15     15   
    16     16   set testdir [file dirname $argv0]
    17     17   source $testdir/tester.tcl
    18     18   source $testdir/malloc_common.tcl
    19     19   set testprefix tempfault
    20     20   
    21         -sqlite3_memdebug_vfs_oom_test 0
           21  +# sqlite3_memdebug_vfs_oom_test 0
    22     22   
    23         -do_faultsim_test 1 -faults oom* -prep {
           23  +do_faultsim_test 1 -faults * -prep {
    24     24     sqlite3 db ""
    25     25     db eval {
    26     26       PRAGMA page_size = 1024;
    27     27       CREATE TABLE t1(a, b);
    28     28       INSERT INTO t1 VALUES(1, 2);
    29     29       INSERT INTO t1 VALUES(3, 4);
    30     30     }
................................................................................
    38     38     }
    39     39     if {$testrc==0 && $msg != "1 2 3 4 5 6"} {
    40     40       error "data mismatch 2: $msg"
    41     41     }
    42     42     faultsim_integrity_check
    43     43   }
    44     44   
    45         -do_faultsim_test 2 -faults oom* -prep {
           45  +do_faultsim_test 2 -faults * -prep {
    46     46     sqlite3 db ""
    47     47     db eval {
    48     48       PRAGMA page_size = 1024;
    49     49       PRAGMA cache_size = 10;
    50     50       CREATE TABLE t1(a, b);
    51     51       CREATE INDEX i1 ON t1(b, a);
    52         -    WITH x(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<50)
           52  +    WITH x(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<100)
    53     53       INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM x;
    54     54     }
    55     55   } -body {
    56     56     execsql { UPDATE t1 SET a = randomblob(99) }
    57     57   } -test {
    58     58     faultsim_test_result {0 {}}
    59     59     faultsim_integrity_check db
    60     60   }
    61     61   
    62         -do_faultsim_test 3 -faults oom* -prep {
           62  +catch { db close }
           63  +do_faultsim_test 2.1 -faults * -prep {
           64  +  if {[info commands db]==""} {
           65  +    sqlite3 db ""
           66  +    execsql {
           67  +      PRAGMA page_size = 1024;
           68  +      PRAGMA cache_size = 10;
           69  +      CREATE TABLE t1(a, b);
           70  +      CREATE INDEX i1 ON t1(b, a);
           71  +      WITH x(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<100)
           72  +          INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM x;
           73  +    }
           74  +  } 
           75  +} -body {
           76  +  execsql { UPDATE t1 SET a = randomblob(99) }
           77  +} -test {
           78  +  faultsim_test_result {0 {}}
           79  +  faultsim_integrity_check db
           80  +}
           81  +
           82  +do_faultsim_test 3 -faults * -prep {
    63     83     sqlite3 db ""
    64     84     db eval {
    65     85       PRAGMA page_size = 1024;
    66     86       PRAGMA cache_size = 10;
    67     87       CREATE TABLE t1(a, b);
    68     88       CREATE INDEX i1 ON t1(b, a);
    69     89       WITH x(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<50)