OLD | NEW |
1 /* | 1 /* |
2 ** 2008 November 05 | 2 ** 2008 November 05 |
3 ** | 3 ** |
4 ** The author disclaims copyright to this source code. In place of | 4 ** The author disclaims copyright to this source code. In place of |
5 ** a legal notice, here is a blessing: | 5 ** a legal notice, here is a blessing: |
6 ** | 6 ** |
7 ** May you do good and not evil. | 7 ** May you do good and not evil. |
8 ** May you find forgiveness for yourself and forgive others. | 8 ** May you find forgiveness for yourself and forgive others. |
9 ** May you share freely, never taking more than you give. | 9 ** May you share freely, never taking more than you give. |
10 ** | 10 ** |
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
272 if( pcache1.nInitPage==0 ) return 0; | 272 if( pcache1.nInitPage==0 ) return 0; |
273 /* Do not bother with a bulk allocation if the cache size very small */ | 273 /* Do not bother with a bulk allocation if the cache size very small */ |
274 if( pCache->nMax<3 ) return 0; | 274 if( pCache->nMax<3 ) return 0; |
275 sqlite3BeginBenignMalloc(); | 275 sqlite3BeginBenignMalloc(); |
276 if( pcache1.nInitPage>0 ){ | 276 if( pcache1.nInitPage>0 ){ |
277 szBulk = pCache->szAlloc * (i64)pcache1.nInitPage; | 277 szBulk = pCache->szAlloc * (i64)pcache1.nInitPage; |
278 }else{ | 278 }else{ |
279 szBulk = -1024 * (i64)pcache1.nInitPage; | 279 szBulk = -1024 * (i64)pcache1.nInitPage; |
280 } | 280 } |
281 if( szBulk > pCache->szAlloc*(i64)pCache->nMax ){ | 281 if( szBulk > pCache->szAlloc*(i64)pCache->nMax ){ |
282 szBulk = pCache->szAlloc*pCache->nMax; | 282 szBulk = pCache->szAlloc*(i64)pCache->nMax; |
283 } | 283 } |
284 zBulk = pCache->pBulk = sqlite3Malloc( szBulk ); | 284 zBulk = pCache->pBulk = sqlite3Malloc( szBulk ); |
285 sqlite3EndBenignMalloc(); | 285 sqlite3EndBenignMalloc(); |
286 if( zBulk ){ | 286 if( zBulk ){ |
287 int nBulk = sqlite3MallocSize(zBulk)/pCache->szAlloc; | 287 int nBulk = sqlite3MallocSize(zBulk)/pCache->szAlloc; |
288 int i; | 288 int i; |
289 for(i=0; i<nBulk; i++){ | 289 for(i=0; i<nBulk; i++){ |
290 PgHdr1 *pX = (PgHdr1*)&zBulk[pCache->szPage]; | 290 PgHdr1 *pX = (PgHdr1*)&zBulk[pCache->szPage]; |
291 pX->page.pBuf = zBulk; | 291 pX->page.pBuf = zBulk; |
292 pX->page.pExtra = &pX[1]; | 292 pX->page.pExtra = &pX[1]; |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
341 #endif | 341 #endif |
342 sqlite3MemdebugSetType(p, MEMTYPE_PCACHE); | 342 sqlite3MemdebugSetType(p, MEMTYPE_PCACHE); |
343 } | 343 } |
344 return p; | 344 return p; |
345 } | 345 } |
346 | 346 |
347 /* | 347 /* |
348 ** Free an allocated buffer obtained from pcache1Alloc(). | 348 ** Free an allocated buffer obtained from pcache1Alloc(). |
349 */ | 349 */ |
350 static void pcache1Free(void *p){ | 350 static void pcache1Free(void *p){ |
351 int nFreed = 0; | |
352 if( p==0 ) return; | 351 if( p==0 ) return; |
353 if( SQLITE_WITHIN(p, pcache1.pStart, pcache1.pEnd) ){ | 352 if( SQLITE_WITHIN(p, pcache1.pStart, pcache1.pEnd) ){ |
354 PgFreeslot *pSlot; | 353 PgFreeslot *pSlot; |
355 sqlite3_mutex_enter(pcache1.mutex); | 354 sqlite3_mutex_enter(pcache1.mutex); |
356 sqlite3StatusDown(SQLITE_STATUS_PAGECACHE_USED, 1); | 355 sqlite3StatusDown(SQLITE_STATUS_PAGECACHE_USED, 1); |
357 pSlot = (PgFreeslot*)p; | 356 pSlot = (PgFreeslot*)p; |
358 pSlot->pNext = pcache1.pFree; | 357 pSlot->pNext = pcache1.pFree; |
359 pcache1.pFree = pSlot; | 358 pcache1.pFree = pSlot; |
360 pcache1.nFreeSlot++; | 359 pcache1.nFreeSlot++; |
361 pcache1.bUnderPressure = pcache1.nFreeSlot<pcache1.nReserve; | 360 pcache1.bUnderPressure = pcache1.nFreeSlot<pcache1.nReserve; |
362 assert( pcache1.nFreeSlot<=pcache1.nSlot ); | 361 assert( pcache1.nFreeSlot<=pcache1.nSlot ); |
363 sqlite3_mutex_leave(pcache1.mutex); | 362 sqlite3_mutex_leave(pcache1.mutex); |
364 }else{ | 363 }else{ |
365 assert( sqlite3MemdebugHasType(p, MEMTYPE_PCACHE) ); | 364 assert( sqlite3MemdebugHasType(p, MEMTYPE_PCACHE) ); |
366 sqlite3MemdebugSetType(p, MEMTYPE_HEAP); | 365 sqlite3MemdebugSetType(p, MEMTYPE_HEAP); |
367 #ifndef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS | 366 #ifndef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS |
368 nFreed = sqlite3MallocSize(p); | 367 { |
369 sqlite3_mutex_enter(pcache1.mutex); | 368 int nFreed = 0; |
370 sqlite3StatusDown(SQLITE_STATUS_PAGECACHE_OVERFLOW, nFreed); | 369 nFreed = sqlite3MallocSize(p); |
371 sqlite3_mutex_leave(pcache1.mutex); | 370 sqlite3_mutex_enter(pcache1.mutex); |
| 371 sqlite3StatusDown(SQLITE_STATUS_PAGECACHE_OVERFLOW, nFreed); |
| 372 sqlite3_mutex_leave(pcache1.mutex); |
| 373 } |
372 #endif | 374 #endif |
373 sqlite3_free(p); | 375 sqlite3_free(p); |
374 } | 376 } |
375 } | 377 } |
376 | 378 |
377 #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT | 379 #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT |
378 /* | 380 /* |
379 ** Return the size of a pcache allocation | 381 ** Return the size of a pcache allocation |
380 */ | 382 */ |
381 static int pcache1MemSize(void *p){ | 383 static int pcache1MemSize(void *p){ |
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
623 ** Discard all pages from cache pCache with a page number (key value) | 625 ** Discard all pages from cache pCache with a page number (key value) |
624 ** greater than or equal to iLimit. Any pinned pages that meet this | 626 ** greater than or equal to iLimit. Any pinned pages that meet this |
625 ** criteria are unpinned before they are discarded. | 627 ** criteria are unpinned before they are discarded. |
626 ** | 628 ** |
627 ** The PCache mutex must be held when this function is called. | 629 ** The PCache mutex must be held when this function is called. |
628 */ | 630 */ |
629 static void pcache1TruncateUnsafe( | 631 static void pcache1TruncateUnsafe( |
630 PCache1 *pCache, /* The cache to truncate */ | 632 PCache1 *pCache, /* The cache to truncate */ |
631 unsigned int iLimit /* Drop pages with this pgno or larger */ | 633 unsigned int iLimit /* Drop pages with this pgno or larger */ |
632 ){ | 634 ){ |
633 TESTONLY( unsigned int nPage = 0; ) /* To assert pCache->nPage is correct */ | 635 TESTONLY( int nPage = 0; ) /* To assert pCache->nPage is correct */ |
634 unsigned int h; | 636 unsigned int h, iStop; |
635 assert( sqlite3_mutex_held(pCache->pGroup->mutex) ); | 637 assert( sqlite3_mutex_held(pCache->pGroup->mutex) ); |
636 for(h=0; h<pCache->nHash; h++){ | 638 assert( pCache->iMaxKey >= iLimit ); |
637 PgHdr1 **pp = &pCache->apHash[h]; | 639 assert( pCache->nHash > 0 ); |
| 640 if( pCache->iMaxKey - iLimit < pCache->nHash ){ |
| 641 /* If we are just shaving the last few pages off the end of the |
| 642 ** cache, then there is no point in scanning the entire hash table. |
| 643 ** Only scan those hash slots that might contain pages that need to |
| 644 ** be removed. */ |
| 645 h = iLimit % pCache->nHash; |
| 646 iStop = pCache->iMaxKey % pCache->nHash; |
| 647 TESTONLY( nPage = -10; ) /* Disable the pCache->nPage validity check */ |
| 648 }else{ |
| 649 /* This is the general case where many pages are being removed. |
| 650 ** It is necessary to scan the entire hash table */ |
| 651 h = pCache->nHash/2; |
| 652 iStop = h - 1; |
| 653 } |
| 654 for(;;){ |
| 655 PgHdr1 **pp; |
638 PgHdr1 *pPage; | 656 PgHdr1 *pPage; |
| 657 assert( h<pCache->nHash ); |
| 658 pp = &pCache->apHash[h]; |
639 while( (pPage = *pp)!=0 ){ | 659 while( (pPage = *pp)!=0 ){ |
640 if( pPage->iKey>=iLimit ){ | 660 if( pPage->iKey>=iLimit ){ |
641 pCache->nPage--; | 661 pCache->nPage--; |
642 *pp = pPage->pNext; | 662 *pp = pPage->pNext; |
643 if( !pPage->isPinned ) pcache1PinPage(pPage); | 663 if( !pPage->isPinned ) pcache1PinPage(pPage); |
644 pcache1FreePage(pPage); | 664 pcache1FreePage(pPage); |
645 }else{ | 665 }else{ |
646 pp = &pPage->pNext; | 666 pp = &pPage->pNext; |
647 TESTONLY( nPage++; ) | 667 TESTONLY( if( nPage>=0 ) nPage++; ) |
648 } | 668 } |
649 } | 669 } |
| 670 if( h==iStop ) break; |
| 671 h = (h+1) % pCache->nHash; |
650 } | 672 } |
651 assert( pCache->nPage==nPage ); | 673 assert( nPage<0 || pCache->nPage==(unsigned)nPage ); |
652 } | 674 } |
653 | 675 |
654 /******************************************************************************/ | 676 /******************************************************************************/ |
655 /******** sqlite3_pcache Methods **********************************************/ | 677 /******** sqlite3_pcache Methods **********************************************/ |
656 | 678 |
657 /* | 679 /* |
658 ** Implementation of the sqlite3_pcache.xInit method. | 680 ** Implementation of the sqlite3_pcache.xInit method. |
659 */ | 681 */ |
660 static int pcache1Init(void *NotUsed){ | 682 static int pcache1Init(void *NotUsed){ |
661 UNUSED_PARAMETER(NotUsed); | 683 UNUSED_PARAMETER(NotUsed); |
(...skipping 23 matching lines...) Expand all Loading... |
685 pcache1.separateCache = 0; | 707 pcache1.separateCache = 0; |
686 #elif SQLITE_THREADSAFE | 708 #elif SQLITE_THREADSAFE |
687 pcache1.separateCache = sqlite3GlobalConfig.pPage==0 | 709 pcache1.separateCache = sqlite3GlobalConfig.pPage==0 |
688 || sqlite3GlobalConfig.bCoreMutex>0; | 710 || sqlite3GlobalConfig.bCoreMutex>0; |
689 #else | 711 #else |
690 pcache1.separateCache = sqlite3GlobalConfig.pPage==0; | 712 pcache1.separateCache = sqlite3GlobalConfig.pPage==0; |
691 #endif | 713 #endif |
692 | 714 |
693 #if SQLITE_THREADSAFE | 715 #if SQLITE_THREADSAFE |
694 if( sqlite3GlobalConfig.bCoreMutex ){ | 716 if( sqlite3GlobalConfig.bCoreMutex ){ |
695 pcache1.grp.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU); | 717 pcache1.grp.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU); |
696 pcache1.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_PMEM); | 718 pcache1.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_PMEM); |
697 } | 719 } |
698 #endif | 720 #endif |
699 if( pcache1.separateCache | 721 if( pcache1.separateCache |
700 && sqlite3GlobalConfig.nPage!=0 | 722 && sqlite3GlobalConfig.nPage!=0 |
701 && sqlite3GlobalConfig.pPage==0 | 723 && sqlite3GlobalConfig.pPage==0 |
702 ){ | 724 ){ |
703 pcache1.nInitPage = sqlite3GlobalConfig.nPage; | 725 pcache1.nInitPage = sqlite3GlobalConfig.nPage; |
704 }else{ | 726 }else{ |
705 pcache1.nInitPage = 0; | 727 pcache1.nInitPage = 0; |
706 } | 728 } |
(...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1122 /* | 1144 /* |
1123 ** Implementation of the sqlite3_pcache.xDestroy method. | 1145 ** Implementation of the sqlite3_pcache.xDestroy method. |
1124 ** | 1146 ** |
1125 ** Destroy a cache allocated using pcache1Create(). | 1147 ** Destroy a cache allocated using pcache1Create(). |
1126 */ | 1148 */ |
1127 static void pcache1Destroy(sqlite3_pcache *p){ | 1149 static void pcache1Destroy(sqlite3_pcache *p){ |
1128 PCache1 *pCache = (PCache1 *)p; | 1150 PCache1 *pCache = (PCache1 *)p; |
1129 PGroup *pGroup = pCache->pGroup; | 1151 PGroup *pGroup = pCache->pGroup; |
1130 assert( pCache->bPurgeable || (pCache->nMax==0 && pCache->nMin==0) ); | 1152 assert( pCache->bPurgeable || (pCache->nMax==0 && pCache->nMin==0) ); |
1131 pcache1EnterMutex(pGroup); | 1153 pcache1EnterMutex(pGroup); |
1132 pcache1TruncateUnsafe(pCache, 0); | 1154 if( pCache->nPage ) pcache1TruncateUnsafe(pCache, 0); |
1133 assert( pGroup->nMaxPage >= pCache->nMax ); | 1155 assert( pGroup->nMaxPage >= pCache->nMax ); |
1134 pGroup->nMaxPage -= pCache->nMax; | 1156 pGroup->nMaxPage -= pCache->nMax; |
1135 assert( pGroup->nMinPage >= pCache->nMin ); | 1157 assert( pGroup->nMinPage >= pCache->nMin ); |
1136 pGroup->nMinPage -= pCache->nMin; | 1158 pGroup->nMinPage -= pCache->nMin; |
1137 pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage; | 1159 pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage; |
1138 pcache1EnforceMaxPage(pCache); | 1160 pcache1EnforceMaxPage(pCache); |
1139 pcache1LeaveMutex(pGroup); | 1161 pcache1LeaveMutex(pGroup); |
1140 sqlite3_free(pCache->pBulk); | 1162 sqlite3_free(pCache->pBulk); |
1141 sqlite3_free(pCache->apHash); | 1163 sqlite3_free(pCache->apHash); |
1142 sqlite3_free(pCache); | 1164 sqlite3_free(pCache); |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1230 for(p=pcache1.grp.lru.pLruNext; p && !p->isAnchor; p=p->pLruNext){ | 1252 for(p=pcache1.grp.lru.pLruNext; p && !p->isAnchor; p=p->pLruNext){ |
1231 assert( p->isPinned==0 ); | 1253 assert( p->isPinned==0 ); |
1232 nRecyclable++; | 1254 nRecyclable++; |
1233 } | 1255 } |
1234 *pnCurrent = pcache1.grp.nCurrentPage; | 1256 *pnCurrent = pcache1.grp.nCurrentPage; |
1235 *pnMax = (int)pcache1.grp.nMaxPage; | 1257 *pnMax = (int)pcache1.grp.nMaxPage; |
1236 *pnMin = (int)pcache1.grp.nMinPage; | 1258 *pnMin = (int)pcache1.grp.nMinPage; |
1237 *pnRecyclable = nRecyclable; | 1259 *pnRecyclable = nRecyclable; |
1238 } | 1260 } |
1239 #endif | 1261 #endif |
OLD | NEW |