]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Move the 'busy-callback' logic to the pager layer. (CVS 1527)
authordanielk1977 <danielk1977@noemail.net>
Fri, 4 Jun 2004 06:22:00 +0000 (06:22 +0000)
committerdanielk1977 <danielk1977@noemail.net>
Fri, 4 Jun 2004 06:22:00 +0000 (06:22 +0000)
FossilOrigin-Name: ff70b6d2b60c143e3ada0606ceff97571998c7e3

12 files changed:
manifest
manifest.uuid
src/btree.c
src/btree.h
src/main.c
src/pager.c
src/pager.h
src/sqliteInt.h
src/test2.c
src/test3.c
src/test5.c
src/vdbe.c

index e4b12f275e3342c0ebef239bca79c07ac396ed4a..bb4ad21f5155eef042b2ef37401f8b0f831dc5a4 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Untested\supdates\sto\ssupport\satomic\smulti-file\stransactions\s(CVS\s1526)
-D 2004-06-03T16:08:41
+C Move\sthe\s'busy-callback'\slogic\sto\sthe\spager\slayer.\s(CVS\s1527)
+D 2004-06-04T06:22:01
 F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a
 F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@@ -25,8 +25,8 @@ F sqlite.def fc4f5734786fe4743cfe2aa98eb2da4b089edb5f
 F sqlite.pc.in 30552343140c53304c2a658c080fbe810cd09ca2
 F src/attach.c c315c58cb16fd6e913b3bfa6412aedecb4567fa5
 F src/auth.c 5c2f0bea4729c98c2be3b69d6b466fc51448fe79
-F src/btree.c 3cf513520d5b6fe54cc4c5fb44ce5c6231f1a535
-F src/btree.h 7b682341772eb1199de3f9c29ce5e34f96836d17
+F src/btree.c 39dfc3954a7af77be42ef7fb19ab22c1fa644a83
+F src/btree.h 589427ac13bb544d298cd99726e2572a6fe4bdaa
 F src/build.c e12e602f06e37a0fbcb49af17cba68ad85e101b6
 F src/date.c 8e6fa3173386fb29fdef012ee08a853c1e9908b2
 F src/delete.c b30f08250c9ed53a25a13c7c04599c1e8753992d
@@ -37,7 +37,7 @@ F src/hash.c 440c2f8cb373ee1b4e13a0988489c7cd95d55b6f
 F src/hash.h 762d95f1e567664d1eafc1687de755626be962fb
 F src/insert.c 4268d9e3959cc845ea243fb4ec7507269404dad9
 F src/legacy.c ad23746f15f67e34577621b1875f639c94839e1f
-F src/main.c d2a7632f459e9c270bb6e313e10916fc840f4a6e
+F src/main.c 4e8e5c96e5a9460e71b97c83cb30cb3ad44db259
 F src/md5.c 4302e84ae516c616bb079c4e6d038c0addb33481
 F src/os.h cc2fd62b2e8e11103701913871908ff77532af58
 F src/os_common.h 744286a27de55c52f1b18921e8d17abbf7fafc0f
@@ -47,8 +47,8 @@ F src/os_unix.c 3175540f8d1c820dab7a470c50875c221c3a98cd
 F src/os_unix.h 7999f2246c6347707e98f7078871ea8ca605df3f
 F src/os_win.c 92b51a38437b98d8aa3ac05b57c71e1d1092e5be
 F src/os_win.h 5d41af24caaef6c13a2d8e2399caa1c57d45c84d
-F src/pager.c 1619b6a0338cefa3b4d8be54afbbe1c46e85e64e
-F src/pager.h ade5bee4a0771adf82180fd702f170cb0031d811
+F src/pager.c 00fabe423729e8d8a4c5e8f9602341b69a5a21b5
+F src/pager.h 0c7b5ac45c69e690c45d160d03bdc8fbd2d4657b
 F src/parse.y 27c1ce09f9d309be91f9e537df2fb00892990af4
 F src/pragma.c 1b58d852b84b36a8b84e2245dd29b63c377414ec
 F src/printf.c ef750e8e2398ca7e8b58be991075f08c6a7f0e53
