/ Check-in [b2da8afc]
Login

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

Overview
Comment:Add evidence marks and assert()s used as evidence for checkpoint requirements.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: b2da8afc7657266fbe8e683c6e50fe18216cbcf3
User & Date: drh 2014-12-03 19:25:41
Context
2014-12-04
04:50
Add an implementation mark and fix a comment describing the OP_Checkpoint opcode. check-in: 7475b90c user: drh tags: trunk
2014-12-03
19:25
Add evidence marks and assert()s used as evidence for checkpoint requirements. check-in: b2da8afc user: drh tags: trunk
19:08
Fix over-length comment lines in sqlite.h.in. No changes to code. check-in: cbd357fd user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/pager.c.

  7071   7071   **
  7072   7072   ** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART.
  7073   7073   */
  7074   7074   int sqlite3PagerCheckpoint(Pager *pPager, int eMode, int *pnLog, int *pnCkpt){
  7075   7075     int rc = SQLITE_OK;
  7076   7076     if( pPager->pWal ){
  7077   7077       rc = sqlite3WalCheckpoint(pPager->pWal, eMode,
  7078         -        pPager->xBusyHandler, pPager->pBusyHandlerArg,
         7078  +        (eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler),
         7079  +        pPager->pBusyHandlerArg,
  7079   7080           pPager->ckptSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace,
  7080   7081           pnLog, pnCkpt
  7081   7082       );
  7082   7083     }
  7083   7084     return rc;
  7084   7085   }
  7085   7086   

