]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Defer the exclusive db lock until the pager cache is flushed to disk. 41
authordanielk1977 <danielk1977@noemail.net>
Fri, 4 Jun 2004 10:38:30 +0000 (10:38 +0000)
committerdanielk1977 <danielk1977@noemail.net>
Fri, 4 Jun 2004 10:38:30 +0000 (10:38 +0000)
tests now fail. (CVS 1528)

FossilOrigin-Name: d2f69e5ef2f261a00bb8427a4e2a1638ecfd17a9

manifest
manifest.uuid
src/os.h
src/os_unix.c
src/pager.c

index bb4ad21f5155eef042b2ef37401f8b0f831dc5a4..c2865072437880cfe58d36bfbe094c60abb347e3 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Move\sthe\s'busy-callback'\slogic\sto\sthe\spager\slayer.\s(CVS\s1527)
-D 2004-06-04T06:22:01
+C Defer\sthe\sexclusive\sdb\slock\suntil\sthe\spager\scache\sis\sflushed\sto\sdisk.\s41\ntests\snow\sfail.\s(CVS\s1528)
+D 2004-06-04T10:38:30
 F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a
 F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@@ -39,15 +39,15 @@ F src/insert.c 4268d9e3959cc845ea243fb4ec7507269404dad9
 F src/legacy.c ad23746f15f67e34577621b1875f639c94839e1f
 F src/main.c 4e8e5c96e5a9460e71b97c83cb30cb3ad44db259
 F src/md5.c 4302e84ae516c616bb079c4e6d038c0addb33481
-F src/os.h cc2fd62b2e8e11103701913871908ff77532af58
+F src/os.h 4e480eb92737ebcdd1e1136bdbf5cd22223bd1b4
 F src/os_common.h 744286a27de55c52f1b18921e8d17abbf7fafc0f
 F src/os_mac.c b823874690615ace0dd520d3ad1fe8bfd864b7e0
 F src/os_mac.h 51d2445f47e182ed32d3bd6937f81070c6fd9bd4
-F src/os_unix.c 3175540f8d1c820dab7a470c50875c221c3a98cd
+F src/os_unix.c a4feb70b23fa5272f53cd2c74588484b54294800
 F src/os_unix.h 7999f2246c6347707e98f7078871ea8ca605df3f
 F src/os_win.c 92b51a38437b98d8aa3ac05b57c71e1d1092e5be
 F src/os_win.h 5d41af24caaef6c13a2d8e2399caa1c57d45c84d
-F src/pager.c 00fabe423729e8d8a4c5e8f9602341b69a5a21b5
+F src/pager.c 944f6b071279887574081281f27bb2af88b42905
 F src/pager.h 0c7b5ac45c69e690c45d160d03bdc8fbd2d4657b
 F src/parse.y 27c1ce09f9d309be91f9e537df2fb00892990af4
 F src/pragma.c 1b58d852b84b36a8b84e2245dd29b63c377414ec
@@ -214,7 +214,7 @@ F www/support.tcl 1801397edd271cc39a2aadd54e701184b5181248
 F www/tclsqlite.tcl 19191cf2a1010eaeff74c51d83fd5f5a4d899075
 F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9
 F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
-P d57e5252c8baaf615c2cd218a33356ea5d95a5e2
-R 2d675c6973e7ef6b1853da4802084a3d
+P ff70b6d2b60c143e3ada0606ceff97571998c7e3
+R 0c89db702f37cfc005476b7d72917d3b
 U danielk1977
-Z bb8854c6d118151a9229d93a5653a12b
+Z 2dc315e5203a158a5157a45199e1dfe1
index 21089207130bdbad2e9dd15a71846f7cbcb5b8c4..ab70ce9809572f2c3c4fe4819452469668a31366 100644 (file)
@@ -1 +1 @@
-ff70b6d2b60c143e3ada0606ceff97571998c7e3
\ No newline at end of file
+d2f69e5ef2f261a00bb8427a4e2a1638ecfd17a9
\ No newline at end of file
index e496564d3e4f93753d0a5b5b6ffbc87626d3b871..a33662190dac9ea0b9739cdf9943a826b8a837d4 100644 (file)
--- a/src/os.h
+++ b/src/os.h
@@ -84,6 +84,7 @@
 ** The following values may be passed as the second argument to
 ** sqlite3OsLock().
 */
+#define NO_LOCK         0
 #define SHARED_LOCK     1
 #define RESERVED_LOCK   2
 #define PENDING_LOCK    3
index 9ea456970762b293eaf1fb3dded3f5e93c027706..8ee48de8825437cff2cab56f344453f868391e4c 100644 (file)
@@ -641,30 +641,6 @@ int sqlite3OsFileSize(OsFile *id, off_t *pSize){
   return SQLITE_OK;
 }
 
