From: danielk1977 Date: Mon, 26 Mar 2007 08:05:12 +0000 (+0000) Subject: Some fixes and test cases for exclusive access mode. (CVS 3714) X-Git-Tag: version-3.6.10~2456 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=334cdb63b03e8ec9408530cf3557e59227e9c538;p=thirdparty%2Fsqlite.git Some fixes and test cases for exclusive access mode. (CVS 3714) FossilOrigin-Name: 899e60707bea0fabab2ff3ac8a3fbb676a539120 --- diff --git a/manifest b/manifest index 9aee18d65a..cbbb72d28f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\ssqlite3_prepare_v2\sand\ssqlite3_prepare16_v2\sAPIs\sto\sthe\sloadable\nextension\sinterface.\s(CVS\s3713) -D 2007-03-25T19:08:47 +C Some\sfixes\sand\stest\scases\sfor\sexclusive\saccess\smode.\s(CVS\s3714) +D 2007-03-26T08:05:12 F Makefile.in 1fe3d0b46e40fd684e1e61f8e8056cefed16de9f F Makefile.linux-gcc 2d8574d1ba75f129aba2019f0b959db380a90935 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028 @@ -86,7 +86,7 @@ F src/os_unix.c 4642f23ed0c1ae0f1440db1d2b4231348af69360 F src/os_unix.h 5768d56d28240d3fe4537fac08cc85e4fb52279e F src/os_win.c 1d1d0989b0f235751504292c2f28e81044be0d70 F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b -F src/pager.c 9023042d50d961cfcaad4e9211eea711abb2b7f4 +F src/pager.c 5846d0c1b010145b656719c7579018f906f2663f F src/pager.h 3c16500c25051536e43fb19e246e58fc7cb51d9f F src/parse.y bcfe366c1fd61cfc40e5344eb69a31997a821af0 F src/pragma.c 9cb8b94e7d38ba35a86037bd517d07ba9870b4b2 @@ -199,7 +199,7 @@ F test/distinctagg.test 2b89d1c5220d966a30ba4b40430338669301188b F test/enc.test 7a03417a1051fe8bc6c7641cf4c8c3f7e0066d52 F test/enc2.test 45710bacfa9df29720bc84c067dfdf8c8ddfb797 F test/enc3.test 890508efff6677345e93bf2a8adb0489b30df030 -F test/exclusive.test 67a1bedd37b92785a0ba3b596401910713653b5e +F test/exclusive.test c2d8b75882a3f35057209e6d5e99737a1ef33d80 F test/expr.test c78843f730ccbe973d0c2ad1c99978f936893131 F test/fkey1.test 153004438d51e6769fb1ce165f6313972d6263ce F test/format4.test bf3bed3b13c63abfb3cfec232597a319a31d0bcc @@ -331,7 +331,7 @@ F test/tkt2192.test 480d0e017ddb01a46ee20809427370f343bb3c03 F test/tkt2213.test 8cf7c446e1fcd0627fffe7fc19046eb24ac7333b F test/tkt2251.test 3f0549213386ed911715665a908ff2bb7a871002 F test/trace.test 75ffc1b992c780d054748a656e3e7fd674f18567 -F test/trans.test f4577bbefe1fb49e6c13f32923a8891250a9d628 +F test/trans.test 3fe1b9e03b523482eee2b869858c5c1eca7b218b F test/trigger1.test 2c79e2bf76350811e362814e98779c120b6a9421 F test/trigger2.test 33bf8ae9b788013be194efe5f66c04a202facbb4 F test/trigger3.test 9102fd3933db294dc654b5aee9edfe9e94f2b9e2 @@ -438,7 +438,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513 -P b6c700370be29db2b974f9abd719c3e56abf8058 -R a1856a5f6fc55ec41d9bcb43f52aec37 -U drh -Z 58bc4e277f7ec6a7398c984dd6cadc27 +P f02ba56d5c6bbd57682a6bb57e9f92021dfb066e +R facce77a37515ab346614e3f902fe80a +U danielk1977 +Z 8062a8ad8fbd5e30464ba813e66b27fe diff --git a/manifest.uuid b/manifest.uuid index d6b7260028..8c521f2a7c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f02ba56d5c6bbd57682a6bb57e9f92021dfb066e \ No newline at end of file +899e60707bea0fabab2ff3ac8a3fbb676a539120 \ No newline at end of file diff --git a/src/pager.c b/src/pager.c index 6569ec4606..41528a8b46 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.294 2007/03/24 16:45:05 danielk1977 Exp $ +** @(#) $Id: pager.c,v 1.295 2007/03/26 08:05:12 danielk1977 Exp $ */ #ifndef SQLITE_OMIT_DISKIO #include "sqliteInt.h" @@ -872,12 +872,14 @@ static void pager_unlock(Pager *pPager){ ** database file. This is a no-op if the pager has already entered ** the error-state. */ -static void pagerUnlockAndRollback(Pager *pPager){ - if( pPager->errCode ) return; - if( pPager->state>=PAGER_RESERVED ){ - sqlite3PagerRollback(pPager); - } - pager_unlock(pPager); +static void pagerUnlockAndRollback(Pager *p){ + if( p->errCode ) return; + if( p->state>=PAGER_RESERVED ){ + sqlite3PagerRollback(p); + } + pager_unlock(p); + assert( p->errCode || !p->journalOpen || (p->exclusiveMode&&!p->journalOff) ); + assert( p->errCode || !p->stmtOpen || p->exclusiveMode ); } @@ -924,15 +926,20 @@ static int pager_unwritelock(Pager *pPager){ return SQLITE_OK; } sqlite3PagerStmtCommit(pPager); - if( pPager->stmtOpen ){ - sqlite3OsClose(&pPager->stfd); - pPager->stmtOpen = 0; + if( pPager->stmtOpen && !pPager->exclusiveMode ){ + if( pPager->exclusiveMode ){ + sqlite3OsClose(&pPager->stfd); + pPager->stmtOpen = 0; + }else{ + sqlite3OsTruncate(pPager->stfd, 0); + } } if( pPager->journalOpen ){ if( pPager->exclusiveMode ){ sqlite3OsTruncate(pPager->jfd, 0); sqlite3OsSeek(pPager->jfd, 0); pPager->journalOff = 0; + pPager->journalStarted = 0; }else{ sqlite3OsClose(&pPager->jfd); pPager->journalOpen = 0; @@ -959,15 +966,10 @@ static int pager_unwritelock(Pager *pPager){ if( !pPager->exclusiveMode ){ rc = sqlite3OsUnlock(pPager->fd, SHARED_LOCK); pPager->state = PAGER_SHARED; - pPager->origDbSize = 0; - }else{ - sqlite3PagerPagecount(pPager); - pPager->origDbSize = pPager->dbSize; - pPager->aInJournal = sqliteMalloc( pPager->dbSize/8 + 1 ); - if( !pPager->aInJournal ){ - rc = SQLITE_NOMEM; - } + }else if( pPager->state==PAGER_SYNCED ){ + pPager->state = PAGER_EXCLUSIVE; } + pPager->origDbSize = 0; pPager->setMaster = 0; pPager->needSync = 0; pPager->pFirstSynced = pPager->pFirst; @@ -1323,7 +1325,7 @@ static int pager_playback(Pager *pPager, int isHot){ */ assert( pPager->journalOpen ); rc = sqlite3OsFileSize(pPager->jfd, &szJ); - if( rc!=SQLITE_OK ){ + if( rc!=SQLITE_OK || szJ==0 ){ goto end_playback; } @@ -2801,7 +2803,8 @@ int sqlite3PagerAcquire(Pager *pPager, Pgno pgno, DbPage **ppPage, int clrFlag){ } /* If this is the first page accessed, then get a SHARED lock - ** on the database file. + ** on the database file. pagerSharedLock() is a no-op if + ** a database lock is already held. */ rc = pagerSharedLock(pPager); if( rc!=SQLITE_OK ){ @@ -2948,9 +2951,10 @@ DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){ assert( pgno!=0 ); if( pPager->state==PAGER_UNLOCK ){ + assert( !pPager->pAll || pPager->exclusiveMode ); return 0; } - if( (pPager->errCode && pPager->errCode!=SQLITE_FULL) ){ + if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){ return 0; } pPg = pager_lookup(pPager, pgno); @@ -3004,7 +3008,6 @@ int sqlite3PagerUnref(DbPage *pPg){ pPager->nRef--; assert( pPager->nRef>=0 ); if( pPager->nRef==0 ){ - /* pager_reset(pPager); */ pagerUnlockAndRollback(pPager); } } @@ -3136,7 +3139,24 @@ int sqlite3PagerBegin(DbPage *pPg, int exFlag){ rc = pager_open_journal(pPager); } } + }else if( pPager->journalOpen && pPager->journalOff==0 ){ + /* This happens when the pager was in exclusive-access mode last + ** time a (read or write) transaction was successfully concluded + ** by this connection. Instead of deleting the journal file it was + ** kept open and truncated to 0 bytes. + */ + assert( pPager->nRec==0 ); + assert( pPager->origDbSize==0 ); + sqlite3PagerPagecount(pPager); + pPager->origDbSize = pPager->dbSize; + pPager->aInJournal = sqliteMalloc( pPager->dbSize/8 + 1 ); + if( !pPager->aInJournal ){ + rc = SQLITE_NOMEM; + }else{ + rc = writeJournalHdr(pPager); + } } + assert( !pPager->journalOpen || pPager->journalOff>0 || rc!=SQLITE_OK ); return rc; } @@ -3614,8 +3634,6 @@ int sqlite3PagerRollback(Pager *pPager){ PgHistory *pHist; assert( !p->alwaysRollback ); if( !p->dirty ){ - assert( p->inJournal==0 ); - assert( p->inStmt==0 ); assert( !((PgHistory *)PGHDR_TO_HIST(p, pPager))->pOrig ); assert( !((PgHistory *)PGHDR_TO_HIST(p, pPager))->pStmt ); continue; @@ -3659,7 +3677,6 @@ int sqlite3PagerRollback(Pager *pPager){ } if( pPager->state==PAGER_RESERVED ){ int rc2; - /* rc = pager_reload_cache(pPager); */ rc = pager_playback(pPager, 0); rc2 = pager_unwritelock(pPager); if( rc==SQLITE_OK ){ diff --git a/test/exclusive.test b/test/exclusive.test index 860fcfdd0a..56019805bf 100644 --- a/test/exclusive.test +++ b/test/exclusive.test @@ -10,7 +10,7 @@ #*********************************************************************** # This file implements regression tests for SQLite library. # -# $Id: exclusive.test,v 1.1 2007/03/24 16:45:05 danielk1977 Exp $ +# $Id: exclusive.test,v 1.2 2007/03/26 08:05:12 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -274,7 +274,7 @@ do_test exclusive-3.4 { ROLLBACK; SELECT * FROM abc; } -} {1 2 3} +} {A B C} do_test exclusive-3.5 { filestate test.db-journal } {1 0} @@ -286,6 +286,11 @@ do_test exclusive-3.6 { filestate test.db-journal } {0 0} +#---------------------------------------------------------------------- +# Tests exclusive-4.X - test that rollback works correctly when +# in exclusive-access mode. +# + # The following procedure computes a "signature" for table "t3". If # T3 changes in any way, the signature should change. # @@ -297,13 +302,9 @@ proc signature {} { return [db eval {SELECT count(*), md5sum(x) FROM t3}] } -if 0 { - do_test exclusive-4.0 { - execsql { PRAGMA default_cache_size=10; } - db close - sqlite3 db test.db execsql { PRAGMA locking_mode = exclusive; } + execsql { PRAGMA default_cache_size = 10; } execsql { BEGIN; CREATE TABLE t3(x TEXT); @@ -313,28 +314,110 @@ do_test exclusive-4.0 { INSERT INTO t3 SELECT randstr(10,400) FROM t3; INSERT INTO t3 SELECT randstr(10,400) FROM t3; INSERT INTO t3 SELECT randstr(10,400) FROM t3; - INSERT INTO t3 SELECT randstr(10,400) FROM t3; - INSERT INTO t3 SELECT randstr(10,400) FROM t3; - INSERT INTO t3 SELECT randstr(10,400) FROM t3; - INSERT INTO t3 SELECT randstr(10,400) FROM t3; - INSERT INTO t3 SELECT randstr(10,400) FROM t3; COMMIT; - SELECT count(*) FROM t3; } -} {1024} -set sig [signature] + execsql {SELECT count(*) FROM t3;} +} {32} + +set ::X [signature] do_test exclusive-4.1 { execsql { BEGIN; DELETE FROM t3 WHERE random()%10!=0; INSERT INTO t3 SELECT randstr(10,10)||x FROM t3; INSERT INTO t3 SELECT randstr(10,10)||x FROM t3; + SELECT count(*) FROM t3; ROLLBACK; } signature -} $sig +} $::X -} +do_test exclusive-4.2 { + execsql { + BEGIN; + DELETE FROM t3 WHERE random()%10!=0; + INSERT INTO t3 SELECT randstr(10,10)||x FROM t3; + DELETE FROM t3 WHERE random()%10!=0; + INSERT INTO t3 SELECT randstr(10,10)||x FROM t3; + ROLLBACK; + } + signature +} $::X + +do_test exclusive-4.3 { + execsql { + INSERT INTO t3 SELECT randstr(10,400) FROM t3 WHERE random()%10==0; + } +} {} + +do_test exclusive-4.4 { + catch {set ::X [signature]} +} {0} +do_test exclusive-4.5 { + execsql { + PRAGMA locking_mode = NORMAL; + DROP TABLE t3; + DROP TABLE abc; + } +} {normal} + +#---------------------------------------------------------------------- +# Tests exclusive-5.X - test that statement journals are truncated +# instead of deleted when in exclusive access mode. +# +#set sqlite_os_trace 1 +do_test exclusive-5.0 { + execsql { + CREATE TABLE abc(a UNIQUE, b UNIQUE, c UNIQUE); + BEGIN; + INSERT INTO abc VALUES(1, 2, 3); + INSERT INTO abc SELECT a+1, b+1, c+1 FROM abc; + } +} {} +do_test exclusive-5.1 { + # Three files are open: The db, journal and statement-journal. + set sqlite_open_file_count +} {3} +do_test exclusive-5.2 { + execsql { + COMMIT; + } + # One file open: the db. + set sqlite_open_file_count +} {1} +do_test exclusive-5.3 { + execsql { + PRAGMA locking_mode = exclusive; + BEGIN; + INSERT INTO abc VALUES(5, 6, 7); + } + # Two files open: the db and journal. + set sqlite_open_file_count +} {2} +do_test exclusive-5.4 { + execsql { + INSERT INTO abc SELECT a+10, b+10, c+10 FROM abc; + } + # Three files are open: The db, journal and statement-journal. + set sqlite_open_file_count +} {3} +do_test exclusive-5.5 { + execsql { + COMMIT; + } + # Three files are still open: The db, journal and statement-journal. + set sqlite_open_file_count +} {3} +do_test exclusive-5.6 { + execsql { + PRAGMA locking_mode = normal; + SELECT * FROM abc; + } +} {normal 1 2 3 2 3 4 5 6 7 11 12 13 12 13 14 15 16 17} +do_test exclusive-5.7 { + # Just the db open. + set sqlite_open_file_count +} {1} finish_test diff --git a/test/trans.test b/test/trans.test index 14902cc7ef..afaae5f00b 100644 --- a/test/trans.test +++ b/test/trans.test @@ -11,7 +11,7 @@ # This file implements regression tests for SQLite library. The # focus of this script is database locks. # -# $Id: trans.test,v 1.33 2007/03/24 16:45:05 danielk1977 Exp $ +# $Id: trans.test,v 1.34 2007/03/26 08:05:12 danielk1977 Exp $ set testdir [file dirname $argv0] @@ -815,7 +815,6 @@ do_test trans-9.1 { } db close sqlite3 db test.db - # execsql { PRAGMA locking_mode = exclusive; } execsql { BEGIN; CREATE TABLE t3(x TEXT);