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