From: danielk1977 Date: Wed, 4 Jun 2008 06:45:59 +0000 (+0000) Subject: Add "pragma journal_size_limit", used to limit the space consumed by persistent journ... X-Git-Tag: version-3.6.10~992 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b53e49609565932c7f699c122b14dd523eb17c32;p=thirdparty%2Fsqlite.git Add "pragma journal_size_limit", used to limit the space consumed by persistent journal files left in the file-system after a transaction has concluded in exclusive (or journal_mode=persist) mode. (CVS 5185) FossilOrigin-Name: 5c59f469d0321c6a2e702ca2c61db012f63aeecc --- diff --git a/manifest b/manifest index 45c892d057..b218fe1100 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Ensure\sthat\svacuum3.test\scloses\sall\sopened\sdatabase\sconnections.\sFix\sfor\s#3157.\s(CVS\s5184) -D 2008-06-03T07:34:09 +C Add\s"pragma\sjournal_size_limit",\sused\sto\slimit\sthe\sspace\sconsumed\sby\spersistent\sjournal\sfiles\sleft\sin\sthe\sfile-system\safter\sa\stransaction\shas\sconcluded\sin\sexclusive\s(or\sjournal_mode=persist)\smode.\s(CVS\s5185) +D 2008-06-04T06:45:59 F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7 F Makefile.in ce92ea8dc7adfb743757794f51c10d1b0d9c55e4 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -133,10 +133,10 @@ F src/os_common.h 24525d8b7bce66c374dfc1810a6c9043f3359b60 F src/os_os2.c 1578149e21c4eac42c7f230a6f40500846f8e781 F src/os_unix.c a6b02934fdd4682db47c006cb03baac8694d8b77 F src/os_win.c 812f9ba8cd90c8aa54914a56897fb534494576d8 -F src/pager.c d0a77feeaeecaaaec9342a3bb3865ed9a490897a -F src/pager.h 1ccde54041195311c2b09b6936404d2192db44da +F src/pager.c d55885a30760028d3fe367df2fe7e2c884d65ff4 +F src/pager.h 71c58cd613174a91b50ed66edad6148639aa064a F src/parse.y fc4bd35c6088901f7c8daead26c6fb11c87d22e7 -F src/pragma.c a4919a29a0923e00c6170b0677a50058e352b58c +F src/pragma.c c6dfbd16fff857aceb2fece8b34891a32d64b19a F src/prepare.c cbc9301aba1d0fc3d05fae576f2eb667c189cb36 F src/printf.c f2d4f6c5b0ec24b643e85fe60258adad8b1f6acc F src/random.c 2b2db2de4ab491f5a14d3480466f8f4b5a5db74a @@ -364,7 +364,7 @@ F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0 F test/join4.test 1a352e4e267114444c29266ce79e941af5885916 F test/join5.test 86675fc2919269aa923c84dd00ee4249b97990fe F test/journal1.test 36f2d1bb9bf03f790f43fbdb439e44c0657fab19 -F test/jrnlmode.test 8e8e359e46799cea23d029f28bda6311f0f4c07b +F test/jrnlmode.test b60a7dae8534ccd2e811deb09258f1172fd6e24f F test/jrnlmode2.test e48ec49320a3f849a5036e3551bf2394112a4aae F test/jrnlmode3.test c77f9d4095945f234dddd60ca0f73c24802ed0c1 F test/jrnlmode4.test 8ee031603fef8ed5deba0de8b012a82be6d5a6a0 @@ -591,7 +591,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81 F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 1dbced29de5f59ba2ebf877edcadf171540374d1 F tool/speedtest8inst1.c c65494ca99d1e09c246dfe37a7ca7a354af9990f -P 03b5e4581a075179c85e8c16b16fd24c151294d3 -R b2702bf888acb9a4ed6edc79a93f42e2 +P 654e3b3de8ddeba3e31e9677ec4086e9f73c3598 +R 6663a334dd4809e3aa8da9c4ad8955dc U danielk1977 -Z 0dbf472f8f6e6a4fc7afad9089837ffd +Z 785d2e00fd28d9fc7c0eeb4393db61ec diff --git a/manifest.uuid b/manifest.uuid index 5783ff19c5..d6a8b7ac4a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -654e3b3de8ddeba3e31e9677ec4086e9f73c3598 \ No newline at end of file +5c59f469d0321c6a2e702ca2c61db012f63aeecc \ No newline at end of file diff --git a/src/pager.c b/src/pager.c index da129dbc7d..44298cea16 100644 --- a/src/pager.c +++ b/src/pager.c @@ -18,7 +18,7 @@ ** file simultaneously, or one process from reading the database while ** another is writing. ** -** @(#) $Id: pager.c,v 1.450 2008/05/21 15:38:15 drh Exp $ +** @(#) $Id: pager.c,v 1.451 2008/06/04 06:45:59 danielk1977 Exp $ */ #ifndef SQLITE_OMIT_DISKIO #include "sqliteInt.h" @@ -406,6 +406,7 @@ struct Pager { #endif char *pTmpSpace; /* Pager.pageSize bytes of space for tmp use */ char dbFileVers[16]; /* Changes whenever database file changes */ + i64 journalSizeLimit; /* Size limit for persistent journal files */ }; /* @@ -974,8 +975,10 @@ static int zeroJournalHdr(Pager *pPager, int doTruncate){ static const char zeroHdr[28]; if( pPager->journalOff ){ + i64 iLimit = pPager->journalSizeLimit; + IOTRACE(("JZEROHDR %p\n", pPager)) - if( doTruncate ){ + if( doTruncate || iLimit==0 ){ rc = sqlite3OsTruncate(pPager->jfd, 0); }else{ rc = sqlite3OsWrite(pPager->jfd, zeroHdr, sizeof(zeroHdr), 0); @@ -983,6 +986,20 @@ static int zeroJournalHdr(Pager *pPager, int doTruncate){ if( rc==SQLITE_OK ){ rc = sqlite3OsSync(pPager->jfd, SQLITE_SYNC_DATAONLY|pPager->sync_flags); } + + /* At this point the transaction is committed but the write lock + ** is still held on the file. If there is a size limit configured for + ** the persistent journal and the journal file currently consumes more + ** space than that limit allows for, truncate it now. There is no need + ** to sync the file following this operation. + */ + if( rc==SQLITE_OK && iLimit>0 ){ + i64 sz; + rc = sqlite3OsFileSize(pPager->jfd, &sz); + if( rc==SQLITE_OK && sz>iLimit ){ + rc = sqlite3OsTruncate(pPager->jfd, iLimit); + } + } } return rc; } @@ -2351,6 +2368,7 @@ int sqlite3PagerOpen( /* pPager->pFirstSynced = 0; */ /* pPager->pLast = 0; */ pPager->nExtra = FORCE_ALIGNMENT(nExtra); + pPager->journalSizeLimit = SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT; assert(pPager->fd->pMethods||memDb||tempFile); if( !memDb ){ setSectorSize(pPager); @@ -5306,6 +5324,16 @@ int sqlite3PagerJournalMode(Pager *pPager, int eMode){ return (int)pPager->journalMode; } +/* +** Get/set the size-limit used for persistent journal files. +*/ +i64 sqlite3PagerJournalSizeLimit(Pager *pPager, i64 iLimit){ + if( iLimit>=-1 ){ + pPager->journalSizeLimit = iLimit; + } + return pPager->journalSizeLimit; +} + #ifdef SQLITE_TEST /* ** Print a listing of all referenced pages and their ref count. diff --git a/src/pager.h b/src/pager.h index 58e0e18ef4..2fefea8d57 100644 --- a/src/pager.h +++ b/src/pager.h @@ -13,12 +13,20 @@ ** 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.73 2008/05/27 18:11:45 shane Exp $ +** @(#) $Id: pager.h,v 1.74 2008/06/04 06:45:59 danielk1977 Exp $ */ #ifndef _PAGER_H_ #define _PAGER_H_ +/* +** If defined as non-zero, auto-vacuum is enabled by default. Otherwise +** it must be turned on for each database using "PRAGMA auto_vacuum = 1". +*/ +#ifndef SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT + #define SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT -1 +#endif + /* ** The type used to represent a page number. The first page in a file ** is called page 1. 0 is used to represent "not a page". @@ -102,6 +110,7 @@ void *sqlite3PagerGetData(DbPage *); void *sqlite3PagerGetExtra(DbPage *); int sqlite3PagerLockingMode(Pager *, int); int sqlite3PagerJournalMode(Pager *, int); +i64 sqlite3PagerJournalSizeLimit(Pager *, i64); void *sqlite3PagerTempSpace(Pager*); int sqlite3PagerSync(Pager *pPager); diff --git a/src/pragma.c b/src/pragma.c index 9a28563e3f..863254b11d 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -11,7 +11,7 @@ ************************************************************************* ** This file contains code used to implement the PRAGMA command. ** -** $Id: pragma.c,v 1.177 2008/05/15 17:48:20 danielk1977 Exp $ +** $Id: pragma.c,v 1.178 2008/06/04 06:45:59 danielk1977 Exp $ */ #include "sqliteInt.h" #include @@ -461,7 +461,7 @@ void sqlite3Pragma( } } if( pId2->n==0 && eMode==PAGER_JOURNALMODE_QUERY ){ - /* Simple "PRAGMA persistent_journal;" statement. This is a query for + /* Simple "PRAGMA journal_mode;" statement. This is a query for ** the current default journal mode (which may be different to ** the journal-mode of the main database). */ @@ -499,6 +499,27 @@ void sqlite3Pragma( azModeName[eMode], P4_STATIC); sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); }else + + /* + ** PRAGMA [database.]journal_size_limit + ** PRAGMA [database.]journal_size_limit=N + ** + ** Get or set the (boolean) value of the database 'auto-vacuum' parameter. + */ + if( sqlite3StrICmp(zLeft,"journal_size_limit")==0 ){ + Pager *pPager = sqlite3BtreePager(pDb->pBt); + i64 iLimit = -2; + if( zRight ){ + int iLimit32 = atoi(zRight); + if( iLimit32<-1 ){ + iLimit32 = -1; + } + iLimit = iLimit32; + } + iLimit = sqlite3PagerJournalSizeLimit(pPager, iLimit); + returnSingleInt(pParse, "journal_size_limit", (int)iLimit); + }else + #endif /* SQLITE_OMIT_PAGER_PRAGMAS */ /* diff --git a/test/jrnlmode.test b/test/jrnlmode.test index 4cc7e1f6cc..cb6c3eb52a 100644 --- a/test/jrnlmode.test +++ b/test/jrnlmode.test @@ -11,7 +11,7 @@ # This file implements regression tests for SQLite library. The focus # of these tests is the journal mode pragma. # -# $Id: jrnlmode.test,v 1.3 2008/05/20 07:05:09 danielk1977 Exp $ +# $Id: jrnlmode.test,v 1.4 2008/06/04 06:46:00 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -251,4 +251,135 @@ ifcapable autovacuum&&pragma { integrity_check jrnlmode-4.5 } +#------------------------------------------------------------------------ +# The following test caes, jrnlmode-5.*, test the journal_size_limit +# pragma. +ifcapable pragma { + db close + file delete -force test.db test2.db test3.db + sqlite3 db test.db + + do_test jrnlmode-5.1 { + execsql {pragma page_size=1024} + execsql {pragma journal_mode=persist} + } {persist} + + do_test jrnlmode-5.2 { + execsql { PRAGMA journal_size_limit } + } {-1} + do_test jrnlmode-5.3 { + execsql { + ATTACH 'test2.db' AS aux; + PRAGMA aux.journal_size_limit; + } + } {-1} + do_test jrnlmode-5.4 { + execsql { PRAGMA aux.journal_size_limit = 10240 } + } {10240} + do_test jrnlmode-5.5 { + execsql { PRAGMA main.journal_size_limit = 20480 } + } {20480} + do_test jrnlmode-5.6 { + execsql { PRAGMA journal_size_limit } + } {20480} + do_test jrnlmode-5.7 { + execsql { PRAGMA aux.journal_size_limit } + } {10240} + + do_test jrnlmode-5.8 { + execsql { ATTACH 'test3.db' AS aux2 } + } {} + + do_test jrnlmode-5.9 { + execsql { + CREATE TABLE main.t1(a, b, c); + CREATE TABLE aux.t2(a, b, c); + CREATE TABLE aux2.t3(a, b, c); + } + } {} + do_test jrnlmode-5.10 { + list \ + [file exists test.db-journal] \ + [file exists test2.db-journal] \ + [file exists test3.db-journal] + } {1 1 1} + do_test jrnlmode-5.11 { + execsql { + BEGIN; + INSERT INTO t3 VALUES(randomblob(1000),randomblob(1000),randomblob(1000)); + INSERT INTO t3 + SELECT randomblob(1000),randomblob(1000),randomblob(1000) FROM t3; + INSERT INTO t3 + SELECT randomblob(1000),randomblob(1000),randomblob(1000) FROM t3; + INSERT INTO t3 + SELECT randomblob(1000),randomblob(1000),randomblob(1000) FROM t3; + INSERT INTO t3 + SELECT randomblob(1000),randomblob(1000),randomblob(1000) FROM t3; + INSERT INTO t3 + SELECT randomblob(1000),randomblob(1000),randomblob(1000) FROM t3; + INSERT INTO t2 SELECT * FROM t3; + INSERT INTO t1 SELECT * FROM t2; + COMMIT; + } + list \ + [file exists test.db-journal] \ + [file exists test2.db-journal] \ + [file exists test3.db-journal] \ + [file size test.db-journal] \ + [file size test2.db-journal] \ + [file size test3.db-journal] + } {1 1 1 0 0 0} + + do_test jrnlmode-5.12 { + execsql { + BEGIN; + UPDATE t1 SET a = randomblob(1000); + } + expr {[file size test.db-journal]>30000} + } {1} + do_test jrnlmode-5.13 { + execsql COMMIT + file size test.db-journal + } {20480} + + do_test jrnlmode-5.14 { + execsql { + BEGIN; + UPDATE t2 SET a = randomblob(1000); + } + expr {[file size test2.db-journal]>30000} + } {1} + do_test jrnlmode-5.15 { + execsql COMMIT + file size test2.db-journal + } {10240} + + do_test jrnlmode-5.16 { + execsql { + BEGIN; + UPDATE t3 SET a = randomblob(1000); + } + set journalsize [file size test3.db-journal] + expr {$journalsize>30000} + } {1} + do_test jrnlmode-5.17 { + execsql COMMIT + file size test3.db-journal + } $journalsize + + do_test jrnlmode-5.18 { + execsql { + PRAGMA journal_size_limit = -4; + BEGIN; + UPDATE t1 SET a = randomblob(1000); + } + set journalsize [file size test.db-journal] + expr {$journalsize>30000} + } {1} + do_test jrnlmode-5.19 { + execsql COMMIT + file size test.db-journal + } $journalsize +} + finish_test