]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Enhance WAL mode so that the WAL file honors the journal size limit set
authordrh <drh@noemail.net>
Mon, 16 May 2011 21:00:27 +0000 (21:00 +0000)
committerdrh <drh@noemail.net>
Mon, 16 May 2011 21:00:27 +0000 (21:00 +0000)
by PRAGMA journal_size_limit.

FossilOrigin-Name: db7e500f69faf1906a84991ba67d26a195f02ae5

manifest
manifest.uuid
src/pager.c
src/wal.c
src/wal.h
test/wal7.test [new file with mode: 0644]

index e52173bba4c3940e9bceb49acdf0354d1d7f844f..4a39930802ae9ce8584c8bc159b9bd3dc4640c1e 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Make\sarrangements\sso\sthat\svirtual\stable\sinserts\sinto\sshadow\stables\sdo\nnot\smodify\sthe\ssqlite3_last_insert_rowid()\sreturn.\s\sDocument\sthat\sthis\nis\show\ssqlite3_last_insert_rowid()\sworks.
-D 2011-05-13T18:51:42.945
+C Enhance\sWAL\smode\sso\sthat\sthe\sWAL\sfile\shonors\sthe\sjournal\ssize\slimit\sset\nby\sPRAGMA\sjournal_size_limit.
+D 2011-05-16T21:00:27.928
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 4a7ed220f2e9a068fd0f0b2ec451439f63e629fc
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -165,7 +165,7 @@ F src/os_common.h a8f95b81eca8a1ab8593d23e94f8a35f35d4078f
 F src/os_os2.c 4a75888ba3dfc820ad5e8177025972d74d7f2440
 F src/os_unix.c 2c67d126874b78eb427371db4793f0e8fbc7448b
 F src/os_win.c ff0e14615a5086fa5ba6926e4ec0dc9cfb5a1a84
-F src/pager.c 24b689bc3639d534f5fb292d2c68038b1e720527
+F src/pager.c ebf0411b037fbc6dec272520be55fc11423e789a
 F src/pager.h 3f8c783de1d4706b40b1ac15b64f5f896bcc78d1
 F src/parse.y 12b7ebd61ea54f0e1b1083ff69cc2c8ce9353d58
 F src/pcache.c 09d38c44ab275db581f7a2f6ff8b9bc7f8c0faaa
@@ -245,8 +245,8 @@ F src/vdbeblob.c c3ccb7c8732858c680f442932e66ad06bb036562
 F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b
 F src/vdbetrace.c 5d0dc3d5fd54878cc8d6d28eb41deb8d5885b114
 F src/vtab.c 48dcef8bc757c2e7b488f68b5ddebb1650da2450
-F src/wal.c 7334009b396285b658a95a3b6bc6d2b016a1f794
-F src/wal.h 7a5fbb00114b7f2cd40c7e1003d4c41ce9d26840
+F src/wal.c de27c34c8016c00be348fc6bed588816557ceb66
+F src/wal.h 66b40bd91bc29a5be1c88ddd1f5ade8f3f48728a
 F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
 F src/where.c 55403ce19c506be6a321c7f129aff693d6103db5
 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
@@ -873,6 +873,7 @@ F test/wal3.test 5c396cc22497244d627306f4c1d360167353f8dd
 F test/wal4.test 3404b048fa5e10605facaf70384e6d2943412e30
 F test/wal5.test 1bbfaa316dc2a1d0d1fac3f4500c38a90055a41b
 F test/wal6.test 07aa31ca8892d0527f2c5c5a9a2a87aa421dfaa8
+F test/wal7.test 09bc8de3d11949571d6f7a4188b308059cec27e5
 F test/wal_common.tcl a98f17fba96206122eff624db0ab13ec377be4fe
 F test/walbak.test 4df1c7369da0301caeb9a48fa45997fd592380e4
 F test/walbig.test e882bc1d014afffbfa2b6ba36e0f07d30a633ad0
@@ -935,7 +936,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
 F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P 966f2d2c1f01b6345eab5df87a40d337ced1c087
-R bc50f0e830166d8298c23030a9099063
+P e569f18b989aef853c9d71eaf73d6967f0a8c583
+R cf1687694ba42845f8565b086734fa2b
 U drh
