1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-10-27 08:52:26 +03:00

Do not require a RESERVED lock when transitioning from SHARED to EXCLUSIVE. (CVS 1542)

FossilOrigin-Name: 4dfdea7373f3471d17498da3d6c3aaf926a72d4b
This commit is contained in:
drh
2004-06-08 00:47:47 +00:00
parent 3f41e976e8
commit b3e043463d
4 changed files with 73 additions and 54 deletions

View File

@@ -1,5 +1,5 @@
C Enhance\sthe\sbuilt-in\sfunction\squote()\sto\ssupport\sblob\svalues.\s(CVS\s1541) C Do\snot\srequire\sa\sRESERVED\slock\swhen\stransitioning\sfrom\sSHARED\sto\sEXCLUSIVE.\s(CVS\s1542)
D 2004-06-08T00:39:01 D 2004-06-08T00:47:47
F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906 F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@@ -43,9 +43,9 @@ F src/os.h a3a9c2df29acbff54aef742e85c302d23634019f
F src/os_common.h 12074232439f904b3805beeff1245bd1b5532994 F src/os_common.h 12074232439f904b3805beeff1245bd1b5532994
F src/os_mac.c b823874690615ace0dd520d3ad1fe8bfd864b7e0 F src/os_mac.c b823874690615ace0dd520d3ad1fe8bfd864b7e0
F src/os_mac.h 51d2445f47e182ed32d3bd6937f81070c6fd9bd4 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_unix.h 7999f2246c6347707e98f7078871ea8ca605df3f
F src/os_win.c 5c46f81f76f2be0c0817773a865c075c56496018 F src/os_win.c a13b85a0d4889e3d0b254ed2a61354acddc59fc4
F src/os_win.h 004eec47b1780fcaf07420ddc2072294b698d48c F src/os_win.h 004eec47b1780fcaf07420ddc2072294b698d48c
F src/pager.c 3fddd1e5b3e449b19e4f762ab1f1d10786d56d28 F src/pager.c 3fddd1e5b3e449b19e4f762ab1f1d10786d56d28
F src/pager.h 0c7b5ac45c69e690c45d160d03bdc8fbd2d4657b F src/pager.h 0c7b5ac45c69e690c45d160d03bdc8fbd2d4657b
@@ -215,7 +215,7 @@ F www/support.tcl 1801397edd271cc39a2aadd54e701184b5181248
F www/tclsqlite.tcl 19191cf2a1010eaeff74c51d83fd5f5a4d899075 F www/tclsqlite.tcl 19191cf2a1010eaeff74c51d83fd5f5a4d899075
F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9 F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9
F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4 F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
P 62e31f396cb6b49f542977e2fade78e11e371132 P 97aa54bb70715934e0af082d51b9b0f6bb847e8e
R 87169ec73e15b83e9be0f5b8ac7aaebe R b382950b985a7f7c010fa51e63195e87
U danielk1977 U drh
Z e31a621434c9bec95d63eda46f31cc00 Z 979bdbef9456a09bba11f45e5a0188cd

View File

@@ -1 +1 @@
97aa54bb70715934e0af082d51b9b0f6bb847e8e 4dfdea7373f3471d17498da3d6c3aaf926a72d4b

View File

