]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Detect attempts to use rbu vacuum on a wal mode database (not allowed). And attempts...
authordan <dan@noemail.net>
Tue, 19 Apr 2016 16:20:24 +0000 (16:20 +0000)
committerdan <dan@noemail.net>
Tue, 19 Apr 2016 16:20:24 +0000 (16:20 +0000)
FossilOrigin-Name: 00b2f4b09ffca5156e43c4db2bfe0b2c979c49b0

ext/rbu/rbuvacuum.test
ext/rbu/sqlite3rbu.c
manifest
manifest.uuid

index 045b2d1bb7ea91282353cb92418965ef486cf7aa..4380b78fbfc8773dd7ade7d4a333621452564a54 100644 (file)
 source [file join [file dirname [info script]] rbu_common.tcl]
 set ::testprefix rbuvacuum
 
-proc do_rbu_vacuum_test {tn} {
+proc do_rbu_vacuum_test {tn step} {
   uplevel [list do_test $tn.1 {
     forcedelete state.db
-    if {$::step==0} { sqlite3rbu_vacuum rbu test.db state.db }
+    if {$step==0} { sqlite3rbu_vacuum rbu test.db state.db }
     while 1 {
-      if {$::step==1} { sqlite3rbu_vacuum rbu test.db state.db }
+      if {$step==1} { sqlite3rbu_vacuum rbu test.db state.db }
       set rc [rbu step]
       if {$rc!="SQLITE_OK"} break
-      if {$::step==1} { rbu close }
+      if {$step==1} { rbu close }
     }
     rbu close
   } {SQLITE_DONE}]
@@ -49,7 +49,7 @@ foreach step {0 1} {
     INSERT INTO t1 VALUES(7, 8, 9);
     PRAGMA integrity_check;
   } {ok}
-  do_rbu_vacuum_test 1.1
+  do_rbu_vacuum_test 1.1 $step
 
   # A vacuum that actually reclaims space.
   do_execsql_test 1.2.1 {
@@ -64,7 +64,7 @@ foreach step {0 1} {
     DELETE FROM t1 WHERE rowid BETWEEN 8 AND 11;
     PRAGMA page_count;
   } {12}
-  do_rbu_vacuum_test 1.2.3
+  do_rbu_vacuum_test 1.2.3 $step
   do_execsql_test 1.2.4 {
     PRAGMA page_count;
   } {3}
@@ -82,7 +82,7 @@ foreach step {0 1} {
     DELETE FROM t1 WHERE rowid BETWEEN 12 AND 15;
     PRAGMA page_count;
   } {18}
-  do_rbu_vacuum_test 1.3.3
+  do_rbu_vacuum_test 1.3.3 $step
   do_execsql_test 1.3.4 {
     PRAGMA page_count;
   } {5}
@@ -102,7 +102,7 @@ foreach step {0 1} {
     DELETE FROM t2 WHERE b BETWEEN 2 AND 7;
     PRAGMA page_count;
   } {20}
-  do_rbu_vacuum_test 1.4.2
+  do_rbu_vacuum_test 1.4.2 $step
   do_execsql_test 1.4.3 {
     PRAGMA page_count;
   } {10}
@@ -120,7 +120,7 @@ foreach step {0 1} {
     DELETE FROM t2 WHERE b BETWEEN 8 AND 12;
     PRAGMA page_count;
   } {35}
-  do_rbu_vacuum_test 1.4.2
+  do_rbu_vacuum_test 1.4.2 $step
   do_execsql_test 1.4.3 {
     PRAGMA page_count;
   } {15}
@@ -135,7 +135,7 @@ foreach step {0 1} {
     INSERT INTO t3 VALUES('d', 'e', 'f');
     INSERT INTO t3 VALUES('g', 'h', 'i');
   }
-  do_rbu_vacuum_test 1.5.2
+  do_rbu_vacuum_test 1.5.2 $step
   do_execsql_test 1.5.3 {
     SELECT * FROM t3
   } {a b c d e f g h i}
@@ -146,7 +146,7 @@ foreach step {0 1} {
     INSERT INTO t3 VALUES('j', 'k', 'l');
     DELETE FROM t3 WHERE a = 'g';
   }
-  do_rbu_vacuum_test 1.5.5
+  do_rbu_vacuum_test 1.5.5 $step
   do_execsql_test 1.5.6 {
     SELECT rowid, * FROM t3 ORDER BY b
   } {1 a b c 2 d e f 4 j k l}
@@ -157,7 +157,7 @@ foreach step {0 1} {
     INSERT INTO t4 VALUES('d', 'e', 'f');
     INSERT INTO t4 VALUES('g', 'h', 'i');
   }
-  do_rbu_vacuum_test 1.6.2
+  do_rbu_vacuum_test 1.6.2 $step
   do_execsql_test 1.6.3 {
     SELECT * FROM t4
   } {a b c d e f g h i}
@@ -169,13 +169,69 @@ foreach step {0 1} {
     INSERT INTO t4 VALUES('j', 'k', 'l');
     DELETE FROM t4 WHERE a='g';
   }
-  do_rbu_vacuum_test 1.6.5
+  do_rbu_vacuum_test 1.6.5 $step
   do_execsql_test 1.6.6 {
     SELECT * FROM t4 ORDER BY b
   } {a b c d e f j k l}
 
 }
 
+#-------------------------------------------------------------------------
+# Test some error cases:
+#
+#   2.1.* the db being vacuumed being in wal mode already.
+#   2.2.* database modified mid vacuum.
+#
+reset_db
+do_execsql_test 2.1.0 {
+  CREATE TABLE t1(a, b);
+  INSERT INTO t1 VALUES(1, 2);
+  INSERT INTO t1 VALUES(3, 4);
+  INSERT INTO t1 VALUES(5, 6);
+  INSERT INTO t1 VALUES(7, 8);
+  PRAGMA journal_mode = wal;
+  INSERT INTO t1 VALUES(9, 10);
+} wal
+do_test 2.1.1 {
+  forcedelete state.db
+  sqlite3rbu_vacuum rbu test.db state.db
+  rbu step
+} {SQLITE_ERROR}
+do_test 2.1.2 {
+  list [catch { rbu close } msg] $msg
+} {1 {SQLITE_ERROR - cannot vacuum wal mode database}}
+
+reset_db
+do_execsql_test 2.2.0 {
+  CREATE TABLE tx(a PRIMARY KEY, b BLOB);
+  INSERT INTO tx VALUES(1, randomblob(900));
+  INSERT INTO tx SELECT a+1, randomblob(900) FROM tx;
+  INSERT INTO tx SELECT a+2, randomblob(900) FROM tx;
+  INSERT INTO tx SELECT a+4, randomblob(900) FROM tx;
+  INSERT INTO tx SELECT a+8, randomblob(900) FROM tx;
+}
+db_save_and_close
+for {set i 1} 1 {incr i} {
+  forcedelete state.db
+  db_restore_and_reopen
+
+  sqlite3rbu_vacuum rbu test.db state.db
+  for {set step 0} {$step<$i} {incr step} { rbu step }
+  rbu close
+  if {[file exists test.db-wal]} break
+
+  execsql { INSERT INTO tx VALUES(20, 20) }
+
+  do_test 2.2.$i.1 {
+    sqlite3rbu_vacuum rbu test.db state.db 
+    rbu step
+  } {SQLITE_BUSY}
+  do_test 2.2.$i.2 {
+    list [catch { rbu close } msg] $msg
+  } {1 {SQLITE_BUSY - database modified during rbu vacuum}}
+
+}
+
 catch { db close }
 finish_test
 
index 60773b79f8f7f7878cffd2c8c1a6c917300e7685..6ccf54826cc56cecdcf1b6165915b7c75b42b5d5 100644 (file)
@@ -399,7 +399,7 @@ struct rbu_file {
   int openFlags;                  /* Flags this file was opened with */
   u32 iCookie;                    /* Cookie value for main db files */
   u8 iWriteVer;                   /* "write-version" value for main db files */
-  u8 bNolock;
+  u8 bNolock;                     /* True to fail EXCLUSIVE locks */
 
   int nShm;                       /* Number of entries in apShm[] array */
   char **apShm;                   /* Array of mmap'd *-shm regions */
@@ -2373,9 +2373,12 @@ static void rbuOpenDatabase(sqlite3rbu *p){
   }
 
   p->eStage = 0;
-  if( p->dbMain==0 ){
+  if( p->rc==SQLITE_OK && p->dbMain==0 ){
     if( !rbuIsVacuum(p) ){
       p->dbMain = rbuOpenDbhandle(p, p->zTarget, 1);
+    }else if( p->pRbuFd->pWalFd ){
+      p->rc = SQLITE_ERROR;
+      p->zErrmsg = sqlite3_mprintf("cannot vacuum wal mode database");
     }else{
       char *zTarget = sqlite3_mprintf("file:%s-vacuum?rbu_memory=1", p->zRbu);
       if( zTarget==0 ){
@@ -2987,6 +2990,7 @@ static void rbuIncrSchemaCookie(sqlite3rbu *p){
 static void rbuSaveState(sqlite3rbu *p, int eStage){
   if( p->rc==SQLITE_OK || p->rc==SQLITE_DONE ){
     sqlite3_stmt *pInsert = 0;
+    rbu_file *pFd = (rbuIsVacuum(p) ? p->pRbuFd : p->pTargetFd);
     int rc;
 
     assert( p->zErrmsg==0 );
@@ -3009,7 +3013,7 @@ static void rbuSaveState(sqlite3rbu *p, int eStage){
           RBU_STATE_ROW, p->nStep, 
           RBU_STATE_PROGRESS, p->nProgress,
           RBU_STATE_CKPT, p->iWalCksum,
-          RBU_STATE_COOKIE, (i64)p->pTargetFd->iCookie,
+          RBU_STATE_COOKIE, (i64)pFd->iCookie,
           RBU_STATE_OALSZ, p->iOalSz,
           RBU_STATE_PHASEONESTEP, p->nPhaseOneStep
       )
@@ -3431,17 +3435,21 @@ static sqlite3rbu *openRbuHandle(
       }
     }
 
-    if( p->rc==SQLITE_OK
-     && !rbuIsVacuum(p)
+    if( p->rc==SQLITE_OK 
      && (p->eStage==RBU_STAGE_OAL || p->eStage==RBU_STAGE_MOVE)
-     && pState->eStage!=0 && p->pTargetFd->iCookie!=pState->iCookie
-    ){   
-      /* At this point (pTargetFd->iCookie) contains the value of the
-      ** change-counter cookie (the thing that gets incremented when a 
-      ** transaction is committed in rollback mode) currently stored on 
-      ** page 1 of the database file. */
-      p->rc = SQLITE_BUSY;
-      p->zErrmsg = sqlite3_mprintf("database modified during rbu update");
+     && pState->eStage!=0
+    ){
+      rbu_file *pFd = (rbuIsVacuum(p) ? p->pRbuFd : p->pTargetFd);
+      if( pFd->iCookie!=pState->iCookie ){   
+        /* At this point (pTargetFd->iCookie) contains the value of the
+        ** change-counter cookie (the thing that gets incremented when a 
+        ** transaction is committed in rollback mode) currently stored on 
+        ** page 1 of the database file. */
+        p->rc = SQLITE_BUSY;
+        p->zErrmsg = sqlite3_mprintf("database modified during rbu %s",
+            (rbuIsVacuum(p) ? "vacuum" : "update")
+        );
+      }
     }
 
     if( p->rc==SQLITE_OK ){
@@ -3841,6 +3849,7 @@ static int rbuVfsRead(
           rbuPutU32(&aBuf[36], 0);          /* number of free pages */
           rbuPutU32(&aBuf[32], 0);          /* first page on free list trunk */
           rbuPutU32(&aBuf[28], 1);          /* size of db file in pages */
+          rbuPutU32(&aBuf[24], pRbu->pRbuFd->iCookie+1);  /* Change counter */
 
           if( iAmt>100 ){
             assert( iAmt>=101 );
@@ -3857,13 +3866,6 @@ static int rbuVfsRead(
       u8 *pBuf = (u8*)zBuf;
       p->iCookie = rbuGetU32(&pBuf[24]);
       p->iWriteVer = pBuf[19];
-      if( pRbu && rbuIsVacuum(p->pRbu) ){
-        rbu_file *pRbuFd = 0;
-        sqlite3_file_control(pRbu->dbRbu, "main", 
-            SQLITE_FCNTL_FILE_POINTER, (void*)&pRbuFd
-        );
-        rbuPutU32(&pBuf[24], pRbuFd->iCookie+1);
-      }
     }
   }
   return rc;
index 068554e465742062d9f51ee9ef48d91334ea671d..fe489077ea7ffafcf0b53dba9506e9fcd84879a1 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Another\sfix\sto\srbu\svacuum\sfor\sa\szipvfs\scase.
-D 2016-04-18T21:00:01.258
+C Detect\sattempts\sto\suse\srbu\svacuum\son\sa\swal\smode\sdatabase\s(not\sallowed).\sAnd\sattempts\sto\swrite\sto\sa\sdatabase\sin\sthe\smiddle\sof\san\srbu\svacuum\s(which\sprevents\sthe\svacuum\sfrom\sresuming).
+D 2016-04-19T16:20:24.513
 F Makefile.in eba680121821b8a60940a81454316f47a341487a
 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
 F Makefile.msc 71b8b16cf9393f68e2e2035486ca104872558836
@@ -246,8 +246,8 @@ F ext/rbu/rbufault2.test 9a7f19edd6ea35c4c9f807d8a3db0a03a5670c06
 F ext/rbu/rbufts.test 828cd689da825f0a7b7c53ffc1f6f7fdb6fa5bda
 F ext/rbu/rbuprogress.test 2023a7df2c523e3df1cb532eff811cda385a789a
 F ext/rbu/rbusave.test 0f43b6686084f426ddd040b878426452fd2c2f48
-F ext/rbu/rbuvacuum.test 75b4231f85622859e814c7f028afad0303f72f60
-F ext/rbu/sqlite3rbu.c ac4621fc62e0bc3e9e92fceb483c0207af25addf
+F ext/rbu/rbuvacuum.test b7194617c22f69e2015082a5414585aae2827a29
+F ext/rbu/sqlite3rbu.c d269d60bddb770fc9bbe747c47522f946562878d
 F ext/rbu/sqlite3rbu.h 1342ab6121e715b8da59ec35c5b5c16060be7a6b
 F ext/rbu/test_rbu.c 430b8b9520c233505371d564d3561e0b554355f4
 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
@@ -1483,7 +1483,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P d76f4aaa4caab713460421bd27365a82ac986c20
-R 02609be0d1cf35faad7663d479babac3
+P 29407d70e44ad9ea5ddaf1011d0e212b602a3ddf
+R da49b342c9cd61c56db951e40b34afc9
 U dan
-Z ecb53ed56b3181cf4b46470b55ef0f36
+Z 3a78d0d54b42b6cec75432abbb63bed7
index 74ea0959b880602f9e225cad7497bdfb6bbaacd2..4483a9f107d3e7668821172fadea22c39cd535e9 100644 (file)
@@ -1 +1 @@
-29407d70e44ad9ea5ddaf1011d0e212b602a3ddf
\ No newline at end of file
+00b2f4b09ffca5156e43c4db2bfe0b2c979c49b0
\ No newline at end of file