diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/pager.c | 22 | ||||
-rw-r--r-- | src/pager.h | 3 | ||||
-rw-r--r-- | src/sqlite.h.in | 4 | ||||
-rw-r--r-- | src/sqliteInt.h | 3 | ||||
-rw-r--r-- | src/tclsqlite.c | 45 | ||||
-rw-r--r-- | src/util.c | 61 |
6 files changed, 93 insertions, 45 deletions
diff --git a/src/pager.c b/src/pager.c index 4ea0c4639..377ee017b 100644 --- a/src/pager.c +++ b/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.225 2005/12/18 08:51:23 danielk1977 Exp $ +** @(#) $Id: pager.c,v 1.226 2005/12/19 14:18:11 danielk1977 Exp $ */ #ifndef SQLITE_OMIT_DISKIO #include "sqliteInt.h" @@ -2323,7 +2323,7 @@ static int pager_recycle(Pager *pPager, int syncOk, PgHdr **ppPg){ ** very slow operation, so we work hard to avoid it. But sometimes ** it can't be helped. */ - if( pPg==0 && syncOk ){ + if( pPg==0 && pPager->pFirst && syncOk ){ int rc = syncJournal(pPager); if( rc!=0 ){ sqlite3pager_rollback(pPager); @@ -2393,12 +2393,14 @@ static int pager_recycle(Pager *pPager, int syncOk, PgHdr **ppPg){ ** by the current thread may be sqliteFree()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 +** been released, the function returns. A negative value for nReq means +** free as much memory as possible. The return value is the total number ** of bytes of memory released. */ +#ifndef SQLITE_OMIT_MEMORY_MANAGEMENT int sqlite3pager_release_memory(int nReq){ SqliteTsd *pTsd = sqlite3Tsd(); - Pager *pPager; + Pager *p; int nReleased = 0; int i; @@ -2411,7 +2413,7 @@ int sqlite3pager_release_memory(int nReq){ for(i=0; i==0 || i==1; i++){ /* Loop through all the SQLite pagers opened by the current thread. */ - for(pPager=pTsd->pPager; pPager && nReleased<nReq; pPager=pPager->pNext){ + for(p=pTsd->pPager; p && (nReq<0 || nReleased<nReq); p=p->pNext){ PgHdr *pPg; int rc; @@ -2419,7 +2421,7 @@ int sqlite3pager_release_memory(int nReq){ ** calling fsync() if this is the first iteration of the outermost ** loop). */ - while( SQLITE_OK==(rc = pager_recycle(pPager, i, &pPg)) && pPg) { + while( SQLITE_OK==(rc = pager_recycle(p, i, &pPg)) && pPg) { /* We've found a page to free. At this point the page has been ** removed from the page hash-table, free-list and synced-list ** (pFirstSynced). It is still in the all pages (pAll) list. @@ -2429,10 +2431,11 @@ int sqlite3pager_release_memory(int nReq){ ** probably is though. */ PgHdr *pTmp; - if( pPg==pPager->pAll ){ - pPager->pAll = pPg->pNextAll; + assert( pPg ); + if( pPg==p->pAll ){ + p->pAll = pPg->pNextAll; }else{ - for( pTmp=pPager->pAll; pTmp->pNextAll!=pPg; pTmp=pTmp->pNextAll ); + for( pTmp=p->pAll; pTmp->pNextAll!=pPg; pTmp=pTmp->pNextAll ); pTmp->pNextAll = pPg->pNextAll; } nReleased += sqliteAllocSize(pPg); @@ -2456,6 +2459,7 @@ int sqlite3pager_release_memory(int nReq){ return nReleased; } +#endif /* ** Acquire a page. diff --git a/src/pager.h b/src/pager.h index 64d6dbd5f..1d7069826 100644 --- a/src/pager.h +++ b/src/pager.h @@ -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.47 2005/12/18 08:51:24 danielk1977 Exp $ +** @(#) $Id: pager.h,v 1.48 2005/12/19 14:18:11 danielk1977 Exp $ */ #ifndef _PAGER_H_ @@ -108,6 +108,7 @@ int sqlite3pager_rename(Pager*, const char *zNewName); void sqlite3pager_set_codec(Pager*,void(*)(void*,void*,Pgno,int),void*); int sqlite3pager_movepage(Pager*,void*,Pgno); int sqlite3pager_reset(Pager*); +int sqlite3pager_release_memory(int); #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) int sqlite3pager_lockstate(Pager*); diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 7fb156077..845ff1e22 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -12,7 +12,7 @@ ** This header file defines the interface that the SQLite library ** presents to client programs. ** -** @(#) $Id: sqlite.h.in,v 1.149 2005/12/18 08:51:24 danielk1977 Exp $ +** @(#) $Id: sqlite.h.in,v 1.150 2005/12/19 14:18:11 danielk1977 Exp $ */ #ifndef _SQLITE3_H_ #define _SQLITE3_H_ @@ -1336,6 +1336,8 @@ void *sqlite3_update_hook( */ void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); +int sqlite3_release_memory(int); + /* ** Undo the hack that converts floating point types to integer for ** builds on processors without floating point support. diff --git a/src/sqliteInt.h b/src/sqliteInt.h index aa2a186f5..822b338b3 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.440 2005/12/18 08:51:24 danielk1977 Exp $ +** @(#) $Id: sqliteInt.h,v 1.441 2005/12/19 14:18:11 danielk1977 Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -272,7 +272,6 @@ typedef struct SqliteTsd SqliteTsd; struct SqliteTsd { int isInit; /* True if structure has been initialised */ int mallocFailed; /* True after a malloc() has failed */ - #ifndef SQLITE_OMIT_MEMORY_MANAGEMENT unsigned int nSoftHeapLimit; /* (uint)-1 for unlimited */ unsigned int nAlloc; /* Number of bytes currently allocated */ diff --git a/src/tclsqlite.c b/src/tclsqlite.c index 337cdefb4..7d1dc0348 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -11,7 +11,7 @@ ************************************************************************* ** A TCL Interface to SQLite ** -** $Id: tclsqlite.c,v 1.140 2005/12/16 06:54:03 danielk1977 Exp $ +** $Id: tclsqlite.c,v 1.141 2005/12/19 14:18:11 danielk1977 Exp $ */ #ifndef NO_TCL /* Omit this whole file if TCL is unavailable */ @@ -666,9 +666,9 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ "exists", "function", "last_insert_rowid", "nullvalue", "onecolumn", "profile", "progress", "rekey", "rollback_hook", - "soft_heap_limit", "timeout", "total_changes", - "trace", "transaction", "update_hook", - "version", 0 + "release_memory", "soft_heap_limit", "timeout", + "total_changes", "trace", "transaction", + "update_hook", "version", 0 }; enum DB_enum { DB_AUTHORIZER, DB_BUSY, DB_CACHE, @@ -678,9 +678,9 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ DB_EXISTS, DB_FUNCTION, DB_LAST_INSERT_ROWID, DB_NULLVALUE, DB_ONECOLUMN, DB_PROFILE, DB_PROGRESS, DB_REKEY, DB_ROLLBACK_HOOK, - DB_SOFT_HEAP_LIMIT, DB_TIMEOUT, DB_TOTAL_CHANGES, - DB_TRACE, DB_TRANSACTION, DB_UPDATE_HOOK, - DB_VERSION + DB_RELEASE_MEMORY, DB_SOFT_HEAP_LIMIT, DB_TIMEOUT, + DB_TOTAL_CHANGES, DB_TRACE, DB_TRANSACTION, + DB_UPDATE_HOOK, DB_VERSION }; /* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */ @@ -1754,9 +1754,10 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ ** $db soft_heap_limit N ** ** Set the soft-heap-limit for this thread. Note that the limit is - ** per-thread, not per-database. + ** per-thread, not per-database. An empty string is returned. */ case DB_SOFT_HEAP_LIMIT: { +#ifndef SQLITE_OMIT_MEMORY_MANAGEMENT int n; if( objc!=3 ){ Tcl_WrongNumArgs(interp, 2, objv, "BYTES"); @@ -1767,6 +1768,34 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ } sqlite3_soft_heap_limit(n); Tcl_ResetResult(interp); +#endif + break; + } + + /* + ** $db release_memory ?N? + ** + ** Try to release memory currently held (but not really required) by + ** SQLite database connections opened by the current thread. If an + ** integer argument is supplied, then SQLite stops trying to free memory + ** after N bytes have been freed. + ** + ** The value returned is the number of bytes actually freed. + **/ + case DB_RELEASE_MEMORY: { + int nRelease = 0; + int N = -1; + if( objc!=2 && objc!=3 ){ + Tcl_WrongNumArgs(interp, 2, objv, "?N?"); + return TCL_ERROR; + } +#ifndef SQLITE_OMIT_MEMORY_MANAGEMENT + if( objc==3 && TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &N) ){ + return TCL_ERROR; + } + nRelease = sqlite3_release_memory(N); +#endif + Tcl_SetObjResult(interp, Tcl_NewIntObj(nRelease)); break; } diff --git a/src/util.c b/src/util.c index 109f12fe5..360f27a33 100644 --- a/src/util.c +++ b/src/util.c @@ -14,7 +14,7 @@ ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** -** $Id: util.c,v 1.155 2005/12/18 08:51:24 danielk1977 Exp $ +** $Id: util.c,v 1.156 2005/12/19 14:18:11 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -35,7 +35,7 @@ ** sqlite3AllocSize() ** ** The function sqlite3FreeX performs the same task as sqlite3Free and is -** guaranteed to be a real function. +** guaranteed to be a real function. The same holds for sqlite3MallocX ** ** The above APIs are implemented in terms of the functions provided at the Os ** level (not in this file). The Os level interface is never accessed directly @@ -48,7 +48,8 @@ ** ** Functions sqlite3MallocRaw() and sqlite3Realloc() may invoke ** sqlite3_release_memory() if a call to sqlite3Os.xMalloc() or -** sqlite3Os.xRealloc() fails. Function sqlite3Malloc() usually invokes +** sqlite3Os.xRealloc() fails (or if the soft-heap-limit for the thread is +** exceeded). Function sqlite3Malloc() usually invokes ** sqlite3MallocRaw(). ** ** MALLOC TEST WRAPPER ARCHITECTURE @@ -63,11 +64,6 @@ ** * Audit outstanding memory allocations (i.e check for leaks). */ -/* -** TODO! -*/ -#define sqlite3_release_memory(x) 0 - #ifdef SQLITE_MEMDEBUG /*-------------------------------------------------------------------------- ** Begin code for memory allocation system test layer. @@ -156,6 +152,37 @@ const char *sqlite3_malloc_id = 0; TESTALLOC_STACKSIZE /* backtrace() stack */ \ ) + +#ifndef SQLITE_OMIT_MEMORY_MANAGEMENT +/* +** Set the soft heap-size limit for the current thread. +*/ +void sqlite3_soft_heap_limit(int n){ + unsigned int N; + if( n<0 ){ + /* No limit */ + N = 0xFFFFFFFF; + }else{ + N = n; + } + sqlite3Tsd()->nSoftHeapLimit = N; +} + +/* +** Release memory held by SQLite instances created by the current thread. +*/ +int sqlite3_release_memory(int n){ + return sqlite3pager_release_memory(n); +} +#else +/* If SQLITE_OMIT_MEMORY_MANAGEMENT is defined, then define a version +** of sqlite3_release_memory() to be used by other code in this file. +** This is done for no better reason than to reduce the number of +** pre-processor #ifndef statements. +*/ +#define sqlite3_release_memory(x) 0 /* 0 == no memory freed */ +#endif + /* ** For keeping track of the number of mallocs and frees. This ** is used to check for memory leaks. The iMallocFail and iMallocReset @@ -452,7 +479,8 @@ void OSMALLOC_FAILED(){ int OSSIZEOF(void *p){ if( p ){ - return sqlite3Os.xAllocationSize(p) - TESTALLOC_OVERHEAD; + u32 *pOs = (u32 *)getOsPointer(p); + return sqlite3Os.xAllocationSize(pOs) - TESTALLOC_OVERHEAD; } return 0; } @@ -1264,21 +1292,6 @@ void sqlite3MallocClearFailed(){ sqlite3Tsd()->mallocFailed = 0; } -#ifndef SQLITE_OMIT_MEMORY_MANAGEMENT -/* -** Set the soft heap-size limit for the current thread. -*/ -void sqlite3_soft_heap_limit(int n){ - unsigned int N; - if( n<0 ){ - /* No limit */ - N = 0xFFFFFFFF; - }else{ - N = n; - } - sqlite3Tsd()->nSoftHeapLimit = N; -} -#endif #ifndef NDEBUG /* |