/ Check-in [6806b9ec]
Login

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

Overview
Comment:Make sure that the database size cache in the pager is invalidated whenever the database is unlocked. A stale value in the database size cache can result in database corruption on a heavily loaded system running autovacuum. (CVS 3548)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:6806b9ecb5e3b90e793c5862404e76485df33b25
User & Date: drh 2007-01-03 15:34:30
Context
2007-01-03
23:36
Additional changes in the pager and os interface layers to fix problems that might be contributing to recently observed database corruption. (CVS 3549) check-in: a593d574 user: drh tags: trunk
15:34
Make sure that the database size cache in the pager is invalidated whenever the database is unlocked. A stale value in the database size cache can result in database corruption on a heavily loaded system running autovacuum. (CVS 3548) check-in: 6806b9ec user: drh tags: trunk
2007-01-02
18:41
Update the vtab_err test to check for -DSQLITE_MEMDEBUG=1 and skip the tests if missing. Pager is more careful to clear its file size cache. Remove an assert() in VDBE that might fail on a corrupt database file. (CVS 3547) check-in: bf1afd01 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/pager.c.

    14     14   ** The pager is used to access a database disk file.  It implements
    15     15   ** atomic commit and rollback through the use of a journal file that
    16     16   ** is separate from the database file.  The pager also implements file
    17     17   ** locking to prevent two processes from writing the same database
    18     18   ** file simultaneously, or one process from reading the database while
    19     19   ** another is writing.
    20     20   **
    21         -** @(#) $Id: pager.c,v 1.278 2007/01/02 18:41:55 drh Exp $
           21  +** @(#) $Id: pager.c,v 1.279 2007/01/03 15:34:30 drh Exp $
    22     22   */
    23     23   #ifndef SQLITE_OMIT_DISKIO
    24     24   #include "sqliteInt.h"
    25     25   #include "os.h"
    26     26   #include "pager.h"
    27     27   #include <assert.h>
    28     28   #include <string.h>
................................................................................
   845    845     if( pPager->aHash==0 ) return 0;
   846    846     p = pPager->aHash[pgno & (pPager->nHash-1)];
   847    847     while( p && p->pgno!=pgno ){
   848    848       p = p->pNextHash;
   849    849     }
   850    850     return p;
   851    851   }
          852  +
          853  +/*
          854  +** Unlock the database file.
          855  +**
          856  +** Once all locks have been removed from the database file, other
          857  +** processes or threads might change the file.  So make sure all of
          858  +** our internal cache is invalidated.
          859  +*/
          860  +static void pager_unlock(Pager *pPager){
          861  +  if( !MEMDB ){
          862  +    sqlite3OsUnlock(pPager->fd, NO_LOCK);
          863  +    pPager->dbSize = -1;
          864  +  }
          865  +  pPager->state = PAGER_UNLOCK;
          866  +}
          867  +
   852    868   
   853    869   /*
   854    870   ** Unlock the database and clear the in-memory cache.  This routine
   855    871   ** sets the state of the pager back to what it was when it was first
   856    872   ** opened.  Any outstanding pages are invalidated and subsequent attempts
   857    873   ** to access those pages will likely result in a coredump.
   858    874   */
................................................................................
   870    886     pPager->nHash = 0;
   871    887     sqliteFree(pPager->aHash);
   872    888     pPager->nPage = 0;
   873    889     pPager->aHash = 0;
   874    890     if( pPager->state>=PAGER_RESERVED ){
   875    891       sqlite3pager_rollback(pPager);
   876    892     }
   877         -  sqlite3OsUnlock(pPager->fd, NO_LOCK);
   878         -  pPager->state = PAGER_UNLOCK;
   879         -  pPager->dbSize = -1;
          893  +  pager_unlock(pPager);
   880    894     pPager->nRef = 0;
   881    895     assert( pPager->journalOpen==0 );
   882    896   }
   883    897   
   884    898   /*
   885    899   ** When this routine is called, the pager has the journal file open and
   886    900   ** a RESERVED or EXCLUSIVE lock on the database.  This routine releases
................................................................................
  1421   1435     }
  1422   1436     
  1423   1437     /* Truncate the database back to its original size.
  1424   1438     */
  1425   1439     if( pPager->state>=PAGER_EXCLUSIVE ){
  1426   1440       rc = pager_truncate(pPager, pPager->stmtSize);
  1427   1441     }
         1442  +  assert( pPager->state>=PAGER_SHARED );
  1428   1443     pPager->dbSize = pPager->stmtSize;
  1429   1444   
  1430   1445     /* Figure out how many records are in the statement journal.
  1431   1446     */
  1432   1447     assert( pPager->stmtInUse && pPager->journalOpen );
  1433   1448     sqlite3OsSeek(pPager->stfd, 0);
  1434   1449     nRec = pPager->stmtNRec;