-
-/*
-** Change the status of the lock on the file "id" to be a readlock.
-** If the file was write locked, then this reduces the lock to a read.
-** If the file was read locked, then this acquires a new read lock.
-**
-** Return SQLITE_OK on success and SQLITE_BUSY on failure.  If this
-** library was compiled with large file support (LFS) but LFS is not
-** available on the host, then an SQLITE_NOLFS is returned.
-*/
-int sqlite3OsReadLock(OsFile *id){
-  return sqlite3OsLock(id, SHARED_LOCK);
-}
-
-/*
-** Change the lock status to be an exclusive or write lock.  Return
-** SQLITE_OK on success and SQLITE_BUSY on a failure.  If this
-** library was compiled with large file support (LFS) but LFS is not
-** available on the host, then an SQLITE_NOLFS is returned.
-*/
-int sqlite3OsWriteLock(OsFile *id){
-  return sqlite3OsLock(id, EXCLUSIVE_LOCK);
-}
-
 /*
 ** This routine checks if there is a RESERVED lock held on the specified
 ** file by this or any other process. If such a lock is held, return
index 1f95e72e6a9c8466f0b5b995541533a19876bc75..3a655b745c7ce9331e0317a3c140f7e026e31698 100644 (file)
@@ -18,7 +18,7 @@
 ** file simultaneously, or one process from reading the database while
 ** another is writing.
 **
-** @(#) $Id: pager.c,v 1.111 2004/06/04 06:22:01 danielk1977 Exp $
+** @(#) $Id: pager.c,v 1.112 2004/06/04 10:38:31 danielk1977 Exp $
 */
 #include "os.h"         /* Must be first to enable large file support */
 #include "sqliteInt.h"
@@ -522,7 +522,7 @@ static int pager_unwritelock(Pager *pPager){
   }else{
     assert( pPager->dirtyFile==0 || pPager->useJournal==0 );
   }
