OpenPKG CVS Repository
  http://cvs.openpkg.org/
  ____________________________________________________________________________

  Server: cvs.openpkg.org                  Name:   Thomas Lotterer
  Root:   /v/openpkg/cvs                   Email:  [EMAIL PROTECTED]
  Module: openpkg-src                      Date:   14-Mar-2005 10:16:08
  Branch: HEAD                             Handle: 2005031409160600

  Modified files:
    openpkg-src/sqlite      sqlite.patch.v3 sqlite.spec

  Log:
    greatly enhance parallel writer capability of SQLite3 by importing
    vendor solution for "SQLite forgets to call the busy handler"

  Summary:
    Revision    Changes     Path
    1.2         +300 -0     openpkg-src/sqlite/sqlite.patch.v3
    1.85        +1  -1      openpkg-src/sqlite/sqlite.spec
  ____________________________________________________________________________

  patch -p0 <<'@@ .'
  Index: openpkg-src/sqlite/sqlite.patch.v3
  ============================================================================
  $ cvs diff -u -r1.1 -r1.2 sqlite.patch.v3
  --- openpkg-src/sqlite/sqlite.patch.v3        15 Feb 2005 18:52:36 -0000      
1.1
  +++ openpkg-src/sqlite/sqlite.patch.v3        14 Mar 2005 09:16:06 -0000      
