From 52622828ce62688382404e237179f188fc46b06d Mon Sep 17 00:00:00 2001 From: danielk1977 Date: Mon, 9 Jan 2006 09:59:49 +0000 Subject: [PATCH] Add a runtime interface to enable memory-management features. (CVS 2894) FossilOrigin-Name: 44f8e3139aa3ad3fcce9028565dd9ad23bbe62a2 --- manifest | 24 ++++++++++----------- manifest.uuid | 2 +- src/btree.c | 16 ++++++++++---- src/pager.c | 28 +++++++++++++++--------- src/sqlite.h.in | 53 +++++++++++++++++++++++++++++---------------- src/sqliteInt.h | 3 ++- src/test1.c | 55 +++++++++++++++++++++++++++++++---------------- src/util.c | 25 +++++++++++++++++++-- test/malloc5.test | 18 ++++++++++++++-- 9 files changed, 156 insertions(+), 68 deletions(-) diff --git a/manifest b/manifest index 3731476a62..3cbd082f4d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Rename\sDbSchema\sto\s"Schema"\sand\sSqliteTsd\sto\s"ThreadData".\s(CVS\s2893) -D 2006-01-09T06:29:48 +C Add\sa\sruntime\sinterface\sto\senable\smemory-management\sfeatures.\s(CVS\s2894) +D 2006-01-09T09:59:49 F Makefile.in c79fbdaa264c6afcd435f2fb492551de5a8cf80d F Makefile.linux-gcc aee18d8a05546dcf1888bd4547e442008a49a092 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028 @@ -34,7 +34,7 @@ F src/alter.c d0dd079b9ef0d551ff4a4ce09ee270c07b307bbb F src/analyze.c ed87abad3f6f60e1bd5308ed6ff6e0fa396db52b F src/attach.c 833e38b4fa6966de05fcf875c94cd521478a2811 F src/auth.c cdec356a5cd8b217c346f816c5912221537fe87f -F src/btree.c fc3f7f936b4f58c05ce95d710c1c15bb86cd522a +F src/btree.c 5e5dff4a667d93d49925d38de2d451a5bd1eabfd F src/btree.h 5663c4f43e8521546ccebc8fc95acb013b8f3184 F src/build.c e40a4caaba4afab3fc7f0866ca8766e8146dd62c F src/callback.c 79cfbac59139b525e3a195ee27b8be1ca06fbd38 @@ -59,7 +59,7 @@ F src/os_unix.c c5d1a3fe88ad93b5f6a29f1b5b889f2a756aaec0 F src/os_unix.h 5768d56d28240d3fe4537fac08cc85e4fb52279e F src/os_win.c 9cedcb13d6bcd4ab5f50907a99112f45cd335893 F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b -F src/pager.c f838695a6c0c8d0051ce7491036fd675052aa6f6 +F src/pager.c 6fbcc25f1f3fbe62cbbda3af3dbb9c3d758f8050 F src/pager.h e0acb095b3ad0bca48f2ab00c87346665643f64f F src/parse.y 83df51fea35f68f7e07384d75dce83d1ed30434c F src/pragma.c 7358baf8e2be14a0f3d71e7afae41e430d76b054 @@ -68,11 +68,11 @@ F src/printf.c f47a2f4b5387cd2ebb12e9117a1a5d6bd9a2b812 F src/random.c d40f8d356cecbd351ccfab6eaedd7ec1b54f5261 F src/select.c d97a43973d82a2e1e24be43ca5543c08b93e9e8d F src/shell.c 66b073375efbdee19045e7e0cd38b85f9aff71da -F src/sqlite.h.in ba3a29daa6a16e054191ccb384a981964e882a1d -F src/sqliteInt.h 9fed92df9ab1cccbe649c28e6d24685a1f3373a4 +F src/sqlite.h.in 537bac9e9ef703695268aaad5c56b6bf64f815be +F src/sqliteInt.h f9e4b620da09737e678271d45135088027d80307 F src/table.c 486dcfce532685b53b5a2b5da8bba0ded6fb2316 F src/tclsqlite.c 42151e6c78502277be77b88c00535d53ce89b917 -F src/test1.c 25e687fcc3c962958c5aa5114a74592cc5b7e6ba +F src/test1.c a526810f7d1c73b7b9a85621dd655d4357e0ae6d F src/test2.c ca74a1d8aeb7d9606e8f6b762c5daf85c1a3f92b F src/test3.c 9742aa146eb750cab81c1d5605286c3a0eb88054 F src/test4.c a8fd681e139e1c61f22a77d07fc3a99cb28fff3f @@ -82,7 +82,7 @@ F src/tokenize.c 196486012c871cdcad6cc84a820cc988603f1b9d F src/trigger.c c515afa5fe964e9854c54dc66dde179a90d0cfe3 F src/update.c 9a3761250c2ac9e6871f4e9c37560b224ba0067e F src/utf.c b7bffac4260177ae7f83c01d025fe0f5ed70ce71 -F src/util.c 9af2eab4203627982e433102be55b58dd38f8a38 +F src/util.c 0153015d99468e994a2c9bc6746262654ed5914a F src/vacuum.c f5a068096b22fad438bf1f1cf69ccb7f9e8cc7fb F src/vdbe.c ce31105fc91e1ea346e2383cd536149cc66c34bd F src/vdbe.h 8729a4ee16ff9aeab2af9667df3cf300ff978e13 @@ -186,7 +186,7 @@ F test/malloc.test 6245418d1b6635a2095d9ed0f5e84e029990da06 F test/malloc2.test e6e321db96d6c94cb18bf82ad7215070c41e624e F test/malloc3.test 9797d39eca7087a1022bcc0eb0b22215475c9698 F test/malloc4.test 2e29d155eb4b4808019ef47eeedfcbe9e09e0f05 -F test/malloc5.test 4ebf827a8173e1429480a6b276d37e89c6ab96f0 +F test/malloc5.test 1bac8c0dd98c387460920c1190f0996c5c62ea66 F test/manydb.test d81debbf5871242e3b5df1d3bb5e14c50431b6f8 F test/memdb.test 1860e060be810bf0775bc57408a5b7c4954bcaea F test/memleak.test df2b2b96e77f8ba159a332299535b1e5f18e49ac @@ -335,7 +335,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl a99cf5f6d8bd4d5537584a2b342f0fb9fa601d8b F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513 -P cc963f8cfc6c704c645c627bffb8df21dfebffc6 -R 7000da8baf46b4c1ff76e715121c7c17 +P 82b81f69c78cb3f54634d9aea4f6a838474dc5e5 +R bcf9f7930a1367ea3da4936a55af71d7 U danielk1977 -Z c505bc6b6a245c795a8be1eda400ccd9 +Z b19a6ec12413214a65f445404992c64a diff --git a/manifest.uuid b/manifest.uuid index 2394636257..f91a995d5f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -82b81f69c78cb3f54634d9aea4f6a838474dc5e5 \ No newline at end of file +44f8e3139aa3ad3fcce9028565dd9ad23bbe62a2 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 3ab5f5c001..df96325d95 100644 --- a/src/btree.c +++ b/src/btree.c @@ -9,7 +9,7 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* -** $Id: btree.c,v 1.287 2006/01/09 06:29:48 danielk1977 Exp $ +** $Id: btree.c,v 1.288 2006/01/09 09:59:49 danielk1977 Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to @@ -6504,11 +6504,19 @@ int sqlite3BtreeLockTable(Btree *p, int iTab, u8 isWriteLock){ ** Enable the shared pager and schema features. */ int sqlite3_enable_shared_cache(int enable){ - ThreadData *pTsd = sqlite3ThreadData(); - if( pTsd->pPager ){ + ThreadData *pTd = sqlite3ThreadData(); + + /* It is only legal to call sqlite3_enable_shared_cache() when there + ** are no currently open b-trees that were opened by the calling thread. + ** This condition is only easy to detect if the shared-cache were + ** previously enabled (and is being disabled). + */ + if( pTd->pBtree && !enable ){ + assert( pTd->useSharedData ); return SQLITE_MISUSE; } - pTsd->useSharedData = enable; + + pTd->useSharedData = enable; return SQLITE_OK; } #endif diff --git a/src/pager.c b/src/pager.c index 6b266c1e06..020477b358 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.232 2006/01/09 06:29:49 danielk1977 Exp $ +** @(#) $Id: pager.c,v 1.233 2006/01/09 09:59:49 danielk1977 Exp $ */ #ifndef SQLITE_OMIT_DISKIO #include "sqliteInt.h" @@ -1623,7 +1623,9 @@ int sqlite3pager_open( int useJournal = (flags & PAGER_OMIT_JOURNAL)==0; int noReadlock = (flags & PAGER_NO_READLOCK)!=0; char zTemp[SQLITE_TEMPNAME_SIZE]; +#ifndef SQLITE_OMIT_MEMORY_MANAGEMENT ThreadData *pTsd = sqlite3ThreadData(); +#endif /* If malloc() has already failed return SQLITE_NOMEM. Before even ** testing for this, set *ppPager to NULL so the caller knows the pager @@ -1723,8 +1725,12 @@ int sqlite3pager_open( pPager->pBusyHandler = 0; memset(pPager->aHash, 0, sizeof(pPager->aHash)); *ppPager = pPager; - pPager->pNext = pTsd->pPager; - pTsd->pPager = pPager; +#ifndef SQLITE_OMIT_MEMORY_MANAGEMENT + if( pTsd->useMemoryManagement ){ + pPager->pNext = pTsd->pPager; + pTsd->pPager = pPager; + } +#endif return SQLITE_OK; } @@ -2088,14 +2094,16 @@ int sqlite3pager_close(Pager *pPager){ #ifndef SQLITE_OMIT_MEMORY_MANAGEMENT /* Remove the pager from the linked list of pagers starting at - ** ThreadData.pPager. + ** ThreadData.pPager if memory-management is enabled. */ - if( pPager==pTsd->pPager ){ - pTsd->pPager = pPager->pNext; - }else{ - Pager *pTmp; - for(pTmp = pTsd->pPager; pTmp->pNext!=pPager; pTmp=pTmp->pNext); - pTmp->pNext = pPager->pNext; + if( pTsd->useMemoryManagement ){ + if( pPager==pTsd->pPager ){ + pTsd->pPager = pPager->pNext; + }else{ + Pager *pTmp; + for(pTmp = pTsd->pPager; pTmp->pNext!=pPager; pTmp=pTmp->pNext); + pTmp->pNext = pPager->pNext; + } } #endif diff --git a/src/sqlite.h.in b/src/sqlite.h.in index afcfe9fe69..5395ef7199 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.152 2005/12/30 16:28:02 danielk1977 Exp $ +** @(#) $Id: sqlite.h.in,v 1.153 2006/01/09 09:59:49 danielk1977 Exp $ */ #ifndef _SQLITE3_H_ #define _SQLITE3_H_ @@ -1276,21 +1276,6 @@ int sqlite3_get_autocommit(sqlite3*); */ sqlite3 *sqlite3_db_handle(sqlite3_stmt*); -/* -** Place a "soft" limit on the amount of heap memory that may be allocated by -** SQLite within the current thread. If an internal allocation is requested -** that would exceed the specified limit, sqlite3_release_memory() is invoked -** one or more times to free up some space before the allocation is made. -** -** The limit is called "soft", because if sqlite3_release_memory() cannot free -** sufficient memory to prevent the limit from being exceeded, the memory is -** allocated anyway and the current operation proceeds. -** -** This function is only available if the library was compiled without the -** SQLITE_OMIT_MEMORY_MANAGEMENT option set. -*/ -void sqlite3_soft_heap_limit(sqlite_int64); - /* ** Register a callback function with the database connection identified by the ** first argument to be invoked whenever a row is updated, inserted or deleted. @@ -1336,8 +1321,6 @@ void *sqlite3_update_hook( */ void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); -int sqlite3_release_memory(int); - /* ** This function is only available if the library is compiled without ** the SQLITE_OMIT_SHARED_CACHE macro defined. It is used to enable or @@ -1346,6 +1329,40 @@ int sqlite3_release_memory(int); */ int sqlite3_enable_shared_cache(int); +/* +** This function is only available if the library is compiled without +** the SQLITE_OMIT_MEMORY_MANAGEMENT macro defined. It is used to enable or +** disable (if the argument is true or false, respectively) the +** "memory management" features (accessed via the sqlite3_soft_heap_limit() +** and sqlite3_release_memory() APIs). +*/ +int sqlite3_enable_memory_management(int); + +/* +** Attempt to free N bytes of heap memory by deallocating non-essential +** memory allocations held by the database library (example: memory +** used to cache database pages to improve performance). +** +** This function is a no-op unless memory-management has been enabled. +*/ +int sqlite3_release_memory(int); + +/* +** Place a "soft" limit on the amount of heap memory that may be allocated by +** SQLite within the current thread. If an internal allocation is requested +** that would exceed the specified limit, sqlite3_release_memory() is invoked +** one or more times to free up some space before the allocation is made. +** +** The limit is called "soft", because if sqlite3_release_memory() cannot free +** sufficient memory to prevent the limit from being exceeded, the memory is +** allocated anyway and the current operation proceeds. +** +** This function is only available if the library was compiled without the +** SQLITE_OMIT_MEMORY_MANAGEMENT option set. It is a no-op unless +** memory-management has been enabled. +*/ +void sqlite3_soft_heap_limit(sqlite_int64); + /* ** 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 20af08b311..4ac590b942 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.454 2006/01/09 06:29:49 danielk1977 Exp $ +** @(#) $Id: sqliteInt.h,v 1.455 2006/01/09 09:59:49 danielk1977 Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -294,6 +294,7 @@ struct ThreadData { u8 disableReleaseMemory; /* True to make sqlite3_release_memory() a no-op */ #ifndef SQLITE_OMIT_MEMORY_MANAGEMENT + u8 useMemoryManagement; /* True if memory-management is enabled */ i64 nSoftHeapLimit; /* Suggested max mem allocation. No limit if <0 */ i64 nAlloc; /* Number of bytes currently allocated */ Pager *pPager; /* Linked list of all pagers in this thread */ diff --git a/src/test1.c b/src/test1.c index a58d711133..98b7802822 100644 --- a/src/test1.c +++ b/src/test1.c @@ -13,7 +13,7 @@ ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** -** $Id: test1.c,v 1.184 2006/01/09 06:29:49 danielk1977 Exp $ +** $Id: test1.c,v 1.185 2006/01/09 09:59:49 danielk1977 Exp $ */ #include "sqliteInt.h" #include "tcl.h" @@ -903,21 +903,16 @@ static int sqlite_malloc_outstanding( ){ extern int sqlite3OutstandingMallocs(Tcl_Interp *interp); - if( objc!=1 && objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "?-bytes?"); - return TCL_ERROR; - } - +#ifndef SQLITE_OMIT_MEMORY_MANAGEMENT if( objc==2 ){ + ThreadData *pTd = sqlite3ThreadData(); const char *zArg = Tcl_GetString(objv[1]); if( 0==strcmp(zArg, "-bytes") ){ - Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3ThreadData()->nAlloc)); -#ifndef SQLITE_OMIT_MEMORY_MANAGEMENT + Tcl_SetObjResult(interp, Tcl_NewIntObj(pTd->nAlloc)); }else if( 0==strcmp(zArg, "-maxbytes") ){ - Tcl_SetObjResult(interp, Tcl_NewWideIntObj(sqlite3ThreadData()->nMaxAlloc)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(pTd->nMaxAlloc)); }else if( 0==strcmp(zArg, "-clearmaxbytes") ){ - sqlite3ThreadData()->nMaxAlloc = sqlite3ThreadData()->nAlloc; -#endif + pTd->nMaxAlloc = pTd->nAlloc; }else{ Tcl_AppendResult(interp, "bad option \"", zArg, "\": must be -bytes, -maxbytes or -clearmaxbytes", 0 @@ -927,27 +922,46 @@ static int sqlite_malloc_outstanding( return TCL_OK; } +#endif + + if( objc!=1 ){ + Tcl_WrongNumArgs(interp, 1, objv, "?-bytes?"); + return TCL_ERROR; + } return sqlite3OutstandingMallocs(interp); } #endif /* -** Usage: sqlite3_enable_shared_cache BOOLEAN +** Usage: sqlite3_enable_shared_cache BOOLEAN +** Usage: sqlite3_enable_memory_management BOOLEAN ** */ -#ifndef SQLITE_OMIT_SHARED_CACHE -static int test_enable_shared_cache( - ClientData clientData, +#if !defined(SQLITE_OMIT_SHARED_CACHE)||!defined(SQLITE_OMIT_MEMORY_MANAGEMENT) +static int test_enable( + ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int objc, /* Number of arguments */ Tcl_Obj *CONST objv[] /* Command arguments */ ){ int rc; int enable; + int ret = 0; + int (*xFunc)(int) = (int(*)(int))clientData; ThreadData *pTsd = sqlite3ThreadData(); - Tcl_SetObjResult(interp, Tcl_NewBooleanObj(pTsd->useSharedData)); +#ifndef SQLITE_OMIT_SHARED_CACHE + if( xFunc==sqlite3_enable_shared_cache ){ + ret = pTsd->useSharedData; + }else +#endif +#ifndef SQLITE_OMIT_MEMORY_MANAGEMENT + { + assert( xFunc==sqlite3_enable_memory_management ); + ret = pTsd->useMemoryManagement; + } +#endif if( objc!=2 ){ Tcl_WrongNumArgs(interp, 1, objv, "BOOLEAN"); return TCL_ERROR; @@ -955,11 +969,12 @@ static int test_enable_shared_cache( if( Tcl_GetBooleanFromObj(interp, objv[1], &enable) ){ return TCL_ERROR; } - rc = sqlite3_enable_shared_cache(enable); + rc = xFunc(enable); if( rc!=SQLITE_OK ){ Tcl_SetResult(interp, (char *)sqlite3ErrStr(rc), TCL_STATIC); return TCL_ERROR; } + Tcl_SetObjResult(interp, Tcl_NewBooleanObj(ret)); return TCL_OK; } #endif @@ -3414,7 +3429,11 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ { "sqlite3_test_errstr", test_errstr, 0 }, { "tcl_variable_type", tcl_variable_type, 0 }, #ifndef SQLITE_OMIT_SHARED_CACHE - { "sqlite3_enable_shared_cache", test_enable_shared_cache, 0}, + { "sqlite3_enable_shared_cache", test_enable, sqlite3_enable_shared_cache}, +#endif +#ifndef SQLITE_OMIT_MEMORY_MANAGEMENT + { "sqlite3_enable_memory_management", test_enable, + sqlite3_enable_memory_management}, #endif }; static int bitmask_size = sizeof(Bitmask)*8; diff --git a/src/util.c b/src/util.c index f5e4c69a86..4732f23c9c 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.163 2006/01/09 06:29:49 danielk1977 Exp $ +** $Id: util.c,v 1.164 2006/01/09 09:59:49 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -529,7 +529,7 @@ static void handleSoftLimit(int n){ } } #else -#define handleSoftLimit() +#define handleSoftLimit(x) #endif /* @@ -1307,7 +1307,9 @@ void *sqlite3TextToPtr(const char *z){ ThreadData *sqlite3ThreadData(){ ThreadData *pTsd = sqlite3OsThreadSpecificData(sizeof(ThreadData)); if( pTsd && !pTsd->isInit ){ +#ifndef SQLITE_OMIT_MEMORY_MANAGEMENT pTsd->nSoftHeapLimit = -1; +#endif #ifndef NDEBUG pTsd->mallocAllowed = 1; #endif @@ -1324,6 +1326,25 @@ void sqlite3MallocClearFailed(){ sqlite3ThreadData()->mallocFailed = 0; } +#ifndef SQLITE_OMIT_MEMORY_MANAGEMENT +/* +** Enable the shared pager and schema features. +*/ +int sqlite3_enable_memory_management(int enable){ + ThreadData *pTsd = sqlite3ThreadData(); + + /* It is only legal to call sqlite3_enable_memory_management() when there + ** are no currently open connections that were opened by the calling + ** thread. This condition is only easy to detect if the feature were + ** previously enabled (and is being disabled). + */ + if( pTsd->pPager && !enable ){ + return SQLITE_MISUSE; + } + pTsd->useMemoryManagement = enable; + return SQLITE_OK; +} +#endif #ifndef NDEBUG /* diff --git a/test/malloc5.test b/test/malloc5.test index 2b38a160ed..e62ba12e90 100644 --- a/test/malloc5.test +++ b/test/malloc5.test @@ -12,15 +12,17 @@ # This file contains test cases focused on the two memory-management APIs, # sqlite3_soft_heap_limit() and sqlite3_release_memory(). # -# $Id: malloc5.test,v 1.4 2006/01/05 15:50:07 drh Exp $ +# $Id: malloc5.test,v 1.5 2006/01/09 09:59:49 danielk1977 Exp $ #--------------------------------------------------------------------------- # NOTES ON EXPECTED BEHAVIOUR # #--------------------------------------------------------------------------- + set testdir [file dirname $argv0] source $testdir/tester.tcl +db close # Only run these tests if memory debugging is turned on. if {[info command sqlite_malloc_stat]==""} { @@ -29,6 +31,15 @@ if {[info command sqlite_malloc_stat]==""} { return } +# Skip these tests if OMIT_MEMORY_MANAGEMENT was defined at compile time. +ifcapable !memorymanage { + finish_test + return +} + +sqlite3_enable_memory_management 1 +sqlite3 db test.db + do_test malloc5-1.1 { # Simplest possible test. Call sqlite3_release_memory when there is exactly # one unused page in a single pager cache. This test case set's the @@ -205,5 +216,8 @@ do_test malloc5-4.3 { # Restore the soft heap limit. sqlite3_soft_heap_limit $::soft_limit - finish_test + +catch {db close} +sqlite3_enable_memory_management 0 + -- 2.47.2