------BEGIN PGP SIGNED MESSAGE-----
-Hash: SHA1
-
-C Change\sthe\sversion\snumber\sto\s3.7.4.
-D 2010-11-01T14:34:31
+C If\sa\sdatabase\sfile\swith\sthe\sWAL\sflag\sset\sis\sopened\sin\sexclusive-locking\smode,\suse\sheap\smemory\sto\sstore\sthe\swal-index\sinstead\sof\sshared-memory.
+D 2010-11-01T17:38:25
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 2c8cefd962eca0147132c7cf9eaa4bb24c656f3f
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F src/os_os2.c 72d0b2e562952a2464308c4ce5f7913ac10bef3e
F src/os_unix.c 00a4a84aba46b61439913bebf0c10d408e42a630
F src/os_win.c 2f90f7bdec714fad51cd31b4ecad3cc1b4bb5aad
-F src/pager.c d9858b47b216e3bcb0431bd50ef17d070ac0b92c
+F src/pager.c c19b0e8d49220825fd382236fbbcb3063c48ce2d
F src/pager.h 8167a1e720d0b7a2790079007128e594010220ad
F src/parse.y 12b7ebd61ea54f0e1b1083ff69cc2c8ce9353d58
F src/pcache.c 09d38c44ab275db581f7a2f6ff8b9bc7f8c0faaa
F src/test_stat.c f682704b5d1ba8e1d4e7e882a6d7922e2dcf066c
F src/test_tclvar.c f4dc67d5f780707210d6bb0eb6016a431c04c7fa
F src/test_thread.c bedd05cad673dba53326f3aa468cc803038896c0
-F src/test_vfs.c 702e52636113f6b9721da90ef1bf26e07fff414d
+F src/test_vfs.c e10fcca756cafa89438311b31522ac1f95bf784b
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/tokenize.c 604607d6813e9551cf5189d899e0a25c12681080
F src/trigger.c b8bedb9c0084ceb51a40f54fcca2ce048c8de852
F src/vdbemem.c 23723a12cd3ba7ab3099193094cbb2eb78956aa9
F src/vdbetrace.c 864cef96919323482ebd9986f2132435115e9cc2
F src/vtab.c b297e8fa656ab5e66244ab15680d68db0adbec30
-F src/wal.c 0dc7eb9e907a2c280cdcde876d313e07ea4ad811
-F src/wal.h 96669b645e27cd5a111ba59f0cae7743a207bc3c
+F src/wal.c f26b8d297bd11cb792e609917f9d4c6718ac8e0e
+F src/wal.h c1aac6593a0b02b15dc625987e619edeab39292e
F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
F src/where.c d9a31eb3d59466b6c53567c8c9a6c2fe68bbd565
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/notnull.test cc7c78340328e6112a13c3e311a9ab3127114347
F test/null.test a8b09b8ed87852742343b33441a9240022108993
F test/openv2.test af02ed0a9cbc0d2a61b8f35171d4d117e588e4ec
-F test/pager1.test 12ad20280db1ba25f1f0d7ddebf0971a305d8f80
+F test/pager1.test fa74657dc832f0e21dc3ce60829feaee143296ba
F test/pager2.test 0fbb6b6dc40ce1fecfe758c555a748ad2e9beaa3
F test/pager3.test 3856d9c80839be0668efee1b74811b1b7f7fc95f
F test/pagerfault.test 3cd3537bf2efb4baef26c74878718f4a32926da4
F test/pagesize.test 76aa9f23ecb0741a4ed9d2e16c5fa82671f28efb
F test/pcache.test 4118a183908ecaed343a06fcef3ba82e87e0129d
F test/pcache2.test 0d85f2ab6963aee28c671d4c71bec038c00a1d16
-F test/permutations.test da40da6433f050b50e65a8ae37265ab6c89f876c
+F test/permutations.test e54d5fc34708ecb4a67f2a18f7b8719b175a1652
F test/pragma.test fdfc09067ea104a0c247a1a79d8093b56656f850
F test/pragma2.test 5364893491b9231dd170e3459bfc2e2342658b47
F test/printf.test 05970cde31b1a9f54bd75af60597be75a5c54fea
F test/tempdb.test 19d0f66e2e3eeffd68661a11c83ba5e6ace9128c
F test/temptable.test f42121a0d29a62f00f93274464164177ab1cc24a
F test/temptrigger.test b0273db072ce5f37cf19140ceb1f0d524bbe9f05
-F test/tester.tcl b9c732d1228f0daab41bbbeddd6d0861394b23aa
+F test/tester.tcl fa48313dcf20f9c6def1af485e284e29100d709e
F test/thread001.test a3e6a7254d1cb057836cb3145b60c10bf5b7e60f
F test/thread002.test afd20095e6e845b405df4f2c920cb93301ca69db
F test/thread003.test b824d4f52b870ae39fc5bae4d8070eca73085dca
F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8
F test/vtab_shared.test 0eff9ce4f19facbe0a3e693f6c14b80711a4222d
F test/wal.test 70227190e713b3e7eb2a7d5ec3510b66db01f327
-F test/wal2.test 223f3e14d475730af772a7f5862d4bcfa7565c3a
+F test/wal2.test c794b8b257af54190bb913678ad3984cbf3311b9
F test/wal3.test 957a5f2a8fe8a6ff01de1a15285ecf2f376fcaf8
F test/wal4.test 3404b048fa5e10605facaf70384e6d2943412e30
F test/wal_common.tcl 895d76138043b86bdccf36494054bdabcf65837b
F test/walcksum.test a37b36375c595e61bdb7e1ec49b5f0979b6fc7ce
F test/walcrash.test e763841551d6b23677ccb419797c1589dcbdbaf5
F test/walcrash2.test 019d60b89d96c1937adb2b30b850ac7e86e5a142
-F test/walfault.test 05c470688d742688e455dd56816bd6bcffa298f8
+F test/walfault.test 1211c3c5f35142d93940c709c61fbaf58c3afab6
F test/walhook.test ed00a40ba7255da22d6b66433ab61fab16a63483
F test/walmode.test 22ddccd073c817ac9ead62b88ac446e8dedc7d2c
+F test/walnoshm.test 732391f72af2785d2758aaa8f9ae563d6d519b20
F test/walshared.test 6dda2293880c300baf5d791c307f653094585761
F test/walslow.test d21625e2e99e11c032ce949e8a94661576548933
F test/walthread.test a25a393c068a2b42b44333fa3fdaae9072f1617c
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P 582db83294599ffd7265d3ab2db2765e7e4fbb8d
-R a1ed7a266761633aef3d19047277de6a
-U drh
-Z 4f48c9a1b8040f4fd58227e590b304c6
------BEGIN PGP SIGNATURE-----
-Version: GnuPG v1.4.6 (GNU/Linux)
-
-iD8DBQFMzs/6oxKgR168RlERAuCbAJ9uimmTB547wDq4mUtvniDAfA0HTwCeNbhj
-lkScdJYDKuse8cKgqrNrUF4=
-=7Gng
------END PGP SIGNATURE-----
+P db64843b540d23c58fe4de199a7fc40d44900bc4
+R 2b6e847446dd321925fabfa8d797522d
+U dan
+Z 4b3ff964892084a664463cd0c913ef99
-db64843b540d23c58fe4de199a7fc40d44900bc4
\ No newline at end of file
+8dd5c69198619866923c6053b71899c1fb8c4c67
\ No newline at end of file
static int pagerUnlockDb(Pager *pPager, int eLock){
int rc = SQLITE_OK;
- assert( !pPager->exclusiveMode );
+ assert( !pPager->exclusiveMode || pPager->eLock==eLock );
assert( eLock==NO_LOCK || eLock==SHARED_LOCK );
assert( eLock!=NO_LOCK || pagerUseWal(pPager)==0 );
if( isOpen(pPager->fd) ){
|| eMode==PAGER_LOCKINGMODE_EXCLUSIVE );
assert( PAGER_LOCKINGMODE_QUERY<0 );
assert( PAGER_LOCKINGMODE_NORMAL>=0 && PAGER_LOCKINGMODE_EXCLUSIVE>=0 );
- if( eMode>=0 && !pPager->tempFile ){
+ assert( pPager->exclusiveMode || 0==sqlite3WalHeapMemory(pPager->pWal) );
+ if( eMode>=0 && !pPager->tempFile && !sqlite3WalHeapMemory(pPager->pWal) ){
pPager->exclusiveMode = (u8)eMode;
}
return (int)pPager->exclusiveMode;
*/
int sqlite3PagerWalSupported(Pager *pPager){
const sqlite3_io_methods *pMethods = pPager->fd->pMethods;
- return pMethods->iVersion>=2 && pMethods->xShmMap!=0;
+ return pPager->exclusiveMode || (pMethods->iVersion>=2 && pMethods->xShmMap);
}
+/*
+** Attempt to take an exclusive lock on the database file. If a PENDING lock
+** is obtained instead, immediately release it.
+*/
+static int pagerExclusiveLock(Pager *pPager){
+ int rc; /* Return code */
+
+ assert( pPager->eLock==SHARED_LOCK || pPager->eLock==EXCLUSIVE_LOCK );
+ rc = pagerLockDb(pPager, EXCLUSIVE_LOCK);
+ if( rc!=SQLITE_OK ){
+ /* If the attempt to grab the pending lock failed, release the
+ ** exclusive lock that may have been obtained instead. */
+ pagerUnlockDb(pPager, SHARED_LOCK);
+ }
+
+ return rc;
+}
+
+/*
+** Call sqlite3WalOpen() to open the WAL handle. If the pager is in
+** exclusive-locking mode when this function is called, take an EXCLUSIVE
+** lock on the database file and use heap-memory to store the wal-index
+** in. Otherwise, use the normal shared-memory.
+*/
+static int pagerOpenWal(Pager *pPager){
+ int rc = SQLITE_OK;
+
+ assert( pPager->pWal==0 && pPager->tempFile==0 );
+ assert( pPager->eLock==SHARED_LOCK || pPager->eLock==EXCLUSIVE_LOCK );
+
+ /* If the pager is already in exclusive-mode, the WAL module will use
+ ** heap-memory for the wal-index instead of the VFS shared-memory
+ ** implementation. Take the exclusive lock now, before opening the WAL
+ ** file, to make sure this is safe.
+ */
+ if( pPager->exclusiveMode ){
+ rc = pagerExclusiveLock(pPager);
+ }
+
+ /* Open the connection to the log file. If this operation fails,
+ ** (e.g. due to malloc() failure), return an error code.
+ */
+ if( rc==SQLITE_OK ){
+ rc = sqlite3WalOpen(pPager->pVfs,
+ pPager->fd, pPager->zWal, pPager->exclusiveMode, &pPager->pWal
+ );
+ }
+
+ return rc;
+}
+
+
/*
** The caller must be holding a SHARED lock on the database file to call
** this function.
/* Close any rollback journal previously open */
sqlite3OsClose(pPager->jfd);
- /* Open the connection to the log file. If this operation fails,
- ** (e.g. due to malloc() failure), unlock the database file and
- ** return an error code.
- */
- rc = sqlite3WalOpen(pPager->pVfs, pPager->fd, pPager->zWal, &pPager->pWal);
+ rc = pagerOpenWal(pPager);
if( rc==SQLITE_OK ){
pPager->journalMode = PAGER_JOURNALMODE_WAL;
pPager->eState = PAGER_OPEN;
);
}
if( rc==SQLITE_OK && logexists ){
- rc = sqlite3WalOpen(pPager->pVfs, pPager->fd,
- pPager->zWal, &pPager->pWal);
+ rc = pagerOpenWal(pPager);
}
}
** the database file, the log and log-summary files will be deleted.
*/
if( rc==SQLITE_OK && pPager->pWal ){
- rc = pagerLockDb(pPager, EXCLUSIVE_LOCK);
+ rc = pagerExclusiveLock(pPager);
if( rc==SQLITE_OK ){
rc = sqlite3WalClose(pPager->pWal,
- (pPager->noSync ? 0 : pPager->sync_flags),
- pPager->pageSize, (u8*)pPager->pTmpSpace
+ (pPager->noSync ? 0 : pPager->sync_flags),
+ pPager->pageSize, (u8*)pPager->pTmpSpace
);
pPager->pWal = 0;
- }else{
- /* If we cannot get an EXCLUSIVE lock, downgrade the PENDING lock
- ** that we did get back to SHARED. */
- pagerUnlockDb(pPager, SQLITE_LOCK_SHARED);
}
}
return rc;
** -default BOOLEAN (True to make the vfs default. Default false)
** -szosfile INTEGER (Value for sqlite3_vfs.szOsFile)
** -mxpathname INTEGER (Value for sqlite3_vfs.mxPathname)
+** -iversion INTEGER (Value for sqlite3_vfs.iVersion)
*/
#include "sqlite3.h"
#endif
};
+/*
+** Candidate values for Wal.exclusiveMode.
+*/
+#define WAL_NORMAL_MODE 0
+#define WAL_EXCLUSIVE_MODE 1
+#define WAL_HEAPMEMORY_MODE 2
+
/*
** Each page of the wal-index mapping contains a hash-table made up of
** an array of HASHTABLE_NSLOT elements of the following type.
/* Request a pointer to the required page from the VFS */
if( pWal->apWiData[iPage]==0 ){
- rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ,
- pWal->writeLock, (void volatile **)&pWal->apWiData[iPage]
- );
+ if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ){
+ pWal->apWiData[iPage] = (u32 volatile *)sqlite3MallocZero(WALINDEX_PGSZ);
+ if( !pWal->apWiData[iPage] ) rc = SQLITE_NOMEM;
+ }else{
+ rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ,
+ pWal->writeLock, (void volatile **)&pWal->apWiData[iPage]
+ );
+ }
}
*ppPage = pWal->apWiData[iPage];
aOut[1] = s2;
}
+static void walShmBarrier(Wal *pWal){
+ if( pWal->exclusiveMode!=WAL_HEAPMEMORY_MODE ){
+ sqlite3OsShmBarrier(pWal->pDbFd);
+ }
+}
+
/*
** Write the header information in pWal->hdr into the wal-index.
**
pWal->hdr.iVersion = WALINDEX_MAX_VERSION;
walChecksumBytes(1, (u8*)&pWal->hdr, nCksum, 0, pWal->hdr.aCksum);
memcpy((void *)&aHdr[1], (void *)&pWal->hdr, sizeof(WalIndexHdr));
- sqlite3OsShmBarrier(pWal->pDbFd);
+ walShmBarrier(pWal);
memcpy((void *)&aHdr[0], (void *)&pWal->hdr, sizeof(WalIndexHdr));
}
** Close an open wal-index.
*/
static void walIndexClose(Wal *pWal, int isDelete){
- sqlite3OsShmUnmap(pWal->pDbFd, isDelete);
+ if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ){
+ int i;
+ for(i=0; i<pWal->nWiData; i++){
+ sqlite3_free((void *)pWal->apWiData[i]);
+ pWal->apWiData[i] = 0;
+ }
+ }else{
+ sqlite3OsShmUnmap(pWal->pDbFd, isDelete);
+ }
}
/*
sqlite3_vfs *pVfs, /* vfs module to open wal and wal-index */
sqlite3_file *pDbFd, /* The open database file */
const char *zWalName, /* Name of the WAL file */
+ int bNoShm, /* True to run in heap-memory mode */
Wal **ppWal /* OUT: Allocated Wal handle */
){
int rc; /* Return Code */
pRet->pDbFd = pDbFd;
pRet->readLock = -1;
pRet->zWalName = zWalName;
+ pRet->exclusiveMode = (bNoShm ? WAL_HEAPMEMORY_MODE: WAL_NORMAL_MODE);
/* Open file handle on the write-ahead log file. */
flags = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_WAL);
*/
rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE);
if( rc==SQLITE_OK ){
- pWal->exclusiveMode = 1;
+ if( pWal->exclusiveMode==WAL_NORMAL_MODE ){
+ pWal->exclusiveMode = WAL_EXCLUSIVE_MODE;
+ }
rc = sqlite3WalCheckpoint(pWal, sync_flags, nBuf, zBuf);
if( rc==SQLITE_OK ){
isDelete = 1;
*/
aHdr = walIndexHdr(pWal);
memcpy(&h1, (void *)&aHdr[0], sizeof(h1));
- sqlite3OsShmBarrier(pWal->pDbFd);
+ walShmBarrier(pWal);
memcpy(&h2, (void *)&aHdr[1], sizeof(h2));
if( memcmp(&h1, &h2, sizeof(h1))!=0 ){
** and can be safely ignored.
*/
rc = walLockShared(pWal, WAL_READ_LOCK(0));
- sqlite3OsShmBarrier(pWal->pDbFd);
+ walShmBarrier(pWal);
if( rc==SQLITE_OK ){
if( memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr)) ){
/* It is not safe to allow the reader to continue here if frames
** log-wrap (either of which would require an exclusive lock on
** WAL_READ_LOCK(mxI)) has not occurred since the snapshot was valid.
*/
- sqlite3OsShmBarrier(pWal->pDbFd);
+ walShmBarrier(pWal);
if( pInfo->aReadMark[mxI]!=mxReadMark
|| memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr))
){
** on the main database file before invoking this operation.
**
** If op is negative, then do a dry-run of the op==1 case but do
-** not actually change anything. The pager uses this to see if it
+** not actually change anything. The pager uses this to see if it
** should acquire the database exclusive lock prior to invoking
** the op==1 case.
*/
int sqlite3WalExclusiveMode(Wal *pWal, int op){
int rc;
assert( pWal->writeLock==0 );
+ assert( pWal->exclusiveMode!=WAL_HEAPMEMORY_MODE || op==-1 );
/* pWal->readLock is usually set, but might be -1 if there was a
** prior error while attempting to acquire are read-lock. This cannot
return rc;
}
+/*
+** Return true if the argument is non-NULL and the WAL module is using
+** heap-memory for the wal-index. Otherwise, if the argument is NULL or the
+** WAL module is using shared-memory, return false.
+*/
+int sqlite3WalHeapMemory(Wal *pWal){
+ return (pWal && pWal->exclusiveMode==WAL_HEAPMEMORY_MODE );
+}
+
#endif /* #ifndef SQLITE_OMIT_WAL */
# define sqlite3WalCheckpoint(u,v,w,x) 0
# define sqlite3WalCallback(z) 0
# define sqlite3WalExclusiveMode(y,z) 0
+# define sqlite3WalHeapMemory(z) 0
#else
#define WAL_SAVEPOINT_NDATA 4
typedef struct Wal Wal;
/* Open and close a connection to a write-ahead log. */
-int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *zName, Wal**);
+int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *zName, int, Wal**);
int sqlite3WalClose(Wal *pWal, int sync_flags, int, u8 *);
/* Used by readers to open (lock) and close (unlock) a snapshot. A
*/
int sqlite3WalExclusiveMode(Wal *pWal, int op);
+/* Return true if the argument is non-NULL and the WAL module is using
+** heap-memory for the wal-index. Otherwise, if the argument is NULL or the
+** WAL module is using shared-memory, return false.
+*/
+int sqlite3WalHeapMemory(Wal *pWal);
+
#endif /* ifndef SQLITE_OMIT_WAL */
#endif /* _WAL_H_ */
COMMIT;
} {1 2} 0 -1
- 4 { PRAGMA journal_mode = WAL } wal -1 -1
- 5 { INSERT INTO t1 VALUES(3, 4) } {} -1 [wal_file_size 1 1024]
- 6 { PRAGMA locking_mode = NORMAL } normal -1 [wal_file_size 1 1024]
- 7 { INSERT INTO t1 VALUES(5, 6); } {} -1 [wal_file_size 2 1024]
+ 4 { PRAGMA journal_mode = WAL } wal -1 -1
+ 5 { INSERT INTO t1 VALUES(3, 4) } {} -1 [wal_file_size 1 1024]
+ 6 { PRAGMA locking_mode = NORMAL } exclusive -1 [wal_file_size 1 1024]
+ 7 { INSERT INTO t1 VALUES(5, 6); } {} -1 [wal_file_size 2 1024]
8 { PRAGMA journal_mode = TRUNCATE } truncate 0 -1
9 { INSERT INTO t1 VALUES(7, 8) } {} 0 -1
} -files {
wal.test wal2.test wal3.test walmode.test
walbak.test walhook.test walcrash2.test walcksum.test
- walfault.test walbig.test
+ walfault.test walbig.test walnoshm.test
}
test_suite "coverage-pager" -description {
global argv cmdlinearg
+ fix_testname name
+
sqlite3_memdebug_settitle $name
# if {[llength $argv]==0} {
sqlite3 db test.db
execsql {
Pragma Journal_Mode = Wal;
- Pragma Locking_Mode = Exclusive;
}
-} {wal exclusive}
+} {wal}
do_test wal2-6.1.2 {
execsql { PRAGMA lock_status }
} {main unlocked temp closed}
do_test wal2-6.1.3 {
+ execsql {
+ SELECT * FROM sqlite_master;
+ Pragma Locking_Mode = Exclusive;
+ }
execsql {
BEGIN;
CREATE TABLE t1(a, b);
do_test wal2-6.2.3 {
db close
sqlite3 db test.db
+ execsql { SELECT * FROM sqlite_master }
execsql { PRAGMA LOCKING_MODE = EXCLUSIVE }
} {exclusive}
do_test wal2-6.2.4 {
T script lock_control
T filter {}
sqlite3 db test.db -vfs T
+ execsql { SELECT * FROM sqlite_master }
execsql { PRAGMA locking_mode = exclusive }
execsql { INSERT INTO t2 VALUES('V', 'VI') }
} {}
T filter {}
execsql { INSERT INTO t2 VALUES('IX', 'X') }
} {}
-do_test wal2-6.6.3 {
+do_test wal2-6.6.4 {
# This time, we have successfully exited exclusive mode. So the second
# connection can read the database.
sqlite3 db2 test.db -vfs T
faultsim_test_result {0 {}}
}
+#-------------------------------------------------------------------------
+# Test simple recovery, reading and writing a database file using a
+# heap-memory wal-index.
+#
+do_test walfault-13-pre-1 {
+ faultsim_delete_and_reopen
+ execsql {
+ PRAGMA journal_mode = WAL;
+ PRAGMA wal_autocheckpoint = 0;
+ BEGIN;
+ CREATE TABLE abc(a PRIMARY KEY);
+ INSERT INTO abc VALUES(randomblob(1500));
+ INSERT INTO abc VALUES(randomblob(1500));
+ COMMIT;
+ }
+ faultsim_save_and_close
+ file delete sv_test.db-shm
+} {}
+
+do_faultsim_test walfault-13.1 -prep {
+ faultsim_restore_and_reopen
+} -body {
+ db eval { PRAGMA locking_mode = exclusive }
+ db eval { SELECT count(*) FROM abc }
+} -test {
+ faultsim_test_result {0 2}
+ if {[file exists test.db-shm]} { error "Not using heap-memory mode" }
+ faultsim_integrity_check
+}
+
+do_faultsim_test walfault-13.2 -prep {
+ faultsim_restore_and_reopen
+ db eval { PRAGMA locking_mode = exclusive }
+} -body {
+ db eval { PRAGMA journal_mode = delete }
+} -test {
+ faultsim_test_result {0 delete}
+ if {[file exists test.db-shm]} { error "Not using heap-memory mode" }
+ faultsim_integrity_check
+}
+
+do_test walfault-13-pre-2 {
+ faultsim_delete_and_reopen
+ execsql {
+ BEGIN;
+ CREATE TABLE abc(a PRIMARY KEY);
+ INSERT INTO abc VALUES(randomblob(1500));
+ INSERT INTO abc VALUES(randomblob(1500));
+ COMMIT;
+ }
+ faultsim_save_and_close
+} {}
+
+do_faultsim_test walfault-13.3 -prep {
+ faultsim_restore_and_reopen
+} -body {
+ db eval {
+ PRAGMA locking_mode = exclusive;
+ PRAGMA journal_mode = WAL;
+ INSERT INTO abc VALUES(randomblob(1500));
+ }
+} -test {
+ faultsim_test_result {0 {exclusive wal}}
+ if {[file exists test.db-shm]} { error "Not using heap-memory mode" }
+ faultsim_integrity_check
+ set nRow [db eval {SELECT count(*) FROM abc}]
+ if {!(($nRow==2 && $testrc) || $nRow==3)} { error "Bad db content" }
+}
finish_test
--- /dev/null
+# 2010 November 1
+#
+# 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 implements regression tests for SQLite library. The
+# focus of this file is testing that WAL databases may be accessed without
+# using the xShm primitives if the connection is in exclusive-mode.
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+set testprefix walnoshm
+ifcapable !wal {finish_test ; return }
+
+db close
+testvfs tvfsshm
+testvfs tvfs -default 1 -iversion 1
+sqlite3 db test.db
+
+#--------------------------------------------------------------------------
+# Test that when using a version 1 VFS, a database can only be converted
+# to WAL mode after setting locking_mode=EXCLUSIVE. Also, test that if a
+# WAL database is opened using heap-memory for the WAL index, the connection
+# cannot change back to locking_mode=NORMAL while the database is still in
+# WAL mode.
+#
+do_execsql_test 1.1 {
+ CREATE TABLE t1(x, y);
+ INSERT INTO t1 VALUES(1, 2);
+}
+
+do_execsql_test 1.2 {
+ PRAGMA journal_mode = WAL;
+ SELECT * FROM t1;
+} {delete 1 2}
+do_test 1.3 { file exists test.db-wal } {0}
+
+do_execsql_test 1.4 {
+ PRAGMA locking_mode = exclusive;
+ PRAGMA journal_mode = WAL;
+ SELECT * FROM t1;
+} {exclusive wal 1 2}
+do_test 1.5 { file exists test.db-wal } {1}
+
+do_execsql_test 1.6 { INSERT INTO t1 VALUES(3, 4) }
+
+do_execsql_test 1.7 {
+ PRAGMA locking_mode = normal;
+} {exclusive}
+do_execsql_test 1.8 {
+ PRAGMA journal_mode = delete;
+ PRAGMA main.locking_mode;
+} {delete exclusive}
+do_execsql_test 1.9 {
+ PRAGMA locking_mode = normal;
+} {normal}
+do_execsql_test 1.10 {
+ SELECT * FROM t1;
+} {1 2 3 4}
+do_test 1.11 { file exists test.db-wal } {0}
+
+#-------------------------------------------------------------------------
+#
+# 2.1.*: Test that a connection using a version 1 VFS can open a WAL database
+# and convert it to rollback mode if it is set to use
+# locking_mode=exclusive.
+#
+# 2.2.*: Test that if the exclusive lock cannot be obtained while attempting
+# the above, the operation fails and the WAL file is not opened.
+#
+do_execsql_test 2.1.1 {
+ CREATE TABLE t2(x, y);
+ INSERT INTO t2 VALUES('a', 'b');
+ INSERT INTO t2 VALUES('c', 'd');
+}
+do_execsql_test 2.1.2 {
+ PRAGMA locking_mode = exclusive;
+ PRAGMA journal_mode = WAL;
+ INSERT INTO t2 VALUES('e', 'f');
+ INSERT INTO t2 VALUES('g', 'h');
+} {exclusive wal}
+
+do_test 2.1.3 {
+ file copy -force test.db test2.db
+ file copy -force test.db-wal test2.db-wal
+ sqlite3 db2 test2.db
+ catchsql { SELECT * FROM t2 } db2
+} {1 {unable to open database file}}
+do_test 2.1.4 {
+ catchsql { PRAGMA journal_mode = delete } db2
+} {1 {unable to open database file}}
+do_test 2.1.5 {
+ execsql {
+ PRAGMA locking_mode = exclusive;
+ PRAGMA journal_mode = delete;
+ SELECT * FROM t2;
+ } db2
+} {exclusive delete a b c d e f g h}
+
+do_test 2.2.1 {
+ file copy -force test.db test2.db
+ file copy -force test.db-wal test2.db-wal
+ sqlite3 db3 test2.db -vfs tvfsshm
+ sqlite3 db2 test2.db
+ execsql { SELECT * FROM t2 } db3
+} {a b c d e f g h}
+
+do_test 2.2.2 {
+ execsql { PRAGMA locking_mode = exclusive } db2
+ catchsql { PRAGMA journal_mode = delete } db2
+} {1 {database is locked}}
+
+do_test 2.2.3 {
+ # This is to test that [db2] is not holding a PENDING lock (which can
+ # happen when an attempt to obtain an EXCLUSIVE lock fails).
+ sqlite3 db4 test2.db -vfs tvfsshm
+ execsql { SELECT * FROM t2 } db4
+} {a b c d e f g h}
+
+do_test 2.2.4 {
+ catchsql { SELECT * FROM t2 } db2
+} {1 {database is locked}}
+
+do_test 2.2.5 {
+ db4 close
+ sqlite3 db4 test2.db -vfs tvfsshm
+ execsql { SELECT * FROM t2 } db4
+} {a b c d e f g h}
+
+do_test 2.2.6 {
+ db3 close
+ db4 close
+ execsql { SELECT * FROM t2 } db2
+} {a b c d e f g h}
+
+db2 close
+
+
+finish_test
+