-C Update\sthe\sversion\snumber\sand\schange\scomments\sin\spreparation\sfor\sthe\nrelease\sof\s3.3.14.\s(CVS\s3789)
-D 2007-04-02T00:53:19
+C Fix\sa\sresource\sleak\sintroduced\sby\sthe\schange-counter\soptimisation.\sAlso\sadd\ssome\stest\scoverage.\s(CVS\s3790)
+D 2007-04-02T05:07:47
F Makefile.in 2f2c3bf69faf0ae7b8e8af4f94f1986849034530
F Makefile.linux-gcc 2d8574d1ba75f129aba2019f0b959db380a90935
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
F src/analyze.c 4bbf5ddf9680587c6d4917e02e378b6037be3651
F src/attach.c a16ada4a4654a0d126b8223ec9494ebb81bc5c3c
F src/auth.c 902f4722661c796b97f007d9606bd7529c02597f
-F src/btree.c 052d0306d66768ad4d5a54609d4464bdc2a17839
+F src/btree.c 48fa58f2d71edeab4a7d08157abe50a0b7a0e489
F src/btree.h 9b2cc0d113c0bc2d37d244b9a394d56948c9acbf
F src/build.c ad3374b5409554e504300f77e1fbc6b4c106a57f
F src/callback.c 31d22b4919c7645cbcbb1591ce2453e8c677c558
F src/os_unix.h 5768d56d28240d3fe4537fac08cc85e4fb52279e
F src/os_win.c c9a99524d6b2bdec636264cad1b67553925e3309
F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
-F src/pager.c 84072e9b5f370752176e5f7575557496bf239bc3
+F src/pager.c a73e3b06cf315bfa70d34d9d311d3395693eef87
F src/pager.h e79a24cf200b8771366217f5bca414f5b7823f42
F src/parse.y 207ab04273ae13aa4a729b96008d294d5f334ab3
F src/pragma.c 3b992b5b2640d6ae25cef05aa6a42cd1d6c43234
F src/table.c 6d0da66dde26ee75614ed8f584a1996467088d06
F src/tclsqlite.c a8d1166319db5d505b25ac6a9820162afe63fc8a
F src/test1.c 0f94df69cd8832799aafaf58f7e28b4527225a3e
-F src/test2.c 710a7252e22a8c690136a2b609e90fdad2697f35
+F src/test2.c 24458b17ab2f3c90cbc1c8446bd7ffe69be62f88
F src/test3.c 65f92247cf8592854e9bf5115b3fb711f8b33280
F src/test4.c 8b784cd82de158a2317cb4ac4bc86f91ad315e25
F src/test5.c 7162f8526affb771c4ed256826eee7bb9eca265f
F test/btree7.test a6d3b842db22af97dd14b989e90a2fd96066b72f
F test/btree8.test fadc112bcbd6a0c622d34c813fc8a648eacf8804
F test/busy.test 0271c854738e23ad76e10d4096a698e5af29d211
+F test/cache.test 02cd1d1b0e7ad59cf24b85d49d77705e33aa5224
F test/capi2.test 7ecc9b342cc9ec27b53bbf95724cf2e5874fd496
F test/capi3.test 1675323145d128e5942a9faffcfd5cf4e219a33f
F test/capi3b.test 5f0bc94b104e11086b1103b20277e1910f59c7f4
F test/malloc2.test 4ed7d719542c4570dec9c2ebe2bbdf3a9f3b0d05
F test/malloc3.test e965954b6f808876a63d3101fd70370320b509a7
F test/malloc4.test 59cd02f71b363302a04c4e77b97c0a1572eaa210
-F test/malloc5.test 7425272e263325fda7d32cb55706e52b5c09e7e0
+F test/malloc5.test 17a32bd72073741d539bb2a1307d712a316b89da
F test/malloc6.test 025ae0b78542e0ddd000d23f79d93e9be9ba0f15
F test/malloc7.test 1cf52834509eac7ebeb92105dacd4669f9ca9869
F test/manydb.test 8de36b8d33aab5ef295b11d9e95310aeded31af8
F test/misc4.test b043a05dea037cca5989f3ae09552fa16119bc80
F test/misc5.test c7d2d2a5a20dc37d3605a8067f0df5af2240122e
F test/misc6.test 3de55ec5cadf466ada587173faa5d6a4790a8bb7
-F test/misc7.test 8663e29f1a57c55321d4e6a8b2b9203d33254c69
+F test/misc7.test db026378fd83c9a318a9b5f5db5c17725db450d9
F test/misuse.test 30b3a458e5a70c31e74c291937b6c82204c59f33
F test/notnull.test 44d600f916b770def8b095a9962dbe3be5a70d82
F test/null.test 9503e1f63e959544c006d9f01709c5b5eab67d54
-F test/pager.test ceeef3caac4bf2046c6c06827f1a87dc1dec30f3
+F test/pager.test 3e12bef9c8512adb3f5db13d5745dc68fb4b92fc
F test/pager2.test c025f91b75fe65e85febda64d9416428b8a5cab5
F test/pager3.test 2323bf27fd5bd887b580247e5bce500ceee994b4
F test/pagesize.test 05c74ea49f790734ec1e9ab765d9bf1cce79b8f2
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
-P 18aec1ddfb08b74f0ef9cf1215eac7af71449db3
-R 1ba2c076c76000f21aa292bb0a8f72c4
-U drh
-Z ab035ae84bd6530ffbee25f61451be81
+P d9f6fdb72b29354921e6de40df5ed4f86b158a01
+R ac656430c79d0852aed9fac02cb5a8d8
+U danielk1977
+Z 6f28f4d19e867b11a92da6fb2f139223
-d9f6fdb72b29354921e6de40df5ed4f86b158a01
\ No newline at end of file
+ba0538a4977aefd6645554f1989f0a98b540b9cd
\ No newline at end of file
** May you share freely, never taking more than you give.
**
*************************************************************************
-** $Id: btree.c,v 1.349 2007/03/31 02:36:44 drh Exp $
+** $Id: btree.c,v 1.350 2007/04/02 05:07:47 danielk1977 Exp $
**
** This file implements a external (disk-based) database using BTrees.
** For a detailed discussion of BTrees, refer to
/*
** This routine is called prior to sqlite3PagerCommit when a transaction
** is commited for an auto-vacuum database.
+**
+** If SQLITE_OK is returned, then *pnTrunc is set to the number of pages
+** the database file should be truncated to during the commit process.
+** i.e. the database has been reorganized so that only the first *pnTrunc
+** pages are in use.
*/
-static int autoVacuumCommit(BtShared *pBt, Pgno *nTrunc){
+static int autoVacuumCommit(BtShared *pBt, Pgno *pnTrunc){
Pager *pPager = pBt->pPager;
Pgno nFreeList; /* Number of pages remaining on the free-list. */
int nPtrMap; /* Number of pointer-map pages deallocated */
*/
nFreeList = get4byte(&pBt->pPage1->aData[36]);
if( nFreeList==0 ){
- *nTrunc = 0;
+ *pnTrunc = 0;
return SQLITE_OK;
}
if( rc!=SQLITE_OK ) goto autovacuum_out;
put4byte(&pBt->pPage1->aData[32], 0);
put4byte(&pBt->pPage1->aData[36], 0);
- *nTrunc = finSize;
+ *pnTrunc = finSize;
assert( finSize!=PENDING_BYTE_PAGE(pBt) );
autovacuum_out:
** file simultaneously, or one process from reading the database while
** another is writing.
**
-** @(#) $Id: pager.c,v 1.313 2007/04/01 23:49:52 drh Exp $
+** @(#) $Id: pager.c,v 1.314 2007/04/02 05:07:47 danielk1977 Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
#include "sqliteInt.h"
** connected by pDirty pointers. The pPrevDirty pointers are
** corrupted by this sort.
*/
-#define N_SORT_BUCKET 25
+#define N_SORT_BUCKET_ALLOC 25
+#define N_SORT_BUCKET 25
+#ifdef SQLITE_TEST
+ int sqlite3_pager_n_sort_bucket = 0;
+ #undef N_SORT_BUCKET
+ #define N_SORT_BUCKET \
+ (sqlite3_pager_n_sort_bucket?sqlite3_pager_n_sort_bucket:N_SORT_BUCKET_ALLOC)
+#endif
static PgHdr *sort_pagelist(PgHdr *pIn){
- PgHdr *a[N_SORT_BUCKET], *p;
+ PgHdr *a[N_SORT_BUCKET_ALLOC], *p;
int i;
memset(a, 0, sizeof(a));
while( pIn ){
}
}
if( i==N_SORT_BUCKET-1 ){
+ /* Coverage: To get here, there need to be 2^(N_SORT_BUCKET)
+ ** elements in the input list. This is possible, but impractical.
+ ** Testing this line is the point of global variable
+ ** sqlite3_pager_n_sort_bucket.
+ */
a[i] = merge_pagelist(a[i], p);
}
}
/* Unlink the old page from the free list and the hash table
*/
unlinkPage(pPg);
- TEST_INCR(pPager->nOvfl);
+ if( pPg && pPg->pgno!=0 ){
+ TEST_INCR(pPager->nOvfl);
+ }
*ppPg = pPg;
return SQLITE_OK;
}
if( pPager->pAll ){
+ /* The shared-lock has just been acquired on the database file
+ ** and there are already pages in the cache (from a previous
+ ** read or write transaction). If the value of the change-counter
+ ** stored in Pager.iChangeCount matches that found on page 1 of
+ ** the database file, then no database changes have occured since
+ ** the cache was last valid and it is safe to retain the cached
+ ** pages. Otherwise, if Pager.iChangeCount does not match the
+ ** change-counter on page 1 of the file, the current cache contents
+ ** must be discarded.
+ */
+
PgHdr *pPage1 = pager_lookup(pPager, 1);
if( pPage1 ){
- unlinkHashChain(pPager, pPage1);
+ unlinkPage(pPage1);
+
+ assert( pPager->pFirst==pPager->pFirstSynced );
+ pPage1->pNextFree = pPager->pFirst;
+ if( pPager->pFirst ){
+ pPager->pFirst->pPrevFree = pPage1;
+ }else{
+ assert( !pPager->pLast );
+ pPager->pLast = pPage1;
+ }
+ pPager->pFirst = pPage1;
+ pPager->pFirstSynced = pPage1;
+
}
assert( !pager_lookup(pPager, 1) );
return rc;
}
+/*
+** Allocate or recycle space for a single page.
+*/
+static int pagerAllocatePage(Pager *pPager, PgHdr **ppPg){
+ int rc = SQLITE_OK;
+ PgHdr *pPg;
+
+ if( !(pPager->pFirstSynced && pPager->pFirstSynced->pgno==0) && (
+ pPager->nPage<pPager->mxPage || pPager->pFirst==0 || MEMDB ||
+ (pPager->pFirstSynced==0 && pPager->doNotSync)
+ ) ){
+ /* Create a new page */
+ if( pPager->nPage>=pPager->nHash ){
+ pager_resize_hash_table(pPager,
+ pPager->nHash<256 ? 256 : pPager->nHash*2);
+ if( pPager->nHash==0 ){
+ rc = SQLITE_NOMEM;
+ goto pager_allocate_out;
+ }
+ }
+ pPg = sqliteMallocRaw( sizeof(*pPg) + pPager->pageSize
+ + sizeof(u32) + pPager->nExtra
+ + MEMDB*sizeof(PgHistory) );
+ if( pPg==0 ){
+ rc = SQLITE_NOMEM;
+ goto pager_allocate_out;
+ }
+ memset(pPg, 0, sizeof(*pPg));
+ if( MEMDB ){
+ memset(PGHDR_TO_HIST(pPg, pPager), 0, sizeof(PgHistory));
+ }
+ pPg->pPager = pPager;
+ pPg->pNextAll = pPager->pAll;
+ pPager->pAll = pPg;
+ pPager->nPage++;
+ if( pPager->nPage>pPager->nMaxPage ){
+ assert( pPager->nMaxPage==(pPager->nPage-1) );
+ pPager->nMaxPage++;
+ }
+ }else{
+ /* Recycle an existing page with a zero ref-count. */
+ rc = pager_recycle(pPager, 1, &pPg);
+ if( rc!=SQLITE_OK ){
+ goto pager_allocate_out;
+ }
+ assert( pPager->state>=SHARED_LOCK );
+ assert(pPg);
+ }
+ *ppPg = pPg;
+
+pager_allocate_out:
+ return rc;
+}
+
/*
** Acquire a page.
**
int nMax;
int h;
TEST_INCR(pPager->nMiss);
- if( pPager->nPage<pPager->mxPage || pPager->pFirst==0 || MEMDB ||
- (pPager->pFirstSynced==0 && pPager->doNotSync)
- ){
- /* Create a new page */
- if( pPager->nPage>=pPager->nHash ){
- pager_resize_hash_table(pPager,
- pPager->nHash<256 ? 256 : pPager->nHash*2);
- if( pPager->nHash==0 ){
- return SQLITE_NOMEM;
- }
- }
- pPg = sqliteMallocRaw( sizeof(*pPg) + pPager->pageSize
- + sizeof(u32) + pPager->nExtra
- + MEMDB*sizeof(PgHistory) );
- if( pPg==0 ){
- return SQLITE_NOMEM;
- }
- memset(pPg, 0, sizeof(*pPg));
- if( MEMDB ){
- memset(PGHDR_TO_HIST(pPg, pPager), 0, sizeof(PgHistory));
- }
- pPg->pPager = pPager;
- pPg->pNextAll = pPager->pAll;
- pPager->pAll = pPg;
- pPager->nPage++;
- if( pPager->nPage>pPager->nMaxPage ){
- assert( pPager->nMaxPage==(pPager->nPage-1) );
- pPager->nMaxPage++;
- }
- }else{
- rc = pager_recycle(pPager, 1, &pPg);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- assert( pPager->state>=SHARED_LOCK );
- assert(pPg);
+ rc = pagerAllocatePage(pPager, &pPg);
+ if( rc!=SQLITE_OK ){
+ return rc;
}
+
pPg->pgno = pgno;
if( pPager->aInJournal && (int)pgno<=pPager->origDbSize ){
sqlite3CheckMemory(pPager->aInJournal, pgno/8);
** is not included in the SQLite library. It is used for automated
** testing of the SQLite library.
**
-** $Id: test2.c,v 1.42 2007/03/30 14:06:34 drh Exp $
+** $Id: test2.c,v 1.43 2007/04/02 05:07:47 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
extern int sqlite3_io_error_hit;
extern int sqlite3_diskfull_pending;
extern int sqlite3_diskfull;
+ extern int sqlite3_pager_n_sort_bucket;
static struct {
char *zName;
Tcl_CmdProc *xProc;
(char*)&sqlite3_pending_byte, TCL_LINK_INT);
Tcl_LinkVar(interp, "pager_pagesize",
(char*)&test_pagesize, TCL_LINK_INT);
+ Tcl_LinkVar(interp, "sqlite_pager_n_sort_bucket",
+ (char*)&sqlite3_pager_n_sort_bucket, TCL_LINK_INT);
return TCL_OK;
}
--- /dev/null
+# 2007 March 24
+#
+# 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.
+#
+#***********************************************************************
+#
+# $Id: cache.test,v 1.1 2007/04/02 05:07:48 danielk1977 Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+ifcapable {!pager_pragmas} {
+ finish_test
+ return
+}
+
+proc pager_cache_size {db} {
+ set bt [btree_from_db $db]
+ array set stats [btree_pager_stats $bt]
+ return $stats(page)
+}
+
+do_test cache-1.1 {
+ pager_cache_size db
+} {0}
+
+do_test cache-1.2 {
+ execsql {
+ CREATE TABLE abc(a, b, c);
+ INSERT INTO abc VALUES(1, 2, 3);
+ }
+ pager_cache_size db
+} {2}
+
+# At one point, repeatedly locking and unlocking the cache was causing
+# a resource leak of one page per repetition. The page wasn't actually
+# leaked, but would not be reused until the pager-cache was full (i.e.
+# 2000 pages by default).
+#
+# This tests that once the pager-cache is initialised, it can be locked
+# and unlocked repeatedly without internally allocating any new pages.
+#
+set cache_size [pager_cache_size db]
+for {set ii 0} {$ii < 10} {incr ii} {
+
+ do_test cache-1.3.$ii {
+ execsql {SELECT * FROM abc}
+ pager_cache_size db
+ } $::cache_size
+
+}
+
+finish_test
# 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.7 2006/01/19 08:43:32 danielk1977 Exp $
+# $Id: malloc5.test,v 1.8 2007/04/02 05:07:48 danielk1977 Exp $
#---------------------------------------------------------------------------
# NOTES ON EXPECTED BEHAVIOUR
do_test malloc5-1.5 {
# Manipulate the cache so that it contains two unused pages. One requires
# a journal-sync to free, the other does not.
+ db2 close
execsql {
SELECT * FROM abc;
CREATE TABLE def(d, e, f);
# Database should not be locked this time. The above test case only
# requested 500 bytes of memory, which can be obtained by freeing the page
# that does not require an fsync().
+ sqlite3 db2 test.db
catchsql {
SELECT * FROM abc;
} db2
do_test malloc5-1.7 {
# Release another 500 bytes of memory. This time we require a sync(),
# so the database file will be locked afterwards.
+ db2 close
sqlite3_release_memory 500
} $::pgalloc
do_test malloc5-1.8 {
+ sqlite3 db2 test.db
catchsql {
SELECT * FROM abc;
} db2
#***********************************************************************
# This file implements regression tests for SQLite library.
#
-# $Id: misc7.test,v 1.9 2007/03/31 10:00:49 danielk1977 Exp $
+# $Id: misc7.test,v 1.10 2007/04/02 05:07:48 danielk1977 Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
}
} {}
-# Test malloc failure whilst installing a foriegn key.
+# Test the UTF-16 version of the "out of memory" message (used when
+# malloc fails during sqlite3_open() ).
#
ifcapable utf16 {
do_test misc7-8 {
}
}
-
-
+sqlite3 db test.db
+set sqlite_pager_n_sort_bucket 4
+do_test misc7-17 {
+ execsql {
+ PRAGMA integrity_check;
+ VACUUM;
+ PRAGMA integrity_check;
+ }
+} {ok ok}
+set sqlite_pager_n_sort_bucket 0
finish_test
# This file implements regression tests for SQLite library. The
# focus of this script is page cache subsystem.
#
-# $Id: pager.test,v 1.26 2007/03/23 18:12:07 danielk1977 Exp $
+# $Id: pager.test,v 1.27 2007/04/02 05:07:48 danielk1977 Exp $
set testdir [file dirname $argv0]
} {1}
do_test pager-2.13 {
pager_stats $::p1
-} {ref 1 page 2 max 10 size 0 state 1 err 0 hit 1 miss 2 ovfl 0}
+} {ref 1 page 1 max 10 size 0 state 1 err 0 hit 1 miss 2 ovfl 0}
do_test pager-2.14 {
set v [catch {
page_write $::g1 "Page-One"
} {0 {}}
do_test pager-2.15 {
pager_stats $::p1
-} {ref 1 page 2 max 10 size 1 state 2 err 0 hit 1 miss 2 ovfl 0}
+} {ref 1 page 1 max 10 size 1 state 2 err 0 hit 1 miss 2 ovfl 0}
do_test pager-2.16 {
page_read $::g1
} {Page-One}
} {0 {}}
do_test pager-2.20 {
pager_stats $::p1
-} {ref 1 page 2 max 10 size -1 state 1 err 0 hit 2 miss 2 ovfl 0}
+} {ref 1 page 1 max 10 size -1 state 1 err 0 hit 2 miss 2 ovfl 0}
do_test pager-2.19 {
pager_pagecount $::p1
} {1}
do_test pager-2.21 {
pager_stats $::p1
-} {ref 1 page 2 max 10 size 1 state 1 err 0 hit 2 miss 2 ovfl 0}
+} {ref 1 page 1 max 10 size 1 state 1 err 0 hit 2 miss 2 ovfl 0}
do_test pager-2.22 {
page_unref $::g1
} {}
do_test pager-2.23 {
pager_stats $::p1
-} {ref 0 page 2 max 10 size -1 state 0 err 0 hit 2 miss 2 ovfl 0}
+} {ref 0 page 1 max 10 size -1 state 0 err 0 hit 2 miss 2 ovfl 0}
do_test pager-2.24 {
set v [catch {
page_get $::p1 1