/ Check-in [2e08ad7b]
Login

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

Overview
Comment:Add a complex assert() that checks a pager invariant. (CVS 6934)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 2e08ad7bf629485a79ccebcf4c413e9dcc0d3ccf
User & Date: danielk1977 2009-07-25 11:40:08
Context
2009-07-25
11:46
Add files that should have gone in with the previous checkin. (CVS 6935) check-in: 64c7afc7 user: danielk1977 tags: trunk
11:40
Add a complex assert() that checks a pager invariant. (CVS 6934) check-in: 2e08ad7b user: danielk1977 tags: trunk
04:12
Add assert() statements to more tightly constrain the state of pager.c. Remove the three pager*.test scripts since they violate the constraints asserted above by modifying the state of the system in ways that it cannot be modified in a live system. (CVS 6933) check-in: 3b6d370e 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.620 2009/07/25 04:12:02 drh Exp $
           21  +** @(#) $Id: pager.c,v 1.621 2009/07/25 11:40:08 danielk1977 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   */
................................................................................
  2621   2621         pPager->state = (u8)locktype;
  2622   2622         IOTRACE(("LOCK %p %d\n", pPager, locktype))
  2623   2623       }
  2624   2624     }
  2625   2625     return rc;
  2626   2626   }
  2627   2627   
         2628  +/*
         2629  +** Function assertTruncateConstraint(pPager) checks that one of the 
         2630  +** following is true for all dirty pages currently in the page-cache:
         2631  +**
         2632  +**   a) The page number is less than or equal to the size of the 
         2633  +**      current database image, in pages, OR
         2634  +**
         2635  +**   b) if the page content were written at this time, it would not
         2636  +**      be necessary to write the current content out to the sub-journal
         2637  +**      (as determined by function subjRequiresPage()).
         2638  +**
         2639  +** If the condition asserted by this function were not true, and the
         2640  +** dirty page were to be discarded from the cache via the pagerStress()
         2641  +** routine, pagerStress() would not write the current page content to
         2642  +** the database file. If a savepoint transaction were rolled back after
         2643  +** this happened, the correct behaviour would be to restore the current
         2644  +** content of the page. However, since this content is not present in either
         2645  +** the database file or the portion of the rollback journal and 
         2646  +** sub-journal rolled back the content could not be restored and the
         2647  +** database image would become corrupt. It is therefore fortunate that 
         2648  +** this circumstance cannot arise.
         2649  +*/
         2650  +#if defined(SQLITE_DEBUG)
         2651  +static void assertTruncateConstraintCb(PgHdr *pPg){
         2652  +  assert( pPg->flags&PGHDR_DIRTY );
         2653  +  assert( !subjRequiresPage(pPg) || pPg->pgno<=pPg->pPager->dbSize );
         2654  +}
         2655  +static void assertTruncateConstraint(Pager *pPager){
         2656  +  sqlite3PcacheIterateDirty(pPager->pPCache, assertTruncateConstraintCb);
         2657  +}
         2658  +#else
         2659  +# define assertTruncateConstraint(pPager)
         2660  +#endif
         2661  +
  2628   2662   /*
  2629   2663   ** Truncate the in-memory database file image to nPage pages. This 
  2630   2664   ** function does not actually modify the database file on disk. It 
  2631   2665   ** just sets the internal state of the pager object so that the 
  2632   2666   ** truncation will be done when the current transaction is committed.
  2633   2667   */
  2634   2668   void sqlite3PagerTruncateImage(Pager *pPager, Pgno nPage){
  2635   2669     assert( pPager->dbSizeValid );
  2636   2670     assert( pPager->dbSize>=nPage );
  2637   2671     assert( pPager->state>=PAGER_RESERVED );
  2638   2672     pPager->dbSize = nPage;
         2673  +  assertTruncateConstraint(pPager);
  2639   2674   }
  2640   2675   
  2641   2676   /*
  2642   2677   ** Shutdown the page cache.  Free all memory and close all files.
  2643   2678   **
  2644   2679   ** If a transaction was in progress when this routine is called, that
  2645   2680   ** transaction is rolled back.  All outstanding pages are invalidated
................................................................................
  4959   4994         if( !aNew[ii].pInSavepoint ){
  4960   4995           return SQLITE_NOMEM;
  4961   4996         }
  4962   4997       }
  4963   4998   
  4964   4999       /* Open the sub-journal, if it is not already opened. */
  4965   5000       rc = openSubJournal(pPager);
         5001  +    assertTruncateConstraint(pPager);
  4966   5002     }
  4967   5003   
  4968   5004     return rc;
  4969   5005   }
  4970   5006   
  4971   5007   /*
  4972   5008   ** This function is called to rollback or release (commit) a savepoint.