]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix a problem with recovering from an IO error in exclusive-locking mode. (CVS 5112)
authordanielk1977 <danielk1977@noemail.net>
Fri, 9 May 2008 16:57:50 +0000 (16:57 +0000)
committerdanielk1977 <danielk1977@noemail.net>
Fri, 9 May 2008 16:57:50 +0000 (16:57 +0000)
FossilOrigin-Name: 7a44fb965b3477fb78901939ba35d569e5638c19

manifest
manifest.uuid
src/btree.c
src/pager.c
src/test_osinst.c
test/incrvacuum_ioerr.test

index aae82aa972d71570385eb79384fc2c2cfe50127c..4dd4e527d257c0d55aa6c0785c90604eab7ab395 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Do\snot\sclear\sthe\serror\scode\sor\serror\smessage\sin\ssqlite3_clear_bindings().\nTicket\s#3063.\s(CVS\s5111)
-D 2008-05-09T14:39:45
+C Fix\sa\sproblem\swith\srecovering\sfrom\san\sIO\serror\sin\sexclusive-locking\smode.\s(CVS\s5112)
+D 2008-05-09T16:57:51
 F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
 F Makefile.in 8b9b8263852f0217157f9042b8e3dae7427ec739
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -85,7 +85,7 @@ F src/attach.c 496cc628b2e8c4d8db99d7c136761fcbebd8420b
 F src/auth.c c8b2ab5c8bad4bd90ed7c294694f48269162c627
 F src/bitvec.c 8ec2212cfb702bc4f402c0b7ae7623d85320c714
 F src/btmutex.c 483ced3c52205b04b97df69161fadbf87f4f1ea2
-F src/btree.c 7401bcbdabd87360351953e5009530c47e4fb305
+F src/btree.c 7bee6ba457f3e241911fab69b1602eb43c65b438
 F src/btree.h 8826591bf54dd35fcf2e67473d5f1bae253861c7
 F src/btreeInt.h dc04ee33d8eb84714b2acdf81336fbbf6e764530
 F src/build.c a52d9d51341444a2131e3431608f245db80d9591
@@ -121,7 +121,7 @@ F src/os_common.h e8b748b2f2ecc8a498e50bfe5d8721f189c19d2a
 F src/os_os2.c 30c378b093d9c17387ebb0ebbf21b7d55a98202b
 F src/os_unix.c a810e2aefdaddacf479407f76f8f4ca381d231b2
 F src/os_win.c 3a60bddd07ea6f8adb2314dd5996ac97b988f403
-F src/pager.c fc173b7ee0b9ee630688466adacd506225417eb7
+F src/pager.c c4e0bcb1f451d2b8601e1cf50e680d88bf175055
 F src/pager.h 4f051fd856de6fd3c19aef5f82eace54122b9173
 F src/parse.y fc4bd35c6088901f7c8daead26c6fb11c87d22e7
 F src/pragma.c 2e4bb2e76e48a32750529fdc4bfe86ac5f54e01b
@@ -156,7 +156,7 @@ F src/test_loadext.c 22065d601a18878e5542191001f0eaa5d77c0ed8
 F src/test_malloc.c c92a65e8f9b31bb2b332448d92d2016c000a963d
 F src/test_md5.c bca40b727c57462ddb415e57c5323445a1bb1a40
 F src/test_onefile.c 2fea6d22f13f5f286356c80c77ffd41f995f2b7a
-F src/test_osinst.c b2947f2ef6201ecc0a922cd2241880a955f5af0d
+F src/test_osinst.c f84ac00d61145af1be287754c153d04048b67888
 F src/test_schema.c e3f93725f7c5b2cff84a69dc4332040dfbc8f81a
 F src/test_server.c a6ece6c835e7eae835054124e09e947e422b1ac5
 F src/test_tclvar.c b2d1115e4d489179d3f029e765211b2ad527ba59
@@ -329,7 +329,7 @@ F test/incrblob.test 4455fffd08b2f9418a9257e18b135d72273eff3e
 F test/incrblob_err.test 5273097dc7c97f9b7008423a6ffd5c80d21923cb
 F test/incrvacuum.test 1a2b0bddc76629afeb41e3d8ea3e4563982d16b9
 F test/incrvacuum2.test 46ef65f377e3937cfd1ba66e818309dab46f590d
-F test/incrvacuum_ioerr.test 34297e36ef3399933064ee551ad55ba5d70c3a15
+F test/incrvacuum_ioerr.test bc1253285d3a8f6a82a510a0596485dfb83d6ec1
 F test/index.test cbf301cdb2da43e4eac636c3400c2439af1834ad
 F test/index2.test ee83c6b5e3173a3d7137140d945d9a5d4fdfb9d6
 F test/index3.test 727d55dceb9a4ec36675057bb5becfc265e28ca6
