]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Incremental checkin on pager state refactoring.
authordan <dan@noemail.net>
Tue, 3 Aug 2010 06:42:39 +0000 (06:42 +0000)
committerdan <dan@noemail.net>
Tue, 3 Aug 2010 06:42:39 +0000 (06:42 +0000)
FossilOrigin-Name: 0a636798bdb6961a47327091715b254f79add823

manifest
manifest.uuid
src/pager.c
src/test_stat.c
src/wal.c
src/wal.h
test/permutations.test

index d8a6e2a31d2759818bde625e25c013197b63298d..625d681ee0827e4449bb1e80b2931b6cb11df351 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Experimental\srefactoring\sof\sthe\sPager\sobject\sstate.
-D 2010-08-02T14:32:52
+C Incremental\scheckin\son\spager\sstate\srefactoring.
+D 2010-08-03T06:42:40
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in ec08dc838fd8110fe24c92e5130bcd91cbb1ff2e
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -156,7 +156,7 @@ F src/os_common.h a8f95b81eca8a1ab8593d23e94f8a35f35d4078f
 F src/os_os2.c 72d0b2e562952a2464308c4ce5f7913ac10bef3e
 F src/os_unix.c ae5ca8a6031380708f3fec7be325233d49944914
 F src/os_win.c 51cb62f76262d961ea4249489383d714501315a7
-F src/pager.c 94f00bedf9afb83c47f9b5d8bf8608f0eff088dd
+F src/pager.c a22869257641c379545e482d843904702d027db7
 F src/pager.h 80726162dc3942f59ab27b738fb667b9ba0a89d5
 F src/parse.y 12b7ebd61ea54f0e1b1083ff69cc2c8ce9353d58
 F src/pcache.c 1e9aa2dbc0845b52e1b51cc39753b6d1e041cb07
@@ -207,7 +207,7 @@ F src/test_osinst.c f408c6a181f2fb04c56273afd5c3e1e82f60392c
 F src/test_pcache.c 7bf828972ac0d2403f5cfa4cd14da41f8ebe73d8
 F src/test_schema.c 8c06ef9ddb240c7a0fcd31bc221a6a2aade58bf0
 F src/test_server.c bbba05c144b5fc4b52ff650a4328027b3fa5fcc6
-F src/test_stat.c 6ebaf2a86d01ccda24e49c148f1d33e8badda06e
+F src/test_stat.c dcabb7d39da058cbfc9ddc427cd92fbf14822b28
 F src/test_tclvar.c f4dc67d5f780707210d6bb0eb6016a431c04c7fa
 F src/test_thread.c bedd05cad673dba53326f3aa468cc803038896c0
 F src/test_vfs.c 7e291f85256516ebde6633bc381ff7eedfa30234
@@ -227,8 +227,8 @@ F src/vdbeblob.c 258a6010ba7a82b72b327fb24c55790655689256
 F src/vdbemem.c 5e579abf6532001dfbee0e640dc34eae897a9807
 F src/vdbetrace.c 864cef96919323482ebd9986f2132435115e9cc2
 F src/vtab.c 82200af3881fa4e1c9cf07cf31d98c09d437e3ab
-F src/wal.c 72cb5df7f4c26f83cb661d5a607b9918da99f758
-F src/wal.h 906c85760598b18584921fe08008435aa4eeeeb2
+F src/wal.c 6e04bccccd75acf86725cc8cb4b107cd245e018c
+F src/wal.h 96669b645e27cd5a111ba59f0cae7743a207bc3c
 F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
 F src/where.c 79202ca81e740eeb1f54512147e29b6c518d84ca
 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
@@ -547,7 +547,7 @@ F test/pageropt.test 8146bf448cf09e87bb1867c2217b921fb5857806
 F test/pagesize.test 76aa9f23ecb0741a4ed9d2e16c5fa82671f28efb
 F test/pcache.test 4118a183908ecaed343a06fcef3ba82e87e0129d
 F test/pcache2.test 0d85f2ab6963aee28c671d4c71bec038c00a1d16
