-C Avoid\sreevaluating\sWHERE\sand\sORDER\sBY\sexpressions\sthat\salias\sterms\sin\sthe\nresult\sset.\s\sTicket\s#3343.\s\sNote\sthat\saliased\sGROUP\sBY\sexpressions\sare\sstill\nevaluated\stwice.\s(CVS\s5637)
-D 2008-08-29T02:14:03
+C If\sa\spage\sis\smade\seligible\sfor\srecycling\swhen\smore\sthan\sthe\sconfigured\smaximum\snumber\sof\spages\sare\sallocated,\sfree\sit\simmediately\sinstead\sof\sadding\sit\sto\sthe\sLRU\slist.\s(CVS\s5638)
+D 2008-08-29T09:10:03
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
F Makefile.in 689e14735f862a5553bceef206d8c13e29504e44
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
F src/pager.c 032d11049af4ec49bdbaa3584e7ce9887098b66a
F src/pager.h 914103bb62dbcc3d8e9f14baec812d027264d457
F src/parse.y d0f76d2cb8d6883d5600dc20beb961a6022b94b8
-F src/pcache.c 4853068cb21ae742507186f8780b2eba33b734ff
-F src/pcache.h bd373ee3e4db310d6bbe7fa6d8d971de9678edd8
+F src/pcache.c e1cb0e77d2a299cfa4aa95d2e3307cc6900d2007
+F src/pcache.h 53730c33310cdf7a5c94e8333c853d59a3b30226
F src/pragma.c f5b271b090af7fcedd308d7c5807a5503f7a853d
F src/prepare.c c197041e0c4770672cda75e6bfe10242f885e510
F src/printf.c 785f87120589c1db672e37c6eb1087c456e6f84d
F src/status.c 8caa772cd9310bc297280f7cf0ede4d69ed5b801
F src/table.c 22744786199c9195720c15a7a42cb97b2e2728d8
F src/tclsqlite.c 420c7936d71f8318ea23b254c0d2cfc365135403
-F src/test1.c bca7922b1eb9e8ca6042651a6974f0e2ad022df7
+F src/test1.c e5781c664321fc10092dda13d6c3d02ae844566f
F src/test2.c eaa77124786649eedf47d3c5e94d8070c0da228f
F src/test3.c e85b7ce5c28c3ce7fbdbf7f98e1467b19786c62b
F src/test4.c 41056378671e7b00e6305fa9ac6fa27e6f96f406
F test/pager3.test 2323bf27fd5bd887b580247e5bce500ceee994b4
F test/pageropt.test 3ee6578891baaca967f0bd349e4abfa736229e1a
F test/pagesize.test 0d9ff3fedfce6e5ffe8fa7aca9b6d3433a2e843b
+F test/pcache.test a0fc9e965d039c4de24f9af929f9a25eb8be8539
F test/permutations.test e16bbd8cf443dd637317d9085b67bbdf91f21a1c
F test/pragma.test b55931bbd5dd543e56fd942dbf4b7439619b09a6
F test/pragma2.test 5364893491b9231dd170e3459bfc2e2342658b47
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 1dbced29de5f59ba2ebf877edcadf171540374d1
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
-P 83e6a75e7d70b4b01f0892924d7a8a49d5ef6bf2
-R f7b963f31369c623d2a04efc9a423904
-U drh
-Z 9a20437031aab1a22d3ddda0e55ea04f
+P ab0292caa5887cc1bdc0e8c9d3f3502b83975440
+R b8688b362830896e075bddc5ac84e1a4
+U danielk1977
+Z e3ebfdb580a05ecf955ac9f707aeb447
-ab0292caa5887cc1bdc0e8c9d3f3502b83975440
\ No newline at end of file
+4b12922dcb4547bf3a7276d0542b2e1d12ad338d
\ No newline at end of file
*************************************************************************
** This file implements that page cache.
**
-** @(#) $Id: pcache.c,v 1.23 2008/08/28 17:46:19 drh Exp $
+** @(#) $Id: pcache.c,v 1.24 2008/08/29 09:10:03 danielk1977 Exp $
*/
#include "sqliteInt.h"
if( (p->flags&PGHDR_DIRTY)==0 ){
pCache->nPinned--;
pcacheEnterMutex();
- pcacheAddToLruList(p);
+ if( pcache.nCurrentPage>pcache.nMaxPage ){
+ pcacheRemoveFromList(&pCache->pClean, p);
+ pcacheRemoveFromHash(p);
+ pcachePageFree(p);
+ }else{
+ pcacheAddToLruList(p);
+ }
pcacheExitMutex();
}else{
/* Move the page to the head of the caches dirty list. */
pcacheExitMutex();
}
+/*
+** If there are currently more than pcache.nMaxPage pages allocated, try
+** to recycle pages to reduce the number allocated to pcache.nMaxPage.
+*/
+static void pcacheEnforceMaxPage(){
+ PgHdr *p;
+ assert( sqlite3_mutex_held(pcache.mutex) );
+ while( pcache.nCurrentPage>pcache.nMaxPage && (p = pcacheRecyclePage()) ){
+ pcachePageFree(p);
+ }
+}
/*
** Close a cache.
if( pCache->bPurgeable ){
pcache.nMaxPage -= pCache->nMax;
pcache.nMinPage -= pCache->nMin;
+ pcacheEnforceMaxPage();
}
sqlite3_free(pCache->apHash);
-
pcacheExitMutex();
}
pcacheEnterMutex();
pcache.nMaxPage -= pCache->nMax;
pcache.nMaxPage += mxPage;
+ pcacheEnforceMaxPage();
pcacheExitMutex();
}
pCache->nMax = mxPage;
return nFree;
}
#endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */
+
+#ifdef SQLITE_TEST
+void sqlite3PcacheStats(
+ int *pnCurrent,
+ int *pnMax,
+ int *pnMin,
+ int *pnRecyclable
+){
+ PgHdr *p;
+ int nRecyclable = 0;
+ for(p=pcache.pLruHead; p; p=p->pNextLru){
+ nRecyclable++;
+ }
+
+ *pnCurrent = pcache.nCurrentPage;
+ *pnMax = pcache.nMaxPage;
+ *pnMin = pcache.nMinPage;
+ *pnRecyclable = nRecyclable;
+}
+#endif
+
** This header file defines the interface that the sqlite page cache
** subsystem.
**
-** @(#) $Id: pcache.h,v 1.8 2008/08/28 02:26:07 drh Exp $
+** @(#) $Id: pcache.h,v 1.9 2008/08/29 09:10:03 danielk1977 Exp $
*/
#ifndef _PCACHE_H_
/* Try to return memory used by the pcache module to the main memory heap */
int sqlite3PcacheReleaseMemory(int);
+void sqlite3PcacheStats(int*,int*,int*,int*);
+
#endif /* _PCACHE_H_ */
** is not included in the SQLite library. It is used for automated
** testing of the SQLite library.
**
-** $Id: test1.c,v 1.320 2008/08/27 15:21:34 drh Exp $
+** $Id: test1.c,v 1.321 2008/08/29 09:10:03 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
return TCL_OK;
}
+/*
+** tclcmd: pcache_stats
+*/
+static int test_pcache_stats(
+ 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 nMin;
+ int nMax;
+ int nCurrent;
+ int nRecyclable;
+ Tcl_Obj *pRet;
+
+ sqlite3PcacheStats(&nCurrent, &nMax, &nMin, &nRecyclable);
+
+ pRet = Tcl_NewObj();
+ Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("current", -1));
+ Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nCurrent));
+ Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("max", -1));
+ Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nMax));
+ Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("min", -1));
+ Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nMin));
+ Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("recyclable", -1));
+ Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nRecyclable));
+
+ Tcl_SetObjResult(interp, pRet);
+
+ return TCL_OK;
+}
+
/*
** Register commands with the TCL interpreter.
{ "sqlite3_blob_read", test_blob_read, 0 },
{ "sqlite3_blob_write", test_blob_write, 0 },
#endif
+ { "pcache_stats", test_pcache_stats, 0 },
};
static int bitmask_size = sizeof(Bitmask)*8;
int i;
--- /dev/null
+# 2008 August 29
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+#
+# This file is focused on testing the pcache module.
+#
+# $Id: pcache.test,v 1.1 2008/08/29 09:10:03 danielk1977 Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+
+# The pcache module limits the number of pages available to purgeable
+# caches to the sum of the 'cache_size' values for the set of open
+# caches. This block of tests, pcache-1.*, test that the library behaves
+# corrctly when it is forced to exceed this limit.
+#
+do_test pcache-1.1 {
+ db close
+ pcache_stats
+} {current 0 max 0 min 0 recyclable 0}
+
+do_test pcache-1.2 {
+ sqlite3 db test.db
+ execsql "PRAGMA cache_size=10"
+ pcache_stats
+} {current 1 max 10 min 10 recyclable 1}
+
+do_test pcache-1.3 {
+ execsql {
+ BEGIN;
+ CREATE TABLE t1(a, b, c);
+ CREATE TABLE t2(a, b, c);
+ CREATE TABLE t3(a, b, c);
+ CREATE TABLE t4(a, b, c);
+ CREATE TABLE t5(a, b, c);
+ }
+ pcache_stats
+} {current 6 max 10 min 10 recyclable 0}
+
+do_test pcache-1.4 {
+ execsql {
+ CREATE TABLE t6(a, b, c);
+ CREATE TABLE t7(a, b, c);
+ CREATE TABLE t8(a, b, c);
+ CREATE TABLE t9(a, b, c);
+ }
+ pcache_stats
+} {current 10 max 10 min 10 recyclable 0}
+
+do_test pcache-1.5 {
+ sqlite3 db2 test.db
+ execsql "PRAGMA cache_size=10" db2
+ pcache_stats
+} {current 11 max 20 min 20 recyclable 1}
+
+do_test pcache-1.6 {
+ execsql {
+ BEGIN;
+ SELECT * FROM sqlite_master;
+ } db2
+ pcache_stats
+} {current 11 max 20 min 20 recyclable 0}
+
+# At this point connection db2 has a read lock on the database file and a
+# single pinned page in its cache. Connection [db] is holding 10 dirty
+# pages. It cannot recycle them because of the read lock held by db2.
+#
+do_test pcache-1.6 {
+ execsql {
+ CREATE INDEX i1 ON t1(a, b);
+ CREATE INDEX i2 ON t2(a, b);
+ CREATE INDEX i3 ON t3(a, b);
+ CREATE INDEX i4 ON t4(a, b);
+ CREATE INDEX i5 ON t5(a, b);
+ CREATE INDEX i6 ON t6(a, b);
+ CREATE INDEX i7 ON t7(a, b);
+ CREATE INDEX i8 ON t8(a, b);
+ CREATE INDEX i9 ON t9(a, b);
+ }
+ pcache_stats
+} {current 20 max 20 min 20 recyclable 0}
+
+do_test pcache-1.7 {
+ execsql {
+ CREATE TABLE t10(a, b, c);
+ }
+ pcache_stats
+} {current 21 max 20 min 20 recyclable 0}
+
+# Rolling back the transaction held by db2 at this point releases a pinned
+# page. Because the number of allocated pages is greater than the
+# configured maximum, this page should be freed immediately instead of
+# recycled.
+#
+do_test pcache-1.8 {
+ execsql {ROLLBACK} db2
+ pcache_stats
+} {current 20 max 20 min 20 recyclable 0}
+
+do_test pcache-1.9 {
+ execsql COMMIT
+ pcache_stats
+} {current 20 max 20 min 20 recyclable 20}
+
+do_test pcache-1.10 {
+ db2 close
+ pcache_stats
+} {current 10 max 10 min 10 recyclable 10}
+
+do_test pcache-1.11 {
+ execsql { PRAGMA cache_size = 20 }
+ pcache_stats
+} {current 10 max 20 min 10 recyclable 10}
+
+do_test pcache-1.12 {
+ execsql {
+ SELECT * FROM t1 ORDER BY a; SELECT * FROM t1;
+ SELECT * FROM t2 ORDER BY a; SELECT * FROM t2;
+ SELECT * FROM t3 ORDER BY a; SELECT * FROM t3;
+ SELECT * FROM t4 ORDER BY a; SELECT * FROM t4;
+ SELECT * FROM t5 ORDER BY a; SELECT * FROM t5;
+ SELECT * FROM t6 ORDER BY a; SELECT * FROM t6;
+ SELECT * FROM t7 ORDER BY a; SELECT * FROM t7;
+ SELECT * FROM t8 ORDER BY a; SELECT * FROM t8;
+ SELECT * FROM t9 ORDER BY a; SELECT * FROM t9;
+ }
+ pcache_stats
+} {current 19 max 20 min 10 recyclable 19}
+
+do_test pcache-1.13 {
+ execsql { PRAGMA cache_size = 15 }
+ pcache_stats
+} {current 15 max 15 min 10 recyclable 15}
+
+finish_test
+