/ Check-in [9dc4100e]
Login

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

Overview
Comment:Always truncate the pager cache when truncating the database file. Also reorganize the code to check the change-counter after first obtaining a shared lock. (CVS 3814)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 9dc4100eff71be579480ce7939c7da712d28f0ae
User & Date: danielk1977 2007-04-05 17:15:53
Context
2007-04-05
17:36
New testfixture command: sqlite3_pager_refcounts. Returns a list of integers which is the pager refcount for each pager in the database. (CVS 3815) check-in: 7338e68e user: drh tags: trunk
17:15
Always truncate the pager cache when truncating the database file. Also reorganize the code to check the change-counter after first obtaining a shared lock. (CVS 3814) check-in: 9dc4100e user: danielk1977 tags: trunk
14:29
Use the MEMDB macro instead of OMIT_MEMORYDB in pager_recycle(). (CVS 3813) check-in: 97c51598 user: danielk1977 tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

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.322 2007/04/05 14:29:43 danielk1977 Exp $
           21  +** @(#) $Id: pager.c,v 1.323 2007/04/05 17:15:53 danielk1977 Exp $
    22     22   */
    23     23   #ifndef SQLITE_OMIT_DISKIO
    24     24   #include "sqliteInt.h"
    25     25   #include "os.h"
    26     26   #include "pager.h"
    27     27   #include <assert.h>
    28     28   #include <string.h>
................................................................................
   885    885     pager_unlock(p);
   886    886     assert( p->errCode || !p->journalOpen || (p->exclusiveMode&&!p->journalOff) );
   887    887     assert( p->errCode || !p->stmtOpen || p->exclusiveMode );
   888    888   }
   889    889   
   890    890   
   891    891   /*
   892         -** Unlock the database and clear the in-memory cache.  This routine
          892  +** Clear the in-memory cache.  This routine
   893    893   ** sets the state of the pager back to what it was when it was first
   894    894   ** opened.  Any outstanding pages are invalidated and subsequent attempts
   895    895   ** to access those pages will likely result in a coredump.
   896    896   */
   897    897   static void pager_reset(Pager *pPager){
   898    898     PgHdr *pPg, *pNext;
   899    899     if( pPager->errCode ) return;
................................................................................
  1261   1261   #endif
  1262   1262     }
  1263   1263     pPager->pDirty = 0;
  1264   1264     return rc;
  1265   1265   }
  1266   1266   #endif
  1267   1267   
         1268  +static void pager_truncate_cache(Pager *pPager);
         1269  +
  1268   1270   /*
  1269   1271   ** Truncate the main file of the given pager to the number of pages
  1270         -** indicated.
         1272  +** indicated. Also truncate the cached representation of the file.
  1271   1273   */
  1272   1274   static int pager_truncate(Pager *pPager, int nPage){
  1273         -  assert( pPager->state>=PAGER_EXCLUSIVE );
  1274         -  return sqlite3OsTruncate(pPager->fd, pPager->pageSize*(i64)nPage);
         1275  +  int rc = SQLITE_OK;
         1276  +  if( pPager->state>=PAGER_EXCLUSIVE ){
         1277  +    rc = sqlite3OsTruncate(pPager->fd, pPager->pageSize*(i64)nPage);
         1278  +  }
         1279  +  if( rc==SQLITE_OK ){
         1280  +    pPager->dbSize = nPage;
         1281  +    pager_truncate_cache(pPager);
         1282  +  }
         1283  +  return rc;
  1275   1284   }
  1276   1285   
  1277   1286   /*
  1278   1287   ** Playback the journal and thus restore the database file to
  1279   1288   ** the state it was in before we started making changes.  
  1280   1289   **
  1281   1290   ** The journal file format is as follows: 
................................................................................
  1394   1403       if( nRec==0 && !isHot ){
  1395   1404         nRec = (szJ - pPager->journalOff) / JOURNAL_PG_SZ(pPager);
  1396   1405       }
  1397   1406   
  1398   1407       /* If this is the first header read from the journal, truncate the
  1399   1408       ** database file back to it's original size.
  1400   1409       */
  1401         -    if( pPager->state>=PAGER_EXCLUSIVE && 
  1402         -        pPager->journalOff==JOURNAL_HDR_SZ(pPager) ){
  1403         -      assert( pPager->origDbSize==0 || pPager->origDbSize==mxPg );
         1410  +    if( pPager->journalOff==JOURNAL_HDR_SZ(pPager) ){
  1404   1411         rc = pager_truncate(pPager, mxPg);
  1405   1412         if( rc!=SQLITE_OK ){
  1406   1413           goto end_playback;
  1407   1414         }
  1408         -      pPager->dbSize = mxPg;
  1409   1415       }
  1410   1416   
  1411   1417       /* Copy original pages out of the journal and back into the database file.
  1412   1418       */
  1413   1419       for(i=0; i<nRec; i++){
  1414   1420         rc = pager_playback_one_page(pPager, pPager->jfd, 1);
  1415   1421         if( rc!=SQLITE_OK ){
................................................................................
  1488   1494     assert( pPager->fullSync || !hdrOff );
  1489   1495     if( !hdrOff ){
  1490   1496       hdrOff = szJ;
  1491   1497     }
  1492   1498     
  1493   1499     /* Truncate the database back to its original size.
  1494   1500     */
  1495         -  if( pPager->state>=PAGER_EXCLUSIVE ){
  1496         -    rc = pager_truncate(pPager, pPager->stmtSize);
  1497         -  }
         1501  +  rc = pager_truncate(pPager, pPager->stmtSize);
  1498   1502     assert( pPager->state>=PAGER_SHARED );
  1499         -  pPager->dbSize = pPager->stmtSize;
  1500   1503   
  1501   1504     /* Figure out how many records are in the statement journal.
  1502   1505     */
  1503   1506     assert( pPager->stmtInUse && pPager->journalOpen );
  1504   1507     sqlite3OsSeek(pPager->stfd, 0);
  1505   1508     nRec = pPager->stmtNRec;
  1506   1509     
................................................................................
  2016   2019     }
  2017   2020     pPg->pNextFree = pPg->pPrevFree = 0;
  2018   2021   
  2019   2022     /* Unlink from the pgno hash table */
  2020   2023     unlinkHashChain(pPager, pPg);
  2021   2024   }
  2022   2025   
  2023         -#ifndef SQLITE_OMIT_MEMORYDB
  2024   2026   /*
  2025         -** This routine is used to truncate an in-memory database.  Delete
  2026         -** all pages whose pgno is larger than pPager->dbSize and is unreferenced.
         2027  +** This routine is used to truncate the cache when a database
         2028  +** is truncated.  Drop from the cache all pages whose pgno is
         2029  +** larger than pPager->dbSize and is unreferenced.
         2030  +**
  2027   2031   ** Referenced pages larger than pPager->dbSize are zeroed.
         2032  +**
         2033  +** Actually, at the point this routine is called, it would be
         2034  +** an error to have a referenced page.  But rather than delete
         2035  +** that page and guarantee a subsequent segfault, it seems better
         2036  +** to zero it and hope that we error out sanely.
  2028   2037   */
  2029         -static void memoryTruncate(Pager *pPager){
         2038  +static void pager_truncate_cache(Pager *pPager){
  2030   2039     PgHdr *pPg;
  2031   2040     PgHdr **ppPg;
  2032   2041     int dbSize = pPager->dbSize;
  2033   2042   
  2034   2043     ppPg = &pPager->pAll;
  2035   2044     while( (pPg = *ppPg)!=0 ){
  2036   2045       if( pPg->pgno<=dbSize ){
................................................................................
  2043   2052         unlinkPage(pPg);
  2044   2053         makeClean(pPg);
  2045   2054         sqliteFree(pPg);
  2046   2055         pPager->nPage--;
  2047   2056       }
  2048   2057     }
  2049   2058   }
  2050         -#else
  2051         -#define memoryTruncate(p)
  2052         -#endif
  2053   2059   
  2054   2060   /*
  2055   2061   ** Try to obtain a lock on a file.  Invoke the busy callback if the lock
  2056   2062   ** is currently not available.  Repeat until the busy callback returns
  2057   2063   ** false or until the lock succeeds.
  2058   2064   **
  2059   2065   ** Return SQLITE_OK on success and an error code if we cannot obtain
................................................................................
  2096   2102       return rc;
  2097   2103     }
  2098   2104     if( nPage>=(unsigned)pPager->dbSize ){
  2099   2105       return SQLITE_OK;
  2100   2106     }
  2101   2107     if( MEMDB ){
  2102   2108       pPager->dbSize = nPage;
  2103         -    memoryTruncate(pPager);
         2109  +    pager_truncate_cache(pPager);
  2104   2110       return SQLITE_OK;
  2105   2111     }
  2106   2112     rc = syncJournal(pPager);
  2107   2113     if( rc!=SQLITE_OK ){
  2108   2114       return rc;
  2109   2115     }
  2110   2116   
................................................................................
  2111   2117     /* Get an exclusive lock on the database before truncating. */
  2112   2118     rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
  2113   2119     if( rc!=SQLITE_OK ){
  2114   2120       return rc;
  2115   2121     }
  2116   2122   
  2117   2123     rc = pager_truncate(pPager, nPage);
  2118         -  if( rc==SQLITE_OK ){
  2119         -    pPager->dbSize = nPage;
  2120         -  }
  2121   2124     return rc;
  2122   2125   }
  2123   2126   
  2124   2127   /*
  2125   2128   ** Shutdown the page cache.  Free all memory and close all files.
  2126   2129   **
  2127   2130   ** If a transaction was in progress when this routine is called, that
................................................................................
  2684   2687         }
  2685   2688       }
  2686   2689     }
  2687   2690   
  2688   2691     return nReleased;
  2689   2692   }
  2690   2693   #endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */
         2694  +
         2695  +/*
         2696  +** Read the content of page pPg out of the database file.
         2697  +*/
         2698  +static int readDbPage(Pager *pPager, PgHdr *pPg, Pgno pgno){
         2699  +  int rc;
         2700  +  assert( MEMDB==0 );
         2701  +  rc = sqlite3OsSeek(pPager->fd, (pgno-1)*(i64)pPager->pageSize);
         2702  +  if( rc==SQLITE_OK ){
         2703  +    rc = sqlite3OsRead(pPager->fd, PGHDR_TO_DATA(pPg),
         2704  +                          pPager->pageSize);
         2705  +  }
         2706  +  IOTRACE(("PGIN %p %d\n", pPager, pgno))
         2707  +  PAGERTRACE3("FETCH %d page %d\n", PAGERID(pPager), pPg->pgno);
         2708  +  CODEC1(pPager, PGHDR_TO_DATA(pPg), pPg->pgno, 3);
         2709  +  return rc;
         2710  +}
         2711  +
  2691   2712   
  2692   2713   /*
  2693   2714   ** This function is called to obtain the shared lock required before
  2694   2715   ** data may be read from the pager cache. If the shared lock has already
  2695   2716   ** been obtained, this function is a no-op.
  2696   2717   **
  2697   2718   ** Immediately after obtaining the shared lock (if required), this function
................................................................................
  2788   2809           ** stored in Pager.iChangeCount matches that found on page 1 of
  2789   2810           ** the database file, then no database changes have occured since
  2790   2811           ** the cache was last valid and it is safe to retain the cached
  2791   2812           ** pages. Otherwise, if Pager.iChangeCount does not match the
  2792   2813           ** change-counter on page 1 of the file, the current cache contents
  2793   2814           ** must be discarded.
  2794   2815           */
         2816  +        u8 zC[4];
         2817  +        u32 iChangeCounter = 0;
         2818  +        sqlite3PagerPagecount(pPager);
  2795   2819   
  2796         -        PgHdr *pPage1 = pager_lookup(pPager, 1);
  2797         -        if( pPage1 ){
  2798         -          unlinkPage(pPage1);
         2820  +        if( pPager->errCode ){
         2821  +          return pPager->errCode;
         2822  +        }
  2799   2823   
  2800         -          /* Make sure the former page 1 is right at the start of the
  2801         -          ** free-list. This triggers a special case in pagerAllocatePage()
  2802         -          ** to re-use this page even if the total number of pages in
  2803         -          ** the cache is less than Pager.mxPage.
  2804         -          */
  2805         -          assert( pPager->pFirst==pPager->pFirstSynced );
  2806         -          pPage1->pNextFree = pPager->pFirst;
  2807         -          if( pPager->pFirst ){
  2808         -            pPager->pFirst->pPrevFree = pPage1;
  2809         -          }else{
  2810         -            assert( !pPager->pLast );
  2811         -            pPager->pLast = pPage1;
         2824  +        if( pPager->dbSize>0 ){
         2825  +          /* Read the 4-byte change counter directly from the file. */
         2826  +          rc = sqlite3OsSeek(pPager->fd, 24);
         2827  +          if( rc!=SQLITE_OK ){
         2828  +            return rc;
         2829  +          }
         2830  +          rc = sqlite3OsRead(pPager->fd, zC, 4);
         2831  +          if( rc!=SQLITE_OK ){
         2832  +            return rc;
  2812   2833             }
  2813         -          pPager->pFirst = pPage1;
  2814         -          pPager->pFirstSynced = pPage1;
         2834  +          iChangeCounter = (zC[0]<<24) + (zC[1]<<16) + (zC[2]<<8) + zC[3];
  2815   2835           }
  2816   2836   
  2817         -        assert( !pager_lookup(pPager, 1) );
  2818         -        rc = sqlite3PagerAcquire(pPager, 1, &pPage1, 0);
  2819         -        if( rc==SQLITE_OK ){
  2820         -	  /* The change-counter is stored at offset 24. See also
  2821         -          ** pager_incr_changecounter().
  2822         -          */
  2823         -          u32 iChangeCount = retrieve32bits(pPage1, 24);
  2824         -          pPager->nRef++;
  2825         -          sqlite3PagerUnref(pPage1);
  2826         -          pPager->nRef--;
  2827         -          if( iChangeCount!=pPager->iChangeCount ){
  2828         -            pager_reset(pPager);
  2829         -          }
  2830         -          pPager->iChangeCount = iChangeCount;
         2837  +        if( iChangeCounter!=pPager->iChangeCount ){
         2838  +          pager_reset(pPager);
  2831   2839           }
  2832   2840         }
  2833   2841       }
  2834   2842       assert( pPager->exclusiveMode || pPager->state<=PAGER_SHARED );
  2835   2843       if( pPager->state==PAGER_UNLOCK ){
  2836   2844         pPager->state = PAGER_SHARED;
  2837   2845       }
  2838   2846     }
  2839   2847   
  2840   2848     return rc;
  2841   2849   }
  2842   2850   
  2843   2851   /*
  2844         -** Allocate or recycle space for a single page.
         2852  +** Allocate a PgHdr object.   Either create a new one or reuse
         2853  +** an existing one that is not otherwise in use.
         2854  +**
         2855  +** A new PgHdr structure is created if any of the following are
         2856  +** true:
         2857  +**
         2858  +**     (1)  We have not exceeded our maximum allocated cache size
         2859  +**          as set by the "PRAGMA cache_size" command.
         2860  +**
         2861  +**     (2)  There are no unused PgHdr objects available at this time.
         2862  +**
         2863  +**     (3)  This is an in-memory database.
         2864  +**
         2865  +**     (4)  There are no PgHdr objects that do not require a journal
         2866  +**          file sync and a sync of the journal file is currently
         2867  +**          prohibited.
         2868  +**
         2869  +** Otherwise, reuse an existing PgHdr.  In other words, reuse an
         2870  +** existing PgHdr if all of the following are true:
         2871  +**
         2872  +**     (1)  We have reached or exceeded the maximum cache size
         2873  +**          allowed by "PRAGMA cache_size".
         2874  +**
         2875  +**     (2)  There is a PgHdr available with PgHdr->nRef==0
         2876  +**
         2877  +**     (3)  We are not in an in-memory database
         2878  +**
         2879  +**     (4)  Either there is an available PgHdr that does not need
         2880  +**          to be synced to disk or else disk syncing is currently
         2881  +**          allowed.
  2845   2882   */
  2846   2883   static int pagerAllocatePage(Pager *pPager, PgHdr **ppPg){
  2847   2884     int rc = SQLITE_OK;
  2848   2885     PgHdr *pPg;
  2849   2886   
  2850         -  if( MEMDB || (!(pPager->pFirstSynced && pPager->pFirstSynced->pgno==0) && (
  2851         -      pPager->nPage<pPager->mxPage || pPager->pFirst==0 || 
  2852         -      (pPager->pFirstSynced==0 && pPager->doNotSync)
  2853         -  )) ){
  2854         -    /* Create a new page */
         2887  +  /* Create a new PgHdr if any of the four conditions defined 
         2888  +  ** above is met: */
         2889  +  if( pPager->nPage<pPager->mxPage
         2890  +   || pPager->pFirst==0 
         2891  +   || MEMDB
         2892  +   || (pPager->pFirstSynced==0 && pPager->doNotSync)
         2893  +  ){
  2855   2894       if( pPager->nPage>=pPager->nHash ){
  2856   2895         pager_resize_hash_table(pPager,
  2857   2896            pPager->nHash<256 ? 256 : pPager->nHash*2);
  2858   2897         if( pPager->nHash==0 ){
  2859   2898           rc = SQLITE_NOMEM;
  2860   2899           goto pager_allocate_out;
  2861   2900         }
................................................................................
  2997   3036   
  2998   3037       /* Populate the page with data, either by reading from the database
  2999   3038       ** file, or by setting the entire page to zero.
  3000   3039       */
  3001   3040       if( nMax<(int)pgno || MEMDB || (clrFlag && !pPager->alwaysRollback) ){
  3002   3041         memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize);
  3003   3042       }else{
  3004         -      assert( MEMDB==0 );
  3005         -      rc = sqlite3OsSeek(pPager->fd, (pgno-1)*(i64)pPager->pageSize);
  3006         -      if( rc==SQLITE_OK ){
  3007         -        rc = sqlite3OsRead(pPager->fd, PGHDR_TO_DATA(pPg),
  3008         -                              pPager->pageSize);
  3009         -      }
  3010         -      IOTRACE(("PGIN %p %d\n", pPager, pgno))
  3011         -      PAGERTRACE3("FETCH %d page %d\n", PAGERID(pPager), pPg->pgno);
  3012         -      CODEC1(pPager, PGHDR_TO_DATA(pPg), pPg->pgno, 3);
         3043  +      rc = readDbPage(pPager, pPg, pgno);
  3013   3044         if( rc!=SQLITE_OK && rc!=SQLITE_IOERR_SHORT_READ ){
  3014   3045           pPg->pgno = 0;
  3015   3046           sqlite3PagerUnref(pPg);
  3016   3047           return rc;
  3017   3048         }else{
  3018   3049           TEST_INCR(pPager->nRead);
  3019   3050         }
................................................................................
  3031   3062   
  3032   3063   #ifdef SQLITE_CHECK_PAGES
  3033   3064       pPg->pageHash = pager_pagehash(pPg);
  3034   3065   #endif
  3035   3066     }else{
  3036   3067       /* The requested page is in the page cache. */
  3037   3068       assert(pPager->nRef>0 || pgno==1);
  3038         -    if( pgno>sqlite3PagerPagecount(pPager) ){
  3039         -      /* This can happen after a truncation in exclusive mode. The pager
  3040         -      ** cache contains pages that are located after the end of the 
  3041         -      ** database file. Zero such pages before returning. Not doing this 
  3042         -      ** was causing the problem reported in ticket #2285.
  3043         -      */
  3044         -      if( pPager->errCode ){
  3045         -        /* This case catches an IO error in sqlite3PagerPagecount(). If
  3046         -        ** the error occured, PagerPagecount() returned 0.
  3047         -        */
  3048         -        return pPager->errCode;
  3049         -      }
  3050         -      memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize);
  3051         -    }
  3052   3069       TEST_INCR(pPager->nHit);
  3053   3070       page_ref(pPg);
  3054   3071     }
  3055   3072     *ppPage = pPg;
  3056   3073     return SQLITE_OK;
  3057   3074   }
  3058   3075   
................................................................................
  3887   3904         if( pPager->xReiniter ){
  3888   3905           pPager->xReiniter(p, pPager->pageSize);
  3889   3906         }
  3890   3907       }
  3891   3908       pPager->pDirty = 0;
  3892   3909       pPager->pStmt = 0;
  3893   3910       pPager->dbSize = pPager->origDbSize;
  3894         -    memoryTruncate(pPager);
         3911  +    pager_truncate_cache(pPager);
  3895   3912       pPager->stmtInUse = 0;
  3896   3913       pPager->state = PAGER_SHARED;
  3897   3914       return SQLITE_OK;
  3898   3915     }
  3899   3916   
  3900   3917     if( !pPager->dirtyCache || !pPager->journalOpen ){
  3901   3918       rc = pager_end_transaction(pPager);
................................................................................
  3914   3931       rc2 = pager_end_transaction(pPager);
  3915   3932       if( rc==SQLITE_OK ){
  3916   3933         rc = rc2;
  3917   3934       }
  3918   3935     }else{
  3919   3936       rc = pager_playback(pPager, 0);
  3920   3937     }
         3938  +  /* pager_reset(pPager); */
  3921   3939     pPager->dbSize = -1;
  3922   3940   
  3923   3941     /* If an error occurs during a ROLLBACK, we can no longer trust the pager
  3924   3942     ** cache. So call pager_error() on the way out to make any error 
  3925   3943     ** persistent.
  3926   3944     */
  3927   3945     return pager_error(pPager, rc);
