pcache.c

Go to the documentation of this file.
00001 /*
00002 ** 2008 August 05
00003 **
00004 ** The author disclaims copyright to this source code.  In place of
00005 ** a legal notice, here is a blessing:
00006 **
00007 **    May you do good and not evil.
00008 **    May you find forgiveness for yourself and forgive others.
00009 **    May you share freely, never taking more than you give.
00010 **
00011 *************************************************************************
00012 ** This file implements that page cache.
00013 **
00014 ** @(#) $Id: pcache.c,v 1.36 2008/11/11 18:43:00 danielk1977 Exp $
00015 */
00016 #include "sqliteInt.h"
00017 
00018 /*
00019 ** A complete page cache is an instance of this structure.
00020 **
00021 ** A cache may only be deleted by its owner and while holding the
00022 ** SQLITE_MUTEX_STATUS_LRU mutex.
00023 */
00024 struct PCache {
00025   /*********************************************************************
00026   ** The first group of elements may be read or written at any time by
00027   ** the cache owner without holding the mutex.  No thread other than the
00028   ** cache owner is permitted to access these elements at any time.
00029   */
00030   PgHdr *pDirty, *pDirtyTail;         /* List of dirty pages in LRU order */
00031   PgHdr *pSynced;                     /* Last synced page in dirty page list */
00032   int nRef;                           /* Number of pinned pages */
00033   int nPinned;                        /* Number of pinned and/or dirty pages */
00034   int nMax;                           /* Configured cache size */
00035   int nMin;                           /* Configured minimum cache size */
00036   /**********************************************************************
00037   ** The next group of elements are fixed when the cache is created and
00038   ** may not be changed afterwards.  These elements can read at any time by
00039   ** the cache owner or by any thread holding the the mutex.  Non-owner
00040   ** threads must hold the mutex when reading these elements to prevent
00041   ** the entire PCache object from being deleted during the read.
00042   */
00043   int szPage;                         /* Size of every page in this cache */
00044   int szExtra;                        /* Size of extra space for each page */
00045   int bPurgeable;                     /* True if pages are on backing store */
00046   int (*xStress)(void*,PgHdr*);       /* Call to try make a page clean */
00047   void *pStress;                      /* Argument to xStress */
00048   /**********************************************************************
00049   ** The final group of elements can only be accessed while holding the
00050   ** mutex.  Both the cache owner and any other thread must hold the mutex
00051   ** to read or write any of these elements.
00052   */
00053   int nPage;                          /* Total number of pages in apHash */
00054   int nHash;                          /* Number of slots in apHash[] */
00055   PgHdr **apHash;                     /* Hash table for fast lookup by pgno */
00056   PgHdr *pClean;                      /* List of clean pages in use */
00057 };
00058 
00059 /*
00060 ** Free slots in the page block allocator
00061 */
00062 typedef struct PgFreeslot PgFreeslot;
00063 struct PgFreeslot {
00064   PgFreeslot *pNext;  /* Next free slot */
00065 };
00066 
00067 /*
00068 ** Global data for the page cache.
00069 */
00070 static SQLITE_WSD struct PCacheGlobal {
00071   int isInit;                         /* True when initialized */
00072   sqlite3_mutex *mutex;               /* static mutex MUTEX_STATIC_LRU */
00073 
00074   int nMaxPage;                       /* Sum of nMaxPage for purgeable caches */
00075   int nMinPage;                       /* Sum of nMinPage for purgeable caches */
00076   int nCurrentPage;                   /* Number of purgeable pages allocated */
00077   PgHdr *pLruHead, *pLruTail;         /* LRU list of unused clean pgs */
00078 
00079   /* Variables related to SQLITE_CONFIG_PAGECACHE settings. */
00080   int szSlot;                         /* Size of each free slot */
00081   void *pStart, *pEnd;                /* Bounds of pagecache malloc range */
00082   PgFreeslot *pFree;                  /* Free page blocks */
00083 } pcache = {0};
00084 
00085 /*
00086 ** All code in this file should access the global pcache structure via the
00087 ** alias "pcache_g". This ensures that the WSD emulation is used when
00088 ** compiling for systems that do not support real WSD.
00089 */
00090 #define pcache_g (GLOBAL(struct PCacheGlobal, pcache))
00091 
00092 /*
00093 ** All global variables used by this module (all of which are grouped 
00094 ** together in global structure "pcache" above) are protected by the static 
00095 ** SQLITE_MUTEX_STATIC_LRU mutex. A pointer to this mutex is stored in
00096 ** variable "pcache.mutex".
00097 **
00098 ** Some elements of the PCache and PgHdr structures are protected by the 
00099 ** SQLITE_MUTEX_STATUS_LRU mutex and other are not.  The protected
00100 ** elements are grouped at the end of the structures and are clearly
00101 ** marked.
00102 **
00103 ** Use the following macros must surround all access (read or write)
00104 ** of protected elements.  The mutex is not recursive and may not be
00105 ** entered more than once.  The pcacheMutexHeld() macro should only be
00106 ** used within an assert() to verify that the mutex is being held.
00107 */
00108 #define pcacheEnterMutex() sqlite3_mutex_enter(pcache_g.mutex)
00109 #define pcacheExitMutex()  sqlite3_mutex_leave(pcache_g.mutex)
00110 #define pcacheMutexHeld()  sqlite3_mutex_held(pcache_g.mutex)
00111 
00112 /*
00113 ** Some of the assert() macros in this code are too expensive to run
00114 ** even during normal debugging.  Use them only rarely on long-running
00115 ** tests.  Enable the expensive asserts using the
00116 ** -DSQLITE_ENABLE_EXPENSIVE_ASSERT=1 compile-time option.
00117 */
00118 #ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
00119 # define expensive_assert(X)  assert(X)
00120 #else
00121 # define expensive_assert(X)
00122 #endif
00123 
00124 /********************************** Linked List Management ********************/
00125 
00126 #if !defined(NDEBUG) && defined(SQLITE_ENABLE_EXPENSIVE_ASSERT)
00127 /*
00128 ** This routine verifies that the number of entries in the hash table
00129 ** is pCache->nPage.  This routine is used within assert() statements
00130 ** only and is therefore disabled during production builds.
00131 */
00132 static int pcacheCheckHashCount(PCache *pCache){
00133   int i;
00134   int nPage = 0;
00135   for(i=0; i<pCache->nHash; i++){
00136     PgHdr *p;
00137     for(p=pCache->apHash[i]; p; p=p->pNextHash){
00138       nPage++;
00139     }
00140   }
00141   assert( nPage==pCache->nPage );
00142   return 1;
00143 }
00144 #endif /* !NDEBUG && SQLITE_ENABLE_EXPENSIVE_ASSERT */
00145 
00146 
00147 #if !defined(NDEBUG) && defined(SQLITE_ENABLE_EXPENSIVE_ASSERT)
00148 /*
00149 ** Based on the current value of PCache.nRef and the contents of the
00150 ** PCache.pDirty list, return the expected value of the PCache.nPinned
00151 ** counter. This is only used in debugging builds, as follows:
00152 **
00153 **   expensive_assert( pCache->nPinned==pcachePinnedCount(pCache) );
00154 */
00155 static int pcachePinnedCount(PCache *pCache){
00156   PgHdr *p;
00157   int nPinned = pCache->nRef;
00158   for(p=pCache->pDirty; p; p=p->pNext){
00159     if( p->nRef==0 ){
00160       nPinned++;
00161     }
00162   }
00163   return nPinned;
00164 }
00165 #endif /* !NDEBUG && SQLITE_ENABLE_EXPENSIVE_ASSERT */
00166 
00167 
00168 #if !defined(NDEBUG) && defined(SQLITE_ENABLE_EXPENSIVE_ASSERT)
00169 /*
00170 ** Check that the pCache->pSynced variable is set correctly. If it
00171 ** is not, either fail an assert or return zero. Otherwise, return
00172 ** non-zero. This is only used in debugging builds, as follows:
00173 **
00174 **   expensive_assert( pcacheCheckSynced(pCache) );
00175 */
00176 static int pcacheCheckSynced(PCache *pCache){
00177   PgHdr *p = pCache->pDirtyTail;
00178   for(p=pCache->pDirtyTail; p!=pCache->pSynced; p=p->pPrev){
00179     assert( p->nRef || (p->flags&PGHDR_NEED_SYNC) );
00180   }
00181   return (p==0 || p->nRef || (p->flags&PGHDR_NEED_SYNC)==0);
00182 }
00183 #endif /* !NDEBUG && SQLITE_ENABLE_EXPENSIVE_ASSERT */
00184 
00185 
00186 
00187 /*
00188 ** Remove a page from its hash table (PCache.apHash[]).
00189 */
00190 static void pcacheRemoveFromHash(PgHdr *pPage){
00191   assert( pcacheMutexHeld() );
00192   if( pPage->pPrevHash ){
00193     pPage->pPrevHash->pNextHash = pPage->pNextHash;
00194   }else{
00195     PCache *pCache = pPage->pCache;
00196     u32 h = pPage->pgno % pCache->nHash;
00197     assert( pCache->apHash[h]==pPage );
00198     pCache->apHash[h] = pPage->pNextHash;
00199   }
00200   if( pPage->pNextHash ){
00201     pPage->pNextHash->pPrevHash = pPage->pPrevHash;
00202   }
00203   pPage->pCache->nPage--;
00204   expensive_assert( pcacheCheckHashCount(pPage->pCache) );
00205 }
00206 
00207 /*
00208 ** Insert a page into the hash table
00209 **
00210 ** The mutex must be held by the caller.
00211 */
00212 static void pcacheAddToHash(PgHdr *pPage){
00213   PCache *pCache = pPage->pCache;
00214   u32 h = pPage->pgno % pCache->nHash;
00215   assert( pcacheMutexHeld() );
00216   pPage->pNextHash = pCache->apHash[h];
00217   pPage->pPrevHash = 0;
00218   if( pCache->apHash[h] ){
00219     pCache->apHash[h]->pPrevHash = pPage;
00220   }
00221   pCache->apHash[h] = pPage;
00222   pCache->nPage++;
00223   expensive_assert( pcacheCheckHashCount(pCache) );
00224 }
00225 
00226 /*
00227 ** Attempt to increase the size the hash table to contain
00228 ** at least nHash buckets.
00229 */
00230 static int pcacheResizeHash(PCache *pCache, int nHash){
00231   PgHdr *p;
00232   PgHdr **pNew;
00233   assert( pcacheMutexHeld() );
00234 #ifdef SQLITE_MALLOC_SOFT_LIMIT
00235   if( nHash*sizeof(PgHdr*)>SQLITE_MALLOC_SOFT_LIMIT ){
00236     nHash = SQLITE_MALLOC_SOFT_LIMIT/sizeof(PgHdr *);
00237   }
00238 #endif
00239   pcacheExitMutex();
00240   pNew = (PgHdr **)sqlite3Malloc(sizeof(PgHdr*)*nHash);
00241   pcacheEnterMutex();
00242   if( !pNew ){
00243     return SQLITE_NOMEM;
00244   }
00245   memset(pNew, 0, sizeof(PgHdr *)*nHash);
00246   sqlite3_free(pCache->apHash);
00247   pCache->apHash = pNew;
00248   pCache->nHash = nHash;
00249   pCache->nPage = 0;
00250  
00251   for(p=pCache->pClean; p; p=p->pNext){
00252     pcacheAddToHash(p);
00253   }
00254   for(p=pCache->pDirty; p; p=p->pNext){
00255     pcacheAddToHash(p);
00256   }
00257   return SQLITE_OK;
00258 }
00259 
00260 /*
00261 ** Remove a page from a linked list that is headed by *ppHead.
00262 ** *ppHead is either PCache.pClean or PCache.pDirty.
00263 */
00264 static void pcacheRemoveFromList(PgHdr **ppHead, PgHdr *pPage){
00265   int isDirtyList = (ppHead==&pPage->pCache->pDirty);
00266   assert( ppHead==&pPage->pCache->pClean || ppHead==&pPage->pCache->pDirty );
00267   assert( pcacheMutexHeld() || ppHead!=&pPage->pCache->pClean );
00268 
00269   if( pPage->pPrev ){
00270     pPage->pPrev->pNext = pPage->pNext;
00271   }else{
00272     assert( *ppHead==pPage );
00273     *ppHead = pPage->pNext;
00274   }
00275   if( pPage->pNext ){
00276     pPage->pNext->pPrev = pPage->pPrev;
00277   }
00278 
00279   if( isDirtyList ){
00280     PCache *pCache = pPage->pCache;
00281     assert( pPage->pNext || pCache->pDirtyTail==pPage );
00282     if( !pPage->pNext ){
00283       pCache->pDirtyTail = pPage->pPrev;
00284     }
00285     if( pCache->pSynced==pPage ){
00286       PgHdr *pSynced = pPage->pPrev;
00287       while( pSynced && (pSynced->flags&PGHDR_NEED_SYNC) ){
00288         pSynced = pSynced->pPrev;
00289       }
00290       pCache->pSynced = pSynced;
00291     }
00292   }
00293 }
00294 
00295 /*
00296 ** Add a page from a linked list that is headed by *ppHead.
00297 ** *ppHead is either PCache.pClean or PCache.pDirty.
00298 */
00299 static void pcacheAddToList(PgHdr **ppHead, PgHdr *pPage){
00300   int isDirtyList = (ppHead==&pPage->pCache->pDirty);
00301   assert( ppHead==&pPage->pCache->pClean || ppHead==&pPage->pCache->pDirty );
00302 
00303   if( (*ppHead) ){
00304     (*ppHead)->pPrev = pPage;
00305   }
00306   pPage->pNext = *ppHead;
00307   pPage->pPrev = 0;
00308   *ppHead = pPage;
00309 
00310   if( isDirtyList ){
00311     PCache *pCache = pPage->pCache;
00312     if( !pCache->pDirtyTail ){
00313       assert( pPage->pNext==0 );
00314       pCache->pDirtyTail = pPage;
00315     }
00316     if( !pCache->pSynced && 0==(pPage->flags&PGHDR_NEED_SYNC) ){
00317       pCache->pSynced = pPage;
00318     }
00319   }
00320 }
00321 
00322 /*
00323 ** Remove a page from the global LRU list
00324 */
00325 static void pcacheRemoveFromLruList(PgHdr *pPage){
00326   assert( sqlite3_mutex_held(pcache_g.mutex) );
00327   assert( (pPage->flags&PGHDR_DIRTY)==0 );
00328   if( pPage->pCache->bPurgeable==0 ) return;
00329   if( pPage->pNextLru ){
00330     assert( pcache_g.pLruTail!=pPage );
00331     pPage->pNextLru->pPrevLru = pPage->pPrevLru;
00332   }else{
00333     assert( pcache_g.pLruTail==pPage );
00334     pcache_g.pLruTail = pPage->pPrevLru;
00335   }
00336   if( pPage->pPrevLru ){
00337     assert( pcache_g.pLruHead!=pPage );
00338     pPage->pPrevLru->pNextLru = pPage->pNextLru;
00339   }else{
00340     assert( pcache_g.pLruHead==pPage );
00341     pcache_g.pLruHead = pPage->pNextLru;
00342   }
00343 }
00344 
00345 /*
00346 ** Add a page to the global LRU list.  The page is normally added
00347 ** to the front of the list so that it will be the last page recycled.
00348 ** However, if the PGHDR_REUSE_UNLIKELY bit is set, the page is added
00349 ** to the end of the LRU list so that it will be the next to be recycled.
00350 */
00351 static void pcacheAddToLruList(PgHdr *pPage){
00352   assert( sqlite3_mutex_held(pcache_g.mutex) );
00353   assert( (pPage->flags&PGHDR_DIRTY)==0 );
00354   if( pPage->pCache->bPurgeable==0 ) return;
00355   if( pcache_g.pLruTail && (pPage->flags & PGHDR_REUSE_UNLIKELY)!=0 ){
00356     /* If reuse is unlikely.  Put the page at the end of the LRU list
00357     ** where it will be recycled sooner rather than later. 
00358     */
00359     assert( pcache_g.pLruHead );
00360     pPage->pNextLru = 0;
00361     pPage->pPrevLru = pcache_g.pLruTail;
00362     pcache_g.pLruTail->pNextLru = pPage;
00363     pcache_g.pLruTail = pPage;
00364     pPage->flags &= ~PGHDR_REUSE_UNLIKELY;
00365   }else{
00366     /* If reuse is possible. the page goes at the beginning of the LRU
00367     ** list so that it will be the last to be recycled.
00368     */
00369     if( pcache_g.pLruHead ){
00370       pcache_g.pLruHead->pPrevLru = pPage;
00371     }
00372     pPage->pNextLru = pcache_g.pLruHead;
00373     pcache_g.pLruHead = pPage;
00374     pPage->pPrevLru = 0;
00375     if( pcache_g.pLruTail==0 ){
00376       pcache_g.pLruTail = pPage;
00377     }
00378   }
00379 }
00380 
00381 /*********************************************** Memory Allocation ***********
00382 **
00383 ** Initialize the page cache memory pool.
00384 **
00385 ** This must be called at start-time when no page cache lines are
00386 ** checked out. This function is not threadsafe.
00387 */
00388 void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){
00389   PgFreeslot *p;
00390   sz &= ~7;
00391   pcache_g.szSlot = sz;
00392   pcache_g.pStart = pBuf;
00393   pcache_g.pFree = 0;
00394   while( n-- ){
00395     p = (PgFreeslot*)pBuf;
00396     p->pNext = pcache_g.pFree;
00397     pcache_g.pFree = p;
00398     pBuf = (void*)&((char*)pBuf)[sz];
00399   }
00400   pcache_g.pEnd = pBuf;
00401 }
00402 
00403 /*
00404 ** Allocate a page cache line.  Look in the page cache memory pool first
00405 ** and use an element from it first if available.  If nothing is available
00406 ** in the page cache memory pool, go to the general purpose memory allocator.
00407 */
00408 static void *pcacheMalloc(int sz, PCache *pCache){
00409   assert( sqlite3_mutex_held(pcache_g.mutex) );
00410   if( sz<=pcache_g.szSlot && pcache_g.pFree ){
00411     PgFreeslot *p = pcache_g.pFree;
00412     pcache_g.pFree = p->pNext;
00413     sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, sz);
00414     sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, 1);
00415     return (void*)p;
00416   }else{
00417     void *p;
00418 
00419     /* Allocate a new buffer using sqlite3Malloc. Before doing so, exit the
00420     ** global pcache mutex and unlock the pager-cache object pCache. This is 
00421     ** so that if the attempt to allocate a new buffer causes the the 
00422     ** configured soft-heap-limit to be breached, it will be possible to
00423     ** reclaim memory from this pager-cache.
00424     */
00425     pcacheExitMutex();
00426     p = sqlite3Malloc(sz);
00427     pcacheEnterMutex();
00428 
00429     if( p ){
00430       sz = sqlite3MallocSize(p);
00431       sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz);
00432     }
00433     return p;
00434   }
00435 }
00436 void *sqlite3PageMalloc(int sz){
00437   void *p;
00438   pcacheEnterMutex();
00439   p = pcacheMalloc(sz, 0);
00440   pcacheExitMutex();
00441   return p;
00442 }
00443 
00444 /*
00445 ** Release a pager memory allocation
00446 */
00447 static void pcacheFree(void *p){
00448   assert( sqlite3_mutex_held(pcache_g.mutex) );
00449   if( p==0 ) return;
00450   if( p>=pcache_g.pStart && p<pcache_g.pEnd ){
00451     PgFreeslot *pSlot;
00452     sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, -1);
00453     pSlot = (PgFreeslot*)p;
00454     pSlot->pNext = pcache_g.pFree;
00455     pcache_g.pFree = pSlot;
00456   }else{
00457     int iSize = sqlite3MallocSize(p);
00458     sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, -iSize);
00459     sqlite3_free(p);
00460   }
00461 }
00462 void sqlite3PageFree(void *p){
00463   pcacheEnterMutex();
00464   pcacheFree(p);
00465   pcacheExitMutex();
00466 }
00467 
00468 /*
00469 ** Allocate a new page.
00470 */
00471 static PgHdr *pcachePageAlloc(PCache *pCache){
00472   PgHdr *p;
00473   int sz = sizeof(*p) + pCache->szPage + pCache->szExtra;
00474   assert( sqlite3_mutex_held(pcache_g.mutex) );
00475   p = pcacheMalloc(sz, pCache);
00476   if( p==0 ) return 0;
00477   memset(p, 0, sizeof(PgHdr));
00478   p->pData = (void*)&p[1];
00479   p->pExtra = (void*)&((char*)p->pData)[pCache->szPage];
00480   if( pCache->bPurgeable ){
00481     pcache_g.nCurrentPage++;
00482   }
00483   return p;
00484 }
00485 
00486 /*
00487 ** Deallocate a page
00488 */
00489 static void pcachePageFree(PgHdr *p){
00490   assert( sqlite3_mutex_held(pcache_g.mutex) );
00491   if( p->pCache->bPurgeable ){
00492     pcache_g.nCurrentPage--;
00493   }
00494   pcacheFree(p);
00495 }
00496 
00497 #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
00498 /*
00499 ** Return the number of bytes that will be returned to the heap when
00500 ** the argument is passed to pcachePageFree().
00501 */
00502 static int pcachePageSize(PgHdr *p){
00503   assert( sqlite3_mutex_held(pcache_g.mutex) );
00504   assert( !pcache_g.pStart );
00505   assert( p && p->pCache );
00506   return sqlite3MallocSize(p);
00507 }
00508 #endif
00509 
00510 /*
00511 ** Attempt to 'recycle' a page from the global LRU list. Only clean,
00512 ** unreferenced pages from purgeable caches are eligible for recycling.
00513 **
00514 ** This function removes page pcache.pLruTail from the global LRU list,
00515 ** and from the hash-table and PCache.pClean list of the owner pcache.
00516 ** There should be no other references to the page.
00517 **
00518 ** A pointer to the recycled page is returned, or NULL if no page is
00519 ** eligible for recycling.
00520 */
00521 static PgHdr *pcacheRecyclePage(void){
00522   PgHdr *p = 0;
00523   assert( sqlite3_mutex_held(pcache_g.mutex) );
00524 
00525   if( (p=pcache_g.pLruTail)!=0 ){
00526     assert( (p->flags&PGHDR_DIRTY)==0 );
00527     pcacheRemoveFromLruList(p);
00528     pcacheRemoveFromHash(p);
00529     pcacheRemoveFromList(&p->pCache->pClean, p);
00530   }
00531 
00532   return p;
00533 }
00534 
00535 /*
00536 ** Obtain space for a page. Try to recycle an old page if the limit on the 
00537 ** number of pages has been reached. If the limit has not been reached or
00538 ** there are no pages eligible for recycling, allocate a new page.
00539 **
00540 ** Return a pointer to the new page, or NULL if an OOM condition occurs.
00541 */
00542 static int pcacheRecycleOrAlloc(PCache *pCache, PgHdr **ppPage){
00543   PgHdr *p = 0;
00544 
00545   int szPage = pCache->szPage;
00546   int szExtra = pCache->szExtra;
00547 
00548   assert( pcache_g.isInit );
00549   assert( sqlite3_mutex_held(pcache_g.mutex) );
00550 
00551   *ppPage = 0;
00552 
00553   /* If we have reached either the global or the local limit for 
00554   ** pinned+dirty pages, and there is at least one dirty page,
00555   ** invoke the xStress callback to cause a page to become clean.
00556   */
00557   expensive_assert( pCache->nPinned==pcachePinnedCount(pCache) );
00558   expensive_assert( pcacheCheckSynced(pCache) );
00559   if( pCache->xStress
00560    && pCache->pDirty
00561    && (pCache->nPinned>=(pcache_g.nMaxPage+pCache->nMin-pcache_g.nMinPage)
00562            || pCache->nPinned>=pCache->nMax)
00563   ){
00564     PgHdr *pPg;
00565     assert(pCache->pDirtyTail);
00566 
00567     for(pPg=pCache->pSynced; 
00568         pPg && (pPg->nRef || (pPg->flags&PGHDR_NEED_SYNC)); 
00569         pPg=pPg->pPrev
00570     );
00571     if( !pPg ){
00572       for(pPg=pCache->pDirtyTail; pPg && pPg->nRef; pPg=pPg->pPrev);
00573     }
00574     if( pPg ){
00575       int rc;
00576       pcacheExitMutex();
00577       rc = pCache->xStress(pCache->pStress, pPg);
00578       pcacheEnterMutex();
00579       if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){
00580         return rc;
00581       }
00582     }
00583   }
00584 
00585   /* If either the local or the global page limit has been reached, 
00586   ** try to recycle a page. 
00587   */
00588   if( pCache->bPurgeable && (pCache->nPage>=pCache->nMax-1 ||
00589                              pcache_g.nCurrentPage>=pcache_g.nMaxPage) ){
00590     p = pcacheRecyclePage();
00591   }
00592 
00593   /* If a page has been recycled but it is the wrong size, free it. */
00594   if( p && (p->pCache->szPage!=szPage || p->pCache->szPage!=szExtra) ){
00595     pcachePageFree(p);
00596     p = 0;
00597   }
00598 
00599   if( !p ){
00600     p = pcachePageAlloc(pCache);
00601   }
00602 
00603   *ppPage = p;
00604   return (p?SQLITE_OK:SQLITE_NOMEM);
00605 }
00606 
00607 /*************************************************** General Interfaces ******
00608 **
00609 ** Initialize and shutdown the page cache subsystem. Neither of these 
00610 ** functions are threadsafe.
00611 */
00612 int sqlite3PcacheInitialize(void){
00613   assert( pcache_g.isInit==0 );
00614   memset(&pcache_g, 0, sizeof(pcache));
00615   if( sqlite3GlobalConfig.bCoreMutex ){
00616     /* No need to check the return value of sqlite3_mutex_alloc(). 
00617     ** Allocating a static mutex cannot fail.
00618     */
00619     pcache_g.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU);
00620   }
00621   pcache_g.isInit = 1;
00622   return SQLITE_OK;
00623 }
00624 void sqlite3PcacheShutdown(void){
00625   memset(&pcache_g, 0, sizeof(pcache));
00626 }
00627 
00628 /*
00629 ** Return the size in bytes of a PCache object.
00630 */
00631 int sqlite3PcacheSize(void){ return sizeof(PCache); }
00632 
00633 /*
00634 ** Create a new PCache object.  Storage space to hold the object
00635 ** has already been allocated and is passed in as the p pointer.
00636 */
00637 void sqlite3PcacheOpen(
00638   int szPage,                  /* Size of every page */
00639   int szExtra,                 /* Extra space associated with each page */
00640   int bPurgeable,              /* True if pages are on backing store */
00641   int (*xStress)(void*,PgHdr*),/* Call to try to make pages clean */
00642   void *pStress,               /* Argument to xStress */
00643   PCache *p                    /* Preallocated space for the PCache */
00644 ){
00645   assert( pcache_g.isInit );
00646   memset(p, 0, sizeof(PCache));
00647   p->szPage = szPage;
00648   p->szExtra = szExtra;
00649   p->bPurgeable = bPurgeable;
00650   p->xStress = xStress;
00651   p->pStress = pStress;
00652   p->nMax = 100;
00653   p->nMin = 10;
00654 
00655   pcacheEnterMutex();
00656   if( bPurgeable ){
00657     pcache_g.nMaxPage += p->nMax;
00658     pcache_g.nMinPage += p->nMin;
00659   }
00660 
00661   pcacheExitMutex();
00662 }
00663 
00664 /*
00665 ** Change the page size for PCache object.  This can only happen
00666 ** when the cache is empty.
00667 */
00668 void sqlite3PcacheSetPageSize(PCache *pCache, int szPage){
00669   assert(pCache->nPage==0);
00670   pCache->szPage = szPage;
00671 }
00672 
00673 /*
00674 ** Try to obtain a page from the cache.
00675 */
00676 int sqlite3PcacheFetch(
00677   PCache *pCache,       /* Obtain the page from this cache */
00678   Pgno pgno,            /* Page number to obtain */
00679   int createFlag,       /* If true, create page if it does not exist already */
00680   PgHdr **ppPage        /* Write the page here */
00681 ){
00682   int rc = SQLITE_OK;
00683   PgHdr *pPage = 0;
00684 
00685   assert( pcache_g.isInit );
00686   assert( pCache!=0 );
00687   assert( pgno>0 );
00688   expensive_assert( pCache->nPinned==pcachePinnedCount(pCache) );
00689 
00690   pcacheEnterMutex();
00691 
00692   /* Search the hash table for the requested page. Exit early if it is found. */
00693   if( pCache->apHash ){
00694     u32 h = pgno % pCache->nHash;
00695     for(pPage=pCache->apHash[h]; pPage; pPage=pPage->pNextHash){
00696       if( pPage->pgno==pgno ){
00697         if( pPage->nRef==0 ){
00698           if( 0==(pPage->flags&PGHDR_DIRTY) ){
00699             pcacheRemoveFromLruList(pPage);
00700             pCache->nPinned++;
00701           }
00702           pCache->nRef++;
00703         }
00704         pPage->nRef++;
00705         break;
00706       }
00707     }
00708   }
00709 
00710   if( !pPage && createFlag ){
00711     if( pCache->nHash<=pCache->nPage ){
00712       rc = pcacheResizeHash(pCache, pCache->nHash<256 ? 256 : pCache->nHash*2);
00713     }
00714     if( rc==SQLITE_OK ){
00715       rc = pcacheRecycleOrAlloc(pCache, &pPage);
00716     }
00717     if( rc==SQLITE_OK ){
00718       pPage->pPager = 0;
00719       pPage->flags = 0;
00720       pPage->pDirty = 0;
00721       pPage->pgno = pgno;
00722       pPage->pCache = pCache;
00723       pPage->nRef = 1;
00724       pCache->nRef++;
00725       pCache->nPinned++;
00726       pcacheAddToList(&pCache->pClean, pPage);
00727       pcacheAddToHash(pPage);
00728     }
00729   }
00730 
00731   pcacheExitMutex();
00732 
00733   *ppPage = pPage;
00734   expensive_assert( pCache->nPinned==pcachePinnedCount(pCache) );
00735   assert( pPage || !createFlag || rc!=SQLITE_OK );
00736   return rc;
00737 }
00738 
00739 /*
00740 ** Dereference a page.  When the reference count reaches zero,
00741 ** move the page to the LRU list if it is clean.
00742 */
00743 void sqlite3PcacheRelease(PgHdr *p){
00744   assert( p->nRef>0 );
00745   p->nRef--;
00746   if( p->nRef==0 ){
00747     PCache *pCache = p->pCache;
00748     pCache->nRef--;
00749     if( (p->flags&PGHDR_DIRTY)==0 ){
00750       pCache->nPinned--;
00751       pcacheEnterMutex();
00752       if( pcache_g.nCurrentPage>pcache_g.nMaxPage ){
00753         pcacheRemoveFromList(&pCache->pClean, p);
00754         pcacheRemoveFromHash(p);
00755         pcachePageFree(p);
00756       }else{
00757         pcacheAddToLruList(p);
00758       }
00759       pcacheExitMutex();
00760     }else{
00761       /* Move the page to the head of the caches dirty list. */
00762       pcacheRemoveFromList(&pCache->pDirty, p);
00763       pcacheAddToList(&pCache->pDirty, p);
00764     }
00765   }
00766 }
00767 
00768 void sqlite3PcacheRef(PgHdr *p){
00769   assert(p->nRef>0);
00770   p->nRef++;
00771 }
00772 
00773 /*
00774 ** Drop a page from the cache. There must be exactly one reference to the
00775 ** page. This function deletes that reference, so after it returns the
00776 ** page pointed to by p is invalid.
00777 */
00778 void sqlite3PcacheDrop(PgHdr *p){
00779   PCache *pCache;
00780   assert( p->nRef==1 );
00781   assert( 0==(p->flags&PGHDR_DIRTY) );
00782   pCache = p->pCache;
00783   pCache->nRef--;
00784   pCache->nPinned--;
00785   pcacheEnterMutex();
00786   pcacheRemoveFromList(&pCache->pClean, p);
00787   pcacheRemoveFromHash(p);
00788   pcachePageFree(p);
00789   pcacheExitMutex();
00790 }
00791 
00792 /*
00793 ** Make sure the page is marked as dirty.  If it isn't dirty already,
00794 ** make it so.
00795 */
00796 void sqlite3PcacheMakeDirty(PgHdr *p){
00797   PCache *pCache;
00798   p->flags &= ~PGHDR_DONT_WRITE;
00799   if( p->flags & PGHDR_DIRTY ) return;
00800   assert( (p->flags & PGHDR_DIRTY)==0 );
00801   assert( p->nRef>0 );
00802   pCache = p->pCache;
00803   pcacheEnterMutex();
00804   pcacheRemoveFromList(&pCache->pClean, p);
00805   pcacheAddToList(&pCache->pDirty, p);
00806   pcacheExitMutex();
00807   p->flags |= PGHDR_DIRTY;
00808 }
00809 
00810 static void pcacheMakeClean(PgHdr *p){
00811   PCache *pCache = p->pCache;
00812   assert( p->flags & PGHDR_DIRTY );
00813   pcacheRemoveFromList(&pCache->pDirty, p);
00814   pcacheAddToList(&pCache->pClean, p);
00815   p->flags &= ~PGHDR_DIRTY;
00816   if( p->nRef==0 ){
00817     pcacheAddToLruList(p);
00818     pCache->nPinned--;
00819   }
00820   expensive_assert( pCache->nPinned==pcachePinnedCount(pCache) );
00821 }
00822 
00823 /*
00824 ** Make sure the page is marked as clean.  If it isn't clean already,
00825 ** make it so.
00826 */
00827 void sqlite3PcacheMakeClean(PgHdr *p){
00828   if( (p->flags & PGHDR_DIRTY) ){
00829     pcacheEnterMutex();
00830     pcacheMakeClean(p);
00831     pcacheExitMutex();
00832   }
00833 }
00834 
00835 /*
00836 ** Make every page in the cache clean.
00837 */
00838 void sqlite3PcacheCleanAll(PCache *pCache){
00839   PgHdr *p;
00840   pcacheEnterMutex();
00841   while( (p = pCache->pDirty)!=0 ){
00842     pcacheRemoveFromList(&pCache->pDirty, p);
00843     p->flags &= ~PGHDR_DIRTY;
00844     pcacheAddToList(&pCache->pClean, p);
00845     if( p->nRef==0 ){
00846       pcacheAddToLruList(p);
00847       pCache->nPinned--;
00848     }
00849   }
00850   sqlite3PcacheAssertFlags(pCache, 0, PGHDR_DIRTY);
00851   expensive_assert( pCache->nPinned==pcachePinnedCount(pCache) );
00852   pcacheExitMutex();
00853 }
00854 
00855 /*
00856 ** Change the page number of page p to newPgno. If newPgno is 0, then the
00857 ** page object is added to the clean-list and the PGHDR_REUSE_UNLIKELY 
00858 ** flag set.
00859 */
00860 void sqlite3PcacheMove(PgHdr *p, Pgno newPgno){
00861   assert( p->nRef>0 );
00862   pcacheEnterMutex();
00863   pcacheRemoveFromHash(p);
00864   p->pgno = newPgno;
00865   if( newPgno==0 ){
00866     if( (p->flags & PGHDR_DIRTY) ){
00867       pcacheMakeClean(p);
00868     }
00869     p->flags = PGHDR_REUSE_UNLIKELY;
00870   }
00871   pcacheAddToHash(p);
00872   pcacheExitMutex();
00873 }
00874 
00875 /*
00876 ** Remove all content from a page cache
00877 */
00878 static void pcacheClear(PCache *pCache){
00879   PgHdr *p, *pNext;
00880   assert( sqlite3_mutex_held(pcache_g.mutex) );
00881   for(p=pCache->pClean; p; p=pNext){
00882     pNext = p->pNext;
00883     pcacheRemoveFromLruList(p);
00884     pcachePageFree(p);
00885   }
00886   for(p=pCache->pDirty; p; p=pNext){
00887     pNext = p->pNext;
00888     pcachePageFree(p);
00889   }
00890   pCache->pClean = 0;
00891   pCache->pDirty = 0;
00892   pCache->pDirtyTail = 0;
00893   pCache->nPage = 0;
00894   pCache->nPinned = 0;
00895   memset(pCache->apHash, 0, pCache->nHash*sizeof(pCache->apHash[0]));
00896 }
00897 
00898 
00899 /*
00900 ** Drop every cache entry whose page number is greater than "pgno".
00901 */
00902 void sqlite3PcacheTruncate(PCache *pCache, Pgno pgno){
00903   PgHdr *p, *pNext;
00904   PgHdr *pDirty = pCache->pDirty;
00905   pcacheEnterMutex();
00906   for(p=pCache->pClean; p||pDirty; p=pNext){
00907     if( !p ){
00908       p = pDirty;
00909       pDirty = 0;
00910     }
00911     pNext = p->pNext;
00912     if( p->pgno>pgno ){
00913       if( p->nRef==0 ){
00914         pcacheRemoveFromHash(p);
00915         if( p->flags&PGHDR_DIRTY ){
00916           pcacheRemoveFromList(&pCache->pDirty, p);
00917           pCache->nPinned--;
00918         }else{
00919           pcacheRemoveFromList(&pCache->pClean, p);
00920           pcacheRemoveFromLruList(p);
00921         }
00922         pcachePageFree(p);
00923       }else{
00924         /* If there are references to the page, it cannot be freed. In this
00925         ** case, zero the page content instead.
00926         */
00927         memset(p->pData, 0, pCache->szPage);
00928       }
00929     }
00930   }
00931   pcacheExitMutex();
00932 }
00933 
00934 /*
00935 ** If there are currently more than pcache.nMaxPage pages allocated, try
00936 ** to recycle pages to reduce the number allocated to pcache.nMaxPage.
00937 */
00938 static void pcacheEnforceMaxPage(void){
00939   PgHdr *p;
00940   assert( sqlite3_mutex_held(pcache_g.mutex) );
00941   while( pcache_g.nCurrentPage>pcache_g.nMaxPage
00942              && (p = pcacheRecyclePage())!=0 ){
00943     pcachePageFree(p);
00944   }
00945 }
00946 
00947 /*
00948 ** Close a cache.
00949 */
00950 void sqlite3PcacheClose(PCache *pCache){
00951   pcacheEnterMutex();
00952 
00953   /* Free all the pages used by this pager and remove them from the LRU list. */
00954   pcacheClear(pCache);
00955   if( pCache->bPurgeable ){
00956     pcache_g.nMaxPage -= pCache->nMax;
00957     pcache_g.nMinPage -= pCache->nMin;
00958     pcacheEnforceMaxPage();
00959   }
00960   sqlite3_free(pCache->apHash);
00961   pcacheExitMutex();
00962 }
00963 
00964 
00965 #ifndef NDEBUG
00966 /* 
00967 ** Assert flags settings on all pages.  Debugging only.
00968 */
00969 void sqlite3PcacheAssertFlags(PCache *pCache, int trueMask, int falseMask){
00970   PgHdr *p;
00971   for(p=pCache->pDirty; p; p=p->pNext){
00972     assert( (p->flags&trueMask)==trueMask );
00973     assert( (p->flags&falseMask)==0 );
00974   }
00975   for(p=pCache->pClean; p; p=p->pNext){
00976     assert( (p->flags&trueMask)==trueMask );
00977     assert( (p->flags&falseMask)==0 );
00978   }
00979 }
00980 #endif
00981 
00982 /* 
00983 ** Discard the contents of the cache.
00984 */
00985 int sqlite3PcacheClear(PCache *pCache){
00986   assert(pCache->nRef==0);
00987   pcacheEnterMutex();
00988   pcacheClear(pCache);
00989   pcacheExitMutex();
00990   return SQLITE_OK;
00991 }
00992 
00993 /*
00994 ** Merge two lists of pages connected by pDirty and in pgno order.
00995 ** Do not both fixing the pPrevDirty pointers.
00996 */
00997 static PgHdr *pcacheMergeDirtyList(PgHdr *pA, PgHdr *pB){
00998   PgHdr result, *pTail;
00999   pTail = &result;
01000   while( pA && pB ){
01001     if( pA->pgno<pB->pgno ){
01002       pTail->pDirty = pA;
01003       pTail = pA;
01004       pA = pA->pDirty;
01005     }else{
01006       pTail->pDirty = pB;
01007       pTail = pB;
01008       pB = pB->pDirty;
01009     }
01010   }
01011   if( pA ){
01012     pTail->pDirty = pA;
01013   }else if( pB ){
01014     pTail->pDirty = pB;
01015   }else{
01016     pTail->pDirty = 0;
01017   }
01018   return result.pDirty;
01019 }
01020 
01021 /*
01022 ** Sort the list of pages in accending order by pgno.  Pages are
01023 ** connected by pDirty pointers.  The pPrevDirty pointers are
01024 ** corrupted by this sort.
01025 */
01026 #define N_SORT_BUCKET_ALLOC 25
01027 #define N_SORT_BUCKET       25
01028 #ifdef SQLITE_TEST
01029   int sqlite3_pager_n_sort_bucket = 0;
01030   #undef N_SORT_BUCKET
01031   #define N_SORT_BUCKET \
01032    (sqlite3_pager_n_sort_bucket?sqlite3_pager_n_sort_bucket:N_SORT_BUCKET_ALLOC)
01033 #endif
01034 static PgHdr *pcacheSortDirtyList(PgHdr *pIn){
01035   PgHdr *a[N_SORT_BUCKET_ALLOC], *p;
01036   int i;
01037   memset(a, 0, sizeof(a));
01038   while( pIn ){
01039     p = pIn;
01040     pIn = p->pDirty;
01041     p->pDirty = 0;
01042     for(i=0; i<N_SORT_BUCKET-1; i++){
01043       if( a[i]==0 ){
01044         a[i] = p;
01045         break;
01046       }else{
01047         p = pcacheMergeDirtyList(a[i], p);
01048         a[i] = 0;
01049       }
01050     }
01051     if( i==N_SORT_BUCKET-1 ){
01052       /* Coverage: To get here, there need to be 2^(N_SORT_BUCKET) 
01053       ** elements in the input list. This is possible, but impractical.
01054       ** Testing this line is the point of global variable
01055       ** sqlite3_pager_n_sort_bucket.
01056       */
01057       a[i] = pcacheMergeDirtyList(a[i], p);
01058     }
01059   }
01060   p = a[0];
01061   for(i=1; i<N_SORT_BUCKET; i++){
01062     p = pcacheMergeDirtyList(p, a[i]);
01063   }
01064   return p;
01065 }
01066 
01067 /*
01068 ** Return a list of all dirty pages in the cache, sorted by page number.
01069 */
01070 PgHdr *sqlite3PcacheDirtyList(PCache *pCache){
01071   PgHdr *p;
01072   for(p=pCache->pDirty; p; p=p->pNext){
01073     p->pDirty = p->pNext;
01074   }
01075   return pcacheSortDirtyList(pCache->pDirty);
01076 }
01077 
01078 /* 
01079 ** Return the total number of outstanding page references.
01080 */
01081 int sqlite3PcacheRefCount(PCache *pCache){
01082   return pCache->nRef;
01083 }
01084 
01085 int sqlite3PcachePageRefcount(PgHdr *p){
01086   return p->nRef;
01087 }
01088 
01089 /* 
01090 ** Return the total number of pages in the cache.
01091 */
01092 int sqlite3PcachePagecount(PCache *pCache){
01093   assert( pCache->nPage>=0 );
01094   return pCache->nPage;
01095 }
01096 
01097 #ifdef SQLITE_CHECK_PAGES
01098 /*
01099 ** This function is used by the pager.c module to iterate through all 
01100 ** pages in the cache. At present, this is only required if the
01101 ** SQLITE_CHECK_PAGES macro (used for debugging) is specified.
01102 */
01103 void sqlite3PcacheIterate(PCache *pCache, void (*xIter)(PgHdr *)){
01104   PgHdr *p;
01105   for(p=pCache->pClean; p; p=p->pNext){
01106     xIter(p);
01107   }
01108   for(p=pCache->pDirty; p; p=p->pNext){
01109     xIter(p);
01110   }
01111 }
01112 #endif
01113 
01114 /* 
01115 ** Set flags on all pages in the page cache 
01116 */
01117 void sqlite3PcacheClearFlags(PCache *pCache, int mask){
01118   PgHdr *p;
01119 
01120   /* Obtain the global mutex before modifying any PgHdr.flags variables 
01121   ** or traversing the LRU list.
01122   */ 
01123   pcacheEnterMutex();
01124 
01125   mask = ~mask;
01126   for(p=pCache->pDirty; p; p=p->pNext){
01127     p->flags &= mask;
01128   }
01129   for(p=pCache->pClean; p; p=p->pNext){
01130     p->flags &= mask;
01131   }
01132 
01133   if( 0==(mask&PGHDR_NEED_SYNC) ){
01134     pCache->pSynced = pCache->pDirtyTail;
01135     assert( !pCache->pSynced || (pCache->pSynced->flags&PGHDR_NEED_SYNC)==0 );
01136   }
01137 
01138   pcacheExitMutex();
01139 }
01140 
01141 /*
01142 ** Set the suggested cache-size value.
01143 */
01144 int sqlite3PcacheGetCachesize(PCache *pCache){
01145   return pCache->nMax;
01146 }
01147 
01148 /*
01149 ** Set the suggested cache-size value.
01150 */
01151 void sqlite3PcacheSetCachesize(PCache *pCache, int mxPage){
01152   if( mxPage<10 ){
01153     mxPage = 10;
01154   }
01155   if( pCache->bPurgeable ){
01156     pcacheEnterMutex();
01157     pcache_g.nMaxPage -= pCache->nMax;
01158     pcache_g.nMaxPage += mxPage;
01159     pcacheEnforceMaxPage();
01160     pcacheExitMutex();
01161   }
01162   pCache->nMax = mxPage;
01163 }
01164 
01165 #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
01166 /*
01167 ** This function is called to free superfluous dynamically allocated memory
01168 ** held by the pager system. Memory in use by any SQLite pager allocated
01169 ** by the current thread may be sqlite3_free()ed.
01170 **
01171 ** nReq is the number of bytes of memory required. Once this much has
01172 ** been released, the function returns. The return value is the total number 
01173 ** of bytes of memory released.
01174 */
01175 int sqlite3PcacheReleaseMemory(int nReq){
01176   int nFree = 0;
01177   if( pcache_g.pStart==0 ){
01178     PgHdr *p;
01179     pcacheEnterMutex();
01180     while( (nReq<0 || nFree<nReq) && (p=pcacheRecyclePage()) ){
01181       nFree += pcachePageSize(p);
01182       pcachePageFree(p);
01183     }
01184     pcacheExitMutex();
01185   }
01186   return nFree;
01187 }
01188 #endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */
01189 
01190 #ifdef SQLITE_TEST
01191 void sqlite3PcacheStats(
01192   int *pnCurrent,
01193   int *pnMax,
01194   int *pnMin,
01195   int *pnRecyclable
01196 ){
01197   PgHdr *p;
01198   int nRecyclable = 0;
01199   for(p=pcache_g.pLruHead; p; p=p->pNextLru){
01200     nRecyclable++;
01201   }
01202 
01203   *pnCurrent = pcache_g.nCurrentPage;
01204   *pnMax = pcache_g.nMaxPage;
01205   *pnMin = pcache_g.nMinPage;
01206   *pnRecyclable = nRecyclable;
01207 }
01208 #endif

ContextLogger2—ContextLogger2 Logger Daemon Internals—Generated on Mon May 2 13:49:55 2011 by Doxygen 1.6.1