Changes to src/wal.c.

  1685   1685   ** The caller must be holding sufficient locks to ensure that no other
  1686   1686   ** checkpoint is running (in any other thread or process) at the same
  1687   1687   ** time.
  1688   1688   */
  1689   1689   static int walCheckpoint(
  1690   1690     Wal *pWal,                      /* Wal connection */
  1691   1691     int eMode,                      /* One of PASSIVE, FULL or RESTART */
  1692         -  int (*xBusyCall)(void*),        /* Function to call when busy */
         1692  +  int (*xBusy)(void*),            /* Function to call when busy */
  1693   1693     void *pBusyArg,                 /* Context argument for xBusyHandler */
  1694   1694     int sync_flags,                 /* Flags for OsSync() (or 0) */
  1695   1695     u8 *zBuf                        /* Temporary buffer to use */
  1696   1696   ){
  1697   1697     int rc;                         /* Return code */
  1698   1698     int szPage;                     /* Database page-size */
  1699   1699     WalIterator *pIter = 0;         /* Wal iterator context */
  1700   1700     u32 iDbpage = 0;                /* Next database page to write */
  1701   1701     u32 iFrame = 0;                 /* Wal frame containing data for iDbpage */
  1702   1702     u32 mxSafeFrame;                /* Max frame that can be backfilled */
  1703   1703     u32 mxPage;                     /* Max database page to write */
  1704   1704     int i;                          /* Loop counter */
  1705   1705     volatile WalCkptInfo *pInfo;    /* The checkpoint status information */
  1706         -  int (*xBusy)(void*) = 0;        /* Function to call when waiting for locks */
  1707   1706   
  1708   1707     szPage = walPagesize(pWal);
  1709   1708     testcase( szPage<=32768 );
  1710   1709     testcase( szPage>=65536 );
  1711   1710     pInfo = walCkptInfo(pWal);
  1712   1711     if( pInfo->nBackfill>=pWal->hdr.mxFrame ) return SQLITE_OK;
  1713   1712   
................................................................................
  1714   1713     /* Allocate the iterator */
  1715   1714     rc = walIteratorInit(pWal, &pIter);
  1716   1715     if( rc!=SQLITE_OK ){
  1717   1716       return rc;
  1718   1717     }
  1719   1718     assert( pIter );
  1720   1719   
  1721         -  if( eMode!=SQLITE_CHECKPOINT_PASSIVE ) xBusy = xBusyCall;
         1720  +  /* EVIDENCE-OF: R-62920-47450 The busy-handler callback is never invoked
         1721  +  ** in the SQLITE_CHECKPOINT_PASSIVE mode. */
         1722  +  assert( eMode!=SQLITE_CHECKPOINT_PASSIVE || xBusy==0 );
  1722   1723   
  1723   1724     /* Compute in mxSafeFrame the index of the last frame of the WAL that is
  1724   1725     ** safe to write into the database.  Frames beyond mxSafeFrame might
  1725   1726     ** overwrite database pages that are in use by active readers and thus
  1726   1727     ** cannot be backfilled from the WAL.
  1727   1728     */
  1728   1729     mxSafeFrame = pWal->hdr.mxFrame;
................................................................................
  2939   2940   ** we can from WAL into the database.
  2940   2941   **
  2941   2942   ** If parameter xBusy is not NULL, it is a pointer to a busy-handler
  2942   2943   ** callback. In this case this function runs a blocking checkpoint.
  2943   2944   */
  2944   2945   int sqlite3WalCheckpoint(
  2945   2946     Wal *pWal,                      /* Wal connection */
  2946         -  int eMode,                      /* PASSIVE, FULL or RESTART */
         2947  +  int eMode,                      /* PASSIVE, FULL, RESTART, or TRUNCATE */
  2947   2948     int (*xBusy)(void*),            /* Function to call when busy */
  2948   2949     void *pBusyArg,                 /* Context argument for xBusyHandler */
  2949   2950     int sync_flags,                 /* Flags to sync db file with (or 0) */
  2950   2951     int nBuf,                       /* Size of temporary buffer */
  2951   2952     u8 *zBuf,                       /* Temporary buffer to use */
  2952   2953     int *pnLog,                     /* OUT: Number of frames in WAL */
  2953   2954     int *pnCkpt                     /* OUT: Number of backfilled frames in WAL */
  2954   2955   ){
  2955   2956     int rc;                         /* Return code */
  2956   2957     int isChanged = 0;              /* True if a new wal-index header is loaded */
  2957   2958     int eMode2 = eMode;             /* Mode to pass to walCheckpoint() */
         2959  +  int (*xBusy2)(void*) = xBusy;   /* Busy handler for eMode2 */
  2958   2960   
  2959   2961     assert( pWal->ckptLock==0 );
  2960   2962     assert( pWal->writeLock==0 );
  2961   2963   
         2964  +  /* EVIDENCE-OF: R-62920-47450 The busy-handler callback is never invoked
         2965  +  ** in the SQLITE_CHECKPOINT_PASSIVE mode. */
         2966  +  assert( eMode!=SQLITE_CHECKPOINT_PASSIVE || xBusy==0 );
         2967  +
  2962   2968     if( pWal->readOnly ) return SQLITE_READONLY;
  2963   2969     WALTRACE(("WAL%p: checkpoint begins\n", pWal));
         2970  +
         2971  +  /* IMPLEMENTATION-OF: R-62028-47212 All calls obtain an exclusive 
         2972  +  ** "checkpoint" lock on the database file. */
  2964   2973     rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1);
  2965   2974     if( rc ){
  2966         -    /* Usually this is SQLITE_BUSY meaning that another thread or process
  2967         -    ** is already running a checkpoint, or maybe a recovery.  But it might
  2968         -    ** also be SQLITE_IOERR. */
         2975  +    /* EVIDENCE-OF: R-10421-19736 If any other process is running a
         2976  +    ** checkpoint operation at the same time, the lock cannot be obtained and
         2977  +    ** SQLITE_BUSY is returned.
         2978  +    ** EVIDENCE-OF: R-53820-33897 Even if there is a busy-handler configured,
         2979  +    ** it will not be invoked in this case.
         2980  +    */
         2981  +    testcase( rc==SQLITE_BUSY );
         2982  +    testcase( xBusy!=0 );
  2969   2983       return rc;
  2970   2984     }
  2971   2985     pWal->ckptLock = 1;
  2972   2986   
  2973         -  /* If this is a blocking-checkpoint, then obtain the write-lock as well
  2974         -  ** to prevent any writers from running while the checkpoint is underway.
  2975         -  ** This has to be done before the call to walIndexReadHdr() below.
         2987  +  /* IMPLEMENTATION-OF: R-59782-36818 The SQLITE_CHECKPOINT_FULL, RESTART and
         2988  +  ** TRUNCATE modes also obtain the exclusive "writer" lock on the database
         2989  +  ** file.
  2976   2990     **
  2977         -  ** If the writer lock cannot be obtained, then a passive checkpoint is
  2978         -  ** run instead. Since the checkpointer is not holding the writer lock,
  2979         -  ** there is no point in blocking waiting for any readers. Assuming no 
  2980         -  ** other error occurs, this function will return SQLITE_BUSY to the caller.
         2991  +  ** EVIDENCE-OF: R-60642-04082 If the writer lock cannot be obtained
         2992  +  ** immediately, and a busy-handler is configured, it is invoked and the
         2993  +  ** writer lock retried until either the busy-handler returns 0 or the
         2994  +  ** lock is successfully obtained.
  2981   2995     */
  2982   2996     if( eMode!=SQLITE_CHECKPOINT_PASSIVE ){
  2983   2997       rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_WRITE_LOCK, 1);
  2984   2998       if( rc==SQLITE_OK ){
  2985   2999         pWal->writeLock = 1;
  2986   3000       }else if( rc==SQLITE_BUSY ){
  2987   3001         eMode2 = SQLITE_CHECKPOINT_PASSIVE;
         3002  +      xBusy2 = 0;
  2988   3003         rc = SQLITE_OK;
  2989   3004       }
  2990   3005     }
  2991   3006   
  2992   3007     /* Read the wal-index header. */
  2993   3008     if( rc==SQLITE_OK ){
  2994   3009       rc = walIndexReadHdr(pWal, &isChanged);
................................................................................
  2998   3013     }
  2999   3014   
  3000   3015     /* Copy data from the log to the database file. */
  3001   3016     if( rc==SQLITE_OK ){
  3002   3017       if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){
  3003   3018         rc = SQLITE_CORRUPT_BKPT;
  3004   3019       }else{
  3005         -      rc = walCheckpoint(pWal, eMode2, xBusy, pBusyArg, sync_flags, zBuf);
         3020  +      rc = walCheckpoint(pWal, eMode2, xBusy2, pBusyArg, sync_flags, zBuf);
  3006   3021       }
  3007   3022   
  3008   3023       /* If no error occurred, set the output variables. */
  3009   3024       if( rc==SQLITE_OK || rc==SQLITE_BUSY ){
  3010   3025         if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame;
  3011   3026         if( pnCkpt ) *pnCkpt = (int)(walCkptInfo(pWal)->nBackfill);
  3012   3027       }