/ Check-in [0a636798]
Login

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

Overview
Comment:Incremental checkin on pager state refactoring.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | experimental
Files: files | file ages | folders
SHA1: 0a636798bdb6961a47327091715b254f79add823
User & Date: dan 2010-08-03 06:42:40
Context
2010-08-03
12:48
Add state diagram to comments in experimental version of pager.c. check-in: 16dcf5a6 user: dan tags: experimental
06:42
Incremental checkin on pager state refactoring. check-in: 0a636798 user: dan tags: experimental
2010-08-02
14:32
Experimental refactoring of the Pager object state. This version is surely buggy. check-in: 03a24051 user: dan tags: experimental
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/pager.c.

   126    126   #define FILEHANDLEID(fd) ((int)fd)
   127    127   
   128    128   /*
   129    129   ** The Pager.eState variable stores the current 'state' of a pager. A
   130    130   ** pager may be in any one of the following six states:
   131    131   **
   132    132   **  NONE:
          133  +**    The pager starts up in this state. Nothing is guaranteed in this
          134  +**    state - the file may or may not be locked and the database size is
          135  +**    unknown. The database may not be read or written.
          136  +**
   133    137   **    * No read or write transaction is active.
   134    138   **    * Any lock, or no lock at all, may be held on the database file.
          139  +**    * The dbSize, dbOrigSize and dbFileSize variables may not be trusted.
   135    140   **
   136    141   **  READER:
   137         -**    * A read transaction is active.
          142  +**    In this state all the requirements for reading the database in 
          143  +**    rollback (non-WAL) mode are met. Unless the pager is (or recently
          144  +**    was) in exclusive-locking mode, a user-level read transaction is 
          145  +**    open. The database size is known in this state.
          146  +** 
          147  +**    * A read transaction may be active.
   138    148   **    * A SHARED or greater lock is held on the database file.
   139         -**    * The dbSize variable is valid.
          149  +**    * The dbSize variable may be trusted (even if a user-level read 
          150  +**      transaction is not active).
   140    151   **
   141    152   **  WRITER_INITIAL:
   142    153   **    * A write transaction is active.
   143    154   **    * A RESERVED or greater lock is held on the database file.
   144    155   **    * The dbSize, dbOrigSize and dbFileSize variables are all valid.
   145    156   **    * The contents of the pager cache have not been modified.
   146    157   **
................................................................................
   163    174   **    * A write transaction is active.
   164    175   **    * An EXCLUSIVE or greater lock is held on the database file.
   165    176   **    * All writing and syncing of journal and database data has finished.
   166    177   **      If no error occured, all that remains is to finalize the journal to
   167    178   **      commit the transaction. If an error did occur, the caller will need
   168    179   **      to rollback the transaction. 
   169    180   **
   170         -**
   171         -** Allowable transitions and the [function] that performe each:
          181  +** Allowable transitions and the [function] that performs each:
   172    182   ** 
   173    183   **   NONE              -> READER              [PagerSharedLock]
   174    184   **   READER            -> WRITER_INITIAL      [PagerBegin]
   175    185   **   WRITER_INITIAL    -> WRITER_CACHEMOD     [pager_open_journal]
   176    186   **   WRITER_CACHEMOD   -> WRITER_DBMOD        [syncJournal]
   177    187   **   WRITER_DBMOD      -> WRITER_FINISHED     [PagerCommitPhaseOne]
   178    188   ** 
   179    189   **   WRITER_INITIAL    -> READER              [pager_end_transaction]
   180    190   **   WRITER_CACHEMOD   -> READER              [pager_end_transaction]
   181    191   **   WRITER_DBMOD      -> READER              [pager_end_transaction]
   182    192   **   WRITER_FINISHED   -> READER              [pager_end_transaction]
   183    193   ** 
   184    194   **   READER            -> NONE                [pager_unlock]
          195  +**
          196  +** Notes:
          197  +**
          198  +**   * A pager is never in WRITER_DBMOD or WRITER_FINISHED state if the
          199  +**     connection is open in WAL mode. A WAL connection is always in one
          200  +**     of the first four states.
          201  +**
          202  +**   * Normally, a connection open in exclusive mode is never in PAGER_NONE
          203  +**     state. There are two exceptions: immediately after exclusive-mode has
          204  +**     been turned on (and before any read or write transactions are 
          205  +**     executed), and when the pager is leaving the "error state".
          206  +**
          207  +**   * See also: assert_pager_state().
   185    208   */
   186    209   #define PAGER_NONE                  0
   187    210   #define PAGER_READER                1
   188    211   #define PAGER_WRITER_INITIAL        2
   189    212   #define PAGER_WRITER_CACHEMOD       3
   190    213   #define PAGER_WRITER_DBMOD          4
   191    214   #define PAGER_WRITER_FINISHED       5
................................................................................
   421    444     ** other variables in this block are described in the comment directly 
   422    445     ** above this class definition.
   423    446     */
   424    447   #if 0
   425    448     u8 state;                   /* PAGER_UNLOCK, _SHARED, _RESERVED, etc. */
   426    449     u8 dbModified;              /* True if there are any changes to the Db */
   427    450     u8 journalStarted;          /* True if header of journal is synced */
   428         -#endif
   429    451     u8 dbSizeValid;             /* Set when dbSize is correct */
          452  +#endif
   430    453     u8 eState;                  /* Pager state (NONE, READER, WRITER_INITIAL..) */
   431    454     u8 eLock;                   /* Current lock held on database file */
   432    455   
   433    456     u8 changeCountDone;         /* Set after incrementing the change-counter */
   434    457     u8 setMaster;               /* True if a m-j name has been written to jrnl */
   435    458     u8 doNotSpill;              /* Do not spill the cache when non-zero */
   436    459     u8 doNotSyncSpill;          /* Do not do a spill that requires jrnl sync */
