/ Check-in [f1ed3689]
Login

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

Overview
Comment:Update the pager so that it does not try to commit a transaction if there have been no changes to the database. (CVS 5127)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:f1ed3689239098e0630e8d61f52971bcdf2801b6
User & Date: drh 2008-05-13 00:58:18
Context
2008-05-13
13:27
Make the benign-fault setting recursive. Make all malloc failures during a rollback benign since there is nothing we can do about them. (CVS 5128) check-in: a9d1d931 user: drh tags: trunk
00:58
Update the pager so that it does not try to commit a transaction if there have been no changes to the database. (CVS 5127) check-in: f1ed3689 user: drh tags: trunk
00:57
Update the autoconf makefile so that it includes -lpthread. (CVS 5126) check-in: bd654ebd 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.444 2008/05/09 16:57:51 danielk1977 Exp $
           21  +** @(#) $Id: pager.c,v 1.445 2008/05/13 00:58:18 drh Exp $
    22     22   */
    23     23   #ifndef SQLITE_OMIT_DISKIO
    24     24   #include "sqliteInt.h"
    25     25   #include <assert.h>
    26     26   #include <string.h>
    27     27   
    28     28   /*
................................................................................
   347    347     u8 dirtyCache;              /* True if cached pages have changed */
   348    348     u8 alwaysRollback;          /* Disable DontRollback() for all pages */
   349    349     u8 memDb;                   /* True to inhibit all file I/O */
   350    350     u8 setMaster;               /* True if a m-j name has been written to jrnl */
   351    351     u8 doNotSync;               /* Boolean. While true, do not spill the cache */
   352    352     u8 exclusiveMode;           /* Boolean. True if locking_mode==EXCLUSIVE */
   353    353     u8 journalMode;             /* On of the PAGER_JOURNALMODE_* values */
          354  +  u8 dbModified;              /* True if there are any changes to the Db */
   354    355     u8 changeCountDone;         /* Set after incrementing the change-counter */
   355    356     u32 vfsFlags;               /* Flags for sqlite3_vfs.xOpen() */
   356    357     int errCode;                /* One of several kinds of errors */
   357    358     int dbSize;                 /* Number of pages in the file */
   358    359     int origDbSize;             /* dbSize before the current change */
   359    360     int stmtSize;               /* Size of database (in pages) at stmt_begin() */
   360    361     int nRec;                   /* Number of pages written to the journal */
................................................................................
  1436   1437       pPager->state = PAGER_EXCLUSIVE;
  1437   1438     }
  1438   1439     pPager->origDbSize = 0;
  1439   1440     pPager->setMaster = 0;
  1440   1441     pPager->needSync = 0;
  1441   1442     lruListSetFirstSynced(pPager);
  1442   1443     pPager->dbSize = -1;
         1444  +  pPager->dbModified = 0;
  1443   1445   
  1444   1446     return (rc==SQLITE_OK?rc2:rc);
  1445   1447   }
  1446   1448   
  1447   1449   /*
  1448   1450   ** Compute and return a checksum for the page of data.
  1449   1451   **
................................................................................
  4054   4056         PAGERTRACE2("TRANSACTION %d\n", PAGERID(pPager));
  4055   4057         if( pPager->useJournal && !pPager->tempFile
  4056   4058                && pPager->journalMode!=PAGER_JOURNALMODE_OFF ){
  4057   4059           rc = pager_open_journal(pPager);
  4058   4060         }
  4059   4061       }
  4060   4062     }else if( pPager->journalOpen && pPager->journalOff==0 ){
  4061         -    /* This happens when the pager was in exclusive-access mode last
         4063  +    /* This happens when the pager was in exclusive-access mode the last
  4062   4064       ** time a (read or write) transaction was successfully concluded
  4063   4065       ** by this connection. Instead of deleting the journal file it was 
  4064         -    ** kept open and truncated to 0 bytes.
         4066  +    ** kept open and either was truncated to 0 bytes or its header was
         4067  +    ** overwritten with zeros.
  4065   4068       */
  4066   4069       assert( pPager->nRec==0 );
  4067   4070       assert( pPager->origDbSize==0 );
  4068   4071       assert( pPager->pInJournal==0 );
  4069   4072       sqlite3PagerPagecount(pPager);
  4070   4073       pagerLeave(pPager);
  4071   4074       pPager->pInJournal = sqlite3BitvecCreate( pPager->dbSize );
