Annotation of embedaddon/sqlite3/src/pcache.c, revision 1.1.1.1

1.1       misho       1: /*
                      2: ** 2008 August 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: ** This file implements that page cache.
                     13: */
                     14: #include "sqliteInt.h"
                     15: 
                     16: /*
                     17: ** A complete page cache is an instance of this structure.
                     18: */
                     19: struct PCache {
                     20:   PgHdr *pDirty, *pDirtyTail;         /* List of dirty pages in LRU order */
                     21:   PgHdr *pSynced;                     /* Last synced page in dirty page list */
                     22:   int nRef;                           /* Number of referenced pages */
                     23:   int szCache;                        /* Configured cache size */
                     24:   int szPage;                         /* Size of every page in this cache */
                     25:   int szExtra;                        /* Size of extra space for each page */
                     26:   int bPurgeable;                     /* True if pages are on backing store */
                     27:   int (*xStress)(void*,PgHdr*);       /* Call to try make a page clean */
                     28:   void *pStress;                      /* Argument to xStress */
                     29:   sqlite3_pcache *pCache;             /* Pluggable cache module */
                     30:   PgHdr *pPage1;                      /* Reference to page 1 */
                     31: };
                     32: 
                     33: /*
                     34: ** Some of the assert() macros in this code are too expensive to run
                     35: ** even during normal debugging.  Use them only rarely on long-running
                     36: ** tests.  Enable the expensive asserts using the
                     37: ** -DSQLITE_ENABLE_EXPENSIVE_ASSERT=1 compile-time option.
                     38: */
                     39: #ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
                     40: # define expensive_assert(X)  assert(X)
                     41: #else
                     42: # define expensive_assert(X)
                     43: #endif
                     44: 
                     45: /********************************** Linked List Management ********************/
                     46: 
                     47: #if !defined(NDEBUG) && defined(SQLITE_ENABLE_EXPENSIVE_ASSERT)
                     48: /*
                     49: ** Check that the pCache->pSynced variable is set correctly. If it
                     50: ** is not, either fail an assert or return zero. Otherwise, return
                     51: ** non-zero. This is only used in debugging builds, as follows:
                     52: **
                     53: **   expensive_assert( pcacheCheckSynced(pCache) );
                     54: */
                     55: static int pcacheCheckSynced(PCache *pCache){
                     56:   PgHdr *p;
                     57:   for(p=pCache->pDirtyTail; p!=pCache->pSynced; p=p->pDirtyPrev){
                     58:     assert( p->nRef || (p->flags&PGHDR_NEED_SYNC) );
                     59:   }
                     60:   return (p==0 || p->nRef || (p->flags&PGHDR_NEED_SYNC)==0);
                     61: }
                     62: #endif /* !NDEBUG && SQLITE_ENABLE_EXPENSIVE_ASSERT */
                     63: 
                     64: /*
                     65: ** Remove page pPage from the list of dirty pages.
                     66: */
                     67: static void pcacheRemoveFromDirtyList(PgHdr *pPage){
                     68:   PCache *p = pPage->pCache;
                     69: 
                     70:   assert( pPage->pDirtyNext || pPage==p->pDirtyTail );
                     71:   assert( pPage->pDirtyPrev || pPage==p->pDirty );
                     72: 
                     73:   /* Update the PCache1.pSynced variable if necessary. */
                     74:   if( p->pSynced==pPage ){
                     75:     PgHdr *pSynced = pPage->pDirtyPrev;
                     76:     while( pSynced && (pSynced->flags&PGHDR_NEED_SYNC) ){
                     77:       pSynced = pSynced->pDirtyPrev;
                     78:     }
                     79:     p->pSynced = pSynced;
                     80:   }
                     81: 
                     82:   if( pPage->pDirtyNext ){
                     83:     pPage->pDirtyNext->pDirtyPrev = pPage->pDirtyPrev;
                     84:   }else{
                     85:     assert( pPage==p->pDirtyTail );
                     86:     p->pDirtyTail = pPage->pDirtyPrev;
                     87:   }
                     88:   if( pPage->pDirtyPrev ){
                     89:     pPage->pDirtyPrev->pDirtyNext = pPage->pDirtyNext;
                     90:   }else{
                     91:     assert( pPage==p->pDirty );
                     92:     p->pDirty = pPage->pDirtyNext;
                     93:   }
                     94:   pPage->pDirtyNext = 0;
                     95:   pPage->pDirtyPrev = 0;
                     96: 
                     97:   expensive_assert( pcacheCheckSynced(p) );
                     98: }
                     99: 
                    100: /*
                    101: ** Add page pPage to the head of the dirty list (PCache1.pDirty is set to
                    102: ** pPage).
                    103: */
                    104: static void pcacheAddToDirtyList(PgHdr *pPage){
                    105:   PCache *p = pPage->pCache;
                    106: 
                    107:   assert( pPage->pDirtyNext==0 && pPage->pDirtyPrev==0 && p->pDirty!=pPage );
                    108: 
                    109:   pPage->pDirtyNext = p->pDirty;
                    110:   if( pPage->pDirtyNext ){
                    111:     assert( pPage->pDirtyNext->pDirtyPrev==0 );
                    112:     pPage->pDirtyNext->pDirtyPrev = pPage;
                    113:   }
                    114:   p->pDirty = pPage;
                    115:   if( !p->pDirtyTail ){
                    116:     p->pDirtyTail = pPage;
                    117:   }
                    118:   if( !p->pSynced && 0==(pPage->flags&PGHDR_NEED_SYNC) ){
                    119:     p->pSynced = pPage;
                    120:   }
                    121:   expensive_assert( pcacheCheckSynced(p) );
                    122: }
                    123: 
                    124: /*
                    125: ** Wrapper around the pluggable caches xUnpin method. If the cache is
                    126: ** being used for an in-memory database, this function is a no-op.
                    127: */
                    128: static void pcacheUnpin(PgHdr *p){
                    129:   PCache *pCache = p->pCache;
                    130:   if( pCache->bPurgeable ){
                    131:     if( p->pgno==1 ){
                    132:       pCache->pPage1 = 0;
                    133:     }
                    134:     sqlite3GlobalConfig.pcache2.xUnpin(pCache->pCache, p->pPage, 0);
                    135:   }
                    136: }
                    137: 
                    138: /*************************************************** General Interfaces ******
                    139: **
                    140: ** Initialize and shutdown the page cache subsystem. Neither of these 
                    141: ** functions are threadsafe.
                    142: */
                    143: int sqlite3PcacheInitialize(void){
                    144:   if( sqlite3GlobalConfig.pcache2.xInit==0 ){
                    145:     /* IMPLEMENTATION-OF: R-26801-64137 If the xInit() method is NULL, then the
                    146:     ** built-in default page cache is used instead of the application defined
                    147:     ** page cache. */
                    148:     sqlite3PCacheSetDefault();
                    149:   }
                    150:   return sqlite3GlobalConfig.pcache2.xInit(sqlite3GlobalConfig.pcache2.pArg);
                    151: }
                    152: void sqlite3PcacheShutdown(void){
                    153:   if( sqlite3GlobalConfig.pcache2.xShutdown ){
                    154:     /* IMPLEMENTATION-OF: R-26000-56589 The xShutdown() method may be NULL. */
                    155:     sqlite3GlobalConfig.pcache2.xShutdown(sqlite3GlobalConfig.pcache2.pArg);
                    156:   }
                    157: }
                    158: 
                    159: /*
                    160: ** Return the size in bytes of a PCache object.
                    161: */
                    162: int sqlite3PcacheSize(void){ return sizeof(PCache); }
                    163: 
                    164: /*
                    165: ** Create a new PCache object. Storage space to hold the object
                    166: ** has already been allocated and is passed in as the p pointer. 
                    167: ** The caller discovers how much space needs to be allocated by 
                    168: ** calling sqlite3PcacheSize().
                    169: */
                    170: void sqlite3PcacheOpen(
                    171:   int szPage,                  /* Size of every page */
                    172:   int szExtra,                 /* Extra space associated with each page */
                    173:   int bPurgeable,              /* True if pages are on backing store */
                    174:   int (*xStress)(void*,PgHdr*),/* Call to try to make pages clean */
                    175:   void *pStress,               /* Argument to xStress */
                    176:   PCache *p                    /* Preallocated space for the PCache */
                    177: ){
                    178:   memset(p, 0, sizeof(PCache));
                    179:   p->szPage = szPage;
                    180:   p->szExtra = szExtra;
                    181:   p->bPurgeable = bPurgeable;
                    182:   p->xStress = xStress;
                    183:   p->pStress = pStress;
                    184:   p->szCache = 100;
                    185: }
                    186: 
                    187: /*
                    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.
                    190: */
                    191: void sqlite3PcacheSetPageSize(PCache *pCache, int szPage){
                    192:   assert( pCache->nRef==0 && pCache->pDirty==0 );
                    193:   if( pCache->pCache ){
                    194:     sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache);
                    195:     pCache->pCache = 0;
                    196:     pCache->pPage1 = 0;
                    197:   }
                    198:   pCache->szPage = szPage;
                    199: }
                    200: 
                    201: /*
                    202: ** Compute the number of pages of cache requested.
                    203: */
                    204: static int numberOfCachePages(PCache *p){
                    205:   if( p->szCache>=0 ){
                    206:     return p->szCache;
                    207:   }else{
                    208:     return (int)((-1024*(i64)p->szCache)/(p->szPage+p->szExtra));
                    209:   }
                    210: }
                    211: 
                    212: /*
                    213: ** Try to obtain a page from the cache.
                    214: */
                    215: int sqlite3PcacheFetch(
                    216:   PCache *pCache,       /* Obtain the page from this cache */
                    217:   Pgno pgno,            /* Page number to obtain */
                    218:   int createFlag,       /* If true, create page if it does not exist already */
                    219:   PgHdr **ppPage        /* Write the page here */
                    220: ){
                    221:   sqlite3_pcache_page *pPage = 0;
                    222:   PgHdr *pPgHdr = 0;
                    223:   int eCreate;
                    224: 
                    225:   assert( pCache!=0 );
                    226:   assert( createFlag==1 || createFlag==0 );
                    227:   assert( pgno>0 );
                    228: 
                    229:   /* If the pluggable cache (sqlite3_pcache*) has not been allocated,
                    230:   ** allocate it now.
                    231:   */
                    232:   if( !pCache->pCache && createFlag ){
                    233:     sqlite3_pcache *p;
                    234:     p = sqlite3GlobalConfig.pcache2.xCreate(
                    235:         pCache->szPage, pCache->szExtra + sizeof(PgHdr), pCache->bPurgeable
                    236:     );
                    237:     if( !p ){
                    238:       return SQLITE_NOMEM;
                    239:     }
                    240:     sqlite3GlobalConfig.pcache2.xCachesize(p, numberOfCachePages(pCache));
                    241:     pCache->pCache = p;
                    242:   }
                    243: 
                    244:   eCreate = createFlag * (1 + (!pCache->bPurgeable || !pCache->pDirty));
                    245:   if( pCache->pCache ){
                    246:     pPage = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, eCreate);
                    247:   }
                    248: 
                    249:   if( !pPage && eCreate==1 ){
                    250:     PgHdr *pPg;
                    251: 
                    252:     /* Find a dirty page to write-out and recycle. First try to find a 
                    253:     ** page that does not require a journal-sync (one with PGHDR_NEED_SYNC
                    254:     ** cleared), but if that is not possible settle for any other 
                    255:     ** unreferenced dirty page.
                    256:     */
                    257:     expensive_assert( pcacheCheckSynced(pCache) );
                    258:     for(pPg=pCache->pSynced; 
                    259:         pPg && (pPg->nRef || (pPg->flags&PGHDR_NEED_SYNC)); 
                    260:         pPg=pPg->pDirtyPrev
                    261:     );
                    262:     pCache->pSynced = pPg;
                    263:     if( !pPg ){
                    264:       for(pPg=pCache->pDirtyTail; pPg && pPg->nRef; pPg=pPg->pDirtyPrev);
                    265:     }
                    266:     if( pPg ){
                    267:       int rc;
                    268: #ifdef SQLITE_LOG_CACHE_SPILL
                    269:       sqlite3_log(SQLITE_FULL, 
                    270:                   "spill page %d making room for %d - cache used: %d/%d",
                    271:                   pPg->pgno, pgno,
                    272:                   sqlite3GlobalConfig.pcache.xPagecount(pCache->pCache),
                    273:                   numberOfCachePages(pCache));
                    274: #endif
                    275:       rc = pCache->xStress(pCache->pStress, pPg);
                    276:       if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){
                    277:         return rc;
                    278:       }
                    279:     }
                    280: 
                    281:     pPage = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, 2);
                    282:   }
                    283: 
                    284:   if( pPage ){
                    285:     pPgHdr = (PgHdr *)pPage->pExtra;
                    286: 
                    287:     if( !pPgHdr->pPage ){
                    288:       memset(pPgHdr, 0, sizeof(PgHdr));
                    289:       pPgHdr->pPage = pPage;
                    290:       pPgHdr->pData = pPage->pBuf;
                    291:       pPgHdr->pExtra = (void *)&pPgHdr[1];
                    292:       memset(pPgHdr->pExtra, 0, pCache->szExtra);
                    293:       pPgHdr->pCache = pCache;
                    294:       pPgHdr->pgno = pgno;
                    295:     }
                    296:     assert( pPgHdr->pCache==pCache );
                    297:     assert( pPgHdr->pgno==pgno );
                    298:     assert( pPgHdr->pData==pPage->pBuf );
                    299:     assert( pPgHdr->pExtra==(void *)&pPgHdr[1] );
                    300: 
                    301:     if( 0==pPgHdr->nRef ){
                    302:       pCache->nRef++;
                    303:     }
                    304:     pPgHdr->nRef++;
                    305:     if( pgno==1 ){
                    306:       pCache->pPage1 = pPgHdr;
                    307:     }
                    308:   }
                    309:   *ppPage = pPgHdr;
                    310:   return (pPgHdr==0 && eCreate) ? SQLITE_NOMEM : SQLITE_OK;
                    311: }
                    312: 
                    313: /*
                    314: ** Decrement the reference count on a page. If the page is clean and the
                    315: ** reference count drops to 0, then it is made elible for recycling.
                    316: */
                    317: void sqlite3PcacheRelease(PgHdr *p){
                    318:   assert( p->nRef>0 );
                    319:   p->nRef--;
                    320:   if( p->nRef==0 ){
                    321:     PCache *pCache = p->pCache;
                    322:     pCache->nRef--;
                    323:     if( (p->flags&PGHDR_DIRTY)==0 ){
                    324:       pcacheUnpin(p);
                    325:     }else{
                    326:       /* Move the page to the head of the dirty list. */
                    327:       pcacheRemoveFromDirtyList(p);
                    328:       pcacheAddToDirtyList(p);
                    329:     }
                    330:   }
                    331: }
                    332: 
                    333: /*
                    334: ** Increase the reference count of a supplied page by 1.
                    335: */
                    336: void sqlite3PcacheRef(PgHdr *p){
                    337:   assert(p->nRef>0);
                    338:   p->nRef++;
                    339: }
                    340: 
                    341: /*
                    342: ** Drop a page from the cache. There must be exactly one reference to the
                    343: ** page. This function deletes that reference, so after it returns the
                    344: ** page pointed to by p is invalid.
                    345: */
                    346: void sqlite3PcacheDrop(PgHdr *p){
                    347:   PCache *pCache;
                    348:   assert( p->nRef==1 );
                    349:   if( p->flags&PGHDR_DIRTY ){
                    350:     pcacheRemoveFromDirtyList(p);
                    351:   }
                    352:   pCache = p->pCache;
                    353:   pCache->nRef--;
                    354:   if( p->pgno==1 ){
                    355:     pCache->pPage1 = 0;
                    356:   }
                    357:   sqlite3GlobalConfig.pcache2.xUnpin(pCache->pCache, p->pPage, 1);
                    358: }
                    359: 
                    360: /*
                    361: ** Make sure the page is marked as dirty. If it isn't dirty already,
                    362: ** make it so.
                    363: */
                    364: void sqlite3PcacheMakeDirty(PgHdr *p){
                    365:   p->flags &= ~PGHDR_DONT_WRITE;
                    366:   assert( p->nRef>0 );
                    367:   if( 0==(p->flags & PGHDR_DIRTY) ){
                    368:     p->flags |= PGHDR_DIRTY;
                    369:     pcacheAddToDirtyList( p);
                    370:   }
                    371: }
                    372: 
                    373: /*
                    374: ** Make sure the page is marked as clean. If it isn't clean already,
                    375: ** make it so.
                    376: */
                    377: void sqlite3PcacheMakeClean(PgHdr *p){
                    378:   if( (p->flags & PGHDR_DIRTY) ){
                    379:     pcacheRemoveFromDirtyList(p);
                    380:     p->flags &= ~(PGHDR_DIRTY|PGHDR_NEED_SYNC);
                    381:     if( p->nRef==0 ){
                    382:       pcacheUnpin(p);
                    383:     }
                    384:   }
                    385: }
                    386: 
                    387: /*
                    388: ** Make every page in the cache clean.
                    389: */
                    390: void sqlite3PcacheCleanAll(PCache *pCache){
                    391:   PgHdr *p;
                    392:   while( (p = pCache->pDirty)!=0 ){
                    393:     sqlite3PcacheMakeClean(p);
                    394:   }
                    395: }
                    396: 
                    397: /*
                    398: ** Clear the PGHDR_NEED_SYNC flag from all dirty pages.
                    399: */
                    400: void sqlite3PcacheClearSyncFlags(PCache *pCache){
                    401:   PgHdr *p;
                    402:   for(p=pCache->pDirty; p; p=p->pDirtyNext){
                    403:     p->flags &= ~PGHDR_NEED_SYNC;
                    404:   }
                    405:   pCache->pSynced = pCache->pDirtyTail;
                    406: }
                    407: 
                    408: /*
                    409: ** Change the page number of page p to newPgno. 
                    410: */
                    411: void sqlite3PcacheMove(PgHdr *p, Pgno newPgno){
                    412:   PCache *pCache = p->pCache;
                    413:   assert( p->nRef>0 );
                    414:   assert( newPgno>0 );
                    415:   sqlite3GlobalConfig.pcache2.xRekey(pCache->pCache, p->pPage, p->pgno,newPgno);
                    416:   p->pgno = newPgno;
                    417:   if( (p->flags&PGHDR_DIRTY) && (p->flags&PGHDR_NEED_SYNC) ){
                    418:     pcacheRemoveFromDirtyList(p);
                    419:     pcacheAddToDirtyList(p);
                    420:   }
                    421: }
                    422: 
                    423: /*
                    424: ** Drop every cache entry whose page number is greater than "pgno". The
                    425: ** caller must ensure that there are no outstanding references to any pages
                    426: ** other than page 1 with a page number greater than pgno.
                    427: **
                    428: ** If there is a reference to page 1 and the pgno parameter passed to this
                    429: ** function is 0, then the data area associated with page 1 is zeroed, but
                    430: ** the page object is not dropped.
                    431: */
                    432: void sqlite3PcacheTruncate(PCache *pCache, Pgno pgno){
                    433:   if( pCache->pCache ){
                    434:     PgHdr *p;
                    435:     PgHdr *pNext;
                    436:     for(p=pCache->pDirty; p; p=pNext){
                    437:       pNext = p->pDirtyNext;
                    438:       /* This routine never gets call with a positive pgno except right
                    439:       ** after sqlite3PcacheCleanAll().  So if there are dirty pages,
                    440:       ** it must be that pgno==0.
                    441:       */
                    442:       assert( p->pgno>0 );
                    443:       if( ALWAYS(p->pgno>pgno) ){
                    444:         assert( p->flags&PGHDR_DIRTY );
                    445:         sqlite3PcacheMakeClean(p);
                    446:       }
                    447:     }
                    448:     if( pgno==0 && pCache->pPage1 ){
                    449:       memset(pCache->pPage1->pData, 0, pCache->szPage);
                    450:       pgno = 1;
                    451:     }
                    452:     sqlite3GlobalConfig.pcache2.xTruncate(pCache->pCache, pgno+1);
                    453:   }
                    454: }
                    455: 
                    456: /*
                    457: ** Close a cache.
                    458: */
                    459: void sqlite3PcacheClose(PCache *pCache){
                    460:   if( pCache->pCache ){
                    461:     sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache);
                    462:   }
                    463: }
                    464: 
                    465: /* 
                    466: ** Discard the contents of the cache.
                    467: */
                    468: void sqlite3PcacheClear(PCache *pCache){
                    469:   sqlite3PcacheTruncate(pCache, 0);
                    470: }
                    471: 
                    472: /*
                    473: ** Merge two lists of pages connected by pDirty and in pgno order.
                    474: ** Do not both fixing the pDirtyPrev pointers.
                    475: */
                    476: static PgHdr *pcacheMergeDirtyList(PgHdr *pA, PgHdr *pB){
                    477:   PgHdr result, *pTail;
                    478:   pTail = &result;
                    479:   while( pA && pB ){
                    480:     if( pA->pgno<pB->pgno ){
                    481:       pTail->pDirty = pA;
                    482:       pTail = pA;
                    483:       pA = pA->pDirty;
                    484:     }else{
                    485:       pTail->pDirty = pB;
                    486:       pTail = pB;
                    487:       pB = pB->pDirty;
                    488:     }
                    489:   }
                    490:   if( pA ){
                    491:     pTail->pDirty = pA;
                    492:   }else if( pB ){
                    493:     pTail->pDirty = pB;
                    494:   }else{
                    495:     pTail->pDirty = 0;
                    496:   }
                    497:   return result.pDirty;
                    498: }
                    499: 
                    500: /*
                    501: ** Sort the list of pages in accending order by pgno.  Pages are
                    502: ** connected by pDirty pointers.  The pDirtyPrev pointers are
                    503: ** corrupted by this sort.
                    504: **
                    505: ** Since there cannot be more than 2^31 distinct pages in a database,
                    506: ** there cannot be more than 31 buckets required by the merge sorter.
                    507: ** One extra bucket is added to catch overflow in case something
                    508: ** ever changes to make the previous sentence incorrect.
                    509: */
                    510: #define N_SORT_BUCKET  32
                    511: static PgHdr *pcacheSortDirtyList(PgHdr *pIn){
                    512:   PgHdr *a[N_SORT_BUCKET], *p;
                    513:   int i;
                    514:   memset(a, 0, sizeof(a));
                    515:   while( pIn ){
                    516:     p = pIn;
                    517:     pIn = p->pDirty;
                    518:     p->pDirty = 0;
                    519:     for(i=0; ALWAYS(i<N_SORT_BUCKET-1); i++){
                    520:       if( a[i]==0 ){
                    521:         a[i] = p;
                    522:         break;
                    523:       }else{
                    524:         p = pcacheMergeDirtyList(a[i], p);
                    525:         a[i] = 0;
                    526:       }
                    527:     }
                    528:     if( NEVER(i==N_SORT_BUCKET-1) ){
                    529:       /* To get here, there need to be 2^(N_SORT_BUCKET) elements in
                    530:       ** the input list.  But that is impossible.
                    531:       */
                    532:       a[i] = pcacheMergeDirtyList(a[i], p);
                    533:     }
                    534:   }
                    535:   p = a[0];
                    536:   for(i=1; i<N_SORT_BUCKET; i++){
                    537:     p = pcacheMergeDirtyList(p, a[i]);
                    538:   }
                    539:   return p;
                    540: }
                    541: 
                    542: /*
                    543: ** Return a list of all dirty pages in the cache, sorted by page number.
                    544: */
                    545: PgHdr *sqlite3PcacheDirtyList(PCache *pCache){
                    546:   PgHdr *p;
                    547:   for(p=pCache->pDirty; p; p=p->pDirtyNext){
                    548:     p->pDirty = p->pDirtyNext;
                    549:   }
                    550:   return pcacheSortDirtyList(pCache->pDirty);
                    551: }
                    552: 
                    553: /* 
                    554: ** Return the total number of referenced pages held by the cache.
                    555: */
                    556: int sqlite3PcacheRefCount(PCache *pCache){
                    557:   return pCache->nRef;
                    558: }
                    559: 
                    560: /*
                    561: ** Return the number of references to the page supplied as an argument.
                    562: */
                    563: int sqlite3PcachePageRefcount(PgHdr *p){
                    564:   return p->nRef;
                    565: }
                    566: 
                    567: /* 
                    568: ** Return the total number of pages in the cache.
                    569: */
                    570: int sqlite3PcachePagecount(PCache *pCache){
                    571:   int nPage = 0;
                    572:   if( pCache->pCache ){
                    573:     nPage = sqlite3GlobalConfig.pcache2.xPagecount(pCache->pCache);
                    574:   }
                    575:   return nPage;
                    576: }
                    577: 
                    578: #ifdef SQLITE_TEST
                    579: /*
                    580: ** Get the suggested cache-size value.
                    581: */
                    582: int sqlite3PcacheGetCachesize(PCache *pCache){
                    583:   return numberOfCachePages(pCache);
                    584: }
                    585: #endif
                    586: 
                    587: /*
                    588: ** Set the suggested cache-size value.
                    589: */
                    590: void sqlite3PcacheSetCachesize(PCache *pCache, int mxPage){
                    591:   pCache->szCache = mxPage;
                    592:   if( pCache->pCache ){
                    593:     sqlite3GlobalConfig.pcache2.xCachesize(pCache->pCache,
                    594:                                            numberOfCachePages(pCache));
                    595:   }
                    596: }
                    597: 
                    598: /*
                    599: ** Free up as much memory as possible from the page cache.
                    600: */
                    601: void sqlite3PcacheShrink(PCache *pCache){
                    602:   if( pCache->pCache ){
                    603:     sqlite3GlobalConfig.pcache2.xShrink(pCache->pCache);
                    604:   }
                    605: }
                    606: 
                    607: #if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG)
                    608: /*
                    609: ** For all dirty pages currently in the cache, invoke the specified
                    610: ** callback. This is only used if the SQLITE_CHECK_PAGES macro is
                    611: ** defined.
                    612: */
                    613: void sqlite3PcacheIterateDirty(PCache *pCache, void (*xIter)(PgHdr *)){
                    614:   PgHdr *pDirty;
                    615:   for(pDirty=pCache->pDirty; pDirty; pDirty=pDirty->pDirtyNext){
                    616:     xIter(pDirty);
                    617:   }
                    618: }
                    619: #endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>