@@ -56,21 +56,21 @@ F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3
 F src/select.c 0297717eb7331604687c2e29c147d3a311359df1
 F src/shell.c a9e2ad8f6c1d39b04bad61a0ec655e9a3a360b50
 F src/sqlite.h.in 8236db65bc6d8f5f47dc5a5e86c4a9bce42f2adf
-F src/sqliteInt.h 1aa9f7d5f88d13442d39c1bc9216c73e9b6c5191
+F src/sqliteInt.h 99f2b4ff4ed28123890a0c71359fec3d2c5901c9
 F src/table.c af14284fa36c8d41f6829e3f2819dce07d3e2de2
 F src/tclsqlite.c 3db6b868bd844bfb71720c8e573f4c9b0d536bd5
 F src/test1.c 4a3cc1b628a29f24c0a43227a035d0f2a96eb634
-F src/test2.c 6195a1ca2c8d0d2d93644e86da3289b403486872
-F src/test3.c b3f331bda440ae21b6cab5171f28ddb402001f26
+F src/test2.c ae18537d8a85e5028c955837797f9da461b908b8
+F src/test3.c beafd0ccf7b9ae784744be1b1e66ffe8f64c25da
 F src/test4.c caf675e443460ec76b04d78e1688986c17c82cec
-F src/test5.c e731274b902eaad09b195cfbac06768dfefba93e
+F src/test5.c 44178ce85c3afd2004ab4eeb5cfd7487116ce366
 F src/tokenize.c 183c5d7da11affab5d70d903d33409c8c0ce6c5b
 F src/trigger.c 04b2c310d0d056b213609cab6df5fff03d5eaf88
 F src/update.c 259f06e7b22c684b2d3dda54a18185892d6e9573
 F src/utf.c c8be20ecdcb10659e23c43e35d835460e964d248
 F src/util.c d3d2f62ec94160db3cb2b092267405ba99122152
 F src/vacuum.c b921eb778842592e1fb48a9d4cef7e861103878f
-F src/vdbe.c 2cf1376f23e2f8ddd1a55143ea9e0e289095504d
+F src/vdbe.c e1e62347215a8dbe0ec72c155e4a042e81c6aa71
 F src/vdbe.h e73f890e0f2a6c42b183d7d6937947930fe4fdeb
 F src/vdbeInt.h 9f5df0a21474be02fe870cbb0a414d09b66eb31a
 F src/vdbeapi.c 77d2e681a992ef189032cd9c1b7bf922f01ebe3e
@@ -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 51348b82c4d5801091537b80059d770410774905
-R 0e06f4b108dd74f5024eb81017752495
+P d57e5252c8baaf615c2cd218a33356ea5d95a5e2
+R 2d675c6973e7ef6b1853da4802084a3d
 U danielk1977
-Z 4a23c8e1ebb05080684ee0992bb72463
+Z bb8854c6d118151a9229d93a5653a12b
index 91ad00296f2b50334554ff4a40bc813df6dbd419..21089207130bdbad2e9dd15a71846f7cbcb5b8c4 100644 (file)
@@ -1 +1 @@
-d57e5252c8baaf615c2cd218a33356ea5d95a5e2
\ No newline at end of file
+ff70b6d2b60c143e3ada0606ceff97571998c7e3
\ No newline at end of file
index 07ebaa9d57dc96e3723ac71c84fb872a13a740b8..c112b559214ba8bfdbfcab66c88dcaa46ecd84a8 100644 (file)
@@ -9,7 +9,7 @@
 **    May you share freely, never taking more than you give.
 **
 *************************************************************************
