From: drh Date: Tue, 8 Jun 2004 00:47:47 +0000 (+0000) Subject: Do not require a RESERVED lock when transitioning from SHARED to EXCLUSIVE. (CVS... X-Git-Tag: version-3.6.10~4533 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b3e043463d01e0bd0037ae692239df2b403b447f;p=thirdparty%2Fsqlite.git Do not require a RESERVED lock when transitioning from SHARED to EXCLUSIVE. (CVS 1542) FossilOrigin-Name: 4dfdea7373f3471d17498da3d6c3aaf926a72d4b --- diff --git a/manifest b/manifest index 14d333b338..dc4d7729cc 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\sthe\sbuilt-in\sfunction\squote()\sto\ssupport\sblob\svalues.\s(CVS\s1541) -D 2004-06-08T00:39:01 +C Do\snot\srequire\sa\sRESERVED\slock\swhen\stransitioning\sfrom\sSHARED\sto\sEXCLUSIVE.\s(CVS\s1542) +D 2004-06-08T00:47:47 F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd @@ -43,9 +43,9 @@ F src/os.h a3a9c2df29acbff54aef742e85c302d23634019f F src/os_common.h 12074232439f904b3805beeff1245bd1b5532994 F src/os_mac.c b823874690615ace0dd520d3ad1fe8bfd864b7e0 F src/os_mac.h 51d2445f47e182ed32d3bd6937f81070c6fd9bd4 -F src/os_unix.c f78604d00c0769e4ffa481dba110cdd098cc276b +F src/os_unix.c 3747274f2712e95f605c0ec66df5ad26e3711e82 F src/os_unix.h 7999f2246c6347707e98f7078871ea8ca605df3f -F src/os_win.c 5c46f81f76f2be0c0817773a865c075c56496018 +F src/os_win.c a13b85a0d4889e3d0b254ed2a61354acddc59fc4 F src/os_win.h 004eec47b1780fcaf07420ddc2072294b698d48c F src/pager.c 3fddd1e5b3e449b19e4f762ab1f1d10786d56d28 F src/pager.h 0c7b5ac45c69e690c45d160d03bdc8fbd2d4657b @@ -215,7 +215,7 @@ F www/support.tcl 1801397edd271cc39a2aadd54e701184b5181248 F www/tclsqlite.tcl 19191cf2a1010eaeff74c51d83fd5f5a4d899075 F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9 F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4 -P 62e31f396cb6b49f542977e2fade78e11e371132 -R 87169ec73e15b83e9be0f5b8ac7aaebe -U danielk1977 -Z e31a621434c9bec95d63eda46f31cc00 +P 97aa54bb70715934e0af082d51b9b0f6bb847e8e +R b382950b985a7f7c010fa51e63195e87 +U drh +Z 979bdbef9456a09bba11f45e5a0188cd diff --git a/manifest.uuid b/manifest.uuid index 84b3f262b8..fb0060ce47 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -97aa54bb70715934e0af082d51b9b0f6bb847e8e \ No newline at end of file +4dfdea7373f3471d17498da3d6c3aaf926a72d4b \ No newline at end of file diff --git a/src/os_unix.c b/src/os_unix.c index 110dca38da..3d4710e359 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -686,15 +686,17 @@ int sqlite3OsCheckWriteLock(OsFile *id){ ** (3) PENDING_LOCK ** (4) EXCLUSIVE_LOCK ** -** Locks are are hierarchical. Getting a lock N implies getting all locks -** N-1, N-2, N-3, .... So, for example, getting a PENDING lock -** implies a SHARED and a RESERVED lock. This routine adds locks one -** at a time until the desired lock is acheived. A locking failure might -** occur at any point. When a failure occurs intermediate locks are -** retained. For example, if a SHARED lock is held and this routine -** is called with EXCLUSIVE, it might obtain a RESERVED and PENDING lock -** but fail to get the EXCLUSIVE lock. In that case, the file would be -** left in the PENDING lock state - it does not revert to SHARED. +** Sometimes when requesting one lock state, additional lock states +** are inserted in between. The locking might fail on one of the later +** transitions leaving the lock state different from what it started but +** still short of its goal. The following chart shows the allowed +** transitions and the inserted intermediate states: +** +** UNLOCKED -> SHARED +** SHARED -> RESERVED +** SHARED -> (PENDING) -> EXCLUSIVE +** RESERVED -> (PENDING) -> EXCLUSIVE +** PENDING -> EXCLUSIVE ** ** This routine will only increase a lock. The sqlite3OsUnlock() routine ** erases all locks at once and returns us immediately to locking level 0. @@ -718,20 +720,15 @@ int sqlite3OsLock(OsFile *id, int locktype){ return SQLITE_OK; } - /* Make sure locking is sequential. In other words, make sure we have - ** SHARED before trying for RESERVED, and that we have RESERVED before - ** trying for PENDING, and that we have PENDING before trying for - ** EXCLUSIVE. + /* Make sure the locking sequence is correct */ - while( locktype>id->locktype+1 ){ - rc = sqlite3OsLock(id, id->locktype+1); - if( rc!=SQLITE_OK ){ - return rc; - } - } - assert( locktype==id->locktype+1 ); + assert( id->locktype!=NO_LOCK || locktype==SHARED_LOCK ); + assert( locktype!=PENDING_LOCK ); + assert( locktype!=RESERVED_LOCK || id->locktype==SHARED_LOCK ); - sqlite3OsEnterMutex(); /* Needed because pLock is shared across threads */ + /* This mutex is needed because id->pLock is shared across threads + */ + sqlite3OsEnterMutex(); /* If some thread using this PID has a lock via a different OsFile* ** handle that precludes the requested lock, return BUSY. diff --git a/src/os_win.c b/src/os_win.c index bc8e02c374..e9356a1b76 100644 --- a/src/os_win.c +++ b/src/os_win.c @@ -368,10 +368,30 @@ static int unlockReadLock(OsFile *id){ } /* -** Acquire a lock of the given type on the specified file. If an -** appropriate lock already exists, this routine is a no-op. Return -** SQLITE_OK on success and SQLITE_BUSY if another thread is already -** holding a conflicting lock. +** Lock the file with the lock specified by parameter locktype - one +** of the following: +** +** (1) SHARED_LOCK +** (2) RESERVED_LOCK +** (3) PENDING_LOCK +** (4) EXCLUSIVE_LOCK +** +** Sometimes when requesting one lock state, additional lock states +** are inserted in between. The locking might fail on one of the later +** transitions leaving the lock state different from what it started but +** still short of its goal. The following chart shows the allowed +** transitions and the inserted intermediate states: +** +** UNLOCKED -> SHARED +** SHARED -> RESERVED +** SHARED -> (PENDING) -> EXCLUSIVE +** RESERVED -> (PENDING) -> EXCLUSIVE +** PENDING -> EXCLUSIVE +** +** This routine will only increase a lock. The sqlite3OsUnlock() routine +** erases all locks at once and returns us immediately to locking level 0. +** It is not possible to lower the locking level one step at a time. You +** must go straight to locking level 0. */ int sqlite3OsLock(OsFile *id, int locktype){ int rc = SQLITE_OK; /* Return code from subroutines */ @@ -390,16 +410,22 @@ int sqlite3OsLock(OsFile *id, int locktype){ return SQLITE_OK; } + /* Make sure the locking sequence is correct + */ + assert( id->locktype!=NO_LOCK || locktype==SHARED_LOCK ); + assert( locktype!=PENDING_LOCK ); + assert( locktype!=RESERVED_LOCK || id->locktype==SHARED_LOCK ); + /* Lock the PENDING_LOCK byte if we need to acquire a PENDING lock or ** a SHARED lock. If we are acquiring a SHARED lock, the acquisition of ** the PENDING_LOCK byte is temporary. */ if( id->locktype==NO_LOCK - || (locktype>=PENDING_LOCK && id->locktypelocktype==RESERVED_LOCK) ){ - int cnt = 4; + int cnt = 3; while( cnt-->0 && (res = LockFile(id->h, PENDING_BYTE, 0, 1, 0))==0 ){ - /* Try 4 times to get the pending lock. The pending lock might be + /* Try 3 times to get the pending lock. The pending lock might be ** held by another reader process who will release it momentarily. */ TRACE2("could not get a PENDING lock. cnt=%d\n", cnt); @@ -410,7 +436,8 @@ int sqlite3OsLock(OsFile *id, int locktype){ /* Acquire a shared lock */ - if( locktype>=SHARED_LOCK && id->locktypelocktype==NO_LOCK ); if( isNT() ){ res = getReadLock(id->h, SHARED_FIRST, SHARED_SIZE); }else{ @@ -426,7 +453,8 @@ int sqlite3OsLock(OsFile *id, int locktype){ /* Acquire a RESERVED lock */ - if( locktype>=RESERVED_LOCK && id->locktypelocktype==SHARED_LOCK ); res = LockFile(id->h, RESERVED_BYTE, 0, 1, 0); if( res ){ newLocktype = RESERVED_LOCK; @@ -435,7 +463,7 @@ int sqlite3OsLock(OsFile *id, int locktype){ /* Acquire a PENDING lock */ - if( locktype>=PENDING_LOCK && res ){ + if( locktype==EXCLUSIVE_LOCK && res ){ newLocktype = PENDING_LOCK; gotPendingLock = 0; } @@ -443,16 +471,10 @@ int sqlite3OsLock(OsFile *id, int locktype){ /* Acquire an EXCLUSIVE lock */ if( locktype==EXCLUSIVE_LOCK && res ){ - if( id->locktype>=SHARED_LOCK ){ - res = unlockReadLock(id); - TRACE2("unreadlock = %d\n", res); - } - if( res ){ - res = LockFile(id->h, SHARED_FIRST, 0, SHARED_SIZE, 0); - }else{ - TRACE2("LOCK FAILED due to failure to unlock read %d\n", id->h); - res = 0; - } + assert( id->locktype>=SHARED_LOCK ); + res = unlockReadLock(id); + TRACE2("unreadlock = %d\n", res); + res = LockFile(id->h, SHARED_FIRST, 0, SHARED_SIZE, 0); if( res ){ newLocktype = EXCLUSIVE_LOCK; }else{ @@ -463,7 +485,7 @@ int sqlite3OsLock(OsFile *id, int locktype){ /* If we are holding a PENDING lock that ought to be released, then ** release it now. */ - if( gotPendingLock && (res==0 || locktypeh, PENDING_BYTE, 0, 1, 0); } @@ -515,15 +537,15 @@ int sqlite3OsUnlock(OsFile *id){ if( type>=EXCLUSIVE_LOCK ){ UnlockFile(id->h, SHARED_FIRST, 0, SHARED_SIZE, 0); } - if( type>=PENDING_LOCK ){ - UnlockFile(id->h, PENDING_BYTE, 0, 1, 0); - } if( type>=RESERVED_LOCK ){ UnlockFile(id->h, RESERVED_BYTE, 0, 1, 0); } if( type>=SHARED_LOCK && type=PENDING_LOCK ){ + UnlockFile(id->h, PENDING_BYTE, 0, 1, 0); + } id->locktype = NO_LOCK; return SQLITE_OK; }