-Z 667528c5e659a82acf6d9a2a3fcf251b
+Z b788aa40bf13c0a5b33fd90cecbf33e8
index 033c321dcb2639e47835bd5a7ab3ca8d1a0ca320..8a54fcea5d8cacde2eea90962f3966365000d0dc 100644 (file)
@@ -1 +1 @@
-e569f18b989aef853c9d71eaf73d6967f0a8c583
\ No newline at end of file
+db7e500f69faf1906a84991ba67d26a195f02ae5
\ No newline at end of file
index 8ad6984f8aad55830926c217c9679ca89fd5d089..24db850273cb3d693a47ab63f5aae2ec8301c6a7 100644 (file)
@@ -6607,6 +6607,7 @@ int sqlite3PagerOkToChangeJournalMode(Pager *pPager){
 i64 sqlite3PagerJournalSizeLimit(Pager *pPager, i64 iLimit){
   if( iLimit>=-1 ){
     pPager->journalSizeLimit = iLimit;
+    sqlite3WalLimit(pPager->pWal, iLimit);
   }
   return pPager->journalSizeLimit;
 }
@@ -6698,7 +6699,8 @@ static int pagerOpenWal(Pager *pPager){
   */
   if( rc==SQLITE_OK ){
     rc = sqlite3WalOpen(pPager->pVfs, 
-        pPager->fd, pPager->zWal, pPager->exclusiveMode, &pPager->pWal
+        pPager->fd, pPager->zWal, pPager->exclusiveMode,
+        pPager->journalSizeLimit, &pPager->pWal
     );
   }
 
index 51ea18fb21677476c9f4ac626c41c1b1a8ef6267..1222660985b6bc04bd275b31f2f5fac2693bd908 100644 (file)
--- a/src/wal.c
+++ b/src/wal.c
@@ -412,6 +412,7 @@ struct Wal {
   sqlite3_file *pDbFd;       /* File handle for the database file */
   sqlite3_file *pWalFd;      /* File handle for WAL file */
   u32 iCallback;             /* Value to pass to log callback (or 0) */
+  i64 mxWalSize;             /* Truncate WAL to this size upon reset */
   int nWiData;               /* Size of array apWiData */
   volatile u32 **apWiData;   /* Pointer to wal-index content in memory */
   u32 szPage;                /* Database page size */
@@ -1234,6 +1235,7 @@ int sqlite3WalOpen(
   sqlite3_file *pDbFd,            /* The open database file */
   const char *zWalName,           /* Name of the WAL file */
   int bNoShm,                     /* True to run in heap-memory mode */
+  i64 mxWalSize,                  /* Truncate WAL to this size on reset */
   Wal **ppWal                     /* OUT: Allocated Wal handle */
 ){
   int rc;                         /* Return Code */
@@ -1266,6 +1268,7 @@ int sqlite3WalOpen(
   pRet->pWalFd = (sqlite3_file *)&pRet[1];
   pRet->pDbFd = pDbFd;
   pRet->readLock = -1;
+  pRet->mxWalSize = mxWalSize;
   pRet->zWalName = zWalName;
   pRet->exclusiveMode = (bNoShm ? WAL_HEAPMEMORY_MODE: WAL_NORMAL_MODE);
 
@@ -1287,6 +1290,13 @@ int sqlite3WalOpen(
   return rc;
 }
 
+/*
+** Change the size to which the WAL file is trucated on each reset.
+*/
+void sqlite3WalLimit(Wal *pWal, i64 iLimit){
+  if( pWal ) pWal->mxWalSize = iLimit;
+}
+
 /*
 ** Find the smallest page number out of all pages held in the WAL that
 ** has not been returned by any prior invocation of this method on the
@@ -2522,6 +2532,22 @@ static int walRestartLog(Wal *pWal){
         */
         int i;                    /* Loop counter */
         u32 *aSalt = pWal->hdr.aSalt;       /* Big-endian salt values */
+
+        /* Limit the size of WAL file if the journal_size_limit PRAGMA is
+        ** set to a non-negative value.  Log errors encountered
+        ** during the truncation attempt. */
+        if( pWal->mxWalSize>=0 ){
+          i64 sz;
+          int rx;
+          rx = sqlite3OsFileSize(pWal->pWalFd, &sz);
+          if( rx==SQLITE_OK && (sz > pWal->mxWalSize) ){
+            rx = sqlite3OsTruncate(pWal->pWalFd, pWal->mxWalSize);
+          }
+          if( rx ){
+            sqlite3_log(rx, "cannot limit WAL size: %s", pWal->zWalName);
+          }
+        }
+
         pWal->nCkpt++;
         pWal->hdr.mxFrame = 0;
         sqlite3Put4byte((u8*)&aSalt[0], 1 + sqlite3Get4byte((u8*)&aSalt[0]));
index 2039c701cf29bae49a7e984c4b1d59aa76683040..a62b23bbdc99f2551bcb8f8083541b0968113478 100644 (file)
--- a/src/wal.h
+++ b/src/wal.h
@@ -21,6 +21,7 @@
 
 #ifdef SQLITE_OMIT_WAL
 # define sqlite3WalOpen(x,y,z)                   0
+# define sqlite3WalLimit(x,y)
 # define sqlite3WalClose(w,x,y,z)                0
 # define sqlite3WalBeginReadTransaction(y,z)     0
 # define sqlite3WalEndReadTransaction(z)
 typedef struct Wal Wal;
 
 /* Open and close a connection to a write-ahead log. */
-int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *zName, int, Wal**);
+int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *, int, i64, Wal**);
 int sqlite3WalClose(Wal *pWal, int sync_flags, int, u8 *);
 
+/* Set the limiting size of a WAL file. */
+void sqlite3WalLimit(Wal*, i64);
+
 /* Used by readers to open (lock) and close (unlock) a snapshot.  A 
 ** snapshot is like a read-transaction.  It is the state of the database
 ** at an instant in time.  sqlite3WalOpenSnapshot gets a read lock and
diff --git a/test/wal7.test b/test/wal7.test
new file mode 100644 (file)
index 0000000..cfe2d7b
--- /dev/null
@@ -0,0 +1,118 @@
+# 2011 May 16
+#
+# The author disclaims copyright to this source code.  In place of
+# a legal notice, here is a blessing:
+#
+#    May you do good and not evil.
+#    May you find forgiveness for yourself and forgive others.
+#    May you share freely, never taking more than you give.
+#
+#***********************************************************************
+# This file implements regression tests for SQLite library.  The
+# focus of this file is testing the PRAGMA journal_size_limit when
+# in WAL mode.
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+ifcapable !wal {finish_test ; return }
+
+# Case 1:  No size limit.  Journal can get large.
+#
+do_test wal7-1.0 {
+  db close
+  forcedelete test.db
+  sqlite3 db test.db
+  db eval {
+    PRAGMA page_size=1024;
+    PRAGMA journal_mode=WAL;
+    PRAGMA wal_autocheckpoint=50;  -- 50 pages
+    CREATE TABLE t1(x, y UNIQUE);
+    INSERT INTO t1 VALUES(1,2);
+    INSERT INTO t1 VALUES(zeroblob(200000),4);
+    CREATE TABLE t2(z);
+    DELETE FROM t1;
+    INSERT INTO t2 SELECT x FROM t1;
+  }
+  expr {[file size test.db-wal]>50*1100}
+} 1
+do_test wal7-1.1 {
+  db eval {PRAGMA wal_checkpoint}
+  expr {[file size test.db-wal]>50*1100}
+} 1
+do_test wal7-1.2 {
+  db eval {INSERT INTO t2 VALUES('hi');}
+  expr {[file size test.db-wal]>50*1100}
+} 1
+
+# Case 2:  Size limit at half the autocheckpoint size.
+#
+do_test wal7-2.0 {
+  db close
+  forcedelete test.db
+  sqlite3 db test.db
+  db eval {
+    PRAGMA page_size=1024;
+    PRAGMA journal_mode=WAL;
+    PRAGMA wal_autocheckpoint=50;  -- 50 pages
+    PRAGMA journal_size_limit=25000;
+    CREATE TABLE t1(x, y UNIQUE);
+    INSERT INTO t1 VALUES(1,2);
+    INSERT INTO t1 VALUES(zeroblob(200000),4);
+    CREATE TABLE t2(z);
+    DELETE FROM t1;
+    INSERT INTO t2 SELECT x FROM t1;
+  }
+  file size test.db-wal
+} 25000
+
+
+# Case 3:  Size limit of zero.
+#
+do_test wal7-3.0 {
+  db close
+  forcedelete test.db
+  sqlite3 db test.db
+  db eval {
+    PRAGMA page_size=1024;
+    PRAGMA journal_mode=WAL;
+    PRAGMA wal_autocheckpoint=50;  -- 50 pages
+    PRAGMA journal_size_limit=0;
+    CREATE TABLE t1(x, y UNIQUE);
+    INSERT INTO t1 VALUES(1,2);
+    INSERT INTO t1 VALUES(zeroblob(200000),4);
+    CREATE TABLE t2(z);
+    DELETE FROM t1;
+    INSERT INTO t2 SELECT x FROM t1;
+  }
+  set sz [file size test.db-wal]
+  expr {$sz>0 && $sz<10000}
+} 1
+
+
+# Case 4:  Size limit set before going WAL
+#
+do_test wal7-4.0 {
+  db close
+  forcedelete test.db
+  sqlite3 db test.db
+  db eval {
+    PRAGMA page_size=1024;
+    PRAGMA journal_size_limit=25000;
+    PRAGMA journal_mode=WAL;
+    PRAGMA wal_autocheckpoint=50;  -- 50 pages
+    CREATE TABLE t1(x, y UNIQUE);
+    INSERT INTO t1 VALUES(1,2);
+    INSERT INTO t1 VALUES(zeroblob(200000),4);
+    CREATE TABLE t2(z);
+    DELETE FROM t1;
+    INSERT INTO t2 SELECT x FROM t1;
+  }
+  set sz [file size test.db-wal]
+} 25000
+
+
+
+
+
+finish_test