more page cache
This commit is contained in:
parent
7248dc6868
commit
7184778c28
|
@ -65,10 +65,7 @@ struct PCache {
|
||||||
#if defined(SQLITE_DEBUG) && 0
|
#if defined(SQLITE_DEBUG) && 0
|
||||||
int sqlite3PcacheTrace = 2; /* 0: off 1: simple 2: cache dumps */
|
int sqlite3PcacheTrace = 2; /* 0: off 1: simple 2: cache dumps */
|
||||||
int sqlite3PcacheMxDump = 9999; /* Max cache entries for pcacheDump() */
|
int sqlite3PcacheMxDump = 9999; /* Max cache entries for pcacheDump() */
|
||||||
#define pcacheTrace(X) \
|
# define pcacheTrace(X) if(sqlite3PcacheTrace){sqlite3DebugPrintf X;}
|
||||||
if (sqlite3PcacheTrace) { \
|
|
||||||
sqlite3DebugPrintf X; \
|
|
||||||
}
|
|
||||||
void pcacheDump(PCache *pCache){
|
void pcacheDump(PCache *pCache){
|
||||||
int N;
|
int N;
|
||||||
int i, j;
|
int i, j;
|
||||||
|
@ -144,6 +141,7 @@ int sqlite3PcachePageSanity(PgHdr *pPg) {
|
||||||
}
|
}
|
||||||
#endif /* SQLITE_DEBUG */
|
#endif /* SQLITE_DEBUG */
|
||||||
|
|
||||||
|
|
||||||
/********************************** Linked List Management ********************/
|
/********************************** Linked List Management ********************/
|
||||||
|
|
||||||
/* Allowed values for second argument to pcacheManageDirtyList() */
|
/* Allowed values for second argument to pcacheManageDirtyList() */
|
||||||
|
@ -160,7 +158,9 @@ int sqlite3PcachePageSanity(PgHdr *pPg) {
|
||||||
static void pcacheManageDirtyList(PgHdr *pPage, u8 addRemove){
|
static void pcacheManageDirtyList(PgHdr *pPage, u8 addRemove){
|
||||||
PCache *p = pPage->pCache;
|
PCache *p = pPage->pCache;
|
||||||
|
|
||||||
pcacheTrace(("%p.DIRTYLIST.%s %d\n", p, addRemove == 1 ? "REMOVE" : addRemove == 2 ? "ADD" : "FRONT", pPage->pgno));
|
pcacheTrace(("%p.DIRTYLIST.%s %d\n", p,
|
||||||
|
addRemove==1 ? "REMOVE" : addRemove==2 ? "ADD" : "FRONT",
|
||||||
|
pPage->pgno));
|
||||||
if( addRemove & PCACHE_DIRTYLIST_REMOVE ){
|
if( addRemove & PCACHE_DIRTYLIST_REMOVE ){
|
||||||
assert( pPage->pDirtyNext || pPage==p->pDirtyTail );
|
assert( pPage->pDirtyNext || pPage==p->pDirtyTail );
|
||||||
assert( pPage->pDirtyPrev || pPage==p->pDirty );
|
assert( pPage->pDirtyPrev || pPage==p->pDirty );
|
||||||
|
@ -212,7 +212,8 @@ static void pcacheManageDirtyList(PgHdr *pPage, u8 addRemove) {
|
||||||
** optimization, as if pSynced points to a page with the NEED_SYNC
|
** optimization, as if pSynced points to a page with the NEED_SYNC
|
||||||
** flag set sqlite3PcacheFetchStress() searches through all newer
|
** flag set sqlite3PcacheFetchStress() searches through all newer
|
||||||
** entries of the dirty-list for a page with NEED_SYNC clear anyway. */
|
** entries of the dirty-list for a page with NEED_SYNC clear anyway. */
|
||||||
if (!p->pSynced && 0 == (pPage->flags & PGHDR_NEED_SYNC) /*OPTIMIZATION-IF-FALSE*/
|
if( !p->pSynced
|
||||||
|
&& 0==(pPage->flags&PGHDR_NEED_SYNC) /*OPTIMIZATION-IF-FALSE*/
|
||||||
){
|
){
|
||||||
p->pSynced = pPage;
|
p->pSynced = pPage;
|
||||||
}
|
}
|
||||||
|
@ -258,7 +259,9 @@ static int numberOfCachePages(PCache *p) {
|
||||||
** Initialize and shutdown the page cache subsystem. Neither of these
|
** Initialize and shutdown the page cache subsystem. Neither of these
|
||||||
** functions are threadsafe.
|
** functions are threadsafe.
|
||||||
*/
|
*/
|
||||||
int sqlite3PcacheInitialize(void) { return pcache2.xInit(pcache2.pArg); }
|
int sqlite3PcacheInitialize(void){
|
||||||
|
return pcache2.xInit(pcache2.pArg);
|
||||||
|
}
|
||||||
void sqlite3PcacheShutdown(void){
|
void sqlite3PcacheShutdown(void){
|
||||||
if( pcache2.xShutdown ){
|
if( pcache2.xShutdown ){
|
||||||
/* IMPLEMENTATION-OF: R-26000-56589 The xShutdown() method may be NULL. */
|
/* IMPLEMENTATION-OF: R-26000-56589 The xShutdown() method may be NULL. */
|
||||||
|
@ -283,7 +286,8 @@ int sqlite3PcacheSize(void) { return sizeof(PCache); }
|
||||||
** to this module, the extra space really ends up being the MemPage
|
** to this module, the extra space really ends up being the MemPage
|
||||||
** structure in the pager.
|
** structure in the pager.
|
||||||
*/
|
*/
|
||||||
int sqlite3PcacheOpen(int szPage, /* Size of every page */
|
int sqlite3PcacheOpen(
|
||||||
|
int szPage, /* Size of every page */
|
||||||
int szExtra, /* Extra space associated with each page */
|
int szExtra, /* Extra space associated with each page */
|
||||||
int bPurgeable, /* True if pages are on backing store */
|
int bPurgeable, /* True if pages are on backing store */
|
||||||
int (*xStress)(void*,PgHdr*),/* Call to try to make pages clean */
|
int (*xStress)(void*,PgHdr*),/* Call to try to make pages clean */
|
||||||
|
@ -312,7 +316,10 @@ int sqlite3PcacheSetPageSize(PCache *pCache, int szPage) {
|
||||||
assert( pCache->nRefSum==0 && pCache->pDirty==0 );
|
assert( pCache->nRefSum==0 && pCache->pDirty==0 );
|
||||||
if( pCache->szPage ){
|
if( pCache->szPage ){
|
||||||
sqlite3_pcache *pNew;
|
sqlite3_pcache *pNew;
|
||||||
pNew = pcache2.xCreate(szPage, pCache->szExtra + ROUND8(sizeof(PgHdr)), pCache->bPurgeable);
|
pNew = pcache2.xCreate(
|
||||||
|
szPage, pCache->szExtra + ROUND8(sizeof(PgHdr)),
|
||||||
|
pCache->bPurgeable
|
||||||
|
);
|
||||||
if( pNew==0 ) return SQLITE_NOMEM_BKPT;
|
if( pNew==0 ) return SQLITE_NOMEM_BKPT;
|
||||||
pcache2.xCachesize(pNew, numberOfCachePages(pCache));
|
pcache2.xCachesize(pNew, numberOfCachePages(pCache));
|
||||||
if( pCache->pCache ){
|
if( pCache->pCache ){
|
||||||
|
@ -322,7 +329,7 @@ int sqlite3PcacheSetPageSize(PCache *pCache, int szPage) {
|
||||||
pCache->szPage = szPage;
|
pCache->szPage = szPage;
|
||||||
pcacheTrace(("%p.PAGESIZE %d\n",pCache,szPage));
|
pcacheTrace(("%p.PAGESIZE %d\n",pCache,szPage));
|
||||||
}
|
}
|
||||||
return SQLITE_OK;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -349,7 +356,8 @@ int sqlite3PcacheSetPageSize(PCache *pCache, int szPage) {
|
||||||
** the stack on entry and pop them back off on exit, which saves a
|
** the stack on entry and pop them back off on exit, which saves a
|
||||||
** lot of pushing and popping.
|
** lot of pushing and popping.
|
||||||
*/
|
*/
|
||||||
sqlite3_pcache_page *sqlite3PcacheFetch(PCache *pCache, /* Obtain the page from this cache */
|
sqlite3_pcache_page *sqlite3PcacheFetch(
|
||||||
|
PCache *pCache, /* Obtain the page from this cache */
|
||||||
Pgno pgno, /* Page number to obtain */
|
Pgno pgno, /* Page number to obtain */
|
||||||
int createFlag /* If true, create page if it does not exist already */
|
int createFlag /* If true, create page if it does not exist already */
|
||||||
){
|
){
|
||||||
|
@ -373,7 +381,8 @@ sqlite3_pcache_page *sqlite3PcacheFetch(PCache *pCache, /* Obtain the page fr
|
||||||
assert( createFlag==0 || pCache->eCreate==eCreate );
|
assert( createFlag==0 || pCache->eCreate==eCreate );
|
||||||
assert( createFlag==0 || eCreate==1+(!pCache->bPurgeable||!pCache->pDirty) );
|
assert( createFlag==0 || eCreate==1+(!pCache->bPurgeable||!pCache->pDirty) );
|
||||||
pRes = pcache2.xFetch(pCache->pCache, pgno, eCreate);
|
pRes = pcache2.xFetch(pCache->pCache, pgno, eCreate);
|
||||||
pcacheTrace(("%p.FETCH %d%s (result: %p)\n", pCache, pgno, createFlag ? " create" : "", pRes));
|
pcacheTrace(("%p.FETCH %d%s (result: %p)\n",pCache,pgno,
|
||||||
|
createFlag?" create":"",pRes));
|
||||||
return pRes;
|
return pRes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -388,7 +397,8 @@ sqlite3_pcache_page *sqlite3PcacheFetch(PCache *pCache, /* Obtain the page fr
|
||||||
**
|
**
|
||||||
** This routine should be invoked only after sqlite3PcacheFetch() fails.
|
** This routine should be invoked only after sqlite3PcacheFetch() fails.
|
||||||
*/
|
*/
|
||||||
int sqlite3PcacheFetchStress(PCache * pCache, /* Obtain the page from this cache */
|
int sqlite3PcacheFetchStress(
|
||||||
|
PCache *pCache, /* Obtain the page from this cache */
|
||||||
Pgno pgno, /* Page number to obtain */
|
Pgno pgno, /* Page number to obtain */
|
||||||
sqlite3_pcache_page **ppPage /* Write result here */
|
sqlite3_pcache_page **ppPage /* Write result here */
|
||||||
){
|
){
|
||||||
|
@ -405,29 +415,33 @@ int sqlite3PcacheFetchStress(PCache * pCache, /* Obtain the page fr
|
||||||
** flag is currently referenced, then the following may leave pSynced
|
** flag is currently referenced, then the following may leave pSynced
|
||||||
** set incorrectly (pointing to other than the LRU page with NEED_SYNC
|
** set incorrectly (pointing to other than the LRU page with NEED_SYNC
|
||||||
** cleared). This is Ok, as pSynced is just an optimization. */
|
** cleared). This is Ok, as pSynced is just an optimization. */
|
||||||
for (pPg = pCache->pSynced; pPg && (pPg->nRef || (pPg->flags & PGHDR_NEED_SYNC)); pPg = pPg->pDirtyPrev)
|
for(pPg=pCache->pSynced;
|
||||||
;
|
pPg && (pPg->nRef || (pPg->flags&PGHDR_NEED_SYNC));
|
||||||
|
pPg=pPg->pDirtyPrev
|
||||||
|
);
|
||||||
pCache->pSynced = pPg;
|
pCache->pSynced = pPg;
|
||||||
if( !pPg ){
|
if( !pPg ){
|
||||||
for (pPg = pCache->pDirtyTail; pPg && pPg->nRef; pPg = pPg->pDirtyPrev)
|
for(pPg=pCache->pDirtyTail; pPg && pPg->nRef; pPg=pPg->pDirtyPrev);
|
||||||
;
|
|
||||||
}
|
}
|
||||||
if( pPg ){
|
if( pPg ){
|
||||||
int rc;
|
int rc;
|
||||||
#ifdef SQLITE_LOG_CACHE_SPILL
|
#ifdef SQLITE_LOG_CACHE_SPILL
|
||||||
sqlite3_log(SQLITE_FULL, "spill page %d making room for %d - cache used: %d/%d", pPg->pgno, pgno,
|
sqlite3_log(SQLITE_FULL,
|
||||||
pcache2.xPagecount(pCache->pCache), numberOfCachePages(pCache));
|
"spill page %d making room for %d - cache used: %d/%d",
|
||||||
|
pPg->pgno, pgno,
|
||||||
|
pcache2.xPagecount(pCache->pCache),
|
||||||
|
numberOfCachePages(pCache));
|
||||||
#endif
|
#endif
|
||||||
pcacheTrace(("%p.SPILL %d\n",pCache,pPg->pgno));
|
pcacheTrace(("%p.SPILL %d\n",pCache,pPg->pgno));
|
||||||
rc = pCache->xStress(pCache->pStress, pPg);
|
rc = pCache->xStress(pCache->pStress, pPg);
|
||||||
pcacheDump(pCache);
|
pcacheDump(pCache);
|
||||||
if (rc != SQLITE_OK && rc != SQLITE_BUSY) {
|
if( rc!=0 && rc!=SQLITE_BUSY ){
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*ppPage = pcache2.xFetch(pCache->pCache, pgno, 2);
|
*ppPage = pcache2.xFetch(pCache->pCache, pgno, 2);
|
||||||
return *ppPage == 0 ? SQLITE_NOMEM_BKPT : SQLITE_OK;
|
return *ppPage==0 ? SQLITE_NOMEM_BKPT : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -465,7 +479,8 @@ static SQLITE_NOINLINE PgHdr *pcacheFetchFinishWithInit(
|
||||||
** must be called after sqlite3PcacheFetch() in order to get a usable
|
** must be called after sqlite3PcacheFetch() in order to get a usable
|
||||||
** result.
|
** result.
|
||||||
*/
|
*/
|
||||||
PgHdr *sqlite3PcacheFetchFinish(PCache * pCache, /* Obtain the page from this cache */
|
PgHdr *sqlite3PcacheFetchFinish(
|
||||||
|
PCache *pCache, /* Obtain the page from this cache */
|
||||||
Pgno pgno, /* Page number obtained */
|
Pgno pgno, /* Page number obtained */
|
||||||
sqlite3_pcache_page *pPage /* Page obtained by prior PcacheFetch() call */
|
sqlite3_pcache_page *pPage /* Page obtained by prior PcacheFetch() call */
|
||||||
){
|
){
|
||||||
|
@ -662,7 +677,9 @@ void sqlite3PcacheClose(PCache *pCache) {
|
||||||
/*
|
/*
|
||||||
** Discard the contents of the cache.
|
** Discard the contents of the cache.
|
||||||
*/
|
*/
|
||||||
void sqlite3PcacheClear(PCache *pCache) { sqlite3PcacheTruncate(pCache, 0); }
|
void sqlite3PcacheClear(PCache *pCache){
|
||||||
|
sqlite3PcacheTruncate(pCache, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Merge two lists of pages connected by pDirty and in pgno order.
|
** Merge two lists of pages connected by pDirty and in pgno order.
|
||||||
|
@ -754,12 +771,16 @@ PgHdr *sqlite3PcacheDirtyList(PCache *pCache) {
|
||||||
** This is not the total number of pages referenced, but the sum of the
|
** This is not the total number of pages referenced, but the sum of the
|
||||||
** reference count for all pages.
|
** reference count for all pages.
|
||||||
*/
|
*/
|
||||||
int sqlite3PcacheRefCount(PCache *pCache) { return pCache->nRefSum; }
|
int sqlite3PcacheRefCount(PCache *pCache){
|
||||||
|
return pCache->nRefSum;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Return the number of references to the page supplied as an argument.
|
** Return the number of references to the page supplied as an argument.
|
||||||
*/
|
*/
|
||||||
int sqlite3PcachePageRefcount(PgHdr *p) { return p->nRef; }
|
int sqlite3PcachePageRefcount(PgHdr *p){
|
||||||
|
return p->nRef;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Return the total number of pages in the cache.
|
** Return the total number of pages in the cache.
|
||||||
|
@ -773,7 +794,9 @@ int sqlite3PcachePagecount(PCache *pCache) {
|
||||||
/*
|
/*
|
||||||
** Get the suggested cache-size value.
|
** Get the suggested cache-size value.
|
||||||
*/
|
*/
|
||||||
int sqlite3PcacheGetCachesize(PCache *pCache) { return numberOfCachePages(pCache); }
|
int sqlite3PcacheGetCachesize(PCache *pCache){
|
||||||
|
return numberOfCachePages(pCache);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -782,7 +805,8 @@ int sqlite3PcacheGetCachesize(PCache *pCache) { return numberOfCachePages(pCache
|
||||||
void sqlite3PcacheSetCachesize(PCache *pCache, int mxPage){
|
void sqlite3PcacheSetCachesize(PCache *pCache, int mxPage){
|
||||||
assert( pCache->pCache!=0 );
|
assert( pCache->pCache!=0 );
|
||||||
pCache->szCache = mxPage;
|
pCache->szCache = mxPage;
|
||||||
pcache2.xCachesize(pCache->pCache, numberOfCachePages(pCache));
|
pcache2.xCachesize(pCache->pCache,
|
||||||
|
numberOfCachePages(pCache));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -834,7 +858,9 @@ int sqlite3PCachePercentDirty(PCache *pCache) {
|
||||||
/*
|
/*
|
||||||
** Return true if there are one or more dirty pages in the cache. Else false.
|
** Return true if there are one or more dirty pages in the cache. Else false.
|
||||||
*/
|
*/
|
||||||
int sqlite3PCacheIsDirty(PCache *pCache) { return (pCache->pDirty != 0); }
|
int sqlite3PCacheIsDirty(PCache *pCache){
|
||||||
|
return (pCache->pDirty!=0);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG)
|
#if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG)
|
||||||
|
|
|
@ -145,7 +145,7 @@ struct PgHdr1 {
|
||||||
** SQLITE_MUTEX_STATIC_LRU.
|
** SQLITE_MUTEX_STATIC_LRU.
|
||||||
*/
|
*/
|
||||||
struct PGroup {
|
struct PGroup {
|
||||||
sqlite3_mutex *mutex; /* MUTEX_STATIC_LRU or NULL */
|
pthread_mutex_t mutex; /* MUTEX_STATIC_LRU or NULL */
|
||||||
unsigned int nMaxPage; /* Sum of nMax for purgeable caches */
|
unsigned int nMaxPage; /* Sum of nMax for purgeable caches */
|
||||||
unsigned int nMinPage; /* Sum of nMin for purgeable caches */
|
unsigned int nMinPage; /* Sum of nMin for purgeable caches */
|
||||||
unsigned int mxPinned; /* nMaxpage + 10 - nMinPage */
|
unsigned int mxPinned; /* nMaxpage + 10 - nMinPage */
|
||||||
|
@ -199,22 +199,6 @@ struct PgFreeslot {
|
||||||
PgFreeslot *pNext; /* Next free slot */
|
PgFreeslot *pNext; /* Next free slot */
|
||||||
};
|
};
|
||||||
|
|
||||||
sqlite3_pcache_methods2 pcache2 = {
|
|
||||||
1, /* iVersion */
|
|
||||||
0, /* pArg */
|
|
||||||
pcache1Init, /* xInit */
|
|
||||||
pcache1Shutdown, /* xShutdown */
|
|
||||||
pcache1Create, /* xCreate */
|
|
||||||
pcache1Cachesize, /* xCachesize */
|
|
||||||
pcache1Pagecount, /* xPagecount */
|
|
||||||
pcache1Fetch, /* xFetch */
|
|
||||||
pcache1Unpin, /* xUnpin */
|
|
||||||
pcache1Rekey, /* xRekey */
|
|
||||||
pcache1Truncate, /* xTruncate */
|
|
||||||
pcache1Destroy, /* xDestroy */
|
|
||||||
pcache1Shrink /* xShrink */
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Global data used by this cache.
|
** Global data used by this cache.
|
||||||
*/
|
*/
|
||||||
|
@ -234,7 +218,7 @@ static struct PCacheGlobal {
|
||||||
int nReserve; /* Try to keep nFreeSlot above this */
|
int nReserve; /* Try to keep nFreeSlot above this */
|
||||||
void *pStart, *pEnd; /* Bounds of global page cache memory */
|
void *pStart, *pEnd; /* Bounds of global page cache memory */
|
||||||
/* Above requires no mutex. Use mutex below for variable that follow. */
|
/* Above requires no mutex. Use mutex below for variable that follow. */
|
||||||
sqlite3_mutex *mutex; /* Mutex for accessing the following: */
|
pthread_mutex_t mutex; /* Mutex for accessing the following: */
|
||||||
PgFreeslot * pFree; /* Free page blocks */
|
PgFreeslot * pFree; /* Free page blocks */
|
||||||
int nFreeSlot; /* Number of unused pcache slots */
|
int nFreeSlot; /* Number of unused pcache slots */
|
||||||
/* The following value requires a mutex to change. We skip the mutex on
|
/* The following value requires a mutex to change. We skip the mutex on
|
||||||
|
@ -260,7 +244,6 @@ static struct PCacheGlobal {
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/******** Page Allocation/SQLITE_CONFIG_PCACHE Related Functions **************/
|
/******** Page Allocation/SQLITE_CONFIG_PCACHE Related Functions **************/
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** This function is called during initialization if a static buffer is
|
** This function is called during initialization if a static buffer is
|
||||||
** supplied to use for the page-cache by passing the SQLITE_CONFIG_PAGECACHE
|
** supplied to use for the page-cache by passing the SQLITE_CONFIG_PAGECACHE
|
||||||
|
@ -446,7 +429,9 @@ static PgHdr1 *pcache1AllocPage(PCache1 *pCache, int benignMalloc){
|
||||||
assert(pCache->pGroup == &pcache1.grp);
|
assert(pCache->pGroup == &pcache1.grp);
|
||||||
pcache1LeaveMutex(pCache->pGroup);
|
pcache1LeaveMutex(pCache->pGroup);
|
||||||
#endif
|
#endif
|
||||||
if( benignMalloc ){ sqlite3BeginBenignMalloc(); }
|
if (benignMalloc) {
|
||||||
|
sqlite3BeginBenignMalloc();
|
||||||
|
}
|
||||||
#ifdef SQLITE_PCACHE_SEPARATE_HEADER
|
#ifdef SQLITE_PCACHE_SEPARATE_HEADER
|
||||||
pPg = pcache1Alloc(pCache->szPage);
|
pPg = pcache1Alloc(pCache->szPage);
|
||||||
p = sqlite3Malloc(sizeof(PgHdr1) + pCache->szExtra);
|
p = sqlite3Malloc(sizeof(PgHdr1) + pCache->szExtra);
|
||||||
|
@ -458,7 +443,9 @@ static PgHdr1 *pcache1AllocPage(PCache1 *pCache, int benignMalloc){
|
||||||
#else
|
#else
|
||||||
pPg = pcache1Alloc(pCache->szAlloc);
|
pPg = pcache1Alloc(pCache->szAlloc);
|
||||||
#endif
|
#endif
|
||||||
if( benignMalloc ){ sqlite3EndBenignMalloc(); }
|
if (benignMalloc) {
|
||||||
|
sqlite3EndBenignMalloc();
|
||||||
|
}
|
||||||
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
|
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
|
||||||
pcache1EnterMutex(pCache->pGroup);
|
pcache1EnterMutex(pCache->pGroup);
|
||||||
#endif
|
#endif
|
||||||
|
@ -509,10 +496,7 @@ void *sqlite3PageMalloc(int sz){
|
||||||
/*
|
/*
|
||||||
** Free an allocated buffer obtained from sqlite3PageMalloc().
|
** Free an allocated buffer obtained from sqlite3PageMalloc().
|
||||||
*/
|
*/
|
||||||
void sqlite3PageFree(void *p){
|
void sqlite3PageFree(void *p) { pcache1Free(p); }
|
||||||
pcache1Free(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Return true if it desirable to avoid allocating a new page cache
|
** Return true if it desirable to avoid allocating a new page cache
|
||||||
|
@ -560,9 +544,13 @@ static void pcache1ResizeHash(PCache1 *p){
|
||||||
}
|
}
|
||||||
|
|
||||||
pcache1LeaveMutex(p->pGroup);
|
pcache1LeaveMutex(p->pGroup);
|
||||||
if( p->nHash ){ sqlite3BeginBenignMalloc(); }
|
if (p->nHash) {
|
||||||
|
sqlite3BeginBenignMalloc();
|
||||||
|
}
|
||||||
apNew = (PgHdr1 **)sqlite3MallocZero(sizeof(PgHdr1 *) * nNew);
|
apNew = (PgHdr1 **)sqlite3MallocZero(sizeof(PgHdr1 *) * nNew);
|
||||||
if( p->nHash ){ sqlite3EndBenignMalloc(); }
|
if (p->nHash) {
|
||||||
|
sqlite3EndBenignMalloc();
|
||||||
|
}
|
||||||
pcache1EnterMutex(p->pGroup);
|
pcache1EnterMutex(p->pGroup);
|
||||||
if (apNew) {
|
if (apNew) {
|
||||||
for (i = 0; i < p->nHash; i++) {
|
for (i = 0; i < p->nHash; i++) {
|
||||||
|
@ -605,7 +593,6 @@ static PgHdr1 *pcache1PinPage(PgHdr1 *pPage){
|
||||||
return pPage;
|
return pPage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Remove the page supplied as an argument from the hash table
|
** Remove the page supplied as an argument from the hash table
|
||||||
** (PCache1.apHash structure) that it is currently stored in.
|
** (PCache1.apHash structure) that it is currently stored in.
|
||||||
|
@ -620,7 +607,8 @@ static void pcache1RemoveFromHash(PgHdr1 *pPage, int freeFlag){
|
||||||
|
|
||||||
assert(sqlite3_mutex_held(pCache->pGroup->mutex));
|
assert(sqlite3_mutex_held(pCache->pGroup->mutex));
|
||||||
h = pPage->iKey % pCache->nHash;
|
h = pPage->iKey % pCache->nHash;
|
||||||
for(pp=&pCache->apHash[h]; (*pp)!=pPage; pp=&(*pp)->pNext);
|
for (pp = &pCache->apHash[h]; (*pp) != pPage; pp = &(*pp)->pNext)
|
||||||
|
;
|
||||||
*pp = (*pp)->pNext;
|
*pp = (*pp)->pNext;
|
||||||
|
|
||||||
pCache->nPage--;
|
pCache->nPage--;
|
||||||
|
@ -635,9 +623,7 @@ static void pcache1EnforceMaxPage(PCache1 *pCache){
|
||||||
PGroup *pGroup = pCache->pGroup;
|
PGroup *pGroup = pCache->pGroup;
|
||||||
PgHdr1 *p;
|
PgHdr1 *p;
|
||||||
assert(sqlite3_mutex_held(pGroup->mutex));
|
assert(sqlite3_mutex_held(pGroup->mutex));
|
||||||
while( pGroup->nPurgeable>pGroup->nMaxPage
|
while (pGroup->nPurgeable > pGroup->nMaxPage && (p = pGroup->lru.pLruPrev)->isAnchor == 0) {
|
||||||
&& (p=pGroup->lru.pLruPrev)->isAnchor==0
|
|
||||||
){
|
|
||||||
assert(p->pCache->pGroup == pGroup);
|
assert(p->pCache->pGroup == pGroup);
|
||||||
assert(PAGE_IS_UNPINNED(p));
|
assert(PAGE_IS_UNPINNED(p));
|
||||||
pcache1PinPage(p);
|
pcache1PinPage(p);
|
||||||
|
@ -656,8 +642,7 @@ static void pcache1EnforceMaxPage(PCache1 *pCache){
|
||||||
**
|
**
|
||||||
** The PCache mutex must be held when this function is called.
|
** The PCache mutex must be held when this function is called.
|
||||||
*/
|
*/
|
||||||
static void pcache1TruncateUnsafe(
|
static void pcache1TruncateUnsafe(PCache1 * pCache, /* The cache to truncate */
|
||||||
PCache1 *pCache, /* The cache to truncate */
|
|
||||||
unsigned int iLimit /* Drop pages with this pgno or larger */
|
unsigned int iLimit /* Drop pages with this pgno or larger */
|
||||||
) {
|
) {
|
||||||
TESTONLY(int nPage = 0;) /* To assert pCache->nPage is correct */
|
TESTONLY(int nPage = 0;) /* To assert pCache->nPage is correct */
|
||||||
|
@ -708,51 +693,44 @@ static void pcache1TruncateUnsafe(
|
||||||
** Implementation of the sqlite3_pcache.xInit method.
|
** Implementation of the sqlite3_pcache.xInit method.
|
||||||
*/
|
*/
|
||||||
static int pcache1Init(void *NotUsed) {
|
static int pcache1Init(void *NotUsed) {
|
||||||
UNUSED_PARAMETER(NotUsed);
|
|
||||||
assert(pcache1.isInit == 0);
|
assert(pcache1.isInit == 0);
|
||||||
memset(&pcache1, 0, sizeof(pcache1));
|
memset(&pcache1, 0, sizeof(pcache1));
|
||||||
|
|
||||||
|
// /*
|
||||||
|
// ** The pcache1.separateCache variable is true if each PCache has its own
|
||||||
|
// ** private PGroup (mode-1). pcache1.separateCache is false if the single
|
||||||
|
// ** PGroup in pcache1.grp is used for all page caches (mode-2).
|
||||||
|
// **
|
||||||
|
// ** * Always use a unified cache (mode-2) if ENABLE_MEMORY_MANAGEMENT
|
||||||
|
// **
|
||||||
|
// ** * Use a unified cache in single-threaded applications that have
|
||||||
|
// ** configured a start-time buffer for use as page-cache memory using
|
||||||
|
// ** sqlite3_config(SQLITE_CONFIG_PAGECACHE, pBuf, sz, N) with non-NULL
|
||||||
|
// ** pBuf argument.
|
||||||
|
// **
|
||||||
|
// ** * Otherwise use separate caches (mode-1)
|
||||||
|
// */
|
||||||
|
// #if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT)
|
||||||
|
// pcache1.separateCache = 0;
|
||||||
|
// #elif SQLITE_THREADSAFE
|
||||||
|
// pcache1.separateCache = sqlite3GlobalConfig.pPage==0
|
||||||
|
// || sqlite3GlobalConfig.bCoreMutex>0;
|
||||||
|
// #else
|
||||||
|
// pcache1.separateCache = sqlite3GlobalConfig.pPage==0;
|
||||||
|
// #endif
|
||||||
|
pcache1.separateCache = 1;
|
||||||
|
|
||||||
/*
|
pthread_mutex_init(&pcache1.grp.mutex, NULL);
|
||||||
** The pcache1.separateCache variable is true if each PCache has its own
|
pthread_mutex_init(&pcache1.mutex, NULL);
|
||||||
** private PGroup (mode-1). pcache1.separateCache is false if the single
|
|
||||||
** PGroup in pcache1.grp is used for all page caches (mode-2).
|
|
||||||
**
|
|
||||||
** * Always use a unified cache (mode-2) if ENABLE_MEMORY_MANAGEMENT
|
|
||||||
**
|
|
||||||
** * Use a unified cache in single-threaded applications that have
|
|
||||||
** configured a start-time buffer for use as page-cache memory using
|
|
||||||
** sqlite3_config(SQLITE_CONFIG_PAGECACHE, pBuf, sz, N) with non-NULL
|
|
||||||
** pBuf argument.
|
|
||||||
**
|
|
||||||
** * Otherwise use separate caches (mode-1)
|
|
||||||
*/
|
|
||||||
#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT)
|
|
||||||
pcache1.separateCache = 0;
|
|
||||||
#elif SQLITE_THREADSAFE
|
|
||||||
pcache1.separateCache = sqlite3GlobalConfig.pPage==0
|
|
||||||
|| sqlite3GlobalConfig.bCoreMutex>0;
|
|
||||||
#else
|
|
||||||
pcache1.separateCache = sqlite3GlobalConfig.pPage==0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if SQLITE_THREADSAFE
|
// if (pcache1.separateCache && sqlite3GlobalConfig.nPage != 0 && sqlite3GlobalConfig.pPage == 0) {
|
||||||
if( sqlite3GlobalConfig.bCoreMutex ){
|
// pcache1.nInitPage = sqlite3GlobalConfig.nPage;
|
||||||
pcache1.grp.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU);
|
// } else {
|
||||||
pcache1.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_PMEM);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if( pcache1.separateCache
|
|
||||||
&& sqlite3GlobalConfig.nPage!=0
|
|
||||||
&& sqlite3GlobalConfig.pPage==0
|
|
||||||
){
|
|
||||||
pcache1.nInitPage = sqlite3GlobalConfig.nPage;
|
|
||||||
}else{
|
|
||||||
pcache1.nInitPage = 0;
|
pcache1.nInitPage = 0;
|
||||||
}
|
// }
|
||||||
pcache1.grp.mxPinned = 10;
|
pcache1.grp.mxPinned = 10;
|
||||||
pcache1.isInit = 1;
|
pcache1.isInit = 1;
|
||||||
return SQLITE_OK;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -761,7 +739,6 @@ static int pcache1Init(void *NotUsed){
|
||||||
** not need to be freed.
|
** not need to be freed.
|
||||||
*/
|
*/
|
||||||
static void pcache1Shutdown(void *NotUsed) {
|
static void pcache1Shutdown(void *NotUsed) {
|
||||||
UNUSED_PARAMETER(NotUsed);
|
|
||||||
assert(pcache1.isInit != 0);
|
assert(pcache1.isInit != 0);
|
||||||
memset(&pcache1, 0, sizeof(pcache1));
|
memset(&pcache1, 0, sizeof(pcache1));
|
||||||
}
|
}
|
||||||
|
@ -875,7 +852,6 @@ static int pcache1Pagecount(sqlite3_pcache *p){
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Implement steps 3, 4, and 5 of the pcache1Fetch() algorithm described
|
** Implement steps 3, 4, and 5 of the pcache1Fetch() algorithm described
|
||||||
** in the header of the pcache1Fetch() procedure.
|
** in the header of the pcache1Fetch() procedure.
|
||||||
|
@ -884,11 +860,7 @@ static int pcache1Pagecount(sqlite3_pcache *p){
|
||||||
** usually not needed, and by avoiding the stack initialization required
|
** usually not needed, and by avoiding the stack initialization required
|
||||||
** for these steps, the main pcache1Fetch() procedure can run faster.
|
** for these steps, the main pcache1Fetch() procedure can run faster.
|
||||||
*/
|
*/
|
||||||
static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2(
|
static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2(PCache1 *pCache, unsigned int iKey, int createFlag) {
|
||||||
PCache1 *pCache,
|
|
||||||
unsigned int iKey,
|
|
||||||
int createFlag
|
|
||||||
){
|
|
||||||
unsigned int nPinned;
|
unsigned int nPinned;
|
||||||
PGroup * pGroup = pCache->pGroup;
|
PGroup * pGroup = pCache->pGroup;
|
||||||
PgHdr1 * pPage = 0;
|
PgHdr1 * pPage = 0;
|
||||||
|
@ -898,11 +870,8 @@ static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2(
|
||||||
nPinned = pCache->nPage - pCache->nRecyclable;
|
nPinned = pCache->nPage - pCache->nRecyclable;
|
||||||
assert(pGroup->mxPinned == pGroup->nMaxPage + 10 - pGroup->nMinPage);
|
assert(pGroup->mxPinned == pGroup->nMaxPage + 10 - pGroup->nMinPage);
|
||||||
assert(pCache->n90pct == pCache->nMax * 9 / 10);
|
assert(pCache->n90pct == pCache->nMax * 9 / 10);
|
||||||
if( createFlag==1 && (
|
if (createFlag == 1 && (nPinned >= pGroup->mxPinned || nPinned >= pCache->n90pct ||
|
||||||
nPinned>=pGroup->mxPinned
|
(pcache1UnderMemoryPressure(pCache) && pCache->nRecyclable < nPinned))) {
|
||||||
|| nPinned>=pCache->n90pct
|
|
||||||
|| (pcache1UnderMemoryPressure(pCache) && pCache->nRecyclable<nPinned)
|
|
||||||
)){
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -910,10 +879,8 @@ static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2(
|
||||||
assert(pCache->nHash > 0 && pCache->apHash);
|
assert(pCache->nHash > 0 && pCache->apHash);
|
||||||
|
|
||||||
/* Step 4. Try to recycle a page. */
|
/* Step 4. Try to recycle a page. */
|
||||||
if( pCache->bPurgeable
|
if (pCache->bPurgeable && !pGroup->lru.pLruPrev->isAnchor &&
|
||||||
&& !pGroup->lru.pLruPrev->isAnchor
|
((pCache->nPage + 1 >= pCache->nMax) || pcache1UnderMemoryPressure(pCache))) {
|
||||||
&& ((pCache->nPage+1>=pCache->nMax) || pcache1UnderMemoryPressure(pCache))
|
|
||||||
){
|
|
||||||
PCache1 *pOther;
|
PCache1 *pOther;
|
||||||
pPage = pGroup->lru.pLruPrev;
|
pPage = pGroup->lru.pLruPrev;
|
||||||
assert(PAGE_IS_UNPINNED(pPage));
|
assert(PAGE_IS_UNPINNED(pPage));
|
||||||
|
@ -1012,17 +979,15 @@ static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2(
|
||||||
** the common case where pGroup->mutex is NULL. The pcache1Fetch() wrapper
|
** the common case where pGroup->mutex is NULL. The pcache1Fetch() wrapper
|
||||||
** invokes the appropriate routine.
|
** invokes the appropriate routine.
|
||||||
*/
|
*/
|
||||||
static PgHdr1 *pcache1FetchNoMutex(
|
static PgHdr1 *pcache1FetchNoMutex(sqlite3_pcache *p, unsigned int iKey, int createFlag) {
|
||||||
sqlite3_pcache *p,
|
|
||||||
unsigned int iKey,
|
|
||||||
int createFlag
|
|
||||||
){
|
|
||||||
PCache1 *pCache = (PCache1 *)p;
|
PCache1 *pCache = (PCache1 *)p;
|
||||||
PgHdr1 * pPage = 0;
|
PgHdr1 * pPage = 0;
|
||||||
|
|
||||||
/* Step 1: Search the hash table for an existing entry. */
|
/* Step 1: Search the hash table for an existing entry. */
|
||||||
pPage = pCache->apHash[iKey % pCache->nHash];
|
pPage = pCache->apHash[iKey % pCache->nHash];
|
||||||
while( pPage && pPage->iKey!=iKey ){ pPage = pPage->pNext; }
|
while (pPage && pPage->iKey != iKey) {
|
||||||
|
pPage = pPage->pNext;
|
||||||
|
}
|
||||||
|
|
||||||
/* Step 2: If the page was found in the hash table, then return it.
|
/* Step 2: If the page was found in the hash table, then return it.
|
||||||
** If the page was not in the hash table and createFlag is 0, abort.
|
** If the page was not in the hash table and createFlag is 0, abort.
|
||||||
|
@ -1042,11 +1007,7 @@ static PgHdr1 *pcache1FetchNoMutex(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if PCACHE1_MIGHT_USE_GROUP_MUTEX
|
#if PCACHE1_MIGHT_USE_GROUP_MUTEX
|
||||||
static PgHdr1 *pcache1FetchWithMutex(
|
static PgHdr1 *pcache1FetchWithMutex(sqlite3_pcache *p, unsigned int iKey, int createFlag) {
|
||||||
sqlite3_pcache *p,
|
|
||||||
unsigned int iKey,
|
|
||||||
int createFlag
|
|
||||||
){
|
|
||||||
PCache1 *pCache = (PCache1 *)p;
|
PCache1 *pCache = (PCache1 *)p;
|
||||||
PgHdr1 * pPage;
|
PgHdr1 * pPage;
|
||||||
|
|
||||||
|
@ -1057,11 +1018,7 @@ static PgHdr1 *pcache1FetchWithMutex(
|
||||||
return pPage;
|
return pPage;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
static sqlite3_pcache_page *pcache1Fetch(
|
static sqlite3_pcache_page *pcache1Fetch(sqlite3_pcache *p, unsigned int iKey, int createFlag) {
|
||||||
sqlite3_pcache *p,
|
|
||||||
unsigned int iKey,
|
|
||||||
int createFlag
|
|
||||||
){
|
|
||||||
#if PCACHE1_MIGHT_USE_GROUP_MUTEX || defined(SQLITE_DEBUG)
|
#if PCACHE1_MIGHT_USE_GROUP_MUTEX || defined(SQLITE_DEBUG)
|
||||||
PCache1 *pCache = (PCache1 *)p;
|
PCache1 *pCache = (PCache1 *)p;
|
||||||
#endif
|
#endif
|
||||||
|
@ -1082,17 +1039,12 @@ static sqlite3_pcache_page *pcache1Fetch(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Implementation of the sqlite3_pcache.xUnpin method.
|
** Implementation of the sqlite3_pcache.xUnpin method.
|
||||||
**
|
**
|
||||||
** Mark a page as unpinned (eligible for asynchronous recycling).
|
** Mark a page as unpinned (eligible for asynchronous recycling).
|
||||||
*/
|
*/
|
||||||
static void pcache1Unpin(
|
static void pcache1Unpin(sqlite3_pcache *p, sqlite3_pcache_page *pPg, int reuseUnlikely) {
|
||||||
sqlite3_pcache *p,
|
|
||||||
sqlite3_pcache_page *pPg,
|
|
||||||
int reuseUnlikely
|
|
||||||
){
|
|
||||||
PCache1 *pCache = (PCache1 *)p;
|
PCache1 *pCache = (PCache1 *)p;
|
||||||
PgHdr1 * pPage = (PgHdr1 *)pPg;
|
PgHdr1 * pPage = (PgHdr1 *)pPg;
|
||||||
PGroup * pGroup = pCache->pGroup;
|
PGroup * pGroup = pCache->pGroup;
|
||||||
|
@ -1123,12 +1075,7 @@ static void pcache1Unpin(
|
||||||
/*
|
/*
|
||||||
** Implementation of the sqlite3_pcache.xRekey method.
|
** Implementation of the sqlite3_pcache.xRekey method.
|
||||||
*/
|
*/
|
||||||
static void pcache1Rekey(
|
static void pcache1Rekey(sqlite3_pcache *p, sqlite3_pcache_page *pPg, unsigned int iOld, unsigned int iNew) {
|
||||||
sqlite3_pcache *p,
|
|
||||||
sqlite3_pcache_page *pPg,
|
|
||||||
unsigned int iOld,
|
|
||||||
unsigned int iNew
|
|
||||||
){
|
|
||||||
PCache1 * pCache = (PCache1 *)p;
|
PCache1 * pCache = (PCache1 *)p;
|
||||||
PgHdr1 * pPage = (PgHdr1 *)pPg;
|
PgHdr1 * pPage = (PgHdr1 *)pPg;
|
||||||
PgHdr1 ** pp;
|
PgHdr1 ** pp;
|
||||||
|
@ -1196,30 +1143,6 @@ static void pcache1Destroy(sqlite3_pcache *p){
|
||||||
sqlite3_free(pCache);
|
sqlite3_free(pCache);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
** This function is called during initialization (sqlite3_initialize()) to
|
|
||||||
** install the default pluggable cache module, assuming the user has not
|
|
||||||
** already provided an alternative.
|
|
||||||
*/
|
|
||||||
void sqlite3PCacheSetDefault(void){
|
|
||||||
static const sqlite3_pcache_methods2 defaultMethods = {
|
|
||||||
1, /* iVersion */
|
|
||||||
0, /* pArg */
|
|
||||||
pcache1Init, /* xInit */
|
|
||||||
pcache1Shutdown, /* xShutdown */
|
|
||||||
pcache1Create, /* xCreate */
|
|
||||||
pcache1Cachesize, /* xCachesize */
|
|
||||||
pcache1Pagecount, /* xPagecount */
|
|
||||||
pcache1Fetch, /* xFetch */
|
|
||||||
pcache1Unpin, /* xUnpin */
|
|
||||||
pcache1Rekey, /* xRekey */
|
|
||||||
pcache1Truncate, /* xTruncate */
|
|
||||||
pcache1Destroy, /* xDestroy */
|
|
||||||
pcache1Shrink /* xShrink */
|
|
||||||
};
|
|
||||||
sqlite3_config(SQLITE_CONFIG_PCACHE2, &defaultMethods);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Return the size of the header on each page of this PCACHE implementation.
|
** Return the size of the header on each page of this PCACHE implementation.
|
||||||
*/
|
*/
|
||||||
|
@ -1229,9 +1152,7 @@ int sqlite3HeaderSizePcache1(void){ return ROUND8(sizeof(PgHdr1)); }
|
||||||
** Return the global mutex used by this PCACHE implementation. The
|
** Return the global mutex used by this PCACHE implementation. The
|
||||||
** sqlite3_status() routine needs access to this mutex.
|
** sqlite3_status() routine needs access to this mutex.
|
||||||
*/
|
*/
|
||||||
sqlite3_mutex *sqlite3Pcache1Mutex(void){
|
sqlite3_mutex *sqlite3Pcache1Mutex(void) { return pcache1.mutex; }
|
||||||
return pcache1.mutex;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
|
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
|
||||||
/*
|
/*
|
||||||
|
@ -1250,10 +1171,7 @@ int sqlite3PcacheReleaseMemory(int nReq){
|
||||||
if (sqlite3GlobalConfig.pPage == 0) {
|
if (sqlite3GlobalConfig.pPage == 0) {
|
||||||
PgHdr1 *p;
|
PgHdr1 *p;
|
||||||
pcache1EnterMutex(&pcache1.grp);
|
pcache1EnterMutex(&pcache1.grp);
|
||||||
while( (nReq<0 || nFree<nReq)
|
while ((nReq < 0 || nFree < nReq) && (p = pcache1.grp.lru.pLruPrev) != 0 && p->isAnchor == 0) {
|
||||||
&& (p=pcache1.grp.lru.pLruPrev)!=0
|
|
||||||
&& p->isAnchor==0
|
|
||||||
){
|
|
||||||
nFree += pcache1MemSize(p->page.pBuf);
|
nFree += pcache1MemSize(p->page.pBuf);
|
||||||
#ifdef SQLITE_PCACHE_SEPARATE_HEADER
|
#ifdef SQLITE_PCACHE_SEPARATE_HEADER
|
||||||
nFree += sqlite3MemSize(p);
|
nFree += sqlite3MemSize(p);
|
||||||
|
@ -1273,8 +1191,7 @@ int sqlite3PcacheReleaseMemory(int nReq){
|
||||||
** This function is used by test procedures to inspect the internal state
|
** This function is used by test procedures to inspect the internal state
|
||||||
** of the global cache.
|
** of the global cache.
|
||||||
*/
|
*/
|
||||||
void sqlite3PcacheStats(
|
void sqlite3PcacheStats(int *pnCurrent, /* OUT: Total number of pages cached */
|
||||||
int *pnCurrent, /* OUT: Total number of pages cached */
|
|
||||||
int *pnMax, /* OUT: Global maximum cache size */
|
int *pnMax, /* OUT: Global maximum cache size */
|
||||||
int *pnMin, /* OUT: Sum of PCache1.nMin for purgeable caches */
|
int *pnMin, /* OUT: Sum of PCache1.nMin for purgeable caches */
|
||||||
int *pnRecyclable /* OUT: Total number of pages available for recycling */
|
int *pnRecyclable /* OUT: Total number of pages available for recycling */
|
||||||
|
@ -1291,3 +1208,19 @@ void sqlite3PcacheStats(
|
||||||
*pnRecyclable = nRecyclable;
|
*pnRecyclable = nRecyclable;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
sqlite3_pcache_methods2 pcache2 = {
|
||||||
|
1, /* iVersion */
|
||||||
|
0, /* pArg */
|
||||||
|
pcache1Init, /* xInit */
|
||||||
|
pcache1Shutdown, /* xShutdown */
|
||||||
|
pcache1Create, /* xCreate */
|
||||||
|
pcache1Cachesize, /* xCachesize */
|
||||||
|
pcache1Pagecount, /* xPagecount */
|
||||||
|
pcache1Fetch, /* xFetch */
|
||||||
|
pcache1Unpin, /* xUnpin */
|
||||||
|
pcache1Rekey, /* xRekey */
|
||||||
|
pcache1Truncate, /* xTruncate */
|
||||||
|
pcache1Destroy, /* xDestroy */
|
||||||
|
pcache1Shrink /* xShrink */
|
||||||
|
};
|
||||||
|
|
|
@ -13,7 +13,10 @@
|
||||||
**
|
**
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <pthread.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#ifndef SQLITEINT_H
|
#ifndef SQLITEINT_H
|
||||||
#define SQLITEINT_H
|
#define SQLITEINT_H
|
||||||
|
@ -32,6 +35,10 @@ typedef struct sqlite3_pcache_page {
|
||||||
void *pExtra; /* Extra information associated with the page */
|
void *pExtra; /* Extra information associated with the page */
|
||||||
} sqlite3_pcache_page;
|
} sqlite3_pcache_page;
|
||||||
|
|
||||||
|
#define ROUNDDOWN8(x) ((x) & ~7)
|
||||||
|
|
||||||
|
#define ROUND8(x) (((x) + 7) & ~7)
|
||||||
|
|
||||||
typedef u32 Pgno;
|
typedef u32 Pgno;
|
||||||
|
|
||||||
typedef struct Pager Pager;
|
typedef struct Pager Pager;
|
||||||
|
|
Loading…
Reference in New Issue