/ Check-in [7f827ba9]
Login

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

Overview
Comment:Correction to check-ins (6246) and (6247): The backup object might not hold a valid destination connection pointer. Also, do not reset the page cache when establishing a read-lock while there is a persistent or truncated journal, only if there is a journal that really needs to rollback. Otherwise backups always reset whenever the source database file is read. (CVS 6248)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 7f827ba9d7af2dfe44aed386b4407716c85daf5e
User & Date: drh 2009-02-03 22:51:06
Context
2009-02-04
01:49
Remove compiler warnings under MSVC. (CVS 6249) check-in: 6301f08a user: shane tags: trunk
2009-02-03
22:51
Correction to check-ins (6246) and (6247): The backup object might not hold a valid destination connection pointer. Also, do not reset the page cache when establishing a read-lock while there is a persistent or truncated journal, only if there is a journal that really needs to rollback. Otherwise backups always reset whenever the source database file is read. (CVS 6248) check-in: 7f827ba9 user: drh tags: trunk
22:17
A backup must clear the internal schema of the destination database so that the schema will be reloaded for the next sqlite3_prepare() (CVS 6247) check-in: 76f23a43 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/backup.c.

     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** This file contains the implementation of the sqlite3_backup_XXX() 
    13     13   ** API functions and the related features.
    14     14   **
    15         -** $Id: backup.c,v 1.3 2009/02/03 22:17:42 drh Exp $
           15  +** $Id: backup.c,v 1.4 2009/02/03 22:51:06 drh Exp $
    16     16   */
    17     17   #include "sqliteInt.h"
    18     18   #include "btreeInt.h"
    19     19   
    20     20   /* Macro to find the minimum of two numeric values.
    21     21   */
    22     22   #ifndef MIN
