-C Add\stests\sto\scheck\sinter-process\sWAL\slocking.
-D 2010-04-14T18:06:51
+C Add\stests\sand\sfix\sbugs\sin\sWAL\slocking\smechanism.
+D 2010-04-14T18:50:08
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
F Makefile.in 4f2f967b7e58a35bb74fb7ec8ae90e0f4ca7868b
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
F src/legacy.c a199d7683d60cef73089e892409113e69c23a99f
F src/lempar.c 7f026423f4d71d989e719a743f98a1cbd4e6d99e
F src/loadext.c 1c7a61ce1281041f437333f366a96aa0d29bb581
-F src/log.c a3558ae5a48f808134db9b77a893141ba79402e7
+F src/log.c 165addfd51fa9581936ec04914b17a3b274c49bd
F src/log.h a2654af46ce7b5732f4d5a731abfdd180f0a06d9
F src/main.c c0e7192bad5b90544508b241eb2487ac661de890
F src/malloc.c a08f16d134f0bfab6b20c3cd142ebf3e58235a6a
F test/vtab_alter.test 9e374885248f69e251bdaacf480b04a197f125e5
F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8
F test/vtab_shared.test 0eff9ce4f19facbe0a3e693f6c14b80711a4222d
-F test/wal.test 812dde0a689f69ce9b2d897ce4f08d752bd06749
+F test/wal.test 8f480128b140e54253684bc395f7af0254dc4e03
F test/walcrash.test 45cfbab30bb7cbe0b2e9d5cabe90dbcad10cb89b
F test/walslow.test 38076d5fad49e3678027be0f8110e6a32d531dc2
F test/walthread.test 58cd64b06f186251f09f64e4918fb74a7e52c963
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P 5e9dd3bd8e829376408925fb4cfcd5bb1eb1105f
-R b62050501d5438f40040e5ea09ab63d7
+P 9435f3135849e0d38fde1669201db508561a6308
+R 271de1f1c02e1bce44bf2011bef4ef6b
U dan
-Z 3f45f30ce9e36f0f15e4d7966accef62
+Z 6918d2483c611afa56b459efd78f482c
-9435f3135849e0d38fde1669201db508561a6308
\ No newline at end of file
+c18077f2465fc34830f11c9832e76be5746eaeea
\ No newline at end of file
/* Region D reader lock operations */
|| (op==LOG_RDLOCK && mRegion==(LOG_REGION_D))
+ || (op==LOG_RDLOCK && mRegion==(LOG_REGION_A))
|| (op==LOG_UNLOCK && mRegion==(LOG_REGION_D))
/* Checkpointer lock operations */
}
/*
-** The caller must hold at least a RESERVED lock on the database file
-** when invoking this function.
-**
** This function returns SQLITE_OK if the caller may write to the database.
** Otherwise, if the caller is operating on a snapshot that has already
-** been overwritten by another writer, SQLITE_OBE is returned.
+** been overwritten by another writer, SQLITE_BUSY is returned.
*/
int sqlite3LogWriteLock(Log *pLog, int op){
assert( pLog->isLocked );
return rc;
}
- /* TODO: What if this is a region D reader? And after writing this
- ** transaction it continues to hold a read-lock on the db? Maybe we
- ** need to switch it to a region A reader here so that unlocking C|D
- ** does not leave the connection with no lock at all.
+ /* If this is connection is a region D, then the SHARED lock on region
+ ** D has just been upgraded to EXCLUSIVE. But no lock at all is held on
+ ** region A. This means that if the write-transaction is committed
+ ** and this connection downgrades to a reader, it will be left with no
+ ** lock at all. And its snapshot could get clobbered by a checkpoint
+ ** operation.
+ **
+ ** To stop this from happening, grab a SHARED lock on region A now.
+ ** This should always be successful, as the only time a client holds
+ ** an EXCLUSIVE lock on region A, it must also be holding an EXCLUSIVE
+ ** lock on region C (a checkpointer does this). This is not possible,
+ ** as this connection currently has the EXCLUSIVE lock on region C.
*/
- assert( pLog->isLocked!=LOG_REGION_D );
+ if( pLog->isLocked==LOG_REGION_D ){
+ logLockRegion(pLog, LOG_REGION_A, LOG_RDLOCK);
+ pLog->isLocked = LOG_REGION_A;
+ }
if( memcmp(&pLog->hdr, pLog->pSummary->aData, sizeof(pLog->hdr)) ){
+ logLockRegion(pLog, LOG_REGION_C|LOG_REGION_D, LOG_UNLOCK);
return SQLITE_BUSY;
}
pLog->isWriteLocked = 1;
return 1
}
db busy busyhandler
- do_test wal-10.$tn.9 {
+ do_test wal-10.$tn.17 {
execsql { PRAGMA checkpoint }
} {}
- do_test wal-10.$tn.10 {
+ do_test wal-10.$tn.18 {
sql3 { SELECT * FROM t1 }
} {1 2 3 4 5 6 7 8 9 10 11 12}
- do_test wal-10.$tn.11 {
+ do_test wal-10.$tn.19 {
catchsql { INSERT INTO t1 VALUES(13, 14) }
} {1 {database is locked}}
- do_test wal-10.$tn.12 {
+ do_test wal-10.$tn.20 {
execsql { SELECT * FROM t1 }
} {1 2 3 4 5 6 7 8 9 10 11 12}
- do_test wal-10.$tn.13 {
+ do_test wal-10.$tn.21 {
sql3 COMMIT
} {}
- do_test wal-10.$tn.14 {
+ do_test wal-10.$tn.22 {
execsql { INSERT INTO t1 VALUES(13, 14) }
execsql { SELECT * FROM t1 }
} {1 2 3 4 5 6 7 8 9 10 11 12 13 14}
+ # Set [db3] up as a "region D" reader again. Then upgrade it to a writer
+ # and back down to a reader. Then, check that a checkpoint is not possible
+ # (as [db3] still has a snapshot locked).
+ #
+ do_test wal-10.$tn.23 {
+ execsql { PRAGMA checkpoint }
+ } {}
+ do_test wal-10.$tn.24 {
+ sql2 { BEGIN; SELECT * FROM t1; }
+ } {1 2 3 4 5 6 7 8 9 10 11 12 13 14}
+ do_test wal-10.$tn.25 {
+ execsql { PRAGMA checkpoint }
+ } {}
+ do_test wal-10.$tn.26 {
+ catchsql { INSERT INTO t1 VALUES(15, 16) }
+ } {1 {database is locked}}
+ do_test wal-10.$tn.27 {
+ sql3 { INSERT INTO t1 VALUES(15, 16) }
+ } {}
+ do_test wal-10.$tn.28 {
+ code3 {
+ set ::STMT [sqlite3_prepare db3 "SELECT * FROM t1" -1 TAIL]
+ sqlite3_step $::STMT
+ }
+ sql3 COMMIT
+ execsql { SELECT * FROM t1 }
+ } {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16}
+ db busy {}
+ do_test wal-10.$tn.29 {
+ execsql { INSERT INTO t1 VALUES(17, 18) }
+ catchsql { PRAGMA checkpoint }
+ } {1 {database is locked}}
+ do_test wal-10.$tn.30 {
+ code3 { sqlite3_finalize $::STMT }
+ execsql { PRAGMA checkpoint }
+ } {}
+
+ # At one point, if a reader failed to upgrade to a writer because it
+ # was reading an old snapshot, the write-locks were not being released.
+ # Test that this bug has been fixed.
+ #
+ do_test wal-10.$tn.31 {
+ execsql { BEGIN ; SELECT * FROM t1 }
+ sql2 { INSERT INTO t1 VALUES(19, 20) }
+ catchsql { INSERT INTO t1 VALUES(21, 22) }
+ } {1 {database is locked}}
+ do_test wal-10.$tn.32 {
+ # This statement would fail when the bug was present.
+ sql2 { INSERT INTO t1 VALUES(21, 22) }
+ } {}
+ do_test wal-10.$tn.33 {
+ execsql { SELECT * FROM t1 ; COMMIT }
+ } {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18}
+ do_test wal-10.$tn.34 {
+ execsql { SELECT * FROM t1 }
+ } {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22}
+
catch { db close }
catch { code2 { db2 close } }
catch { code3 { db3 close } }