@@ -634,7 +634,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
 F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
-P ab18b4e75916b05863b31bc63625aa64a104a42c
-R 18e63cebbbff2189e064184403f168a0
-U drh
-Z d4393eb7d22c3e8846462316d45daa10
+P 069f4560107246fdc31e1f15c3ad7d3dae2b9ad8
+R f45b51024a5e8c743be851676769c12e
+U danielk1977
+Z 6411c1571b3ff8cf23c5c624d3f8d386
index e8b2663b7abbd1486e85074d7f4f7db6914464c5..c5964fc1c4d6870bd0ab754d34766520d003cd56 100644 (file)
@@ -1 +1 @@
-069f4560107246fdc31e1f15c3ad7d3dae2b9ad8
\ No newline at end of file
+7a44fb965b3477fb78901939ba35d569e5638c19
\ No newline at end of file
index d87eb040f21fac7c7d781be9297080d5593f5aef..2f8c6ed3d5cdd7cd4dfc79a17f1305c55485a782 100644 (file)
@@ -9,7 +9,7 @@
 **    May you share freely, never taking more than you give.
 **
 *************************************************************************
-** $Id: btree.c,v 1.457 2008/05/07 19:11:03 danielk1977 Exp $
+** $Id: btree.c,v 1.458 2008/05/09 16:57:51 danielk1977 Exp $
 **
 ** This file implements a external (disk-based) database using BTrees.
 ** See the header comment on "btreeInt.h" for additional information.
