/* ** Drop every cache entry whose page number is greater than "pgno". */ void sqlite3PcacheTruncate(PCache *pCache, Pgno pgno){ PgHdr *p, *pNext; PgHdr *pDirty = pCache->pDirty; pcacheEnterMutex(); for(p=pCache->pClean; p||pDirty; p=pNext){ if( !p ){ p = pDirty; pDirty = 0; } pNext = p->pNext; if( p->pgno>pgno ){ if( p->nRef==0 ){ pcacheRemoveFromHash(p); if( p->flags&PGHDR_DIRTY ){ pcacheRemoveFromList(&pCache->pDirty, p); pCache->nPinned--; }else{ pcacheRemoveFromList(&pCache->pClean, p); pcacheRemoveFromLruList(p); } pcachePageFree(p); }else{ /* If there are references to the page, it cannot be freed. In this ** case, zero the page content instead. */ memset(p->pData, 0, pCache->szPage); } } } pcacheExitMutex(); }
/* ** Dereference a page. When the reference count reaches zero, ** move the page to the LRU list if it is clean. */ void sqlite3PcacheRelease(PgHdr *p) { assert( p->nRef>0 ); p->nRef--; if( p->nRef==0 ) { PCache *pCache = p->pCache; if( p->pCache->xDestroy ) { p->pCache->xDestroy(p); } pCache->nRef--; if( (p->flags&PGHDR_DIRTY)==0 ) { pCache->nPinned--; pcacheEnterMutex(); if( pcache.nCurrentPage>pcache.nMaxPage ) { pcacheRemoveFromList(&pCache->pClean, p); pcacheRemoveFromHash(p); pcachePageFree(p); } else { pcacheAddToLruList(p); } pcacheExitMutex(); } else { /* Move the page to the head of the caches dirty list. */ pcacheRemoveFromList(&pCache->pDirty, p); pcacheAddToList(&pCache->pDirty, p); } } }
/* ** Drop a page from the cache. There must be exactly one reference to the ** page. This function deletes that reference, so after it returns the ** page pointed to by p is invalid. */ void sqlite3PcacheDrop(PgHdr *p){ PCache *pCache; assert( p->nRef==1 ); assert( 0==(p->flags&PGHDR_DIRTY) ); pCache = p->pCache; pCache->nRef--; pCache->nPinned--; pcacheEnterMutex(); pcacheRemoveFromList(&pCache->pClean, p); pcacheRemoveFromHash(p); pcachePageFree(p); pcacheExitMutex(); }
/* ** Attempt to 'recycle' a page from the global LRU list. Only clean, ** unreferenced pages from purgeable caches are eligible for recycling. ** ** This function removes page pcache.pLruTail from the global LRU list, ** and from the hash-table and PCache.pClean list of the owner pcache. ** There should be no other references to the page. ** ** A pointer to the recycled page is returned, or NULL if no page is ** eligible for recycling. */ static PgHdr *pcacheRecyclePage(void){ PgHdr *p = 0; assert( sqlite3_mutex_held(pcache_g.mutex) ); if( (p=pcache_g.pLruTail)!=0 ){ assert( (p->flags&PGHDR_DIRTY)==0 ); pcacheRemoveFromLruList(p); pcacheRemoveFromHash(p); pcacheRemoveFromList(&p->pCache->pClean, p); } return p; }
/* ** Change the page number of page p to newPgno. If newPgno is 0, then the ** page object is added to the clean-list and the PGHDR_REUSE_UNLIKELY ** flag set. */ void sqlite3PcacheMove(PgHdr *p, Pgno newPgno){ assert( p->nRef>0 ); pcacheEnterMutex(); pcacheRemoveFromHash(p); p->pgno = newPgno; if( newPgno==0 ){ if( (p->flags & PGHDR_DIRTY) ){ pcacheMakeClean(p); } p->flags = PGHDR_REUSE_UNLIKELY; } pcacheAddToHash(p); pcacheExitMutex(); }