-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
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
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
** (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.
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.
}
/*
-** 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 */
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);
/* 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{
/* 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;
/* Acquire a PENDING lock
*/
- if( locktype>=PENDING_LOCK && res ){
+ if( locktype==EXCLUSIVE_LOCK && res ){
newLocktype = PENDING_LOCK;
gotPendingLock = 0;
}
/* 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{
/* 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);
}
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;
}