/ Check-in [0be92a75]
Login

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

Overview
Comment:Make sure the change counter and SQLite version numbers in the header are set correctly, even when running in WAL mode and when VACUUMing in WAL mode. Ticket [5d863f876ee9561b9].
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:0be92a75769dbafbc08c3b229089aaac03a9a907
User & Date: drh 2011-01-15 21:42:23
References
2011-02-20
03:32
Make sure the change-counter and SQLite-version fields of the header are set correctly even after vacuuming. This is a backport of changes [0be92a7576] and [04fa1e1690] to address ticket [5d863f876ee]. check-in: 442be135 user: drh tags: branch-3.7.4
Context
2011-01-16
00:56
Make sure the change-counter and SQLite-version fields of the header are set correctly even when doing a VACUUM with locking_mode=EXCLUSIVE. Ticket [5d863f876ee9561b]. check-in: 04fa1e16 user: drh tags: trunk
2011-01-15
21:42
Make sure the change counter and SQLite version numbers in the header are set correctly, even when running in WAL mode and when VACUUMing in WAL mode. Ticket [5d863f876ee9561b9]. check-in: 0be92a75 user: drh tags: trunk
18:11
Fix the change-counter increment for WAL pages so that it works even when invoked from xStress. Ticket [5d863f876ee9561b95e2]. Closed-Leaf check-in: 228e7c34 user: drh tags: bug-5d863f87
16:52
Add a test case demonstrating the problem described by ticket [5d863f876e]. check-in: af54963f user: dan tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/pager.c.

  2911   2911       rc = pagerUndoCallback((void *)pPager, pList->pgno);
  2912   2912       pList = pNext;
  2913   2913     }
  2914   2914   
  2915   2915     return rc;
  2916   2916   }
  2917   2917   
         2918  +
         2919  +/*
         2920  +** Update the value of the change-counter at offsets 24 and 92 in
         2921  +** the header and the sqlite version number at offset 96.
         2922  +**
         2923  +** This is an unconditional update.  See also the pager_incr_changecounter()
         2924  +** routine which only updates the change-counter if the update is actually
         2925  +** needed, as determined by the pPager->changeCountDone state variable.
         2926  +*/
         2927  +static void pager_write_changecounter(PgHdr *pPg){
         2928  +  u32 change_counter;
         2929  +
         2930  +  /* Increment the value just read and write it back to byte 24. */
         2931  +  change_counter = sqlite3Get4byte((u8*)pPg->pPager->dbFileVers)+1;
         2932  +  put32bits(((char*)pPg->pData)+24, change_counter);
         2933  +
         2934  +  /* Also store the SQLite version number in bytes 96..99 and in
         2935  +  ** bytes 92..95 store the change counter for which the version number
         2936  +  ** is valid. */
         2937  +  put32bits(((char*)pPg->pData)+92, change_counter);
         2938  +  put32bits(((char*)pPg->pData)+96, SQLITE_VERSION_NUMBER);
         2939  +}
         2940  +
  2918   2941   /*
  2919   2942   ** This function is a wrapper around sqlite3WalFrames(). As well as logging
  2920   2943   ** the contents of the list of pages headed by pList (connected by pDirty),
  2921   2944   ** this function notifies any active backup processes that the pages have
  2922         -** changed. 
         2945  +** changed.
         2946  +**
         2947  +** The list of pages passed into this routine is always sorted by page number.
         2948  +** Hence, if page 1 appears anywhere on the list, it will be the first page.
  2923   2949   */ 
  2924   2950   static int pagerWalFrames(
  2925   2951     Pager *pPager,                  /* Pager object */
  2926   2952     PgHdr *pList,                   /* List of frames to log */
  2927   2953     Pgno nTruncate,                 /* Database size after this commit */
  2928   2954     int isCommit,                   /* True if this is a commit */
  2929   2955     int syncFlags                   /* Flags to pass to OsSync() (or 0) */
  2930   2956   ){
  2931   2957     int rc;                         /* Return code */
         2958  +#if defined(SQLITE_DEBUG) || defined(SQLITE_CHECK_PAGES)
         2959  +  PgHdr *p;                       /* For looping over pages */
         2960  +#endif
  2932   2961   
  2933   2962     assert( pPager->pWal );
         2963  +#ifdef SQLITE_DEBUG
         2964  +  /* Verify that the page list is in accending order */
         2965  +  for(p=pList; p && p->pDirty; p=p->pDirty){
         2966  +    assert( p->pgno < p->pDirty->pgno );
         2967  +  }
         2968  +#endif
         2969  +
         2970  +  if( pList->pgno==1 ) pager_write_changecounter(pList);
  2934   2971     rc = sqlite3WalFrames(pPager->pWal, 
  2935   2972         pPager->pageSize, pList, nTruncate, isCommit, syncFlags
  2936   2973     );
  2937   2974     if( rc==SQLITE_OK && pPager->pBackup ){
  2938   2975       PgHdr *p;
  2939   2976       for(p=pList; p; p=p->pDirty){
  2940   2977         sqlite3BackupUpdate(pPager->pBackup, p->pgno, (u8 *)p->pData);
  2941   2978       }
  2942   2979     }
  2943   2980   
  2944   2981   #ifdef SQLITE_CHECK_PAGES
  2945         -  {
  2946         -    PgHdr *p;
  2947         -    for(p=pList; p; p=p->pDirty) pager_set_pagehash(p);
         2982  +  for(p=pList; p; p=p->pDirty){
         2983  +    pager_set_pagehash(p);
  2948   2984     }
  2949   2985   #endif
  2950   2986   
  2951   2987     return rc;
  2952   2988   }
  2953   2989   
  2954   2990   /*
................................................................................
  5485   5521       pager_set_pagehash(pPg);
  5486   5522     }
  5487   5523   }
  5488   5524   
  5489   5525   /*
  5490   5526   ** This routine is called to increment the value of the database file 
  5491   5527   ** change-counter, stored as a 4-byte big-endian integer starting at 
  5492         -** byte offset 24 of the pager file.
         5528  +** byte offset 24 of the pager file.  The secondary change counter at
         5529  +** 92 is also updated, as is the SQLite version number at offset 96.
         5530  +**
         5531  +** But this only happens if the pPager->changeCountDone flag is false.
         5532  +** To avoid excess churning of page 1, the update only happens once.
         5533  +** See also the pager_write_changecounter() routine that does an 
         5534  +** unconditional update of the change counters.
  5493   5535   **
  5494   5536   ** If the isDirectMode flag is zero, then this is done by calling 
  5495   5537   ** sqlite3PagerWrite() on page 1, then modifying the contents of the
  5496   5538   ** page data. In this case the file will be updated when the current
  5497   5539   ** transaction is committed.
  5498   5540   **
  5499   5541   ** The isDirectMode flag may only be non-zero if the library was compiled
................................................................................
  5526   5568     UNUSED_PARAMETER(isDirectMode);
  5527   5569   #else
  5528   5570   # define DIRECT_MODE isDirectMode
  5529   5571   #endif
  5530   5572   
  5531   5573     if( !pPager->changeCountDone && pPager->dbSize>0 ){
  5532   5574       PgHdr *pPgHdr;                /* Reference to page 1 */
  5533         -    u32 change_counter;           /* Initial value of change-counter field */
  5534   5575   
  5535   5576       assert( !pPager->tempFile && isOpen(pPager->fd) );
  5536   5577   
  5537   5578       /* Open page 1 of the file for writing. */
  5538   5579       rc = sqlite3PagerGet(pPager, 1, &pPgHdr);
  5539   5580       assert( pPgHdr==0 || rc==SQLITE_OK );
  5540   5581   
................................................................................
  5544   5585       ** above is always successful - hence the ALWAYS on rc==SQLITE_OK.
  5545   5586       */
  5546   5587       if( !DIRECT_MODE && ALWAYS(rc==SQLITE_OK) ){
  5547   5588         rc = sqlite3PagerWrite(pPgHdr);
  5548   5589       }
  5549   5590   
  5550   5591       if( rc==SQLITE_OK ){
  5551         -      /* Increment the value just read and write it back to byte 24. */
  5552         -      change_counter = sqlite3Get4byte((u8*)pPager->dbFileVers);
  5553         -      change_counter++;
  5554         -      put32bits(((char*)pPgHdr->pData)+24, change_counter);
  5555         -
  5556         -      /* Also store the SQLite version number in bytes 96..99 and in
  5557         -      ** bytes 92..95 store the change counter for which the version number
  5558         -      ** is valid. */
  5559         -      put32bits(((char*)pPgHdr->pData)+92, change_counter);
  5560         -      put32bits(((char*)pPgHdr->pData)+96, SQLITE_VERSION_NUMBER);
         5592  +      /* Actually do the update of the change counter */
         5593  +      pager_write_changecounter(pPgHdr);
  5561   5594   
  5562   5595         /* If running in direct mode, write the contents of page 1 to the file. */
  5563   5596         if( DIRECT_MODE ){
  5564   5597           const void *zBuf;
  5565   5598           assert( pPager->dbFileSize>0 );
  5566   5599           CODEC2(pPager, pPgHdr->pData, 1, 6, rc=SQLITE_NOMEM, zBuf);
  5567   5600           if( rc==SQLITE_OK ){

test/progress.test became a regular file.


tool/mkopts.tcl became a regular file.