]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Change things so that journal2.test works with ENABLE_ATOMIC_WRITE.
authordan <dan@noemail.net>
Mon, 21 Jun 2010 12:34:29 +0000 (12:34 +0000)
committerdan <dan@noemail.net>
Mon, 21 Jun 2010 12:34:29 +0000 (12:34 +0000)
FossilOrigin-Name: a64d96db09ef2b7651fa4e98d3c7bf3ae5d3fe96

manifest
manifest.uuid
src/pager.c
test/malloc_common.tcl
test/pager1.test

index 231f496cdf3848a00851822e1f725b90948d3583..e54d79b686dcff4a27b21828a996ab7ec7802f82 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Add\sfurther\spager\stests.
-D 2010-06-21T07:45:47
+C Change\sthings\sso\sthat\sjournal2.test\sworks\swith\sENABLE_ATOMIC_WRITE.
+D 2010-06-21T12:34:30
 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
 F Makefile.in a5cad1f8f3e021356bfcc6c77dc16f6f1952bbc3
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -156,7 +156,7 @@ F src/os_common.h a8f95b81eca8a1ab8593d23e94f8a35f35d4078f
 F src/os_os2.c 665876d5eec7585226b0a1cf5e18098de2b2da19
 F src/os_unix.c 5231a75a3799872b1250bc70c0e6a1a5960bc865
 F src/os_win.c 73608839342de32280cb378d3c2fc85a5dd80bd2
-F src/pager.c 6ebb43239ad4ae2c0b0720bbd88a6a84a301bc8a
+F src/pager.c 9f138b79b47090c1e31efe3d9ea191cc92981643
 F src/pager.h ca1f23c0cf137ac26f8908df2427c8b308361efd
 F src/parse.y ace5c7a125d9f2a410e431ee3209034105045f7e
 F src/pcache.c 1e9aa2dbc0845b52e1b51cc39753b6d1e041cb07
@@ -509,7 +509,7 @@ F test/mallocH.test 79b65aed612c9b3ed2dcdaa727c85895fd1bfbdb
 F test/mallocI.test e3ea401904d010cb7c1e4b2ee8803f4a9f5b999d
 F test/mallocJ.test b5d1839da331d96223e5f458856f8ffe1366f62e
 F test/mallocK.test d79968641d1b70d88f6c01bdb9a7eb4a55582cc9
-F test/malloc_common.tcl 4981dd86adf0d3f25c755ac3a425d6208fda6362
+F test/malloc_common.tcl 58caffc4be307b56c5b1438b5eba3eb278bd81f5
 F test/manydb.test b3d3bc4c25657e7f68d157f031eb4db7b3df0d3c
 F test/memdb.test 0825155b2290e900264daaaf0334b6dfe69ea498
 F test/memleak.test 10b9c6c57e19fc68c32941495e9ba1c50123f6e2
@@ -534,7 +534,7 @@ F test/notify2.test 195a467e021f74197be2c4fb02d6dee644b8d8db
 F test/notnull.test cc7c78340328e6112a13c3e311a9ab3127114347
 F test/null.test a8b09b8ed87852742343b33441a9240022108993
 F test/openv2.test af02ed0a9cbc0d2a61b8f35171d4d117e588e4ec
-F test/pager1.test e086d98a5312a7395d579117a1211d9110faffcc
+F test/pager1.test 86d034bf3ffe4e99648714443776440d0555f705
 F test/pager2.test ad062a51030dc1e2749f506528db4cc5bae6474c
 F test/pagerfault.test e67e9c18bf7b4bb8cc8d458d3a5ecc980f18a225
 F test/pageropt.test 8146bf448cf09e87bb1867c2217b921fb5857806
@@ -825,7 +825,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P f6d26e07b70965e332b1589804ca938593a5f432
-R 57527134db79eb4730ccc85bc2c2f806
+P 4104b175a8c3560a7680f3d2b54416821bb2e19d
+R aa81338105a8066f92038016780c9df7
 U dan
