blob: ffaa5e8f4e4ca39c770366057246465f84beb50f [file] [log] [blame]
danielk19778c0a7912008-08-20 14:49:23 +00001/*
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**
danielk19770d3c5d32008-08-21 04:41:01 +000014** @(#) $Id: pcache.c,v 1.3 2008/08/21 04:41:02 danielk1977 Exp $
danielk19778c0a7912008-08-20 14:49:23 +000015*/
16#include "sqliteInt.h"
17
18/*
19** A complete page cache is an instance of this structure.
20*/
21struct PCache {
22 PCache *pNextAll, *pPrevAll; /* List of all page caches */
23 int szPage; /* Size of every page in this cache */
24 int szExtra; /* Size of extra space for each page */
25 int nHash; /* Number of slots in apHash[] */
26 int nPage; /* Total number of pages in apHash */
27 int nMax; /* Configured cache size */
28 PgHdr **apHash; /* Hash table for fast lookup by pgno */
29 int bPurgeable; /* True if pages are on backing store */
30 void (*xDestroy)(PgHdr*); /* Called when refcnt goes 1->0 */
31 int (*xStress)(void*); /* Call to try to make pages clean */
32 void *pStress; /* Argument to xStress */
33 PgHdr *pClean; /* List of clean pages in use */
34 PgHdr *pDirty; /* List of dirty pages */
35 int nRef; /* Number of outstanding page refs */
36
37 int iInUseMM;
38 int iInUseDB;
39};
40
41/*
42** Free slots in the page block allocator
43*/
44typedef struct PgFreeslot PgFreeslot;
45struct PgFreeslot {
46 PgFreeslot *pNext; /* Next free slot */
47};
48
49/*
50** Global data for the page cache.
51**
52** The maximum number of cached pages stored by the system is determined
53** by the pcache.mxPage and pcache.mxPagePurgeable variables. If
54** mxPage is non-zero, then the system tries to limit the number of
55** cached pages stored to mxPage. In this case mxPagePurgeable is not
56** used.
57**
58** If mxPage is zero, then the system tries to limit the number of
59** pages held by purgable caches to mxPagePurgeable.
60*/
61static struct PCacheGlobal {
62 int isInit; /* True when initialized */
63 sqlite3_mutex *mutex_mem2; /* static mutex MUTEX_STATIC_MEM2 */
64 sqlite3_mutex *mutex_lru; /* static mutex MUTEX_STATIC_LRU */
65 PCache *pAll; /* list of all page caches */
66 int nPage; /* Number of pages */
67 int nPurgeable; /* Number of pages in purgable caches */
drh41d30272008-08-20 21:47:45 +000068 int mxPage; /* Globally configured page maximum */
danielk19778c0a7912008-08-20 14:49:23 +000069 int mxPagePurgeable; /* Purgeable page maximum */
70 PgHdr *pLruHead, *pLruTail; /* Global LRU list of unused pages */
71 int szSlot; /* Size of each free slot */
72 void *pStart, *pEnd; /* Bounds of pagecache malloc range */
73 PgFreeslot *pFree; /* Free page blocks */
74} pcache = {0};
75
76/*
77** All global variables used by this module (most of which are grouped
78** together in global structure "pcache" above) except the list of all
79** pager-caches starting with pcache.pAll, are protected by the static
80** SQLITE_MUTEX_STATIC_LRU mutex. A pointer to this mutex is stored in
81** variable "pcache.mutex_lru".
82**
83** The list of all pager-caches (PCache structures) headed by pcache.pAll
84** is protected by SQLITE_MUTEX_STATIC_MEM2.
85**
86** Access to the contents of the individual PCache structures is not
87** protected. It is the job of the caller to ensure that these structures
88** are accessed in a thread-safe manner. However, this module provides the
89** functions sqlite3PcacheLock() and sqlite3PcacheUnlock() that may be used
90** by the caller to increment/decrement a lock-count on an individual
91** pager-cache object. This module guarantees that the xStress() callback
92** will not be invoked on a pager-cache with a non-zero lock-count except
93** from within a call to sqlite3PcacheFetch() on the same pager. A call
94** to sqlite3PcacheLock() may block if such an xStress() call is currently
95** underway.
96**
97** Before the xStress callback of a pager-cache (PCache) is invoked, the
98** SQLITE_MUTEX_STATIC_MEM2 mutex is obtained and the SQLITE_MUTEX_STATIC_LRU
99** mutex released (in that order) before making the call.
100*/
101
drh41d30272008-08-20 21:47:45 +0000102#define pcacheEnterGlobal() sqlite3_mutex_enter(pcache.mutex_lru)
103#define pcacheExitGlobal() sqlite3_mutex_leave(pcache.mutex_lru)
danielk19778c0a7912008-08-20 14:49:23 +0000104
105/*
106** Increment the reference count on both page p and its cache by n.
107*/
drh41d30272008-08-20 21:47:45 +0000108static void pcacheRef(PgHdr *p, int n){
danielk19778c0a7912008-08-20 14:49:23 +0000109 /* This next block assert()s that the number of references to the
110 ** PCache is the sum of the number of references to all pages in
111 ** the PCache. This is a bit expensive to leave turned on all the
112 ** time, even in debugging builds.
113 */
114#if 0
115 PgHdr *pHdr;
116 int nRef = 0;
117 for(pHdr=p->pCache->pClean; pHdr; pHdr=pHdr->pNext) nRef += pHdr->nRef;
118 for(pHdr=p->pCache->pDirty; pHdr; pHdr=pHdr->pNext) nRef += pHdr->nRef;
119 assert( p->pCache->nRef==nRef );
120#endif
121 p->nRef += n;
122 p->pCache->nRef += n;
123}
124
125/********************************** Linked List Management ********************/
126
drh41d30272008-08-20 21:47:45 +0000127#ifndef NDEBUG
128/*
129** This routine verifies that the number of entries in the hash table
130** is pCache->nPage. This routine is used within assert() statements
131** only and is therefore disabled during production builds.
132*/
133static int pcacheCheckHashCount(PCache *pCache){
danielk19778c0a7912008-08-20 14:49:23 +0000134 int i;
135 int nPage = 0;
136 for(i=0; i<pCache->nHash; i++){
137 PgHdr *p;
138 for(p=pCache->apHash[i]; p; p=p->pNextHash){
139 nPage++;
140 }
141 }
142 assert( nPage==pCache->nPage );
143 return 1;
144}
drh41d30272008-08-20 21:47:45 +0000145#endif
danielk19778c0a7912008-08-20 14:49:23 +0000146
147/*
148** Remove a page from its hash table (PCache.apHash[]).
149*/
150static void pcacheRemoveFromHash(PgHdr *pPage){
151 if( pPage->pPrevHash ){
152 pPage->pPrevHash->pNextHash = pPage->pNextHash;
153 }else{
154 PCache *pCache = pPage->pCache;
155 u32 h = pPage->pgno % pCache->nHash;
156 assert( pCache->apHash[h]==pPage );
157 pCache->apHash[h] = pPage->pNextHash;
158 }
159 if( pPage->pNextHash ){
160 pPage->pNextHash->pPrevHash = pPage->pPrevHash;
161 }
162 pPage->pCache->nPage--;
drh41d30272008-08-20 21:47:45 +0000163 assert( pcacheCheckHashCount(pPage->pCache) );
danielk19778c0a7912008-08-20 14:49:23 +0000164}
165
166/*
167** Insert a page into the hash table
168*/
169static void pcacheAddToHash(PgHdr *pPage){
170 PCache *pCache = pPage->pCache;
171 u32 h = pPage->pgno % pCache->nHash;
172 pPage->pNextHash = pCache->apHash[h];
173 pPage->pPrevHash = 0;
174 if( pCache->apHash[h] ){
175 pCache->apHash[h]->pPrevHash = pPage;
176 }
177 pCache->apHash[h] = pPage;
178 pCache->nPage++;
drh41d30272008-08-20 21:47:45 +0000179 assert( pcacheCheckHashCount(pCache) );
danielk19778c0a7912008-08-20 14:49:23 +0000180}
181
182/*
drh41d30272008-08-20 21:47:45 +0000183** Attempt to increase the size the hash table to contain
184** at least nHash buckets.
danielk19778c0a7912008-08-20 14:49:23 +0000185*/
186static int pcacheResizeHash(PCache *pCache, int nHash){
187#ifdef SQLITE_MALLOC_SOFT_LIMIT
drh41d30272008-08-20 21:47:45 +0000188 if( nHash*sizeof(PgHdr*)>SQLITE_MALLOC_SOFT_LIMIT ){
danielk19778c0a7912008-08-20 14:49:23 +0000189 nHash = SQLITE_MALLOC_SOFT_LIMIT/sizeof(PgHdr *);
190 }
191#endif
192 if( nHash>pCache->nHash ){
193 PgHdr *p;
drh41d30272008-08-20 21:47:45 +0000194 PgHdr **pNew = (PgHdr **)sqlite3_malloc(sizeof(PgHdr*)*nHash);
danielk19778c0a7912008-08-20 14:49:23 +0000195 if( !pNew ){
196 return SQLITE_NOMEM;
197 }
198 memset(pNew, 0, sizeof(PgHdr *)*nHash);
199 sqlite3_free(pCache->apHash);
200 pCache->apHash = pNew;
201 pCache->nHash = nHash;
202 pCache->nPage = 0;
203
204 for(p=pCache->pClean; p; p=p->pNext){
205 pcacheAddToHash(p);
206 }
207 for(p=pCache->pDirty; p; p=p->pNext){
208 pcacheAddToHash(p);
209 }
210 }
211 return SQLITE_OK;
212}
213
214/*
215** Remove a page from a linked list that is headed by *ppHead.
216** *ppHead is either PCache.pClean or PCache.pDirty.
217*/
218static void pcacheRemoveFromList(PgHdr **ppHead, PgHdr *pPage){
219 if( pPage->pPrev ){
220 pPage->pPrev->pNext = pPage->pNext;
221 }else{
222 assert( *ppHead==pPage );
223 *ppHead = pPage->pNext;
224 }
225 if( pPage->pNext ){
226 pPage->pNext->pPrev = pPage->pPrev;
227 }
228}
229
230/*
231** Add a page from a linked list that is headed by *ppHead.
232** *ppHead is either PCache.pClean or PCache.pDirty.
233*/
234static void pcacheAddToList(PgHdr **ppHead, PgHdr *pPage){
235 if( (*ppHead) ){
236 (*ppHead)->pPrev = pPage;
237 }
238 pPage->pNext = *ppHead;
239 pPage->pPrev = 0;
240 *ppHead = pPage;
241}
242
243/*
244** Remove a page from the global LRU list
245*/
246static void pcacheRemoveFromLruList(PgHdr *pPage){
247 assert( sqlite3_mutex_held(pcache.mutex_lru) );
248 if( pPage->pCache->bPurgeable==0 ) return;
249 if( pPage->pNextLru ){
250 pPage->pNextLru->pPrevLru = pPage->pPrevLru;
251 }else{
252 assert( pcache.pLruTail==pPage );
253 pcache.pLruTail = pPage->pPrevLru;
254 }
255 if( pPage->pPrevLru ){
256 pPage->pPrevLru->pNextLru = pPage->pNextLru;
257 }else{
258 assert( pcache.pLruHead==pPage );
259 pcache.pLruHead = pPage->pNextLru;
260 }
261}
262
263/*
264** Add a page to the global LRU list. The page is normally added
265** to the front of the list so that it will be the last page recycled.
266** However, if the PGHDR_REUSE_UNLIKELY bit is set, the page is added
267** to the end of the LRU list so that it will be the next to be recycled.
268*/
269static void pcacheAddToLruList(PgHdr *pPage){
270 assert( sqlite3_mutex_held(pcache.mutex_lru) );
271 if( pPage->pCache->bPurgeable==0 ) return;
272 if( pcache.pLruTail && (pPage->flags & PGHDR_REUSE_UNLIKELY)!=0 ){
273 /* If reuse is unlikely. Put the page at the end of the LRU list
274 ** where it will be recycled sooner rather than later.
275 */
276 assert( pcache.pLruHead );
277 pPage->pNextLru = 0;
278 pPage->pPrevLru = pcache.pLruTail;
279 pcache.pLruTail->pNextLru = pPage;
280 pcache.pLruTail = pPage;
281 pPage->flags &= ~PGHDR_REUSE_UNLIKELY;
282 }else{
283 /* If reuse is possible. the page goes at the beginning of the LRU
284 ** list so that it will be the last to be recycled.
285 */
286 if( pcache.pLruHead ){
287 pcache.pLruHead->pPrevLru = pPage;
288 }
289 pPage->pNextLru = pcache.pLruHead;
290 pcache.pLruHead = pPage;
291 pPage->pPrevLru = 0;
292 if( pcache.pLruTail==0 ){
293 pcache.pLruTail = pPage;
294 }
295 }
296}
297
298/*********************************************** Memory Allocation ***********
299**
300** Initialize the page cache memory pool.
301**
302** This must be called at start-time when no page cache lines are
303** checked out. This function is not threadsafe.
304*/
305void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){
306 PgFreeslot *p;
307 sz &= ~7;
308 pcache.szSlot = sz;
309 pcache.pStart = pBuf;
310 pcache.pFree = 0;
311 while( n-- ){
312 p = (PgFreeslot*)pBuf;
313 p->pNext = pcache.pFree;
314 pcache.pFree = p;
315 pBuf = (void*)&((char*)pBuf)[sz];
316 }
317 pcache.pEnd = pBuf;
318}
319
320/*
321** Allocate a page cache line. Look in the page cache memory pool first
322** and use an element from it first if available. If nothing is available
323** in the page cache memory pool, go to the general purpose memory allocator.
324*/
325void *pcacheMalloc(int sz){
326 assert( sqlite3_mutex_held(pcache.mutex_lru) );
327 if( sz<=pcache.szSlot && pcache.pFree ){
328 PgFreeslot *p = pcache.pFree;
329 pcache.pFree = p->pNext;
330 sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, sz);
331 sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, 1);
332 return (void*)p;
333 }else{
334 void *p = sqlite3Malloc(sz);
335 if( p ){
336 sz = sqlite3MallocSize(p);
337 sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz);
338 }
339 return p;
340 }
341}
342void *sqlite3PageMalloc(sz){
343 void *p;
drh41d30272008-08-20 21:47:45 +0000344 pcacheEnterGlobal();
danielk19778c0a7912008-08-20 14:49:23 +0000345 p = pcacheMalloc(sz);
drh41d30272008-08-20 21:47:45 +0000346 pcacheExitGlobal();
danielk19778c0a7912008-08-20 14:49:23 +0000347 return p;
348}
349
350/*
351** Release a pager memory allocation
352*/
353void pcacheFree(void *p){
354 assert( sqlite3_mutex_held(pcache.mutex_lru) );
355 if( p==0 ) return;
356 if( p>=pcache.pStart && p<pcache.pEnd ){
357 PgFreeslot *pSlot;
358 sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, -1);
359 pSlot = (PgFreeslot*)p;
360 pSlot->pNext = pcache.pFree;
361 pcache.pFree = pSlot;
362 }else{
363 int iSize = sqlite3MallocSize(p);
364 sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, -iSize);
365 sqlite3_free(p);
366 }
367}
368void sqlite3PageFree(void *p){
drh41d30272008-08-20 21:47:45 +0000369 pcacheEnterGlobal();
danielk19778c0a7912008-08-20 14:49:23 +0000370 pcacheFree(p);
drh41d30272008-08-20 21:47:45 +0000371 pcacheExitGlobal();
danielk19778c0a7912008-08-20 14:49:23 +0000372}
373
374/*
375** Allocate a new page.
376*/
377static PgHdr *pcachePageAlloc(int szPage, int szExtra, int bPurgeable){
378 PgHdr *p;
379 int sz = sizeof(*p) + szPage + szExtra;
380 assert( sqlite3_mutex_held(pcache.mutex_lru) );
381 p = pcacheMalloc( sz );
382 if( p==0 ) return 0;
383 memset(p, 0, sizeof(PgHdr));
384 p->pData = (void*)&p[1];
385 p->pExtra = (void*)&((char*)p->pData)[szPage];
386
387 pcache.nPage++;
388 if( bPurgeable ){
389 pcache.nPurgeable++;
390 }
391
392 return p;
393}
394
395/*
396** Deallocate a page
397*/
398static void pcachePageFree(PgHdr *p){
399 assert( sqlite3_mutex_held(pcache.mutex_lru) );
400 pcache.nPage--;
401 if( p->pCache->bPurgeable ){
402 pcache.nPurgeable--;
403 }
404 pcacheFree(p->apSave[0]);
405 pcacheFree(p->apSave[1]);
406 pcacheFree(p);
407}
408
409/*
410** Obtain space for a page. Try to recycle an old page if the limit on the
411** number of pages has been reached. If the limit has not been reached or
412** there are no pages eligible for recycling, allocate a new page.
413**
414** Return a pointer to the new page, or NULL if an OOM condition occurs.
415*/
416static PgHdr *pcacheRecycleOrAlloc(PCache *pCache){
417 PgHdr *p = 0;
418
419 int szPage = pCache->szPage;
420 int szExtra = pCache->szExtra;
421 int bPurg = pCache->bPurgeable;
422
423 assert( pcache.isInit );
424 assert( sqlite3_mutex_notheld(pcache.mutex_lru) );
425
drh41d30272008-08-20 21:47:45 +0000426 pcacheEnterGlobal();
danielk19778c0a7912008-08-20 14:49:23 +0000427
428 if( (pcache.mxPage && pcache.nPage>=pcache.mxPage)
429 || (!pcache.mxPage && bPurg && pcache.nPurgeable>=pcache.mxPagePurgeable)
430 ){
431 PCache *pCsr;
432
433 /* If the above test succeeds, then a page will be obtained by recycling
434 ** an existing page.
435 */
436 if( !pcache.pLruTail && SQLITE_OK==sqlite3_mutex_try(pcache.mutex_mem2) ){
437
438 /* Invoke xStress() callbacks until the LRU list contains at least one
439 ** page that can be reused or until the xStress() callback of all
440 ** caches has been invoked.
441 */
442 for(pCsr=pcache.pAll; pCsr&&!pcache.pLruTail; pCsr=pCsr->pNextAll){
443 assert( pCsr->iInUseMM==0 );
444 pCsr->iInUseMM = 1;
445 if( pCsr->xStress && (pCsr->iInUseDB==0 || pCache==pCsr) ){
drh41d30272008-08-20 21:47:45 +0000446 pcacheExitGlobal();
danielk19778c0a7912008-08-20 14:49:23 +0000447 pCsr->xStress(pCsr->pStress);
drh41d30272008-08-20 21:47:45 +0000448 pcacheEnterGlobal();
danielk19778c0a7912008-08-20 14:49:23 +0000449 }
450 pCsr->iInUseMM = 0;
451 }
452
453 sqlite3_mutex_leave(pcache.mutex_mem2);
454 }
455
456 p = pcache.pLruTail;
457 }
458
459 if( p ){
460 pcacheRemoveFromLruList(p);
461 pcacheRemoveFromHash(p);
462 pcacheRemoveFromList(&p->pCache->pClean, p);
463
464 /* If the always-rollback flag is set on the page being recycled, set
465 ** the always-rollback flag on the corresponding pager.
466 */
467 if( p->flags&PGHDR_ALWAYS_ROLLBACK ){
468 assert(p->pPager);
469 sqlite3PagerAlwaysRollback(p->pPager);
470 }
471
472 if( p->pCache->szPage!=szPage || p->pCache->szExtra!=szExtra ){
473 pcachePageFree(p);
474 p = 0;
475 }
476 }
477
478 if( !p ){
479 /* Allocate a new page object. */
480 p = pcachePageAlloc(szPage, szExtra, bPurg);
481 }
482
drh41d30272008-08-20 21:47:45 +0000483 pcacheExitGlobal();
danielk19778c0a7912008-08-20 14:49:23 +0000484 return p;
485}
486
487/*************************************************** General Interfaces ******
488**
489** Initialize and shutdown the page cache subsystem. Neither of these
490** functions are threadsafe.
491*/
492int sqlite3PcacheInitialize(void){
493 assert( pcache.isInit==0 );
494 memset(&pcache, 0, sizeof(pcache));
495 if( sqlite3Config.bCoreMutex ){
496 pcache.mutex_lru = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU);
497 pcache.mutex_mem2 = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM2);
498 if( pcache.mutex_lru==0 || pcache.mutex_mem2==0 ){
499 return SQLITE_NOMEM;
500 }
501 }
502 pcache.isInit = 1;
503 return SQLITE_OK;
504}
505void sqlite3PcacheShutdown(void){
506 memset(&pcache, 0, sizeof(pcache));
507}
508
509/*
510** Return the size in bytes of a PCache object.
511*/
512int sqlite3PcacheSize(void){ return sizeof(PCache); }
513
514/*
515** Create a new PCache object. Storage space to hold the object
516** has already been allocated and is passed in as the p pointer.
517*/
518void sqlite3PcacheOpen(
519 int szPage, /* Size of every page */
520 int szExtra, /* Extra space associated with each page */
521 int bPurgeable, /* True if pages are on backing store */
522 void (*xDestroy)(PgHdr*), /* Called to destroy a page */
523 int (*xStress)(void*), /* Call to try to make pages clean */
524 void *pStress, /* Argument to xStress */
525 PCache *p /* Preallocated space for the PCache */
526){
527 assert( pcache.isInit );
528 memset(p, 0, sizeof(PCache));
529 p->szPage = szPage;
530 p->szExtra = szExtra;
531 p->bPurgeable = bPurgeable;
532 p->xDestroy = xDestroy;
533 p->xStress = xStress;
534 p->pStress = pStress;
535 p->nMax = 100;
536
537 if( bPurgeable ){
drh41d30272008-08-20 21:47:45 +0000538 pcacheEnterGlobal();
danielk19778c0a7912008-08-20 14:49:23 +0000539 pcache.mxPagePurgeable += p->nMax;
drh41d30272008-08-20 21:47:45 +0000540 pcacheExitGlobal();
danielk19778c0a7912008-08-20 14:49:23 +0000541 }
542
543 /* Add the new pager-cache to the list of caches starting at pcache.pAll */
544 sqlite3_mutex_enter(pcache.mutex_mem2);
545 p->pNextAll = pcache.pAll;
546 if( pcache.pAll ){
547 pcache.pAll->pPrevAll = p;
548 }
549 p->pPrevAll = 0;
550 pcache.pAll = p;
551 sqlite3_mutex_leave(pcache.mutex_mem2);
552}
553
drh41d30272008-08-20 21:47:45 +0000554/*
555** Change the page size for PCache object. This can only happen
556** when the cache is empty.
557*/
danielk19778c0a7912008-08-20 14:49:23 +0000558void sqlite3PcacheSetPageSize(PCache *pCache, int szPage){
559 assert(pCache->nPage==0);
560 pCache->szPage = szPage;
561}
562
563/*
564** Try to obtain a page from the cache.
565*/
566int sqlite3PcacheFetch(
567 PCache *pCache, /* Obtain the page from this cache */
568 Pgno pgno, /* Page number to obtain */
569 int createFlag, /* If true, create page if it does not exist already */
570 PgHdr **ppPage /* Write the page here */
571){
572 PgHdr *pPage;
573 assert( pcache.isInit );
574 assert( pCache!=0 );
575 assert( pgno>0 );
576 assert( pCache->iInUseDB || pCache->iInUseMM );
577
578 /* Search the hash table for the requested page. Exit early if it is found. */
579 if( pCache->apHash ){
580 u32 h = pgno % pCache->nHash;
581 for(pPage=pCache->apHash[h]; pPage; pPage=pPage->pNextHash){
582 if( pPage->pgno==pgno ){
583 if( pPage->nRef==0 && (pPage->flags & PGHDR_DIRTY)==0 ){
drh41d30272008-08-20 21:47:45 +0000584 pcacheEnterGlobal();
danielk19778c0a7912008-08-20 14:49:23 +0000585 pcacheRemoveFromLruList(pPage);
drh41d30272008-08-20 21:47:45 +0000586 pcacheExitGlobal();
danielk19778c0a7912008-08-20 14:49:23 +0000587 }
drh41d30272008-08-20 21:47:45 +0000588 pcacheRef(pPage, 1);
danielk19778c0a7912008-08-20 14:49:23 +0000589 *ppPage = pPage;
590 return SQLITE_OK;
591 }
592 }
593 }
594
595 if( createFlag ){
596 if( pCache->nHash<=pCache->nPage ){
597 int rc = pcacheResizeHash(pCache, pCache->nHash<256?256:pCache->nHash*2);
598 if( rc!=SQLITE_OK ){
599 return rc;
600 }
601 }
602
603 pPage = pcacheRecycleOrAlloc(pCache);
604 *ppPage = pPage;
605 if( pPage==0 ){
606 return SQLITE_NOMEM;
607 }
608
609 pPage->pPager = 0;
610 pPage->flags = 0;
611 pPage->pDirty = 0;
612 pPage->nRef = 0;
613 pPage->pgno = pgno;
614 pPage->pCache = pCache;
drh41d30272008-08-20 21:47:45 +0000615 pcacheRef(pPage, 1);
danielk19778c0a7912008-08-20 14:49:23 +0000616 pcacheAddToList(&pCache->pClean, pPage);
617 pcacheAddToHash(pPage);
618 }else{
619 *ppPage = 0;
620 }
621
622 return SQLITE_OK;
623}
624
625/*
626** Dereference a page. When the reference count reaches zero,
627** move the page to the LRU list if it is clean.
628*/
629void sqlite3PcacheRelease(PgHdr *p){
630 assert( p->nRef>0 );
631 assert( p->pCache->iInUseDB || p->pCache->iInUseMM );
drh41d30272008-08-20 21:47:45 +0000632 pcacheRef(p, -1);
danielk19778c0a7912008-08-20 14:49:23 +0000633 if( p->nRef!=0 ) return;
634 if( p->pCache->xDestroy ){
635 p->pCache->xDestroy(p);
636 }
637 if( (p->flags & PGHDR_DIRTY)!=0 ) return;
drh41d30272008-08-20 21:47:45 +0000638 pcacheEnterGlobal();
danielk19778c0a7912008-08-20 14:49:23 +0000639 pcacheAddToLruList(p);
drh41d30272008-08-20 21:47:45 +0000640 pcacheExitGlobal();
danielk19778c0a7912008-08-20 14:49:23 +0000641}
642
643void sqlite3PcacheRef(PgHdr *p){
644 assert(p->nRef>=0);
drh41d30272008-08-20 21:47:45 +0000645 pcacheRef(p, 1);
danielk19778c0a7912008-08-20 14:49:23 +0000646}
647
648/*
649** Drop a page from the cache. This should be the only reference to
650** the page.
651*/
652void sqlite3PcacheDrop(PgHdr *p){
653 PCache *pCache;
654 assert( p->pCache->iInUseDB );
655 assert( p->nRef==1 );
656 pCache = p->pCache;
657 pCache->nRef--;
658 if( p->flags & PGHDR_DIRTY ){
659 pcacheRemoveFromList(&pCache->pDirty, p);
660 }else{
661 pcacheRemoveFromList(&pCache->pClean, p);
662 }
663 pcacheRemoveFromHash(p);
drh41d30272008-08-20 21:47:45 +0000664 pcacheEnterGlobal();
danielk19778c0a7912008-08-20 14:49:23 +0000665 pcachePageFree(p);
drh41d30272008-08-20 21:47:45 +0000666 pcacheExitGlobal();
danielk19778c0a7912008-08-20 14:49:23 +0000667}
668
669/*
670** Make sure the page is marked as dirty. If it isn't dirty already,
671** make it so.
672*/
673void sqlite3PcacheMakeDirty(PgHdr *p){
674 PCache *pCache;
675 assert( p->pCache->iInUseDB );
676 if( p->flags & PGHDR_DIRTY ) return;
677 assert( (p->flags & PGHDR_DIRTY)==0 );
678 assert( p->nRef>0 );
679 pCache = p->pCache;
680 pcacheRemoveFromList(&pCache->pClean, p);
681 pcacheAddToList(&pCache->pDirty, p);
682 p->flags |= PGHDR_DIRTY;
683}
684
685/*
686** Make sure the page is marked as clean. If it isn't clean already,
687** make it so.
688*/
689void sqlite3PcacheMakeClean(PgHdr *p){
690 PCache *pCache;
691 assert( p->pCache->iInUseDB || p->pCache->iInUseMM );
692 if( (p->flags & PGHDR_DIRTY)==0 ) return;
693 assert( p->apSave[0]==0 && p->apSave[1]==0 );
694 assert( p->flags & PGHDR_DIRTY );
695 /* assert( p->nRef>0 ); */
696 pCache = p->pCache;
697 pcacheRemoveFromList(&pCache->pDirty, p);
698 pcacheAddToList(&pCache->pClean, p);
699 p->flags &= ~PGHDR_DIRTY;
700 if( p->nRef==0 ){
drh41d30272008-08-20 21:47:45 +0000701 pcacheEnterGlobal();
danielk19778c0a7912008-08-20 14:49:23 +0000702 pcacheAddToLruList(p);
drh41d30272008-08-20 21:47:45 +0000703 pcacheExitGlobal();
danielk19778c0a7912008-08-20 14:49:23 +0000704 }
705}
706
707/*
708** Make every page in the cache clean.
709*/
710void sqlite3PcacheCleanAll(PCache *pCache){
711 PgHdr *p;
712 assert( pCache->iInUseDB );
713 while( (p = pCache->pDirty)!=0 ){
714 assert( p->apSave[0]==0 && p->apSave[1]==0 );
715 pcacheRemoveFromList(&pCache->pDirty, p);
716 pcacheAddToList(&pCache->pClean, p);
717 p->flags &= ~PGHDR_DIRTY;
718 if( p->nRef==0 ){
drh41d30272008-08-20 21:47:45 +0000719 pcacheEnterGlobal();
danielk19778c0a7912008-08-20 14:49:23 +0000720 pcacheAddToLruList(p);
drh41d30272008-08-20 21:47:45 +0000721 pcacheExitGlobal();
danielk19778c0a7912008-08-20 14:49:23 +0000722 }
723 }
724}
725
726/*
727** Change the page number of page p to newPgno. If newPgno is 0, then the
728** page object is added to the clean-list and the PGHDR_REUSE_UNLIKELY
729** flag set.
730*/
731void sqlite3PcacheMove(PgHdr *p, Pgno newPgno){
732 assert( p->pCache->iInUseDB );
733 pcacheRemoveFromHash(p);
734 p->pgno = newPgno;
735 if( newPgno==0 ){
736 p->flags |= PGHDR_REUSE_UNLIKELY;
drh41d30272008-08-20 21:47:45 +0000737 pcacheEnterGlobal();
danielk19778c0a7912008-08-20 14:49:23 +0000738 pcacheFree(p->apSave[0]);
739 pcacheFree(p->apSave[1]);
drh41d30272008-08-20 21:47:45 +0000740 pcacheExitGlobal();
danielk19778c0a7912008-08-20 14:49:23 +0000741 p->apSave[0] = 0;
742 p->apSave[1] = 0;
743 sqlite3PcacheMakeClean(p);
744 }
745 pcacheAddToHash(p);
746}
747
748/*
749** Set the global maximum number of pages. Return the previous value.
750*/
751void sqlite3PcacheGlobalMax(int mx){
drh41d30272008-08-20 21:47:45 +0000752 pcacheEnterGlobal();
danielk19778c0a7912008-08-20 14:49:23 +0000753 pcache.mxPage = mx;
drh41d30272008-08-20 21:47:45 +0000754 pcacheExitGlobal();
danielk19778c0a7912008-08-20 14:49:23 +0000755}
756
757/*
758** Remove all content from a page cache
759*/
760void pcacheClear(PCache *pCache){
761 PgHdr *p, *pNext;
762 assert( sqlite3_mutex_held(pcache.mutex_lru) );
763 for(p=pCache->pClean; p; p=pNext){
764 pNext = p->pNext;
765 pcacheRemoveFromLruList(p);
766 pcachePageFree(p);
767 }
768 for(p=pCache->pDirty; p; p=pNext){
769 pNext = p->pNext;
770 pcachePageFree(p);
771 }
772 pCache->pClean = 0;
773 pCache->pDirty = 0;
774 pCache->nPage = 0;
775 memset(pCache->apHash, 0, pCache->nHash*sizeof(pCache->apHash[0]));
776}
777
778
779/*
780** Drop every cache entry whose page number is greater than "pgno".
781*/
782void sqlite3PcacheTruncate(PCache *pCache, Pgno pgno){
783 PgHdr *p, *pNext;
784 PgHdr *pDirty = pCache->pDirty;
785 assert( pCache->iInUseDB );
drh41d30272008-08-20 21:47:45 +0000786 pcacheEnterGlobal();
danielk19778c0a7912008-08-20 14:49:23 +0000787 for(p=pCache->pClean; p||pDirty; p=pNext){
788 if( !p ){
789 p = pDirty;
790 pDirty = 0;
791 }
792 pNext = p->pNext;
793 if( p->pgno>pgno ){
794 if( p->nRef==0 ){
795 pcacheRemoveFromHash(p);
796 if( p->flags&PGHDR_DIRTY ){
797 pcacheRemoveFromList(&pCache->pDirty, p);
798 }else{
799 pcacheRemoveFromLruList(p);
800 pcacheRemoveFromList(&pCache->pClean, p);
801 }
802 pcachePageFree(p);
803 }else{
804 /* If there are references to the page, it cannot be freed. In this
805 ** case, zero the page content instead.
806 */
807 memset(p->pData, 0, pCache->szPage);
808 }
809 }
810 }
drh41d30272008-08-20 21:47:45 +0000811 pcacheExitGlobal();
danielk19778c0a7912008-08-20 14:49:23 +0000812}
813
814
815/*
816** Close a cache.
817*/
818void sqlite3PcacheClose(PCache *pCache){
819 assert( pCache->iInUseDB==1 );
820
821 /* Free all the pages used by this pager and remove them from the LRU
822 ** list. This requires the protection of the MUTEX_STATIC_LRU mutex.
823 */
drh41d30272008-08-20 21:47:45 +0000824 pcacheEnterGlobal();
danielk19778c0a7912008-08-20 14:49:23 +0000825 pcacheClear(pCache);
826 if( pCache->bPurgeable ){
827 pcache.mxPagePurgeable -= pCache->nMax;
828 }
829 sqlite3_free(pCache->apHash);
drh41d30272008-08-20 21:47:45 +0000830 pcacheExitGlobal();
danielk19778c0a7912008-08-20 14:49:23 +0000831
832 /* Now remove the pager-cache structure itself from the list of
833 ** all such structures headed by pcache.pAll. This required the
834 ** MUTEX_STATIC_MEM2 mutex.
835 */
836 sqlite3_mutex_enter(pcache.mutex_mem2);
837 assert(pCache==pcache.pAll || pCache->pPrevAll);
838 assert(pCache->pNextAll==0 || pCache->pNextAll->pPrevAll==pCache);
839 assert(pCache->pPrevAll==0 || pCache->pPrevAll->pNextAll==pCache);
840 if( pCache->pPrevAll ){
841 pCache->pPrevAll->pNextAll = pCache->pNextAll;
842 }else{
843 pcache.pAll = pCache->pNextAll;
844 }
845 if( pCache->pNextAll ){
846 pCache->pNextAll->pPrevAll = pCache->pPrevAll;
847 }
848 sqlite3_mutex_leave(pcache.mutex_mem2);
849}
850
851/*
852** Preserve the content of the page, if it has not been preserved
853** already. If idJournal==0 then this is for the overall transaction.
854** If idJournal==1 then this is for the statement journal.
855**
856** This routine is used for in-memory databases only.
857**
858** Return SQLITE_OK or SQLITE_NOMEM if a memory allocation fails.
859*/
860int sqlite3PcachePreserve(PgHdr *p, int idJournal){
861 void *x;
862 int sz;
863 assert( p->pCache->iInUseDB );
864 assert( p->pCache->bPurgeable==0 );
865 if( !p->apSave[idJournal] ){
866 sz = p->pCache->szPage;
867 p->apSave[idJournal] = x = sqlite3PageMalloc( sz );
868 if( x==0 ) return SQLITE_NOMEM;
869 memcpy(x, p->pData, sz);
870 }
871 return SQLITE_OK;
872}
873
874/*
875** Commit a change previously preserved.
876*/
877void sqlite3PcacheCommit(PCache *pCache, int idJournal){
878 PgHdr *p;
879 assert( pCache->iInUseDB );
drh41d30272008-08-20 21:47:45 +0000880 pcacheEnterGlobal(); /* Mutex is required to call pcacheFree() */
danielk19778c0a7912008-08-20 14:49:23 +0000881 for(p=pCache->pDirty; p; p=p->pNext){
882 if( p->apSave[idJournal] ){
883 pcacheFree(p->apSave[idJournal]);
884 p->apSave[idJournal] = 0;
885 }
886 }
drh41d30272008-08-20 21:47:45 +0000887 pcacheExitGlobal();
danielk19778c0a7912008-08-20 14:49:23 +0000888}
889
890/*
891** Rollback a change previously preserved.
892*/
893void sqlite3PcacheRollback(PCache *pCache, int idJournal){
894 PgHdr *p;
895 int sz;
896 assert( pCache->iInUseDB );
drh41d30272008-08-20 21:47:45 +0000897 pcacheEnterGlobal(); /* Mutex is required to call pcacheFree() */
danielk19778c0a7912008-08-20 14:49:23 +0000898 sz = pCache->szPage;
899 for(p=pCache->pDirty; p; p=p->pNext){
900 if( p->apSave[idJournal] ){
901 memcpy(p->pData, p->apSave[idJournal], sz);
902 pcacheFree(p->apSave[idJournal]);
903 p->apSave[idJournal] = 0;
904 }
905 }
drh41d30272008-08-20 21:47:45 +0000906 pcacheExitGlobal();
danielk19778c0a7912008-08-20 14:49:23 +0000907}
908
909/*
910** Assert flags settings on all pages. Debugging only.
911*/
912void sqlite3PcacheAssertFlags(PCache *pCache, int trueMask, int falseMask){
913 PgHdr *p;
914 assert( pCache->iInUseDB || pCache->iInUseMM );
915 for(p=pCache->pDirty; p; p=p->pNext){
916 assert( (p->flags&trueMask)==trueMask );
917 assert( (p->flags&falseMask)==0 );
918 }
919 for(p=pCache->pClean; p; p=p->pNext){
920 assert( (p->flags&trueMask)==trueMask );
921 assert( (p->flags&falseMask)==0 );
922 }
923}
924
925/*
926** Discard the contents of the cache.
927*/
928int sqlite3PcacheClear(PCache *pCache){
929 assert( pCache->iInUseDB );
930 assert(pCache->nRef==0);
drh41d30272008-08-20 21:47:45 +0000931 pcacheEnterGlobal();
danielk19778c0a7912008-08-20 14:49:23 +0000932 pcacheClear(pCache);
drh41d30272008-08-20 21:47:45 +0000933 pcacheExitGlobal();
danielk19778c0a7912008-08-20 14:49:23 +0000934 return SQLITE_OK;
935}
936
937/*
938** Merge two lists of pages connected by pDirty and in pgno order.
939** Do not both fixing the pPrevDirty pointers.
940*/
941static PgHdr *pcacheMergeDirtyList(PgHdr *pA, PgHdr *pB){
942 PgHdr result, *pTail;
943 pTail = &result;
944 while( pA && pB ){
945 if( pA->pgno<pB->pgno ){
946 pTail->pDirty = pA;
947 pTail = pA;
948 pA = pA->pDirty;
949 }else{
950 pTail->pDirty = pB;
951 pTail = pB;
952 pB = pB->pDirty;
953 }
954 }
955 if( pA ){
956 pTail->pDirty = pA;
957 }else if( pB ){
958 pTail->pDirty = pB;
959 }else{
960 pTail->pDirty = 0;
961 }
962 return result.pDirty;
963}
964
965/*
966** Sort the list of pages in accending order by pgno. Pages are
967** connected by pDirty pointers. The pPrevDirty pointers are
968** corrupted by this sort.
969*/
970#define N_SORT_BUCKET_ALLOC 25
971#define N_SORT_BUCKET 25
972#ifdef SQLITE_TEST
973 int sqlite3_pager_n_sort_bucket = 0;
974 #undef N_SORT_BUCKET
975 #define N_SORT_BUCKET \
976 (sqlite3_pager_n_sort_bucket?sqlite3_pager_n_sort_bucket:N_SORT_BUCKET_ALLOC)
977#endif
978static PgHdr *pcacheSortDirtyList(PgHdr *pIn){
979 PgHdr *a[N_SORT_BUCKET_ALLOC], *p;
980 int i;
981 memset(a, 0, sizeof(a));
982 while( pIn ){
983 p = pIn;
984 pIn = p->pDirty;
985 p->pDirty = 0;
986 for(i=0; i<N_SORT_BUCKET-1; i++){
987 if( a[i]==0 ){
988 a[i] = p;
989 break;
990 }else{
991 p = pcacheMergeDirtyList(a[i], p);
992 a[i] = 0;
993 }
994 }
995 if( i==N_SORT_BUCKET-1 ){
996 /* Coverage: To get here, there need to be 2^(N_SORT_BUCKET)
997 ** elements in the input list. This is possible, but impractical.
998 ** Testing this line is the point of global variable
999 ** sqlite3_pager_n_sort_bucket.
1000 */
1001 a[i] = pcacheMergeDirtyList(a[i], p);
1002 }
1003 }
1004 p = a[0];
1005 for(i=1; i<N_SORT_BUCKET; i++){
1006 p = pcacheMergeDirtyList(p, a[i]);
1007 }
1008 return p;
1009}
1010
1011/*
1012** Return a list of all dirty pages in the cache, sorted by page number.
1013*/
1014PgHdr *sqlite3PcacheDirtyList(PCache *pCache){
1015 PgHdr *p;
1016 assert( pCache->iInUseDB );
1017 for(p=pCache->pDirty; p; p=p->pNext){
1018 p->pDirty = p->pNext;
1019 }
1020 return pcacheSortDirtyList(pCache->pDirty);
1021}
1022
1023/*
1024** This function searches cache pCache for a dirty page for which the
1025** reference count is zero. If such a page can be found, the PgHdr.pDirty
1026** pointer is set to 0 and a pointer to the page is returned. If no
1027** such page is found, 0 is returned.
1028**
1029** This is used by the pager module to implement the xStress callback.
1030*/
1031PgHdr *sqlite3PcacheDirtyPage(PCache *pCache){
1032 PgHdr *p = 0;
danielk19778c0a7912008-08-20 14:49:23 +00001033#if 1
1034 PgHdr *pIter;
1035 Pgno min_pgno;
1036 for(pIter=pCache->pDirty; pIter; pIter=pIter->pNext){
1037 if( pIter->nRef==0 && (p==0 || pIter->pgno<min_pgno) ){
1038 p = pIter;
1039 min_pgno = pIter->pgno;
1040 }
1041 }
1042#else
1043 for(p=pCache->pDirty; p && p->nRef; p=p->pNext);
1044#endif
danielk19770d3c5d32008-08-21 04:41:01 +00001045 assert( pCache->iInUseMM );
danielk19778c0a7912008-08-20 14:49:23 +00001046 if( p ){
1047 p->pDirty = 0;
1048 }
1049 return p;
1050}
1051
1052/*
1053** Return the total number of outstanding page references.
1054*/
1055int sqlite3PcacheRefCount(PCache *pCache){
1056 return pCache->nRef;
1057}
1058
1059/*
1060** Return the total number of pages in the cache.
1061*/
1062int sqlite3PcachePagecount(PCache *pCache){
1063 assert( pCache->iInUseDB || pCache->iInUseMM );
1064 assert( pCache->nPage>=0 );
1065 return pCache->nPage;
1066}
1067
1068#ifdef SQLITE_CHECK_PAGES
1069/*
1070** This function is used by the pager.c module to iterate through all
1071** pages in the cache. At present, this is only required if the
1072** SQLITE_CHECK_PAGES macro (used for debugging) is specified.
1073*/
1074void sqlite3PcacheIterate(PCache *pCache, void (*xIter)(PgHdr *)){
1075 PgHdr *p;
1076 assert( pCache->iInUseDB || pCache->iInUseMM );
1077 for(p=pCache->pClean; p; p=p->pNext){
1078 xIter(p);
1079 }
1080 for(p=pCache->pDirty; p; p=p->pNext){
1081 xIter(p);
1082 }
1083}
1084#endif
1085
1086/*
1087** Set flags on all pages in the page cache
1088*/
1089void sqlite3PcacheSetFlags(PCache *pCache, int andMask, int orMask){
1090 PgHdr *p;
1091 assert( pCache->iInUseDB || pCache->iInUseMM );
1092 for(p=pCache->pDirty; p; p=p->pNext){
1093 p->flags = (p->flags&andMask)|orMask;
1094 }
1095 for(p=pCache->pClean; p; p=p->pNext){
1096 p->flags = (p->flags&andMask)|orMask;
1097 }
1098}
1099
1100/*
1101** Set the suggested cache-size value.
1102*/
1103int sqlite3PcacheGetCachesize(PCache *pCache){
1104 return pCache->nMax;
1105}
1106
1107/*
1108** Set the suggested cache-size value.
1109*/
1110void sqlite3PcacheSetCachesize(PCache *pCache, int mxPage){
1111 if( mxPage<10 ){
1112 mxPage = 10;
1113 }
1114 if( pCache->bPurgeable ){
drh41d30272008-08-20 21:47:45 +00001115 pcacheEnterGlobal();
danielk19778c0a7912008-08-20 14:49:23 +00001116 pcache.mxPagePurgeable -= pCache->nMax;
1117 pcache.mxPagePurgeable += mxPage;
drh41d30272008-08-20 21:47:45 +00001118 pcacheExitGlobal();
danielk19778c0a7912008-08-20 14:49:23 +00001119 }
1120 pCache->nMax = mxPage;
1121}
1122
1123/*
1124** Lock a pager-cache.
1125*/
1126void sqlite3PcacheLock(PCache *pCache){
1127 pCache->iInUseDB++;
1128 if( pCache->iInUseMM && pCache->iInUseDB==1 ){
1129 pCache->iInUseDB = 0;
1130 sqlite3_mutex_enter(pcache.mutex_mem2);
1131 assert( pCache->iInUseMM==0 && pCache->iInUseDB==0 );
1132 pCache->iInUseDB = 1;
1133 sqlite3_mutex_leave(pcache.mutex_mem2);
1134 }
1135}
1136
1137/*
1138** Unlock a pager-cache.
1139*/
1140void sqlite3PcacheUnlock(PCache *pCache){
1141 pCache->iInUseDB--;
1142 assert( pCache->iInUseDB>=0 );
1143}