]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Do not require a RESERVED lock when transitioning from SHARED to EXCLUSIVE. (CVS...
authordrh <drh@noemail.net>
Tue, 8 Jun 2004 00:47:47 +0000 (00:47 +0000)
committerdrh <drh@noemail.net>
Tue, 8 Jun 2004 00:47:47 +0000 (00:47 +0000)
FossilOrigin-Name: 4dfdea7373f3471d17498da3d6c3aaf926a72d4b

manifest
manifest.uuid
src/os_unix.c
src/os_win.c

index 14d333b338a3caf19a4da93b63d84e404f03c4fb..dc4d7729cc606b0b661bbe07f32e875d9c2409f9 100644 (file)
--- 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
index 84b3f262b8a4512754e32e524810db8ab8d5a252..fb0060ce47eb2348c0b8ecd0f6d92b4bf93db1c3 100644 (file)
@@ -1 +1 @@
-97aa54bb70715934e0af082d51b9b0f6bb847e8e
\ No newline at end of file
+4dfdea7373f3471d17498da3d6c3aaf926a72d4b
\ No newline at end of file
index 110dca38da39ac0fe3d6fb23a9b72fa76282b4db..3d4710e3595717eb55ff0c7abb2d60d2bd8d415f 100644 (file)
@@ -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.
index bc8e02c374f9d253e7d1e3949662ccd1ec344223..e9356a1b76cbe8b221f727adabb1c68ae8354250 100644 (file)
@@ -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 ){
-      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 || 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;
 }