mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-30 19:03:16 +03:00
If a database file with the WAL flag set is opened in exclusive-locking mode, use heap memory to store the wal-index instead of shared-memory.
FossilOrigin-Name: 8dd5c69198619866923c6053b71899c1fb8c4c67
This commit is contained in:
41
manifest
41
manifest
@ -1,8 +1,5 @@
|
||||
-----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
|
||||
@ -165,7 +162,7 @@ F src/os_common.h a8f95b81eca8a1ab8593d23e94f8a35f35d4078f
|
||||
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
|
||||
@ -221,7 +218,7 @@ F src/test_server.c bbba05c144b5fc4b52ff650a4328027b3fa5fcc6
|
||||
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
|
||||
@ -238,8 +235,8 @@ F src/vdbeblob.c e0ce3c54cc0c183af2ec67b63a289acf92251df4
|
||||
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
|
||||
@ -569,7 +566,7 @@ F test/notify3.test d60923e186e0900f4812a845fcdfd8eea096e33a
|
||||
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
|
||||
@ -578,7 +575,7 @@ F test/pageropt.test 8146bf448cf09e87bb1867c2217b921fb5857806
|
||||
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
|
||||
@ -655,7 +652,7 @@ F test/tclsqlite.test 8c154101e704170c2be10f137a5499ac2c6da8d3
|
||||
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
|
||||
@ -823,7 +820,7 @@ F test/vtab_alter.test 9e374885248f69e251bdaacf480b04a197f125e5
|
||||
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
|
||||
@ -832,9 +829,10 @@ F test/walbig.test e882bc1d014afffbfa2b6ba36e0f07d30a633ad0
|
||||
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
|
||||
@ -884,14 +882,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
||||
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
|
||||
|
@ -1 +1 @@
|
||||
db64843b540d23c58fe4de199a7fc40d44900bc4
|
||||
8dd5c69198619866923c6053b71899c1fb8c4c67
|
78
src/pager.c
78
src/pager.c
@ -1050,7 +1050,7 @@ static int write32bits(sqlite3_file *fd, i64 offset, u32 val){
|
||||
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) ){
|
||||
@ -6350,7 +6350,8 @@ int sqlite3PagerLockingMode(Pager *pPager, int eMode){
|
||||
|| 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;
|
||||
@ -6537,9 +6538,61 @@ int sqlite3PagerWalCallback(Pager *pPager){
|
||||
*/
|
||||
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.
|
||||
@ -6573,11 +6626,7 @@ int sqlite3PagerOpenWal(
|
||||
/* 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;
|
||||
@ -6616,8 +6665,7 @@ int sqlite3PagerCloseWal(Pager *pPager){
|
||||
);
|
||||
}
|
||||
if( rc==SQLITE_OK && logexists ){
|
||||
rc = sqlite3WalOpen(pPager->pVfs, pPager->fd,
|
||||
pPager->zWal, &pPager->pWal);
|
||||
rc = pagerOpenWal(pPager);
|
||||
}
|
||||
}
|
||||
|
||||
@ -6625,17 +6673,13 @@ int sqlite3PagerCloseWal(Pager *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;
|
||||
|
@ -26,6 +26,7 @@
|
||||
** -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"
|
||||
|
60
src/wal.c
60
src/wal.c
@ -428,6 +428,13 @@ struct Wal {
|
||||
#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.
|
||||
@ -514,9 +521,14 @@ static int walIndexPage(Wal *pWal, int iPage, volatile u32 **ppPage){
|
||||
|
||||
/* 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];
|
||||
@ -599,6 +611,12 @@ static void walChecksumBytes(
|
||||
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.
|
||||
**
|
||||
@ -613,7 +631,7 @@ static void walIndexWriteHdr(Wal *pWal){
|
||||
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));
|
||||
}
|
||||
|
||||
@ -1185,7 +1203,15 @@ recovery_error:
|
||||
** 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);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1207,6 +1233,7 @@ int sqlite3WalOpen(
|
||||
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 */
|
||||
@ -1240,6 +1267,7 @@ int sqlite3WalOpen(
|
||||
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);
|
||||
@ -1673,7 +1701,9 @@ int sqlite3WalClose(
|
||||
*/
|
||||
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;
|
||||
@ -1729,7 +1759,7 @@ static int walIndexTryHdr(Wal *pWal, int *pChanged){
|
||||
*/
|
||||
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 ){
|
||||
@ -1930,7 +1960,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
|
||||
** 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
|
||||
@ -2024,7 +2054,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
|
||||
** 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))
|
||||
){
|
||||
@ -2667,13 +2697,14 @@ int sqlite3WalCallback(Wal *pWal){
|
||||
** 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
|
||||
@ -2707,4 +2738,13 @@ int sqlite3WalExclusiveMode(Wal *pWal, int op){
|
||||
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 */
|
||||
|
@ -35,6 +35,7 @@
|
||||
# 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
|
||||
@ -45,7 +46,7 @@
|
||||
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
|
||||
@ -102,5 +103,11 @@ int sqlite3WalCallback(Wal *pWal);
|
||||
*/
|
||||
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_ */
|
||||
|
@ -1107,10 +1107,10 @@ ifcapable wal {
|
||||
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
|
||||
|
@ -183,7 +183,7 @@ test_suite "coverage-wal" -description {
|
||||
} -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 {
|
||||
|
@ -303,6 +303,8 @@ proc do_test {name cmd expected} {
|
||||
|
||||
global argv cmdlinearg
|
||||
|
||||
fix_testname name
|
||||
|
||||
sqlite3_memdebug_settitle $name
|
||||
|
||||
# if {[llength $argv]==0} {
|
||||
|
@ -430,13 +430,16 @@ do_test wal2-6.1.1 {
|
||||
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);
|
||||
@ -486,6 +489,7 @@ do_test wal2-6.2.2 {
|
||||
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 {
|
||||
@ -732,6 +736,7 @@ do_test wal2-6.6.1 {
|
||||
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') }
|
||||
} {}
|
||||
@ -755,7 +760,7 @@ do_test wal2-6.6.2 {
|
||||
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
|
||||
|
@ -446,5 +446,73 @@ do_faultsim_test walfault-12 -prep {
|
||||
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
|
||||
|
146
test/walnoshm.test
Normal file
146
test/walnoshm.test
Normal file
@ -0,0 +1,146 @@
|
||||
# 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
|
||||
|
Reference in New Issue
Block a user