-** $Id: btree.c,v 1.156 2004/06/03 16:08:41 danielk1977 Exp $
+** $Id: btree.c,v 1.157 2004/06/04 06:22:01 danielk1977 Exp $
 **
 ** This file implements a external (disk-based) database using BTrees.
 ** For a detailed discussion of BTrees, refer to
@@ -977,7 +977,8 @@ int sqlite3BtreeOpen(
   const char *zFilename,  /* Name of the file containing the BTree database */
   Btree **ppBtree,        /* Pointer to new Btree object written here */
   int nCache,             /* Number of cache pages */
-  int flags               /* Options */
+  int flags,              /* Options */
+  void *pBusyHandler      /* Busy callback info passed to pager layer */
 ){
   Btree *pBt;
   int rc;
@@ -1002,7 +1003,7 @@ int sqlite3BtreeOpen(
   }
   if( nCache<10 ) nCache = 10;
   rc = sqlite3pager_open(&pBt->pPager, zFilename, nCache, EXTRA_SIZE,
-                        (flags & BTREE_OMIT_JOURNAL)==0);
+                        (flags & BTREE_OMIT_JOURNAL)==0, pBusyHandler);
   if( rc!=SQLITE_OK ){
     if( pBt->pPager ) sqlite3pager_close(pBt->pPager);
     sqliteFree(pBt);
index 472fd9052958e5c46e8d3f4c39118ea2b3d430a7..48ba97e0df865f75fa31d05b903abd6c66ae096b 100644 (file)
@@ -13,7 +13,7 @@
 ** subsystem.  See comments in the source code for a detailed description
 ** of what each interface routine does.
 **
-** @(#) $Id: btree.h,v 1.52 2004/06/03 16:08:41 danielk1977 Exp $
+** @(#) $Id: btree.h,v 1.53 2004/06/04 06:22:01 danielk1977 Exp $
 */
 #ifndef _BTREE_H_
 #define _BTREE_H_
@@ -30,7 +30,13 @@ typedef struct Btree Btree;
 typedef struct BtCursor BtCursor;
 
 
-int sqlite3BtreeOpen(const char *zFilename, Btree **, int nCache, int flags);
+int sqlite3BtreeOpen(
+  const char *zFilename, 
+  Btree **, 
+  int nCache, 
+  int flags,
+  void *pBusyHandler
+);
 
 /* The flags parameter to sqlite3BtreeOpen can be the bitwise or of the
 ** following values.
index 57d6b0170e740f9a7b436dc209558dcbf3e7b869..ce93f2eff2436b295f73e111d264a34d328a6302 100644 (file)
@@ -14,7 +14,7 @@
 ** other files are for internal use by SQLite and should not be
 ** accessed by users of the library.
 **
-** $Id: main.c,v 1.203 2004/06/02 00:41:09 drh Exp $
+** $Id: main.c,v 1.204 2004/06/04 06:22:01 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -570,8 +570,8 @@ void sqlite3_busy_handler(
   int (*xBusy)(void*,const char*,int),
   void *pArg
 ){
-  db->xBusyCallback = xBusy;
-  db->pBusyArg = pArg;
+  db->busyHandler.xFunc = xBusy;
+  db->busyHandler.pArg = pArg;
 }
 
 #ifndef SQLITE_OMIT_PROGRESS_CALLBACK
@@ -762,7 +762,8 @@ int sqlite3BtreeFactory(
     btree_flags |= BTREE_MEMORY;
   }
 
-  return sqlite3BtreeOpen(zFilename, ppBtree, nCache, btree_flags);
+  return sqlite3BtreeOpen(zFilename, ppBtree, nCache, btree_flags,
+      &db->busyHandler);
 }
 
 /*
@@ -847,9 +848,7 @@ int sqlite3_prepare(
   if( !db->init.busy ){
     if( (db->flags & SQLITE_Initialized)==0 ){
       int cnt = 1;
-      while( (rc = sqlite3Init(db, &zErrMsg))==SQLITE_BUSY
-         && db->xBusyCallback
-         && db->xBusyCallback(db->pBusyArg, "", cnt++)!=0 ){}
+      rc = sqlite3Init(db, &zErrMsg);
       if( rc!=SQLITE_OK ){
         goto prepare_out;
       }
index 7068df7861e57f8a6f68bbf73aea686214eddd13..1f95e72e6a9c8466f0b5b995541533a19876bc75 100644 (file)
@@ -18,7 +18,7 @@
 ** file simultaneously, or one process from reading the database while
 ** another is writing.
 **
-** @(#) $Id: pager.c,v 1.110 2004/06/03 16:08:42 danielk1977 Exp $
+** @(#) $Id: pager.c,v 1.111 2004/06/04 06:22:01 danielk1977 Exp $
 */
 #include "os.h"         /* Must be first to enable large file support */
 #include "sqliteInt.h"
@@ -213,6 +213,7 @@ struct Pager {
   PgHdr *pStmt;               /* List of pages in the statement subjournal */
   PgHdr *aHash[N_PG_HASH];    /* Hash table to map page number of PgHdr */
   int nMaster;                /* Number of bytes to reserve for master j.p */
+  BusyHandler *pBusyHandler;  /* Pointer to sqlite.busyHandler */
 };
 
 /*
@@ -1080,7 +1081,8 @@ int sqlite3pager_open(
   const char *zFilename,   /* Name of the database file to open */
   int mxPage,              /* Max number of in-memory cache pages */
   int nExtra,              /* Extra bytes append to each in-memory page */
-  int useJournal           /* TRUE to use a rollback journal on this file */
+  int useJournal,          /* TRUE to use a rollback journal on this file */
+  void  *pBusyHandler      /* Busy callback */
 ){
   Pager *pPager;
   char *zFullPathname;
@@ -1161,6 +1163,7 @@ int sqlite3pager_open(
   pPager->pFirstSynced = 0;
   pPager->pLast = 0;
   pPager->nExtra = nExtra;
+  pPager->pBusyHandler = (BusyHandler *)pBusyHandler;
   memset(pPager->aHash, 0, sizeof(pPager->aHash));
   *ppPager = pPager;
   return SQLITE_OK;
@@ -1603,9 +1606,21 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){
   ** on the database file.
   */
   if( pPager->nRef==0 && !pPager->memDb ){
-    rc = sqlite3OsReadLock(&pPager->fd);
-    if( rc!=SQLITE_OK ){
-      return rc;
+    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;
+      }
     }
     pPager->state = SQLITE_READLOCK;
 
@@ -2004,9 +2019,21 @@ int sqlite3pager_begin(void *pData, int nMaster){
       pPager->state = SQLITE_WRITELOCK;
       pPager->origDbSize = pPager->dbSize;
     }else{
-      rc = sqlite3OsWriteLock(&pPager->fd);
-      if( rc!=SQLITE_OK ){
-        return rc;
+      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;
+        }
       }
       pPager->nMaster = nMaster;
       pPager->state = SQLITE_WRITELOCK;
index 132989d76b430d5298e60e352f8b71bb7b3e1e6b..5ae27167e9a3c1f5525a5bf094f2c13704ab44d6 100644 (file)
@@ -13,7 +13,7 @@
 ** subsystem.  The page cache subsystem reads and writes a file a page
 ** at a time and provides a journal for rollback.
 **
-** @(#) $Id: pager.h,v 1.30 2004/06/03 16:08:42 danielk1977 Exp $
+** @(#) $Id: pager.h,v 1.31 2004/06/04 06:22:02 danielk1977 Exp $
 */
 
 /*
@@ -70,7 +70,8 @@ typedef struct Pager Pager;
 ** routines:
 */
 int sqlite3pager_open(Pager **ppPager, const char *zFilename,
-                     int nPage, int nExtra, int useJournal);
+                     int nPage, int nExtra, int useJournal,
+                     void *pBusyHandler);
 void sqlite3pager_set_destructor(Pager*, void(*)(void*,int));
 void sqlite3pager_set_cachesize(Pager*, int);
 int sqlite3pager_close(Pager *pPager);
index d00210c5837d1e73d33a7d16036999311b7ff00e..aa95275db54ad10d63eb562e0381a5f5fd66efaa 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.267 2004/06/02 00:41:09 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.268 2004/06/04 06:22:02 danielk1977 Exp $
 */
 #include "config.h"
 #include "sqlite3.h"
@@ -264,6 +264,7 @@ typedef struct AuthContext AuthContext;
 typedef struct KeyClass KeyClass;
 typedef struct CollSeq CollSeq;
 typedef struct KeyInfo KeyInfo;
+typedef struct BusyHandler BusyHandler;
 
 
 /*
@@ -326,6 +327,20 @@ struct Db {
 #define TEXT_Utf16be       3
 #define TEXT_Utf16         (SQLITE_BIGENDIAN?TEXT_Utf16be:TEXT_Utf16le)
 
+/*
+** An instance of the following structure is used to store the busy-handler
+** callback for a given sqlite handle. 
+**
+** The sqlite.busyHandler member of the sqlite struct contains the busy
+** callback for the database handle. Each pager opened via the sqlite
+** handle is passed a pointer to sqlite.busyHandler. The busy-handler
+** callback is currently invoked only from within pager.c.
+*/
+struct BusyHandler {
+  int (*xFunc)(void *,const char*,int);  /* The busy callback */
+  void *pArg;                            /* First arg to busy callback */
+};
+
 /*
 ** Each database is an instance of the following structure.
 **
@@ -369,8 +384,7 @@ struct sqlite {
   int next_cookie;              /* Next value of aDb[0].schema_cookie */
   int cache_size;               /* Number of pages to use in the cache */
   int nTable;                   /* Number of tables in the database */
-  void *pBusyArg;               /* 1st Argument to the busy callback */
-  int (*xBusyCallback)(void *,const char*,int);  /* The busy callback */
+  BusyHandler busyHandler;      /* Busy callback */
   void *pCommitArg;             /* Argument to xCommitCallback() */   
   int (*xCommitCallback)(void*);/* Invoked at every commit. */
   Hash aFunc;                   /* All functions that can be in SQL exprs */
index 72b68c56b894916fd57b02d99ed9f4d5cc574e48..177043f0258ec60cec8ef57619c77f078f742937 100644 (file)
@@ -13,7 +13,7 @@
 ** is not included in the SQLite library.  It is used for automated
 ** testing of the SQLite library.
 **
-** $Id: test2.c,v 1.19 2004/05/10 10:34:53 danielk1977 Exp $
+** $Id: test2.c,v 1.20 2004/06/04 06:22:02 danielk1977 Exp $
 */
 #include "os.h"
 #include "sqliteInt.h"
@@ -76,7 +76,7 @@ static int pager_open(
     return TCL_ERROR;
   }
   if( Tcl_GetInt(interp, argv[2], &nPage) ) return TCL_ERROR;
-  rc = sqlite3pager_open(&pPager, argv[1], nPage, 0, 1);
+  rc = sqlite3pager_open(&pPager, argv[1], nPage, 0, 1, 0);
   if( rc!=SQLITE_OK ){
     Tcl_AppendResult(interp, errorName(rc), 0);
     return TCL_ERROR;
index a5e5f92a23055ba81d5b6913134486b5c45a3076..2c2ab86b2d030ae90ebe76182c936593dc163f7d 100644 (file)
@@ -13,7 +13,7 @@
 ** is not included in the SQLite library.  It is used for automated
 ** testing of the SQLite library.
 **
-** $Id: test3.c,v 1.42 2004/06/03 16:08:42 danielk1977 Exp $
+** $Id: test3.c,v 1.43 2004/06/04 06:22:02 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 #include "pager.h"
@@ -70,7 +70,7 @@ static int btree_open(
   }
   if( Tcl_GetInt(interp, argv[2], &nCache) ) return TCL_ERROR;
   if( Tcl_GetInt(interp, argv[3], &flags) ) return TCL_ERROR;
-  rc = sqlite3BtreeOpen(argv[1], &pBt, nCache, flags);
+  rc = sqlite3BtreeOpen(argv[1], &pBt, nCache, flags, 0);
   if( rc!=SQLITE_OK ){
     Tcl_AppendResult(interp, errorName(rc), 0);
     return TCL_ERROR;
index f288d3052b7759677902552239c3393056367c52..ff3fa6f5539d4b7b7e4785ab9d8946069790279a 100644 (file)
@@ -15,7 +15,7 @@
 ** is used for testing the SQLite routines for converting between
 ** the various supported unicode encodings.
 **
-** $Id: test5.c,v 1.7 2004/06/02 00:41:10 drh Exp $
+** $Id: test5.c,v 1.8 2004/06/04 06:22:02 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"         /* to get SQLITE_BIGENDIAN */
@@ -248,7 +248,7 @@ int Sqlitetest5_Init(Tcl_Interp *interp){
     { "sqlite_utf8to16be",       (Tcl_ObjCmdProc*)sqlite_utf8to16be  },
     { "sqlite_utf16to16le",      (Tcl_ObjCmdProc*)sqlite_utf16to16le },
     { "sqlite_utf16to16be",      (Tcl_ObjCmdProc*)sqlite_utf16to16be },
-    { "binarize",                (Tcl_ObjCmdProc*)binarize }
+    { "binarize",                (Tcl_ObjCmdProc*)binarize },
   };
   int i;
   for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
index 491f107b7bd76499fdbc3ef5f1783bcd90340130..dfc25601d1a680ea25169c13599578bf37046cb2 100644 (file)
@@ -43,7 +43,7 @@
 ** in this file for details.  If in doubt, do not deviate from existing
 ** commenting and indentation practices when changing or adding code.
 **
-** $Id: vdbe.c,v 1.356 2004/06/03 16:08:42 danielk1977 Exp $
+** $Id: vdbe.c,v 1.357 2004/06/04 06:22:02 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -2281,40 +2281,27 @@ case OP_AutoCommit: {
 ** If P2 is zero, then a read-lock is obtained on the database file.
 */
 case OP_Transaction: {
-  int busy = 1;
   int i = pOp->p1;
   Btree *pBt;
 
   assert( i>=0 && i<db->nDb );
   pBt = db->aDb[i].pBt;
 
-  while( pBt && busy ){
+  if( pBt ){
     int nMaster = strlen(sqlite3BtreeGetFilename(db->aDb[0].pBt))+11;
-    rc = sqlite3BtreeBeginTrans(db->aDb[i].pBt, pOp->p2, nMaster);
-    switch( rc ){
-      case SQLITE_BUSY: {
-        if( db->xBusyCallback==0 ){
+    rc = sqlite3BtreeBeginTrans(pBt, pOp->p2, nMaster);
+    if( rc==SQLITE_BUSY ){
+        if( db->busyHandler.xFunc==0 ){
           p->pc = pc;
           p->rc = SQLITE_BUSY;
           p->pTos = pTos;
           return SQLITE_BUSY;
-        }else if( (*db->xBusyCallback)(db->pBusyArg, "", busy++)==0 ){
+        }else{
           sqlite3SetString(&p->zErrMsg, sqlite3ErrStr(rc), (char*)0);
-          busy = 0;
         }
-        break;
-      }
-      case SQLITE_READONLY: {
-        rc = SQLITE_OK;
-        /* Fall thru into the next case */
-      }
-      case SQLITE_OK: {
-        busy = 0;
-        break;
-      }
-      default: {
-        goto abort_due_to_error;
-      }
+    }
+    if( rc!=SQLITE_OK && rc!=SQLITE_READONLY && rc!=SQLITE_BUSY ){
+      goto abort_due_to_error;
     }
   }
   break;
@@ -2445,7 +2432,6 @@ case OP_VerifyCookie: {
 */
 case OP_OpenRead:
 case OP_OpenWrite: {
-  int busy = 0;
   int i = pOp->p1;
   int p2 = pOp->p2;
   int wrFlag;
@@ -2478,49 +2464,44 @@ case OP_OpenWrite: {
   sqlite3VdbeCleanupCursor(pCur);
   pCur->nullRow = 1;
   if( pX==0 ) break;
-  do{
-    /* We always provide a key comparison function.  If the table being
-    ** opened is of type INTKEY, the comparision function will be ignored. */
-    rc = sqlite3BtreeCursor(pX, p2, wrFlag,
-             sqlite3VdbeRecordCompare, pOp->p3,
-             &pCur->pCursor);
-    pCur->pKeyInfo = (KeyInfo*)pOp->p3;
-    if( pCur->pKeyInfo ){
-      pCur->pIncrKey = &pCur->pKeyInfo->incrKey;
-      pCur->pKeyInfo->enc = p->db->enc;
-    }else{
-      pCur->pIncrKey = &pCur->bogusIncrKey;
-    }
-    switch( rc ){
-      case SQLITE_BUSY: {
-        if( db->xBusyCallback==0 ){
-          p->pc = pc;
-          p->rc = SQLITE_BUSY;
-          p->pTos = &pTos[1 + (pOp->p2<=0)]; /* Operands must remain on stack */
-          return SQLITE_BUSY;
-        }else if( (*db->xBusyCallback)(db->pBusyArg, pOp->p3, ++busy)==0 ){
-          sqlite3SetString(&p->zErrMsg, sqlite3ErrStr(rc), (char*)0);
-          busy = 0;
-        }
-        break;
-      }
-      case SQLITE_OK: {
-        int flags = sqlite3BtreeFlags(pCur->pCursor);
-        pCur->intKey = (flags & BTREE_INTKEY)!=0;
-        pCur->zeroData = (flags & BTREE_ZERODATA)!=0;
-        busy = 0;
-        break;
-      }
-      case SQLITE_EMPTY: {
-        rc = SQLITE_OK;
-        busy = 0;
-        break;
-      }
-      default: {
-        goto abort_due_to_error;
+  /* We always provide a key comparison function.  If the table being
+  ** opened is of type INTKEY, the comparision function will be ignored. */
+  rc = sqlite3BtreeCursor(pX, p2, wrFlag,
+           sqlite3VdbeRecordCompare, pOp->p3,
+           &pCur->pCursor);
+  pCur->pKeyInfo = (KeyInfo*)pOp->p3;
+  if( pCur->pKeyInfo ){
+    pCur->pIncrKey = &pCur->pKeyInfo->incrKey;
+    pCur->pKeyInfo->enc = p->db->enc;
+  }else{
+    pCur->pIncrKey = &pCur->bogusIncrKey;
+  }
+  switch( rc ){
+    case SQLITE_BUSY: {
+      if( db->busyHandler.xFunc ){
+        p->pc = pc;
+        p->rc = SQLITE_BUSY;
+        p->pTos = &pTos[1 + (pOp->p2<=0)]; /* Operands must remain on stack */
+        return SQLITE_BUSY;
+      }else{
+        sqlite3SetString(&p->zErrMsg, sqlite3ErrStr(rc), (char*)0);
       }
+      break;
     }
-  }while( busy );
+    case SQLITE_OK: {
+      int flags = sqlite3BtreeFlags(pCur->pCursor);
+      pCur->intKey = (flags & BTREE_INTKEY)!=0;
+      pCur->zeroData = (flags & BTREE_ZERODATA)!=0;
+      break;
+    }
+    case SQLITE_EMPTY: {
+      rc = SQLITE_OK;
+      break;
+    }
+    default: {
+      goto abort_due_to_error;
+    }
+  }
   break;
 }