From abfb62f9bda5611503d3fed5b84fce5a466f7242 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 30 Jul 2010 11:20:35 +0000 Subject: [PATCH] Cherry-pick the multi-file transaction fix for ticket [f3e5abed55] out of the experimental branch. FossilOrigin-Name: 40f7f0a583e6bba66cd006253a0ef4623ea74f17 --- manifest | 29 ++++++---- manifest.uuid | 2 +- src/pager.c | 20 +++++++ src/pager.h | 1 + src/vdbeaux.c | 10 ++-- test/tkt-f3e5abed55.test | 113 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 161 insertions(+), 14 deletions(-) create mode 100644 test/tkt-f3e5abed55.test diff --git a/manifest b/manifest index 0279e04f11..fbacb619e7 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,8 @@ -C Add\stests\sto\scheck\sthat\sthe\sICU\sregexp()\sfunction\scan\sonly\sbe\scalled\swith\sexactly\stwo\sarguments. -D 2010-07-30T05:06:05 +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA1 + +C Cherry-pick\sthe\smulti-file\stransaction\sfix\sfor\sticket\s[f3e5abed55]\sout\sof\nthe\sexperimental\sbranch. +D 2010-07-30T11:20:36 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in ec08dc838fd8110fe24c92e5130bcd91cbb1ff2e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -156,8 +159,8 @@ F src/os_common.h a8f95b81eca8a1ab8593d23e94f8a35f35d4078f F src/os_os2.c 72d0b2e562952a2464308c4ce5f7913ac10bef3e F src/os_unix.c 3109e0e5a0d5551bab2e8c7322b20a3b8b171248 F src/os_win.c 1f8b0a1a5bcf6289e7754d0d3c16cec16d4c93ab -F src/pager.c 33117640d8e0058dbf705b95e20ebf246cbb4bc1 -F src/pager.h 879fdde5a102d2f21a3135d6f647530b21c2796c +F src/pager.c d559cc0bb784fe5f5b812b2bc2329f09231515a5 +F src/pager.h 80726162dc3942f59ab27b738fb667b9ba0a89d5 F src/parse.y 12b7ebd61ea54f0e1b1083ff69cc2c8ce9353d58 F src/pcache.c 1e9aa2dbc0845b52e1b51cc39753b6d1e041cb07 F src/pcache.h c683390d50f856d4cd8e24342ae62027d1bb6050 @@ -222,7 +225,7 @@ F src/vdbe.c cefff41564b68a412e65e6a1013ec1b1c1ece6c4 F src/vdbe.h 4de0efb4b0fdaaa900cf419b35c458933ef1c6d2 F src/vdbeInt.h ffd68c4d4229227a5089bec53a1c635146177abc F src/vdbeapi.c d0f4407e465f261780ad725c1caece7d66a6aa35 -F src/vdbeaux.c 77442ab4233858cf603910429033fbbd997ecdef +F src/vdbeaux.c 8a443e73760ca65ffdfda3e26df4c8c90eeefa11 F src/vdbeblob.c 258a6010ba7a82b72b327fb24c55790655689256 F src/vdbemem.c 5e579abf6532001dfbee0e640dc34eae897a9807 F src/vdbetrace.c 864cef96919323482ebd9986f2132435115e9cc2 @@ -645,6 +648,7 @@ F test/tkt-9d68c883.test 458f7d82a523d7644b54b497c986378a7d8c8b67 F test/tkt-cbd054fa6b.test f14f97ea43662e6f70c9e63287081e8be5d9d589 F test/tkt-d11f09d36e.test fb44f7961aa6d4b632fb7b9768239832210b5fc7 F test/tkt-d82e3f3721.test 731359dfdcdb36fea0559cd33fec39dd0ceae8e6 +F test/tkt-f3e5abed55.test 91713833e266fbdc60f2030e05647ad4762073f6 F test/tkt-f777251dc7a.test 6f24c053bc5cdb7e1e19be9a72c8887cf41d5e87 F test/tkt-f973c7ac31.test 1da0ed15ec2c7749fb5ce2828cd69d07153ad9f4 F test/tkt-fc62af4523.test 72825d3febdedcd5593a27989fc05accdbfc2bb4 @@ -839,7 +843,14 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P d37443d33388b402e610a00c362a1e2e79548801 -R 1df44901de4b741a545cdb85506640b4 -U dan -Z 47b66d0e2bb0d61fe912692f971ceef4 +P 451d965742cc219db709939b4ba1da2f2343dbce +R b0221ec16dca16ffff1bd5b40fa2847e +U drh +Z 3292246f79754c1a33410d74f4888b7e +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.4.6 (GNU/Linux) + +iD8DBQFMUrWIoxKgR168RlERAgl9AJ9pHsRDtGgzTlt5S8NSiNWiQ7ew2QCdH2kx +84Gf1zkCE4fUgXSzHJvHTGU= +=LLzG +-----END PGP SIGNATURE----- diff --git a/manifest.uuid b/manifest.uuid index 98e6351865..1ceb992a23 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -451d965742cc219db709939b4ba1da2f2343dbce \ No newline at end of file +40f7f0a583e6bba66cd006253a0ef4623ea74f17 \ No newline at end of file diff --git a/src/pager.c b/src/pager.c index d5bbae145c..003ff6a2d6 100644 --- a/src/pager.c +++ b/src/pager.c @@ -5061,6 +5061,26 @@ int sqlite3PagerSync(Pager *pPager){ return rc; } +/* +** This function may only be called while a write-transaction is active in +** rollback. If the connection is in WAL mode, this call is a no-op. +** Otherwise, if the connection does not already have an EXCLUSIVE lock on +** the database file, an attempt is made to obtain one. +** +** If the EXCLUSIVE lock is already held or the attempt to obtain it is +** successful, or the connection is in WAL mode, SQLITE_OK is returned. +** Otherwise, either SQLITE_BUSY or an SQLITE_IOERR_XXX error code is +** returned. +*/ +int sqlite3PagerExclusiveLock(Pager *pPager){ + int rc = SQLITE_OK; + assert( pPager->state>=PAGER_RESERVED ); + if( 0==pagerUseWal(pPager) ){ + rc = pager_wait_on_lock(pPager, PAGER_EXCLUSIVE); + } + return rc; +} + /* ** Sync the database file for the pager pPager. zMaster points to the name ** of a master journal file that should be written into the individual diff --git a/src/pager.h b/src/pager.h index 6036827e43..3b724c4ba8 100644 --- a/src/pager.h +++ b/src/pager.h @@ -129,6 +129,7 @@ void *sqlite3PagerGetExtra(DbPage *); int sqlite3PagerPagecount(Pager*, int*); int sqlite3PagerBegin(Pager*, int exFlag, int); int sqlite3PagerCommitPhaseOne(Pager*,const char *zMaster, int); +int sqlite3PagerExclusiveLock(Pager*); int sqlite3PagerSync(Pager *pPager); int sqlite3PagerCommitPhaseTwo(Pager*); int sqlite3PagerRollback(Pager*); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index c7cd3e4284..295a8c3a8d 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -1646,9 +1646,6 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){ ** to the transaction. */ rc = sqlite3VtabSync(db, &p->zErrMsg); - if( rc!=SQLITE_OK ){ - return rc; - } /* This loop determines (a) if the commit hook should be invoked and ** (b) how many database files have open write transactions, not @@ -1656,13 +1653,17 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){ ** one database file has an open write transaction, a master journal ** file is required for an atomic commit. */ - for(i=0; inDb; i++){ + for(i=0; rc==SQLITE_OK && inDb; i++){ Btree *pBt = db->aDb[i].pBt; if( sqlite3BtreeIsInTrans(pBt) ){ needXcommit = 1; if( i!=1 ) nTrans++; + rc = sqlite3PagerExclusiveLock(sqlite3BtreePager(pBt)); } } + if( rc!=SQLITE_OK ){ + return rc; + } /* If there are any write-transactions at all, invoke the commit hook */ if( needXcommit && db->xCommitCallback ){ @@ -1801,6 +1802,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){ } } sqlite3OsCloseFree(pMaster); + assert( rc!=SQLITE_BUSY ); if( rc!=SQLITE_OK ){ sqlite3DbFree(db, zMaster); return rc; diff --git a/test/tkt-f3e5abed55.test b/test/tkt-f3e5abed55.test new file mode 100644 index 0000000000..d574480b24 --- /dev/null +++ b/test/tkt-f3e5abed55.test @@ -0,0 +1,113 @@ +# 2010 July 29 +# +# 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. +# +#*********************************************************************** +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +source $testdir/malloc_common.tcl + +foreach f [glob -nocomplain test.db*mj*] { file delete -force $f } +file delete -force test.db2 + +do_test tkt-f3e5abed55-1.1 { + execsql { + ATTACH 'test.db2' AS aux; + CREATE TABLE main.t1(a, b); + CREATE TABLE aux.t2(c, d); + } +} {} + +do_test tkt-f3e5abed55-1.2 { + glob -nocomplain test.db*mj* +} {} + +do_test tkt-f3e5abed55-1.3 { + sqlite3 db2 test.db + execsql { BEGIN; SELECT * FROM t1 } db2 +} {} + +do_test tkt-f3e5abed55-1.4 { + execsql { + BEGIN; + INSERT INTO t1 VALUES(1, 2); + INSERT INTO t2 VALUES(1, 2); + } + catchsql COMMIT +} {1 {database is locked}} + +do_test tkt-f3e5abed55-1.5 { + execsql COMMIT db2 + execsql COMMIT +} {} + +do_test tkt-f3e5abed55-1.6 { + glob -nocomplain test.db*mj* +} {} +foreach f [glob -nocomplain test.db*mj*] { file delete -force $f } +db close +db2 close + + + +# Set up a testvfs so that the next time SQLite tries to delete the +# file "test.db-journal", a snapshot of the current file-system contents +# is taken. +# +testvfs tvfs -default 1 +tvfs script xDelete +tvfs filter xDelete +proc xDelete {method file args} { + if {[file tail $file] == "test.db-journal"} { + faultsim_save + tvfs filter {} + } + return "SQLITE_OK" +} + +sqlite3 db test.db +sqlite3 db2 test.db +do_test tkt-f3e5abed55-2.1 { + execsql { + ATTACH 'test.db2' AS aux; + BEGIN; + INSERT INTO t1 VALUES(3, 4); + INSERT INTO t2 VALUES(3, 4); + } +} {} +do_test tkt-f3e5abed55-2.2 { + execsql { BEGIN; SELECT * FROM t1 } db2 +} {1 2} +do_test tkt-f3e5abed55-2.3 { + catchsql COMMIT +} {1 {database is locked}} + +do_test tkt-f3e5abed55-2.4 { + execsql COMMIT db2 + execsql { + COMMIT; + SELECT * FROM t1; + SELECT * FROM t2; + } +} {1 2 3 4 1 2 3 4} +do_test tkt-f3e5abed55-2.5 { + db close + db2 close + faultsim_restore_and_reopen + execsql { + ATTACH 'test.db2' AS aux; + SELECT * FROM t1; + SELECT * FROM t2; + } +} {1 2 3 4 1 2 3 4} + + +finish_test + -- 2.47.2