/ Check-in [47866d67]
Login

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

Overview
Comment:Add an API to support custom page cache implementations. (CVS 5899)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 47866d6708e9b69e367937fd85f93580fd025447
User & Date: danielk1977 2008-11-13 14:28:29
Context
2008-11-13
14:42
Update mksqlite3c.tcl to include new file pcache1.c. (CVS 5900) check-in: 00442e0f user: danielk1977 tags: trunk
14:28
Add an API to support custom page cache implementations. (CVS 5899) check-in: 47866d67 user: danielk1977 tags: trunk
2008-11-12
18:21
Avoid some buffer overreads detected by valgrind while running corruptC.test. (CVS 5898) check-in: faa6bd7b user: danielk1977 tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to Makefile.in.

   163    163           btree.lo build.lo callback.lo complete.lo date.lo \
   164    164           delete.lo expr.lo fault.lo func.lo global.lo \
   165    165           hash.lo journal.lo insert.lo legacy.lo loadext.lo \
   166    166           main.lo malloc.lo mem0.lo mem1.lo mem2.lo mem3.lo mem5.lo \
   167    167           memjournal.lo \
   168    168           mutex.lo mutex_noop.lo mutex_os2.lo mutex_unix.lo mutex_w32.lo \
   169    169           opcodes.lo os.lo os_unix.lo os_win.lo os_os2.lo \
   170         -        pager.lo parse.lo pcache.lo pragma.lo prepare.lo printf.lo random.lo \
   171         -        resolve.lo select.lo status.lo \
          170  +        pager.lo parse.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \
          171  +        random.lo resolve.lo select.lo status.lo \
   172    172           table.lo tokenize.lo trigger.lo update.lo \
   173    173           util.lo vacuum.lo \
   174    174           vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbefifo.lo vdbemem.lo \
   175    175           walker.lo where.lo utf.lo vtab.lo
   176    176   
   177    177   # Object files for the amalgamation.
   178    178   #
................................................................................
   233    233     $(TOP)/src/os_win.c \
   234    234     $(TOP)/src/os_os2.c \
   235    235     $(TOP)/src/pager.c \
   236    236     $(TOP)/src/pager.h \
   237    237     $(TOP)/src/parse.y \
   238    238     $(TOP)/src/pcache.c \
   239    239     $(TOP)/src/pcache.h \
          240  +  $(TOP)/src/pcache1.c \
   240    241     $(TOP)/src/pragma.c \
   241    242     $(TOP)/src/prepare.c \
   242    243     $(TOP)/src/printf.c \
   243    244     $(TOP)/src/random.c \
   244    245     $(TOP)/src/resolve.c \
   245    246     $(TOP)/src/select.c \
   246    247     $(TOP)/src/status.c \
................................................................................
   331    332     $(TOP)/src/malloc.c \
   332    333     $(TOP)/src/os.c \
   333    334     $(TOP)/src/os_os2.c \
   334    335     $(TOP)/src/os_unix.c \
   335    336     $(TOP)/src/os_win.c \
   336    337     $(TOP)/src/pager.c \
   337    338     $(TOP)/src/pcache.c \
          339  +  $(TOP)/src/pcache1.c \
   338    340     $(TOP)/src/pragma.c \
   339    341     $(TOP)/src/prepare.c \
   340    342     $(TOP)/src/printf.c \
   341    343     $(TOP)/src/random.c \
   342    344     $(TOP)/src/select.c \
   343    345     $(TOP)/src/tokenize.c \
   344    346     $(TOP)/src/utf.c \
................................................................................
   591    593   	$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mutex_w32.c
   592    594   
   593    595   pager.lo:	$(TOP)/src/pager.c $(HDR) $(TOP)/src/pager.h
   594    596   	$(LTCOMPILE) -c $(TOP)/src/pager.c
   595    597   
   596    598   pcache.lo:	$(TOP)/src/pcache.c $(HDR) $(TOP)/src/pcache.h
   597    599   	$(LTCOMPILE) -c $(TOP)/src/pcache.c
          600  +
          601  +pcache1.lo:	$(TOP)/src/pcache1.c $(HDR) $(TOP)/src/pcache.h
          602  +	$(LTCOMPILE) -c $(TOP)/src/pcache1.c
   598    603   
   599    604   opcodes.lo:	opcodes.c
   600    605   	$(LTCOMPILE) -c opcodes.c
   601    606   
   602    607   opcodes.c:	opcodes.h $(TOP)/mkopcodec.awk
   603    608   	sort -n -b -k 3 opcodes.h | $(NAWK) -f $(TOP)/mkopcodec.awk >opcodes.c
   604    609   

Changes to main.mk.

    56     56            fts3_tokenizer.o fts3_tokenizer1.o \
    57     57            func.o global.o hash.o \
    58     58            icu.o insert.o journal.o legacy.o loadext.o \
    59     59            main.o malloc.o mem0.o mem1.o mem2.o mem3.o mem5.o \
    60     60            memjournal.o \
    61     61            mutex.o mutex_noop.o mutex_os2.o mutex_unix.o mutex_w32.o \
    62     62            opcodes.o os.o os_os2.o os_unix.o os_win.o \
    63         -         pager.o parse.o pcache.o pragma.o prepare.o printf.o \
           63  +         pager.o parse.o pcache.o pcache1.o pragma.o prepare.o printf.o \
    64     64            random.o resolve.o rtree.o select.o status.o \
    65     65            table.o tokenize.o trigger.o \
    66     66            update.o util.o vacuum.o \
    67     67            vdbe.o vdbeapi.o vdbeaux.o vdbeblob.o vdbefifo.o vdbemem.o \
    68     68            walker.o where.o utf.o vtab.o
    69     69   
    70     70   
................................................................................
   118    118     $(TOP)/src/os_unix.c \
   119    119     $(TOP)/src/os_win.c \
   120    120     $(TOP)/src/pager.c \
   121    121     $(TOP)/src/pager.h \
   122    122     $(TOP)/src/parse.y \
   123    123     $(TOP)/src/pcache.c \
   124    124     $(TOP)/src/pcache.h \
          125  +  $(TOP)/src/pcache1.c \
   125    126     $(TOP)/src/pragma.c \
   126    127     $(TOP)/src/prepare.c \
   127    128     $(TOP)/src/printf.c \
   128    129     $(TOP)/src/random.c \
   129    130     $(TOP)/src/resolve.c \
   130    131     $(TOP)/src/select.c \
   131    132     $(TOP)/src/status.c \
................................................................................
   238    239   
   239    240   TESTSRC2 = \
   240    241     $(TOP)/src/attach.c $(TOP)/src/btree.c $(TOP)/src/build.c $(TOP)/src/date.c  \
   241    242     $(TOP)/src/expr.c $(TOP)/src/func.c $(TOP)/src/insert.c $(TOP)/src/os.c      \
   242    243     $(TOP)/src/os_os2.c $(TOP)/src/os_unix.c $(TOP)/src/os_win.c                 \
   243    244     $(TOP)/src/pager.c $(TOP)/src/pragma.c $(TOP)/src/prepare.c                  \
   244    245     $(TOP)/src/printf.c $(TOP)/src/random.c $(TOP)/src/pcache.c                  \
   245         -  $(TOP)/src/select.c $(TOP)/src/tokenize.c                                    \
          246  +  $(TOP)/src/pcache1.c $(TOP)/src/select.c $(TOP)/src/tokenize.c               \
   246    247     $(TOP)/src/utf.c $(TOP)/src/util.c $(TOP)/src/vdbeapi.c $(TOP)/src/vdbeaux.c \
   247    248     $(TOP)/src/vdbe.c $(TOP)/src/vdbemem.c $(TOP)/src/where.c parse.c            \
   248    249     $(TOP)/ext/fts3/fts3.c $(TOP)/ext/fts3/fts3_tokenizer.c 
   249    250   
   250    251   # Header files used by all library source files.
   251    252   #
   252    253   HDR = \

Changes to src/btree.c.

     5      5   ** a legal notice, here is a blessing:
     6      6   **
     7      7   **    May you do good and not evil.
     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12         -** $Id: btree.c,v 1.534 2008/11/12 18:21:36 danielk1977 Exp $
           12  +** $Id: btree.c,v 1.535 2008/11/13 14:28:29 danielk1977 Exp $
    13     13   **
    14     14   ** This file implements a external (disk-based) database using BTrees.
    15     15   ** See the header comment on "btreeInt.h" for additional information.
    16     16   ** Including a description of file format and an overview of operation.
    17     17   */
    18     18   #include "btreeInt.h"
    19     19   
................................................................................
  2599   2599   ** save the state of the cursor.  The cursor must be
  2600   2600   ** invalidated.
  2601   2601   */
  2602   2602   void sqlite3BtreeTripAllCursors(Btree *pBtree, int errCode){
  2603   2603     BtCursor *p;
  2604   2604     sqlite3BtreeEnter(pBtree);
  2605   2605     for(p=pBtree->pBt->pCursor; p; p=p->pNext){
         2606  +    int i;
  2606   2607       sqlite3BtreeClearCursor(p);
  2607   2608       p->eState = CURSOR_FAULT;
  2608   2609       p->skip = errCode;
         2610  +    for(i=0; i<=p->iPage; i++){
         2611  +      releasePage(p->apPage[i]);
         2612  +      p->apPage[i] = 0;
         2613  +    }
  2609   2614     }
  2610   2615     sqlite3BtreeLeave(pBtree);
  2611   2616   }
  2612   2617   
  2613   2618   /*
  2614   2619   ** Rollback the transaction in progress.  All cursors will be
  2615   2620   ** invalided by this operation.  Any attempt to use a cursor
................................................................................
  5611   5616     usableSize = pBt->usableSize;
  5612   5617     data = pPage->aData;
  5613   5618     hdr = pPage->hdrOffset;
  5614   5619     cbrk = get2byte(&data[hdr+5]);
  5615   5620     cdata = pChild->aData;
  5616   5621     memcpy(cdata, &data[hdr], pPage->cellOffset+2*pPage->nCell-hdr);
  5617   5622     memcpy(&cdata[cbrk], &data[cbrk], usableSize-cbrk);
  5618         -  
         5623  +
         5624  +  assert( pChild->isInit==0 );
  5619   5625     rc = sqlite3BtreeInitPage(pChild);
  5620   5626     if( rc==SQLITE_OK ){
  5621   5627       int nCopy = pPage->nOverflow*sizeof(pPage->aOvfl[0]);
  5622   5628       memcpy(pChild->aOvfl, pPage->aOvfl, nCopy);
  5623   5629       pChild->nOverflow = pPage->nOverflow;
  5624   5630       if( pChild->nOverflow ){
  5625   5631         pChild->nFree = 0;

Changes to src/main.c.

    10     10   **
    11     11   *************************************************************************
    12     12   ** Main file for the SQLite library.  The routines in this file
    13     13   ** implement the programmer interface to the library.  Routines in
    14     14   ** other files are for internal use by SQLite and should not be
    15     15   ** accessed by users of the library.
    16     16   **
    17         -** $Id: main.c,v 1.511 2008/11/10 18:05:36 shane Exp $
           17  +** $Id: main.c,v 1.512 2008/11/13 14:28:29 danielk1977 Exp $
    18     18   */
    19     19   #include "sqliteInt.h"
    20     20   #include <ctype.h>
    21     21   
    22     22   #ifdef SQLITE_ENABLE_FTS3
    23     23   # include "fts3.h"
    24     24   #endif
................................................................................
   304    304       case SQLITE_CONFIG_PAGECACHE: {
   305    305         /* Designate a buffer for scratch memory space */
   306    306         sqlite3GlobalConfig.pPage = va_arg(ap, void*);
   307    307         sqlite3GlobalConfig.szPage = va_arg(ap, int);
   308    308         sqlite3GlobalConfig.nPage = va_arg(ap, int);
   309    309         break;
   310    310       }
          311  +
          312  +    case SQLITE_CONFIG_PCACHE: {
          313  +      /* Specify an alternative malloc implementation */
          314  +      sqlite3GlobalConfig.pcache = *va_arg(ap, sqlite3_pcache_methods*);
          315  +      break;
          316  +    }
   311    317   
   312    318   #if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
   313    319       case SQLITE_CONFIG_HEAP: {
   314    320         /* Designate a buffer for heap memory space */
   315    321         sqlite3GlobalConfig.pHeap = va_arg(ap, void*);
   316    322         sqlite3GlobalConfig.nHeap = va_arg(ap, int);
   317    323         sqlite3GlobalConfig.mnReq = va_arg(ap, int);

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.502 2008/11/07 00:24:54 drh Exp $
           21  +** @(#) $Id: pager.c,v 1.503 2008/11/13 14:28:29 danielk1977 Exp $
    22     22   */
    23     23   #ifndef SQLITE_OMIT_DISKIO
    24     24   #include "sqliteInt.h"
    25     25   
    26     26   /*
    27     27   ** Macros for troubleshooting.  Normally turned off
    28     28   */
................................................................................
   307    307   ** journal (or statement snapshot has been created, if *pPg is part
   308    308   ** of an in-memory database).
   309    309   */
   310    310   static int pageInStatement(PgHdr *pPg){
   311    311     Pager *pPager = pPg->pPager;
   312    312     return sqlite3BitvecTest(pPager->pInStmt, pPg->pgno);
   313    313   }
          314  +
          315  +static int pageInJournal(PgHdr *pPg){
          316  +  return sqlite3BitvecTest(pPg->pPager->pInJournal, pPg->pgno);
          317  +}
   314    318   
   315    319   /*
   316    320   ** Read a 32-bit integer from the given file descriptor.  Store the integer
   317    321   ** that is read in *pRes.  Return SQLITE_OK if everything worked, or an
   318    322   ** error code is something goes wrong.
   319    323   **
   320    324   ** All values are stored on disk as big-endian.
................................................................................
   450    454       hash = (hash*1039) + pData[i];
   451    455     }
   452    456     return hash;
   453    457   }
   454    458   static u32 pager_pagehash(PgHdr *pPage){
   455    459     return pager_datahash(pPage->pPager->pageSize, (unsigned char *)pPage->pData);
   456    460   }
   457         -static u32 pager_set_pagehash(PgHdr *pPage){
          461  +static void pager_set_pagehash(PgHdr *pPage){
   458    462     pPage->pageHash = pager_pagehash(pPage);
   459    463   }
   460    464   
   461    465   /*
   462    466   ** The CHECK_PAGE macro takes a PgHdr* as an argument. If SQLITE_CHECK_PAGES
   463    467   ** is defined, and NDEBUG is not defined, an assert() statement checks
   464    468   ** that the page is either dirty or still matches the calculated page-hash.
................................................................................
   993    997           rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0);
   994    998         }
   995    999       }
   996   1000       sqlite3BitvecDestroy(pPager->pInJournal);
   997   1001       pPager->pInJournal = 0;
   998   1002       sqlite3BitvecDestroy(pPager->pAlwaysRollback);
   999   1003       pPager->pAlwaysRollback = 0;
  1000         -    sqlite3PcacheCleanAll(pPager->pPCache);
  1001   1004   #ifdef SQLITE_CHECK_PAGES
  1002         -    sqlite3PcacheIterate(pPager->pPCache, pager_set_pagehash);
         1005  +    sqlite3PcacheIterateDirty(pPager->pPCache, pager_set_pagehash);
  1003   1006   #endif
  1004         -    sqlite3PcacheClearFlags(pPager->pPCache,
  1005         -       PGHDR_IN_JOURNAL | PGHDR_NEED_SYNC
  1006         -    );
         1007  +    sqlite3PcacheCleanAll(pPager->pPCache);
  1007   1008       pPager->dirtyCache = 0;
  1008   1009       pPager->nRec = 0;
  1009   1010     }else{
  1010   1011       assert( pPager->pInJournal==0 );
  1011   1012     }
  1012   1013   
  1013   1014     if( !pPager->exclusiveMode ){
................................................................................
  2335   2336         }
  2336   2337         pPager->journalStarted = 1;
  2337   2338       }
  2338   2339       pPager->needSync = 0;
  2339   2340   
  2340   2341       /* Erase the needSync flag from every page.
  2341   2342       */
  2342         -    sqlite3PcacheClearFlags(pPager->pPCache, PGHDR_NEED_SYNC);
         2343  +    sqlite3PcacheClearSyncFlags(pPager->pPCache);
  2343   2344     }
  2344   2345   
  2345         -#ifndef NDEBUG
  2346         -  /* If the Pager.needSync flag is clear then the PgHdr.needSync
  2347         -  ** flag must also be clear for all pages.  Verify that this
  2348         -  ** invariant is true.
  2349         -  */
  2350         -  else{
  2351         -    sqlite3PcacheAssertFlags(pPager->pPCache, 0, PGHDR_NEED_SYNC);
  2352         -  }
  2353         -#endif
  2354         -
  2355   2346     return rc;
  2356   2347   }
  2357   2348   
  2358   2349   /*
  2359   2350   ** Given a list of pages (connected by the PgHdr.pDirty pointer) write
  2360   2351   ** every one of those pages out to the database file. No calls are made
  2361   2352   ** to the page-cache to mark the pages as clean. It is the responsibility
................................................................................
  2848   2839     if( pPg->pPager==0 ){
  2849   2840       /* The pager cache has created a new page. Its content needs to 
  2850   2841       ** be initialized.
  2851   2842       */
  2852   2843       int nMax;
  2853   2844       PAGER_INCR(pPager->nMiss);
  2854   2845       pPg->pPager = pPager;
  2855         -    if( sqlite3BitvecTest(pPager->pInJournal, pgno) ){
  2856         -      pPg->flags |= PGHDR_IN_JOURNAL;
  2857         -    }
  2858   2846       memset(pPg->pExtra, 0, pPager->nExtra);
  2859   2847   
  2860   2848       rc = sqlite3PagerPagecount(pPager, &nMax);
  2861   2849       if( rc!=SQLITE_OK ){
  2862   2850         sqlite3PagerUnref(pPg);
  2863   2851         return rc;
  2864   2852       }