-F test/permutations.test 3fe47c21c32b294b2354e702a25bfbff65747bb1
+F test/permutations.test 17498d1219f922d5a6da893a94c4dc7766fb2426
 F test/pragma.test ed78d200f65c6998df51196cb8c39d5300570f24
 F test/pragma2.test 5364893491b9231dd170e3459bfc2e2342658b47
 F test/printf.test 05970cde31b1a9f54bd75af60597be75a5c54fea
@@ -841,7 +841,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P 347f22a5b777af92873590a5b9af5a6498bef918
-R fb51b6835fc754e61c37a4fea5d6298b
+P 03a240514aa07a22db787d221641253f23933e88
+R 0befc920b01bc332d217d8425323f579
 U dan
-Z 550ac78d14ba82c7a2ec704cc3fbe702
+Z 0621f056ce54ddd71f6be378b7d6f549
index 00992652061771c0ab441df1b83057aef8715832..2daa89506520e546cc98090a0549ff3503d23da1 100644 (file)
@@ -1 +1 @@
-03a240514aa07a22db787d221641253f23933e88
\ No newline at end of file
+0a636798bdb6961a47327091715b254f79add823
\ No newline at end of file
index 947194927ffe914c003afcce2096a80c68ef02ce..c9f2d2ebf586a4a40334f90bb9cd121cd5f537a3 100644 (file)
@@ -130,13 +130,24 @@ int sqlite3PagerTrace=1;  /* True to enable tracing */
 ** pager may be in any one of the following six states:
 **
 **  NONE:
+**    The pager starts up in this state. Nothing is guaranteed in this
+**    state - the file may or may not be locked and the database size is
+**    unknown. The database may not be read or written.
+**
 **    * No read or write transaction is active.
 **    * Any lock, or no lock at all, may be held on the database file.
+**    * The dbSize, dbOrigSize and dbFileSize variables may not be trusted.
 **
 **  READER:
-**    * A read transaction is active.
+**    In this state all the requirements for reading the database in 
+**    rollback (non-WAL) mode are met. Unless the pager is (or recently
+**    was) in exclusive-locking mode, a user-level read transaction is 
+**    open. The database size is known in this state.
+** 
+**    * A read transaction may be active.
 **    * A SHARED or greater lock is held on the database file.
-**    * The dbSize variable is valid.
+**    * The dbSize variable may be trusted (even if a user-level read 
+**      transaction is not active).
 **
 **  WRITER_INITIAL:
 **    * A write transaction is active.
@@ -167,8 +178,7 @@ int sqlite3PagerTrace=1;  /* True to enable tracing */
 **      commit the transaction. If an error did occur, the caller will need
 **      to rollback the transaction. 
 **
-**
-** Allowable transitions and the [function] that performe each:
+** Allowable transitions and the [function] that performs each:
 ** 
 **   NONE              -> READER              [PagerSharedLock]
 **   READER            -> WRITER_INITIAL      [PagerBegin]
@@ -182,6 +192,19 @@ int sqlite3PagerTrace=1;  /* True to enable tracing */
 **   WRITER_FINISHED   -> READER              [pager_end_transaction]
 ** 
 **   READER            -> NONE                [pager_unlock]
+**
+** Notes:
+**
+**   * A pager is never in WRITER_DBMOD or WRITER_FINISHED state if the
+**     connection is open in WAL mode. A WAL connection is always in one
+**     of the first four states.
+**
+**   * Normally, a connection open in exclusive mode is never in PAGER_NONE
+**     state. There are two exceptions: immediately after exclusive-mode has
+**     been turned on (and before any read or write transactions are 
+**     executed), and when the pager is leaving the "error state".
+**
+**   * See also: assert_pager_state().
 */
 #define PAGER_NONE                  0
 #define PAGER_READER                1
