]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
If a page is made eligible for recycling when more than the configured maximum number...
authordanielk1977 <danielk1977@noemail.net>
Fri, 29 Aug 2008 09:10:02 +0000 (09:10 +0000)
committerdanielk1977 <danielk1977@noemail.net>
Fri, 29 Aug 2008 09:10:02 +0000 (09:10 +0000)
FossilOrigin-Name: 4b12922dcb4547bf3a7276d0542b2e1d12ad338d

manifest
manifest.uuid
src/pcache.c
src/pcache.h
src/test1.c
test/pcache.test [new file with mode: 0644]

index cda16b2cf7fa84dd7e1b13fa89ee91384553beab..39dc294cdc634eccd428198896e2acf5a3d8e6d8 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-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
@@ -137,8 +137,8 @@ F src/os_win.c aefe9ee26430678a19a058a874e4e2bd91398142
 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
@@ -153,7 +153,7 @@ F src/sqliteLimit.h f435e728c6b620ef7312814d660a81f9356eb5c8
 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
@@ -445,6 +445,7 @@ F test/pager2.test 070983b89a308adaba525a2f9c1ba0592c72fa3d
 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
@@ -626,7 +627,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81
 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
index e6f959c8d478c1ba0dbc045ae4de42dc677f1bef..e9f6d7b7088075a62610c1b4ccdd19aec061d1d8 100644 (file)
@@ -1 +1 @@
-ab0292caa5887cc1bdc0e8c9d3f3502b83975440
\ No newline at end of file
+4b12922dcb4547bf3a7276d0542b2e1d12ad338d
\ No newline at end of file
index f0f5a964c6457b1b7453081c36c90ea3d8199107..552f6c772db20877621bc1a3b0098c533ed4407e 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** 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"
 
@@ -748,7 +748,13 @@ void sqlite3PcacheRelease(PgHdr *p){
     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. */
@@ -930,6 +936,17 @@ void sqlite3PcacheTruncate(PCache *pCache, Pgno pgno){
   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.
@@ -942,9 +959,9 @@ void sqlite3PcacheClose(PCache *pCache){
   if( pCache->bPurgeable ){
     pcache.nMaxPage -= pCache->nMax;
     pcache.nMinPage -= pCache->nMin;
+    pcacheEnforceMaxPage();
   }
   sqlite3_free(pCache->apHash);
-
   pcacheExitMutex();
 }
 
@@ -1193,6 +1210,7 @@ void sqlite3PcacheSetCachesize(PCache *pCache, int mxPage){
     pcacheEnterMutex();
     pcache.nMaxPage -= pCache->nMax;
     pcache.nMaxPage += mxPage;
+    pcacheEnforceMaxPage();
     pcacheExitMutex();
   }
   pCache->nMax = mxPage;
@@ -1222,3 +1240,24 @@ int sqlite3PcacheReleaseMemory(int nReq){
   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
+
index d3fd7a93310fd743e916e6546dcf54939824ab3f..f01e98b89cafe686e1a171129b428186aacc2cfe 100644 (file)
@@ -12,7 +12,7 @@
 ** 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_
@@ -161,4 +161,6 @@ void sqlite3PcacheSetCachesize(PCache *, int);
 /* 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_ */
index 7680e29f30148ae0cefd73657d8f18c30453ee39..e6bc2aa882ee577a60c26fb3e9c9af4b98f221c4 100644 (file)
@@ -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.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"
@@ -4501,6 +4501,38 @@ static int reset_prng_state(
   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.
@@ -4675,6 +4707,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
      { "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;
diff --git a/test/pcache.test b/test/pcache.test
new file mode 100644 (file)
index 0000000..1639823
--- /dev/null
@@ -0,0 +1,144 @@
+# 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
+