Detect database file changes using a 128-bit segment of the file header
that includes the change counter. Ticket #2303. (CVS 3844) FossilOrigin-Name: e44995debf2456e55b502783849e93a045a527c8
This commit is contained in:
parent
9e4e6e502f
commit
86a88114fa
16
manifest
16
manifest
@ -1,5 +1,5 @@
|
||||
C Update\sthe\swhentouse.html\sdocument\sto\smention\sthat\sless\sbitmap\smemory\nis\sused\sfor\slarger\spage\ssizes.\s(CVS\s3843)
|
||||
D 2007-04-14T12:04:39
|
||||
C Detect\sdatabase\sfile\schanges\susing\sa\s128-bit\ssegment\sof\sthe\sfile\sheader\nthat\sincludes\sthe\schange\scounter.\s\sTicket\s#2303.\s(CVS\s3844)
|
||||
D 2007-04-16T15:02:19
|
||||
F Makefile.in 8cab54f7c9f5af8f22fd97ddf1ecfd1e1860de62
|
||||
F Makefile.linux-gcc 2d8574d1ba75f129aba2019f0b959db380a90935
|
||||
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
|
||||
@ -86,7 +86,7 @@ F src/os_unix.c 426b4c03c304ad78746d65d9ba101e0b72e18e23
|
||||
F src/os_unix.h 5768d56d28240d3fe4537fac08cc85e4fb52279e
|
||||
F src/os_win.c e94903c7dc1c0599c8ddce42efa0b6928068ddc5
|
||||
F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
|
||||
F src/pager.c 4fb7253edc2377b12f16fa33adffda79f070c1b4
|
||||
F src/pager.c 33c632ce9c228d87f14879a139fa123d43e4bf25
|
||||
F src/pager.h d652ddf092d2318d00e41f8539760fe8e57c157c
|
||||
F src/parse.y b6cfbadb6d5b21b5087d30698ee5af0ebb098767
|
||||
F src/pragma.c 3b992b5b2640d6ae25cef05aa6a42cd1d6c43234
|
||||
@ -204,7 +204,7 @@ F test/enc.test 7a03417a1051fe8bc6c7641cf4c8c3f7e0066d52
|
||||
F test/enc2.test 45710bacfa9df29720bc84c067dfdf8c8ddfb797
|
||||
F test/enc3.test 890508efff6677345e93bf2a8adb0489b30df030
|
||||
F test/exclusive.test 5bc520ba366ae3d242420af025ab64d465b04706
|
||||
F test/exclusive2.test dcb10d527722eb066ef7d060a0d47d7e59070d2e
|
||||
F test/exclusive2.test 6ef76efd3b442c95819446f8d15e6a63a1e95a4e
|
||||
F test/exclusive3.test 0e49c35b7e7cb8e7280b4ce3f0359d30b207d2ff
|
||||
F test/expr.test ab21e2fc3613595131efd7d8bbca4b95ed5cc608
|
||||
F test/filefmt.test 053b622009fbbb74dd37921ffad374d852c13cd8
|
||||
@ -316,7 +316,7 @@ F test/shared3.test 01e3e124dbb3859788aabc7cfb82f7ea04421749
|
||||
F test/shared_err.test cc528f6e78665787e93d9ce3a782a2ce5179d821
|
||||
F test/sort.test 0e4456e729e5a92a625907c63dcdedfbe72c5dc5
|
||||
F test/speed1.test 22e1b27af0683ed44dcd2f93ed817a9c3e65084a
|
||||
F test/speed2.test 9b93b93681f82f320caa4b2c9f15c0de4f3a3d33
|
||||
F test/speed2.test 53177056baf6556dcbdcf032bbdfc41c1aa74ded
|
||||
F test/subquery.test ae324ee928c5fb463a3ce08a8860d6e7f1ca5797
|
||||
F test/subselect.test 974e87f8fc91c5f00dd565316d396a5a6c3106c4
|
||||
F test/sync.test d05397b8f89f423dd6dba528692019ab036bc1c3
|
||||
@ -458,7 +458,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9
|
||||
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
||||
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
|
||||
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
|
||||
P cfc6f933dc60ca88ae848f7f0c402e820437c2ff
|
||||
R 28caddcdc5058b3369c1c52b75efe638
|
||||
P 2c8e2a5be34cdfe11ef22bd6f78ec0519f497392
|
||||
R 814512695981b3392256843a965db823
|
||||
U drh
|
||||
Z 5805ea2bb38918a004e8fa50c9627a61
|
||||
Z 2bdc95de39af6db85ea861709e0ec935
|
||||
|
@ -1 +1 @@
|
||||
2c8e2a5be34cdfe11ef22bd6f78ec0519f497392
|
||||
e44995debf2456e55b502783849e93a045a527c8
|
58
src/pager.c
58
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.328 2007/04/13 04:01:59 drh Exp $
|
||||
** @(#) $Id: pager.c,v 1.329 2007/04/16 15:02:19 drh Exp $
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_DISKIO
|
||||
#include "sqliteInt.h"
|
||||
@ -294,7 +294,7 @@ struct Pager {
|
||||
Pager *pNext; /* Linked list of pagers in this thread */
|
||||
#endif
|
||||
char *pTmpSpace; /* Pager.pageSize bytes of space for tmp use */
|
||||
u32 iChangeCount; /* Db change-counter for which cache is valid */
|
||||
char dbFileVers[16]; /* Changes whenever database file changes */
|
||||
};
|
||||
|
||||
/*
|
||||
@ -1131,12 +1131,14 @@ static int pager_playback_one_page(Pager *pPager, OsFile *jfd, int useCksum){
|
||||
#ifdef SQLITE_CHECK_PAGES
|
||||
pPg->pageHash = pager_pagehash(pPg);
|
||||
#endif
|
||||
CODEC1(pPager, pData, pPg->pgno, 3);
|
||||
|
||||
/* If this was page 1, then restore the value of Pager.iChangeCount */
|
||||
/* If this was page 1, then restore the value of Pager.dbFileVers.
|
||||
** Do this before any decoding. */
|
||||
if( pgno==1 ){
|
||||
pPager->iChangeCount = retrieve32bits(pPg, 24);
|
||||
memcpy(&pPager->dbFileVers, &((u8*)pData)[24],sizeof(pPager->dbFileVers));
|
||||
}
|
||||
|
||||
/* Decode the page just read from disk */
|
||||
CODEC1(pPager, pData, pPg->pgno, 3);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@ -2441,6 +2443,9 @@ static int pager_write_pagelist(PgHdr *pList){
|
||||
rc = sqlite3OsWrite(pPager->fd, pData, pPager->pageSize);
|
||||
PAGER_INCR(sqlite3_pager_writedb_count);
|
||||
PAGER_INCR(pPager->nWrite);
|
||||
if( pList->pgno==1 ){
|
||||
memcpy(&pPager->dbFileVers, &pData[24], sizeof(pPager->dbFileVers));
|
||||
}
|
||||
}
|
||||
#ifndef NDEBUG
|
||||
else{
|
||||
@ -2680,6 +2685,10 @@ static int readDbPage(Pager *pPager, PgHdr *pPg, Pgno pgno){
|
||||
PAGER_INCR(pPager->nRead);
|
||||
IOTRACE(("PGIN %p %d\n", pPager, pgno));
|
||||
PAGERTRACE3("FETCH %d page %d\n", PAGERID(pPager), pPg->pgno);
|
||||
if( pgno==1 ){
|
||||
memcpy(&pPager->dbFileVers, &((u8*)PGHDR_TO_DATA(pPg))[24],
|
||||
sizeof(pPager->dbFileVers));
|
||||
}
|
||||
CODEC1(pPager, PGHDR_TO_DATA(pPg), pPg->pgno, 3);
|
||||
return rc;
|
||||
}
|
||||
@ -2780,16 +2789,21 @@ static int pagerSharedLock(Pager *pPager){
|
||||
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.
|
||||
** read or write transaction). Check to see if the database
|
||||
** has been modified. If the database has changed, flush the
|
||||
** cache.
|
||||
**
|
||||
** Database changes is detected by looking at 15 bytes beginning
|
||||
** at offset 24 into the file. The first 4 of these 16 bytes are
|
||||
** a 32-bit counter that is incremented with each change. The
|
||||
** other bytes change randomly with each file change when
|
||||
** a codec is in use.
|
||||
**
|
||||
** There is a vanishingly small chance that a change will not be
|
||||
** deteched. The chance of an undetected change is so small that
|
||||
** it can be neglected.
|
||||
*/
|
||||
u8 zC[4];
|
||||
u32 iChangeCounter = 0;
|
||||
char dbFileVers[sizeof(pPager->dbFileVers)];
|
||||
sqlite3PagerPagecount(pPager);
|
||||
|
||||
if( pPager->errCode ){
|
||||
@ -2797,21 +2811,20 @@ static int pagerSharedLock(Pager *pPager){
|
||||
}
|
||||
|
||||
if( pPager->dbSize>0 ){
|
||||
/* Read the 4-byte change counter directly from the file. */
|
||||
rc = sqlite3OsSeek(pPager->fd, 24);
|
||||
if( rc!=SQLITE_OK ){
|
||||
return rc;
|
||||
}
|
||||
rc = sqlite3OsRead(pPager->fd, zC, 4);
|
||||
rc = sqlite3OsRead(pPager->fd, &dbFileVers, sizeof(dbFileVers));
|
||||
if( rc!=SQLITE_OK ){
|
||||
return rc;
|
||||
}
|
||||
iChangeCounter = (zC[0]<<24) + (zC[1]<<16) + (zC[2]<<8) + zC[3];
|
||||
}else{
|
||||
memset(dbFileVers, 0, sizeof(dbFileVers));
|
||||
}
|
||||
|
||||
if( iChangeCounter!=pPager->iChangeCount ){
|
||||
if( memcmp(pPager->dbFileVers, dbFileVers, sizeof(dbFileVers))!=0 ){
|
||||
pager_reset(pPager);
|
||||
pPager->iChangeCount = iChangeCounter;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3029,10 +3042,6 @@ int sqlite3PagerAcquire(
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
/* If this was page 1, then restore the value of Pager.iChangeCount */
|
||||
if( pgno==1 ){
|
||||
pPager->iChangeCount = retrieve32bits(pPg, 24);
|
||||
}
|
||||
|
||||
/* Link the page into the page hash table */
|
||||
h = pgno & (pPager->nHash-1);
|
||||
@ -3722,7 +3731,6 @@ static int pager_incr_changecounter(Pager *pPager){
|
||||
/* Increment the value just read and write it back to byte 24. */
|
||||
change_counter++;
|
||||
put32bits(((char*)PGHDR_TO_DATA(pPgHdr))+24, change_counter);
|
||||
pPager->iChangeCount = change_counter;
|
||||
|
||||
/* Release the page reference. */
|
||||
sqlite3PagerUnref(pPgHdr);
|
||||
|
@ -10,7 +10,7 @@
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library.
|
||||
#
|
||||
# $Id: exclusive2.test,v 1.3 2007/04/08 16:52:22 drh Exp $
|
||||
# $Id: exclusive2.test,v 1.4 2007/04/16 15:02:20 drh Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@ -56,8 +56,9 @@ do_test exclusive2-1.0 {
|
||||
# The following tests - exclusive2-1.X - check that:
|
||||
#
|
||||
# 1-3: Build a database with connection 1, calculate a signature.
|
||||
# 4-9: Modify the database using a second connection, then reset
|
||||
# the pager change-counter to the value it had before the modifications.
|
||||
# 4-9: Modify the database using a second connection in a way that
|
||||
# does not modify the freelist, then reset the pager change-counter
|
||||
# to the value it had before the modifications.
|
||||
# 8: Check that using the first connection, the database signature
|
||||
# is still the same. This is because it uses the in-memory cache.
|
||||
# It can't tell the db has changed because we reset the change-counter.
|
||||
@ -69,14 +70,14 @@ do_test exclusive2-1.0 {
|
||||
do_test exclusive2-1.1 {
|
||||
execsql {
|
||||
BEGIN;
|
||||
CREATE TABLE t1(a UNIQUE);
|
||||
INSERT INTO t1 VALUES(randstr(10, 400));
|
||||
INSERT INTO t1 VALUES(randstr(10, 400));
|
||||
INSERT INTO t1 SELECT randstr(10, 400) FROM t1;
|
||||
INSERT INTO t1 SELECT randstr(10, 400) FROM t1;
|
||||
INSERT INTO t1 SELECT randstr(10, 400) FROM t1;
|
||||
INSERT INTO t1 SELECT randstr(10, 400) FROM t1;
|
||||
INSERT INTO t1 SELECT randstr(10, 400) FROM t1;
|
||||
CREATE TABLE t1(a, b);
|
||||
INSERT INTO t1(a) VALUES(randstr(10, 400));
|
||||
INSERT INTO t1(a) VALUES(randstr(10, 400));
|
||||
INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
|
||||
INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
|
||||
INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
|
||||
INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
|
||||
INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
|
||||
COMMIT;
|
||||
SELECT count(*) FROM t1;
|
||||
}
|
||||
@ -94,7 +95,7 @@ do_test exclusive2-1.4 {
|
||||
} $::sig
|
||||
do_test exclusive2-1.5 {
|
||||
execsql {
|
||||
DELETE FROM t1;
|
||||
UPDATE t1 SET b=a, a=NULL;
|
||||
} db2
|
||||
expr {[t1sig db2] eq $::sig}
|
||||
} 0
|
||||
@ -135,13 +136,14 @@ do_test exclusive2-2.1 {
|
||||
execsql {PRAGMA locking_mode = exclusive;}
|
||||
execsql {
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES(randstr(10, 400));
|
||||
INSERT INTO t1 VALUES(randstr(10, 400));
|
||||
INSERT INTO t1 SELECT randstr(10, 400) FROM t1;
|
||||
INSERT INTO t1 SELECT randstr(10, 400) FROM t1;
|
||||
INSERT INTO t1 SELECT randstr(10, 400) FROM t1;
|
||||
INSERT INTO t1 SELECT randstr(10, 400) FROM t1;
|
||||
INSERT INTO t1 SELECT randstr(10, 400) FROM t1;
|
||||
DELETE FROM t1;
|
||||
INSERT INTO t1(a) VALUES(randstr(10, 400));
|
||||
INSERT INTO t1(a) VALUES(randstr(10, 400));
|
||||
INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
|
||||
INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
|
||||
INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
|
||||
INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
|
||||
INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
|
||||
COMMIT;
|
||||
SELECT count(*) FROM t1;
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this script is measuring executing speed.
|
||||
#
|
||||
# $Id: speed2.test,v 1.6 2007/03/31 22:34:16 drh Exp $
|
||||
# $Id: speed2.test,v 1.7 2007/04/16 15:02:20 drh Exp $
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
@ -67,7 +67,7 @@ do_test speed2-1.0 {
|
||||
execsql {
|
||||
PRAGMA page_size=1024;
|
||||
PRAGMA cache_size=8192;
|
||||
-- PRAGMA locking_mode=EXCLUSIVE;
|
||||
PRAGMA locking_mode=EXCLUSIVE;
|
||||
CREATE TABLE t1(a INTEGER, b INTEGER, c TEXT);
|
||||
CREATE TABLE t2(a INTEGER, b INTEGER, c TEXT);
|
||||
CREATE INDEX i2a ON t2(a);
|
||||
|
Loading…
Reference in New Issue
Block a user