................................................................................
   619    642     /* Check that MEMDB implies noSync. */
   620    643     assert( !MEMDB || p->noSync );
   621    644   
   622    645     switch( p->eState ){
   623    646       case PAGER_NONE:
   624    647         assert( !MEMDB );
   625    648         assert( !p->tempFile );
   626         -      assert( !pagerUseWal(pPager) );
   627    649         break;
   628    650   
   629    651       case PAGER_READER:
   630    652         assert( p->eLock>=SHARED_LOCK || p->noReadlock );
   631    653         break;
   632    654   
   633    655       case PAGER_WRITER_INITIAL:
................................................................................
  1344   1366   **
  1345   1367   ** TODO: Why can we not reset the pager while in error state?
  1346   1368   */
  1347   1369   static void pager_reset(Pager *pPager){
  1348   1370     if( SQLITE_OK==pPager->errCode ){
  1349   1371       sqlite3BackupRestart(pPager->pBackup);
  1350   1372       sqlite3PcacheClear(pPager->pPCache);
  1351         -    pPager->dbSizeValid = 0;
  1352   1373     }
  1353   1374   }
  1354   1375   
  1355   1376   /*
  1356   1377   ** Free all structures in the Pager.aSavepoint[] array and set both
  1357   1378   ** Pager.aSavepoint and Pager.nSavepoint to zero. Close the sub-journal
  1358   1379   ** if it is open and the pager is not in exclusive mode.
................................................................................
  1424   1445         sqlite3OsClose(pPager->jfd);
  1425   1446       }
  1426   1447   
  1427   1448       sqlite3BitvecDestroy(pPager->pInJournal);
  1428   1449       pPager->pInJournal = 0;
  1429   1450       releaseAllSavepoints(pPager);
  1430   1451   
  1431         -    /* If the file is unlocked, somebody else might change it. The
  1432         -    ** values stored in Pager.dbSize etc. might become invalid if
  1433         -    ** this happens.  One can argue that this doesn't need to be cleared
  1434         -    ** until the change-counter check fails in PagerSharedLock().
  1435         -    ** Clearing the page size cache here is being conservative.
  1436         -    */
  1437         -    pPager->dbSizeValid = 0;
  1438         -
  1439   1452       if( pagerUseWal(pPager) ){
  1440   1453         sqlite3WalEndReadTransaction(pPager->pWal);
  1441   1454       }else{
  1442   1455         rc = osUnlock(pPager, NO_LOCK);
  1443   1456       }
  1444   1457       if( rc ){
  1445   1458         pPager->errCode = rc;
................................................................................
  2585   2598   ** other writers or checkpointers.
  2586   2599   */
  2587   2600   static int pagerBeginReadTransaction(Pager *pPager){
  2588   2601     int rc;                         /* Return code */
  2589   2602     int changed = 0;                /* True if cache must be reset */
  2590   2603   
  2591   2604     assert( pagerUseWal(pPager) );
         2605  +  assert( pPager->eState==PAGER_NONE || pPager->eState==PAGER_SHARED );
  2592   2606   
  2593   2607     /* sqlite3WalEndReadTransaction() was not called for the previous
  2594   2608     ** transaction in locking_mode=EXCLUSIVE.  So call it now.  If we
  2595   2609     ** are in locking_mode=NORMAL and EndRead() was previously called,
  2596   2610     ** the duplicate call is harmless.
  2597   2611     */
  2598   2612     sqlite3WalEndReadTransaction(pPager->pWal);
  2599   2613   
  2600   2614     rc = sqlite3WalBeginReadTransaction(pPager->pWal, &changed);
  2601         -  if( rc==SQLITE_OK ){
  2602         -    int dummy;
  2603         -    if( changed ){
  2604         -      pager_reset(pPager);
  2605         -      assert( pPager->errCode || pPager->dbSizeValid==0 );
  2606         -    }
  2607         -    rc = sqlite3PagerPagecount(pPager, &dummy);
  2608         -  }
  2609         -  pPager->eState = PAGER_READER;
  2610         -
  2611         -  return rc;
  2612         -}
         2615  +  if( rc==SQLITE_OK && changed ){
         2616  +    pager_reset(pPager);
         2617  +  }
         2618  +
         2619  +  return rc;
         2620  +}
         2621  +
         2622  +
         2623  +/*
         2624  +** TODO: Description here.
         2625  +*/
         2626  +static int pagerPagecount(Pager *pPager, Pgno *pnPage){
         2627  +  Pgno nPage;                     /* Value to return via *pnPage */
         2628  +
         2629  +  assert( pPager->eState==PAGER_NONE );
         2630  +  nPage = sqlite3WalDbsize(pPager->pWal);
         2631  +  if( nPage==0 ){
         2632  +    i64 n = 0;                    /* Size of db file in bytes */
         2633  +    assert( isOpen(pPager->fd) || pPager->tempFile );
         2634  +    if( isOpen(pPager->fd) ){
         2635  +      int rc = sqlite3OsFileSize(pPager->fd, &n);
         2636  +      if( rc!=SQLITE_OK ){
         2637  +        return rc;
         2638  +      }
         2639  +    }
         2640  +    nPage = (Pgno)(n / pPager->pageSize);
         2641  +    if( nPage==0 && n>0 ){
         2642  +      nPage = 1;
         2643  +    }
         2644  +  }
         2645  +  *pnPage = nPage;
         2646  +  return SQLITE_OK;
         2647  +}
         2648  +
  2613   2649   
  2614   2650   /*
  2615   2651   ** Check if the *-wal file that corresponds to the database opened by pPager
  2616   2652   ** exists if the database is not empy, or verify that the *-wal file does
  2617   2653   ** not exist (by deleting it) if the database file is empty.
  2618   2654   **
  2619   2655   ** If the database is not empty and the *-wal file exists, open the pager
................................................................................
  2631   2667   ** between the xAccess() below and an xDelete() being executed by some 
  2632   2668   ** other connection.
  2633   2669   */
  2634   2670   static int pagerOpenWalIfPresent(Pager *pPager){
  2635   2671     int rc = SQLITE_OK;
  2636   2672     if( !pPager->tempFile ){
  2637   2673       int isWal;                    /* True if WAL file exists */
  2638         -    int nPage;                    /* Size of the database file */
         2674  +    Pgno nPage;                   /* Size of the database file */
  2639   2675   
         2676  +    assert( pPager->eState==PAGER_NONE );
  2640   2677       assert( pPager->eLock>=SHARED_LOCK || pPager->noReadlock );
  2641         -    rc = sqlite3PagerPagecount(pPager, &nPage);
         2678  +    rc = pagerPagecount(pPager, &nPage);
  2642   2679       if( rc ) return rc;
  2643   2680       if( nPage==0 ){
  2644   2681         rc = sqlite3OsDelete(pPager->pVfs, pPager->zWal, 0);
  2645   2682         isWal = 0;
  2646   2683       }else{
  2647   2684         rc = sqlite3OsAccess(
  2648   2685             pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &isWal
  2649   2686         );
  2650   2687       }
  2651   2688       if( rc==SQLITE_OK ){
  2652   2689         if( isWal ){
  2653         -        pager_reset(pPager);
         2690  +        assert( sqlite3PcachePagecount(pPager->pPCache)==0 );
  2654   2691           rc = sqlite3PagerOpenWal(pPager, 0);
  2655   2692           if( rc==SQLITE_OK ){
  2656   2693             rc = pagerBeginReadTransaction(pPager);
  2657   2694           }
  2658   2695         }else if( pPager->journalMode==PAGER_JOURNALMODE_WAL ){
  2659   2696           pPager->journalMode = PAGER_JOURNALMODE_DELETE;
  2660   2697         }
................................................................................
  2956   2993     if( rc==SQLITE_OK ){
  2957   2994       u16 pageSize = *pPageSize;
  2958   2995       assert( pageSize==0 || (pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE) );
  2959   2996       if( (pPager->memDb==0 || pPager->dbSize==0)
  2960   2997        && sqlite3PcacheRefCount(pPager->pPCache)==0 
  2961   2998        && pageSize && pageSize!=pPager->pageSize 
  2962   2999       ){
  2963         -      char *pNew = (char *)sqlite3PageMalloc(pageSize);
         3000  +      char *pNew;                 /* New temp space */
         3001  +      i64 nByte = 0;
         3002  +      if( pPager->eState>PAGER_NONE && isOpen(pPager->fd) ){
         3003  +        rc = sqlite3OsFileSize(pPager->fd, &nByte);
         3004  +        if( rc!=SQLITE_OK ) return rc;
         3005  +      }
         3006  +      pNew = (char *)sqlite3PageMalloc(pageSize);
  2964   3007         if( !pNew ){
  2965   3008           rc = SQLITE_NOMEM;
  2966   3009         }else{
         3010  +        assert( pPager->eState==PAGER_NONE || pPager->eState==PAGER_READER );
  2967   3011           pager_reset(pPager);
         3012  +        pPager->dbSize = nByte/pageSize;
  2968   3013           pPager->pageSize = pageSize;
  2969   3014           sqlite3PageFree(pPager->pTmpSpace);
  2970   3015           pPager->pTmpSpace = pNew;
  2971   3016           sqlite3PcacheSetPageSize(pPager->pPCache, pageSize);
  2972   3017         }
  2973   3018       }
  2974   3019       *pPageSize = (u16)pPager->pageSize;
................................................................................
  3084   3129   **
  3085   3130   ** Otherwise, if everything is successful, then SQLITE_OK is returned
  3086   3131   ** and *pnPage is set to the number of pages in the database.
  3087   3132   */
  3088   3133   int sqlite3PagerPagecount(Pager *pPager, int *pnPage){
  3089   3134     Pgno nPage = 0;           /* Value to return via *pnPage */
  3090   3135   
         3136  +  assert( pPager->eState>=PAGER_SHARED );
         3137  +  assert( pPager->eState!=PAGER_WRITER_FINISHED );
         3138  +
  3091   3139     /* Determine the number of pages in the file. Store this in nPage. */
  3092         -  if( pPager->dbSizeValid ){
         3140  +  if( pPager->eState>PAGER_NONE ){
  3093   3141       nPage = pPager->dbSize;
  3094   3142     }else{
  3095   3143       int rc;                 /* Error returned by OsFileSize() */
  3096   3144       i64 n = 0;              /* File size in bytes returned by OsFileSize() */
  3097   3145   
  3098   3146       if( pagerUseWal(pPager) && pPager->eState!=PAGER_NONE ){
  3099         -      sqlite3WalDbsize(pPager->pWal, &nPage);
         3147  +      nPage = sqlite3WalDbsize(pPager->pWal);
  3100   3148       }
  3101   3149   
  3102   3150       if( nPage==0 ){
  3103   3151         assert( isOpen(pPager->fd) || pPager->tempFile );
  3104   3152         if( isOpen(pPager->fd) ){
  3105   3153           if( SQLITE_OK!=(rc = sqlite3OsFileSize(pPager->fd, &n)) ){
  3106   3154             pager_error(pPager, rc);
................................................................................
  3112   3160         }else{
  3113   3161           nPage = (Pgno)(n / pPager->pageSize);
  3114   3162         }
  3115   3163       }
  3116   3164       if( pPager->eState!=PAGER_NONE ){
  3117   3165         pPager->dbSize = nPage;
  3118   3166         pPager->dbFileSize = nPage;
  3119         -      pPager->dbSizeValid = 1;
  3120   3167       }
  3121   3168     }
  3122   3169   
  3123   3170     /* If the current number of pages in the file is greater than the 
  3124   3171     ** configured maximum pager number, increase the allowed limit so
  3125   3172     ** that the file can be read.
  3126   3173     */
................................................................................
  3231   3278   /*
  3232   3279   ** Truncate the in-memory database file image to nPage pages. This 
  3233   3280   ** function does not actually modify the database file on disk. It 
  3234   3281   ** just sets the internal state of the pager object so that the 
  3235   3282   ** truncation will be done when the current transaction is committed.
  3236   3283   */
  3237   3284   void sqlite3PagerTruncateImage(Pager *pPager, Pgno nPage){
  3238         -  assert( pPager->dbSizeValid );
  3239   3285     assert( pPager->dbSize>=nPage );
  3240   3286     assert( pPager->eState>=PAGER_WRITER_CACHEMOD );
  3241   3287     pPager->dbSize = nPage;
  3242   3288     assertTruncateConstraint(pPager);
  3243   3289   }
  3244   3290   
  3245   3291   
................................................................................
  4060   4106     IOTRACE(("OPEN %p %s\n", pPager, pPager->zFilename))
  4061   4107   
  4062   4108     pPager->useJournal = (u8)useJournal;
  4063   4109     pPager->noReadlock = (noReadlock && readOnly) ?1:0;
  4064   4110     /* pPager->stmtOpen = 0; */
  4065   4111     /* pPager->stmtInUse = 0; */
  4066   4112     /* pPager->nRef = 0; */
  4067         -  pPager->dbSizeValid = (u8)memDb;
  4068   4113     /* pPager->stmtSize = 0; */
  4069   4114     /* pPager->stmtJSize = 0; */
  4070   4115     /* pPager->nPage = 0; */
  4071   4116     pPager->mxPgno = SQLITE_MAX_PAGE_COUNT;
  4072   4117     /* pPager->state = PAGER_UNLOCK; */
  4073   4118   #if 0
  4074   4119     assert( pPager->state == (tempFile ? PAGER_EXCLUSIVE : PAGER_UNLOCK) );
................................................................................
  4142   4187   */
  4143   4188   static int hasHotJournal(Pager *pPager, int *pExists){
  4144   4189     sqlite3_vfs * const pVfs = pPager->pVfs;
  4145   4190     int rc = SQLITE_OK;           /* Return code */
  4146   4191     int exists = 1;               /* True if a journal file is present */
  4147   4192     int jrnlOpen = !!isOpen(pPager->jfd);
  4148   4193   
  4149         -  assert( pPager!=0 );
  4150   4194     assert( pPager->useJournal );
  4151   4195     assert( isOpen(pPager->fd) );
  4152         -  assert( pPager->eState<=PAGER_SHARED );
         4196  +  assert( pPager->eState==PAGER_NONE );
  4153   4197   
  4154   4198     assert( jrnlOpen==0 || ( sqlite3OsDeviceCharacteristics(pPager->jfd) &
  4155   4199       SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN
  4156   4200     ));
  4157   4201   
  4158   4202     *pExists = 0;
  4159   4203     if( !jrnlOpen ){
................................................................................
  4168   4212       ** we get to the following sqlite3OsCheckReservedLock() call.  If that
  4169   4213       ** is the case, this routine might think there is a hot journal when
  4170   4214       ** in fact there is none.  This results in a false-positive which will
  4171   4215       ** be dealt with by the playback routine.  Ticket #3883.
  4172   4216       */
  4173   4217       rc = sqlite3OsCheckReservedLock(pPager->fd, &locked);
  4174   4218       if( rc==SQLITE_OK && !locked ){
  4175         -      int nPage;
         4219  +      Pgno nPage;                 /* Number of pages in database file */
  4176   4220   
  4177   4221         /* Check the size of the database file. If it consists of 0 pages,
  4178   4222         ** then delete the journal file. See the header comment above for 
  4179   4223         ** the reasoning here.  Delete the obsolete journal file under
  4180   4224         ** a RESERVED lock to avoid race conditions and to avoid violating
  4181   4225         ** [H33020].
  4182   4226         */
  4183         -      rc = sqlite3PagerPagecount(pPager, &nPage);
         4227  +      rc = pagerPagecount(pPager, &nPage);
  4184   4228         if( rc==SQLITE_OK ){
  4185   4229           if( nPage==0 ){
  4186   4230             sqlite3BeginBenignMalloc();
  4187   4231             if( sqlite3OsLock(pPager->fd, RESERVED_LOCK)==SQLITE_OK ){
  4188   4232               sqlite3OsDelete(pVfs, pPager->zJournal, 0);
  4189   4233               sqlite3OsUnlock(pPager->fd, SHARED_LOCK);
  4190   4234             }
................................................................................
  4264   4308   ** file or rolling back a journal file, the IO error code is returned.
  4265   4309   */
  4266   4310   int sqlite3PagerSharedLock(Pager *pPager){
  4267   4311     int rc = SQLITE_OK;                /* Return code */
  4268   4312     int isErrorReset = 0;              /* True if recovering from error state */
  4269   4313   
  4270   4314     /* This routine is only called from b-tree and only when there are no
  4271         -  ** outstanding pages */
         4315  +  ** outstanding pages. This implies that the pager state should either
         4316  +  ** be NONE or READER. READER is only possible if the pager is or was in 
         4317  +  ** exclusive access mode.
         4318  +  */
  4272   4319     assert( sqlite3PcacheRefCount(pPager->pPCache)==0 );
         4320  +  assert( pPager->eState==PAGER_NONE || pPager->eState==PAGER_READER );
         4321  +  assert( assert_pager_state(pPager) );
  4273   4322     if( NEVER(MEMDB && pPager->errCode) ){ return pPager->errCode; }
  4274   4323   
  4275   4324     /* If this database is in an error-state, now is a chance to clear
  4276   4325     ** the error. Discard the contents of the pager-cache and rollback
  4277   4326     ** any hot journal in the file-system.
  4278   4327     */
  4279   4328     if( pPager->errCode ){
  4280   4329       if( isOpen(pPager->jfd) || pPager->zJournal ){
  4281   4330         isErrorReset = 1;
  4282   4331       }
  4283   4332       pPager->errCode = SQLITE_OK;
         4333  +    pPager->eState = PAGER_NONE;
  4284   4334       pager_reset(pPager);
  4285   4335     }
  4286   4336   
  4287         -  if( pagerUseWal(pPager) ){
  4288         -    rc = pagerBeginReadTransaction(pPager);
  4289         -  }else if( pPager->eState==PAGER_NONE || isErrorReset ){
         4337  +  if( !pagerUseWal(pPager) && pPager->eState==PAGER_NONE ){
  4290   4338       sqlite3_vfs * const pVfs = pPager->pVfs;
  4291         -    int isHotJournal = 0;
  4292   4339   
  4293   4340       assert( !MEMDB && !pPager->tempFile );
  4294   4341       assert( sqlite3PcacheRefCount(pPager->pPCache)==0 );
  4295   4342       assert( pPager->noReadlock==0 || pPager->readOnly );
  4296   4343   
  4297   4344       if( pPager->noReadlock==0 ){
  4298   4345         rc = pager_wait_on_lock(pPager, SHARED_LOCK);
  4299   4346         if( rc!=SQLITE_OK ){
  4300   4347           assert( pPager->eLock==PAGER_UNLOCK );
  4301   4348           return pager_error(pPager, rc);
  4302   4349         }
  4303   4350       }
  4304         -    pPager->eState = PAGER_READER;
  4305   4351   
  4306   4352       /* If a journal file exists, and there is no RESERVED lock on the
  4307   4353       ** database file, then it either needs to be played back or deleted.
  4308   4354       */
  4309   4355       if( !isErrorReset ){
  4310         -      rc = hasHotJournal(pPager, &isHotJournal);
         4356  +      rc = hasHotJournal(pPager, &isErrorReset);
  4311   4357         if( rc!=SQLITE_OK ){
  4312   4358           goto failed;
  4313   4359         }
  4314   4360       }
  4315         -    if( isErrorReset || isHotJournal ){
         4361  +    if( isErrorReset ){
  4316   4362         /* Get an EXCLUSIVE lock on the database file. At this point it is
  4317   4363         ** important that a RESERVED lock is not obtained on the way to the
  4318   4364         ** EXCLUSIVE lock. If it were, another process might open the
  4319   4365         ** database file, detect the RESERVED lock, and conclude that the
  4320   4366         ** database is safe to read while this process is still rolling the 
  4321   4367         ** hot-journal back.
  4322   4368         ** 
................................................................................
  4385   4431         ** the journal before playing it back.
  4386   4432         */
  4387   4433         if( isOpen(pPager->jfd) ){
  4388   4434           rc = pagerSyncHotJournal(pPager);
  4389   4435           if( rc==SQLITE_OK ){
  4390   4436             pPager->eState = PAGER_WRITER_FINISHED;
  4391   4437             rc = pager_playback(pPager, 1);
  4392         -          pPager->eState = PAGER_READER;
         4438  +          pPager->eState = PAGER_NONE;
  4393   4439           }
  4394   4440           if( rc!=SQLITE_OK ){
  4395   4441             rc = pager_error(pPager, rc);
  4396   4442             goto failed;
  4397   4443           }
  4398   4444         }else{
  4399   4445           osUnlock(pPager, SHARED_LOCK);
  4400   4446         }
  4401   4447   
  4402         -      assert( pPager->eState==PAGER_READER );
         4448  +      assert( pPager->eState==PAGER_NONE );
  4403   4449         assert( (pPager->eLock==SHARED_LOCK)
  4404   4450              || (pPager->exclusiveMode && pPager->eLock>SHARED_LOCK)
  4405   4451         );
  4406   4452       }
  4407   4453   
  4408   4454       if( pPager->pBackup || sqlite3PcachePagecount(pPager->pPCache)>0 ){
  4409   4455         /* The shared-lock has just been acquired on the database file
................................................................................
  4418   4464         ** other bytes change randomly with each file change when
  4419   4465         ** a codec is in use.
  4420   4466         ** 
  4421   4467         ** There is a vanishingly small chance that a change will not be 
  4422   4468         ** detected.  The chance of an undetected change is so small that
  4423   4469         ** it can be neglected.
  4424   4470         */
  4425         -      int nPage = 0;
         4471  +      Pgno nPage = 0;
  4426   4472         char dbFileVers[sizeof(pPager->dbFileVers)];
  4427         -      sqlite3PagerPagecount(pPager, &nPage);
  4428   4473   
  4429         -      if( pPager->errCode ){
  4430         -        rc = pPager->errCode;
  4431         -        goto failed;
  4432         -      }
         4474  +      rc = pagerPagecount(pPager, &nPage);
         4475  +      if( rc ) goto failed;
  4433   4476   
  4434   4477         if( nPage>0 ){
  4435   4478           IOTRACE(("CKVERS %p %d\n", pPager, sizeof(dbFileVers)));
  4436   4479           rc = sqlite3OsRead(pPager->fd, &dbFileVers, sizeof(dbFileVers), 24);
  4437   4480           if( rc!=SQLITE_OK ){
  4438   4481             goto failed;
  4439   4482           }
................................................................................
  4441   4484           memset(dbFileVers, 0, sizeof(dbFileVers));
  4442   4485         }
  4443   4486   
  4444   4487         if( memcmp(pPager->dbFileVers, dbFileVers, sizeof(dbFileVers))!=0 ){
  4445   4488           pager_reset(pPager);
  4446   4489         }
  4447   4490       }
  4448         -    assert( pPager->eState==PAGER_READER );
  4449   4491   
  4450   4492       /* If there is a WAL file in the file-system, open this database in WAL
  4451   4493       ** mode. Otherwise, the following function call is a no-op.
  4452   4494       */
  4453   4495       rc = pagerOpenWalIfPresent(pPager);
  4454   4496     }
         4497  +
         4498  +  if( pagerUseWal(pPager) && rc==SQLITE_OK ){
         4499  +    rc = pagerBeginReadTransaction(pPager);
         4500  +  }
         4501  +
         4502  +  if( pPager->eState==PAGER_NONE && rc==SQLITE_OK ){
         4503  +    pPager->eState = PAGER_NONE;
         4504  +    rc = pagerPagecount(pPager, &pPager->dbSize);
         4505  +  }
  4455   4506   
  4456   4507    failed:
  4457   4508     if( rc!=SQLITE_OK ){
  4458   4509       /* pager_unlock() is a no-op for exclusive mode and in-memory databases. */
  4459   4510       pager_unlock(pPager);
         4511  +  }else{
         4512  +    pPager->eState = PAGER_READER;
  4460   4513     }
  4461   4514     return rc;
  4462   4515   }
  4463   4516   
  4464   4517   /*
  4465   4518   ** If the reference count has reached zero, rollback any active
  4466   4519   ** transaction and unlock the pager.
................................................................................
  4709   4762     
  4710   4763     /* If already in the error state, this function is a no-op.  But on
  4711   4764     ** the other hand, this routine is never called if we are already in
  4712   4765     ** an error state. */
  4713   4766     if( NEVER(pPager->errCode) ) return pPager->errCode;
  4714   4767   
  4715   4768     if( !pagerUseWal(pPager) && pPager->journalMode!=PAGER_JOURNALMODE_OFF ){
  4716         -    testcase( pPager->dbSizeValid==0 );
  4717   4769       rc = sqlite3PagerPagecount(pPager, &nPage);
  4718   4770       if( rc ) return rc;
  4719   4771       pPager->pInJournal = sqlite3BitvecCreate(nPage);
  4720   4772       if( pPager->pInJournal==0 ){
  4721   4773         return SQLITE_NOMEM;
  4722   4774       }
  4723   4775     
................................................................................
  5632   5684         if( rc==SQLITE_OK ){
  5633   5685           rc = rc2;
  5634   5686         }
  5635   5687       }else{
  5636   5688         rc = pager_playback(pPager, 0);
  5637   5689       }
  5638   5690   
  5639         -    if( !MEMDB ){
  5640         -      pPager->dbSizeValid = 0;
  5641         -    }
  5642         -
  5643   5691       /* If an error occurs during a ROLLBACK, we can no longer trust the pager
  5644   5692       ** cache. So call pager_error() on the way out to make any error 
  5645   5693       ** persistent.
  5646   5694       */
  5647   5695       rc = pager_error(pPager, rc);
  5648   5696     }
  5649   5697     return rc;
................................................................................
  5688   5736   ** This routine is used for testing and analysis only.
  5689   5737   */
  5690   5738   int *sqlite3PagerStats(Pager *pPager){
  5691   5739     static int a[11];
  5692   5740     a[0] = sqlite3PcacheRefCount(pPager->pPCache);
  5693   5741     a[1] = sqlite3PcachePagecount(pPager->pPCache);
  5694   5742     a[2] = sqlite3PcacheGetCachesize(pPager->pPCache);
  5695         -  a[3] = pPager->dbSizeValid ? (int) pPager->dbSize : -1;
         5743  +  a[3] = pPager->eState==PAGER_NONE ? -1 : (int) pPager->dbSize;
  5696   5744     a[4] = pPager->eState;
  5697   5745     a[5] = pPager->errCode;
  5698   5746     a[6] = pPager->nHit;
  5699   5747     a[7] = pPager->nMiss;
  5700   5748     a[8] = 0;  /* Used to be pPager->nOvfl */
  5701   5749     a[9] = pPager->nRead;
  5702   5750     a[10] = pPager->nWrite;
................................................................................
  6006   6054     pPgOld = pager_lookup(pPager, pgno);
  6007   6055     assert( !pPgOld || pPgOld->nRef==1 );
  6008   6056     if( pPgOld ){
  6009   6057       pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC);
  6010   6058       if( MEMDB ){
  6011   6059         /* Do not discard pages from an in-memory database since we might
  6012   6060         ** need to rollback later.  Just move the page out of the way. */
  6013         -      assert( pPager->dbSizeValid );
  6014   6061         sqlite3PcacheMove(pPgOld, pPager->dbSize+1);
  6015   6062       }else{
  6016   6063         sqlite3PcacheDrop(pPgOld);
  6017   6064       }
  6018   6065     }
  6019   6066   
  6020   6067     origPgno = pPg->pgno;
................................................................................
  6283   6330   ** The caller must be holding a SHARED lock on the database file to call
  6284   6331   ** this function.
  6285   6332   **
  6286   6333   ** If the pager passed as the first argument is open on a real database
  6287   6334   ** file (not a temp file or an in-memory database), and the WAL file
  6288   6335   ** is not already open, make an attempt to open it now. If successful,
  6289   6336   ** return SQLITE_OK. If an error occurs or the VFS used by the pager does 
  6290         -** not support the xShmXXX() methods, return an error code. *pisOpen is
         6337  +** not support the xShmXXX() methods, return an error code. *pbOpen is
  6291   6338   ** not modified in either case.
  6292   6339   **
  6293   6340   ** If the pager is open on a temp-file (or in-memory database), or if
  6294         -** the WAL file is already open, set *pisOpen to 1 and return SQLITE_OK
         6341  +** the WAL file is already open, set *pbOpen to 1 and return SQLITE_OK
  6295   6342   ** without doing anything.
  6296   6343   */
  6297   6344   int sqlite3PagerOpenWal(
  6298   6345     Pager *pPager,                  /* Pager object */
  6299         -  int *pisOpen                    /* OUT: Set to true if call is a no-op */
         6346  +  int *pbOpen                     /* OUT: Set to true if call is a no-op */
  6300   6347   ){
  6301   6348     int rc = SQLITE_OK;             /* Return code */
  6302   6349   
  6303         -  assert( pPager->eState>=PAGER_READER );
  6304         -  assert( (pisOpen==0 && !pPager->tempFile && !pPager->pWal) || *pisOpen==0 );
         6350  +  assert( assert_pager_state(pPager) );
         6351  +  assert( pPager->eState==PAGER_NONE   || pbOpen );
         6352  +  assert( pPager->eState==PAGER_READER || !pbOpen );
         6353  +  assert( pbOpen==0 || *pbOpen==0 );
         6354  +  assert( pbOpen!=0 || (!pPager->tempFile && !pPager->pWal) );
  6305   6355   
  6306   6356     if( !pPager->tempFile && !pPager->pWal ){
  6307   6357       if( !sqlite3PagerWalSupported(pPager) ) return SQLITE_CANTOPEN;
  6308   6358   
  6309   6359       /* Open the connection to the log file. If this operation fails, 
  6310   6360       ** (e.g. due to malloc() failure), unlock the database file and 
  6311   6361       ** return an error code.
  6312   6362       */
  6313   6363       rc = sqlite3WalOpen(pPager->pVfs, pPager->fd, pPager->zWal, &pPager->pWal);
  6314   6364       if( rc==SQLITE_OK ){
  6315   6365         pPager->journalMode = PAGER_JOURNALMODE_WAL;
         6366  +      pPager->eState = PAGER_NONE;
  6316   6367       }
  6317   6368     }else{
  6318         -    *pisOpen = 1;
         6369  +    *pbOpen = 1;
  6319   6370     }
  6320   6371   
  6321   6372     return rc;
  6322   6373   }
  6323   6374   
  6324   6375   /*
  6325   6376   ** This function is called to close the connection to the log file prior

Changes to src/test_stat.c.

   372    372   
   373    373     sqlite3_free(pCsr->zPath);
   374    374     pCsr->zPath = 0;
   375    375   
   376    376     if( pCsr->aPage[0].pPg==0 ){
   377    377       rc = sqlite3_step(pCsr->pStmt);
   378    378       if( rc==SQLITE_ROW ){
          379  +      int nPage;
   379    380         u32 iRoot = sqlite3_column_int64(pCsr->pStmt, 1);
          381  +      sqlite3PagerPagecount(pPager, &nPage);
          382  +      if( nPage==0 ){
          383  +        pCsr->isEof = 1;
          384  +        return sqlite3_reset(pCsr->pStmt);
          385  +      }
   380    386         rc = sqlite3PagerGet(pPager, iRoot, &pCsr->aPage[0].pPg);
   381    387         pCsr->aPage[0].iPgno = iRoot;
   382    388         pCsr->aPage[0].iCell = 0;
   383    389         pCsr->aPage[0].zPath = sqlite3_mprintf("/");
   384    390         pCsr->iPage = 0;
   385    391       }else{
   386    392         pCsr->isEof = 1;
................................................................................
   482    488   }
   483    489   
   484    490   static int statFilter(
   485    491     sqlite3_vtab_cursor *pCursor, 
   486    492     int idxNum, const char *idxStr,
   487    493     int argc, sqlite3_value **argv
   488    494   ){
   489         -  sqlite3 *db = ((StatTable *)(pCursor->pVtab))->db;
   490    495     StatCursor *pCsr = (StatCursor *)pCursor;
   491         -  int nPage = 0;
   492    496   
   493    497     statResetCsr((StatCursor *)pCursor);
   494         -  sqlite3PagerPagecount(sqlite3BtreePager(db->aDb[0].pBt), &nPage);
   495         -  if( nPage==0 ){
   496         -    pCsr->isEof = 1;
   497         -    return SQLITE_OK;
   498         -  }
   499         -
   500    498     return statNext(pCursor);
   501    499   }
   502    500   
   503    501   static int statColumn(
   504    502     sqlite3_vtab_cursor *pCursor, 
   505    503     sqlite3_context *ctx, 
   506    504     int i

Changes to src/wal.c.

  2162   2162   
  2163   2163     *pInWal = 0;
  2164   2164     return SQLITE_OK;
  2165   2165   }
  2166   2166   
  2167   2167   
  2168   2168   /* 
  2169         -** Set *pPgno to the size of the database file (or zero, if unknown).
         2169  +** Return the size of the database in pages (or zero, if unknown).
  2170   2170   */
  2171         -void sqlite3WalDbsize(Wal *pWal, Pgno *pPgno){
  2172         -  assert( pWal->readLock>=0 || pWal->lockError );
  2173         -  *pPgno = pWal->hdr.nPage;
         2171  +Pgno sqlite3WalDbsize(Wal *pWal){
         2172  +  if( pWal && pWal->readLock>=0 ){
         2173  +    return pWal->hdr.nPage;
         2174  +  }
         2175  +  return 0;
  2174   2176   }
  2175   2177   
  2176   2178   
  2177   2179   /* 
  2178   2180   ** This function starts a write transaction on the WAL.
  2179   2181   **
  2180   2182   ** A read transaction must have already been started by a prior call

Changes to src/wal.h.

    21     21   
    22     22   #ifdef SQLITE_OMIT_WAL
    23     23   # define sqlite3WalOpen(x,y,z)                 0
    24     24   # define sqlite3WalClose(w,x,y,z)              0
    25     25   # define sqlite3WalBeginReadTransaction(y,z)   0
    26     26   # define sqlite3WalEndReadTransaction(z)
    27     27   # define sqlite3WalRead(v,w,x,y,z)             0
    28         -# define sqlite3WalDbsize(y,z)
           28  +# define sqlite3WalDbsize(y)                   0
    29     29   # define sqlite3WalBeginWriteTransaction(y)    0
    30     30   # define sqlite3WalEndWriteTransaction(x)      0
    31     31   # define sqlite3WalUndo(x,y,z)                 0
    32     32   # define sqlite3WalSavepoint(y,z)
    33     33   # define sqlite3WalSavepointUndo(y,z)          0
    34     34   # define sqlite3WalFrames(u,v,w,x,y,z)         0
    35     35   # define sqlite3WalCheckpoint(u,v,w,x)         0
................................................................................
    57     57   */
    58     58   int sqlite3WalBeginReadTransaction(Wal *pWal, int *);
    59     59   void sqlite3WalEndReadTransaction(Wal *pWal);
    60     60   
    61     61   /* Read a page from the write-ahead log, if it is present. */
    62     62   int sqlite3WalRead(Wal *pWal, Pgno pgno, int *pInWal, int nOut, u8 *pOut);
    63     63   
    64         -/* Return the size of the database as it existed at the beginning
    65         -** of the snapshot */
    66         -void sqlite3WalDbsize(Wal *pWal, Pgno *pPgno);
           64  +/* If the WAL is not empty, return the size of the database. */
           65  +Pgno sqlite3WalDbsize(Wal *pWal);
    67     66   
    68     67   /* Obtain or release the WRITER lock. */
    69     68   int sqlite3WalBeginWriteTransaction(Wal *pWal);
    70     69   int sqlite3WalEndWriteTransaction(Wal *pWal);
    71     70   
    72     71   /* Undo any frames written (but not committed) to the log */
    73     72   int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx);

Changes to test/permutations.test.

   125    125   lappend ::testsuitelist xxx
   126    126   
   127    127   test_suite "veryquick" -prefix "" -description {
   128    128     "Very" quick test suite. Runs in less than 5 minutes on a workstation. 
   129    129     This test suite is the same as the "quick" tests, except that some files
   130    130     that test malloc and IO errors are omitted.
   131    131   } -files [
   132         -  test_set $allquicktests -exclude *malloc* *ioerr* *fault* 
          132  +  test_set $allquicktests -exclude *malloc* *ioerr* *fault*
   133    133   ]
   134    134   
   135    135   test_suite "quick" -prefix "" -description {
   136    136     Quick test suite. Runs in around 10 minutes on a workstation.
   137    137   } -files [
   138    138     test_set $allquicktests
   139    139   ]