-Z 286faa52a0364bba3d1b0d11286b24cb
+Z 4c6c5e973462d689a9ddf24faae3aa9f
index e246eaf3dc80170cec80257944605507b9321e1e..003bedc5728541d722271b37ed5925def2e6c5f8 100644 (file)
@@ -1 +1 @@
-4104b175a8c3560a7680f3d2b54416821bb2e19d
\ No newline at end of file
+a64d96db09ef2b7651fa4e98d3c7bf3ae5d3fe96
\ No newline at end of file
index 3d16c66f258c0dab313925004d06488cce172a6a..a5377d4c3ada4fa0ece9e5f1e858e4679b2f68b0 100644 (file)
@@ -336,7 +336,6 @@ struct Pager {
   u8 tempFile;                /* zFilename is a temporary file */
   u8 readOnly;                /* True for a read-only database */
   u8 memDb;                   /* True to inhibit all file I/O */
-  u8 safeJrnlHandle;          /* True if jrnl may be held open with no lock */
 
   /* The following block contains those class members that are dynamically
   ** modified during normal operations. The other variables in this structure
@@ -1220,14 +1219,20 @@ static int pagerUseWal(Pager *pPager){
 static void pager_unlock(Pager *pPager){
   if( !pPager->exclusiveMode ){
     int rc = SQLITE_OK;          /* Return code */
+    int iDc = isOpen(pPager->fd)?sqlite3OsDeviceCharacteristics(pPager->fd):0;
 
     /* Always close the journal file when dropping the database lock.
     ** Otherwise, another connection with journal_mode=delete might
     ** delete the file out from under us.
     */
-    if( pPager->safeJrnlHandle==0 
-     || (pPager->journalMode!=PAGER_JOURNALMODE_TRUNCATE 
-      && pPager->journalMode!=PAGER_JOURNALMODE_PERSIST)
+    assert( (PAGER_JOURNALMODE_MEMORY   & 5)!=1 );
+    assert( (PAGER_JOURNALMODE_OFF      & 5)!=1 );
+    assert( (PAGER_JOURNALMODE_WAL      & 5)!=1 );
+    assert( (PAGER_JOURNALMODE_DELETE   & 5)!=1 );
+    assert( (PAGER_JOURNALMODE_TRUNCATE & 5)==1 );
+    assert( (PAGER_JOURNALMODE_PERSIST  & 5)==1 );
+    if( 0==(iDc & SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN)
+     || 1!=(pPager->journalMode & 5)
     ){
       sqlite3OsClose(pPager->jfd);
     }
@@ -3096,7 +3101,6 @@ int sqlite3PagerClose(Pager *pPager){
   sqlite3BeginBenignMalloc();
   pPager->errCode = 0;
   pPager->exclusiveMode = 0;
-  pPager->safeJrnlHandle = 0;
 #ifndef SQLITE_OMIT_WAL
   sqlite3WalClose(pPager->pWal,
     (pPager->noSync ? 0 : pPager->sync_flags), 
@@ -3123,6 +3127,7 @@ int sqlite3PagerClose(Pager *pPager){
   enable_simulated_io_errors();
   PAGERTRACE(("CLOSE %d\n", PAGERID(pPager)));
   IOTRACE(("CLOSE %p\n", pPager))
+  sqlite3OsClose(pPager->jfd);
   sqlite3OsClose(pPager->fd);
   sqlite3PageFree(pTmp);
   sqlite3PcacheClose(pPager->pPCache);
@@ -4507,10 +4512,6 @@ static int pager_open_journal(Pager *pPager){
       );
 #else
       rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, flags, 0);
-      if( rc==SQLITE_OK ){
-        int iDc = sqlite3OsDeviceCharacteristics(pPager->jfd);
-        pPager->safeJrnlHandle = (iDc&SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN)!=0;
-      }
 #endif
     }
     assert( rc!=SQLITE_OK || isOpen(pPager->jfd) );
index dc68b1b53a6818b26b7e649ac903e4a200578203..8202b19aff0fabe5ec48d0bdac7de13b94efdf00 100644 (file)
@@ -136,14 +136,14 @@ proc faultsim_save_and_close {} {
   catch { db close }
   return ""
 }
-proc faultsim_restore_and_reopen {} {
+proc faultsim_restore_and_reopen {{dbfile test.db}} {
   catch { db close }
   foreach f [glob -nocomplain test.db*] { file delete -force $f }
   foreach f2 [glob -nocomplain sv_test.db*] {
     set f [string range $f2 3 end]
     file copy -force $f2 $f
   }
-  sqlite3 db test.db
+  sqlite3 db $dbfile
   sqlite3_extended_result_codes db 1
   sqlite3_db_config_lookaside db 0 0 0
 }
@@ -156,7 +156,7 @@ proc faultsim_integrity_check {{db db}} {
 proc faultsim_delete_and_reopen {{file test.db}} {
   catch { db close }
   foreach f [glob -nocomplain test.db*] { file delete -force $f }
-  sqlite3 db test.db
+  sqlite3 db $file
 }
 
 
index 313c0f36e04f3f6ce5b2da559b5380ecde0d8318..f7a821b6d210bd8d2ce164c8c24136cc5eb1dd64 100644 (file)
@@ -227,6 +227,13 @@ do_execsql_test pager1-3.6 { COMMIT } {}
 # pager1.4.3.*: Test that the contents of a hot-journal are ignored if the
 #               page-size or sector-size in the journal header appear to
 #               be invalid (too large, too small or not a power of 2).
+#
+# pager1.4.4.*: Test hot-journal rollback of journal file with a master
+#               journal pointer generated in various "PRAGMA synchronous"
+#               modes.
+#
+# pager1.4.5.*: Test that hot-journal rollback stops if it encounters a
+#               journal-record for which the checksum fails.
 # 
 do_test pager1.4.1.1 {
   faultsim_delete_and_reopen
@@ -354,6 +361,146 @@ foreach {tn ofst value result} {
 }
 db close
 
+# Set up a VFS that snapshots the file-system just before a master journal
+# file is deleted to commit a multi-file transaction. Specifically, the
+# file-system is saved just before the xDelete() call to remove the 
+# master journal file from the file-system.
+#
+testvfs tv -default 1
+tv script copy_on_mj_delete
+set ::mj_filename_length 0
+proc copy_on_mj_delete {method filename args} {
+  if {[string match *mj* [file tail $filename]]} { 
+    set ::mj_filename_length [string length $filename]
+    faultsim_save 
+  }
+  return SQLITE_OK
+}
+
+set pwd [pwd]
+foreach {tn1 tcl} {
+  1 { set prefix "test.db" }
+  2 { 
+    # This test depends on the underlying VFS being able to open paths
+    # 512 bytes in length. The idea is to create a hot-journal file that
+    # contains a master-journal pointer so large that it could contain
+    # a valid page record (if the file page-size is 512 bytes). So as to
+    # make sure SQLite doesn't get confused by this.
+    #
+    set nPadding [expr 511 - $::mj_filename_length]
+
+    # We cannot just create a really long database file name to open, as
+    # Linux limits a single component of a path to 255 bytes by default
+    # (and presumably other systems have limits too). So create a directory
+    # hierarchy to work in.
+    #
+    set dirname "d123456789012345678901234567890/"
+    set nDir [expr $nPadding / 32]
+    if { $nDir } {
+      set p [string repeat $dirname $nDir]
+      file mkdir $p
+      cd $p
+    }
+
+    set padding [string repeat x [expr $nPadding %32]]
+    set prefix "test.db${padding}"
+  }
+} {
+  eval $tcl
+  foreach {tn2 sql} {
+    o { 
+      PRAGMA main.synchronous=OFF;
+      PRAGMA aux.synchronous=OFF;
+    }
+    o512 { 
+      PRAGMA main.synchronous=OFF;
+      PRAGMA aux.synchronous=OFF;
+      PRAGMA main.page_size = 512;
+      PRAGMA aux.page_size = 512;
+    }
+    n { 
+      PRAGMA main.synchronous=NORMAL;
+      PRAGMA aux.synchronous=NORMAL;
+    }
+    f { 
+      PRAGMA main.synchronous=FULL;
+      PRAGMA aux.synchronous=FULL;
+    }
+  } {
+
+    set tn "${tn1}.${tn2}"
+  
+    # Set up a connection to have two databases, test.db (main) and 
+    # test.db2 (aux). Then run a multi-file transaction on them. The
+    # VFS will snapshot the file-system just before the master-journal
+    # file is deleted to commit the transaction.
+    #
+    tv filter xDelete
+    do_test pager1-4.4.$tn.1 {
+      faultsim_delete_and_reopen $prefix
+      execsql "
+        ATTACH '${prefix}2' AS aux;
+        $sql
+        CREATE TABLE a(x);
+        CREATE TABLE aux.b(x);
+        INSERT INTO a VALUES('double-you');
+        INSERT INTO a VALUES('why');
+        INSERT INTO a VALUES('zed');
+        INSERT INTO b VALUES('won');
+        INSERT INTO b VALUES('too');
+        INSERT INTO b VALUES('free');
+      "
+      execsql {
+        BEGIN;
+          INSERT INTO a SELECT * FROM b WHERE rowid<=3;
+          INSERT INTO b SELECT * FROM a WHERE rowid<=3;
+        COMMIT;
+      }
+    } {}
+    tv filter {}
+    
+    # Check that the transaction was committed successfully.
+    #
+    do_execsql_test pager1-4.4.$tn.2 {
+      SELECT * FROM a
+    } {double-you why zed won too free}
+    do_execsql_test pager1-4.4.$tn.3 {
+      SELECT * FROM b
+    } {won too free double-you why zed}
+    
+    # Restore the file-system and reopen the databases. Check that it now
+    # appears that the transaction was not committed (because the file-system
+    # was restored to the state where it had not been).
+    #
+    do_test pager1-4.4.$tn.4 {
+      faultsim_restore_and_reopen $prefix
+      execsql "ATTACH '${prefix}2' AS aux"
+    } {}
+    do_execsql_test pager1-4.4.$tn.5 {SELECT * FROM a} {double-you why zed}
+    do_execsql_test pager1-4.4.$tn.6 {SELECT * FROM b} {won too free}
+    
+    # Restore the file-system again. This time, before reopening the databases,
+    # delete the master-journal file from the file-system. It now appears that
+    # the transaction was committed (no master-journal file == no rollback).
+    #
+    do_test pager1-4.4.$tn.7 {
+      faultsim_restore_and_reopen $prefix
+      foreach f [glob ${prefix}-mj*] { file delete -force $f }
+      execsql "ATTACH '${prefix}2' AS aux"
+    } {}
+    do_execsql_test pager1-4.4.$tn.8 {
+      SELECT * FROM a
+    } {double-you why zed won too free}
+    do_execsql_test pager1-4.4.$tn.9 {
+      SELECT * FROM b
+    } {won too free double-you why zed}
+  }
+
+  cd $pwd
+}
+db close
+tv delete
+
 #-------------------------------------------------------------------------
 # The following tests deal with multi-file commits.
 #
@@ -373,7 +520,10 @@ db close
 #               name does not lie on the same sector as the last journal file
 #               record.
 #
-# pager1-5.5.*: 
+# pager1-5.5.*: Check that in journal_mode=PERSIST mode, a journal file is
+#               truncated to zero bytes when a multi-file transaction is 
+#               committed (instead of the first couple of bytes being zeroed).
+#
 #
 do_test pager1-5.1.1 {
   faultsim_delete_and_reopen