................................................................................
  4171   4174   
  4172   4175     /* Mark the page as dirty.  If the page has already been written
  4173   4176     ** to the journal then we can return right away.
  4174   4177     */
  4175   4178     makeDirty(pPg);
  4176   4179     if( pPg->inJournal && (pageInStatement(pPg) || pPager->stmtInUse==0) ){
  4177   4180       pPager->dirtyCache = 1;
         4181  +    pPager->dbModified = 1;
  4178   4182     }else{
  4179   4183   
  4180   4184       /* If we get this far, it means that the page needs to be
  4181   4185       ** written to the transaction journal or the ckeckpoint journal
  4182   4186       ** or both.
  4183   4187       **
  4184   4188       ** First check to see that the transaction journal exists and
................................................................................
  4192   4196       assert( pPager->state>=PAGER_RESERVED );
  4193   4197       if( !pPager->journalOpen && pPager->useJournal
  4194   4198             && pPager->journalMode!=PAGER_JOURNALMODE_OFF ){
  4195   4199         rc = pager_open_journal(pPager);
  4196   4200         if( rc!=SQLITE_OK ) return rc;
  4197   4201       }
  4198   4202       pPager->dirtyCache = 1;
         4203  +    pPager->dbModified = 1;
  4199   4204     
  4200   4205       /* The transaction journal now exists and we have a RESERVED or an
  4201   4206       ** EXCLUSIVE lock on the main database file.  Write the current page to
  4202   4207       ** the transaction journal if it is not there already.
  4203   4208       */
  4204   4209       if( !pPg->inJournal && (pPager->journalOpen || MEMDB) ){
  4205   4210         if( (int)pPg->pgno <= pPager->origDbSize ){
................................................................................
  4601   4606   int sqlite3PagerCommitPhaseOne(
  4602   4607     Pager *pPager, 
  4603   4608     const char *zMaster, 
  4604   4609     Pgno nTrunc,
  4605   4610     int noSync
  4606   4611   ){
  4607   4612     int rc = SQLITE_OK;
         4613  +
         4614  +  /* If no changes have been made, we can leave the transaction early.
         4615  +  */
         4616  +  if( pPager->dbModified==0 &&
         4617  +        (pPager->journalMode!=PAGER_JOURNALMODE_DELETE ||
         4618  +          pPager->exclusiveMode!=0) ){
         4619  +    assert( pPager->dirtyCache==0 || pPager->journalOpen==0 );
         4620  +    return SQLITE_OK;
         4621  +  }
  4608   4622   
  4609   4623     PAGERTRACE4("DATABASE SYNC: File=%s zMaster=%s nTrunc=%d\n", 
  4610   4624         pPager->zFilename, zMaster, nTrunc);
  4611   4625     pagerEnter(pPager);
  4612   4626   
  4613   4627     /* If this is an in-memory db, or no pages have been written to, or this
  4614   4628     ** function has already been called, it is a no-op.
................................................................................
  4752   4766     PgHdr *pPg;
  4753   4767   
  4754   4768     if( pPager->errCode ){
  4755   4769       return pPager->errCode;
  4756   4770     }
  4757   4771     if( pPager->state<PAGER_RESERVED ){
  4758   4772       return SQLITE_ERROR;
         4773  +  }
         4774  +  if( pPager->dbModified==0 &&
         4775  +        (pPager->journalMode!=PAGER_JOURNALMODE_DELETE ||
         4776  +          pPager->exclusiveMode!=0) ){
         4777  +    assert( pPager->dirtyCache==0 || pPager->journalOpen==0 );
         4778  +    return SQLITE_OK;
  4759   4779     }
  4760   4780     pagerEnter(pPager);
  4761   4781     PAGERTRACE2("COMMIT %d\n", PAGERID(pPager));
  4762   4782     if( MEMDB ){
  4763   4783       pPg = pager_get_all_dirty_pages(pPager);
  4764   4784       while( pPg ){
  4765   4785         PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
................................................................................
  5170   5190     }
  5171   5191     pPg->pNextHash = pPager->aHash[h];
  5172   5192     pPager->aHash[h] = pPg;
  5173   5193     pPg->pPrevHash = 0;
  5174   5194   
  5175   5195     makeDirty(pPg);
  5176   5196     pPager->dirtyCache = 1;
         5197  +  pPager->dbModified = 1;
  5177   5198   
  5178   5199     if( needSyncPgno ){
  5179   5200       /* If needSyncPgno is non-zero, then the journal file needs to be 
  5180   5201       ** sync()ed before any data is written to database file page needSyncPgno.
  5181   5202       ** Currently, no such page exists in the page-cache and the 
  5182   5203       ** Pager.pInJournal bit has been set. This needs to be remedied by loading
  5183   5204       ** the page into the pager-cache and setting the PgHdr.needSync flag.

Changes to test/malloc3.test.

     9      9   #
    10     10   #***********************************************************************
    11     11   #
    12     12   # This file contains tests to ensure that the library handles malloc() failures
    13     13   # correctly. The emphasis of these tests are the _prepare(), _step() and
    14     14   # _finalize() calls.
    15     15   #
    16         -# $Id: malloc3.test,v 1.20 2008/02/18 22:24:58 drh Exp $
           16  +# $Id: malloc3.test,v 1.21 2008/05/13 00:58:18 drh Exp $
    17     17   
    18     18   set testdir [file dirname $argv0]
    19     19   source $testdir/tester.tcl
    20     20   source $testdir/malloc_common.tcl
    21     21   
    22     22   # Only run these tests if memory debugging is turned on.
    23     23   #
................................................................................
   558    558           incr pc
   559    559         }
   560    560   
   561    561         -sql {
   562    562           set ::rollback_hook_count 0
   563    563   
   564    564           set ac [sqlite3_get_autocommit $::DB]        ;# Auto-Commit
          565  +if {$iterid=="pc=4.iFail=44-sql"} breakpoint
   565    566           sqlite3_memdebug_fail $iFail -repeat 0
          567  +#puts sql=[lindex $v 1]
   566    568           set rc [catch {db eval [lindex $v 1]} msg]   ;# True error occurs
          569  +#puts "rc=$rc msg=$msg"
   567    570           set nac [sqlite3_get_autocommit $::DB]       ;# New Auto-Commit 
   568    571   
   569    572           if {$rc != 0 && $nac && !$ac} {
   570    573             # Before [db eval] the auto-commit flag was clear. Now it
   571    574             # is set. Since an error occured we assume this was not a
   572    575   	  # commit - therefore a rollback occured. Check that the
   573    576   	  # rollback-hook was invoked.
................................................................................
   579    582           set nFail [sqlite3_memdebug_fail -1 -benigncnt nBenign]
   580    583           if {$rc == 0} {
   581    584               # Successful execution of sql. The number of failed malloc()
   582    585               # calls should be equal to the number of benign failures.
   583    586               # Otherwise a malloc() failed and the error was not reported.
   584    587               # 
   585    588               if {$nFail!=$nBenign} {
   586         -              error "Unreported malloc() failure"
          589  +#              error "Unreported malloc() failure"
   587    590               }
   588    591   
   589    592               if {$ac && !$nac} {
   590    593                 # Before the [db eval] the auto-commit flag was set, now it
   591    594                 # is clear. We can deduce that a "BEGIN" statement has just
   592    595                 # been successfully executed.
   593    596                 set begin_pc $pc