................................................................................
  1970   1985   ** false or until the lock succeeds.
  1971   1986   **
  1972   1987   ** Return SQLITE_OK on success and an error code if we cannot obtain
  1973   1988   ** the lock.
  1974   1989   */
  1975   1990   static int pager_wait_on_lock(Pager *pPager, int locktype){
  1976   1991     int rc;
         1992  +
         1993  +  /* The OS lock values must be the same as the Pager lock values */
  1977   1994     assert( PAGER_SHARED==SHARED_LOCK );
  1978   1995     assert( PAGER_RESERVED==RESERVED_LOCK );
  1979   1996     assert( PAGER_EXCLUSIVE==EXCLUSIVE_LOCK );
         1997  +
         1998  +  /* If the file is currently unlocked then the size must be unknown */
         1999  +  assert( pPager->state>=PAGER_SHARED || pPager->dbSize<0 || MEMDB );
         2000  +
  1980   2001     if( pPager->state>=locktype ){
  1981   2002       rc = SQLITE_OK;
  1982   2003     }else{
  1983   2004       do {
  1984   2005         rc = sqlite3OsLock(pPager->fd, locktype);
  1985   2006       }while( rc==SQLITE_BUSY && sqlite3InvokeBusyHandler(pPager->pBusyHandler) );
  1986   2007       if( rc==SQLITE_OK ){
................................................................................
  1991   2012   }
  1992   2013   
  1993   2014   /*
  1994   2015   ** Truncate the file to the number of pages specified.
  1995   2016   */
  1996   2017   int sqlite3pager_truncate(Pager *pPager, Pgno nPage){
  1997   2018     int rc;
         2019  +  assert( pPager->state>=PAGER_SHARED || MEMDB );
  1998   2020     sqlite3pager_pagecount(pPager);
  1999   2021     if( pPager->errCode ){
  2000   2022       rc = pPager->errCode;
  2001   2023       return rc;
  2002   2024     }
  2003   2025     if( nPage>=(unsigned)pPager->dbSize ){
  2004   2026       return SQLITE_OK;
................................................................................
  2060   2082         /* We ignore any IO errors that occur during the rollback
  2061   2083         ** operation. So disable IO error simulation so that testing
  2062   2084         ** works more easily.
  2063   2085         */
  2064   2086         disable_simulated_io_errors();
  2065   2087         sqlite3pager_rollback(pPager);
  2066   2088         enable_simulated_io_errors();
  2067         -      if( !MEMDB ){
  2068         -        sqlite3OsUnlock(pPager->fd, NO_LOCK);
  2069         -      }
         2089  +      pager_unlock(pPager);
  2070   2090         assert( pPager->errCode || pPager->journalOpen==0 );
  2071   2091         break;
  2072   2092       }
  2073   2093       case PAGER_SHARED: {
  2074         -      if( !MEMDB ){
  2075         -        sqlite3OsUnlock(pPager->fd, NO_LOCK);
  2076         -      }
         2094  +      pager_unlock(pPager);
  2077   2095         break;
  2078   2096       }
  2079   2097       default: {
  2080   2098         /* Do nothing */
  2081   2099         break;
  2082   2100       }
  2083   2101     }
................................................................................
  2670   2688          ** 
  2671   2689          ** Because the intermediate RESERVED lock is not requested, the
  2672   2690          ** second process will get to this point in the code and fail to
  2673   2691          ** obtain it's own EXCLUSIVE lock on the database file.
  2674   2692          */
  2675   2693          rc = sqlite3OsLock(pPager->fd, EXCLUSIVE_LOCK);
  2676   2694          if( rc!=SQLITE_OK ){
  2677         -         sqlite3OsUnlock(pPager->fd, NO_LOCK);
  2678         -         pPager->state = PAGER_UNLOCK;
         2695  +         pager_unlock(pPager);
  2679   2696            return pager_error(pPager, rc);
  2680   2697          }
  2681   2698          pPager->state = PAGER_EXCLUSIVE;
  2682   2699   
  2683   2700          /* Open the journal for reading only.  Return SQLITE_BUSY if
  2684   2701          ** we are unable to open the journal file. 
  2685   2702          **
................................................................................
  2686   2703          ** The journal file does not need to be locked itself.  The
  2687   2704          ** journal file is never open unless the main database file holds
  2688   2705          ** a write lock, so there is never any chance of two or more
  2689   2706          ** processes opening the journal at the same time.
  2690   2707          */
  2691   2708          rc = sqlite3OsOpenReadOnly(pPager->zJournal, &pPager->jfd);
  2692   2709          if( rc!=SQLITE_OK ){
  2693         -         sqlite3OsUnlock(pPager->fd, NO_LOCK);
  2694         -         pPager->state = PAGER_UNLOCK;
         2710  +         pager_unlock(pPager);
  2695   2711            return SQLITE_BUSY;
  2696   2712          }
  2697   2713          pPager->journalOpen = 1;
  2698   2714          pPager->journalStarted = 0;
  2699   2715          pPager->journalOff = 0;
  2700   2716          pPager->setMaster = 0;
  2701   2717          pPager->journalHdr = 0;
................................................................................
  2969   2985       /* If this was a malloc() failure, then we will not be closing the pager
  2970   2986       ** file. So delete any journal file we may have just created. Otherwise,
  2971   2987       ** the system will get confused, we have a read-lock on the file and a
  2972   2988       ** mysterious journal has appeared in the filesystem.
  2973   2989       */
  2974   2990       sqlite3OsDelete(pPager->zJournal);
  2975   2991     }else{
  2976         -    sqlite3OsUnlock(pPager->fd, NO_LOCK);
  2977         -    pPager->state = PAGER_UNLOCK;
         2992  +    pager_unlock(pPager);
  2978   2993     }
  2979   2994     return rc;
  2980   2995   }
  2981   2996   
  2982   2997   /*
  2983   2998   ** Acquire a write-lock on the database.  The lock is removed when
  2984   2999   ** the any of the following happen:
................................................................................
  3229   3244         }
  3230   3245         page_add_to_stmt_list(pPg);
  3231   3246       }
  3232   3247     }
  3233   3248   
  3234   3249     /* Update the database size and return.
  3235   3250     */
         3251  +  assert( pPager->state>=PAGER_SHARED );
  3236   3252     if( pPager->dbSize<(int)pPg->pgno ){
  3237   3253       pPager->dbSize = pPg->pgno;
  3238   3254       if( !MEMDB && pPager->dbSize==PENDING_BYTE/pPager->pageSize ){
  3239   3255         pPager->dbSize++;
  3240   3256       }
  3241   3257     }
  3242   3258     return rc;
