mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-19 21:43:15 +03:00
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
This commit is contained in:
@@ -12,7 +12,7 @@
|
||||
**
|
||||
** Memory allocation functions used throughout sqlite.
|
||||
**
|
||||
** $Id: malloc.c,v 1.35 2008/08/20 14:49:24 danielk1977 Exp $
|
||||
** $Id: malloc.c,v 1.36 2008/08/21 12:19:44 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <stdarg.h>
|
||||
@@ -62,8 +62,11 @@ void sqlite3_soft_heap_limit(int n){
|
||||
*/
|
||||
int sqlite3_release_memory(int n){
|
||||
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
|
||||
int nRet = sqlite3VdbeReleaseMemory(n);
|
||||
nRet += sqlite3PagerReleaseMemory(n-nRet);
|
||||
int nRet = 0;
|
||||
#if 0
|
||||
nRet += sqlite3VdbeReleaseMemory(n);
|
||||
#endif
|
||||
nRet += sqlite3PcacheReleaseMemory(n-nRet);
|
||||
return nRet;
|
||||
#else
|
||||
return SQLITE_OK;
|
||||
|
||||
49
src/pager.c
49
src/pager.c
@@ -18,7 +18,7 @@
|
||||
** file simultaneously, or one process from reading the database while
|
||||
** another is writing.
|
||||
**
|
||||
** @(#) $Id: pager.c,v 1.472 2008/08/21 04:35:19 danielk1977 Exp $
|
||||
** @(#) $Id: pager.c,v 1.473 2008/08/21 12:19:44 danielk1977 Exp $
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_DISKIO
|
||||
#include "sqliteInt.h"
|
||||
@@ -2453,22 +2453,26 @@ static int pagerStress(void *p){
|
||||
PgHdr *pPg = sqlite3PcacheDirtyPage(pPager->pPCache);
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
if( pPg && pPager->errCode==SQLITE_OK ){
|
||||
if( pPg ){
|
||||
assert( pPg->flags&PGHDR_DIRTY );
|
||||
if( pPg->flags&PGHDR_NEED_SYNC ){
|
||||
rc = syncJournal(pPager);
|
||||
if( rc==SQLITE_OK && pPager->fullSync
|
||||
&& !(sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_SAFE_APPEND)
|
||||
){
|
||||
pPager->nRec = 0;
|
||||
rc = writeJournalHdr(pPager);
|
||||
if( pPager->errCode==SQLITE_OK ){
|
||||
if( pPg->flags&PGHDR_NEED_SYNC ){
|
||||
rc = syncJournal(pPager);
|
||||
if( rc==SQLITE_OK && pPager->fullSync &&
|
||||
!(sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_SAFE_APPEND)
|
||||
){
|
||||
pPager->nRec = 0;
|
||||
rc = writeJournalHdr(pPager);
|
||||
}
|
||||
}
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = pager_write_pagelist(pPg);
|
||||
}
|
||||
if( rc!=SQLITE_OK ){
|
||||
pager_error(pPager, rc);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = pager_write_pagelist(pPg);
|
||||
}
|
||||
if( rc!=SQLITE_OK ){
|
||||
pager_error(pPager, rc);
|
||||
}
|
||||
}else{
|
||||
sqlite3PcacheMakeClean(pPg);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
@@ -2523,21 +2527,6 @@ static int hasHotJournal(Pager *pPager, int *pExists){
|
||||
return rc;
|
||||
}
|
||||
|
||||
#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 sqlite3PagerReleaseMemory(int nReq){
|
||||
return 0;
|
||||
}
|
||||
#endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */
|
||||
|
||||
/*
|
||||
** Read the content of page pPg out of the database file.
|
||||
*/
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
** subsystem. The page cache subsystem reads and writes a file a page
|
||||
** at a time and provides a journal for rollback.
|
||||
**
|
||||
** @(#) $Id: pager.h,v 1.78 2008/08/20 14:49:25 danielk1977 Exp $
|
||||
** @(#) $Id: pager.h,v 1.79 2008/08/21 12:19:44 danielk1977 Exp $
|
||||
*/
|
||||
|
||||
#ifndef _PAGER_H_
|
||||
@@ -115,10 +115,6 @@ void *sqlite3PagerTempSpace(Pager*);
|
||||
int sqlite3PagerSync(Pager *pPager);
|
||||
void sqlite3PagerAlwaysRollback(Pager *pPager);
|
||||
|
||||
#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) && !defined(SQLITE_OMIT_DISKIO)
|
||||
int sqlite3PagerReleaseMemory(int);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_HAS_CODEC
|
||||
void sqlite3PagerSetCodec(Pager*,void*(*)(void*,void*,Pgno,int),void*);
|
||||
#endif
|
||||
|
||||
141
src/pcache.c
141
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);
|
||||
@@ -406,6 +409,65 @@ static void pcachePageFree(PgHdr *p){
|
||||
pcacheFree(p);
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the number of bytes that will be returned to the heap when
|
||||
** the argument is passed to pcachePageFree().
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
static PgHdr *pcacheRecycle(PCache *pCache){
|
||||
PCache *pCsr;
|
||||
PgHdr *p = 0;
|
||||
|
||||
assert( pcache.isInit );
|
||||
assert( sqlite3_mutex_held(pcache.mutex_lru) );
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
sqlite3_mutex_leave(pcache.mutex_mem2);
|
||||
}
|
||||
|
||||
p = pcache.pLruTail;
|
||||
|
||||
if( p ){
|
||||
pcacheRemoveFromLruList(p);
|
||||
pcacheRemoveFromHash(p);
|
||||
pcacheRemoveFromList(&p->pCache->pClean, p);
|
||||
|
||||
/* If the always-rollback flag is set on the page being recycled, set
|
||||
** the always-rollback flag on the corresponding pager.
|
||||
*/
|
||||
if( p->flags&PGHDR_ALWAYS_ROLLBACK ){
|
||||
assert(p->pPager);
|
||||
sqlite3PagerAlwaysRollback(p->pPager);
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
@@ -428,51 +490,14 @@ static PgHdr *pcacheRecycleOrAlloc(PCache *pCache){
|
||||
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.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
sqlite3_mutex_leave(pcache.mutex_mem2);
|
||||
}
|
||||
|
||||
p = pcache.pLruTail;
|
||||
/* If the above test succeeds, then try to obtain a buffer by recycling
|
||||
** an existing page. */
|
||||
p = pcacheRecycle(pCache);
|
||||
}
|
||||
|
||||
if( p ){
|
||||
pcacheRemoveFromLruList(p);
|
||||
pcacheRemoveFromHash(p);
|
||||
pcacheRemoveFromList(&p->pCache->pClean, p);
|
||||
|
||||
/* If the always-rollback flag is set on the page being recycled, set
|
||||
** the always-rollback flag on the corresponding pager.
|
||||
*/
|
||||
if( p->flags&PGHDR_ALWAYS_ROLLBACK ){
|
||||
assert(p->pPager);
|
||||
sqlite3PagerAlwaysRollback(p->pPager);
|
||||
}
|
||||
|
||||
if( p->pCache->szPage!=szPage || p->pCache->szExtra!=szExtra ){
|
||||
pcachePageFree(p);
|
||||
p = 0;
|
||||
}
|
||||
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 */
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
** This header file defines the interface that the sqlite page cache
|
||||
** subsystem.
|
||||
**
|
||||
** @(#) $Id: pcache.h,v 1.1 2008/08/20 14:49:25 danielk1977 Exp $
|
||||
** @(#) $Id: pcache.h,v 1.2 2008/08/21 12:19:44 danielk1977 Exp $
|
||||
*/
|
||||
|
||||
#ifndef _PCACHE_H_
|
||||
@@ -171,5 +171,7 @@ void sqlite3PcacheSetCachesize(PCache *, int);
|
||||
void sqlite3PcacheLock(PCache *);
|
||||
void sqlite3PcacheUnlock(PCache *);
|
||||
|
||||
int sqlite3PcacheReleaseMemory(int);
|
||||
|
||||
#endif /* _PCACHE_H_ */
|
||||
|
||||
|
||||
@@ -13,12 +13,12 @@
|
||||
** This file contains code use to implement APIs that are part of the
|
||||
** VDBE.
|
||||
**
|
||||
** $Id: vdbeapi.c,v 1.139 2008/08/11 18:44:58 drh Exp $
|
||||
** $Id: vdbeapi.c,v 1.140 2008/08/21 12:19:44 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "vdbeInt.h"
|
||||
|
||||
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
|
||||
#if 0 && defined(SQLITE_ENABLE_MEMORY_MANAGEMENT)
|
||||
/*
|
||||
** The following structure contains pointers to the end points of a
|
||||
** doubly-linked list of all compiled SQL statements that may be holding
|
||||
|
||||
Reference in New Issue
Block a user