/ Check-in [7222ad26]
Login

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

Overview
Comment:Simplifications to pager.c in support of structural coverage testing. (CVS 6927)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 7222ad2667b95d6021d9ae47f548b76b224f46aa
User & Date: drh 2009-07-24 16:32:01
Context
2009-07-24
17:58
Allow virtual tables to be used in shared-cache mode. (CVS 6928) check-in: 5d9e767a user: danielk1977 tags: trunk
16:32
Simplifications to pager.c in support of structural coverage testing. (CVS 6927) check-in: 7222ad26 user: drh tags: trunk
12:35
Simplifications and comment improvements in pager.c. (CVS 6926) check-in: 2d2f42ca 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.614 2009/07/24 12:35:57 drh Exp $
           21  +** @(#) $Id: pager.c,v 1.615 2009/07/24 16:32:01 drh Exp $
    22     22   */
    23     23   #ifndef SQLITE_OMIT_DISKIO
    24     24   #include "sqliteInt.h"
    25     25   
    26     26   /*
    27     27   ** Macros for troubleshooting.  Normally turned off
    28     28   */
................................................................................
  3946   3946   ** returns NULL if the page is not in cache or if a disk I/O error 
  3947   3947   ** has ever happened.
  3948   3948   */
  3949   3949   DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){
  3950   3950     PgHdr *pPg = 0;
  3951   3951     assert( pPager!=0 );
  3952   3952     assert( pgno!=0 );
  3953         -
  3954         -  if( (pPager->state!=PAGER_UNLOCK)
  3955         -   && (pPager->errCode==SQLITE_OK || pPager->errCode==SQLITE_FULL)
  3956         -  ){
  3957         -    sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &pPg);
  3958         -  }
  3959         -
         3953  +  assert( pPager->pPCache!=0 );
         3954  +  assert( pPager->state > PAGER_UNLOCK );
         3955  +  sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &pPg);
  3960   3956     return pPg;
  3961   3957   }
  3962   3958   
  3963   3959   /*
  3964   3960   ** Release a page reference.
  3965   3961   **
  3966   3962   ** If the number of references to the page drop to zero, then the
................................................................................
  4023   4019     int rc = SQLITE_OK;                        /* Return code */
  4024   4020     sqlite3_vfs * const pVfs = pPager->pVfs;   /* Local cache of vfs pointer */
  4025   4021   
  4026   4022     assert( pPager->state>=PAGER_RESERVED );
  4027   4023     assert( pPager->useJournal );
  4028   4024     assert( pPager->pInJournal==0 );
  4029   4025     
  4030         -  /* If already in the error state, this function is a no-op. */
  4031         -  if( pPager->errCode ){
  4032         -    return pPager->errCode;
  4033         -  }
         4026  +  /* If already in the error state, this function is a no-op.  But on
         4027  +  ** the other hand, this routine is never called if we are already in
         4028  +  ** an error state. */
         4029  +  if( NEVER(pPager->errCode) ) return pPager->errCode;
  4034   4030   
  4035   4031     /* TODO: Is it really possible to get here with dbSizeValid==0? If not,
  4036   4032     ** the call to PagerPagecount() can be removed.
  4037   4033     */
  4038   4034     testcase( pPager->dbSizeValid==0 );
  4039   4035     sqlite3PagerPagecount(pPager, 0);
  4040   4036   
................................................................................
  4180   4176   ** of any open savepoints as appropriate.
  4181   4177   */
  4182   4178   static int pager_write(PgHdr *pPg){
  4183   4179     void *pData = pPg->pData;
  4184   4180     Pager *pPager = pPg->pPager;
  4185   4181     int rc = SQLITE_OK;
  4186   4182   
  4187         -  /* Check for errors
         4183  +  /* If an error has been previously detected, we should not be
         4184  +  ** calling this routine.  Repeat the error for robustness.
  4188   4185     */
  4189         -  if( pPager->errCode ){ 
  4190         -    return pPager->errCode;
  4191         -  }
  4192         -  if( pPager->readOnly ){
  4193         -    return SQLITE_PERM;
  4194         -  }
         4186  +  if( NEVER(pPager->errCode) )  return pPager->errCode;
         4187  +
         4188  +  /* Higher-level routines never call this function if database is not
         4189  +  ** writable.  But check anyway, just for robustness. */
         4190  +  if( NEVER(pPager->readOnly) ) return SQLITE_PERM;
  4195   4191   
  4196   4192     assert( !pPager->setMaster );
  4197   4193   
  4198   4194     CHECK_PAGE(pPg);
  4199   4195   
  4200   4196     /* Mark the page as dirty.  If the page has already been written
  4201   4197     ** to the journal then we can return right away.
................................................................................
  4500   4496       assert( !pPager->tempFile && isOpen(pPager->fd) );
  4501   4497   
  4502   4498       /* Open page 1 of the file for writing. */
  4503   4499       rc = sqlite3PagerGet(pPager, 1, &pPgHdr);
  4504   4500       assert( pPgHdr==0 || rc==SQLITE_OK );
  4505   4501   
  4506   4502       /* If page one was fetched successfully, and this function is not
  4507         -    ** operating in direct-mode, make page 1 writable.
         4503  +    ** operating in direct-mode, make page 1 writable.  When not in 
         4504  +    ** direct mode, page 1 is always held in cache and hence the PagerGet()
         4505  +    ** above is always successful - hence the ALWAYS on rc==SQLITE_OK.
  4508   4506       */
  4509         -    if( rc==SQLITE_OK && !DIRECT_MODE ){
         4507  +    if( !DIRECT_MODE && ALWAYS(rc==SQLITE_OK) ){
  4510   4508         rc = sqlite3PagerWrite(pPgHdr);
  4511   4509       }
  4512   4510   
  4513   4511       if( rc==SQLITE_OK ){
  4514   4512         /* Increment the value just read and write it back to byte 24. */
  4515   4513         change_counter = sqlite3Get4byte((u8*)pPager->dbFileVers);
  4516   4514         change_counter++;
................................................................................
  4540   4538   ** or pages with the Pager.noSync flag set.
  4541   4539   **
  4542   4540   ** If successful, or called on a pager for which it is a no-op, this
  4543   4541   ** function returns SQLITE_OK. Otherwise, an IO error code is returned.
  4544   4542   */
  4545   4543   int sqlite3PagerSync(Pager *pPager){
  4546   4544     int rc;                              /* Return code */
  4547         -  if( MEMDB || pPager->noSync ){
         4545  +  assert( !MEMDB );
         4546  +  if( pPager->noSync ){
  4548   4547       rc = SQLITE_OK;
  4549   4548     }else{
  4550   4549       rc = sqlite3OsSync(pPager->fd, pPager->sync_flags);
  4551   4550     }
  4552   4551     return rc;
  4553   4552   }
  4554   4553   
................................................................................
  4581   4580   int sqlite3PagerCommitPhaseOne(
  4582   4581     Pager *pPager,                  /* Pager object */
  4583   4582     const char *zMaster,            /* If not NULL, the master journal name */
  4584   4583     int noSync                      /* True to omit the xSync on the db file */
  4585   4584   ){
  4586   4585     int rc = SQLITE_OK;             /* Return code */
  4587   4586   
         4587  +  /* The dbOrigSize is never set if journal_mode=OFF */
         4588  +  assert( pPager->journalMode!=PAGER_JOURNALMODE_OFF || pPager->dbOrigSize==0 );
         4589  +
  4588   4590     /* If a prior error occurred, this routine should not be called.  ROLLBACK
  4589   4591     ** is the appropriate response to an error, not COMMIT.  Guard against
  4590   4592     ** coding errors by repeating the prior error. */
  4591   4593     if( NEVER(pPager->errCode) ) return pPager->errCode;
  4592   4594   
  4593   4595     PAGERTRACE(("DATABASE SYNC: File=%s zMaster=%s nSize=%d\n", 
  4594   4596         pPager->zFilename, zMaster, pPager->dbSize));
................................................................................
  4655   4657       ** file. This can only happen in auto-vacuum mode.
  4656   4658       **
  4657   4659       ** Before reading the pages with page numbers larger than the 
  4658   4660       ** current value of Pager.dbSize, set dbSize back to the value
  4659   4661       ** that it took at the start of the transaction. Otherwise, the
  4660   4662       ** calls to sqlite3PagerGet() return zeroed pages instead of 
  4661   4663       ** reading data from the database file.
         4664  +    **
         4665  +    ** When journal_mode==OFF the dbOrigSize is always zero, so this
         4666  +    ** block never runs if journal_mode=OFF.
  4662   4667       */
  4663   4668   #ifndef SQLITE_OMIT_AUTOVACUUM
  4664         -    if( pPager->dbSize<pPager->dbOrigSize
  4665         -     && pPager->journalMode!=PAGER_JOURNALMODE_OFF 
         4669  +    if( pPager->dbSize<pPager->dbOrigSize 
         4670  +     && ALWAYS(pPager->journalMode!=PAGER_JOURNALMODE_OFF)
  4666   4671       ){
  4667   4672         Pgno i;                                   /* Iterator variable */
  4668   4673         const Pgno iSkip = PAGER_MJ_PGNO(pPager); /* Pending lock page */
  4669   4674         const Pgno dbSize = pPager->dbSize;       /* Database image size */ 
  4670   4675         pPager->dbSize = pPager->dbOrigSize;
  4671   4676         for( i=dbSize+1; i<=pPager->dbOrigSize; i++ ){
  4672   4677           if( !sqlite3BitvecTest(pPager->pInJournal, i) && i!=iSkip ){

Changes to test/pager.test.

     7      7   #    May you find forgiveness for yourself and forgive others.
     8      8   #    May you share freely, never taking more than you give.
     9      9   #
    10     10   #***********************************************************************
    11     11   # This file implements regression tests for SQLite library.  The
    12     12   # focus of this script is page cache subsystem.
    13     13   #
    14         -# $Id: pager.test,v 1.35 2009/06/05 17:09:12 drh Exp $
           14  +# $Id: pager.test,v 1.36 2009/07/24 16:32:01 drh Exp $
    15     15   
    16     16   
    17     17   set testdir [file dirname $argv0]
    18     18   source $testdir/tester.tcl
    19     19   
    20     20   if {[info commands pager_open]!=""} {
    21     21   db close
................................................................................
    51     51   } {0}
    52     52   #do_test pager-2.2 {
    53     53   #  set v [catch {
    54     54   #    set ::g1 [page_get $::p1 0]
    55     55   #  } msg]
    56     56   #  lappend v $msg
    57     57   #} {1 SQLITE_ERROR}
    58         -do_test pager-2.3.1 {
    59         -  set ::gx [page_lookup $::p1 1]
    60         -} {}
           58  +#do_test pager-2.3.1 {
           59  +#  set ::gx [page_lookup $::p1 1]
           60  +#} {}
    61     61   do_test pager-2.3.2 {
    62     62     pager_stats $::p1
    63     63   } {ref 0 page 0 max 10 size -1 state 0 err 0 hit 0 miss 0 ovfl 0}
    64     64   do_test pager-2.3.3 {
    65     65     set v [catch {
    66     66       set ::g1 [page_get $::p1 1]
    67     67     } msg]