@@ -686,15 +686,17 @@ int sqlite3OsCheckWriteLock(OsFile *id){
** (3) PENDING_LOCK ** (3) PENDING_LOCK
** (4) EXCLUSIVE_LOCK ** (4) EXCLUSIVE_LOCK
** **
** Locks are are hierarchical. Getting a lock N implies getting all locks ** Sometimes when requesting one lock state, additional lock states
** N-1, N-2, N-3, .... So, for example, getting a PENDING lock ** are inserted in between. The locking might fail on one of the later
** implies a SHARED and a RESERVED lock. This routine adds locks one ** transitions leaving the lock state different from what it started but
** at a time until the desired lock is acheived. A locking failure might ** still short of its goal. The following chart shows the allowed
** occur at any point. When a failure occurs intermediate locks are ** transitions and the inserted intermediate states:
** retained. For example, if a SHARED lock is held and this routine **
** is called with EXCLUSIVE, it might obtain a RESERVED and PENDING lock ** UNLOCKED -> SHARED
** but fail to get the EXCLUSIVE lock. In that case, the file would be ** SHARED -> RESERVED
** left in the PENDING lock state - it does not revert to SHARED. ** SHARED -> (PENDING) -> EXCLUSIVE
** RESERVED -> (PENDING) -> EXCLUSIVE
** PENDING -> EXCLUSIVE
** **
** This routine will only increase a lock. The sqlite3OsUnlock() routine ** This routine will only increase a lock. The sqlite3OsUnlock() routine
** erases all locks at once and returns us immediately to locking level 0. ** 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; return SQLITE_OK;
} }
/* Make sure locking is sequential. In other words, make sure we have /* Make sure the locking sequence is correct
** SHARED before trying for RESERVED, and that we have RESERVED before
** trying for PENDING, and that we have PENDING before trying for
** EXCLUSIVE.
*/ */
while( locktype>id->locktype+1 ){ assert( id->locktype!=NO_LOCK || locktype==SHARED_LOCK );
rc = sqlite3OsLock(id, id->locktype+1); assert( locktype!=PENDING_LOCK );
if( rc!=SQLITE_OK ){ assert( locktype!=RESERVED_LOCK || id->locktype==SHARED_LOCK );
return rc;
}
}
assert( locktype==id->locktype+1 );
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* /* If some thread using this PID has a lock via a different OsFile*
** handle that precludes the requested lock, return BUSY. ** handle that precludes the requested lock, return BUSY.

View File

@@ -368,10 +368,30 @@ static int unlockReadLock(OsFile *id){
} }
/* /*
** Acquire a lock of the given type on the specified file. If an ** Lock the file with the lock specified by parameter locktype - one
** appropriate lock already exists, this routine is a no-op. Return ** of the following:
** SQLITE_OK on success and SQLITE_BUSY if another thread is already **
** holding a conflicting lock. ** (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 sqlite3OsLock(OsFile *id, int locktype){
int rc = SQLITE_OK; /* Return code from subroutines */ int rc = SQLITE_OK; /* Return code from subroutines */
@@ -390,16 +410,22 @@ int sqlite3OsLock(OsFile *id, int locktype){
return SQLITE_OK; 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 /* 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 ** a SHARED lock. If we are acquiring a SHARED lock, the acquisition of
** the PENDING_LOCK byte is temporary. ** the PENDING_LOCK byte is temporary.
*/ */
if( id->locktype==NO_LOCK if( id->locktype==NO_LOCK
|| (locktype>=PENDING_LOCK && id->locktype<PENDING_LOCK) || (locktype==EXCLUSIVE_LOCK && id->locktype==RESERVED_LOCK)
){ ){
int cnt = 4; int cnt = 3;
while( cnt-->0 && (res = LockFile(id->h, PENDING_BYTE, 0, 1, 0))==0 ){ 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. ** held by another reader process who will release it momentarily.
*/ */
TRACE2("could not get a PENDING lock. cnt=%d\n", cnt); 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 /* Acquire a shared lock
*/ */
if( locktype>=SHARED_LOCK && id->locktype<SHARED_LOCK && res ){ if( locktype==SHARED_LOCK && res ){
assert( id->locktype==NO_LOCK );
if( isNT() ){ if( isNT() ){
res = getReadLock(id->h, SHARED_FIRST, SHARED_SIZE); res = getReadLock(id->h, SHARED_FIRST, SHARED_SIZE);
}else{ }else{
@@ -426,7 +453,8 @@ int sqlite3OsLock(OsFile *id, int locktype){
/* Acquire a RESERVED lock /* Acquire a RESERVED lock
*/ */
if( locktype>=RESERVED_LOCK && id->locktype<RESERVED_LOCK && res ){ if( locktype==RESERVED_LOCK && res ){
assert( id->locktype==SHARED_LOCK );
res = LockFile(id->h, RESERVED_BYTE, 0, 1, 0); res = LockFile(id->h, RESERVED_BYTE, 0, 1, 0);
if( res ){ if( res ){
newLocktype = RESERVED_LOCK; newLocktype = RESERVED_LOCK;
@@ -435,7 +463,7 @@ int sqlite3OsLock(OsFile *id, int locktype){
/* Acquire a PENDING lock /* Acquire a PENDING lock
*/ */
if( locktype>=PENDING_LOCK && res ){ if( locktype==EXCLUSIVE_LOCK && res ){
newLocktype = PENDING_LOCK; newLocktype = PENDING_LOCK;
gotPendingLock = 0; gotPendingLock = 0;
} }
@@ -443,16 +471,10 @@ int sqlite3OsLock(OsFile *id, int locktype){
/* Acquire an EXCLUSIVE lock /* Acquire an EXCLUSIVE lock
*/ */
if( locktype==EXCLUSIVE_LOCK && res ){ if( locktype==EXCLUSIVE_LOCK && res ){
if( id->locktype>=SHARED_LOCK ){ assert( id->locktype>=SHARED_LOCK );
res = unlockReadLock(id); res = unlockReadLock(id);
TRACE2("unreadlock = %d\n", res); TRACE2("unreadlock = %d\n", res);
} res = LockFile(id->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
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;
}
if( res ){ if( res ){
newLocktype = EXCLUSIVE_LOCK; newLocktype = EXCLUSIVE_LOCK;
}else{ }else{
@@ -463,7 +485,7 @@ int sqlite3OsLock(OsFile *id, int locktype){
/* If we are holding a PENDING lock that ought to be released, then /* If we are holding a PENDING lock that ought to be released, then
** release it now. ** release it now.
*/ */
if( gotPendingLock && (res==0 || locktype<PENDING_LOCK) ){ if( gotPendingLock && locktype==SHARED_LOCK ){
UnlockFile(id->h, PENDING_BYTE, 0, 1, 0); UnlockFile(id->h, PENDING_BYTE, 0, 1, 0);
} }
@@ -515,15 +537,15 @@ int sqlite3OsUnlock(OsFile *id){
if( type>=EXCLUSIVE_LOCK ){ if( type>=EXCLUSIVE_LOCK ){
UnlockFile(id->h, SHARED_FIRST, 0, SHARED_SIZE, 0); 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 ){ if( type>=RESERVED_LOCK ){
UnlockFile(id->h, RESERVED_BYTE, 0, 1, 0); UnlockFile(id->h, RESERVED_BYTE, 0, 1, 0);
} }
if( type>=SHARED_LOCK && type<EXCLUSIVE_LOCK ){ if( type>=SHARED_LOCK && type<EXCLUSIVE_LOCK ){
unlockReadLock(id); unlockReadLock(id);
} }
if( type>=PENDING_LOCK ){
UnlockFile(id->h, PENDING_BYTE, 0, 1, 0);
}
id->locktype = NO_LOCK; id->locktype = NO_LOCK;
return SQLITE_OK; return SQLITE_OK;
} }