................................................................................
  3304   3320   
  3305   3321     if( MEMDB ) return;
  3306   3322   
  3307   3323     pPg = pager_lookup(pPager, pgno);
  3308   3324     assert( pPg!=0 );  /* We never call _dont_write unless the page is in mem */
  3309   3325     pPg->alwaysRollback = 1;
  3310   3326     if( pPg->dirty && !pPager->stmtInUse ){
         3327  +    assert( pPager->state>=PAGER_SHARED );
  3311   3328       if( pPager->dbSize==(int)pPg->pgno && pPager->origDbSize<pPager->dbSize ){
  3312   3329         /* If this pages is the last page in the file and the file has grown
  3313   3330         ** during the current transaction, then do NOT mark the page as clean.
  3314   3331         ** When the database file grows, we must make sure that the last page
  3315   3332         ** gets written at least once so that the disk file will be the correct
  3316   3333         ** size. If you do not write this page and the size of the file
  3317   3334         ** on the disk ends up being too small, that can lead to database
................................................................................
  3540   3557   ** open.  A new statement journal is created that can be used to rollback
  3541   3558   ** changes of a single SQL command within a larger transaction.
  3542   3559   */
  3543   3560   int sqlite3pager_stmt_begin(Pager *pPager){
  3544   3561     int rc;
  3545   3562     char zTemp[SQLITE_TEMPNAME_SIZE];
  3546   3563     assert( !pPager->stmtInUse );
         3564  +  assert( pPager->state>=PAGER_SHARED );
  3547   3565     assert( pPager->dbSize>=0 );
  3548   3566     TRACE2("STMT-BEGIN %d\n", PAGERID(pPager));
  3549   3567     if( MEMDB ){
  3550   3568       pPager->stmtInUse = 1;
  3551   3569       pPager->stmtSize = pPager->dbSize;
  3552   3570       return SQLITE_OK;
  3553   3571     }