From 67e3da7ad43b63ff9efbb69565aae4ec87cf0941 Mon Sep 17 00:00:00 2001 From: danielk1977 Date: Thu, 21 Aug 2008 12:19:44 +0000 Subject: [PATCH] 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 --- manifest | 24 ++++---- manifest.uuid | 2 +- src/malloc.c | 9 ++- src/pager.c | 49 +++++++--------- src/pager.h | 6 +- src/pcache.c | 141 ++++++++++++++++++++++++++++++++--------------- src/pcache.h | 4 +- src/vdbeapi.c | 4 +- test/mutex1.test | 7 +-- 9 files changed, 141 insertions(+), 105 deletions(-) diff --git a/manifest b/manifest index 31a97c523d..21f30fedad 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Move\san\sassert()\sin\ssqlite3PcacheDirtyPage()\sso\sthat\sit\sdoes\snot\soccur\sbefore\slocal\svariable\sdeclarations.\sTicket\s#3325.\s(CVS\s5575) -D 2008-08-21T04:41:02 +C Fix\sthe\sfunctionality\sassociated\swith\ssqlite3_release_memory()\sand\ssqlite3_soft_heap_limit().\sIt\sis\sautomatically\sdisabled\sif\sthe\sSQLITE_CONFIG_PAGECACHE\soption\sis\sused.\s(CVS\s5576) +D 2008-08-21T12:19:44 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.in 0b1c022000f55221454a7846022f11674d8024bf F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -116,7 +116,7 @@ F src/journal.c cffd2cd214e58c0e99c3ff632b3bee6c7cbb260e F src/legacy.c aac57bd984e666059011ea01ec4383892a253be3 F src/loadext.c eb1fe4f44d7c8ff53fc0c6a4388ab79fbd34cd64 F src/main.c aaf5af6ffe2c05f8ea4d75a850581a68ac529fa0 -F src/malloc.c 56918cddc4da7a0590eef4a2497e97b781f5c25f +F src/malloc.c 7ccc630b359f57a47b6034af54e42eb838eebd46 F src/md5.c 008216bbb5d34c6fbab5357aa68575ad8a31516a F src/mem1.c 3a7fe31d8290baa3bb203af72f7dfd6323966bcd F src/mem2.c 7256327b96927020824e06ffb3443b99a28da047 @@ -135,11 +135,11 @@ F src/os_common.h 24525d8b7bce66c374dfc1810a6c9043f3359b60 F src/os_os2.c 676ed273b17bd260f905df81375c9f9950d85517 F src/os_unix.c fe0dbc35bcd3de49e46b132abfc0f45d6dd6a864 F src/os_win.c aefe9ee26430678a19a058a874e4e2bd91398142 -F src/pager.c 08e257feabce0d2b3f9cba83915327e2f97a51a7 -F src/pager.h fb9376af5ba8e1eb78ee3b4f15eb0f60658ffd65 +F src/pager.c 3a4358c72c9c8415e8648001c776857e6952e2b4 +F src/pager.h 3778bea71dfb9658b6c94394e18db4a5b27e6ded F src/parse.y d0f76d2cb8d6883d5600dc20beb961a6022b94b8 -F src/pcache.c e244ef4b7019ce08b768b3e019f5c39585dc7a96 -F src/pcache.h 71ade7a84ed87d9d20507315260b1d91808d7c9a +F src/pcache.c 614f927e2e4e87d8a27379deefb2c0c7163e7d2f +F src/pcache.h aef1dedd7ff6186f27052a2509fff437a8906977 F src/pragma.c f5b271b090af7fcedd308d7c5807a5503f7a853d F src/prepare.c c197041e0c4770672cda75e6bfe10242f885e510 F src/printf.c 2e984b2507291a7e16d89dc9bb60582904f6247d @@ -189,7 +189,7 @@ F src/vacuum.c ef342828002debc97514617af3424aea8ef8522c F src/vdbe.c ae37f601426e01c4cdf6f650f465928bc18ad0c9 F src/vdbe.h 41c99aaad9167c1b5431993db446de74b2f71fc3 F src/vdbeInt.h b48c74d86a9fb62b707a3186ccca76bb32f1c6be -F src/vdbeapi.c f21971516880fd3a10821b2cdd0e64a5a63952c9 +F src/vdbeapi.c 3c98fbed9d4e10a4fbe09fce47e88ec567927a7b F src/vdbeaux.c 45a53a4459c01db4e6befc977952346bfef405c3 F src/vdbeblob.c f93110888ddc246215e9ba1f831d3d375bfd8355 F src/vdbefifo.c 20fda2a7c4c0bcee1b90eb7e545fefcdbf2e1de7 @@ -434,7 +434,7 @@ F test/misc5.test 6a5c1e3217a95b0db05ff9a0f1ecb5ce9043ffef F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91 F test/misc7.test fd424ff93a83bb6a31463eb043c588777d8215a8 F test/misuse.test 30b3a458e5a70c31e74c291937b6c82204c59f33 -F test/mutex1.test 3f7c86418b85404f5c5d921f5d8023684bb3ac49 +F test/mutex1.test ee9fb9c12d03eb2291ab500a3ce30bcad6fb46e8 F test/mutex2.test 56f282f436596e9febdc6e0db2c507432b6724bb F test/nan.test 14c41572ff52dbc740b1c3303dd313a90dc6084c F test/notnull.test 44d600f916b770def8b095a9962dbe3be5a70d82 @@ -623,7 +623,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81 F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 1dbced29de5f59ba2ebf877edcadf171540374d1 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e -P 5e9559c0490b9e0395e1da4d36bd33942350978c -R ffb9b74aabb8421663a6722de8981c79 +P 899fa19d1ab9c40a2ffc1c5170476292d0509e33 +R ad1e5ab4aaee003ca6f449d2a77708ca U danielk1977 -Z e689954593a083b11a089928219e4342 +Z a88d7d4ec4d431cb5810e83fa3ed8841 diff --git a/manifest.uuid b/manifest.uuid index 037df2ae1b..0f72819b4a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -899fa19d1ab9c40a2ffc1c5170476292d0509e33 \ No newline at end of file +d025866b09352b32a6d35b97144eaad2fafb7165 \ No newline at end of file diff --git a/src/malloc.c b/src/malloc.c index 663e44f1ff..a1727e6032 100644 --- a/src/malloc.c +++ b/src/malloc.c @@ -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 @@ -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; diff --git a/src/pager.c b/src/pager.c index 1c56a7a8f8..b9a71c0a0a 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.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. */ diff --git a/src/pager.h b/src/pager.h index d6a200b41f..356466c9c2 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.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 diff --git a/src/pcache.c b/src/pcache.c index ffaa5e8f4e..89fc85354f 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); @@ -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