Fixes for locking issues in WAL mode.
FossilOrigin-Name: a9617eff39177250e2f118f25fdd4b3acb8b0478
This commit is contained in:
parent
64d039e512
commit
b9bf16bfde
18
manifest
18
manifest
@ -1,5 +1,5 @@
|
||||
C Add\sexperimental\slocking\sscheme.
|
||||
D 2010-04-13T19:27:31
|
||||
C Fixes\sfor\slocking\sissues\sin\sWAL\smode.
|
||||
D 2010-04-14T11:23:30
|
||||
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
|
||||
F Makefile.in 4f2f967b7e58a35bb74fb7ec8ae90e0f4ca7868b
|
||||
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
||||
@ -131,7 +131,7 @@ F src/journal.c b0ea6b70b532961118ab70301c00a33089f9315c
|
||||
F src/legacy.c a199d7683d60cef73089e892409113e69c23a99f
|
||||
F src/lempar.c 7f026423f4d71d989e719a743f98a1cbd4e6d99e
|
||||
F src/loadext.c 1c7a61ce1281041f437333f366a96aa0d29bb581
|
||||
F src/log.c d89988bb26a3cd414858c97642a612b4ce6e540f
|
||||
F src/log.c 78575e5bed43578580a0ee86fd3c2e924abe4a88
|
||||
F src/log.h a2654af46ce7b5732f4d5a731abfdd180f0a06d9
|
||||
F src/main.c c0e7192bad5b90544508b241eb2487ac661de890
|
||||
F src/malloc.c a08f16d134f0bfab6b20c3cd142ebf3e58235a6a
|
||||
@ -160,7 +160,7 @@ F src/parse.y ace5c7a125d9f2a410e431ee3209034105045f7e
|
||||
F src/pcache.c ace8f6a5ecd4711cc66a1b23053be7109bd437cf
|
||||
F src/pcache.h c683390d50f856d4cd8e24342ae62027d1bb6050
|
||||
F src/pcache1.c 6dc1871ce8ead9187161c370a58cd06c84221f76
|
||||
F src/pragma.c 9f1d53d40b47743f3d6151df15915970367c9de5
|
||||
F src/pragma.c f12cb58a8aa0d80cfed282ef87a285ed71beb793
|
||||
F src/prepare.c fd1398cb1da54385ba5bd68d93928f10d10a1d9c
|
||||
F src/printf.c 5f5b65a83e63f2096a541a340722a509fa0240a7
|
||||
F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
|
||||
@ -756,10 +756,10 @@ F test/vtabE.test 7c4693638d7797ce2eda17af74292b97e705cc61
|
||||
F test/vtab_alter.test 9e374885248f69e251bdaacf480b04a197f125e5
|
||||
F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8
|
||||
F test/vtab_shared.test 0eff9ce4f19facbe0a3e693f6c14b80711a4222d
|
||||
F test/wal.test d5916b3a40d74dd5bf6ff21b42e6fa7f255efd13
|
||||
F test/wal.test a4be3c7a36e3db3d9d276dc7664c2ed5eece1e8a
|
||||
F test/walcrash.test 45cfbab30bb7cbe0b2e9d5cabe90dbcad10cb89b
|
||||
F test/walslow.test 38076d5fad49e3678027be0f8110e6a32d531dc2
|
||||
F test/walthread.test 1592116f74261d77ea697d9503b0cd1ab1c15e74
|
||||
F test/walthread.test 58cd64b06f186251f09f64e4918fb74a7e52c963
|
||||
F test/where.test de337a3fe0a459ec7c93db16a519657a90552330
|
||||
F test/where2.test 45eacc126aabb37959a387aa83e59ce1f1f03820
|
||||
F test/where3.test 97d3936e6a443b968f1a61cdcc0f673252000e94
|
||||
@ -803,7 +803,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
||||
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
||||
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
||||
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
||||
P f4e1150fed2c520c7c52612cb1019429d78dc32a
|
||||
R da172d13acb33c194abd32bf4ed20cc9
|
||||
P 3f958e87c33d667d299b03ffdef58db5dc6363f4
|
||||
R 91ba1bf1aecd8bbf6dbeda941d0dbe58
|
||||
U dan
|
||||
Z cd10eeca0187a805032040fdd27191f0
|
||||
Z d3b26d31320c12902d5354af18b08451
|
||||
|
@ -1 +1 @@
|
||||
3f958e87c33d667d299b03ffdef58db5dc6363f4
|
||||
a9617eff39177250e2f118f25fdd4b3acb8b0478
|
128
src/log.c
128
src/log.c
@ -617,7 +617,7 @@ int sqlite3LogOpen(
|
||||
const char *zDb, /* Name of database file */
|
||||
Log **ppLog /* OUT: Allocated Log handle */
|
||||
){
|
||||
int rc; /* Return Code */
|
||||
int rc = SQLITE_OK; /* Return Code */
|
||||
Log *pRet; /* Object to allocate and return */
|
||||
LogSummary *pSummary = 0; /* Summary object */
|
||||
sqlite3_mutex *mutex = 0; /* LOG_SUMMARY_MUTEX mutex */
|
||||
@ -806,7 +806,7 @@ static int logCheckpoint(
|
||||
int pgsz = pLog->hdr.pgsz; /* Database page-size */
|
||||
LogCheckpoint *pIter = 0; /* Log iterator context */
|
||||
u32 iDbpage = 0; /* Next database page to write */
|
||||
u32 iFrame; /* Log frame containing data for iDbpage */
|
||||
u32 iFrame = 0; /* Log frame containing data for iDbpage */
|
||||
|
||||
/* Allocate the iterator */
|
||||
pIter = logCheckpointInit(pLog);
|
||||
@ -1080,6 +1080,77 @@ static int logLockRegion(Log *pLog, u32 mRegion, int op){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Try to read the log-summary header. Attempt to verify the header
|
||||
** checksum. If the checksum can be verified, copy the log-summary
|
||||
** header into structure pLog->hdr. If the contents of pLog->hdr are
|
||||
** modified by this and pChanged is not NULL, set *pChanged to 1.
|
||||
** Otherwise leave *pChanged unmodified.
|
||||
**
|
||||
** If the checksum cannot be verified return SQLITE_ERROR.
|
||||
*/
|
||||
int logSummaryTryHdr(Log *pLog, int *pChanged){
|
||||
u32 aCksum[2] = {1, 1};
|
||||
u32 aHdr[LOGSUMMARY_HDR_NFIELD+2];
|
||||
|
||||
/* First try to read the header without a lock. Verify the checksum
|
||||
** before returning. This will almost always work.
|
||||
*/
|
||||
memcpy(aHdr, pLog->pSummary->aData, sizeof(aHdr));
|
||||
logChecksumBytes((u8*)aHdr, sizeof(u32)*LOGSUMMARY_HDR_NFIELD, aCksum);
|
||||
if( aCksum[0]!=aHdr[LOGSUMMARY_HDR_NFIELD]
|
||||
|| aCksum[1]!=aHdr[LOGSUMMARY_HDR_NFIELD+1]
|
||||
){
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
|
||||
if( memcmp(&pLog->hdr, aHdr, sizeof(LogSummaryHdr)) ){
|
||||
if( pChanged ){
|
||||
*pChanged = 1;
|
||||
}
|
||||
memcpy(&pLog->hdr, aHdr, sizeof(LogSummaryHdr));
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Read the log-summary header from the log-summary file into structure
|
||||
** pLog->hdr. If attempting to verify the header checksum fails, try
|
||||
** to recover the log before returning.
|
||||
**
|
||||
** If the log-summary header is successfully read, return SQLITE_OK.
|
||||
** Otherwise an SQLite error code.
|
||||
*/
|
||||
int logSummaryReadHdr(Log *pLog, int *pChanged){
|
||||
int rc;
|
||||
|
||||
/* First try to read the header without a lock. Verify the checksum
|
||||
** before returning. This will almost always work.
|
||||
*/
|
||||
if( SQLITE_OK==logSummaryTryHdr(pLog, pChanged) ){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/* If the first attempt to read the header failed, lock the log-summary
|
||||
** file and try again. If the header checksum verification fails this
|
||||
** time as well, run log recovery.
|
||||
*/
|
||||
if( SQLITE_OK==(rc = logEnterMutex(pLog)) ){
|
||||
if( SQLITE_OK!=logSummaryTryHdr(pLog, pChanged) ){
|
||||
if( pChanged ){
|
||||
*pChanged = 1;
|
||||
}
|
||||
rc = logSummaryRecover(pLog->pSummary, pLog->pFd);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = logSummaryTryHdr(pLog, 0);
|
||||
}
|
||||
}
|
||||
logLeaveMutex(pLog);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Lock a snapshot.
|
||||
**
|
||||
@ -1122,31 +1193,7 @@ int sqlite3LogOpenSnapshot(Log *pLog, int *pChanged){
|
||||
return rc;
|
||||
}
|
||||
|
||||
if( SQLITE_OK==(rc = logEnterMutex(pLog)) ){
|
||||
u32 aCksum[2] = {1, 1};
|
||||
u32 aHdr[LOGSUMMARY_HDR_NFIELD+2];
|
||||
memcpy(aHdr, pLog->pSummary->aData, sizeof(aHdr));
|
||||
|
||||
/* Verify the checksum on the log-summary header. If it fails,
|
||||
** recover the log-summary from the log file.
|
||||
*/
|
||||
logChecksumBytes((u8*)aHdr, sizeof(u32)*LOGSUMMARY_HDR_NFIELD, aCksum);
|
||||
if( aCksum[0]!=aHdr[LOGSUMMARY_HDR_NFIELD]
|
||||
|| aCksum[1]!=aHdr[LOGSUMMARY_HDR_NFIELD+1]
|
||||
){
|
||||
rc = logSummaryRecover(pLog->pSummary, pLog->pFd);
|
||||
memcpy(aHdr, pLog->pSummary->aData, sizeof(aHdr));
|
||||
*pChanged = 1;
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
if( memcmp(&pLog->hdr, aHdr, sizeof(LogSummaryHdr)) ){
|
||||
*pChanged = 1;
|
||||
memcpy(&pLog->hdr, aHdr, LOGSUMMARY_HDR_NFIELD*sizeof(u32));
|
||||
}
|
||||
}
|
||||
logLeaveMutex(pLog);
|
||||
}
|
||||
|
||||
rc = logSummaryReadHdr(pLog, pChanged);
|
||||
if( rc!=SQLITE_OK ){
|
||||
/* An error occured while attempting log recovery. */
|
||||
sqlite3LogCloseSnapshot(pLog);
|
||||
@ -1409,8 +1456,13 @@ int sqlite3LogFrames(
|
||||
}
|
||||
|
||||
/*
|
||||
** Checkpoint the database. When this function is called the caller
|
||||
** must hold an exclusive lock on the database file.
|
||||
** Checkpoint the database:
|
||||
**
|
||||
** 1. Wait for an EXCLUSIVE lock on regions B and C.
|
||||
** 2. Wait for an EXCLUSIVE lock on region A.
|
||||
** 3. Copy the contents of the log into the database file.
|
||||
** 4. Zero the log-summary header (so new readers will ignore the log).
|
||||
** 5. Drop the locks obtained in steps 1 and 2.
|
||||
*/
|
||||
int sqlite3LogCheckpoint(
|
||||
Log *pLog, /* Log connection */
|
||||
@ -1419,20 +1471,30 @@ int sqlite3LogCheckpoint(
|
||||
int (*xBusyHandler)(void *), /* Pointer to busy-handler function */
|
||||
void *pBusyHandlerArg /* Argument to pass to xBusyHandler */
|
||||
){
|
||||
int rc;
|
||||
int rc; /* Return code */
|
||||
|
||||
/* Wait for a write-lock on regions B and C. */
|
||||
do {
|
||||
rc = logLockRegion(pLog, LOG_REGION_B|LOG_REGION_C, LOG_WRLOCK);
|
||||
}while( rc==SQLITE_BUSY && xBusyHandler(pBusyHandlerArg) );
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
|
||||
/* Wait for a write-lock on region A. */
|
||||
do {
|
||||
rc = logLockRegion(pLog, LOG_REGION_A, LOG_WRLOCK);
|
||||
}while( rc==SQLITE_BUSY && xBusyHandler(pBusyHandlerArg) );
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
|
||||
rc = logCheckpoint(pLog, pFd, zBuf);
|
||||
if( rc!=SQLITE_OK ){
|
||||
logLockRegion(pLog, LOG_REGION_B|LOG_REGION_C, LOG_UNLOCK);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Copy data from the log to the database file. */
|
||||
rc = logSummaryReadHdr(pLog, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = logCheckpoint(pLog, pFd, zBuf);
|
||||
}
|
||||
|
||||
/* Release the locks. */
|
||||
logLockRegion(pLog, LOG_REGION_A|LOG_REGION_B|LOG_REGION_C, LOG_UNLOCK);
|
||||
return rc;
|
||||
}
|
||||
|
@ -1386,7 +1386,6 @@ void sqlite3Pragma(
|
||||
|
||||
if( sqlite3StrICmp(zLeft, "checkpoint")==0 ){
|
||||
sqlite3VdbeUsesBtree(v, iDb);
|
||||
sqlite3VdbeAddOp2(v, OP_Transaction, iDb, 1);
|
||||
sqlite3VdbeAddOp3(v, OP_Checkpoint, iDb, 0, 0);
|
||||
}else
|
||||
|
||||
|
370
test/wal.test
370
test/wal.test
@ -27,7 +27,7 @@ proc range {args} {
|
||||
}
|
||||
|
||||
proc reopen_db {} {
|
||||
db close
|
||||
catch { db close }
|
||||
file delete -force test.db test.db-wal
|
||||
sqlite3_wal db test.db
|
||||
#register_logtest
|
||||
@ -223,7 +223,6 @@ do_test wal-7.1 {
|
||||
CREATE TABLE t1(a, b);
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
}
|
||||
|
||||
list [file size test.db] [file size test.db-wal]
|
||||
} [list 0 [expr (1024+20)*3]]
|
||||
do_test wal-7.2 {
|
||||
@ -231,272 +230,17 @@ do_test wal-7.2 {
|
||||
list [file size test.db] [file size test.db-wal]
|
||||
} [list 2048 [expr (1024+20)*3]]
|
||||
|
||||
# db close
|
||||
# sqlite3_wal db test.db
|
||||
# register_logsummary_module db
|
||||
# # Warm-body tests of the virtual tables used for testing.
|
||||
# #
|
||||
# do_test wal-8.1 {
|
||||
# execsql { CREATE VIRTUAL TABLE temp.logsummary USING logsummary }
|
||||
# execsql { CREATE VIRTUAL TABLE temp.logcontent USING logcontent }
|
||||
# execsql { CREATE VIRTUAL TABLE temp.loglock USING loglock }
|
||||
# execsql { SELECT * FROM logsummary }
|
||||
# } [list [file join [pwd] test.db] 1 0 0 0 0 0 0]
|
||||
#
|
||||
# do_test wal-8.2 {
|
||||
# sqlite3_wal db2 test.db
|
||||
# execsql { SELECT * FROM logsummary }
|
||||
# } [list [file join [pwd] test.db] 2 0 0 0 0 0 0]
|
||||
# do_test wal-8.3 {
|
||||
# db2 close
|
||||
# execsql { SELECT * FROM logsummary }
|
||||
# } [list [file join [pwd] test.db] 1 0 0 0 0 0 0]
|
||||
# do_test wal-8.4 {
|
||||
# execsql { INSERT INTO t1 VALUES(3, 4) }
|
||||
# execsql { SELECT * FROM logsummary }
|
||||
# } [list [file join [pwd] test.db] 1 1024 2 2 3 0 0]
|
||||
# do_test wal-8.5 {
|
||||
# execsql { PRAGMA checkpoint }
|
||||
# execsql { SELECT * FROM logsummary }
|
||||
# } [list [file join [pwd] test.db] 1 1024 0 0 0 0 0]
|
||||
#
|
||||
# do_test wal-8.6 {
|
||||
# execsql { INSERT INTO t1 VALUES(5, 6) }
|
||||
# execsql { PRAGMA checkpoint('1 1 1') }
|
||||
# execsql { SELECT * FROM logsummary }
|
||||
# } [list [file join [pwd] test.db] 1 1024 2 0 3 0 0]
|
||||
# do_test wal-8.7 {
|
||||
# execsql { SELECT logpage, dbpage FROM logcontent }
|
||||
# } {}
|
||||
# do_test wal-8.8 {
|
||||
# execsql { INSERT INTO t1 VALUES(7, 8) }
|
||||
# execsql { SELECT logpage, dbpage FROM logcontent }
|
||||
# } {4 T:4 5 2}
|
||||
# do_test wal-8.9 {
|
||||
# execsql { SELECT * FROM logsummary }
|
||||
# } [list [file join [pwd] test.db] 1 1024 2 4 5 0 0]
|
||||
# do_test wal-8.10 {
|
||||
# execsql { SELECT * FROM loglock }
|
||||
# } [list [file join [pwd] test.db] 0 0 0]
|
||||
# do_test wal-8.11 {
|
||||
# execsql { BEGIN; SELECT * FROM t1; }
|
||||
# execsql { SELECT * FROM loglock }
|
||||
# } [list [file join [pwd] test.db] 0 0 4]
|
||||
#
|
||||
# # Try making the log wrap around.
|
||||
# #
|
||||
# reopen_db
|
||||
#
|
||||
# do_test wal-9.1 {
|
||||
# execsql {
|
||||
# BEGIN;
|
||||
# CREATE TABLE t1(a PRIMARY KEY, b);
|
||||
# }
|
||||
# for {set i 0} {$i < 100} {incr i} {
|
||||
# execsql { INSERT INTO t1 VALUES($i, randomblob(100)) }
|
||||
# }
|
||||
# execsql COMMIT
|
||||
# execsql { SELECT * FROM logsummary }
|
||||
# } [list [file join [pwd] test.db] 1 1024 2 2 17 0 0]
|
||||
# do_test wal-9.2 {
|
||||
# execsql { SELECT logpage, dbpage FROM logcontent }
|
||||
# } {2 T:2 3 1 4 2 5 3 6 4 7 5 8 6 9 7 10 8 11 9 12 10 13 11 14 12 15 13 16 14 17 15}
|
||||
# do_test wal-9.3 {
|
||||
# execsql { PRAGMA checkpoint('12, 12') }
|
||||
# execsql { SELECT * FROM logsummary }
|
||||
# } [list [file join [pwd] test.db] 1 1024 2 15 17 0 0]
|
||||
# do_test wal-9.4 {
|
||||
# execsql { SELECT logpage, dbpage FROM logcontent }
|
||||
# } {15 13 16 14 17 15}
|
||||
# do_test wal-9.5 {
|
||||
# execsql { SELECT count(*) FROM t1 }
|
||||
# } {100}
|
||||
# do_test wal-9.6 {
|
||||
# execsql { INSERT INTO t1 VALUES(100, randomblob(100)) }
|
||||
# execsql { SELECT * FROM logsummary }
|
||||
# } [list [file join [pwd] test.db] 1 1024 2 15 20 0 0]
|
||||
#
|
||||
# do_test wal-9.7 {
|
||||
# execsql { SELECT count(*) FROM t1 }
|
||||
# } {101}
|
||||
# do_test wal-9.8 {
|
||||
# db close
|
||||
# sqlite3_wal db test.db
|
||||
# register_logtest
|
||||
# execsql { SELECT count(*) FROM t1 }
|
||||
# } {101}
|
||||
# do_test wal-9.9 {
|
||||
# execsql { SELECT * FROM logsummary }
|
||||
# } [list [file join [pwd] test.db] 1 0 0 0 0 0 0]
|
||||
#
|
||||
# reopen_db
|
||||
# do_test wal-10.1 {
|
||||
# execsql {
|
||||
# PRAGMA page_size = 1024;
|
||||
# CREATE TABLE t1(x PRIMARY KEY);
|
||||
# INSERT INTO t1 VALUES(randomblob(900));
|
||||
# INSERT INTO t1 VALUES(randomblob(900));
|
||||
# INSERT INTO t1 SELECT randomblob(900) FROM t1; -- 4
|
||||
# INSERT INTO t1 SELECT randomblob(900) FROM t1; -- 8
|
||||
# INSERT INTO t1 SELECT randomblob(900) FROM t1; -- 16
|
||||
# }
|
||||
# list [file size test.db] [file size test.db-wal]
|
||||
# } {0 55296}
|
||||
# do_test wal-10.2 {
|
||||
# execsql { PRAGMA checkpoint('20 30') }
|
||||
# } {}
|
||||
# do_test wal-10.3 {
|
||||
# execsql { SELECT * FROM logsummary }
|
||||
# } [list [file join [pwd] test.db] 1 1024 34 38 54 0 0]
|
||||
# do_test wal-10.4 {
|
||||
# execsql { SELECT dbpage FROM logcontent }
|
||||
# } {21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37}
|
||||
# do_test wal-10.5 {
|
||||
# execsql { INSERT INTO t1 VALUES(randomblob(900)) }
|
||||
# execsql { SELECT * FROM logsummary }
|
||||
# } [list [file join [pwd] test.db] 1 1024 34 38 6 34 54]
|
||||
# do_test wal-10.6 {
|
||||
# execsql { SELECT count(*) FROM t1 WHERE x NOT NULL }
|
||||
# } {17}
|
||||
# do_test wal-10.8 {
|
||||
# execsql { SELECT logpage FROM logcontent }
|
||||
# } [range 38 54 1 6]
|
||||
# do_test wal-10.9 {
|
||||
# execsql { INSERT INTO t1 SELECT randomblob(900) FROM t1 }
|
||||
# execsql { SELECT * FROM logsummary }
|
||||
# } [list [file join [pwd] test.db] 1 1024 34 38 68 34 54]
|
||||
#
|
||||
# do_test wal-10.10 {
|
||||
# execsql { SELECT logpage FROM logcontent }
|
||||
# } [range 38 54 1 33 55 68]
|
||||
#
|
||||
# do_test wal-10.11 {
|
||||
# execsql { SELECT count(*) FROM t1 WHERE x NOT NULL }
|
||||
# } {34}
|
||||
#
|
||||
# do_test wal-10.12 {
|
||||
# execsql { PRAGMA checkpoint('35 35') }
|
||||
# } {}
|
||||
# do_test wal-10.13 {
|
||||
# execsql { SELECT logpage FROM logcontent }
|
||||
# } [range 22 68]
|
||||
# do_test wal-10.13a {
|
||||
# execsql { SELECT dbpage FROM logcontent }
|
||||
# } [list \
|
||||
# 50 51 52 53 54 55 56 57 58 59 60 61 \
|
||||
# 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \
|
||||
# 62 63 64 65 66 67 68 69 70 71 72 73 74 75 \
|
||||
# ]
|
||||
#
|
||||
# do_test wal-10.14 {
|
||||
# execsql { SELECT count(*) FROM t1 WHERE x NOT NULL }
|
||||
# } {34}
|
||||
# do_test wal-10.15 {
|
||||
# execsql { PRAGMA integrity_check }
|
||||
# } {ok}
|
||||
# do_test wal-10.16 {
|
||||
# execsql { PRAGMA checkpoint('20 20') }
|
||||
# execsql { SELECT * FROM logsummary }
|
||||
# } [list [file join [pwd] test.db] 1 1024 7 63 68 0 0]
|
||||
# do_test wal-10.17 {
|
||||
# execsql { SELECT logpage FROM logcontent }
|
||||
# } [range 63 68]
|
||||
# do_test wal-10.17a {
|
||||
# execsql { SELECT dbpage FROM logcontent }
|
||||
# } {70 71 72 73 74 75}
|
||||
#
|
||||
# do_test wal-10.18 {
|
||||
# execsql { INSERT INTO t1 SELECT randomblob(900) FROM t1 }
|
||||
# execsql { SELECT logpage FROM logcontent }
|
||||
# } [range 63 147]
|
||||
# integrity_check wal-10.19
|
||||
#
|
||||
# do_test wal-10.20 {
|
||||
# execsql { PRAGMA checkpoint('52 52') }
|
||||
# execsql { SELECT logpage FROM logcontent }
|
||||
# } [range 116 147]
|
||||
# do_test wal-10.20a {
|
||||
# execsql { SELECT * FROM logsummary }
|
||||
# } [list [file join [pwd] test.db] 1 1024 69 116 147 0 0]
|
||||
# integrity_check wal-10.20.integrity
|
||||
#
|
||||
# do_test wal-10.21 {
|
||||
# execsql { INSERT INTO t1 VALUES( randomblob(900) ) }
|
||||
# execsql { SELECT logpage FROM logcontent }
|
||||
# } [range 116 152]
|
||||
# do_test wal-10.22 {
|
||||
# execsql { PRAGMA integrity_check }
|
||||
# } {ok}
|
||||
#
|
||||
# file delete -force testX.db testX.db-wal
|
||||
# file copy test.db testX.db
|
||||
# file copy test.db-wal testX.db-wal
|
||||
# do_test wal-10.23 {
|
||||
# sqlite3_wal db2 testX.db
|
||||
# register_logtest db2
|
||||
# execsql { SELECT logpage FROM logcontent WHERE db LIKE '%testX%' } db2
|
||||
# } [range 34 54 1 33 55 152]
|
||||
#
|
||||
# do_test wal-10.24 {
|
||||
# execsql { PRAGMA integrity_check } db2
|
||||
# } {ok}
|
||||
# db2 close
|
||||
#
|
||||
# do_test wal-11.1 {
|
||||
# reopen_db
|
||||
# sqlite3_wal db2 test.db
|
||||
#
|
||||
# execsql {
|
||||
# BEGIN;
|
||||
# CREATE TABLE t1(x);
|
||||
# CREATE TABLE t2(x PRIMARY KEY);
|
||||
# INSERT INTO t1 VALUES(randomblob(900));
|
||||
# INSERT INTO t1 VALUES(randomblob(900));
|
||||
# INSERT INTO t1 SELECT randomblob(900) FROM t1; /* 4 */
|
||||
# INSERT INTO t1 SELECT randomblob(900) FROM t1; /* 8 */
|
||||
# INSERT INTO t1 SELECT randomblob(900) FROM t1; /* 16 */
|
||||
# INSERT INTO t1 SELECT randomblob(900) FROM t1; /* 32 */
|
||||
# INSERT INTO t1 SELECT randomblob(900) FROM t1; /* 64 */
|
||||
#
|
||||
# INSERT INTO t2 VALUES('x');
|
||||
# INSERT INTO t2 VALUES('y');
|
||||
# INSERT INTO t2 VALUES('z');
|
||||
# COMMIT;
|
||||
# SELECT * FROM logsummary;
|
||||
# }
|
||||
# } [list [file join [pwd] test.db] 2 1024 2 2 70 0 0]
|
||||
#
|
||||
# do_test wal-11.2 {
|
||||
# execsql {
|
||||
# BEGIN; SELECT x FROM t2;
|
||||
# } db2
|
||||
# } {x y z}
|
||||
# do_test wal-11.2 {
|
||||
# execsql {
|
||||
# INSERT INTO t1 VALUES(randomblob(900));
|
||||
# PRAGMA checkpoint('10 100');
|
||||
# INSERT INTO t1 VALUES(randomblob(900));
|
||||
# INSERT INTO t2 VALUES('0');
|
||||
# SELECT * FROM logsummary;
|
||||
# }
|
||||
# } [list [file join [pwd] test.db] 2 1024 71 71 7 71 73]
|
||||
# do_test wal-12.3 {
|
||||
# execsql { PRAGMA integrity_check } db2
|
||||
# } {ok}
|
||||
# db2 close
|
||||
|
||||
|
||||
# Execute some transactions in auto-vacuum mode to test database file
|
||||
# truncation.
|
||||
#
|
||||
do_test wal-12.1 {
|
||||
do_test wal-8.1 {
|
||||
reopen_db
|
||||
execsql {
|
||||
PRAGMA auto_vacuum = 1;
|
||||
PRAGMA auto_vacuum;
|
||||
}
|
||||
} {1}
|
||||
do_test wal-12.2 {
|
||||
do_test wal-8.2 {
|
||||
execsql {
|
||||
PRAGMA page_size = 1024;
|
||||
CREATE TABLE t1(x);
|
||||
@ -511,7 +255,7 @@ do_test wal-12.2 {
|
||||
}
|
||||
file size test.db
|
||||
} [expr 68*1024]
|
||||
do_test wal-12.3 {
|
||||
do_test wal-8.3 {
|
||||
execsql {
|
||||
DELETE FROM t1 WHERE rowid<54;
|
||||
PRAGMA checkpoint;
|
||||
@ -522,7 +266,7 @@ do_test wal-12.3 {
|
||||
# Run some "warm-body" tests to ensure that log-summary files with more
|
||||
# than 256 entries (log summaries that contain index blocks) work Ok.
|
||||
#
|
||||
do_test wal-13.1 {
|
||||
do_test wal-9.1 {
|
||||
reopen_db
|
||||
execsql {
|
||||
PRAGMA page_size = 1024;
|
||||
@ -539,12 +283,12 @@ do_test wal-13.1 {
|
||||
}
|
||||
file size test.db
|
||||
} 0
|
||||
do_test wal-13.2 {
|
||||
do_test wal-9.2 {
|
||||
sqlite3_wal db2 test.db
|
||||
execsql {PRAGMA integrity_check } db2
|
||||
} {ok}
|
||||
|
||||
do_test wal-13.3 {
|
||||
do_test wal-9.3 {
|
||||
file delete -force test2.db test2.db-wal
|
||||
file copy test.db test2.db
|
||||
file copy test.db-wal test2.db-wal
|
||||
@ -553,8 +297,7 @@ do_test wal-13.3 {
|
||||
} {ok}
|
||||
db3 close
|
||||
|
||||
do_test wal-13.4 {
|
||||
breakpoint
|
||||
do_test wal-9.4 {
|
||||
execsql { PRAGMA checkpoint }
|
||||
db2 close
|
||||
sqlite3_wal db2 test.db
|
||||
@ -564,5 +307,102 @@ breakpoint
|
||||
foreach handle {db db2 db3} { catch { $handle close } }
|
||||
unset handle
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# The following block of tests - wal-10.* - test that the WAL locking
|
||||
# scheme works for clients in a single process.
|
||||
#
|
||||
reopen_db
|
||||
sqlite3_wal db2 test.db
|
||||
sqlite3_wal db3 test.db
|
||||
|
||||
do_test wal-10.1 {
|
||||
execsql {
|
||||
CREATE TABLE t1(a, b);
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES(3, 4);
|
||||
}
|
||||
execsql "SELECT * FROM t1" db2
|
||||
} {1 2}
|
||||
do_test wal-10.2 {
|
||||
execsql { COMMIT }
|
||||
execsql "SELECT * FROM t1" db2
|
||||
} {1 2 3 4}
|
||||
do_test wal-10.3 {
|
||||
execsql {
|
||||
BEGIN;
|
||||
SELECT * FROM t1;
|
||||
} db2
|
||||
} {1 2 3 4}
|
||||
do_test wal-10.4 {
|
||||
catchsql { PRAGMA checkpoint }
|
||||
} {1 {database is locked}}
|
||||
do_test wal-10.5 {
|
||||
execsql { INSERT INTO t1 VALUES(5, 6) }
|
||||
execsql { SELECT * FROM t1 } db2
|
||||
} {1 2 3 4}
|
||||
|
||||
# Connection [db2] is holding a lock on a snapshot, preventing [db] from
|
||||
# checkpointing the database. Add a busy-handler to [db]. If [db2] completes
|
||||
# its transaction from within the busy-handler, [db] is able to complete
|
||||
# the checkpoint operation.
|
||||
#
|
||||
proc busyhandler x {
|
||||
if {$x==4} {
|
||||
execsql { COMMIT } db2
|
||||
}
|
||||
if {$x<5} {return 0}
|
||||
return 1
|
||||
}
|
||||
db busy busyhandler
|
||||
do_test wal-10.6 {
|
||||
execsql { PRAGMA checkpoint }
|
||||
} {}
|
||||
|
||||
# Similar to the test above. Except this time, a new read transaction is
|
||||
# started (db3) while the checkpointer is waiting for an old one to finish.
|
||||
# The checkpointer can finish, but any subsequent write operations must
|
||||
# wait until after db3 has closed the read transaction.
|
||||
#
|
||||
db busy {}
|
||||
do_test wal-10.7 {
|
||||
execsql {
|
||||
BEGIN;
|
||||
SELECT * FROM t1;
|
||||
} db2
|
||||
} {1 2 3 4 5 6}
|
||||
do_test wal-10.8 {
|
||||
execsql { INSERT INTO t1 VALUES(7, 8) }
|
||||
catchsql { PRAGMA checkpoint }
|
||||
} {1 {database is locked}}
|
||||
proc busyhandler x {
|
||||
if {$x==3} { execsql { BEGIN; SELECT * FROM t1 } db3 }
|
||||
if {$x==4} { execsql { COMMIT } db2 }
|
||||
if {$x<5} { return 0 }
|
||||
return 1
|
||||
}
|
||||
db busy busyhandler
|
||||
do_test wal-10.9 {
|
||||
execsql { PRAGMA checkpoint }
|
||||
} {}
|
||||
do_test wal-10.10 {
|
||||
execsql { SELECT * FROM t1 } db3
|
||||
} {1 2 3 4 5 6 7 8}
|
||||
do_test wal-10.11 {
|
||||
catchsql { INSERT INTO t1 VALUES(9, 10) }
|
||||
} {1 {database is locked}}
|
||||
do_test wal-10.12 {
|
||||
execsql { SELECT * FROM t1 }
|
||||
} {1 2 3 4 5 6 7 8}
|
||||
do_test wal-10.13 {
|
||||
execsql { COMMIT } db3
|
||||
} {}
|
||||
do_test wal-10.14 {
|
||||
execsql { INSERT INTO t1 VALUES(9, 10) }
|
||||
execsql { SELECT * FROM t1 }
|
||||
} {1 2 3 4 5 6 7 8 9 10}
|
||||
|
||||
foreach handle {db db2 db3} { catch { $handle close } }
|
||||
unset handle
|
||||
finish_test
|
||||
|
||||
|
@ -62,7 +62,7 @@ do_test walthread-1.4 {
|
||||
# Each of the N threads runs N read transactions followed by a single write
|
||||
# transaction in a loop as fast as possible.
|
||||
#
|
||||
# There is also a single checkpointer thread. It runs the following loop:
|
||||
# Ther is also a single checkpointer thread. It runs the following loop:
|
||||
#
|
||||
# 1) Execute "CHECKPOINT main 32 -1 1"
|
||||
# 2) Sleep for 500 ms.
|
||||
@ -85,7 +85,7 @@ set thread_program {
|
||||
set rc [sqlite3_finalize $stmt]
|
||||
|
||||
if {$rc ne "SQLITE_OK"} {
|
||||
error $rc
|
||||
error "$rc: [sqlite3_errmsg $DB]"
|
||||
}
|
||||
return $res
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user