-  rc = sqlite3OsReadLock(&pPager->fd);
+  rc = sqlite3OsLock(&pPager->fd, SHARED_LOCK);
   if( rc==SQLITE_OK ){
     pPager->state = SQLITE_READLOCK;
   }else{
@@ -658,15 +658,28 @@ static int pager_delmaster(const char *zMaster){
         */
         OsFile journal;
         int nMaster;
+        off_t jsz;
 
         rc = sqlite3OsOpenReadOnly(zJournal, &journal);
+        sqliteFree(zJournal);
         if( rc!=SQLITE_OK ){
           sqlite3OsClose(&journal);
-          sqliteFree(zJournal);
           goto delmaster_out;
         }
-        sqlite3OsClose(&journal);
 
+       /* Check if the file is big enough to be a format 3 journal file
+        ** with the required master journal name. If not, ignore it.
+        */
+        rc = sqlite3OsFileSize(&journal, &jsz);
+        if( rc!=SQLITE_OK ){
+          sqlite3OsClose(&journal);
+          goto delmaster_out;
+        }
+        if( jsz<(sizeof(aJournalMagic3)+4*sizeof(u32)+strlen(zMaster)+1) ){
+          sqlite3OsClose(&journal);
+          continue;
+        }
+        
         /* Seek to the point in the journal where the master journal name
         ** is stored. Read the master journal name into memory obtained
         ** from malloc.
@@ -1532,9 +1545,40 @@ static int syncJournal(Pager *pPager, const char *zMaster){
 static int pager_write_pagelist(PgHdr *pList){
   Pager *pPager;
   int rc;
+  int busy = 1;
 
   if( pList==0 ) return SQLITE_OK;
   pPager = pList->pPager;
+
+  /* At this point there may be either a RESERVED or EXCLUSIVE lock on the
+  ** database file. If there is already an EXCLUSIVE lock, the following
+  ** calls to sqlite3OsLock() are no-ops.
+  **
+  ** The upgrade from a RESERVED to PENDING lock cannot return SQLITE_BUSY,
+  ** unless someone is not following the locking protocol. 
+  **
+  ** The upgrade from PENDING to EXCLUSIVE can return SQLITE_BUSY. It's
+  ** not totally clear that the busy-callback should be invoked here
+  ** though. (?)
+  */
+  rc = sqlite3OsLock(&pPager->fd, PENDING_LOCK);
+  if( rc==SQLITE_BUSY ){
+    return SQLITE_PROTOCOL;
+  }
+  if( rc!=SQLITE_OK ){
+    return rc;
+  }
+  do {
+    rc = sqlite3OsLock(&pPager->fd, EXCLUSIVE_LOCK);
+  }while( rc==SQLITE_BUSY && 
+      pPager->pBusyHandler && 
+      pPager->pBusyHandler->xFunc && 
+      pPager->pBusyHandler->xFunc(pPager->pBusyHandler->pArg, "", busy++)
+  );
+  if( rc!=SQLITE_OK ){
+    return rc;
+  }
+
   while( pList ){
     assert( pList->dirty );
     sqlite3OsSeek(&pPager->fd, (pList->pgno-1)*(off_t)SQLITE_PAGE_SIZE);
@@ -1607,20 +1651,15 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){
   */
   if( pPager->nRef==0 && !pPager->memDb ){
     int busy = 1;
-    while( busy ){
-      rc = sqlite3OsReadLock(&pPager->fd);
-      if( rc==SQLITE_BUSY && 
-          pPager->pBusyHandler && 
-          pPager->pBusyHandler->xFunc && 
-          pPager->pBusyHandler->xFunc(pPager->pBusyHandler->pArg, "", busy++)
-      ){
-        rc = SQLITE_OK;
-      }else{
-        busy = 0;
-      }
-      if( rc!=SQLITE_OK ){
-        return rc;
-      }
+    do {
+      rc = sqlite3OsLock(&pPager->fd, SHARED_LOCK);
+    }while( rc==SQLITE_BUSY && 
+        pPager->pBusyHandler && 
+        pPager->pBusyHandler->xFunc && 
+        pPager->pBusyHandler->xFunc(pPager->pBusyHandler->pArg, "", busy++)
+    );
+    if( rc!=SQLITE_OK ){
+      return rc;
     }
     pPager->state = SQLITE_READLOCK;
 
@@ -1906,7 +1945,7 @@ static int pager_open_journal(Pager *pPager){
   sqlite3pager_pagecount(pPager);
   pPager->aInJournal = sqliteMalloc( pPager->dbSize/8 + 1 );
   if( pPager->aInJournal==0 ){
-    sqlite3OsReadLock(&pPager->fd);
+    sqlite3OsLock(&pPager->fd, SHARED_LOCK);
     pPager->state = SQLITE_READLOCK;
     return SQLITE_NOMEM;
   }
@@ -1914,7 +1953,7 @@ static int pager_open_journal(Pager *pPager){
   if( rc!=SQLITE_OK ){
     sqliteFree(pPager->aInJournal);
     pPager->aInJournal = 0;
-    sqlite3OsReadLock(&pPager->fd);
+    sqlite3OsLock(&pPager->fd, SHARED_LOCK);
     pPager->state = SQLITE_READLOCK;
     return SQLITE_CANTOPEN;
   }
@@ -2020,20 +2059,20 @@ int sqlite3pager_begin(void *pData, int nMaster){
       pPager->origDbSize = pPager->dbSize;
     }else{
       int busy = 1;
-      while( busy ){
-        rc = sqlite3OsWriteLock(&pPager->fd);
-        if( rc==SQLITE_BUSY && 
-            pPager->pBusyHandler && 
-            pPager->pBusyHandler->xFunc && 
-            pPager->pBusyHandler->xFunc(pPager->pBusyHandler->pArg, "", busy++)
-        ){
-          rc = SQLITE_OK;
-        }else{
-          busy = 0;
-        }
-        if( rc!=SQLITE_OK ){
-          return rc;
-        }
+      do {
+       /* If the library grabs an EXCLUSIVE lock here, as in the commented
+        ** out line, then it exhibits the old locking behaviour - a writer
+        ** excludes all readers, not just other writers.
+        */
+        /* rc = sqlite3OsLock(&pPager->fd, EXCLUSIVE_LOCK); */
+        rc = sqlite3OsLock(&pPager->fd, RESERVED_LOCK);
+      }while( rc==SQLITE_BUSY && 
+          pPager->pBusyHandler && 
+          pPager->pBusyHandler->xFunc && 
+          pPager->pBusyHandler->xFunc(pPager->pBusyHandler->pArg, "", busy++)
+      );
+      if( rc!=SQLITE_OK ){
+        return rc;
       }
       pPager->nMaster = nMaster;
       pPager->state = SQLITE_WRITELOCK;
@@ -2515,7 +2554,7 @@ int sqlite3pager_stmt_begin(Pager *pPager){
   assert( pPager->journalOpen );
   pPager->aInStmt = sqliteMalloc( pPager->dbSize/8 + 1 );
   if( pPager->aInStmt==0 ){
-    sqlite3OsReadLock(&pPager->fd);
+    sqlite3OsLock(&pPager->fd, SHARED_LOCK);
     return SQLITE_NOMEM;
   }
 #ifndef NDEBUG