@@ -1644,6 +1644,7 @@ int sqlite3BtreeGetAutoVacuum(Btree *p){
 static int lockBtree(BtShared *pBt){
   int rc;
   MemPage *pPage1;
+  int nPage;
 
   assert( sqlite3_mutex_held(pBt->mutex) );
   if( pBt->pPage1 ) return SQLITE_OK;
@@ -1654,7 +1655,11 @@ static int lockBtree(BtShared *pBt){
   ** a valid database file. 
   */
   rc = SQLITE_NOTADB;
-  if( sqlite3PagerPagecount(pBt->pPager)>0 ){
+  nPage = sqlite3PagerPagecount(pBt->pPager);
+  if( nPage<0 ){
+    rc = SQLITE_IOERR;
+    goto page1_init_failed;
+  }else if( nPage>0 ){
     int pageSize;
     int usableSize;
     u8 *page1 = pPage1->aData;
index e99e60a53bfb815754a4196e6a22c336eb261998..75f069de6b292b3f7eced72c98e7a4f0f083c4c5 100644 (file)
@@ -18,7 +18,7 @@
 ** file simultaneously, or one process from reading the database while
 ** another is writing.
 **
-** @(#) $Id: pager.c,v 1.443 2008/05/07 19:11:03 danielk1977 Exp $
+** @(#) $Id: pager.c,v 1.444 2008/05/09 16:57:51 danielk1977 Exp $
 */
 #ifndef SQLITE_OMIT_DISKIO
 #include "sqliteInt.h"
@@ -1397,9 +1397,11 @@ static int pager_end_transaction(Pager *pPager, int hasMaster){
     pPager->stmtOpen = 0;
   }
   if( pPager->journalOpen ){
-    if( (pPager->exclusiveMode ||
-         pPager->journalMode==PAGER_JOURNALMODE_PERSIST) 
-       && (rc = zeroJournalHdr(pPager, hasMaster))==SQLITE_OK ){
+    if( pPager->exclusiveMode 
+     || pPager->journalMode==PAGER_JOURNALMODE_PERSIST
+    ){
+      rc = zeroJournalHdr(pPager, hasMaster);
+      pager_error(pPager, rc);
       pPager->journalOff = 0;
       pPager->journalStarted = 0;
     }else{
@@ -3412,8 +3414,8 @@ static int pagerSharedLock(Pager *pPager){
     if( pPager->journalOpen ){
       isHot = 1;
     }
-    pager_reset(pPager);
     pPager->errCode = SQLITE_OK;
+    pager_reset(pPager);
   }
 
   /* If the pager is still in an error state, do not proceed. The error 
index ab7bb54cf2e47fd81b7a0da6727df6bd04e8c426..3e61110d1421522773c28af6035bf3aa0899530b 100644 (file)
@@ -303,7 +303,9 @@ static int instWrite(
 ** Truncate an inst-file.
 */
 static int instTruncate(sqlite3_file *pFile, sqlite_int64 size){
-  OS_TIME_IO(OS_TRUNCATE, 0, size, p->pReal->pMethods->xTruncate(p->pReal, size));
+  OS_TIME_IO(OS_TRUNCATE, 0, (int)size, 
+    p->pReal->pMethods->xTruncate(p->pReal, size)
+  );
 }
 
 /*
@@ -632,6 +634,34 @@ static void put32bits(unsigned char *p, unsigned int v){
   p[3] = v;
 }
 
+static void binarylog_flush(InstVfsBinaryLog *pLog){
+  sqlite3_file *pFile = pLog->pOut;
+
+#ifdef SQLITE_TEST
+  extern int sqlite3_io_error_pending;
+  extern int sqlite3_io_error_persist;
+  extern int sqlite3_diskfull_pending;
+
+  int pending = sqlite3_io_error_pending;
+  int persist = sqlite3_io_error_persist;
+  int diskfull = sqlite3_diskfull_pending;
+
+  sqlite3_io_error_pending = 0;
+  sqlite3_io_error_persist = 0;
+  sqlite3_diskfull_pending = 0;
+#endif
+
+  pFile->pMethods->xWrite(pFile, pLog->zBuf, pLog->nBuf, pLog->iOffset);
+  pLog->iOffset += pLog->nBuf;
+  pLog->nBuf = 0;
+
+#ifdef SQLITE_TEST
+  sqlite3_io_error_pending = pending;
+  sqlite3_io_error_persist = persist;
+  sqlite3_diskfull_pending = diskfull;
+#endif
+}
+
 static void binarylog_xcall(
   void *p,
   int eEvent,
@@ -646,10 +676,7 @@ static void binarylog_xcall(
   InstVfsBinaryLog *pLog = (InstVfsBinaryLog *)p;
   unsigned char *zRec;
   if( (28+pLog->nBuf)>BINARYLOG_BUFFERSIZE ){
-    sqlite3_file *pFile = pLog->pOut;
-    pFile->pMethods->xWrite(pFile, pLog->zBuf, pLog->nBuf, pLog->iOffset);
-    pLog->iOffset += pLog->nBuf;
-    pLog->nBuf = 0;
+    binarylog_flush(pLog);
   }
   zRec = (unsigned char *)&pLog->zBuf[pLog->nBuf];
   put32bits(&zRec[0], eEvent);
@@ -669,7 +696,7 @@ static void binarylog_xdel(void *p){
   InstVfsBinaryLog *pLog = (InstVfsBinaryLog *)p;
   sqlite3_file *pFile = pLog->pOut;
   if( pLog->nBuf ){
-    pFile->pMethods->xWrite(pFile, pLog->zBuf, pLog->nBuf, pLog->iOffset);
+    binarylog_flush(pLog);
   }
   pFile->pMethods->xClose(pFile);
   sqlite3_free(pLog->pOut);
@@ -698,10 +725,7 @@ static void binarylog_blob(
   nWrite = nBlob + 28;
 
   if( (nWrite+pLog->nBuf)>BINARYLOG_BUFFERSIZE ){
-    sqlite3_file *pFile = pLog->pOut;
-    pFile->pMethods->xWrite(pFile, pLog->zBuf, pLog->nBuf, pLog->iOffset);
-    pLog->iOffset += pLog->nBuf;
-    pLog->nBuf = 0;
+    binarylog_flush(pLog);
   }
 
   zRec = (unsigned char *)&pLog->zBuf[pLog->nBuf];
@@ -750,8 +774,9 @@ sqlite3_vfs *sqlite3_instvfs_binarylog(
   pParent->xDelete(pParent, p->zOut, 0);
   rc = pParent->xOpen(pParent, p->zOut, p->pOut, flags, &flags);
   if( rc==SQLITE_OK ){
-    rc = p->pOut->pMethods->xWrite(p->pOut, "sqlite_ostrace1.....", 20, 0);
-    p->iOffset = 20;
+    memcpy(p->zBuf, "sqlite_ostrace1.....", 20);
+    p->iOffset = 0;
+    p->nBuf = 20;
   }
   if( rc ){
     binarylog_xdel(p);
@@ -863,18 +888,31 @@ static int test_sqlite3_instvfs(
     case IV_BINARYLOG: {
       char *zName = 0;
       char *zLog = 0;
+      char *zParent = 0;
       sqlite3_vfs *p;
       int isDefault = 0;
-      if( objc>2 && 0==strcmp("-default", Tcl_GetString(objv[2])) ){
+      int argbase = 2;
+
+      if( objc>2 && 0==strcmp("-default", Tcl_GetString(objv[argbase])) ){
         isDefault = 1;
+        argbase++;
+      }
+      if( objc>(argbase+1) 
+       && 0==strcmp("-parent", Tcl_GetString(objv[argbase])) 
+      ){
+        zParent = Tcl_GetString(objv[argbase+1]);
+        argbase += 2;
       }
-      if( (objc-isDefault)!=4 ){
-        Tcl_WrongNumArgs(interp, 2, objv, "?-default? NAME LOGFILE");
+
+      if( (objc-argbase)!=2 ){
+        Tcl_WrongNumArgs(
+            interp, 2, objv, "?-default? ?-parent VFS? NAME LOGFILE"
+        );
         return TCL_ERROR;
       }
-      zName = Tcl_GetString(objv[2+isDefault]);
-      zLog = Tcl_GetString(objv[3+isDefault]);
-      p = sqlite3_instvfs_binarylog(zName, 0, zLog);
+      zName = Tcl_GetString(objv[argbase]);
+      zLog = Tcl_GetString(objv[argbase+1]);
+      p = sqlite3_instvfs_binarylog(zName, zParent, zLog);
       if( !p ){
         Tcl_AppendResult(interp, "error creating vfs ", 0);
         return TCL_ERROR;
index fdc38670819f913ac9fad62661156b96897e7af9..a63b1c6ce697663ae414e073e7eccf40e596dad0 100644 (file)
@@ -15,7 +15,7 @@
 # The tests in this file use special facilities that are only
 # available in the SQLite test fixture.
 #
-# $Id: incrvacuum_ioerr.test,v 1.3 2008/05/06 18:13:26 danielk1977 Exp $
+# $Id: incrvacuum_ioerr.test,v 1.4 2008/05/09 16:57:51 danielk1977 Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -27,6 +27,8 @@ ifcapable {!autovacuum} {
   return
 }
 
+if 0 {
+
 do_ioerr_test incrvacuum-ioerr-1 -cksum 1 -sqlprep {
   PRAGMA auto_vacuum = 'incremental';
   CREATE TABLE abc(a);
@@ -104,5 +106,81 @@ do_ioerr_test incrvacuum-ioerr-3 -start 1 -cksum 1 -tclprep {
   db close
 }
 
+}
+
+
+ifcapable shared_cache {
+
+  catch { db close }
+  file delete -force test.db
+  set ::enable_shared_cache [sqlite3_enable_shared_cache 1]
+  
+  # Create two connections to a single shared-cache:
+  #
+  sqlite3 db1 test.db
+  sqlite3 db2 test.db
+  
+  # Create a database with around 20 free pages.
+  #
+  do_test incrvacuum-ioerr-4.0 {
+    execsql {
+      PRAGMA page_size = 1024;
+      PRAGMA locking_mode = exclusive;
+      PRAGMA auto_vacuum = 'incremental';
+      BEGIN;
+      CREATE TABLE a(i integer, b blob);
+    } db1
+    for {set ii 0} {$ii < 20} {incr ii} {
+      execsql { INSERT INTO a VALUES($ii, randstr(800,1500)); } db1
+    }
+    execsql COMMIT db1
+    execsql {DELETE FROM a WHERE oid} db1
+  } {}
+  
+  set ::rc 1
+  for {set iTest 1} {$::rc && $iTest<2000} {incr iTest} {
+  
+    # Figure out how big the database is and how many free pages it
+    # has before running incremental-vacuum.
+    #
+    set nPage [expr {[file size test.db]/1024}]
+    set nFree [execsql {pragma freelist_count} db1]
+  
+    # Now run incremental-vacuum to vacuum 5 pages from the db file.
+    # The iTest'th I/O call is set to fail.
+    #
+    set ::sqlite_io_error_pending $iTest
+    set ::sqlite_io_error_persist 1
+    do_test incrvacuum-ioerr-4.$iTest.1 {
+      set ::rc [catch {execsql {pragma incremental_vacuum(5)} db1} msg]
+      expr {$::rc==0 || $msg eq "disk I/O error"}
+    } {1}
+  
+    set ::sqlite_io_error_pending 0
+    set ::sqlite_io_error_persist 0
+    set ::sqlite_io_error_hit 0
+    set ::sqlite_io_error_hardhit 0
+  
+    set nFree2 [execsql {pragma freelist_count} db1]
+    set nPage2 [expr {[file size test.db]/1024}]
+  
+    do_test incrvacuum-ioerr-4.$iTest.2 {
+      set shrink [expr {$nPage-$nPage2}]
+      expr {$shrink==0 || $shrink==5}
+    } {1}
+  
+    do_test incrvacuum-ioerr-4.$iTest.3 {
+      expr {$nPage - $nPage2}
+    } [expr {$nFree - $nFree2}]
+  }
+  
+  # Close the two database connections and restore the default
+  # shared-cache mode setting.
+  #
+  db1 close
+  db2 close
+  sqlite3_enable_shared_cache $::enable_shared_cache
+}
 
 finish_test
+