@@ -425,8 +448,8 @@ struct Pager {
   u8 state;                   /* PAGER_UNLOCK, _SHARED, _RESERVED, etc. */
   u8 dbModified;              /* True if there are any changes to the Db */
   u8 journalStarted;          /* True if header of journal is synced */
-#endif
   u8 dbSizeValid;             /* Set when dbSize is correct */
+#endif
   u8 eState;                  /* Pager state (NONE, READER, WRITER_INITIAL..) */
   u8 eLock;                   /* Current lock held on database file */
 
@@ -623,7 +646,6 @@ static int assert_pager_state(Pager *p){
     case PAGER_NONE:
       assert( !MEMDB );
       assert( !p->tempFile );
-      assert( !pagerUseWal(pPager) );
       break;
 
     case PAGER_READER:
@@ -1348,7 +1370,6 @@ static void pager_reset(Pager *pPager){
   if( SQLITE_OK==pPager->errCode ){
     sqlite3BackupRestart(pPager->pBackup);
     sqlite3PcacheClear(pPager->pPCache);
-    pPager->dbSizeValid = 0;
   }
 }
 
@@ -1428,14 +1449,6 @@ static void pager_unlock(Pager *pPager){
     pPager->pInJournal = 0;
     releaseAllSavepoints(pPager);
 
-    /* If the file is unlocked, somebody else might change it. The
-    ** values stored in Pager.dbSize etc. might become invalid if
-    ** this happens.  One can argue that this doesn't need to be cleared
-    ** until the change-counter check fails in PagerSharedLock().
-    ** Clearing the page size cache here is being conservative.
-    */
-    pPager->dbSizeValid = 0;
-
     if( pagerUseWal(pPager) ){
       sqlite3WalEndReadTransaction(pPager->pWal);
     }else{
@@ -2589,6 +2602,7 @@ static int pagerBeginReadTransaction(Pager *pPager){
   int changed = 0;                /* True if cache must be reset */
 
   assert( pagerUseWal(pPager) );
+  assert( pPager->eState==PAGER_NONE || pPager->eState==PAGER_SHARED );
 
   /* sqlite3WalEndReadTransaction() was not called for the previous
   ** transaction in locking_mode=EXCLUSIVE.  So call it now.  If we
@@ -2598,19 +2612,41 @@ static int pagerBeginReadTransaction(Pager *pPager){
   sqlite3WalEndReadTransaction(pPager->pWal);
 
   rc = sqlite3WalBeginReadTransaction(pPager->pWal, &changed);
-  if( rc==SQLITE_OK ){
-    int dummy;
-    if( changed ){
-      pager_reset(pPager);
-      assert( pPager->errCode || pPager->dbSizeValid==0 );
-    }
-    rc = sqlite3PagerPagecount(pPager, &dummy);
+  if( rc==SQLITE_OK && changed ){
+    pager_reset(pPager);
   }
-  pPager->eState = PAGER_READER;
 
   return rc;
 }
 
+
+/*
+** TODO: Description here.
+*/
+static int pagerPagecount(Pager *pPager, Pgno *pnPage){
+  Pgno nPage;                     /* Value to return via *pnPage */
+
+  assert( pPager->eState==PAGER_NONE );
+  nPage = sqlite3WalDbsize(pPager->pWal);
+  if( nPage==0 ){
+    i64 n = 0;                    /* Size of db file in bytes */
+    assert( isOpen(pPager->fd) || pPager->tempFile );
+    if( isOpen(pPager->fd) ){
+      int rc = sqlite3OsFileSize(pPager->fd, &n);
+      if( rc!=SQLITE_OK ){
+        return rc;
+      }
+    }
+    nPage = (Pgno)(n / pPager->pageSize);
+    if( nPage==0 && n>0 ){
+      nPage = 1;
+    }
+  }
+  *pnPage = nPage;
+  return SQLITE_OK;
+}
+
+
 /*
 ** Check if the *-wal file that corresponds to the database opened by pPager
 ** exists if the database is not empy, or verify that the *-wal file does
@@ -2635,10 +2671,11 @@ static int pagerOpenWalIfPresent(Pager *pPager){
   int rc = SQLITE_OK;
   if( !pPager->tempFile ){
     int isWal;                    /* True if WAL file exists */
-    int nPage;                    /* Size of the database file */
+    Pgno nPage;                   /* Size of the database file */
 
+    assert( pPager->eState==PAGER_NONE );
     assert( pPager->eLock>=SHARED_LOCK || pPager->noReadlock );
-    rc = sqlite3PagerPagecount(pPager, &nPage);
+    rc = pagerPagecount(pPager, &nPage);
     if( rc ) return rc;
     if( nPage==0 ){
       rc = sqlite3OsDelete(pPager->pVfs, pPager->zWal, 0);
@@ -2650,7 +2687,7 @@ static int pagerOpenWalIfPresent(Pager *pPager){
     }
     if( rc==SQLITE_OK ){
       if( isWal ){
-        pager_reset(pPager);
+        assert( sqlite3PcachePagecount(pPager->pPCache)==0 );
         rc = sqlite3PagerOpenWal(pPager, 0);
         if( rc==SQLITE_OK ){
           rc = pagerBeginReadTransaction(pPager);
@@ -2960,11 +2997,19 @@ int sqlite3PagerSetPagesize(Pager *pPager, u16 *pPageSize, int nReserve){
      && sqlite3PcacheRefCount(pPager->pPCache)==0 
      && pageSize && pageSize!=pPager->pageSize 
     ){
-      char *pNew = (char *)sqlite3PageMalloc(pageSize);
+      char *pNew;                 /* New temp space */
+      i64 nByte = 0;
+      if( pPager->eState>PAGER_NONE && isOpen(pPager->fd) ){
+        rc = sqlite3OsFileSize(pPager->fd, &nByte);
+        if( rc!=SQLITE_OK ) return rc;
+      }
+      pNew = (char *)sqlite3PageMalloc(pageSize);
       if( !pNew ){
         rc = SQLITE_NOMEM;
       }else{
+        assert( pPager->eState==PAGER_NONE || pPager->eState==PAGER_READER );
         pager_reset(pPager);
+        pPager->dbSize = nByte/pageSize;
         pPager->pageSize = pageSize;
         sqlite3PageFree(pPager->pTmpSpace);
         pPager->pTmpSpace = pNew;
@@ -3088,15 +3133,18 @@ int sqlite3PagerReadFileheader(Pager *pPager, int N, unsigned char *pDest){
 int sqlite3PagerPagecount(Pager *pPager, int *pnPage){
   Pgno nPage = 0;           /* Value to return via *pnPage */
 
+  assert( pPager->eState>=PAGER_SHARED );
+  assert( pPager->eState!=PAGER_WRITER_FINISHED );
+
   /* Determine the number of pages in the file. Store this in nPage. */
-  if( pPager->dbSizeValid ){
+  if( pPager->eState>PAGER_NONE ){
     nPage = pPager->dbSize;
   }else{
     int rc;                 /* Error returned by OsFileSize() */
     i64 n = 0;              /* File size in bytes returned by OsFileSize() */
 
     if( pagerUseWal(pPager) && pPager->eState!=PAGER_NONE ){
-      sqlite3WalDbsize(pPager->pWal, &nPage);
+      nPage = sqlite3WalDbsize(pPager->pWal);
     }
 
     if( nPage==0 ){
@@ -3116,7 +3164,6 @@ int sqlite3PagerPagecount(Pager *pPager, int *pnPage){
     if( pPager->eState!=PAGER_NONE ){
       pPager->dbSize = nPage;
       pPager->dbFileSize = nPage;
-      pPager->dbSizeValid = 1;
     }
   }
 
@@ -3235,7 +3282,6 @@ static void assertTruncateConstraint(Pager *pPager){
 ** truncation will be done when the current transaction is committed.
 */
 void sqlite3PagerTruncateImage(Pager *pPager, Pgno nPage){
-  assert( pPager->dbSizeValid );
   assert( pPager->dbSize>=nPage );
   assert( pPager->eState>=PAGER_WRITER_CACHEMOD );
   pPager->dbSize = nPage;
@@ -4064,7 +4110,6 @@ int sqlite3PagerOpen(
   /* pPager->stmtOpen = 0; */
   /* pPager->stmtInUse = 0; */
   /* pPager->nRef = 0; */
-  pPager->dbSizeValid = (u8)memDb;
   /* pPager->stmtSize = 0; */
   /* pPager->stmtJSize = 0; */
   /* pPager->nPage = 0; */
@@ -4146,10 +4191,9 @@ static int hasHotJournal(Pager *pPager, int *pExists){
   int exists = 1;               /* True if a journal file is present */
   int jrnlOpen = !!isOpen(pPager->jfd);
 
-  assert( pPager!=0 );
   assert( pPager->useJournal );
   assert( isOpen(pPager->fd) );
-  assert( pPager->eState<=PAGER_SHARED );
+  assert( pPager->eState==PAGER_NONE );
 
   assert( jrnlOpen==0 || ( sqlite3OsDeviceCharacteristics(pPager->jfd) &
     SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN
@@ -4172,7 +4216,7 @@ static int hasHotJournal(Pager *pPager, int *pExists){
     */
     rc = sqlite3OsCheckReservedLock(pPager->fd, &locked);
     if( rc==SQLITE_OK && !locked ){
-      int nPage;
+      Pgno nPage;                 /* Number of pages in database file */
 
       /* Check the size of the database file. If it consists of 0 pages,
       ** then delete the journal file. See the header comment above for 
@@ -4180,7 +4224,7 @@ static int hasHotJournal(Pager *pPager, int *pExists){
       ** a RESERVED lock to avoid race conditions and to avoid violating
       ** [H33020].
       */
-      rc = sqlite3PagerPagecount(pPager, &nPage);
+      rc = pagerPagecount(pPager, &nPage);
       if( rc==SQLITE_OK ){
         if( nPage==0 ){
           sqlite3BeginBenignMalloc();
@@ -4268,8 +4312,13 @@ int sqlite3PagerSharedLock(Pager *pPager){
   int isErrorReset = 0;              /* True if recovering from error state */
 
   /* This routine is only called from b-tree and only when there are no
-  ** outstanding pages */
+  ** outstanding pages. This implies that the pager state should either
+  ** be NONE or READER. READER is only possible if the pager is or was in 
+  ** exclusive access mode.
+  */
   assert( sqlite3PcacheRefCount(pPager->pPCache)==0 );
+  assert( pPager->eState==PAGER_NONE || pPager->eState==PAGER_READER );
+  assert( assert_pager_state(pPager) );
   if( NEVER(MEMDB && pPager->errCode) ){ return pPager->errCode; }
 
   /* If this database is in an error-state, now is a chance to clear
@@ -4281,14 +4330,12 @@ int sqlite3PagerSharedLock(Pager *pPager){
       isErrorReset = 1;
     }
     pPager->errCode = SQLITE_OK;
+    pPager->eState = PAGER_NONE;
     pager_reset(pPager);
   }
 
-  if( pagerUseWal(pPager) ){
-    rc = pagerBeginReadTransaction(pPager);
-  }else if( pPager->eState==PAGER_NONE || isErrorReset ){
+  if( !pagerUseWal(pPager) && pPager->eState==PAGER_NONE ){
     sqlite3_vfs * const pVfs = pPager->pVfs;
-    int isHotJournal = 0;
 
     assert( !MEMDB && !pPager->tempFile );
     assert( sqlite3PcacheRefCount(pPager->pPCache)==0 );
@@ -4301,18 +4348,17 @@ int sqlite3PagerSharedLock(Pager *pPager){
         return pager_error(pPager, rc);
       }
     }
-    pPager->eState = PAGER_READER;
 
     /* If a journal file exists, and there is no RESERVED lock on the
     ** database file, then it either needs to be played back or deleted.
     */
     if( !isErrorReset ){
-      rc = hasHotJournal(pPager, &isHotJournal);
+      rc = hasHotJournal(pPager, &isErrorReset);
       if( rc!=SQLITE_OK ){
         goto failed;
       }
     }
-    if( isErrorReset || isHotJournal ){
+    if( isErrorReset ){
       /* Get an EXCLUSIVE lock on the database file. At this point it is
       ** important that a RESERVED lock is not obtained on the way to the
       ** EXCLUSIVE lock. If it were, another process might open the
@@ -4389,7 +4435,7 @@ int sqlite3PagerSharedLock(Pager *pPager){
         if( rc==SQLITE_OK ){
           pPager->eState = PAGER_WRITER_FINISHED;
           rc = pager_playback(pPager, 1);
-          pPager->eState = PAGER_READER;
+          pPager->eState = PAGER_NONE;
         }
         if( rc!=SQLITE_OK ){
           rc = pager_error(pPager, rc);
@@ -4399,7 +4445,7 @@ int sqlite3PagerSharedLock(Pager *pPager){
         osUnlock(pPager, SHARED_LOCK);
       }
 
-      assert( pPager->eState==PAGER_READER );
+      assert( pPager->eState==PAGER_NONE );
       assert( (pPager->eLock==SHARED_LOCK)
            || (pPager->exclusiveMode && pPager->eLock>SHARED_LOCK)
       );
@@ -4422,14 +4468,11 @@ int sqlite3PagerSharedLock(Pager *pPager){
       ** detected.  The chance of an undetected change is so small that
       ** it can be neglected.
       */
-      int nPage = 0;
+      Pgno nPage = 0;
       char dbFileVers[sizeof(pPager->dbFileVers)];
-      sqlite3PagerPagecount(pPager, &nPage);
 
-      if( pPager->errCode ){
-        rc = pPager->errCode;
-        goto failed;
-      }
+      rc = pagerPagecount(pPager, &nPage);
+      if( rc ) goto failed;
 
       if( nPage>0 ){
         IOTRACE(("CKVERS %p %d\n", pPager, sizeof(dbFileVers)));
@@ -4445,7 +4488,6 @@ int sqlite3PagerSharedLock(Pager *pPager){
         pager_reset(pPager);
       }
     }
-    assert( pPager->eState==PAGER_READER );
 
     /* If there is a WAL file in the file-system, open this database in WAL
     ** mode. Otherwise, the following function call is a no-op.
@@ -4453,10 +4495,21 @@ int sqlite3PagerSharedLock(Pager *pPager){
     rc = pagerOpenWalIfPresent(pPager);
   }
 
+  if( pagerUseWal(pPager) && rc==SQLITE_OK ){
+    rc = pagerBeginReadTransaction(pPager);
+  }
+
+  if( pPager->eState==PAGER_NONE && rc==SQLITE_OK ){
+    pPager->eState = PAGER_NONE;
+    rc = pagerPagecount(pPager, &pPager->dbSize);
+  }
+
  failed:
   if( rc!=SQLITE_OK ){
     /* pager_unlock() is a no-op for exclusive mode and in-memory databases. */
     pager_unlock(pPager);
+  }else{
+    pPager->eState = PAGER_READER;
   }
   return rc;
 }
@@ -4713,7 +4766,6 @@ static int pager_open_journal(Pager *pPager){
   if( NEVER(pPager->errCode) ) return pPager->errCode;
 
   if( !pagerUseWal(pPager) && pPager->journalMode!=PAGER_JOURNALMODE_OFF ){
-    testcase( pPager->dbSizeValid==0 );
     rc = sqlite3PagerPagecount(pPager, &nPage);
     if( rc ) return rc;
     pPager->pInJournal = sqlite3BitvecCreate(nPage);
@@ -5636,10 +5688,6 @@ int sqlite3PagerRollback(Pager *pPager){
       rc = pager_playback(pPager, 0);
     }
 
-    if( !MEMDB ){
-      pPager->dbSizeValid = 0;
-    }
-
     /* If an error occurs during a ROLLBACK, we can no longer trust the pager
     ** cache. So call pager_error() on the way out to make any error 
     ** persistent.
@@ -5692,7 +5740,7 @@ int *sqlite3PagerStats(Pager *pPager){
   a[0] = sqlite3PcacheRefCount(pPager->pPCache);
   a[1] = sqlite3PcachePagecount(pPager->pPCache);
   a[2] = sqlite3PcacheGetCachesize(pPager->pPCache);
-  a[3] = pPager->dbSizeValid ? (int) pPager->dbSize : -1;
+  a[3] = pPager->eState==PAGER_NONE ? -1 : (int) pPager->dbSize;
   a[4] = pPager->eState;
   a[5] = pPager->errCode;
   a[6] = pPager->nHit;
@@ -6010,7 +6058,6 @@ int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
     if( MEMDB ){
       /* Do not discard pages from an in-memory database since we might
       ** need to rollback later.  Just move the page out of the way. */
-      assert( pPager->dbSizeValid );
       sqlite3PcacheMove(pPgOld, pPager->dbSize+1);
     }else{
       sqlite3PcacheDrop(pPgOld);
@@ -6287,21 +6334,24 @@ int sqlite3PagerWalSupported(Pager *pPager){
 ** file (not a temp file or an in-memory database), and the WAL file
 ** is not already open, make an attempt to open it now. If successful,
 ** return SQLITE_OK. If an error occurs or the VFS used by the pager does 
-** not support the xShmXXX() methods, return an error code. *pisOpen is
+** not support the xShmXXX() methods, return an error code. *pbOpen is
 ** not modified in either case.
 **
 ** If the pager is open on a temp-file (or in-memory database), or if
-** the WAL file is already open, set *pisOpen to 1 and return SQLITE_OK
+** the WAL file is already open, set *pbOpen to 1 and return SQLITE_OK
 ** without doing anything.
 */
 int sqlite3PagerOpenWal(
   Pager *pPager,                  /* Pager object */
-  int *pisOpen                    /* OUT: Set to true if call is a no-op */
+  int *pbOpen                     /* OUT: Set to true if call is a no-op */
 ){
   int rc = SQLITE_OK;             /* Return code */
 
-  assert( pPager->eState>=PAGER_READER );
-  assert( (pisOpen==0 && !pPager->tempFile && !pPager->pWal) || *pisOpen==0 );
+  assert( assert_pager_state(pPager) );
+  assert( pPager->eState==PAGER_NONE   || pbOpen );
+  assert( pPager->eState==PAGER_READER || !pbOpen );
+  assert( pbOpen==0 || *pbOpen==0 );
+  assert( pbOpen!=0 || (!pPager->tempFile && !pPager->pWal) );
 
   if( !pPager->tempFile && !pPager->pWal ){
     if( !sqlite3PagerWalSupported(pPager) ) return SQLITE_CANTOPEN;
@@ -6313,9 +6363,10 @@ int sqlite3PagerOpenWal(
     rc = sqlite3WalOpen(pPager->pVfs, pPager->fd, pPager->zWal, &pPager->pWal);
     if( rc==SQLITE_OK ){
       pPager->journalMode = PAGER_JOURNALMODE_WAL;
+      pPager->eState = PAGER_NONE;
     }
   }else{
-    *pisOpen = 1;
+    *pbOpen = 1;
   }
 
   return rc;
index 894be80ecb9eb2023e507c0a8c1e597668b05345..1534621114c0945f5a73b5dfbc3a60211ac30e77 100644 (file)
@@ -376,7 +376,13 @@ static int statNext(sqlite3_vtab_cursor *pCursor){
   if( pCsr->aPage[0].pPg==0 ){
     rc = sqlite3_step(pCsr->pStmt);
     if( rc==SQLITE_ROW ){
+      int nPage;
       u32 iRoot = sqlite3_column_int64(pCsr->pStmt, 1);
+      sqlite3PagerPagecount(pPager, &nPage);
+      if( nPage==0 ){
+        pCsr->isEof = 1;
+        return sqlite3_reset(pCsr->pStmt);
+      }
       rc = sqlite3PagerGet(pPager, iRoot, &pCsr->aPage[0].pPg);
       pCsr->aPage[0].iPgno = iRoot;
       pCsr->aPage[0].iCell = 0;
@@ -486,17 +492,9 @@ static int statFilter(
   int idxNum, const char *idxStr,
   int argc, sqlite3_value **argv
 ){
-  sqlite3 *db = ((StatTable *)(pCursor->pVtab))->db;
   StatCursor *pCsr = (StatCursor *)pCursor;
-  int nPage = 0;
 
   statResetCsr((StatCursor *)pCursor);
-  sqlite3PagerPagecount(sqlite3BtreePager(db->aDb[0].pBt), &nPage);
-  if( nPage==0 ){
-    pCsr->isEof = 1;
-    return SQLITE_OK;
-  }
-
   return statNext(pCursor);
 }
 
index 3ac8071548700ad1509cd7d536b81f6fa97c6211..be8c466428826b711f1a1866da3803dd079a391d 100644 (file)
--- a/src/wal.c
+++ b/src/wal.c
@@ -2166,11 +2166,13 @@ int sqlite3WalRead(
 
 
 /* 
-** Set *pPgno to the size of the database file (or zero, if unknown).
+** Return the size of the database in pages (or zero, if unknown).
 */
-void sqlite3WalDbsize(Wal *pWal, Pgno *pPgno){
-  assert( pWal->readLock>=0 || pWal->lockError );
-  *pPgno = pWal->hdr.nPage;
+Pgno sqlite3WalDbsize(Wal *pWal){
+  if( pWal && pWal->readLock>=0 ){
+    return pWal->hdr.nPage;
+  }
+  return 0;
 }
 
 
index f29d5838f5f6e3c4ea034a6a50b1e94f96e8c866..f20dfa8e17586bed8cf039d21b39d28cd79107aa 100644 (file)
--- a/src/wal.h
+++ b/src/wal.h
@@ -25,7 +25,7 @@
 # define sqlite3WalBeginReadTransaction(y,z)   0
 # define sqlite3WalEndReadTransaction(z)
 # define sqlite3WalRead(v,w,x,y,z)             0
-# define sqlite3WalDbsize(y,z)
+# define sqlite3WalDbsize(y)                   0
 # define sqlite3WalBeginWriteTransaction(y)    0
 # define sqlite3WalEndWriteTransaction(x)      0
 # define sqlite3WalUndo(x,y,z)                 0
@@ -61,9 +61,8 @@ void sqlite3WalEndReadTransaction(Wal *pWal);
 /* Read a page from the write-ahead log, if it is present. */
 int sqlite3WalRead(Wal *pWal, Pgno pgno, int *pInWal, int nOut, u8 *pOut);
 
-/* Return the size of the database as it existed at the beginning
-** of the snapshot */
-void sqlite3WalDbsize(Wal *pWal, Pgno *pPgno);
+/* If the WAL is not empty, return the size of the database. */
+Pgno sqlite3WalDbsize(Wal *pWal);
 
 /* Obtain or release the WRITER lock. */
 int sqlite3WalBeginWriteTransaction(Wal *pWal);
index f1fb74fe614a0d232bcfe6659c1593991253833e..086897c468d13828ef2bbff7c035f432ab07d004 100644 (file)
@@ -129,7 +129,7 @@ test_suite "veryquick" -prefix "" -description {
   This test suite is the same as the "quick" tests, except that some files
   that test malloc and IO errors are omitted.
 } -files [
-  test_set $allquicktests -exclude *malloc* *ioerr* *fault* 
+  test_set $allquicktests -exclude *malloc* *ioerr* *fault*
 ]
 
 test_suite "quick" -prefix "" -description {