................................................................................
  4063   4081           if( pHist->pStmt ){
  4064   4082             memcpy(PGHDR_TO_DATA(pPg), pHist->pStmt, pPager->pageSize);
  4065   4083             sqliteFree(pHist->pStmt);
  4066   4084             pHist->pStmt = 0;
  4067   4085           }
  4068   4086         }
  4069   4087         pPager->dbSize = pPager->stmtSize;
  4070         -      memoryTruncate(pPager);
         4088  +      pager_truncate_cache(pPager);
  4071   4089         rc = SQLITE_OK;
  4072   4090       }else{
  4073   4091         rc = pager_stmt_playback(pPager);
  4074   4092       }
  4075   4093       sqlite3PagerStmtCommit(pPager);
  4076   4094     }else{
  4077   4095       rc = SQLITE_OK;

Changes to test/diskfull.test.

     8      8   #    May you share freely, never taking more than you give.
     9      9   #
    10     10   #***********************************************************************
    11     11   # This file implements regression tests for SQLite library.  The
    12     12   # focus of this file is testing for correct handling of disk full
    13     13   # errors.
    14     14   # 
    15         -# $Id: diskfull.test,v 1.5 2007/03/31 10:00:48 danielk1977 Exp $
           15  +# $Id: diskfull.test,v 1.6 2007/04/05 17:15:53 danielk1977 Exp $
    16     16   
    17     17   set testdir [file dirname $argv0]
    18     18   source $testdir/tester.tcl
    19     19   
    20     20   set sqlite_io_error_persist 0
    21     21   set sqlite_io_error_hit 0
    22     22   set sqlite_io_error_pending 0
................................................................................
    52     52   set sqlite_diskfull_pending 0
    53     53   set sqlite_io_error_hit 0
    54     54   integrity_check diskfull-1.6
    55     55   
    56     56   proc do_diskfull_test {prefix sql} {
    57     57     set ::go 1
    58     58     set ::sql $sql
    59         -  set ::i 52
           59  +  set ::i 1
    60     60     while {$::go} {
    61     61       incr ::i
    62     62       do_test ${prefix}.$::i.1 {
    63     63         set ::sqlite_diskfull_pending $::i
    64     64         set ::sqlite_diskfull 0
    65     65         set r [catchsql $::sql]
    66     66         if {!$::sqlite_diskfull} {

Changes to test/pager.test.

     7      7   #    May you find forgiveness for yourself and forgive others.
     8      8   #    May you share freely, never taking more than you give.
     9      9   #
    10     10   #***********************************************************************
    11     11   # This file implements regression tests for SQLite library.  The
    12     12   # focus of this script is page cache subsystem.
    13     13   #
    14         -# $Id: pager.test,v 1.27 2007/04/02 05:07:48 danielk1977 Exp $
           14  +# $Id: pager.test,v 1.28 2007/04/05 17:15:53 danielk1977 Exp $
    15     15   
    16     16   
    17     17   set testdir [file dirname $argv0]
    18     18   source $testdir/tester.tcl
    19     19   
    20     20   if {[info commands pager_open]!=""} {
    21     21   db close
................................................................................
   115    115     expr {$::g1!=0}
   116    116   } {1}
   117    117   do_test pager-2.12 {
   118    118     page_number $::g1
   119    119   } {1}
   120    120   do_test pager-2.13 {
   121    121     pager_stats $::p1
   122         -} {ref 1 page 1 max 10 size 0 state 1 err 0 hit 1 miss 2 ovfl 0}
          122  +} {ref 1 page 1 max 10 size 0 state 1 err 0 hit 1 miss 1 ovfl 0}
   123    123   do_test pager-2.14 {
   124    124     set v [catch {
   125    125       page_write $::g1 "Page-One"
   126    126     } msg]
   127    127     lappend v $msg
   128    128   } {0 {}}
   129    129   do_test pager-2.15 {
   130    130     pager_stats $::p1
   131         -} {ref 1 page 1 max 10 size 1 state 2 err 0 hit 1 miss 2 ovfl 0}
          131  +} {ref 1 page 1 max 10 size 1 state 2 err 0 hit 1 miss 1 ovfl 0}
   132    132   do_test pager-2.16 {
   133    133     page_read $::g1
   134    134   } {Page-One}
   135    135   do_test pager-2.17 {
   136    136     set v [catch {
   137    137       pager_commit $::p1
   138    138     } msg]
   139    139     lappend v $msg
   140    140   } {0 {}}
   141    141   do_test pager-2.20 {
   142    142     pager_stats $::p1
   143         -} {ref 1 page 1 max 10 size -1 state 1 err 0 hit 2 miss 2 ovfl 0}
          143  +} {ref 1 page 1 max 10 size -1 state 1 err 0 hit 2 miss 1 ovfl 0}
   144    144   do_test pager-2.19 {
   145    145     pager_pagecount $::p1
   146    146   } {1}
   147    147   do_test pager-2.21 {
   148    148     pager_stats $::p1
   149         -} {ref 1 page 1 max 10 size 1 state 1 err 0 hit 2 miss 2 ovfl 0}
          149  +} {ref 1 page 1 max 10 size 1 state 1 err 0 hit 2 miss 1 ovfl 0}
   150    150   do_test pager-2.22 {
   151    151     page_unref $::g1
   152    152   } {}
   153    153   do_test pager-2.23 {
   154    154     pager_stats $::p1
   155         -} {ref 0 page 1 max 10 size -1 state 0 err 0 hit 2 miss 2 ovfl 0}
          155  +} {ref 0 page 1 max 10 size -1 state 0 err 0 hit 2 miss 1 ovfl 0}
   156    156   do_test pager-2.24 {
   157    157     set v [catch {
   158    158       page_get $::p1 1
   159    159     } ::g1]
   160    160     if {$v} {lappend v $::g1}
   161    161     set v
   162    162   } {0}