1.2
  @@ -25,3 +25,303 @@
    int sqlite3_vdbe_addop_trace = 0;
    #endif
    
  +vendor solution for "Ticket 1159: SQLite forgets to call the busy handler"
  +http://www.sqlite.org/cvstrac/tktview?tn=1159
  +http://www.mail-archive.com/sqlite-users%40sqlite.org/msg06900.html
  +http://www.sqlite.org/cvstrac/chngview?cn=2385
  +Index: src/btree.c
  +===================================================================
  +RCS file: /sqlite/sqlite/src/btree.c,v
  +retrieving revision 1.251
  +retrieving revision 1.252
  +diff -u -d -u -d -r1.251 -r1.252
  +--- src/btree.c      10 Mar 2005 17:06:34 -0000      1.251
  ++++ src/btree.c      14 Mar 2005 02:01:50 -0000      1.252
  +@@ -9,7 +9,7 @@
  + **    May you share freely, never taking more than you give.
  + **
  + *************************************************************************
  +-** $Id: sqlite.patch.v3,v 1.2 2005/03/14 09:16:06 thl Exp $
  ++** $Id: sqlite.patch.v3,v 1.2 2005/03/14 09:16:06 thl Exp $
  + **
  + ** This file implements a external (disk-based) database using BTrees.
  + ** For a detailed discussion of BTrees, refer to
  +@@ -314,6 +314,7 @@
  +   int minLocal;         /* Minimum local payload in non-LEAFDATA tables */
  +   int maxLeaf;          /* Maximum local payload in a LEAFDATA table */
  +   int minLeaf;          /* Minimum local payload in a LEAFDATA table */
  ++  BusyHandler *pBusyHandler;   /* Callback for when there is lock 
contention */
  + };
  + typedef Btree Bt;
  + 
  +@@ -1291,6 +1292,7 @@
  + ** Change the busy handler callback function.
  + */
  + int sqlite3BtreeSetBusyHandler(Btree *pBt, BusyHandler *pHandler){
  ++  pBt->pBusyHandler = pHandler;
  +   sqlite3pager_set_busyhandler(pBt->pPager, pHandler);
  +   return SQLITE_OK;
  + }
  +@@ -1480,6 +1482,20 @@
  + }
  + 
  + /*
  ++** This routine works like lockBtree() except that it also invokes the
  ++** busy callback if there is lock contention.
  ++*/
  ++static int lockBtreeWithRetry(Btree *pBt){
  ++  int rc = SQLITE_OK;
  ++  if( pBt->inTrans==TRANS_NONE ){
  ++    rc = sqlite3BtreeBeginTrans(pBt, 0);
  ++    pBt->inTrans = TRANS_NONE;
  ++  }
  ++  return rc;
  ++}
  ++       
  ++
  ++/*
  + ** If there are no outstanding cursors and we are not in the middle
  + ** of a transaction but there is a read lock on the database, then
  + ** this routine unrefs the first page of the database file which 
  +@@ -1543,7 +1559,7 @@
  + ** transaction.  If the second argument is 2 or more and exclusive
  + ** transaction is started, meaning that no other process is allowed
  + ** to access the database.  A preexisting transaction may not be
  +-** upgrade to exclusive by calling this routine a second time - the
  ++** upgraded to exclusive by calling this routine a second time - the
  + ** exclusivity flag only works for a new transaction.
  + **
  + ** A write-transaction must be started before attempting any 
  +@@ -1558,43 +1574,60 @@
  + **      sqlite3BtreeDelete()
  + **      sqlite3BtreeUpdateMeta()
  + **
  +-** If wrflag is true, then nMaster specifies the maximum length of
  +-** a master journal file name supplied later via sqlite3BtreeSync().
  +-** This is so that appropriate space can be allocated in the journal file
  +-** when it is created..
  ++** If an initial attempt to acquire the lock fails because of lock 
contention
  ++** and the database was previously unlocked, then invoke the busy handler
  ++** if there is one.  But if there was previously a read-lock, do not
  ++** invoke the busy handler - just return SQLITE_BUSY.  SQLITE_BUSY is 
  ++** returned when there is already a read-lock in order to avoid a deadlock.
  ++**
  ++** Suppose there are two processes A and B.  A has a read lock and B has
  ++** a reserved lock.  B tries to promote to exclusive but is blocked because
  ++** of A's read lock.  A tries to promote to reserved but is blocked by B.
  ++** One or the other of the two processes must give way or there can be
  ++** no progress.  By returning SQLITE_BUSY and not invoking the busy callback
  ++** when A already has a read lock, we encourage A to give up and let B
  ++** proceed.
  + */
  + int sqlite3BtreeBeginTrans(Btree *pBt, int wrflag){
  +   int rc = SQLITE_OK;
  ++  int busy = 0;
  ++  BusyHandler *pH;
  + 
  +   /* If the btree is already in a write-transaction, or it
  +   ** is already in a read-transaction and a read-transaction
  +   ** is requested, this is a no-op.
  +   */
  +-  if( pBt->inTrans==TRANS_WRITE || 
  +-      (pBt->inTrans==TRANS_READ && !wrflag) ){
  ++  if( pBt->inTrans==TRANS_WRITE || (pBt->inTrans==TRANS_READ && !wrflag) ){
  +     return SQLITE_OK;
  +   }
  ++
  ++  /* Write transactions are not possible on a read-only database */
  +   if( pBt->readOnly && wrflag ){
  +     return SQLITE_READONLY;
  +   }
  + 
  +-  if( pBt->pPage1==0 ){
  +-    rc = lockBtree(pBt);
  +-  }
  +-
  +-  if( rc==SQLITE_OK && wrflag ){
  +-    rc = sqlite3pager_begin(pBt->pPage1->aData, wrflag>1);
  ++  do {
  ++    if( pBt->pPage1==0 ){
  ++      rc = lockBtree(pBt);
  ++    }
  ++  
  ++    if( rc==SQLITE_OK && wrflag ){
  ++      rc = sqlite3pager_begin(pBt->pPage1->aData, wrflag>1);
  ++      if( rc==SQLITE_OK ){
  ++        rc = newDatabase(pBt);
  ++      }
  ++    }
  ++  
  +     if( rc==SQLITE_OK ){
  +-      rc = newDatabase(pBt);
  ++      pBt->inTrans = (wrflag?TRANS_WRITE:TRANS_READ);
  ++      if( wrflag ) pBt->inStmt = 0;
  ++    }else{
  ++      unlockBtreeIfUnused(pBt);
  +     }
  +-  }
  +-
  +-  if( rc==SQLITE_OK ){
  +-    pBt->inTrans = (wrflag?TRANS_WRITE:TRANS_READ);
  +-    if( wrflag ) pBt->inStmt = 0;
  +-  }else{
  +-    unlockBtreeIfUnused(pBt);
  +-  }
  ++  }while( rc==SQLITE_BUSY && pBt->inTrans==TRANS_NONE &&
  ++      (pH = pBt->pBusyHandler)!=0 && 
  ++      pH->xFunc && pH->xFunc(pH->pArg, busy++)
  ++  );
  +   return rc;
  + }
  + 
  +@@ -2116,7 +2149,7 @@
  +     }
  +   }
  +   if( pBt->pPage1==0 ){
  +-    rc = lockBtree(pBt);
  ++    rc = lockBtreeWithRetry(pBt);
  +     if( rc!=SQLITE_OK ){
  +       return rc;
  +     }
  +@@ -5531,7 +5564,7 @@
  +   IntegrityCk sCheck;
  + 
  +   nRef = *sqlite3pager_stats(pBt->pPager);
  +-  if( lockBtree(pBt)!=SQLITE_OK ){
  ++  if( lockBtreeWithRetry(pBt)!=SQLITE_OK ){
  +     return sqliteStrDup("Unable to acquire a read lock on the database");
  +   }
  +   sCheck.pBt = pBt;
  +Index: src/pager.c
  +===================================================================
  +RCS file: /sqlite/sqlite/src/pager.c,v
  +retrieving revision 1.192
  +retrieving revision 1.193
  +diff -u -d -u -d -r1.192 -r1.193
  +--- src/pager.c      10 Mar 2005 14:11:13 -0000      1.192
  ++++ src/pager.c      14 Mar 2005 02:01:50 -0000      1.193
  +@@ -18,7 +18,7 @@
  + ** file simultaneously, or one process from reading the database while
  + ** another is writing.
  + **
  +-** @(#) $Id: sqlite.patch.v3,v 1.2 2005/03/14 09:16:06 thl Exp $
  ++** @(#) $Id: sqlite.patch.v3,v 1.2 2005/03/14 09:16:06 thl Exp $
  + */
  + #include "sqliteInt.h"
  + #include "os.h"
  +@@ -1824,12 +1824,12 @@
  +     rc = SQLITE_OK;
  +   }else{
  +     int busy = 1;
  ++    BusyHandler *pH;
  +     do {
  +       rc = sqlite3OsLock(&pPager->fd, locktype);
  +     }while( rc==SQLITE_BUSY && 
  +-        pPager->pBusyHandler && 
  +-        pPager->pBusyHandler->xFunc && 
  +-        pPager->pBusyHandler->xFunc(pPager->pBusyHandler->pArg, busy++)
  ++        (pH = pPager->pBusyHandler)!=0 && 
  ++        pH->xFunc && pH->xFunc(pH->pArg, busy++)
  +     );
  +     if( rc==SQLITE_OK ){
  +       pPager->state = locktype;
  +@@ -2633,11 +2633,7 @@
  +       pPager->state = PAGER_EXCLUSIVE;
  +       pPager->origDbSize = pPager->dbSize;
  +     }else{
  +-      if( SQLITE_BUSY_RESERVED_LOCK || exFlag ){
  +-        rc = pager_wait_on_lock(pPager, RESERVED_LOCK);
  +-      }else{
  +-        rc = sqlite3OsLock(&pPager->fd, RESERVED_LOCK);
  +-      }
  ++      rc = sqlite3OsLock(&pPager->fd, RESERVED_LOCK);
  +       if( rc==SQLITE_OK ){
  +         pPager->state = PAGER_RESERVED;
  +         if( exFlag ){
  +Index: test/lock.test
  +===================================================================
  +RCS file: /sqlite/sqlite/test/lock.test,v
  +retrieving revision 1.30
  +retrieving revision 1.31
  +diff -u -d -u -d -r1.30 -r1.31
  +--- test/lock.test   12 Jan 2005 12:44:04 -0000      1.30
  ++++ test/lock.test   14 Mar 2005 02:01:50 -0000      1.31
  +@@ -11,7 +11,7 @@
  + # This file implements regression tests for SQLite library.  The
  + # focus of this script is database locks.
  + #
  +-# $Id: sqlite.patch.v3,v 1.2 2005/03/14 09:16:06 thl Exp $
  ++# $Id: sqlite.patch.v3,v 1.2 2005/03/14 09:16:06 thl Exp $
  + 
  + 
  + set testdir [file dirname $argv0]
  +@@ -169,30 +169,56 @@
  + } {0 {9 8}}
  + 
  + # If the other thread (the one that does not hold the transaction with
  +-# a RESERVED lock) tries to get a RESERVED lock, we do not get a busy 
callback.
  ++# a RESERVED lock) tries to get a RESERVED lock, we do get a busy callback
  ++# as long as we were not orginally holding a READ lock.
  + #
  +-do_test lock-2.3 {
  ++do_test lock-2.3.1 {
  +   proc callback {count} {
  +     set ::callback_value $count
  +     break
  +   }
  +   set ::callback_value {}
  +   db2 busy callback
  ++  # db2 does not hold a lock so we should get a busy callback here
  ++  set r [catch {execsql {UPDATE t1 SET a=b, b=a} db2} msg]
  ++  lappend r $msg
  ++  lappend r $::callback_value
  ++} {1 {database is locked} 0}
  ++do_test lock-2.3.2 {
  ++  set ::callback_value {}
  ++  execsql {BEGIN; SELECT rowid FROM sqlite_master LIMIT 1} db2
  ++  # This time db2 does hold a read lock.  No busy callback this time.
  +   set r [catch {execsql {UPDATE t1 SET a=b, b=a} db2} msg]
  +   lappend r $msg
  +   lappend r $::callback_value
  + } {1 {database is locked} {}}
  +-do_test lock-2.4 {
  ++catch {execsql {ROLLBACK} db2}
  ++do_test lock-2.4.1 {
  ++  proc callback {count} {
  ++    lappend ::callback_value $count
  ++    if {$count>4} break
  ++  }
  ++  set ::callback_value {}
  ++  db2 busy callback
  ++  # We get a busy callback because db2 is not holding a lock
  ++  set r [catch {execsql {UPDATE t1 SET a=b, b=a} db2} msg]
  ++  lappend r $msg
  ++  lappend r $::callback_value
  ++} {1 {database is locked} {0 1 2 3 4 5}}
  ++do_test lock-2.4.2 {
  +   proc callback {count} {
  +     lappend ::callback_value $count
  +     if {$count>4} break
  +   }
  +   set ::callback_value {}
  +   db2 busy callback
  ++  execsql {BEGIN; SELECT rowid FROM sqlite_master LIMIT 1} db2
  ++  # No busy callback this time because we are holding a lock
  +   set r [catch {execsql {UPDATE t1 SET a=b, b=a} db2} msg]
  +   lappend r $msg
  +   lappend r $::callback_value
  + } {1 {database is locked} {}}
  ++catch {execsql {ROLLBACK} db2}
  + do_test lock-2.5 {
  +   proc callback {count} {
  +     lappend ::callback_value $count
  +@@ -255,7 +281,7 @@
  +   db2 busy callback
  +   set rc [catch {db2 eval {UPDATE t1 SET a=0}} msg]
  +   lappend rc $msg $::callback_value
  +-} {1 {database is locked} {}}
  ++} {1 {database is locked} {0 1 2 3 4 5}}
  + execsql {ROLLBACK}
  + 
  + # When one thread is writing, other threads cannot read.  Except if the
  +
  @@ .
  patch -p0 <<'@@ .'
  Index: openpkg-src/sqlite/sqlite.spec
  ============================================================================
  $ cvs diff -u -r1.84 -r1.85 sqlite.spec
  --- openpkg-src/sqlite/sqlite.spec    12 Mar 2005 06:44:57 -0000      1.84
  +++ openpkg-src/sqlite/sqlite.spec    14 Mar 2005 09:16:06 -0000      1.85
  @@ -38,7 +38,7 @@
   Group:        Database
   License:      PD
   Version:      %{V_v2}
  -Release:      20050312
  +Release:      20050314
   
   #   package options
   %option       with_utf8            no
  @@ .
______________________________________________________________________
The OpenPKG Project                                    www.openpkg.org
CVS Repository Commit List                     [email protected]

Reply via email to