From: drh Date: Mon, 31 May 2010 20:28:37 +0000 (+0000) Subject: Fix issues with locking_mode=EXCLUSIVE in WAL. X-Git-Tag: version-3.7.2~328^2~10 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=61e4acecf48acd9569ba947a863ca518fa442236;p=thirdparty%2Fsqlite.git Fix issues with locking_mode=EXCLUSIVE in WAL. FossilOrigin-Name: 8deba0cebd135a18da68530fab9e7d19dc21ddcb --- diff --git a/manifest b/manifest index be86961955..7e0cdb20dd 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,8 @@ -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 -C Add\san\s"isInit"\sfield\sin\sthe\swal-index\sheader\sthat\smust\sbe\snon-zero\sfor\na\svalid\sheader.\s\sUse\sthis\sto\sdetect\san\suninitialized\swal-index. -D 2010-05-31T18:24:19 +C Fix\sissues\swith\slocking_mode=EXCLUSIVE\sin\sWAL. +D 2010-05-31T20:28:38 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.in a5cad1f8f3e021356bfcc6c77dc16f6f1952bbc3 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -155,9 +155,9 @@ F src/os.c 1516984144e26734f97748f891f1a04f9e294c2e F src/os.h 6f604986f0ef0ca288c2330b16051ff70b431e8c F src/os_common.h a8f95b81eca8a1ab8593d23e94f8a35f35d4078f F src/os_os2.c 665876d5eec7585226b0a1cf5e18098de2b2da19 -F src/os_unix.c 18ed6016685593e23c0e559804dd391a030dfb62 +F src/os_unix.c 129e60ccca3abe59ca4374e28138c540c1069a09 F src/os_win.c f815403c51a2adad30244374c801dd7fd2734567 -F src/pager.c f7128f02623beab9462ca6e73516cf73c49186f8 +F src/pager.c acbef227bf158776449907c275c5d9332e4e52f9 F src/pager.h 76466c3a5af56943537f68b1f16567101a0cd1d0 F src/parse.y ace5c7a125d9f2a410e431ee3209034105045f7e F src/pcache.c ace8f6a5ecd4711cc66a1b23053be7109bd437cf @@ -227,7 +227,7 @@ F src/vdbeblob.c 5327132a42a91e8b7acfb60b9d2c3b1c5c863e0e F src/vdbemem.c 2a82f455f6ca6f78b59fb312f96054c04ae0ead1 F src/vdbetrace.c 864cef96919323482ebd9986f2132435115e9cc2 F src/vtab.c a0f8a40274e4261696ef57aa806de2776ab72cda -F src/wal.c a20a069a7ed79ea16cccbf0d83a34d5e2a7250a6 +F src/wal.c b3f312fe54d298f965de98870af9eae0c5829310 F src/wal.h 1c1c9feb629b7f4afcbe0b47f80f47c5551d3a02 F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f F src/where.c 75fee9e255b62f773fcadd1d1f25b6f63ac7a356 @@ -818,14 +818,14 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 552658da2845c2323167b6c7db6e5c00090f280c -R cd1f6d6abaca428c2e0680ad6a01cc30 +P a16fde190183d1ae252d1aa305b23fdb88c603dc +R 7ca4bba7f34b45ef2eb156ca8f31e257 U drh -Z 611237a4cf581f565db3251639fe3292 +Z 95075c06905af9e6fca1be95088ee79b -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) -iD8DBQFMA/7XoxKgR168RlERAvMDAJ41dyIAjGkayTRj8Kw2ioAehVpN+QCfbTwC -9y9JhOrCL2VhmOxcK/DziJQ= -=4aF+ +iD8DBQFMBBv5oxKgR168RlERAmKCAJ953sKjjyeIhzGjYESyG8xuJ6EZyQCfcwsk +dvi+rRNsOxQx96r9i6h2uoU= +=APx0 -----END PGP SIGNATURE----- diff --git a/manifest.uuid b/manifest.uuid index 76a2a6d7bc..469b85a5d5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a16fde190183d1ae252d1aa305b23fdb88c603dc \ No newline at end of file +8deba0cebd135a18da68530fab9e7d19dc21ddcb \ No newline at end of file diff --git a/src/os_unix.c b/src/os_unix.c index 91f641e057..c6ca5fc468 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -3399,10 +3399,6 @@ static int unixShmClose( assert( pShmNode==pDbFd->pInode->pShmNode ); assert( pShmNode->pInode==pDbFd->pInode ); - /* Verify that the connection being closed holds no locks */ - assert( p->exclMask==0 ); - assert( p->sharedMask==0 ); - /* Remove connection p from the set of connections associated ** with pShmNode */ sqlite3_mutex_enter(pShmNode->mutex); diff --git a/src/pager.c b/src/pager.c index a88ec5cab9..3eb1233483 100644 --- a/src/pager.c +++ b/src/pager.c @@ -1445,9 +1445,8 @@ static int pager_end_transaction(Pager *pPager, int hasMaster){ */ if( rc2==SQLITE_OK && !pPager->exclusiveMode - && sqlite3WalExclusiveMode(pPager->pWal, -1) + && sqlite3WalExclusiveMode(pPager->pWal, 0) ){ - sqlite3WalExclusiveMode(pPager->pWal, 0); rc2 = osUnlock(pPager->fd, SHARED_LOCK); } }else if( !pPager->exclusiveMode ){ @@ -2375,6 +2374,13 @@ static int pagerBeginReadTransaction(Pager *pPager){ assert( pagerUseWal(pPager) ); + /* sqlite3WalEndReadTransaction() was not called for the previous + ** transaction in locking_mode=EXCLUSIVE. So call it now. If we + ** are in locking_mode=NORMAL and EndRead() was previously called, + ** the duplicate call is harmless. + */ + sqlite3WalEndReadTransaction(pPager->pWal); + rc = sqlite3WalBeginReadTransaction(pPager->pWal, &changed); if( rc==SQLITE_OK ){ int dummy; @@ -4546,7 +4552,7 @@ int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory){ /* If the pager is configured to use locking_mode=exclusive, and an ** exclusive lock on the database is not already held, obtain it now. */ - if( pPager->exclusiveMode && !sqlite3WalExclusiveMode(pPager->pWal, -1) ){ + if( pPager->exclusiveMode && sqlite3WalExclusiveMode(pPager->pWal, -1) ){ rc = sqlite3OsLock(pPager->fd, EXCLUSIVE_LOCK); pPager->state = PAGER_SHARED; if( rc!=SQLITE_OK ){ diff --git a/src/wal.c b/src/wal.c index 9801565c3e..99d884c463 100644 --- a/src/wal.c +++ b/src/wal.c @@ -1693,7 +1693,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal){ int i; /* Loop counter */ int rc; /* Return code */ - assert( pWal->readLock<0 ); /* No read lock held on entry */ + assert( pWal->readLock<0 ); /* Not currently locked */ if( !useWal ){ rc = walIndexReadHdr(pWal, pChanged); @@ -2350,29 +2350,54 @@ int sqlite3WalCallback(Wal *pWal){ } /* -** This function is called to set or query the exclusive-mode flag -** associated with the WAL connection passed as the first argument. The -** exclusive-mode flag should be set to indicate that the caller is -** holding an EXCLUSIVE lock on the database file (it does this in -** locking_mode=exclusive mode). If the EXCLUSIVE lock is to be dropped, -** the flag set by this function should be cleared before doing so. -** -** When the flag is set, this module does not call the VFS xShmLock() -** method to obtain any locks on the wal-index (as it assumes it -** has exclusive access to the wal and wal-index files anyhow). It -** continues to hold (and does not drop) the existing READ lock on -** the wal-index. -** -** To set or clear the flag, the "op" parameter is passed 1 or 0, -** respectively. To query the flag, pass -1. In all cases, the value -** returned is the value of the exclusive-mode flag (after its value -** has been modified, if applicable). +** This function is called to change the WAL subsystem into or out +** of locking_mode=EXCLUSIVE. +** +** If op is zero, then attempt to change from locking_mode=EXCLUSIVE +** into locking_mode=NORMAL. This means that we must acquire a lock +** on the pWal->readLock byte. If the WAL is already in locking_mode=NORMAL +** or if the acquisition of the lock fails, then return 0. If the +** transition out of exclusive-mode is successful, return 1. This +** operation must occur while the pager is still holding the exclusive +** lock on the main database file. +** +** If op is one, then change from locking_mode=NORMAL into +** locking_mode=EXCLUSIVE. This means that the pWal->readLock must +** be released. Return 1 if the transition is made and 0 if the +** WAL is already in exclusive-locking mode - meaning that this +** routine is a no-op. The pager must already hold the exclusive lock +** 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 +** should acquire the database exclusive lock prior to invoking +** the op==1 case. */ int sqlite3WalExclusiveMode(Wal *pWal, int op){ - if( op>=0 ){ - pWal->exclusiveMode = (u8)op; + int rc; + assert( pWal->writeLock==0 && pWal->readLock>=0 ); + if( op==0 ){ + if( pWal->exclusiveMode ){ + pWal->exclusiveMode = 0; + if( walLockShared(pWal, WAL_READ_LOCK(pWal->readLock))!=SQLITE_OK ){ + pWal->exclusiveMode = 1; + } + rc = pWal->exclusiveMode==0; + }else{ + /* No changes. Either already in locking_mode=NORMAL or else the + ** acquisition of the read-lock failed. The pager must continue to + ** hold the database exclusive lock. */ + rc = 0; + } + }else if( op>0 ){ + assert( pWal->exclusiveMode==0 ); + walUnlockShared(pWal, WAL_READ_LOCK(pWal->readLock)); + pWal->exclusiveMode = 1; + rc = 1; + }else{ + rc = pWal->exclusiveMode==0; } - return pWal->exclusiveMode; + return rc; } #endif /* #ifndef SQLITE_OMIT_WAL */