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:
16
manifest
16
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
|
||||
|
||||
@@ -1 +1 @@
|
||||
97aa54bb70715934e0af082d51b9b0f6bb847e8e
|
||||
4dfdea7373f3471d17498da3d6c3aaf926a72d4b
|
||||
@@ -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.
|
||||
|
||||
64
src/os_win.c
64
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->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 ){
|
||||
/* 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->locktype<SHARED_LOCK && res ){
|
||||
if( locktype==SHARED_LOCK && res ){
|
||||
assert( id->locktype==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->locktype<RESERVED_LOCK && res ){
|
||||
if( locktype==RESERVED_LOCK && res ){
|
||||
assert( id->locktype==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 ){
|
||||
assert( 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;
|
||||
}
|
||||
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 || locktype<PENDING_LOCK) ){
|
||||
if( gotPendingLock && locktype==SHARED_LOCK ){
|
||||
UnlockFile(id->h, 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<EXCLUSIVE_LOCK ){
|
||||
unlockReadLock(id);
|
||||
}
|
||||
if( type>=PENDING_LOCK ){
|
||||
UnlockFile(id->h, PENDING_BYTE, 0, 1, 0);
|
||||
}
|
||||
id->locktype = NO_LOCK;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user