................................................................................
  3054   3042     Pager *pPager = pPg->pPager;
  3055   3043     int rc = SQLITE_OK;
  3056   3044     assert( pPg->nRef>0 );
  3057   3045     assert( pPager->state!=PAGER_UNLOCK );
  3058   3046     if( pPager->state==PAGER_SHARED ){
  3059   3047       assert( pPager->pInJournal==0 );
  3060   3048       assert( !MEMDB );
  3061         -    sqlite3PcacheAssertFlags(pPager->pPCache, 0, PGHDR_IN_JOURNAL);
  3062   3049       rc = sqlite3OsLock(pPager->fd, RESERVED_LOCK);
  3063   3050       if( rc==SQLITE_OK ){
  3064   3051         pPager->state = PAGER_RESERVED;
  3065   3052         if( exFlag ){
  3066   3053           rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
  3067   3054         }
  3068   3055       }
................................................................................
  3163   3150       return rc;
  3164   3151     }
  3165   3152   
  3166   3153     /* Mark the page as dirty.  If the page has already been written
  3167   3154     ** to the journal then we can return right away.
  3168   3155     */
  3169   3156     makeDirty(pPg);
  3170         -  if( (pPg->flags&PGHDR_IN_JOURNAL)
  3171         -   && (pageInStatement(pPg) || pPager->stmtInUse==0) 
  3172         -  ){
         3157  +  if( pageInJournal(pPg) && (pageInStatement(pPg) || pPager->stmtInUse==0) ){
  3173   3158       pPager->dirtyCache = 1;
  3174   3159       pPager->dbModified = 1;
  3175   3160     }else{
  3176   3161   
  3177   3162       /* If we get this far, it means that the page needs to be
  3178   3163       ** written to the transaction journal or the ckeckpoint journal
  3179   3164       ** or both.
................................................................................
  3195   3180       pPager->dirtyCache = 1;
  3196   3181       pPager->dbModified = 1;
  3197   3182     
  3198   3183       /* The transaction journal now exists and we have a RESERVED or an
  3199   3184       ** EXCLUSIVE lock on the main database file.  Write the current page to
  3200   3185       ** the transaction journal if it is not there already.
  3201   3186       */
  3202         -    if( !(pPg->flags&PGHDR_IN_JOURNAL) && pPager->journalOpen ){
         3187  +    if( !pageInJournal(pPg) && pPager->journalOpen ){
  3203   3188         if( (int)pPg->pgno <= pPager->origDbSize ){
  3204   3189           u32 cksum;
  3205   3190           char *pData2;
  3206   3191   
  3207   3192           /* We should never write to the journal file the page that
  3208   3193           ** contains the database locks.  The following assert verifies
  3209   3194           ** that we do not. */
................................................................................
  3250   3235           PAGERTRACE4("APPEND %d page %d needSync=%d\n",
  3251   3236                   PAGERID(pPager), pPg->pgno,
  3252   3237                  ((pPg->flags&PGHDR_NEED_SYNC)?1:0));
  3253   3238         }
  3254   3239         if( pPg->flags&PGHDR_NEED_SYNC ){
  3255   3240           pPager->needSync = 1;
  3256   3241         }
  3257         -      pPg->flags |= PGHDR_IN_JOURNAL;
  3258   3242       }
  3259   3243     
  3260   3244       /* If the statement journal is open and the page is not in it,
  3261   3245       ** then write the current page to the statement journal.  Note that
  3262   3246       ** the statement journal format differs from the standard journal format
  3263   3247       ** in that it omits the checksums and the header.
  3264   3248       */
  3265   3249       if( pPager->stmtInUse 
  3266   3250        && !pageInStatement(pPg) 
  3267   3251        && (int)pPg->pgno<=pPager->stmtSize 
  3268   3252       ){
  3269   3253         i64 offset = pPager->stmtNRec*(4+pPager->pageSize);
  3270   3254         char *pData2 = CODEC2(pPager, pData, pPg->pgno, 7);
  3271         -      assert( (pPg->flags&PGHDR_IN_JOURNAL) 
  3272         -                 || (int)pPg->pgno>pPager->origDbSize );
         3255  +      assert( pageInJournal(pPg) || (int)pPg->pgno>pPager->origDbSize );
  3273   3256         rc = write32bits(pPager->stfd, offset, pPg->pgno);
  3274   3257         if( rc==SQLITE_OK ){
  3275   3258           rc = sqlite3OsWrite(pPager->stfd, pData2, pPager->pageSize, offset+4);
  3276   3259         }
  3277   3260         PAGERTRACE3("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno);
  3278   3261         if( rc!=SQLITE_OK ){
  3279   3262           return rc;
................................................................................
  3511   3494     ** pages on the freelist (ex: corrupt9.test) then the following is not
  3512   3495     ** necessarily true:
  3513   3496     */
  3514   3497     /* assert( !pPg->inJournal && (int)pPg->pgno <= pPager->origDbSize ); */
  3515   3498   
  3516   3499     assert( pPager->pInJournal!=0 );
  3517   3500     sqlite3BitvecSet(pPager->pInJournal, pPg->pgno);
  3518         -  pPg->flags |= PGHDR_IN_JOURNAL;
  3519   3501     pPg->flags &= ~PGHDR_NEED_READ;
  3520   3502     if( pPager->stmtInUse ){
  3521   3503       assert( pPager->stmtSize >= pPager->origDbSize );
  3522   3504       sqlite3BitvecSet(pPager->pInStmt, pPg->pgno);
  3523   3505     }
  3524   3506     PAGERTRACE3("DONT_ROLLBACK page %d of %d\n", pPg->pgno, PAGERID(pPager));
  3525   3507     IOTRACE(("GARBAGE %p %d\n", pPager, pPg->pgno))
................................................................................
  4073   4055     **
  4074   4056     ** If the isCommit flag is set, there is no need to remember that
  4075   4057     ** the journal needs to be sync()ed before database page pPg->pgno 
  4076   4058     ** can be written to. The caller has already promised not to write to it.
  4077   4059     */
  4078   4060     if( (pPg->flags&PGHDR_NEED_SYNC) && !isCommit ){
  4079   4061       needSyncPgno = pPg->pgno;
  4080         -    assert( (pPg->flags&PGHDR_IN_JOURNAL) || (int)pgno>pPager->origDbSize );
         4062  +    assert( pageInJournal(pPg) || (int)pgno>pPager->origDbSize );
  4081   4063       assert( pPg->flags&PGHDR_DIRTY );
  4082   4064       assert( pPager->needSync );
  4083   4065     }
  4084   4066   
  4085   4067     /* If the cache contains a page with page-number pgno, remove it
  4086   4068     ** from its hash chain. Also, if the PgHdr.needSync was set for 
  4087   4069     ** page pgno before the 'move' operation, it needs to be retained 
  4088   4070     ** for the page moved there.
  4089   4071     */
  4090         -  pPg->flags &= ~(PGHDR_NEED_SYNC|PGHDR_IN_JOURNAL);
         4072  +  pPg->flags &= ~PGHDR_NEED_SYNC;
  4091   4073     pPgOld = pager_lookup(pPager, pgno);
  4092   4074     assert( !pPgOld || pPgOld->nRef==1 );
  4093   4075     if( pPgOld ){
  4094   4076       pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC);
  4095   4077     }
  4096         -  if( sqlite3BitvecTest(pPager->pInJournal, pgno) ){
  4097         -    pPg->flags |= PGHDR_IN_JOURNAL;
  4098         -  }
  4099   4078   
  4100   4079     sqlite3PcacheMove(pPg, pgno);
  4101   4080     if( pPgOld ){
  4102         -    sqlite3PcacheMove(pPgOld, 0);
  4103         -    sqlite3PcacheRelease(pPgOld);
         4081  +    sqlite3PcacheDrop(pPgOld);
  4104   4082     }
  4105   4083   
  4106   4084     makeDirty(pPg);
  4107   4085     pPager->dirtyCache = 1;
  4108   4086     pPager->dbModified = 1;
  4109   4087   
  4110   4088     if( needSyncPgno ){
................................................................................
  4134   4112           sqlite3BitvecClear(pPager->pInJournal, needSyncPgno);
  4135   4113         }
  4136   4114         return rc;
  4137   4115       }
  4138   4116       pPager->needSync = 1;
  4139   4117       assert( pPager->noSync==0 && !MEMDB );
  4140   4118       pPgHdr->flags |= PGHDR_NEED_SYNC;
  4141         -    pPgHdr->flags |= PGHDR_IN_JOURNAL;
  4142   4119       makeDirty(pPgHdr);
  4143   4120       sqlite3PagerUnref(pPgHdr);
  4144   4121     }
  4145   4122   
  4146   4123     return SQLITE_OK;
  4147   4124   }
  4148   4125   #endif

Changes to src/pcache.c.

     7      7   **    May you do good and not evil.
     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** This file implements that page cache.
    13     13   **
    14         -** @(#) $Id: pcache.c,v 1.36 2008/11/11 18:43:00 danielk1977 Exp $
           14  +** @(#) $Id: pcache.c,v 1.37 2008/11/13 14:28:29 danielk1977 Exp $
    15     15   */
    16     16   #include "sqliteInt.h"
    17     17   
    18     18   /*
    19     19   ** A complete page cache is an instance of this structure.
    20         -**
    21         -** A cache may only be deleted by its owner and while holding the
    22         -** SQLITE_MUTEX_STATUS_LRU mutex.
    23     20   */
    24     21   struct PCache {
    25         -  /*********************************************************************
    26         -  ** The first group of elements may be read or written at any time by
    27         -  ** the cache owner without holding the mutex.  No thread other than the
    28         -  ** cache owner is permitted to access these elements at any time.
    29         -  */
    30     22     PgHdr *pDirty, *pDirtyTail;         /* List of dirty pages in LRU order */
    31     23     PgHdr *pSynced;                     /* Last synced page in dirty page list */
    32         -  int nRef;                           /* Number of pinned pages */
    33         -  int nPinned;                        /* Number of pinned and/or dirty pages */
           24  +  int nRef;                           /* Number of referenced pages */
    34     25     int nMax;                           /* Configured cache size */
    35     26     int nMin;                           /* Configured minimum cache size */
    36         -  /**********************************************************************
    37         -  ** The next group of elements are fixed when the cache is created and
    38         -  ** may not be changed afterwards.  These elements can read at any time by
    39         -  ** the cache owner or by any thread holding the the mutex.  Non-owner
    40         -  ** threads must hold the mutex when reading these elements to prevent
    41         -  ** the entire PCache object from being deleted during the read.
    42         -  */
    43     27     int szPage;                         /* Size of every page in this cache */
    44     28     int szExtra;                        /* Size of extra space for each page */
    45     29     int bPurgeable;                     /* True if pages are on backing store */
    46     30     int (*xStress)(void*,PgHdr*);       /* Call to try make a page clean */
    47     31     void *pStress;                      /* Argument to xStress */
    48         -  /**********************************************************************
    49         -  ** The final group of elements can only be accessed while holding the
    50         -  ** mutex.  Both the cache owner and any other thread must hold the mutex
    51         -  ** to read or write any of these elements.
    52         -  */
    53         -  int nPage;                          /* Total number of pages in apHash */
    54         -  int nHash;                          /* Number of slots in apHash[] */
    55         -  PgHdr **apHash;                     /* Hash table for fast lookup by pgno */
    56         -  PgHdr *pClean;                      /* List of clean pages in use */
           32  +  sqlite3_pcache *pCache;             /* Pluggable cache module */
           33  +  PgHdr *pPage1;
    57     34   };
    58     35   
    59         -/*
    60         -** Free slots in the page block allocator
    61         -*/
    62         -typedef struct PgFreeslot PgFreeslot;
    63         -struct PgFreeslot {
    64         -  PgFreeslot *pNext;  /* Next free slot */
    65         -};
    66         -
    67         -/*
    68         -** Global data for the page cache.
    69         -*/
    70         -static SQLITE_WSD struct PCacheGlobal {
    71         -  int isInit;                         /* True when initialized */
    72         -  sqlite3_mutex *mutex;               /* static mutex MUTEX_STATIC_LRU */
    73         -
    74         -  int nMaxPage;                       /* Sum of nMaxPage for purgeable caches */
    75         -  int nMinPage;                       /* Sum of nMinPage for purgeable caches */
    76         -  int nCurrentPage;                   /* Number of purgeable pages allocated */
    77         -  PgHdr *pLruHead, *pLruTail;         /* LRU list of unused clean pgs */
    78         -
    79         -  /* Variables related to SQLITE_CONFIG_PAGECACHE settings. */
    80         -  int szSlot;                         /* Size of each free slot */
    81         -  void *pStart, *pEnd;                /* Bounds of pagecache malloc range */
    82         -  PgFreeslot *pFree;                  /* Free page blocks */
    83         -} pcache = {0};
    84         -
    85         -/*
    86         -** All code in this file should access the global pcache structure via the
    87         -** alias "pcache_g". This ensures that the WSD emulation is used when
    88         -** compiling for systems that do not support real WSD.
    89         -*/
    90         -#define pcache_g (GLOBAL(struct PCacheGlobal, pcache))
    91         -
    92         -/*
    93         -** All global variables used by this module (all of which are grouped 
    94         -** together in global structure "pcache" above) are protected by the static 
    95         -** SQLITE_MUTEX_STATIC_LRU mutex. A pointer to this mutex is stored in
    96         -** variable "pcache.mutex".
    97         -**
    98         -** Some elements of the PCache and PgHdr structures are protected by the 
    99         -** SQLITE_MUTEX_STATUS_LRU mutex and other are not.  The protected
   100         -** elements are grouped at the end of the structures and are clearly
   101         -** marked.
   102         -**
   103         -** Use the following macros must surround all access (read or write)
   104         -** of protected elements.  The mutex is not recursive and may not be
   105         -** entered more than once.  The pcacheMutexHeld() macro should only be
   106         -** used within an assert() to verify that the mutex is being held.
   107         -*/
   108         -#define pcacheEnterMutex() sqlite3_mutex_enter(pcache_g.mutex)
   109         -#define pcacheExitMutex()  sqlite3_mutex_leave(pcache_g.mutex)
   110         -#define pcacheMutexHeld()  sqlite3_mutex_held(pcache_g.mutex)
   111         -
   112     36   /*
   113     37   ** Some of the assert() macros in this code are too expensive to run
   114     38   ** even during normal debugging.  Use them only rarely on long-running
   115     39   ** tests.  Enable the expensive asserts using the
   116     40   ** -DSQLITE_ENABLE_EXPENSIVE_ASSERT=1 compile-time option.
   117     41   */
   118     42   #ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
   119     43   # define expensive_assert(X)  assert(X)
   120     44   #else
   121     45   # define expensive_assert(X)
   122     46   #endif
   123     47   
   124     48   /********************************** Linked List Management ********************/
   125         -
   126         -#if !defined(NDEBUG) && defined(SQLITE_ENABLE_EXPENSIVE_ASSERT)
   127         -/*
   128         -** This routine verifies that the number of entries in the hash table
   129         -** is pCache->nPage.  This routine is used within assert() statements
   130         -** only and is therefore disabled during production builds.
   131         -*/
   132         -static int pcacheCheckHashCount(PCache *pCache){
   133         -  int i;
   134         -  int nPage = 0;
   135         -  for(i=0; i<pCache->nHash; i++){
   136         -    PgHdr *p;
   137         -    for(p=pCache->apHash[i]; p; p=p->pNextHash){
   138         -      nPage++;
   139         -    }
   140         -  }
   141         -  assert( nPage==pCache->nPage );
   142         -  return 1;
   143         -}
   144         -#endif /* !NDEBUG && SQLITE_ENABLE_EXPENSIVE_ASSERT */
   145         -
   146         -
   147         -#if !defined(NDEBUG) && defined(SQLITE_ENABLE_EXPENSIVE_ASSERT)
   148         -/*
   149         -** Based on the current value of PCache.nRef and the contents of the
   150         -** PCache.pDirty list, return the expected value of the PCache.nPinned
   151         -** counter. This is only used in debugging builds, as follows:
   152         -**
   153         -**   expensive_assert( pCache->nPinned==pcachePinnedCount(pCache) );
   154         -*/
   155         -static int pcachePinnedCount(PCache *pCache){
   156         -  PgHdr *p;
   157         -  int nPinned = pCache->nRef;
   158         -  for(p=pCache->pDirty; p; p=p->pNext){
   159         -    if( p->nRef==0 ){
   160         -      nPinned++;
   161         -    }
   162         -  }
   163         -  return nPinned;
   164         -}
   165         -#endif /* !NDEBUG && SQLITE_ENABLE_EXPENSIVE_ASSERT */
   166         -
   167     49   
   168     50   #if !defined(NDEBUG) && defined(SQLITE_ENABLE_EXPENSIVE_ASSERT)
   169     51   /*
   170     52   ** Check that the pCache->pSynced variable is set correctly. If it
   171     53   ** is not, either fail an assert or return zero. Otherwise, return
   172     54   ** non-zero. This is only used in debugging builds, as follows:
   173     55   **
   174     56   **   expensive_assert( pcacheCheckSynced(pCache) );
   175     57   */
   176     58   static int pcacheCheckSynced(PCache *pCache){
   177         -  PgHdr *p = pCache->pDirtyTail;
   178         -  for(p=pCache->pDirtyTail; p!=pCache->pSynced; p=p->pPrev){
           59  +  PgHdr *p;
           60  +  for(p=pCache->pDirtyTail; p!=pCache->pSynced; p=p->pDirtyPrev){
   179     61       assert( p->nRef || (p->flags&PGHDR_NEED_SYNC) );
   180     62     }
   181     63     return (p==0 || p->nRef || (p->flags&PGHDR_NEED_SYNC)==0);
   182     64   }
   183     65   #endif /* !NDEBUG && SQLITE_ENABLE_EXPENSIVE_ASSERT */
   184     66   
           67  +/*
           68  +** Remove page pPage from the list of dirty pages.
           69  +*/
           70  +static void pcacheRemoveFromDirtyList(PgHdr *pPage){
           71  +  PCache *p = pPage->pCache;
   185     72   
           73  +  assert( pPage->pDirtyNext || pPage==p->pDirtyTail );
           74  +  assert( pPage->pDirtyPrev || pPage==p->pDirty );
   186     75   
   187         -/*
   188         -** Remove a page from its hash table (PCache.apHash[]).
   189         -*/
   190         -static void pcacheRemoveFromHash(PgHdr *pPage){
   191         -  assert( pcacheMutexHeld() );
   192         -  if( pPage->pPrevHash ){
   193         -    pPage->pPrevHash->pNextHash = pPage->pNextHash;
           76  +  /* Update the PCache1.pSynced variable if necessary. */
           77  +  if( p->pSynced==pPage ){
           78  +    PgHdr *pSynced = pPage->pDirtyPrev;
           79  +    while( pSynced && (pSynced->flags&PGHDR_NEED_SYNC) ){
           80  +      pSynced = pSynced->pDirtyPrev;
           81  +    }
           82  +    p->pSynced = pSynced;
           83  +  }
           84  +
           85  +  if( pPage->pDirtyNext ){
           86  +    pPage->pDirtyNext->pDirtyPrev = pPage->pDirtyPrev;
   194     87     }else{
   195         -    PCache *pCache = pPage->pCache;
   196         -    u32 h = pPage->pgno % pCache->nHash;
   197         -    assert( pCache->apHash[h]==pPage );
   198         -    pCache->apHash[h] = pPage->pNextHash;
           88  +    assert( pPage==p->pDirtyTail );
           89  +    p->pDirtyTail = pPage->pDirtyPrev;
   199     90     }
   200         -  if( pPage->pNextHash ){
   201         -    pPage->pNextHash->pPrevHash = pPage->pPrevHash;
   202         -  }
   203         -  pPage->pCache->nPage--;
   204         -  expensive_assert( pcacheCheckHashCount(pPage->pCache) );
   205         -}
   206         -
   207         -/*
   208         -** Insert a page into the hash table
   209         -**
   210         -** The mutex must be held by the caller.
   211         -*/
   212         -static void pcacheAddToHash(PgHdr *pPage){
   213         -  PCache *pCache = pPage->pCache;
   214         -  u32 h = pPage->pgno % pCache->nHash;
   215         -  assert( pcacheMutexHeld() );
   216         -  pPage->pNextHash = pCache->apHash[h];
   217         -  pPage->pPrevHash = 0;
   218         -  if( pCache->apHash[h] ){
   219         -    pCache->apHash[h]->pPrevHash = pPage;
   220         -  }
   221         -  pCache->apHash[h] = pPage;
   222         -  pCache->nPage++;
   223         -  expensive_assert( pcacheCheckHashCount(pCache) );
   224         -}
   225         -
   226         -/*
   227         -** Attempt to increase the size the hash table to contain
   228         -** at least nHash buckets.
   229         -*/
   230         -static int pcacheResizeHash(PCache *pCache, int nHash){
   231         -  PgHdr *p;
   232         -  PgHdr **pNew;
   233         -  assert( pcacheMutexHeld() );
   234         -#ifdef SQLITE_MALLOC_SOFT_LIMIT
   235         -  if( nHash*sizeof(PgHdr*)>SQLITE_MALLOC_SOFT_LIMIT ){
   236         -    nHash = SQLITE_MALLOC_SOFT_LIMIT/sizeof(PgHdr *);
   237         -  }
   238         -#endif
   239         -  pcacheExitMutex();
   240         -  pNew = (PgHdr **)sqlite3Malloc(sizeof(PgHdr*)*nHash);
   241         -  pcacheEnterMutex();
   242         -  if( !pNew ){
   243         -    return SQLITE_NOMEM;
   244         -  }
   245         -  memset(pNew, 0, sizeof(PgHdr *)*nHash);
   246         -  sqlite3_free(pCache->apHash);
   247         -  pCache->apHash = pNew;
   248         -  pCache->nHash = nHash;
   249         -  pCache->nPage = 0;
   250         - 
   251         -  for(p=pCache->pClean; p; p=p->pNext){
   252         -    pcacheAddToHash(p);
   253         -  }
   254         -  for(p=pCache->pDirty; p; p=p->pNext){
   255         -    pcacheAddToHash(p);
   256         -  }
   257         -  return SQLITE_OK;
   258         -}
   259         -
   260         -/*
   261         -** Remove a page from a linked list that is headed by *ppHead.
   262         -** *ppHead is either PCache.pClean or PCache.pDirty.
   263         -*/
   264         -static void pcacheRemoveFromList(PgHdr **ppHead, PgHdr *pPage){
   265         -  int isDirtyList = (ppHead==&pPage->pCache->pDirty);
   266         -  assert( ppHead==&pPage->pCache->pClean || ppHead==&pPage->pCache->pDirty );
   267         -  assert( pcacheMutexHeld() || ppHead!=&pPage->pCache->pClean );
   268         -
   269         -  if( pPage->pPrev ){
   270         -    pPage->pPrev->pNext = pPage->pNext;
           91  +  if( pPage->pDirtyPrev ){
           92  +    pPage->pDirtyPrev->pDirtyNext = pPage->pDirtyNext;
   271     93     }else{
   272         -    assert( *ppHead==pPage );
   273         -    *ppHead = pPage->pNext;
   274         -  }
   275         -  if( pPage->pNext ){
   276         -    pPage->pNext->pPrev = pPage->pPrev;
   277         -  }
   278         -
   279         -  if( isDirtyList ){
   280         -    PCache *pCache = pPage->pCache;
   281         -    assert( pPage->pNext || pCache->pDirtyTail==pPage );
   282         -    if( !pPage->pNext ){
   283         -      pCache->pDirtyTail = pPage->pPrev;
   284         -    }
   285         -    if( pCache->pSynced==pPage ){
   286         -      PgHdr *pSynced = pPage->pPrev;
   287         -      while( pSynced && (pSynced->flags&PGHDR_NEED_SYNC) ){
   288         -        pSynced = pSynced->pPrev;
   289         -      }
   290         -      pCache->pSynced = pSynced;
   291         -    }
   292         -  }
   293         -}
   294         -
   295         -/*
   296         -** Add a page from a linked list that is headed by *ppHead.
   297         -** *ppHead is either PCache.pClean or PCache.pDirty.
   298         -*/
   299         -static void pcacheAddToList(PgHdr **ppHead, PgHdr *pPage){
   300         -  int isDirtyList = (ppHead==&pPage->pCache->pDirty);
   301         -  assert( ppHead==&pPage->pCache->pClean || ppHead==&pPage->pCache->pDirty );
   302         -
   303         -  if( (*ppHead) ){
   304         -    (*ppHead)->pPrev = pPage;
   305         -  }
   306         -  pPage->pNext = *ppHead;
   307         -  pPage->pPrev = 0;
   308         -  *ppHead = pPage;
   309         -
   310         -  if( isDirtyList ){
   311         -    PCache *pCache = pPage->pCache;
   312         -    if( !pCache->pDirtyTail ){
   313         -      assert( pPage->pNext==0 );
   314         -      pCache->pDirtyTail = pPage;
   315         -    }
   316         -    if( !pCache->pSynced && 0==(pPage->flags&PGHDR_NEED_SYNC) ){
   317         -      pCache->pSynced = pPage;
   318         -    }
   319         -  }
   320         -}
   321         -
   322         -/*
   323         -** Remove a page from the global LRU list
   324         -*/
   325         -static void pcacheRemoveFromLruList(PgHdr *pPage){
   326         -  assert( sqlite3_mutex_held(pcache_g.mutex) );
   327         -  assert( (pPage->flags&PGHDR_DIRTY)==0 );
   328         -  if( pPage->pCache->bPurgeable==0 ) return;
   329         -  if( pPage->pNextLru ){
   330         -    assert( pcache_g.pLruTail!=pPage );
   331         -    pPage->pNextLru->pPrevLru = pPage->pPrevLru;
   332         -  }else{
   333         -    assert( pcache_g.pLruTail==pPage );
   334         -    pcache_g.pLruTail = pPage->pPrevLru;
   335         -  }
   336         -  if( pPage->pPrevLru ){
   337         -    assert( pcache_g.pLruHead!=pPage );
   338         -    pPage->pPrevLru->pNextLru = pPage->pNextLru;
   339         -  }else{
   340         -    assert( pcache_g.pLruHead==pPage );
   341         -    pcache_g.pLruHead = pPage->pNextLru;
   342         -  }
   343         -}
   344         -
   345         -/*
   346         -** Add a page to the global LRU list.  The page is normally added
   347         -** to the front of the list so that it will be the last page recycled.
   348         -** However, if the PGHDR_REUSE_UNLIKELY bit is set, the page is added
   349         -** to the end of the LRU list so that it will be the next to be recycled.
   350         -*/
   351         -static void pcacheAddToLruList(PgHdr *pPage){
   352         -  assert( sqlite3_mutex_held(pcache_g.mutex) );
   353         -  assert( (pPage->flags&PGHDR_DIRTY)==0 );
   354         -  if( pPage->pCache->bPurgeable==0 ) return;
   355         -  if( pcache_g.pLruTail && (pPage->flags & PGHDR_REUSE_UNLIKELY)!=0 ){
   356         -    /* If reuse is unlikely.  Put the page at the end of the LRU list
   357         -    ** where it will be recycled sooner rather than later. 
   358         -    */
   359         -    assert( pcache_g.pLruHead );
   360         -    pPage->pNextLru = 0;
   361         -    pPage->pPrevLru = pcache_g.pLruTail;
   362         -    pcache_g.pLruTail->pNextLru = pPage;
   363         -    pcache_g.pLruTail = pPage;
   364         -    pPage->flags &= ~PGHDR_REUSE_UNLIKELY;
   365         -  }else{
   366         -    /* If reuse is possible. the page goes at the beginning of the LRU
   367         -    ** list so that it will be the last to be recycled.
   368         -    */
   369         -    if( pcache_g.pLruHead ){
   370         -      pcache_g.pLruHead->pPrevLru = pPage;
   371         -    }
   372         -    pPage->pNextLru = pcache_g.pLruHead;
   373         -    pcache_g.pLruHead = pPage;
   374         -    pPage->pPrevLru = 0;
   375         -    if( pcache_g.pLruTail==0 ){
   376         -      pcache_g.pLruTail = pPage;
   377         -    }
   378         -  }
   379         -}
   380         -
   381         -/*********************************************** Memory Allocation ***********
   382         -**
   383         -** Initialize the page cache memory pool.
   384         -**
   385         -** This must be called at start-time when no page cache lines are
   386         -** checked out. This function is not threadsafe.
   387         -*/
   388         -void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){
   389         -  PgFreeslot *p;
   390         -  sz &= ~7;
   391         -  pcache_g.szSlot = sz;
   392         -  pcache_g.pStart = pBuf;
   393         -  pcache_g.pFree = 0;
   394         -  while( n-- ){
   395         -    p = (PgFreeslot*)pBuf;
   396         -    p->pNext = pcache_g.pFree;
   397         -    pcache_g.pFree = p;
   398         -    pBuf = (void*)&((char*)pBuf)[sz];
   399         -  }
   400         -  pcache_g.pEnd = pBuf;
   401         -}
   402         -
   403         -/*
   404         -** Allocate a page cache line.  Look in the page cache memory pool first
   405         -** and use an element from it first if available.  If nothing is available
   406         -** in the page cache memory pool, go to the general purpose memory allocator.
   407         -*/
   408         -static void *pcacheMalloc(int sz, PCache *pCache){
   409         -  assert( sqlite3_mutex_held(pcache_g.mutex) );
   410         -  if( sz<=pcache_g.szSlot && pcache_g.pFree ){
   411         -    PgFreeslot *p = pcache_g.pFree;
   412         -    pcache_g.pFree = p->pNext;
   413         -    sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, sz);
   414         -    sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, 1);
   415         -    return (void*)p;
   416         -  }else{
   417         -    void *p;
   418         -
   419         -    /* Allocate a new buffer using sqlite3Malloc. Before doing so, exit the
   420         -    ** global pcache mutex and unlock the pager-cache object pCache. This is 
   421         -    ** so that if the attempt to allocate a new buffer causes the the 
   422         -    ** configured soft-heap-limit to be breached, it will be possible to
   423         -    ** reclaim memory from this pager-cache.
   424         -    */
   425         -    pcacheExitMutex();
   426         -    p = sqlite3Malloc(sz);
   427         -    pcacheEnterMutex();
   428         -
   429         -    if( p ){
   430         -      sz = sqlite3MallocSize(p);
   431         -      sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz);
   432         -    }
   433         -    return p;
   434         -  }
   435         -}
   436         -void *sqlite3PageMalloc(int sz){
   437         -  void *p;
   438         -  pcacheEnterMutex();
   439         -  p = pcacheMalloc(sz, 0);
   440         -  pcacheExitMutex();
   441         -  return p;
   442         -}
   443         -
   444         -/*
   445         -** Release a pager memory allocation
   446         -*/
   447         -static void pcacheFree(void *p){
   448         -  assert( sqlite3_mutex_held(pcache_g.mutex) );
   449         -  if( p==0 ) return;
   450         -  if( p>=pcache_g.pStart && p<pcache_g.pEnd ){
   451         -    PgFreeslot *pSlot;
   452         -    sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, -1);
   453         -    pSlot = (PgFreeslot*)p;
   454         -    pSlot->pNext = pcache_g.pFree;
   455         -    pcache_g.pFree = pSlot;
   456         -  }else{
   457         -    int iSize = sqlite3MallocSize(p);
   458         -    sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, -iSize);
   459         -    sqlite3_free(p);
   460         -  }
   461         -}
   462         -void sqlite3PageFree(void *p){
   463         -  pcacheEnterMutex();
   464         -  pcacheFree(p);
   465         -  pcacheExitMutex();
   466         -}
   467         -
   468         -/*
   469         -** Allocate a new page.
   470         -*/
   471         -static PgHdr *pcachePageAlloc(PCache *pCache){
   472         -  PgHdr *p;
   473         -  int sz = sizeof(*p) + pCache->szPage + pCache->szExtra;
   474         -  assert( sqlite3_mutex_held(pcache_g.mutex) );
   475         -  p = pcacheMalloc(sz, pCache);
   476         -  if( p==0 ) return 0;
   477         -  memset(p, 0, sizeof(PgHdr));
   478         -  p->pData = (void*)&p[1];
   479         -  p->pExtra = (void*)&((char*)p->pData)[pCache->szPage];
           94  +    assert( pPage==p->pDirty );
           95  +    p->pDirty = pPage->pDirtyNext;
           96  +  }
           97  +  pPage->pDirtyNext = 0;
           98  +  pPage->pDirtyPrev = 0;
           99  +
          100  +  expensive_assert( pcacheCheckSynced(p) );
          101  +}
          102  +
          103  +/*
          104  +** Add page pPage to the head of the dirty list (PCache1.pDirty is set to
          105  +** pPage).
          106  +*/
          107  +static void pcacheAddToDirtyList(PgHdr *pPage){
          108  +  PCache *p = pPage->pCache;
          109  +
          110  +  assert( pPage->pDirtyNext==0 && pPage->pDirtyPrev==0 && p->pDirty!=pPage );
          111  +
          112  +  pPage->pDirtyNext = p->pDirty;
          113  +  if( pPage->pDirtyNext ){
          114  +    assert( pPage->pDirtyNext->pDirtyPrev==0 );
          115  +    pPage->pDirtyNext->pDirtyPrev = pPage;
          116  +  }
          117  +  p->pDirty = pPage;
          118  +  if( !p->pDirtyTail ){
          119  +    p->pDirtyTail = pPage;
          120  +  }
          121  +  if( !p->pSynced && 0==(pPage->flags&PGHDR_NEED_SYNC) ){
          122  +    p->pSynced = pPage;
          123  +  }
          124  +  expensive_assert( pcacheCheckSynced(p) );
          125  +}
          126  +
          127  +/*
          128  +** Wrapper around the pluggable caches xUnpin method. If the cache is
          129  +** being used for an in-memory database, this function is a no-op.
          130  +*/
          131  +static void pcacheUnpin(PgHdr *p){
          132  +  PCache *pCache = p->pCache;
   480    133     if( pCache->bPurgeable ){
   481         -    pcache_g.nCurrentPage++;
   482         -  }
   483         -  return p;
   484         -}
   485         -
   486         -/*
   487         -** Deallocate a page
   488         -*/
   489         -static void pcachePageFree(PgHdr *p){
   490         -  assert( sqlite3_mutex_held(pcache_g.mutex) );
   491         -  if( p->pCache->bPurgeable ){
   492         -    pcache_g.nCurrentPage--;
   493         -  }
   494         -  pcacheFree(p);
   495         -}
   496         -
   497         -#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
   498         -/*
   499         -** Return the number of bytes that will be returned to the heap when
   500         -** the argument is passed to pcachePageFree().
   501         -*/
   502         -static int pcachePageSize(PgHdr *p){
   503         -  assert( sqlite3_mutex_held(pcache_g.mutex) );
   504         -  assert( !pcache_g.pStart );
   505         -  assert( p && p->pCache );
   506         -  return sqlite3MallocSize(p);
   507         -}
   508         -#endif
   509         -
   510         -/*
   511         -** Attempt to 'recycle' a page from the global LRU list. Only clean,
   512         -** unreferenced pages from purgeable caches are eligible for recycling.
   513         -**
   514         -** This function removes page pcache.pLruTail from the global LRU list,
   515         -** and from the hash-table and PCache.pClean list of the owner pcache.
   516         -** There should be no other references to the page.
   517         -**
   518         -** A pointer to the recycled page is returned, or NULL if no page is
   519         -** eligible for recycling.
   520         -*/
   521         -static PgHdr *pcacheRecyclePage(void){
   522         -  PgHdr *p = 0;
   523         -  assert( sqlite3_mutex_held(pcache_g.mutex) );
   524         -
   525         -  if( (p=pcache_g.pLruTail)!=0 ){
   526         -    assert( (p->flags&PGHDR_DIRTY)==0 );
   527         -    pcacheRemoveFromLruList(p);
   528         -    pcacheRemoveFromHash(p);
   529         -    pcacheRemoveFromList(&p->pCache->pClean, p);
   530         -  }
   531         -
   532         -  return p;
   533         -}
   534         -
   535         -/*
   536         -** Obtain space for a page. Try to recycle an old page if the limit on the 
   537         -** number of pages has been reached. If the limit has not been reached or
   538         -** there are no pages eligible for recycling, allocate a new page.
   539         -**
   540         -** Return a pointer to the new page, or NULL if an OOM condition occurs.
   541         -*/
   542         -static int pcacheRecycleOrAlloc(PCache *pCache, PgHdr **ppPage){
   543         -  PgHdr *p = 0;
   544         -
   545         -  int szPage = pCache->szPage;
   546         -  int szExtra = pCache->szExtra;
   547         -
   548         -  assert( pcache_g.isInit );
   549         -  assert( sqlite3_mutex_held(pcache_g.mutex) );
   550         -
   551         -  *ppPage = 0;
   552         -
   553         -  /* If we have reached either the global or the local limit for 
   554         -  ** pinned+dirty pages, and there is at least one dirty page,
   555         -  ** invoke the xStress callback to cause a page to become clean.
   556         -  */
   557         -  expensive_assert( pCache->nPinned==pcachePinnedCount(pCache) );
   558         -  expensive_assert( pcacheCheckSynced(pCache) );
   559         -  if( pCache->xStress
   560         -   && pCache->pDirty
   561         -   && (pCache->nPinned>=(pcache_g.nMaxPage+pCache->nMin-pcache_g.nMinPage)
   562         -           || pCache->nPinned>=pCache->nMax)
   563         -  ){
   564         -    PgHdr *pPg;
   565         -    assert(pCache->pDirtyTail);
   566         -
   567         -    for(pPg=pCache->pSynced; 
   568         -        pPg && (pPg->nRef || (pPg->flags&PGHDR_NEED_SYNC)); 
   569         -        pPg=pPg->pPrev
   570         -    );
   571         -    if( !pPg ){
   572         -      for(pPg=pCache->pDirtyTail; pPg && pPg->nRef; pPg=pPg->pPrev);
   573         -    }
   574         -    if( pPg ){
   575         -      int rc;
   576         -      pcacheExitMutex();
   577         -      rc = pCache->xStress(pCache->pStress, pPg);
   578         -      pcacheEnterMutex();
   579         -      if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){
   580         -        return rc;
   581         -      }
   582         -    }
   583         -  }
   584         -
   585         -  /* If either the local or the global page limit has been reached, 
   586         -  ** try to recycle a page. 
   587         -  */
   588         -  if( pCache->bPurgeable && (pCache->nPage>=pCache->nMax-1 ||
   589         -                             pcache_g.nCurrentPage>=pcache_g.nMaxPage) ){
   590         -    p = pcacheRecyclePage();
   591         -  }
   592         -
   593         -  /* If a page has been recycled but it is the wrong size, free it. */
   594         -  if( p && (p->pCache->szPage!=szPage || p->pCache->szPage!=szExtra) ){
   595         -    pcachePageFree(p);
   596         -    p = 0;
   597         -  }
   598         -
   599         -  if( !p ){
   600         -    p = pcachePageAlloc(pCache);
   601         -  }
   602         -
   603         -  *ppPage = p;
   604         -  return (p?SQLITE_OK:SQLITE_NOMEM);
          134  +    if( p->pgno==1 ){
          135  +      pCache->pPage1 = 0;
          136  +    }
          137  +    sqlite3GlobalConfig.pcache.xUnpin(pCache->pCache, p, 0);
          138  +  }
   605    139   }
   606    140   
   607    141   /*************************************************** General Interfaces ******
   608    142   **
   609    143   ** Initialize and shutdown the page cache subsystem. Neither of these 
   610    144   ** functions are threadsafe.
   611    145   */
   612    146   int sqlite3PcacheInitialize(void){
   613         -  assert( pcache_g.isInit==0 );
   614         -  memset(&pcache_g, 0, sizeof(pcache));
   615         -  if( sqlite3GlobalConfig.bCoreMutex ){
   616         -    /* No need to check the return value of sqlite3_mutex_alloc(). 
   617         -    ** Allocating a static mutex cannot fail.
   618         -    */
   619         -    pcache_g.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU);
          147  +  if( sqlite3GlobalConfig.pcache.xInit==0 ){
          148  +    sqlite3PCacheSetDefault();
   620    149     }
   621         -  pcache_g.isInit = 1;
   622         -  return SQLITE_OK;
          150  +  return sqlite3GlobalConfig.pcache.xInit(sqlite3GlobalConfig.pcache.pArg);
   623    151   }
   624    152   void sqlite3PcacheShutdown(void){
   625         -  memset(&pcache_g, 0, sizeof(pcache));
          153  +  if( sqlite3GlobalConfig.pcache.xShutdown ){
          154  +    sqlite3GlobalConfig.pcache.xShutdown(sqlite3GlobalConfig.pcache.pArg);
          155  +  }
   626    156   }
   627    157   
   628    158   /*
   629    159   ** Return the size in bytes of a PCache object.
   630    160   */
   631    161   int sqlite3PcacheSize(void){ return sizeof(PCache); }
   632    162   
   633    163   /*
   634         -** Create a new PCache object.  Storage space to hold the object
   635         -** has already been allocated and is passed in as the p pointer.
          164  +** Create a new PCache object. Storage space to hold the object
          165  +** has already been allocated and is passed in as the p pointer. 
          166  +** The caller discovers how much space needs to be allocated by 
          167  +** calling sqlite3PcacheSize().
   636    168   */
   637    169   void sqlite3PcacheOpen(
   638    170     int szPage,                  /* Size of every page */
   639    171     int szExtra,                 /* Extra space associated with each page */
   640    172     int bPurgeable,              /* True if pages are on backing store */
   641    173     int (*xStress)(void*,PgHdr*),/* Call to try to make pages clean */
   642    174     void *pStress,               /* Argument to xStress */
   643    175     PCache *p                    /* Preallocated space for the PCache */
   644    176   ){
   645         -  assert( pcache_g.isInit );
   646    177     memset(p, 0, sizeof(PCache));
   647    178     p->szPage = szPage;
   648    179     p->szExtra = szExtra;
   649    180     p->bPurgeable = bPurgeable;
   650    181     p->xStress = xStress;
   651    182     p->pStress = pStress;
   652    183     p->nMax = 100;
   653    184     p->nMin = 10;
   654         -
   655         -  pcacheEnterMutex();
   656         -  if( bPurgeable ){
   657         -    pcache_g.nMaxPage += p->nMax;
   658         -    pcache_g.nMinPage += p->nMin;
   659         -  }
   660         -
   661         -  pcacheExitMutex();
   662    185   }
   663    186   
   664    187   /*
   665         -** Change the page size for PCache object.  This can only happen
   666         -** when the cache is empty.
          188  +** Change the page size for PCache object. The caller must ensure that there
          189  +** are no outstanding page references when this function is called.
   667    190   */
   668    191   void sqlite3PcacheSetPageSize(PCache *pCache, int szPage){
   669         -  assert(pCache->nPage==0);
          192  +  assert( pCache->nRef==0 && pCache->pDirty==0 );
          193  +  if( pCache->pCache ){
          194  +    sqlite3GlobalConfig.pcache.xDestroy(pCache->pCache);
          195  +    pCache->pCache = 0;
          196  +  }
   670    197     pCache->szPage = szPage;
   671    198   }
   672    199   
   673    200   /*
   674    201   ** Try to obtain a page from the cache.
   675    202   */
   676    203   int sqlite3PcacheFetch(
   677    204     PCache *pCache,       /* Obtain the page from this cache */
   678    205     Pgno pgno,            /* Page number to obtain */
   679    206     int createFlag,       /* If true, create page if it does not exist already */
   680    207     PgHdr **ppPage        /* Write the page here */
   681    208   ){
   682         -  int rc = SQLITE_OK;
   683    209     PgHdr *pPage = 0;
          210  +  int eCreate;
   684    211   
   685         -  assert( pcache_g.isInit );
   686    212     assert( pCache!=0 );
   687    213     assert( pgno>0 );
   688         -  expensive_assert( pCache->nPinned==pcachePinnedCount(pCache) );
   689         -
   690         -  pcacheEnterMutex();
   691         -
   692         -  /* Search the hash table for the requested page. Exit early if it is found. */
   693         -  if( pCache->apHash ){
   694         -    u32 h = pgno % pCache->nHash;
   695         -    for(pPage=pCache->apHash[h]; pPage; pPage=pPage->pNextHash){
   696         -      if( pPage->pgno==pgno ){
   697         -        if( pPage->nRef==0 ){
   698         -          if( 0==(pPage->flags&PGHDR_DIRTY) ){
   699         -            pcacheRemoveFromLruList(pPage);
   700         -            pCache->nPinned++;
   701         -          }
   702         -          pCache->nRef++;
   703         -        }
   704         -        pPage->nRef++;
   705         -        break;
          214  +
          215  +  /* If the pluggable cache (sqlite3_pcache*) has not been allocated,
          216  +  ** allocate it now.
          217  +  */
          218  +  if( !pCache->pCache && createFlag ){
          219  +    sqlite3_pcache *p;
          220  +    int nByte;
          221  +    nByte = pCache->szPage + pCache->szExtra + sizeof(PgHdr);
          222  +    p = sqlite3GlobalConfig.pcache.xCreate(nByte, pCache->bPurgeable);
          223  +    if( !p ){
          224  +      return SQLITE_NOMEM;
          225  +    }
          226  +    sqlite3GlobalConfig.pcache.xCachesize(p, pCache->nMax);
          227  +    pCache->pCache = p;
          228  +  }
          229  +
          230  +  eCreate = createFlag ? 1 : 0;
          231  +  if( eCreate && (!pCache->bPurgeable || !pCache->pDirty) ){
          232  +    eCreate = 2;
          233  +  }
          234  +  if( pCache->pCache ){
          235  +    pPage = sqlite3GlobalConfig.pcache.xFetch(pCache->pCache, pgno, eCreate);
          236  +  }
          237  +
          238  +  if( !pPage && eCreate==1 ){
          239  +    PgHdr *pPg;
          240  +
          241  +    /* Find a dirty page to write-out and recycle. First try to find a 
          242  +    ** page that does not require a journal-sync (one with PGHDR_NEED_SYNC
          243  +    ** cleared), but if that is not possible settle for any other 
          244  +    ** unreferenced dirty page.
          245  +    */
          246  +    expensive_assert( pcacheCheckSynced(pCache) );
          247  +    for(pPg=pCache->pSynced; 
          248  +        pPg && (pPg->nRef || (pPg->flags&PGHDR_NEED_SYNC)); 
          249  +        pPg=pPg->pDirtyPrev
          250  +    );
          251  +    if( !pPg ){
          252  +      for(pPg=pCache->pDirtyTail; pPg && pPg->nRef; pPg=pPg->pDirtyPrev);
          253  +    }
          254  +    if( pPg ){
          255  +      int rc;
          256  +      rc = pCache->xStress(pCache->pStress, pPg);
          257  +      if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){
          258  +        return rc;
   706    259         }
   707    260       }
          261  +
          262  +    pPage = sqlite3GlobalConfig.pcache.xFetch(pCache->pCache, pgno, 2);
   708    263     }
   709    264   
   710         -  if( !pPage && createFlag ){
   711         -    if( pCache->nHash<=pCache->nPage ){
   712         -      rc = pcacheResizeHash(pCache, pCache->nHash<256 ? 256 : pCache->nHash*2);
   713         -    }
   714         -    if( rc==SQLITE_OK ){
   715         -      rc = pcacheRecycleOrAlloc(pCache, &pPage);
          265  +  if( pPage ){
          266  +    if( 0==pPage->nRef ){
          267  +      pCache->nRef++;
   716    268       }
   717         -    if( rc==SQLITE_OK ){
   718         -      pPage->pPager = 0;
   719         -      pPage->flags = 0;
   720         -      pPage->pDirty = 0;
   721         -      pPage->pgno = pgno;
   722         -      pPage->pCache = pCache;
   723         -      pPage->nRef = 1;
   724         -      pCache->nRef++;
   725         -      pCache->nPinned++;
   726         -      pcacheAddToList(&pCache->pClean, pPage);
   727         -      pcacheAddToHash(pPage);
          269  +    pPage->nRef++;
          270  +    pPage->pData = (void*)&pPage[1];
          271  +    pPage->pExtra = (void*)&((char*)pPage->pData)[pCache->szPage];
          272  +    pPage->pCache = pCache;
          273  +    pPage->pgno = pgno;
          274  +    if( pgno==1 ){
          275  +      pCache->pPage1 = pPage;
   728    276       }
   729    277     }
   730         -
   731         -  pcacheExitMutex();
   732         -
   733    278     *ppPage = pPage;
   734         -  expensive_assert( pCache->nPinned==pcachePinnedCount(pCache) );
   735         -  assert( pPage || !createFlag || rc!=SQLITE_OK );
   736         -  return rc;
          279  +  return (pPage==0 && eCreate) ? SQLITE_NOMEM : SQLITE_OK;
   737    280   }
   738    281   
   739    282   /*
   740         -** Dereference a page.  When the reference count reaches zero,
   741         -** move the page to the LRU list if it is clean.
          283  +** Decrement the reference count on a page. If the page is clean and the
          284  +** reference count drops to 0, then it is made elible for recycling.
   742    285   */
   743    286   void sqlite3PcacheRelease(PgHdr *p){
   744    287     assert( p->nRef>0 );
   745    288     p->nRef--;
   746    289     if( p->nRef==0 ){
   747    290       PCache *pCache = p->pCache;
   748    291       pCache->nRef--;
   749    292       if( (p->flags&PGHDR_DIRTY)==0 ){
   750         -      pCache->nPinned--;
   751         -      pcacheEnterMutex();
   752         -      if( pcache_g.nCurrentPage>pcache_g.nMaxPage ){
   753         -        pcacheRemoveFromList(&pCache->pClean, p);
   754         -        pcacheRemoveFromHash(p);
   755         -        pcachePageFree(p);
   756         -      }else{
   757         -        pcacheAddToLruList(p);
   758         -      }
   759         -      pcacheExitMutex();
          293  +      pcacheUnpin(p);
   760    294       }else{
   761         -      /* Move the page to the head of the caches dirty list. */
   762         -      pcacheRemoveFromList(&pCache->pDirty, p);
   763         -      pcacheAddToList(&pCache->pDirty, p);
          295  +      /* Move the page to the head of the dirty list. */
          296  +      pcacheRemoveFromDirtyList(p);
          297  +      pcacheAddToDirtyList(p);
   764    298       }
   765    299     }
   766    300   }
   767    301   
          302  +/*
          303  +** Increase the reference count of a supplied page by 1.
          304  +*/
   768    305   void sqlite3PcacheRef(PgHdr *p){
   769    306     assert(p->nRef>0);
   770    307     p->nRef++;
   771    308   }
   772    309   
   773    310   /*
   774    311   ** Drop a page from the cache. There must be exactly one reference to the
   775    312   ** page. This function deletes that reference, so after it returns the
   776    313   ** page pointed to by p is invalid.
   777    314   */
   778    315   void sqlite3PcacheDrop(PgHdr *p){
   779    316     PCache *pCache;
   780    317     assert( p->nRef==1 );
   781         -  assert( 0==(p->flags&PGHDR_DIRTY) );
          318  +  if( p->flags&PGHDR_DIRTY ){
          319  +    pcacheRemoveFromDirtyList(p);
          320  +  }
   782    321     pCache = p->pCache;
   783    322     pCache->nRef--;
   784         -  pCache->nPinned--;
   785         -  pcacheEnterMutex();
   786         -  pcacheRemoveFromList(&pCache->pClean, p);
   787         -  pcacheRemoveFromHash(p);
   788         -  pcachePageFree(p);
   789         -  pcacheExitMutex();
          323  +  if( p->pgno==1 ){
          324  +    pCache->pPage1 = 0;
          325  +  }
          326  +  sqlite3GlobalConfig.pcache.xUnpin(pCache->pCache, p, 1);
   790    327   }
   791    328   
   792    329   /*
   793         -** Make sure the page is marked as dirty.  If it isn't dirty already,
          330  +** Make sure the page is marked as dirty. If it isn't dirty already,
   794    331   ** make it so.
   795    332   */
   796    333   void sqlite3PcacheMakeDirty(PgHdr *p){
   797    334     PCache *pCache;
   798    335     p->flags &= ~PGHDR_DONT_WRITE;
   799         -  if( p->flags & PGHDR_DIRTY ) return;
   800         -  assert( (p->flags & PGHDR_DIRTY)==0 );
   801    336     assert( p->nRef>0 );
   802         -  pCache = p->pCache;
   803         -  pcacheEnterMutex();
   804         -  pcacheRemoveFromList(&pCache->pClean, p);
   805         -  pcacheAddToList(&pCache->pDirty, p);
   806         -  pcacheExitMutex();
   807         -  p->flags |= PGHDR_DIRTY;
   808         -}
   809         -
   810         -static void pcacheMakeClean(PgHdr *p){
   811         -  PCache *pCache = p->pCache;
   812         -  assert( p->flags & PGHDR_DIRTY );
   813         -  pcacheRemoveFromList(&pCache->pDirty, p);
   814         -  pcacheAddToList(&pCache->pClean, p);
   815         -  p->flags &= ~PGHDR_DIRTY;
   816         -  if( p->nRef==0 ){
   817         -    pcacheAddToLruList(p);
   818         -    pCache->nPinned--;
          337  +  if( 0==(p->flags & PGHDR_DIRTY) ){
          338  +    pCache = p->pCache;
          339  +    p->flags |= PGHDR_DIRTY;
          340  +    pcacheAddToDirtyList( p);
   819    341     }
   820         -  expensive_assert( pCache->nPinned==pcachePinnedCount(pCache) );
   821    342   }
   822    343   
   823    344   /*
   824         -** Make sure the page is marked as clean.  If it isn't clean already,
          345  +** Make sure the page is marked as clean. If it isn't clean already,
   825    346   ** make it so.
   826    347   */
   827    348   void sqlite3PcacheMakeClean(PgHdr *p){
   828    349     if( (p->flags & PGHDR_DIRTY) ){
   829         -    pcacheEnterMutex();
   830         -    pcacheMakeClean(p);
   831         -    pcacheExitMutex();
          350  +    pcacheRemoveFromDirtyList(p);
          351  +    p->flags &= ~(PGHDR_DIRTY|PGHDR_NEED_SYNC);
          352  +    if( p->nRef==0 ){
          353  +      pcacheUnpin(p);
          354  +    }
   832    355     }
   833    356   }
   834    357   
   835    358   /*
   836    359   ** Make every page in the cache clean.
   837    360   */
   838    361   void sqlite3PcacheCleanAll(PCache *pCache){
   839    362     PgHdr *p;
   840         -  pcacheEnterMutex();
   841    363     while( (p = pCache->pDirty)!=0 ){
   842         -    pcacheRemoveFromList(&pCache->pDirty, p);
   843         -    p->flags &= ~PGHDR_DIRTY;
   844         -    pcacheAddToList(&pCache->pClean, p);
   845         -    if( p->nRef==0 ){
   846         -      pcacheAddToLruList(p);
   847         -      pCache->nPinned--;
   848         -    }
          364  +    sqlite3PcacheMakeClean(p);
          365  +  }
          366  +}
          367  +
          368  +/*
          369  +** Clear the PGHDR_NEED_SYNC flag from all dirty pages.
          370  +*/
          371  +void sqlite3PcacheClearSyncFlags(PCache *pCache){
          372  +  PgHdr *p;
          373  +  for(p=pCache->pDirty; p; p=p->pDirtyNext){
          374  +    p->flags &= ~PGHDR_NEED_SYNC;
   849    375     }
   850         -  sqlite3PcacheAssertFlags(pCache, 0, PGHDR_DIRTY);
   851         -  expensive_assert( pCache->nPinned==pcachePinnedCount(pCache) );
   852         -  pcacheExitMutex();
          376  +  pCache->pSynced = pCache->pDirtyTail;
   853    377   }
   854    378   
   855    379   /*
   856         -** Change the page number of page p to newPgno. If newPgno is 0, then the
   857         -** page object is added to the clean-list and the PGHDR_REUSE_UNLIKELY 
   858         -** flag set.
          380  +** Change the page number of page p to newPgno. 
   859    381   */
   860    382   void sqlite3PcacheMove(PgHdr *p, Pgno newPgno){
          383  +  PCache *pCache = p->pCache;
   861    384     assert( p->nRef>0 );
   862         -  pcacheEnterMutex();
   863         -  pcacheRemoveFromHash(p);
          385  +  assert( newPgno>0 );
          386  +  sqlite3GlobalConfig.pcache.xRekey(pCache->pCache, p, p->pgno, newPgno);
   864    387     p->pgno = newPgno;
   865         -  if( newPgno==0 ){
   866         -    if( (p->flags & PGHDR_DIRTY) ){
   867         -      pcacheMakeClean(p);
   868         -    }
   869         -    p->flags = PGHDR_REUSE_UNLIKELY;
          388  +  if( (p->flags&PGHDR_DIRTY) && (p->flags&PGHDR_NEED_SYNC) ){
          389  +    pcacheRemoveFromDirtyList(p);
          390  +    pcacheAddToDirtyList(p);
   870    391     }
   871         -  pcacheAddToHash(p);
   872         -  pcacheExitMutex();
   873    392   }
   874    393   
   875    394   /*
   876         -** Remove all content from a page cache
   877         -*/
   878         -static void pcacheClear(PCache *pCache){
   879         -  PgHdr *p, *pNext;
   880         -  assert( sqlite3_mutex_held(pcache_g.mutex) );
   881         -  for(p=pCache->pClean; p; p=pNext){
   882         -    pNext = p->pNext;
   883         -    pcacheRemoveFromLruList(p);
   884         -    pcachePageFree(p);
   885         -  }
   886         -  for(p=pCache->pDirty; p; p=pNext){
   887         -    pNext = p->pNext;
   888         -    pcachePageFree(p);
   889         -  }
   890         -  pCache->pClean = 0;
   891         -  pCache->pDirty = 0;
   892         -  pCache->pDirtyTail = 0;
   893         -  pCache->nPage = 0;
   894         -  pCache->nPinned = 0;
   895         -  memset(pCache->apHash, 0, pCache->nHash*sizeof(pCache->apHash[0]));
   896         -}
   897         -
   898         -
   899         -/*
   900         -** Drop every cache entry whose page number is greater than "pgno".
          395  +** Drop every cache entry whose page number is greater than "pgno". The
          396  +** caller must ensure that there are no outstanding references to any pages
          397  +** other than page 1 with a page number greater than pgno.
          398  +**
          399  +** If there is a reference to page 1 and the pgno parameter passed to this
          400  +** function is 0, then the data area associated with page 1 is zeroed, but
          401  +** the page object is not dropped.
   901    402   */
   902    403   void sqlite3PcacheTruncate(PCache *pCache, Pgno pgno){
   903         -  PgHdr *p, *pNext;
   904         -  PgHdr *pDirty = pCache->pDirty;
   905         -  pcacheEnterMutex();
   906         -  for(p=pCache->pClean; p||pDirty; p=pNext){
   907         -    if( !p ){
   908         -      p = pDirty;
   909         -      pDirty = 0;
   910         -    }
   911         -    pNext = p->pNext;
   912         -    if( p->pgno>pgno ){
   913         -      if( p->nRef==0 ){
   914         -        pcacheRemoveFromHash(p);
   915         -        if( p->flags&PGHDR_DIRTY ){
   916         -          pcacheRemoveFromList(&pCache->pDirty, p);
   917         -          pCache->nPinned--;
   918         -        }else{
   919         -          pcacheRemoveFromList(&pCache->pClean, p);
   920         -          pcacheRemoveFromLruList(p);
   921         -        }
   922         -        pcachePageFree(p);
   923         -      }else{
   924         -        /* If there are references to the page, it cannot be freed. In this
   925         -        ** case, zero the page content instead.
   926         -        */
   927         -        memset(p->pData, 0, pCache->szPage);
          404  +  if( pCache->pCache ){
          405  +    PgHdr *p;
          406  +    PgHdr *pNext;
          407  +    for(p=pCache->pDirty; p; p=pNext){
          408  +      pNext = p->pDirtyNext;
          409  +      if( p->pgno>pgno ){
          410  +        assert( p->flags&PGHDR_DIRTY );
          411  +        sqlite3PcacheMakeClean(p);
   928    412         }
   929    413       }
   930         -  }
   931         -  pcacheExitMutex();
   932         -}
   933         -
   934         -/*
   935         -** If there are currently more than pcache.nMaxPage pages allocated, try
   936         -** to recycle pages to reduce the number allocated to pcache.nMaxPage.
   937         -*/
   938         -static void pcacheEnforceMaxPage(void){
   939         -  PgHdr *p;
   940         -  assert( sqlite3_mutex_held(pcache_g.mutex) );
   941         -  while( pcache_g.nCurrentPage>pcache_g.nMaxPage
   942         -             && (p = pcacheRecyclePage())!=0 ){
   943         -    pcachePageFree(p);
          414  +    if( pgno==0 && pCache->pPage1 ){
          415  +      memset(pCache->pPage1->pData, 0, pCache->szPage);
          416  +      pgno = 1;
          417  +    }
          418  +    sqlite3GlobalConfig.pcache.xTruncate(pCache->pCache, pgno+1);
   944    419     }
   945    420   }
   946    421   
   947    422   /*
   948    423   ** Close a cache.
   949    424   */
   950    425   void sqlite3PcacheClose(PCache *pCache){
   951         -  pcacheEnterMutex();
   952         -
   953         -  /* Free all the pages used by this pager and remove them from the LRU list. */
   954         -  pcacheClear(pCache);
   955         -  if( pCache->bPurgeable ){
   956         -    pcache_g.nMaxPage -= pCache->nMax;
   957         -    pcache_g.nMinPage -= pCache->nMin;
   958         -    pcacheEnforceMaxPage();
   959         -  }
   960         -  sqlite3_free(pCache->apHash);
   961         -  pcacheExitMutex();
   962         -}
   963         -
   964         -
   965         -#ifndef NDEBUG
   966         -/* 
   967         -** Assert flags settings on all pages.  Debugging only.
   968         -*/
   969         -void sqlite3PcacheAssertFlags(PCache *pCache, int trueMask, int falseMask){
   970         -  PgHdr *p;
   971         -  for(p=pCache->pDirty; p; p=p->pNext){
   972         -    assert( (p->flags&trueMask)==trueMask );
   973         -    assert( (p->flags&falseMask)==0 );
   974         -  }
   975         -  for(p=pCache->pClean; p; p=p->pNext){
   976         -    assert( (p->flags&trueMask)==trueMask );
   977         -    assert( (p->flags&falseMask)==0 );
          426  +  if( pCache->pCache ){
          427  +    sqlite3GlobalConfig.pcache.xDestroy(pCache->pCache);
   978    428     }
   979    429   }
   980         -#endif
   981    430   
   982    431   /* 
   983    432   ** Discard the contents of the cache.
   984    433   */
   985    434   int sqlite3PcacheClear(PCache *pCache){
   986         -  assert(pCache->nRef==0);
   987         -  pcacheEnterMutex();
   988         -  pcacheClear(pCache);
   989         -  pcacheExitMutex();
          435  +  sqlite3PcacheTruncate(pCache, 0);
   990    436     return SQLITE_OK;
   991    437   }
   992    438   
   993    439   /*
   994    440   ** Merge two lists of pages connected by pDirty and in pgno order.
   995         -** Do not both fixing the pPrevDirty pointers.
          441  +** Do not both fixing the pDirtyPrev pointers.
   996    442   */
   997    443   static PgHdr *pcacheMergeDirtyList(PgHdr *pA, PgHdr *pB){
   998    444     PgHdr result, *pTail;
   999    445     pTail = &result;
  1000    446     while( pA && pB ){
  1001    447       if( pA->pgno<pB->pgno ){
  1002    448         pTail->pDirty = pA;
................................................................................
  1016    462       pTail->pDirty = 0;
  1017    463     }
  1018    464     return result.pDirty;
  1019    465   }
  1020    466   
  1021    467   /*
  1022    468   ** Sort the list of pages in accending order by pgno.  Pages are
  1023         -** connected by pDirty pointers.  The pPrevDirty pointers are
          469  +** connected by pDirty pointers.  The pDirtyPrev pointers are
  1024    470   ** corrupted by this sort.
  1025    471   */
  1026    472   #define N_SORT_BUCKET_ALLOC 25
  1027    473   #define N_SORT_BUCKET       25
  1028    474   #ifdef SQLITE_TEST
  1029    475     int sqlite3_pager_n_sort_bucket = 0;
  1030    476     #undef N_SORT_BUCKET
................................................................................
  1065    511   }
  1066    512   
  1067    513   /*
  1068    514   ** Return a list of all dirty pages in the cache, sorted by page number.
  1069    515   */
  1070    516   PgHdr *sqlite3PcacheDirtyList(PCache *pCache){
  1071    517     PgHdr *p;
  1072         -  for(p=pCache->pDirty; p; p=p->pNext){
  1073         -    p->pDirty = p->pNext;
          518  +  for(p=pCache->pDirty; p; p=p->pDirtyNext){
          519  +    p->pDirty = p->pDirtyNext;
  1074    520     }
  1075    521     return pcacheSortDirtyList(pCache->pDirty);
  1076    522   }
  1077    523   
  1078    524   /* 
  1079         -** Return the total number of outstanding page references.
          525  +** Return the total number of referenced pages held by the cache.
  1080    526   */
  1081    527   int sqlite3PcacheRefCount(PCache *pCache){
  1082    528     return pCache->nRef;
  1083    529   }
  1084    530   
          531  +/*
          532  +** Return the number of references to the page supplied as an argument.
          533  +*/
  1085    534   int sqlite3PcachePageRefcount(PgHdr *p){
  1086    535     return p->nRef;
  1087    536   }
  1088    537   
  1089    538   /* 
  1090    539   ** Return the total number of pages in the cache.
  1091    540   */
  1092    541   int sqlite3PcachePagecount(PCache *pCache){
  1093         -  assert( pCache->nPage>=0 );
  1094         -  return pCache->nPage;
  1095         -}
  1096         -
  1097         -#ifdef SQLITE_CHECK_PAGES
  1098         -/*
  1099         -** This function is used by the pager.c module to iterate through all 
  1100         -** pages in the cache. At present, this is only required if the
  1101         -** SQLITE_CHECK_PAGES macro (used for debugging) is specified.
  1102         -*/
  1103         -void sqlite3PcacheIterate(PCache *pCache, void (*xIter)(PgHdr *)){
  1104         -  PgHdr *p;
  1105         -  for(p=pCache->pClean; p; p=p->pNext){
  1106         -    xIter(p);
          542  +  int nPage = 0;
          543  +  if( pCache->pCache ){
          544  +    nPage = sqlite3GlobalConfig.pcache.xPagecount(pCache->pCache);
  1107    545     }
  1108         -  for(p=pCache->pDirty; p; p=p->pNext){
  1109         -    xIter(p);
  1110         -  }
  1111         -}
  1112         -#endif
  1113         -
  1114         -/* 
  1115         -** Set flags on all pages in the page cache 
  1116         -*/
  1117         -void sqlite3PcacheClearFlags(PCache *pCache, int mask){
  1118         -  PgHdr *p;
  1119         -
  1120         -  /* Obtain the global mutex before modifying any PgHdr.flags variables 
  1121         -  ** or traversing the LRU list.
  1122         -  */ 
  1123         -  pcacheEnterMutex();
  1124         -
  1125         -  mask = ~mask;
  1126         -  for(p=pCache->pDirty; p; p=p->pNext){
  1127         -    p->flags &= mask;
  1128         -  }
  1129         -  for(p=pCache->pClean; p; p=p->pNext){
  1130         -    p->flags &= mask;
  1131         -  }
  1132         -
  1133         -  if( 0==(mask&PGHDR_NEED_SYNC) ){
  1134         -    pCache->pSynced = pCache->pDirtyTail;
  1135         -    assert( !pCache->pSynced || (pCache->pSynced->flags&PGHDR_NEED_SYNC)==0 );
  1136         -  }
  1137         -
  1138         -  pcacheExitMutex();
          546  +  return nPage;
  1139    547   }
  1140    548   
  1141    549   /*
  1142         -** Set the suggested cache-size value.
          550  +** Get the suggested cache-size value.
  1143    551   */
  1144    552   int sqlite3PcacheGetCachesize(PCache *pCache){
  1145    553     return pCache->nMax;
  1146    554   }
  1147    555   
  1148    556   /*
  1149    557   ** Set the suggested cache-size value.
  1150    558   */
  1151    559   void sqlite3PcacheSetCachesize(PCache *pCache, int mxPage){
  1152         -  if( mxPage<10 ){
  1153         -    mxPage = 10;
  1154         -  }
  1155         -  if( pCache->bPurgeable ){
  1156         -    pcacheEnterMutex();
  1157         -    pcache_g.nMaxPage -= pCache->nMax;
  1158         -    pcache_g.nMaxPage += mxPage;
  1159         -    pcacheEnforceMaxPage();
  1160         -    pcacheExitMutex();
  1161         -  }
  1162    560     pCache->nMax = mxPage;
          561  +  if( pCache->pCache ){
          562  +    sqlite3GlobalConfig.pcache.xCachesize(pCache->pCache, mxPage);
          563  +  }
  1163    564   }
  1164    565   
  1165         -#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
          566  +#ifdef SQLITE_CHECK_PAGES
  1166    567   /*
  1167         -** This function is called to free superfluous dynamically allocated memory
  1168         -** held by the pager system. Memory in use by any SQLite pager allocated
  1169         -** by the current thread may be sqlite3_free()ed.
  1170         -**
  1171         -** nReq is the number of bytes of memory required. Once this much has
  1172         -** been released, the function returns. The return value is the total number 
  1173         -** of bytes of memory released.
          568  +** For all dirty pages currently in the cache, invoke the specified
          569  +** callback. This is only used if the SQLITE_CHECK_PAGES macro is
          570  +** defined.
  1174    571   */
  1175         -int sqlite3PcacheReleaseMemory(int nReq){
  1176         -  int nFree = 0;
  1177         -  if( pcache_g.pStart==0 ){
  1178         -    PgHdr *p;
  1179         -    pcacheEnterMutex();
  1180         -    while( (nReq<0 || nFree<nReq) && (p=pcacheRecyclePage()) ){
  1181         -      nFree += pcachePageSize(p);
  1182         -      pcachePageFree(p);
  1183         -    }
  1184         -    pcacheExitMutex();
          572  +void sqlite3PcacheIterateDirty(PCache *pCache, void (*xIter)(PgHdr *)){
          573  +  PgHdr *pDirty;
          574  +  for(pDirty=pCache->pDirty; pDirty; pDirty=pDirty->pDirtyNext){
          575  +    xIter(pDirty);
  1185    576     }
  1186         -  return nFree;
  1187         -}
  1188         -#endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */
  1189         -
  1190         -#ifdef SQLITE_TEST
  1191         -void sqlite3PcacheStats(
  1192         -  int *pnCurrent,
  1193         -  int *pnMax,
  1194         -  int *pnMin,
  1195         -  int *pnRecyclable
  1196         -){
  1197         -  PgHdr *p;
  1198         -  int nRecyclable = 0;
  1199         -  for(p=pcache_g.pLruHead; p; p=p->pNextLru){
  1200         -    nRecyclable++;
  1201         -  }
  1202         -
  1203         -  *pnCurrent = pcache_g.nCurrentPage;
  1204         -  *pnMax = pcache_g.nMaxPage;
  1205         -  *pnMin = pcache_g.nMinPage;
  1206         -  *pnRecyclable = nRecyclable;
  1207    577   }
  1208    578   #endif
          579  +

Changes to src/pcache.h.

     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** This header file defines the interface that the sqlite page cache
    13     13   ** subsystem. 
    14     14   **
    15         -** @(#) $Id: pcache.h,v 1.14 2008/10/17 18:51:53 danielk1977 Exp $
           15  +** @(#) $Id: pcache.h,v 1.15 2008/11/13 14:28:29 danielk1977 Exp $
    16     16   */
    17     17   
    18     18   #ifndef _PCACHE_H_
    19     19   
    20     20   typedef struct PgHdr PgHdr;
    21     21   typedef struct PCache PCache;
    22     22   
................................................................................
    30     30     PgHdr *pDirty;                 /* Transient list of dirty pages */
    31     31     Pgno pgno;                     /* Page number for this page */
    32     32     Pager *pPager;                 /* The pager this page is part of */
    33     33   #ifdef SQLITE_CHECK_PAGES
    34     34     u32 pageHash;                  /* Hash of page content */
    35     35   #endif
    36     36     u16 flags;                     /* PGHDR flags defined below */
           37  +
    37     38     /**********************************************************************
    38     39     ** Elements above are public.  All that follows is private to pcache.c
    39     40     ** and should not be accessed by other modules.
    40     41     */
    41     42     i16 nRef;                      /* Number of users of this page */
    42     43     PCache *pCache;                /* Cache that owns this page */
    43     44   
    44         -  /**********************************************************************
    45         -  ** Elements above are accessible at any time by the owner of the cache
    46         -  ** without the need for a mutex.  The elements that follow can only be
    47         -  ** accessed while holding the SQLITE_MUTEX_STATIC_LRU mutex.
    48         -  */
    49         -  PgHdr *pNextHash, *pPrevHash;  /* Hash collision chain for PgHdr.pgno */
    50         -  PgHdr *pNext, *pPrev;          /* List of clean or dirty pages */
    51         -  PgHdr *pNextLru, *pPrevLru;    /* Part of global LRU list */
           45  +  PgHdr *pDirtyNext;             /* Next element in list of dirty pages */
           46  +  PgHdr *pDirtyPrev;             /* Previous element in list of dirty pages */
    52     47   };
    53     48   
    54     49   /* Bit values for PgHdr.flags */
    55         -#define PGHDR_IN_JOURNAL        0x001  /* Page is in rollback journal */
    56     50   #define PGHDR_DIRTY             0x002  /* Page has changed */
    57     51   #define PGHDR_NEED_SYNC         0x004  /* Fsync the rollback journal before
    58     52                                          ** writing this page to the database */
    59     53   #define PGHDR_NEED_READ         0x008  /* Content is unread */
    60     54   #define PGHDR_REUSE_UNLIKELY    0x010  /* A hint that reuse is unlikely */
    61     55   #define PGHDR_DONT_WRITE        0x020  /* Do not write content to disk */
    62     56   
................................................................................
   112    106   /* Get a list of all dirty pages in the cache, sorted by page number */
   113    107   PgHdr *sqlite3PcacheDirtyList(PCache*);
   114    108   
   115    109   /* Reset and close the cache object */
   116    110   void sqlite3PcacheClose(PCache*);
   117    111   
   118    112   /* Clear flags from pages of the page cache */
   119         -void sqlite3PcacheClearFlags(PCache*, int mask);
   120         -
   121         -/* Assert flags settings on all pages.  Debugging only */
   122         -#ifndef NDEBUG
   123         -  void sqlite3PcacheAssertFlags(PCache*, int trueMask, int falseMask);
   124         -#else
   125         -# define sqlite3PcacheAssertFlags(A,B,C)
   126         -#endif
          113  +void sqlite3PcacheClearSyncFlags(PCache *);
   127    114   
   128    115   /* Return true if the number of dirty pages is 0 or 1 */
   129    116   int sqlite3PcacheZeroOrOneDirtyPages(PCache*);
   130    117   
   131    118   /* Discard the contents of the cache */
   132    119   int sqlite3PcacheClear(PCache*);
   133    120   
................................................................................
   139    126   
   140    127   int sqlite3PcachePageRefcount(PgHdr*);
   141    128   
   142    129   /* Return the total number of pages stored in the cache */
   143    130   int sqlite3PcachePagecount(PCache*);
   144    131   
   145    132   #ifdef SQLITE_CHECK_PAGES
   146         -/* Iterate through all pages currently stored in the cache. This interface
   147         -** is only available if SQLITE_CHECK_PAGES is defined when the library is 
   148         -** built.
          133  +/* Iterate through all dirty pages currently stored in the cache. This
          134  +** interface is only available if SQLITE_CHECK_PAGES is defined when the 
          135  +** library is built.
   149    136   */
   150         -void sqlite3PcacheIterate(PCache *pCache, void (*xIter)(PgHdr *));
          137  +void sqlite3PcacheIterateDirty(PCache *pCache, void (*xIter)(PgHdr *));
   151    138   #endif
   152    139   
   153    140   /* Set and get the suggested cache-size for the specified pager-cache.
   154    141   **
   155    142   ** If no global maximum is configured, then the system attempts to limit
   156    143   ** the total number of pages cached by purgeable pager-caches to the sum
   157    144   ** of the suggested cache-sizes.
................................................................................
   163    150   /* Try to return memory used by the pcache module to the main memory heap */
   164    151   int sqlite3PcacheReleaseMemory(int);
   165    152   #endif
   166    153   
   167    154   #ifdef SQLITE_TEST
   168    155   void sqlite3PcacheStats(int*,int*,int*,int*);
   169    156   #endif
          157  +
          158  +void sqlite3PCacheSetDefault(void);
   170    159   
   171    160   #endif /* _PCACHE_H_ */

Added src/pcache1.c.

            1  +/*
            2  +** 2008 November 05
            3  +**
            4  +** The author disclaims copyright to this source code.  In place of
            5  +** a legal notice, here is a blessing:
            6  +**
            7  +**    May you do good and not evil.
            8  +**    May you find forgiveness for yourself and forgive others.
            9  +**    May you share freely, never taking more than you give.
           10  +**
           11  +*************************************************************************
           12  +**
           13  +** This file implements the default page cache implementation (the
           14  +** sqlite3_pcache interface). It also contains part of the implementation
           15  +** of the SQLITE_CONFIG_PAGECACHE and sqlite3_release_memory() features.
           16  +** If the default page cache implementation is overriden, then neither of
           17  +** these two features are available.
           18  +**
           19  +** @(#) $Id: pcache1.c,v 1.1 2008/11/13 14:28:29 danielk1977 Exp $
           20  +*/
           21  +
           22  +#include "sqliteInt.h"
           23  +
           24  +typedef struct PCache1 PCache1;
           25  +typedef struct PgHdr1 PgHdr1;
           26  +typedef struct PgFreeslot PgFreeslot;
           27  +
           28  +/* Pointers to structures of this type are cast and returned as 
           29  +** opaque sqlite3_pcache* handles
           30  +*/
           31  +struct PCache1 {
           32  +  /* Cache configuration parameters. Page size (szPage) and the purgeable
           33  +  ** flag (bPurgeable) are set when the cache is created. nMax may be 
           34  +  ** modified at any time by a call to the pcache1CacheSize() method.
           35  +  ** The global mutex must be held when accessing nMax.
           36  +  */
           37  +  int szPage;                         /* Size of allocated pages in bytes */
           38  +  int bPurgeable;                     /* True if cache is purgeable */
           39  +  int nMin;                           /* Minimum number of pages reserved */
           40  +  int nMax;                           /* Configured "cache_size" value */
           41  +
           42  +  /* Hash table of all pages. The following variables may only be accessed
           43  +  ** when the accessor is holding the global mutex (see pcache1EnterMutex() 
           44  +  ** and pcache1LeaveMutex()).
           45  +  */
           46  +  int nRecyclable;                    /* Number of pages in the LRU list */
           47  +  int nPage;                          /* Total number of pages in apHash */
           48  +  int nHash;                          /* Number of slots in apHash[] */
           49  +  PgHdr1 **apHash;                    /* Hash table for fast lookup by key */
           50  +};
           51  +
           52  +/*
           53  +** Each cache entry is represented by an instance of the following 
           54  +** structure. A buffer of PgHdr1.pCache->szPage bytes is allocated 
           55  +** directly after the structure in memory (see the PGHDR1_TO_PAGE() 
           56  +** macro below).
           57  +*/
           58  +struct PgHdr1 {
           59  +  unsigned int iKey;             /* Key value (page number) */
           60  +  PgHdr1 *pNext;                 /* Next in hash table chain */
           61  +  PCache1 *pCache;               /* Cache that currently owns this page */
           62  +  PgHdr1 *pLruNext;              /* Next in LRU list of unpinned pages */
           63  +  PgHdr1 *pLruPrev;              /* Previous in LRU list of unpinned pages */
           64  +};
           65  +
           66  +/*
           67  +** Free slots in the allocator used to divide up the buffer provided using
           68  +** the SQLITE_CONFIG_PAGECACHE mechanism.
           69  +*/
           70  +struct PgFreeslot {
           71  +  PgFreeslot *pNext;  /* Next free slot */
           72  +};
           73  +
           74  +/*
           75  +** Global data used by this cache.
           76  +*/
           77  +static SQLITE_WSD struct PCacheGlobal {
           78  +  sqlite3_mutex *mutex;               /* static mutex MUTEX_STATIC_LRU */
           79  +
           80  +  int nMaxPage;                       /* Sum of nMaxPage for purgeable caches */
           81  +  int nMinPage;                       /* Sum of nMinPage for purgeable caches */
           82  +  int nCurrentPage;                   /* Number of purgeable pages allocated */
           83  +  PgHdr1 *pLruHead, *pLruTail;        /* LRU list of unpinned pages */
           84  +
           85  +  /* Variables related to SQLITE_CONFIG_PAGECACHE settings. */
           86  +  int szSlot;                         /* Size of each free slot */
           87  +  void *pStart, *pEnd;                /* Bounds of pagecache malloc range */
           88  +  PgFreeslot *pFree;                  /* Free page blocks */
           89  +} pcache1_g = {0};
           90  +
           91  +/*
           92  +** All code in this file should access the global structure above via the
           93  +** alias "pcache1". This ensures that the WSD emulation is used when
           94  +** compiling for systems that do not support real WSD.
           95  +*/
           96  +#define pcache1 (GLOBAL(struct PCacheGlobal, pcache1_g))
           97  +
           98  +/*
           99  +** When a PgHdr1 structure is allocated, the associated PCache1.szPage
          100  +** bytes of data are located directly after it in memory (i.e. the total
          101  +** size of the allocation is sizeof(PgHdr1)+PCache1.szPage byte). The
          102  +** PGHDR1_TO_PAGE() macro takes a pointer to a PgHdr1 structure as
          103  +** an argument and returns a pointer to the associated block of szPage
          104  +** bytes. The PAGE_TO_PGHDR1() macro does the opposite: its argument is
          105  +** a pointer to a block of szPage bytes of data and the return value is
          106  +** a pointer to the associated PgHdr1 structure.
          107  +**
          108  +**   assert( PGHDR1_TO_PAGE(PAGE_TO_PGHDR1(X))==X );
          109  +*/
          110  +#define PGHDR1_TO_PAGE(p) (void *)(&((unsigned char *)p)[sizeof(PgHdr1)])
          111  +#define PAGE_TO_PGHDR1(p) (PgHdr1 *)(&((unsigned char *)p)[-1*sizeof(PgHdr1)])
          112  +
          113  +/*
          114  +** Macros to enter and leave the global LRU mutex.
          115  +*/
          116  +#define pcache1EnterMutex() sqlite3_mutex_enter(pcache1.mutex)
          117  +#define pcache1LeaveMutex() sqlite3_mutex_leave(pcache1.mutex)
          118  +
          119  +/******************************************************************************/
          120  +/******** Page Allocation/SQLITE_CONFIG_PCACHE Related Functions **************/
          121  +
          122  +/*
          123  +** This function is called during initialization if a static buffer is 
          124  +** supplied to use for the page-cache by passing the SQLITE_CONFIG_PAGECACHE
          125  +** verb to sqlite3_config(). Parameter pBuf points to an allocation large
          126  +** enough to contain 'n' buffers of 'sz' bytes each.
          127  +*/
          128  +void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){
          129  +  PgFreeslot *p;
          130  +  sz &= ~7;
          131  +  pcache1.szSlot = sz;
          132  +  pcache1.pStart = pBuf;
          133  +  pcache1.pFree = 0;
          134  +  while( n-- ){
          135  +    p = (PgFreeslot*)pBuf;
          136  +    p->pNext = pcache1.pFree;
          137  +    pcache1.pFree = p;
          138  +    pBuf = (void*)&((char*)pBuf)[sz];
          139  +  }
          140  +  pcache1.pEnd = pBuf;
          141  +}
          142  +
          143  +/*
          144  +** Malloc function used within this file to allocate space from the buffer
          145  +** configured using sqlite3_config(SQLITE_CONFIG_PAGECACHE) option. If no 
          146  +** such buffer exists or there is no space left in it, this function falls 
          147  +** back to sqlite3Malloc().
          148  +*/
          149  +static void *pcache1Alloc(int nByte){
          150  +  void *p;
          151  +  assert( sqlite3_mutex_held(pcache1.mutex) );
          152  +  if( nByte<=pcache1.szSlot && pcache1.pFree ){
          153  +    p = (PgHdr1 *)pcache1.pFree;
          154  +    pcache1.pFree = pcache1.pFree->pNext;
          155  +    sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, nByte);
          156  +    sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, 1);
          157  +  }else{
          158  +
          159  +    /* Allocate a new buffer using sqlite3Malloc. Before doing so, exit the
          160  +    ** global pcache mutex and unlock the pager-cache object pCache. This is 
          161  +    ** so that if the attempt to allocate a new buffer causes the the 
          162  +    ** configured soft-heap-limit to be breached, it will be possible to
          163  +    ** reclaim memory from this pager-cache.
          164  +    */
          165  +    pcache1LeaveMutex();
          166  +    p = sqlite3Malloc(nByte);
          167  +    pcache1EnterMutex();
          168  +    if( p ){
          169  +      int sz = sqlite3MallocSize(p);
          170  +      sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz);
          171  +    }
          172  +  }
          173  +  return p;
          174  +}
          175  +
          176  +/*
          177  +** Free an allocated buffer obtained from pcache1Alloc().
          178  +*/
          179  +static void pcache1Free(void *p){
          180  +  assert( sqlite3_mutex_held(pcache1.mutex) );
          181  +  if( p==0 ) return;
          182  +  if( p>=pcache1.pStart && p<pcache1.pEnd ){
          183  +    PgFreeslot *pSlot;
          184  +    sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, -1);
          185  +    pSlot = (PgFreeslot*)p;
          186  +    pSlot->pNext = pcache1.pFree;
          187  +    pcache1.pFree = pSlot;
          188  +  }else{
          189  +    int iSize = sqlite3MallocSize(p);
          190  +    sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, -iSize);
          191  +    sqlite3_free(p);
          192  +  }
          193  +}
          194  +
          195  +/*
          196  +** Allocate a new page object initially associated with cache pCache.
          197  +*/
          198  +static PgHdr1 *pcache1AllocPage(PCache1 *pCache){
          199  +  int nByte = sizeof(PgHdr1) + pCache->szPage;
          200  +  PgHdr1 *p = (PgHdr1 *)pcache1Alloc(nByte);
          201  +  if( p ){
          202  +    memset(p, 0, nByte);
          203  +    if( pCache->bPurgeable ){
          204  +      pcache1.nCurrentPage++;
          205  +    }
          206  +  }
          207  +  return p;
          208  +}
          209  +
          210  +/*
          211  +** Free a page object allocated by pcache1AllocPage().
          212  +*/
          213  +static void pcache1FreePage(PgHdr1 *p){
          214  +  if( p ){
          215  +    if( p->pCache->bPurgeable ){
          216  +      pcache1.nCurrentPage--;
          217  +    }
          218  +    pcache1Free(p);
          219  +  }
          220  +}
          221  +
          222  +/*
          223  +** Malloc function used by SQLite to obtain space from the buffer configured
          224  +** using sqlite3_config(SQLITE_CONFIG_PAGECACHE) option. If no such buffer
          225  +** exists, this function falls back to sqlite3Malloc().
          226  +*/
          227  +void *sqlite3PageMalloc(int sz){
          228  +  void *p;
          229  +  pcache1EnterMutex();
          230  +  p = pcache1Alloc(sz);
          231  +  pcache1LeaveMutex();
          232  +  return p;
          233  +}
          234  +
          235  +/*
          236  +** Free an allocated buffer obtained from sqlite3PageMalloc().
          237  +*/
          238  +void sqlite3PageFree(void *p){
          239  +  pcache1EnterMutex();
          240  +  pcache1Free(p);
          241  +  pcache1LeaveMutex();
          242  +}
          243  +
          244  +/******************************************************************************/
          245  +/******** General Implementation Functions ************************************/
          246  +
          247  +/*
          248  +** This function is used to resize the hash table used by the cache passed
          249  +** as the first argument.
          250  +**
          251  +** The global mutex must be held when this function is called.
          252  +*/
          253  +static int pcache1ResizeHash(PCache1 *p){
          254  +  PgHdr1 **apNew;
          255  +  int nNew;
          256  +  unsigned int i;
          257  +
          258  +  assert( sqlite3_mutex_held(pcache1.mutex) );
          259  +
          260  +  nNew = p->nHash*2;
          261  +  if( nNew<256 ){
          262  +    nNew = 256;
          263  +  }
          264  +
          265  +  pcache1LeaveMutex();
          266  +  apNew = (PgHdr1 **)sqlite3_malloc(sizeof(PgHdr1 *)*nNew);
          267  +  pcache1EnterMutex();
          268  +  if( apNew ){
          269  +    memset(apNew, 0, sizeof(PgHdr1 *)*nNew);
          270  +    for(i=0; i<p->nHash; i++){
          271  +      PgHdr1 *pPage;
          272  +      PgHdr1 *pNext = p->apHash[i];
          273  +      while( (pPage = pNext) ){
          274  +        unsigned int h = pPage->iKey % nNew;
          275  +        pNext = pPage->pNext;
          276  +        pPage->pNext = apNew[h];
          277  +        apNew[h] = pPage;
          278  +      }
          279  +    }
          280  +    sqlite3_free(p->apHash);
          281  +    p->apHash = apNew;
          282  +    p->nHash = nNew;
          283  +  }
          284  +
          285  +  return (p->apHash ? SQLITE_OK : SQLITE_NOMEM);
          286  +}
          287  +
          288  +/*
          289  +** This function is used internally to remove the page pPage from the 
          290  +** global LRU list, if is part of it. If pPage is not part of the global
          291  +** LRU list, then this function is a no-op.
          292  +**
          293  +** The global mutex must be held when this function is called.
          294  +*/
          295  +static void pcache1PinPage(PgHdr1 *pPage){
          296  +  assert( sqlite3_mutex_held(pcache1.mutex) );
          297  +  if( pPage && (pPage->pLruNext || pPage==pcache1.pLruTail) ){
          298  +    if( pPage->pLruPrev ){
          299  +      pPage->pLruPrev->pLruNext = pPage->pLruNext;
          300  +    }
          301  +    if( pPage->pLruNext ){
          302  +      pPage->pLruNext->pLruPrev = pPage->pLruPrev;
          303  +    }
          304  +    if( pcache1.pLruHead==pPage ){
          305  +      pcache1.pLruHead = pPage->pLruNext;
          306  +    }
          307  +    if( pcache1.pLruTail==pPage ){
          308  +      pcache1.pLruTail = pPage->pLruPrev;
          309  +    }
          310  +    pPage->pLruNext = 0;
          311  +    pPage->pLruPrev = 0;
          312  +    pPage->pCache->nRecyclable--;
          313  +  }
          314  +}
          315  +
          316  +
          317  +/*
          318  +** Remove the page supplied as an argument from the hash table 
          319  +** (PCache1.apHash structure) that it is currently stored in.
          320  +**
          321  +** The global mutex must be held when this function is called.
          322  +*/
          323  +static void pcache1RemoveFromHash(PgHdr1 *pPage){
          324  +  unsigned int h;
          325  +  PCache1 *pCache = pPage->pCache;
          326  +  PgHdr1 **pp;
          327  +
          328  +  h = pPage->iKey % pCache->nHash;
          329  +  for(pp=&pCache->apHash[h]; (*pp)!=pPage; pp=&(*pp)->pNext);
          330  +  *pp = (*pp)->pNext;
          331  +
          332  +  pCache->nPage--;
          333  +}
          334  +
          335  +/*
          336  +** If there are currently more than pcache.nMaxPage pages allocated, try
          337  +** to recycle pages to reduce the number allocated to pcache.nMaxPage.
          338  +*/
          339  +static void pcache1EnforceMaxPage(void){
          340  +  assert( sqlite3_mutex_held(pcache1.mutex) );
          341  +  while( pcache1.nCurrentPage>pcache1.nMaxPage && pcache1.pLruTail ){
          342  +    PgHdr1 *p = pcache1.pLruTail;
          343  +    pcache1PinPage(p);
          344  +    pcache1RemoveFromHash(p);
          345  +    pcache1FreePage(p);
          346  +  }
          347  +}
          348  +
          349  +/*
          350  +** Discard all pages from cache pCache with a page number (key value) 
          351  +** greater than or equal to iLimit. Any pinned pages that meet this 
          352  +** criteria are unpinned before they are discarded.
          353  +**
          354  +** The global mutex must be held when this function is called.
          355  +*/
          356  +static void pcache1TruncateUnsafe(
          357  +  PCache1 *pCache, 
          358  +  unsigned int iLimit 
          359  +){
          360  +  unsigned int h;
          361  +  assert( sqlite3_mutex_held(pcache1.mutex) );
          362  +  for(h=0; h<pCache->nHash; h++){
          363  +    PgHdr1 **pp = &pCache->apHash[h]; 
          364  +    PgHdr1 *pPage;
          365  +    while( (pPage = *pp) ){
          366  +      if( pPage->iKey>=iLimit ){
          367  +        pcache1PinPage(pPage);
          368  +        *pp = pPage->pNext;
          369  +        pcache1FreePage(pPage);
          370  +      }else{
          371  +        pp = &pPage->pNext;
          372  +      }
          373  +    }
          374  +  }
          375  +}
          376  +
          377  +/******************************************************************************/
          378  +/******** sqlite3_pcache Methods **********************************************/
          379  +
          380  +/*
          381  +** Implementation of the sqlite3_pcache.xInit method.
          382  +*/
          383  +static int pcache1Init(void *pUnused){
          384  +  memset(&pcache1, 0, sizeof(pcache1));
          385  +  if( sqlite3GlobalConfig.bCoreMutex ){
          386  +    pcache1.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU);
          387  +  }
          388  +  return SQLITE_OK;
          389  +}
          390  +
          391  +/*
          392  +** Implementation of the sqlite3_pcache.xShutdown method.
          393  +*/
          394  +static void pcache1Shutdown(void *pUnused){
          395  +  /* no-op */
          396  +}
          397  +
          398  +/*
          399  +** Implementation of the sqlite3_pcache.xCreate method.
          400  +**
          401  +** Allocate a new cache.
          402  +*/
          403  +static sqlite3_pcache *pcache1Create(int szPage, int bPurgeable){
          404  +  PCache1 *pCache;
          405  +
          406  +  pCache = (PCache1 *)sqlite3_malloc(sizeof(PCache1));
          407  +  if( pCache ){
          408  +    memset(pCache, 0, sizeof(PCache1));
          409  +    pCache->szPage = szPage;
          410  +    pCache->bPurgeable = (bPurgeable ? 1 : 0);
          411  +    if( bPurgeable ){
          412  +      pCache->nMin = 10;
          413  +      pcache1EnterMutex();
          414  +      pcache1.nMinPage += pCache->nMin;
          415  +      pcache1LeaveMutex();
          416  +    }
          417  +  }
          418  +  return (sqlite3_pcache *)pCache;
          419  +}
          420  +
          421  +/*
          422  +** Implementation of the sqlite3_pcache.xCachesize method. 
          423  +**
          424  +** Configure the cache_size limit for a cache.
          425  +*/
          426  +static void pcache1Cachesize(sqlite3_pcache *p, int nMax){
          427  +  PCache1 *pCache = (PCache1 *)p;
          428  +  if( pCache->bPurgeable ){
          429  +    pcache1EnterMutex();
          430  +    pcache1.nMaxPage += (nMax - pCache->nMax);
          431  +    pCache->nMax = nMax;
          432  +    pcache1EnforceMaxPage();
          433  +    pcache1LeaveMutex();
          434  +  }
          435  +}
          436  +
          437  +/*
          438  +** Implementation of the sqlite3_pcache.xPagecount method. 
          439  +*/
          440  +static int pcache1Pagecount(sqlite3_pcache *p){
          441  +  int n;
          442  +  pcache1EnterMutex();
          443  +  n = ((PCache1 *)p)->nPage;
          444  +  pcache1LeaveMutex();
          445  +  return n;
          446  +}
          447  +
          448  +/*
          449  +** Implementation of the sqlite3_pcache.xFetch method. 
          450  +**
          451  +** Fetch a page by key value.
          452  +**
          453  +** Whether or not a new page may be allocated by this function depends on
          454  +** the value of the createFlag argument.
          455  +**
          456  +** There are three different approaches to obtaining space for a page,
          457  +** depending on the value of parameter createFlag (which may be 0, 1 or 2).
          458  +**
          459  +**   1. Regardless of the value of createFlag, the cache is searched for a 
          460  +**      copy of the requested page. If one is found, it is returned.
          461  +**
          462  +**   2. If createFlag==0 and the page is not already in the cache, NULL is
          463  +**      returned.
          464  +**
          465  +**   3. If createFlag is 1, the cache is marked as purgeable and the page is 
          466  +**      not already in the cache, and if either of the following are true, 
          467  +**      return NULL:
          468  +**
          469  +**       (a) the number of pages pinned by the cache is greater than
          470  +**           PCache1.nMax, or
          471  +**       (b) the number of pages pinned by the cache is greater than
          472  +**           the sum of nMax for all purgeable caches, less the sum of 
          473  +**           nMin for all other purgeable caches. 
          474  +**
          475  +**   4. If none of the first three conditions apply and the cache is marked
          476  +**      as purgeable, and if one of the following is true:
          477  +**
          478  +**       (a) The number of pages allocated for the cache is already 
          479  +**           PCache1.nMax, or
          480  +**
          481  +**       (b) The number of pages allocated for all purgeable caches is
          482  +**           already equal to or greater than the sum of nMax for all
          483  +**           purgeable caches,
          484  +**
          485  +**      then attempt to recycle a page from the LRU list. If it is the right
          486  +**      size, return the recycled buffer. Otherwise, free the buffer and
          487  +**      proceed to step 5. 
          488  +**
          489  +**   5. Otherwise, allocate and return a new page buffer.
          490  +*/
          491  +static void *pcache1Fetch(sqlite3_pcache *p, unsigned int iKey, int createFlag){
          492  +  int nPinned;
          493  +  PCache1 *pCache = (PCache1 *)p;
          494  +  PgHdr1 *pPage = 0;
          495  +
          496  +  pcache1EnterMutex();
          497  +  if( createFlag==1 ) sqlite3BeginBenignMalloc();
          498  +
          499  +  /* Search the hash table for an existing entry. */
          500  +  if( pCache->nHash>0 ){
          501  +    unsigned int h = iKey % pCache->nHash;
          502  +    for(pPage=pCache->apHash[h]; pPage&&pPage->iKey!=iKey; pPage=pPage->pNext);
          503  +  }
          504  +
          505  +  if( pPage || createFlag==0 ){
          506  +    pcache1PinPage(pPage);
          507  +    goto fetch_out;
          508  +  }
          509  +
          510  +  /* Step 3 of header comment. */
          511  +  nPinned = pCache->nPage - pCache->nRecyclable;
          512  +  if( createFlag==1 && pCache->bPurgeable && (
          513  +        nPinned>=(pcache1.nMaxPage+pCache->nMin-pcache1.nMinPage)
          514  +     || nPinned>=(pCache->nMax)
          515  +  )){
          516  +    goto fetch_out;
          517  +  }
          518  +
          519  +  if( pCache->nPage>=pCache->nHash && pcache1ResizeHash(pCache) ){
          520  +    goto fetch_out;
          521  +  }
          522  +
          523  +  /* Step 4. Try to recycle a page buffer if appropriate. */
          524  +  if( pCache->bPurgeable && pcache1.pLruTail && (
          525  +      pCache->nPage>=pCache->nMax-1 || pcache1.nCurrentPage>=pcache1.nMaxPage
          526  +  )){
          527  +    pPage = pcache1.pLruTail;
          528  +    pcache1RemoveFromHash(pPage);
          529  +    pcache1PinPage(pPage);
          530  +    if( pPage->pCache->szPage!=pCache->szPage ){
          531  +      pcache1FreePage(pPage);
          532  +      pPage = 0;
          533  +    }else{
          534  +      pcache1.nCurrentPage -= (pPage->pCache->bPurgeable - pCache->bPurgeable);
          535  +    }
          536  +  }
          537  +
          538  +  /* Step 5. If a usable page buffer has still not been found, 
          539  +  ** attempt to allocate a new one. 
          540  +  */
          541  +  if( !pPage ){
          542  +    pPage = pcache1AllocPage(pCache);
          543  +  }
          544  +
          545  +  if( pPage ){
          546  +    unsigned int h = iKey % pCache->nHash;
          547  +    memset(pPage, 0, pCache->szPage + sizeof(PgHdr1));
          548  +    pCache->nPage++;
          549  +    pPage->iKey = iKey;
          550  +    pPage->pNext = pCache->apHash[h];
          551  +    pPage->pCache = pCache;
          552  +    pCache->apHash[h] = pPage;
          553  +  }
          554  +
          555  +fetch_out:
          556  +  if( createFlag==1 ) sqlite3EndBenignMalloc();
          557  +  pcache1LeaveMutex();
          558  +  return (pPage ? PGHDR1_TO_PAGE(pPage) : 0);
          559  +}
          560  +
          561  +
          562  +/*
          563  +** Implementation of the sqlite3_pcache.xUnpin method.
          564  +**
          565  +** Mark a page as unpinned (eligible for asynchronous recycling).
          566  +*/
          567  +static void pcache1Unpin(sqlite3_pcache *p, void *pPg, int reuseUnlikely){
          568  +  PCache1 *pCache = (PCache1 *)p;
          569  +  PgHdr1 *pPage = PAGE_TO_PGHDR1(pPg);
          570  +
          571  +  pcache1EnterMutex();
          572  +
          573  +  /* It is an error to call this function if the page is already 
          574  +  ** part of the global LRU list.
          575  +  */
          576  +  assert( pPage->pLruPrev==0 && pPage->pLruNext==0 );
          577  +  assert( pcache1.pLruHead!=pPage && pcache1.pLruTail!=pPage );
          578  +
          579  +  if( reuseUnlikely || pcache1.nCurrentPage>pcache1.nMaxPage ){
          580  +    pcache1RemoveFromHash(pPage);
          581  +    pcache1FreePage(pPage);
          582  +  }else{
          583  +    /* Add the page to the global LRU list. Normally, the page is added to
          584  +    ** the head of the list (last page to be recycled). However, if the 
          585  +    ** reuseUnlikely flag passed to this function is true, the page is added
          586  +    ** to the tail of the list (first page to be recycled).
          587  +    */
          588  +    if( pcache1.pLruHead ){
          589  +      pcache1.pLruHead->pLruPrev = pPage;
          590  +      pPage->pLruNext = pcache1.pLruHead;
          591  +      pcache1.pLruHead = pPage;
          592  +    }else{
          593  +      pcache1.pLruTail = pPage;
          594  +      pcache1.pLruHead = pPage;
          595  +    }
          596  +    pCache->nRecyclable++;
          597  +  }
          598  +
          599  +  pcache1LeaveMutex();
          600  +}
          601  +
          602  +/*
          603  +** Implementation of the sqlite3_pcache.xRekey method. 
          604  +*/
          605  +static void pcache1Rekey(
          606  +  sqlite3_pcache *p,
          607  +  void *pPg,
          608  +  unsigned int iOld,
          609  +  unsigned int iNew
          610  +){
          611  +  PCache1 *pCache = (PCache1 *)p;
          612  +  PgHdr1 *pPage = PAGE_TO_PGHDR1(pPg);
          613  +  PgHdr1 **pp;
          614  +  unsigned int h; 
          615  +  assert( pPage->iKey==iOld );
          616  +
          617  +  pcache1EnterMutex();
          618  +
          619  +  h = iOld%pCache->nHash;
          620  +  pp = &pCache->apHash[h];
          621  +  while( (*pp)!=pPage ){
          622  +    pp = &(*pp)->pNext;
          623  +  }
          624  +  *pp = pPage->pNext;
          625  +
          626  +  h = iNew%pCache->nHash;
          627  +  pPage->iKey = iNew;
          628  +  pPage->pNext = pCache->apHash[h];
          629  +  pCache->apHash[h] = pPage;
          630  +
          631  +  pcache1LeaveMutex();
          632  +}
          633  +
          634  +/*
          635  +** Implementation of the sqlite3_pcache.xTruncate method. 
          636  +**
          637  +** Discard all unpinned pages in the cache with a page number equal to
          638  +** or greater than parameter iLimit. Any pinned pages with a page number
          639  +** equal to or greater than iLimit are implicitly unpinned.
          640  +*/
          641  +static void pcache1Truncate(sqlite3_pcache *p, unsigned int iLimit){
          642  +  PCache1 *pCache = (PCache1 *)p;
          643  +  pcache1EnterMutex();
          644  +  pcache1TruncateUnsafe(pCache, iLimit);
          645  +  pcache1LeaveMutex();
          646  +}
          647  +
          648  +/*
          649  +** Implementation of the sqlite3_pcache.xDestroy method. 
          650  +**
          651  +** Destroy a cache allocated using pcache1Create().
          652  +*/
          653  +static void pcache1Destroy(sqlite3_pcache *p){
          654  +  PCache1 *pCache = (PCache1 *)p;
          655  +  pcache1EnterMutex();
          656  +  pcache1TruncateUnsafe(pCache, 0);
          657  +  pcache1.nMaxPage -= pCache->nMax;
          658  +  pcache1.nMinPage -= pCache->nMin;
          659  +  pcache1EnforceMaxPage();
          660  +  pcache1LeaveMutex();
          661  +  sqlite3_free(pCache->apHash);
          662  +  sqlite3_free(pCache);
          663  +}
          664  +
          665  +/*
          666  +** This function is called during initialization (sqlite3_initialize()) to
          667  +** install the default pluggable cache module, assuming the user has not
          668  +** already provided an alternative.
          669  +*/
          670  +void sqlite3PCacheSetDefault(void){
          671  +  static sqlite3_pcache_methods defaultMethods = {
          672  +    0,                       /* pArg */
          673  +    pcache1Init,             /* xInit */
          674  +    pcache1Shutdown,         /* xShutdown */
          675  +    pcache1Create,           /* xCreate */
          676  +    pcache1Cachesize,        /* xCachesize */
          677  +    pcache1Pagecount,        /* xPagecount */
          678  +    pcache1Fetch,            /* xFetch */
          679  +    pcache1Unpin,            /* xUnpin */
          680  +    pcache1Rekey,            /* xRekey */
          681  +    pcache1Truncate,         /* xTruncate */
          682  +    pcache1Destroy           /* xDestroy */
          683  +  };
          684  +  sqlite3_config(SQLITE_CONFIG_PCACHE, &defaultMethods);
          685  +}
          686  +
          687  +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
          688  +/*
          689  +** This function is called to free superfluous dynamically allocated memory
          690  +** held by the pager system. Memory in use by any SQLite pager allocated
          691  +** by the current thread may be sqlite3_free()ed.
          692  +**
          693  +** nReq is the number of bytes of memory required. Once this much has
          694  +** been released, the function returns. The return value is the total number 
          695  +** of bytes of memory released.
          696  +*/
          697  +int sqlite3PcacheReleaseMemory(int nReq){
          698  +  int nFree = 0;
          699  +  if( pcache1.pStart==0 ){
          700  +    PgHdr1 *p;
          701  +    pcache1EnterMutex();
          702  +    while( (nReq<0 || nFree<nReq) && (p=pcache1.pLruTail) ){
          703  +      nFree += sqlite3MallocSize(p);
          704  +      pcache1PinPage(p);
          705  +      pcache1RemoveFromHash(p);
          706  +      pcache1FreePage(p);
          707  +    }
          708  +    pcache1LeaveMutex();
          709  +  }
          710  +  return nFree;
          711  +}
          712  +#endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */
          713  +
          714  +#ifdef SQLITE_TEST
          715  +/*
          716  +** This function is used by test procedures to inspect the internal state
          717  +** of the global cache.
          718  +*/
          719  +void sqlite3PcacheStats(
          720  +  int *pnCurrent,      /* OUT: Total number of pages cached */
          721  +  int *pnMax,          /* OUT: Global maximum cache size */
          722  +  int *pnMin,          /* OUT: Sum of PCache1.nMin for purgeable caches */
          723  +  int *pnRecyclable    /* OUT: Total number of pages available for recycling */
          724  +){
          725  +  PgHdr1 *p;
          726  +  int nRecyclable = 0;
          727  +  for(p=pcache1.pLruHead; p; p=p->pLruNext){
          728  +    nRecyclable++;
          729  +  }
          730  +  *pnCurrent = pcache1.nCurrentPage;
          731  +  *pnMax = pcache1.nMaxPage;
          732  +  *pnMin = pcache1.nMinPage;
          733  +  *pnRecyclable = nRecyclable;
          734  +}
          735  +#endif

Changes to src/sqlite.h.in.

    26     26   ** on how SQLite interfaces are suppose to operate.
    27     27   **
    28     28   ** The name of this file under configuration management is "sqlite.h.in".
    29     29   ** The makefile makes some minor changes to this file (such as inserting
    30     30   ** the version number) and changes its name to "sqlite3.h" as
    31     31   ** part of the build process.
    32     32   **
    33         -** @(#) $Id: sqlite.h.in,v 1.412 2008/11/10 23:54:06 drh Exp $
           33  +** @(#) $Id: sqlite.h.in,v 1.413 2008/11/13 14:28:29 danielk1977 Exp $
    34     34   */
    35     35   #ifndef _SQLITE3_H_
    36     36   #define _SQLITE3_H_
    37     37   #include <stdarg.h>     /* Needed for the definition of va_list */
    38     38   
    39     39   /*
    40     40   ** Make sure we can call this stuff from C++.
................................................................................
  1330   1330   #define SQLITE_CONFIG_PAGECACHE     7  /* void*, int sz, int N */
  1331   1331   #define SQLITE_CONFIG_HEAP          8  /* void*, int nByte, int min */
  1332   1332   #define SQLITE_CONFIG_MEMSTATUS     9  /* boolean */
  1333   1333   #define SQLITE_CONFIG_MUTEX        10  /* sqlite3_mutex_methods* */
  1334   1334   #define SQLITE_CONFIG_GETMUTEX     11  /* sqlite3_mutex_methods* */
  1335   1335   /* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */ 
  1336   1336   #define SQLITE_CONFIG_LOOKASIDE    13  /* int int */
         1337  +#define SQLITE_CONFIG_PCACHE       14  /* sqlite3_pcache_methods* */
         1338  +#define SQLITE_CONFIG_GETPCACHE    15  /* sqlite3_pcache_methods* */
  1337   1339   
  1338   1340   /*
  1339   1341   ** CAPI3REF: Configuration Options {H10170} <S20000>
  1340   1342   ** EXPERIMENTAL
  1341   1343   **
  1342   1344   ** These constants are the available integer configuration options that
  1343   1345   ** can be passed as the second argument to the [sqlite3_db_config()] interface.
................................................................................
  6550   6552   ** A non-zero value in this counter may indicate an opportunity to
  6551   6553   ** improvement performance through careful use of indices.</dd>
  6552   6554   **
  6553   6555   ** </dl>
  6554   6556   */
  6555   6557   #define SQLITE_STMTSTATUS_FULLSCAN_STEP     1
  6556   6558   #define SQLITE_STMTSTATUS_SORT              2
         6559  +
         6560  +/*
         6561  +** The sqlite3_pcache type is opaque.  It is implemented by
         6562  +** the pluggable module.  The SQLite core has no knowledge of
         6563  +** its size or internal structure and never deals with the
         6564  +** sqlite3_pcache object except by holding and passing pointers
         6565  +** to the object.
         6566  +*/
         6567  +typedef struct sqlite3_pcache sqlite3_pcache;
         6568  +
         6569  +/*
         6570  +** CAPI3REF: Custom Page Cache API.
         6571  +** EXPERIMENTAL
         6572  +**
         6573  +** The sqlite3_config(SQLITE_CONFIG_SET_PCACHE, ...) interface can
         6574  +** register an alternative page cache implementation by passing in an 
         6575  +** instance of the sqlite3_pcache_methods structure. The majority of the 
         6576  +** heap memory used by sqlite is used by the page cache to cache data read 
         6577  +** from, or ready to be written to, the database file. By implementing a 
         6578  +** custom page cache using this API, an application can control more 
         6579  +** precisely the amount of memory consumed by sqlite, the way in which 
         6580  +** said memory is allocated and released, and the policies used to 
         6581  +** determine exactly which parts of a database file are cached and for 
         6582  +** how long.
         6583  +**
         6584  +** The contents of the structure are copied to an internal buffer by sqlite
         6585  +** within the call to [sqlite3_config].
         6586  +**
         6587  +** The xInit() method is called once for each call to sqlite3_initialize()
         6588  +** (usually only once during the lifetime of the process). It is passed
         6589  +** a copy of the sqlite3_pcache_methods.pArg value. It can be used to set
         6590  +** up global structures and mutexes required by the custom page cache 
         6591  +** implementation. The xShutdown() method is called from within 
         6592  +** sqlite3_shutdown(), if the application invokes this API. It can be used
         6593  +** to clean up any outstanding resources before process shutdown, if required.
         6594  +**
         6595  +** The xCreate() method is used to construct a new cache instance. The
         6596  +** first parameter, szPage, is the size in bytes of the pages that must
         6597  +** be allocated by the cache. szPage will not be a power of two. The
         6598  +** second argument, bPurgeable, is true if the cache being created will
         6599  +** be used to cache database pages read from a file stored on disk, or
         6600  +** false if it is used for an in-memory database. The cache implementation
         6601  +** does not have to do anything special based on the value of bPurgeable,
         6602  +** it is purely advisory. 
         6603  +**
         6604  +** The xCachesize() method may be called at any time by SQLite to set the
         6605  +** suggested maximum cache-size (number of pages stored by) the cache
         6606  +** instance passed as the first argument. This is the value configured using
         6607  +** the SQLite "PRAGMA cache_size" command. As with the bPurgeable parameter,
         6608  +** the implementation is not required to do anything special with this
         6609  +** value, it is advisory only.
         6610  +**
         6611  +** The xPagecount() method should return the number of pages currently
         6612  +** stored in the cache supplied as an argument.
         6613  +** 
         6614  +** The xFetch() method is used to fetch a page and return a pointer to it. 
         6615  +** A 'page', in this context, is a buffer of szPage bytes aligned at an
         6616  +** 8-byte boundary. The page to be fetched is determined by the key. The
         6617  +** mimimum key value is 1. After it has been retrieved using xFetch, the page 
         6618  +** is considered to be pinned.
         6619  +**
         6620  +** If the requested page is already in the page cache, then a pointer to
         6621  +** the cached buffer should be returned with its contents intact. If the
         6622  +** page is not already in the cache, then the expected behaviour of the
         6623  +** cache is determined by the value of the createFlag parameter passed
         6624  +** to xFetch, according to the following table:
         6625  +**
         6626  +** <table border=1 width=85% align=center>
         6627  +**   <tr><th>createFlag<th>Expected Behaviour
         6628  +**   <tr><td>0<td>NULL should be returned. No new cache entry is created.
         6629  +**   <tr><td>1<td>If createFlag is set to 1, this indicates that 
         6630  +**                SQLite is holding pinned pages that can be unpinned
         6631  +**                by writing their contents to the database file (a
         6632  +**                relatively expensive operation). In this situation the
         6633  +**                cache implementation has two choices: it can return NULL,
         6634  +**                in which case SQLite will attempt to unpin one or more 
         6635  +**                pages before re-requesting the same page, or it can
         6636  +**                allocate a new page and return a pointer to it. If a new
         6637  +**                page is allocated, then it must be completely zeroed before 
         6638  +**                it is returned.
         6639  +**   <tr><td>2<td>If createFlag is set to 2, then SQLite is not holding any
         6640  +**                pinned pages associated with the specific cache passed
         6641  +**                as the first argument to xFetch() that can be unpinned. The
         6642  +**                cache implementation should attempt to allocate a new
         6643  +**                cache entry and return a pointer to it. Again, the new
         6644  +**                page should be zeroed before it is returned. If the xFetch()
         6645  +**                method returns NULL when createFlag==2, SQLite assumes that
         6646  +**                a memory allocation failed and returns SQLITE_NOMEM to the
         6647  +**                user.
         6648  +** </table>
         6649  +**
         6650  +** xUnpin() is called by SQLite with a pointer to a currently pinned page
         6651  +** as its second argument. If the third parameter, discard, is non-zero,
         6652  +** then the page should be evicted from the cache. In this case SQLite 
         6653  +** assumes that the next time the page is retrieved from the cache using
         6654  +** the xFetch() method, it will be zeroed. If the discard parameter is
         6655  +** zero, then the page is considered to be unpinned. The cache implementation
         6656  +** may choose to reclaim (free or recycle) unpinned pages at any time.
         6657  +** SQLite assumes that next time the page is retrieved from the cache
         6658  +** it will either be zeroed, or contain the same data that it did when it
         6659  +** was unpinned.
         6660  +**
         6661  +** The cache is not required to perform any reference counting. A single 
         6662  +** call to xUnpin() unpins the page regardless of the number of prior calls 
         6663  +** to xFetch().
         6664  +**
         6665  +** The xRekey() method is used to change the key value associated with the
         6666  +** page passed as the second argument from oldKey to newKey. If the cache
         6667  +** contains an entry associated with oldKey, it should be discarded. Any
         6668  +** cache entry associated with oldKey is guaranteed not to be pinned.
         6669  +**
         6670  +** When SQLite calls the xTruncate() method, the cache must discard all
         6671  +** existing cache entries with page numbers (keys) greater than or equal
         6672  +** to the value of the iLimit parameter passed to xTruncate(). If any
         6673  +** of these pages are pinned, they are implicitly unpinned, meaning that
         6674  +** they can be safely discarded.
         6675  +**
         6676  +** The xDestroy() method is used to delete a cache allocated by xCreate().
         6677  +** All resources associated with the specified cache should be freed. After
         6678  +** calling the xDestroy() method, SQLite considers the sqlite3_pcache*
         6679  +** handle invalid, and will not use it with any other sqlite3_pcache_methods
         6680  +** functions.
         6681  +*/
         6682  +typedef struct sqlite3_pcache_methods sqlite3_pcache_methods;
         6683  +struct sqlite3_pcache_methods {
         6684  +  void *pArg;
         6685  +  int (*xInit)(void*);
         6686  +  void (*xShutdown)(void*);
         6687  +  sqlite3_pcache *(*xCreate)(int szPage, int bPurgeable);
         6688  +  void (*xCachesize)(sqlite3_pcache*, int nCachesize);
         6689  +  int (*xPagecount)(sqlite3_pcache*);
         6690  +  void *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag);
         6691  +  void (*xUnpin)(sqlite3_pcache*, void*, int discard);
         6692  +  void (*xRekey)(sqlite3_pcache*, void*, unsigned oldKey, unsigned newKey);
         6693  +  void (*xTruncate)(sqlite3_pcache*, unsigned iLimit);
         6694  +  void (*xDestroy)(sqlite3_pcache*);
         6695  +};
  6557   6696   
  6558   6697   /*
  6559   6698   ** Undo the hack that converts floating point types to integer for
  6560   6699   ** builds on processors without floating point support.
  6561   6700   */
  6562   6701   #ifdef SQLITE_OMIT_FLOATING_POINT
  6563   6702   # undef double
  6564   6703   #endif
  6565   6704   
  6566   6705   #ifdef __cplusplus
  6567   6706   }  /* End of the 'extern "C"' block */
  6568   6707   #endif
  6569   6708   #endif

Changes to src/sqliteInt.h.

     7      7   **    May you do good and not evil.
     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** Internal interface definitions for SQLite.
    13     13   **
    14         -** @(#) $Id: sqliteInt.h,v 1.790 2008/11/11 18:29:00 drh Exp $
           14  +** @(#) $Id: sqliteInt.h,v 1.791 2008/11/13 14:28:30 danielk1977 Exp $
    15     15   */
    16     16   #ifndef _SQLITEINT_H_
    17     17   #define _SQLITEINT_H_
    18     18   
    19     19   /*
    20     20   ** Include the configuration header output by 'configure' if we're using the
    21     21   ** autoconf-based build
................................................................................
  1954   1954     int bCoreMutex;                   /* True to enable core mutexing */
  1955   1955     int bFullMutex;                   /* True to enable full mutexing */
  1956   1956     int mxStrlen;                     /* Maximum string length */
  1957   1957     int szLookaside;                  /* Default lookaside buffer size */
  1958   1958     int nLookaside;                   /* Default lookaside buffer count */
  1959   1959     sqlite3_mem_methods m;            /* Low-level memory allocation interface */
  1960   1960     sqlite3_mutex_methods mutex;      /* Low-level mutex interface */
         1961  +  sqlite3_pcache_methods pcache;    /* Low-level page-cache interface */
  1961   1962     void *pHeap;                      /* Heap storage space */
  1962   1963     int nHeap;                        /* Size of pHeap[] */
  1963   1964     int mnReq, mxReq;                 /* Min and max heap requests sizes */
  1964   1965     void *pScratch;                   /* Scratch memory */
  1965   1966     int szScratch;                    /* Size of each scratch buffer */
  1966   1967     int nScratch;                     /* Number of scratch buffers */
  1967   1968     void *pPage;                      /* Page cache memory */