diff options
author | danielk1977 <danielk1977@noemail.net> | 2008-08-21 12:19:44 +0000 |
---|---|---|
committer | danielk1977 <danielk1977@noemail.net> | 2008-08-21 12:19:44 +0000 |
commit | 67e3da7ad43b63ff9efbb69565aae4ec87cf0941 (patch) | |
tree | e2b68d949e64099ab52787b7ba331ef9730062e3 /src/pcache.c | |
parent | 0d3c5d3239a658aaff40b86f5c5c7c2e64b21dc3 (diff) | |
download | sqlite-67e3da7ad43b63ff9efbb69565aae4ec87cf0941.tar.gz sqlite-67e3da7ad43b63ff9efbb69565aae4ec87cf0941.zip |
Fix the functionality associated with sqlite3_release_memory() and sqlite3_soft_heap_limit(). It is automatically disabled if the SQLITE_CONFIG_PAGECACHE option is used. (CVS 5576)
FossilOrigin-Name: d025866b09352b32a6d35b97144eaad2fafb7165
Diffstat (limited to 'src/pcache.c')
-rw-r--r-- | src/pcache.c | 137 |
1 files changed, 94 insertions, 43 deletions
diff --git a/src/pcache.c b/src/pcache.c index ffaa5e8f4..89fc85354 100644 --- a/src/pcache.c +++ b/src/pcache.c @@ -11,7 +11,7 @@ ************************************************************************* ** This file implements that page cache. ** -** @(#) $Id: pcache.c,v 1.3 2008/08/21 04:41:02 danielk1977 Exp $ +** @(#) $Id: pcache.c,v 1.4 2008/08/21 12:19:44 danielk1977 Exp $ */ #include "sqliteInt.h" @@ -331,7 +331,10 @@ void *pcacheMalloc(int sz){ sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, 1); return (void*)p; }else{ - void *p = sqlite3Malloc(sz); + void *p; + pcacheExitGlobal(); + p = sqlite3Malloc(sz); + pcacheEnterGlobal(); if( p ){ sz = sqlite3MallocSize(p); sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz); @@ -407,55 +410,47 @@ static void pcachePageFree(PgHdr *p){ } /* -** Obtain space for a page. Try to recycle an old page if the limit on the -** number of pages has been reached. If the limit has not been reached or -** there are no pages eligible for recycling, allocate a new page. -** -** Return a pointer to the new page, or NULL if an OOM condition occurs. +** Return the number of bytes that will be returned to the heap when +** the argument is passed to pcachePageFree(). */ -static PgHdr *pcacheRecycleOrAlloc(PCache *pCache){ - PgHdr *p = 0; +static int pcachePageSize(PgHdr *p){ + assert( sqlite3_mutex_held(pcache.mutex_lru) ); + assert( !pcache.pStart ); + assert( p->apSave[0]==0 ); + assert( p->apSave[1]==0 ); + assert( p && p->pCache ); + return sqlite3MallocSize(p); +} - int szPage = pCache->szPage; - int szExtra = pCache->szExtra; - int bPurg = pCache->bPurgeable; +static PgHdr *pcacheRecycle(PCache *pCache){ + PCache *pCsr; + PgHdr *p = 0; assert( pcache.isInit ); - assert( sqlite3_mutex_notheld(pcache.mutex_lru) ); + assert( sqlite3_mutex_held(pcache.mutex_lru) ); - pcacheEnterGlobal(); + if( !pcache.pLruTail && SQLITE_OK==sqlite3_mutex_try(pcache.mutex_mem2) ){ - if( (pcache.mxPage && pcache.nPage>=pcache.mxPage) - || (!pcache.mxPage && bPurg && pcache.nPurgeable>=pcache.mxPagePurgeable) - ){ - PCache *pCsr; - - /* If the above test succeeds, then a page will be obtained by recycling - ** an existing page. + /* Invoke xStress() callbacks until the LRU list contains at least one + ** page that can be reused or until the xStress() callback of all + ** caches has been invoked. */ - if( !pcache.pLruTail && SQLITE_OK==sqlite3_mutex_try(pcache.mutex_mem2) ){ - - /* Invoke xStress() callbacks until the LRU list contains at least one - ** page that can be reused or until the xStress() callback of all - ** caches has been invoked. - */ - for(pCsr=pcache.pAll; pCsr&&!pcache.pLruTail; pCsr=pCsr->pNextAll){ - assert( pCsr->iInUseMM==0 ); - pCsr->iInUseMM = 1; - if( pCsr->xStress && (pCsr->iInUseDB==0 || pCache==pCsr) ){ - pcacheExitGlobal(); - pCsr->xStress(pCsr->pStress); - pcacheEnterGlobal(); - } - pCsr->iInUseMM = 0; + for(pCsr=pcache.pAll; pCsr&&!pcache.pLruTail; pCsr=pCsr->pNextAll){ + assert( pCsr->iInUseMM==0 ); + pCsr->iInUseMM = 1; + if( pCsr->xStress && (pCsr->iInUseDB==0 || pCache==pCsr) ){ + pcacheExitGlobal(); + pCsr->xStress(pCsr->pStress); + pcacheEnterGlobal(); } - - sqlite3_mutex_leave(pcache.mutex_mem2); + pCsr->iInUseMM = 0; } - p = pcache.pLruTail; + sqlite3_mutex_leave(pcache.mutex_mem2); } + p = pcache.pLruTail; + if( p ){ pcacheRemoveFromLruList(p); pcacheRemoveFromHash(p); @@ -468,11 +463,41 @@ static PgHdr *pcacheRecycleOrAlloc(PCache *pCache){ assert(p->pPager); sqlite3PagerAlwaysRollback(p->pPager); } + } - if( p->pCache->szPage!=szPage || p->pCache->szExtra!=szExtra ){ - pcachePageFree(p); - p = 0; - } + return p; +} + +/* +** Obtain space for a page. Try to recycle an old page if the limit on the +** number of pages has been reached. If the limit has not been reached or +** there are no pages eligible for recycling, allocate a new page. +** +** Return a pointer to the new page, or NULL if an OOM condition occurs. +*/ +static PgHdr *pcacheRecycleOrAlloc(PCache *pCache){ + PgHdr *p = 0; + + int szPage = pCache->szPage; + int szExtra = pCache->szExtra; + int bPurg = pCache->bPurgeable; + + assert( pcache.isInit ); + assert( sqlite3_mutex_notheld(pcache.mutex_lru) ); + + pcacheEnterGlobal(); + + if( (pcache.mxPage && pcache.nPage>=pcache.mxPage) + || (!pcache.mxPage && bPurg && pcache.nPurgeable>=pcache.mxPagePurgeable) + ){ + /* If the above test succeeds, then try to obtain a buffer by recycling + ** an existing page. */ + p = pcacheRecycle(pCache); + } + + if( p && (p->pCache->szPage!=szPage || p->pCache->szExtra!=szExtra) ){ + pcachePageFree(p); + p = 0; } if( !p ){ @@ -1141,3 +1166,29 @@ void sqlite3PcacheUnlock(PCache *pCache){ pCache->iInUseDB--; assert( pCache->iInUseDB>=0 ); } + +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT +/* +** This function is called to free superfluous dynamically allocated memory +** held by the pager system. Memory in use by any SQLite pager allocated +** by the current thread may be sqlite3_free()ed. +** +** nReq is the number of bytes of memory required. Once this much has +** been released, the function returns. The return value is the total number +** of bytes of memory released. +*/ +int sqlite3PcacheReleaseMemory(int nReq){ + int nFree = 0; + if( pcache.pStart==0 ){ + PgHdr *p; + pcacheEnterGlobal(); + while( (nReq<0 || nFree<nReq) && (p=pcacheRecycle(0)) ){ + nFree += pcachePageSize(p); + pcachePageFree(p); + } + pcacheExitGlobal(); + } + return nFree; +} +#endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */ + |