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