................................................................................
   247    247   ** Copy nPage pages from the source b-tree to the destination.
   248    248   */
   249    249   int sqlite3_backup_step(sqlite3_backup *p, int nPage){
   250    250     int rc;
   251    251   
   252    252     sqlite3_mutex_enter(p->pSrcDb->mutex);
   253    253     sqlite3BtreeEnter(p->pSrc);
   254         -  sqlite3_mutex_enter(p->pDestDb->mutex);
          254  +  if( p->pDestDb ){
          255  +    sqlite3_mutex_enter(p->pDestDb->mutex);
          256  +  }
   255    257   
   256    258     rc = p->rc;
   257    259     if( rc==SQLITE_OK ){
   258    260       Pager * const pSrcPager = sqlite3BtreePager(p->pSrc);     /* Source pager */
   259    261       Pager * const pDestPager = sqlite3BtreePager(p->pDest);   /* Dest pager */
   260    262       int ii;                            /* Iterator variable */
   261    263       int nSrcPage;                      /* Size of source db in pages */
................................................................................
   320    322     
   321    323         /* Update the schema version field in the destination database. This
   322    324         ** is to make sure that the schema-version really does change in
   323    325         ** the case where the source and destination databases have the
   324    326         ** same schema version.
   325    327         */
   326    328         sqlite3BtreeUpdateMeta(p->pDest, 1, p->iDestSchema+1);
   327         -      sqlite3ResetInternalSchema(p->pDestDb, 0);
          329  +      if( p->pDestDb ){
          330  +        sqlite3ResetInternalSchema(p->pDestDb, 0);
          331  +      }
   328    332   
   329    333         /* Set nDestTruncate to the final number of pages in the destination
   330    334         ** database. The complication here is that the destination page
   331    335         ** size may be different to the source page size. 
   332    336         **
   333    337         ** If the source page size is smaller than the destination page size, 
   334    338         ** round up. In this case the call to sqlite3OsTruncate() below will
................................................................................
   404    408         assert( rc2==SQLITE_OK );
   405    409       }
   406    410     
   407    411       if( rc!=SQLITE_LOCKED && rc!=SQLITE_BUSY ){
   408    412         p->rc = rc;
   409    413       }
   410    414     }
   411         -  sqlite3_mutex_leave(p->pDestDb->mutex);
          415  +  if( p->pDestDb ){
          416  +    sqlite3_mutex_leave(p->pDestDb->mutex);
          417  +  }
   412    418     sqlite3BtreeLeave(p->pSrc);
   413    419     sqlite3_mutex_leave(p->pSrcDb->mutex);
   414    420     return rc;
   415    421   }
   416    422   
   417    423   /*
   418    424   ** Release all resources associated with an sqlite3_backup* handle.
................................................................................
   422    428     sqlite3_mutex *mutex;                /* Mutex to protect source database */
   423    429     int rc;                              /* Value to return */
   424    430   
   425    431     /* Enter the mutexes */
   426    432     sqlite3_mutex_enter(p->pSrcDb->mutex);
   427    433     sqlite3BtreeEnter(p->pSrc);
   428    434     mutex = p->pSrcDb->mutex;
   429         -  sqlite3_mutex_enter(p->pDestDb->mutex);
          435  +  if( p->pDestDb ){
          436  +    sqlite3_mutex_enter(p->pDestDb->mutex);
          437  +  }
   430    438   
   431    439     /* Detach this backup from the source pager. */
   432    440     if( p->pDestDb ){
   433    441       pp = sqlite3PagerBackupPtr(sqlite3BtreePager(p->pSrc));
   434    442       while( *pp!=p ){
   435    443         pp = &(*pp)->pNext;
   436    444       }
................................................................................
   442    450     sqlite3BtreeRollback(p->pDest);
   443    451   
   444    452     /* Set the error code of the destination database handle. */
   445    453     rc = (p->rc==SQLITE_DONE) ? SQLITE_OK : p->rc;
   446    454     sqlite3Error(p->pDestDb, rc, 0);
   447    455   
   448    456     /* Exit the mutexes and free the backup context structure. */
   449         -  sqlite3_mutex_leave(p->pDestDb->mutex);
          457  +  if( p->pDestDb ){
          458  +    sqlite3_mutex_leave(p->pDestDb->mutex);
          459  +  }
   450    460     sqlite3BtreeLeave(p->pSrc);
   451    461     if( p->pDestDb ){
   452    462       sqlite3_free(p);
   453    463     }
   454    464     sqlite3_mutex_leave(mutex);
   455    465     return rc;
   456    466   }

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.562 2009/02/03 16:51:25 danielk1977 Exp $
           21  +** @(#) $Id: pager.c,v 1.563 2009/02/03 22:51:06 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   */
................................................................................
  1891   1891   ** journal file then all pages up to the first corrupted page are rolled
  1892   1892   ** back (or no pages if the journal header is corrupted). The journal file
  1893   1893   ** is then deleted and SQLITE_OK returned, just as if no corruption had
  1894   1894   ** been encountered.
  1895   1895   **
  1896   1896   ** If an I/O or malloc() error occurs, the journal-file is not deleted
  1897   1897   ** and an error code is returned.
         1898  +**
         1899  +** The isHot parameter indicates that we are trying to rollback a journal
         1900  +** that might be a hot journal.  Or, it could be that the journal is 
         1901  +** preserved because of JOURNALMODE_PERSIST or JOURNALMODE_TRUNCATE.
         1902  +** If the journal really is hot, reset the pager cache prior rolling
         1903  +** back any content.  If the journal is merely persistent, no reset is
         1904  +** needed.
  1898   1905   */
  1899   1906   static int pager_playback(Pager *pPager, int isHot){
  1900   1907     sqlite3_vfs *pVfs = pPager->pVfs;
  1901   1908     i64 szJ;                 /* Size of the journal file in bytes */
  1902   1909     u32 nRec;                /* Number of Records in the journal */
  1903   1910     u32 u;                   /* Unsigned loop counter */
  1904   1911     Pgno mxPg = 0;           /* Size of the original file in pages */
  1905   1912     int rc;                  /* Result code of a subroutine */
  1906   1913     int res = 1;             /* Value returned by sqlite3OsAccess() */
  1907   1914     char *zMaster = 0;       /* Name of master journal file if any */
         1915  +  int needPagerReset;      /* True to reset page prior to first page rollback */
  1908   1916   
  1909   1917     /* Figure out how many records are in the journal.  Abort early if
  1910   1918     ** the journal is empty.
  1911   1919     */
  1912   1920     assert( isOpen(pPager->jfd) );
  1913   1921     rc = sqlite3OsFileSize(pPager->jfd, &szJ);
  1914   1922     if( rc!=SQLITE_OK || szJ==0 ){
................................................................................
  1932   1940       rc = sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS, &res);
  1933   1941     }
  1934   1942     zMaster = 0;
  1935   1943     if( rc!=SQLITE_OK || !res ){
  1936   1944       goto end_playback;
  1937   1945     }
  1938   1946     pPager->journalOff = 0;
         1947  +  needPagerReset = isHot;
  1939   1948   
  1940   1949     /* This loop terminates either when a readJournalHdr() or 
  1941   1950     ** pager_playback_one_page() call returns SQLITE_DONE or an IO error 
  1942   1951     ** occurs. 
  1943   1952     */
  1944   1953     while( 1 ){
  1945   1954   
................................................................................
  2001   2010         pPager->dbSize = mxPg;
  2002   2011       }
  2003   2012   
  2004   2013       /* Copy original pages out of the journal and back into the 
  2005   2014       ** database file and/or page cache.
  2006   2015       */
  2007   2016       for(u=0; u<nRec; u++){
         2017  +      if( needPagerReset ){
         2018  +        pager_reset(pPager);
         2019  +        needPagerReset = 0;
         2020  +      }
  2008   2021         rc = pager_playback_one_page(pPager, 1, &pPager->journalOff, 0, 0);
  2009   2022         if( rc!=SQLITE_OK ){
  2010   2023           if( rc==SQLITE_DONE ){
  2011   2024             rc = SQLITE_OK;
  2012   2025             pPager->journalOff = szJ;
  2013   2026             break;
  2014   2027           }else{
................................................................................
  3553   3566         pPager->journalHdr = 0;
  3554   3567    
  3555   3568         /* Playback and delete the journal.  Drop the database write
  3556   3569         ** lock and reacquire the read lock. Purge the cache before
  3557   3570         ** playing back the hot-journal so that we don't end up with
  3558   3571         ** an inconsistent cache.
  3559   3572         */
  3560         -      pager_reset(pPager);
  3561   3573         rc = pager_playback(pPager, 1);
  3562   3574         if( rc!=SQLITE_OK ){
  3563   3575           rc = pager_error(pPager, rc);
  3564   3576           goto failed;
  3565   3577         }
  3566   3578         assert( (pPager->state==PAGER_SHARED)
  3567   3579              || (pPager->exclusiveMode && pPager->state>PAGER_SHARED)