From: dan Date: Sat, 13 Jan 2024 20:36:34 +0000 (+0000) Subject: Merge latest wal2 changes into this branch. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=83b448f75aa00c5070e57b58b60b642bf4dc5949;p=thirdparty%2Fsqlite.git Merge latest wal2 changes into this branch. FossilOrigin-Name: c39f6585226dfc460372d55189b37fba07468126d3961bff625cea8a95956783 --- 83b448f75aa00c5070e57b58b60b642bf4dc5949 diff --cc manifest index 5d5fd6f767,e75d7b0266..90a4989b0f --- a/manifest +++ b/manifest @@@ -1,5 -1,5 +1,5 @@@ - C Merge\sthe\slatest\strunk\senhancements\sinto\sthe\sbedrock\sbranch. - D 2024-01-04T16:28:49.340 -C Merge\slatest\strunk\schanges\sinto\sthis\sbranch. -D 2024-01-13T20:21:36.767 ++C Merge\slatest\swal2\schanges\sinto\sthis\sbranch. ++D 2024-01-13T20:36:34.773 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@@ -100,7 -99,7 +100,7 @@@ F ext/fts5/fts5_config.c 8072a207034b51 F ext/fts5/fts5_expr.c e91156ebdcc08d837f4f324168f69f3c0d7fdef0e521fd561efb48ef3297b696 F ext/fts5/fts5_hash.c adda4272be401566a6e0ba1acbe70ee5cb97fce944bc2e04dc707152a0ec91b1 F ext/fts5/fts5_index.c bb1965c3965f6fe5f64160bf1c0694a9684a790a783f293a76da1d38d319b258 - F ext/fts5/fts5_main.c a508be9e9b15d54cba47c5261278d611985434be98029cbc4c8efbd86bb3d09f -F ext/fts5/fts5_main.c 94a03dd431022d706290bb81b7f2180a0bb7c98f1397b5fbc90e18d3ed8d366c ++F ext/fts5/fts5_main.c 67ee70a2ab8e0405e18b39ab39f8059c2c7143e8e94fde2436af4ab871b44f72 F ext/fts5/fts5_storage.c f9e31b0d155e9b2c92d5d3a09ad7a56b937fbf1c7f962e10f4ca6281349f3934 F ext/fts5/fts5_tcl.c cf0fd0dbe64ec272491b749e0d594f563cda03336aeb60900129e6d18b0aefb8 F ext/fts5/fts5_test_mi.c 08c11ec968148d4cb4119d96d819f8c1f329812c568bac3684f5464be177d3ee @@@ -574,11 -570,9 +574,11 @@@ F ext/session/sessionrowid.test 85187c2 F ext/session/sessionsize.test 8fcf4685993c3dbaa46a24183940ab9f5aa9ed0d23e5fb63bfffbdb56134b795 F ext/session/sessionstat1.test b039e38e2ba83767b464baf39b297cc0b1cc6f3292255cb467ea7e12d0d0280c F ext/session/sessionwor.test 6fd9a2256442cebde5b2284936ae9e0d54bde692d0f5fd009ecef8511f4cf3fc -F ext/session/sqlite3session.c 829d468f0f3d2710aace56b0116a7ca3f414683ce78e3125ae5e21547a895078 -F ext/session/sqlite3session.h 4cf19a51975746d7cff2fdd74db8b769c570958e1c3639ac150d824ac1553b3e -F ext/session/test_session.c 7b94ad945cd4afe6c73ee935aeb3d44b4446186e1729362af616c7695a5283d9 +F ext/session/sqlite3changebatch.c d488b42d8fd49fb013a1e9c4535232680dabeb28ae8f9421b65ea0ccc3b430f7 +F ext/session/sqlite3changebatch.h e72016998c9a22d439ddfd547b69e1ebac810c24 - F ext/session/sqlite3session.c d3656920881b96d84a7a8f94ca207c4231f96812a7fee17d90aef5fa7303f9e2 ++F ext/session/sqlite3session.c a70713b0220a63b8930bf01ee01dcf8a66292cc3947c0988a18414cc687ae23b +F ext/session/sqlite3session.h 92ff8b769f667f762ba1af16912e448e37b7942b4ed38396954e09afe35637ee +F ext/session/test_session.c 81ebc0df0cab8e7db29da35ff57180c1127e984dc9aebcc7472b14b8d407c960 F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3 F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04 F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865f002fc80cb @@@ -682,12 -676,12 +682,12 @@@ F src/analyze.c 0f15753308c3bca7674f31f F src/attach.c cc9d00d30da916ff656038211410ccf04ed784b7564639b9b61d1839ed69fd39 F src/auth.c 19b7ccacae3dfba23fc6f1d0af68134fa216e9040e53b0681b4715445ea030b4 F src/backup.c 5c97e8023aab1ce14a42387eb3ae00ba5a0644569e3476f38661fa6f824c3523 -F src/bitvec.c 9eac5f42c11914d5ef00a75605bb205e934f435c579687f985f1f8b0995c8645 +F src/bitvec.c 501daeef838fa82a9fb53540d72f29e3d9172c8867f1e19f94f681e2e20b966e F src/btmutex.c 79a43670447eacc651519a429f6ece9fd638563cf95b469d6891185ddae2b522 -F src/btree.c 737d43c75d9f15310663a9b0e4dff2d3f0e8f9b7ce4d5fa6e196c513eca34106 -F src/btree.h 03e3356f5208bcab8eed4e094240fdac4a7f9f5ddf5e91045ce589f67d47c240 -F src/btreeInt.h 3e2589726c4f105e653461814f65857465da68be1fac688de340c43b873f4062 -F src/build.c e7d9044592eeeea8e78d8ae53ca8d31fd6e92ca0d4f53e2f2e8ccf7352e0b04b +F src/btree.c 5c0163ebbca4f0d8ed86ee38bff765fd5fe9c18f036babc6f3e4b3b41ad53252 +F src/btree.h d906e4d53f483c83d471d99479fa73fcdf20696305d578876f46ee283f3507cb +F src/btreeInt.h 4e04041380c1ac1f4b2e80d7fb072c6d74c1be605a4271625347ba06b651e37a - F src/build.c a5a67f51bd0958d2871cc441d186a026c810cf4980959203ecdec6a009975243 ++F src/build.c 9bbb6fcdde621fc52ebadc29ed9fa51837c6a9f0576abe2dfe0a93b2bb41694b F src/callback.c db3a45e376deff6a16c0058163fe0ae2b73a2945f3f408ca32cf74960b28d490 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c 047a0613c4c3ff65e05903d5b6931185b3df8f34b5178ad2f8d865ada4e9da44 @@@ -729,28 -723,28 +729,28 @@@ F src/os.h 1ff5ae51d339d0e30d8a9d814f4b F src/os_common.h 6c0eb8dd40ef3e12fe585a13e709710267a258e2c8dd1c40b1948a1d14582e06 F src/os_kv.c 4d39e1f1c180b11162c6dc4aa8ad34053873a639bac6baae23272fc03349986a F src/os_setup.h 6011ad7af5db4e05155f385eb3a9b4470688de6f65d6166b8956e58a3d872107 - F src/os_unix.c 34fd19cd2ff4309909cbe901a9f5242b8d8bc37c63822aab4c6c034f0561f162 -F src/os_unix.c 5dc41030cd5dfd99b907976b1725a4ed695566405d33744e4824c3d6aff245a3 ++F src/os_unix.c 5293c5c03e618201660b2e15c97fd8a3f3e647cd9b351df7be16f0adb82d5fbe F src/os_win.c 4a50a154aeebc66a1f8fb79c1ff6dd5fe3d005556533361e0d460d41cb6a45a8 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a -F src/pager.c ac0201bd6782fb760a433b1ebaddb0b8a5998f3efea6dad24954855db60a27bd -F src/pager.h fc0c95d27f2aefffcb39b4373b3557e89e1b4b9a36b183cc04d6f22002bf0ad2 -F src/parse.y 020d80386eb216ec9520549106353c517d2bbc89be28752ffdca649a9eaf56ec +F src/pager.c 76a1c3cc5fe198c38c6d15d7bda1e864642eb0131c53c2f2a94f0bcff50930a5 +F src/pager.h a195b4396e0f374922d7162ceb66f6d48a6583242b7200fa999ab52fed6341ca +F src/parse.y e583113148bb13280de7faab4f213fa183d9e6498483d5eee02f9578a07b9cd4 F src/pcache.c 040b165f30622a21b7a9a77c6f2e4877a32fb7f22d4c7f0d2a6fa6833a156a75 F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5 -F src/pcache1.c 602acb23c471bb8d557a6f0083cc2be641d6cafcafa19e481eba7ef4c9ca0f00 +F src/pcache1.c 181baf62714c20e41c77655360bd4179661f519ecd952314cdeacf60460a1878 F src/pragma.c 54dd8e18efaa3c4eecce92dc68d1d148409d216367df3a99b93dbad9870fdbf1 -F src/pragma.h e690a356c18e98414d2e870ea791c1be1545a714ba623719deb63f7f226d8bb7 +F src/pragma.h 6ebbdee90ed56a892d2c728e27fd9c1ce48c8a28841888d0c6c147946b38cb25 F src/prepare.c 371f6115cb69286ebc12c6f2d7511279c2e47d9f54f475d46a554d687a3b312c F src/printf.c 18fbdf028345c8fbe6044f5f5bfda5a10d48d6287afef088cc21b0ca57985640 -F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c +F src/random.c 9bd018738ec450bf35d28050b4b33fa9a6eebf3aaefb1a1cff42dc14a7725673 F src/resolve.c e25f51a473a5f30a0d978e4df2aaa98aeec84eac29ecae1ad4708a6c3e669345 F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97 -F src/select.c f1a81ff4f8e9e76c224e2ab3a4baa799add0db22158c7fcede65d8cc4a6fa2da +F src/select.c c581265a87628e1abcff72df3e96b56d89e8137ddb780d2522863cce08cf43cd - F src/shell.c.in 85f8d52fa4f7773823736dd39d0a268fd739207fcae95883c9ec8ce4af59f7df + F src/shell.c.in d1ed426aae2d547932971e8019939cacb4dfda8258e45b8924b250e488e2d53d -F src/sqlite.h.in 61a60b4ea04db8ead15e1579b20b64cb56e9f55d52c5f9f9694de630110593a3 +F src/sqlite.h.in 4f050c1c3e36ead0dc721e6585edfc6784fafc9eb7b61c079024ff9df502a236 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54 -F src/sqliteInt.h 73800d73e21180e6b3df8d0fe7d11758dc24367fd2b0b0075b48fc116de406bb +F src/sqliteInt.h f722ed424969d5aeb857c40c50e6f12f137ac75e6cee5651f9f9f81e0a335384 F src/sqliteLimit.h 6878ab64bdeb8c24a1d762d45635e34b96da21132179023338c93f820eee6728 F src/status.c cb11f8589a6912af2da3bb1ec509a94dd8ef27df4d4c1a97e0bcf2309ece972b F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 @@@ -827,8 -821,8 +827,8 @@@ F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1 F src/vdbevtab.c 2143db7db0ceed69b21422581f434baffc507a08d831565193a7a02882a1b6a7 F src/vtab.c 11948e105f56e84099ca17f1f434b1944539ea84de26d0d767eadfbc670ce1ea F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 - F src/wal.c 5070f3b1917b687f2f27050d0c105104726323f47422db18297c7d5904e02438 -F src/wal.c 2586d8f3503ed7a59cb3becb380bd90a5ca218c2d331d3d33e3bed58d26aa1ae -F src/wal.h 97b8a9903387401377b59507e86b93a148ef1ad4e5ce0f23659a12dcdce56af2 ++F src/wal.c bf87522c6adf40c36bf33c736ba202c998b1825b8f26202771b4e9306f2773d8 +F src/wal.h 8d02ab8c2a93a941f5898eb3345bf711c1d3f8f86f4be8d5428fb6c074962d8a F src/walker.c 7c7ea0115345851c3da4e04e2e239a29983b61fb5b038b94eede6aba462640e2 F src/where.c 217fe82a26c0fb6a3c7fd01865d821e752f9c01fb72f114af3f0b77ce234d1fb F src/whereInt.h 82a13766f13d1a53b05387c2e60726289ef26404bc7b9b1f7770204d97357fb8 @@@ -2193,8 -2171,8 +2194,8 @@@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a9 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 - P 5a17b972ed455aac751453cd8eaa8f059db1ac5c7f27965dce4956563e7911ea 8fb42df89a47b716c824de8742b7e3bda1a5c0f9a85ce3f328d7aa94ab735497 - R ba8e645a8dcf8de84a22d66e2ef51f4e - U drh - Z 0296ceef4c551981ca78da92b346a1c6 -P 8fb42df89a47b716c824de8742b7e3bda1a5c0f9a85ce3f328d7aa94ab735497 f47a5f4e0ce078e6cc1183e6cbb3c4013af379b496efae94863a42e5c39928ed -R 533592aca6769708484a27173b269b8a ++P 707f79c70c8b0fd889aede8806148457c691a008d0ce030084ba79f1e66ec53d 68c2b8d0ebd1a180c4828cb4996c6c5fd67386c3b6304edf587c255f8d067c24 ++R cfdd30d1649af86a8d872a739bf0bcdb + U dan -Z 3755d176b3b83dd08bce5a725f4586c0 ++Z 120321dc5329d8b4fcb46cfaa81efb29 # Remove this line to create a well-formed Fossil manifest. diff --cc manifest.uuid index a61c989f13,e9ab004510..b7964835dd --- a/manifest.uuid +++ b/manifest.uuid @@@ -1,1 -1,1 +1,1 @@@ - 707f79c70c8b0fd889aede8806148457c691a008d0ce030084ba79f1e66ec53d -68c2b8d0ebd1a180c4828cb4996c6c5fd67386c3b6304edf587c255f8d067c24 ++c39f6585226dfc460372d55189b37fba07468126d3961bff625cea8a95956783 diff --cc src/wal.c index e70270e8e1,17d63439ad..ad8cbec6d4 --- a/src/wal.c +++ b/src/wal.c @@@ -4428,225 -4410,41 +4476,225 @@@ int sqlite3WalBeginWriteTransaction(Wa return SQLITE_OK; } #endif + + rc = walWriteLock(pWal); + if( rc==SQLITE_OK ){ + /* If another connection has written to the database file since the + ** time the read transaction on this connection was started, then + ** the write is disallowed. Release the WRITER lock and return + ** SQLITE_BUSY_SNAPSHOT in this case. */ + SEH_TRY { + if( memcmp(&pWal->hdr, (void*)walIndexHdr(pWal),sizeof(WalIndexHdr))!=0 ){ + rc = SQLITE_BUSY_SNAPSHOT; + } + } + SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; ) + if( rc!=SQLITE_OK ){ + walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1); + pWal->writeLock = 0; + } + } + return rc; +} + +/* +** This function is called by a writer that has a read-lock on aReadmark[0] +** (pWal->readLock==0). This function relinquishes that lock and takes a +** lock on a different aReadmark[] slot. +** +** SQLITE_OK is returned if successful, or an SQLite error code otherwise. +*/ +static int walUpgradeReadlock(Wal *pWal){ + int cnt; + int rc; + assert( pWal->writeLock && pWal->readLock==0 ); + assert( isWalMode2(pWal)==0 ); + walUnlockShared(pWal, WAL_READ_LOCK(0)); + pWal->readLock = -1; + cnt = 0; + do{ + int notUsed; - rc = walTryBeginRead(pWal, ¬Used, 1, ++cnt); ++ rc = walTryBeginRead(pWal, ¬Used, 1, &cnt); + }while( rc==WAL_RETRY ); + assert( (rc&0xff)!=SQLITE_BUSY ); /* BUSY not possible when useWal==1 */ + testcase( (rc&0xff)==SQLITE_IOERR ); + testcase( rc==SQLITE_PROTOCOL ); + testcase( rc==SQLITE_OK ); + return rc; +} - /* Cannot start a write transaction without first holding a read - ** transaction. */ - assert( pWal->readLock!=WAL_LOCK_NONE ); - assert( pWal->writeLock==0 && pWal->iReCksum==0 ); - if( pWal->readOnly ){ - return SQLITE_READONLY; +#ifndef SQLITE_OMIT_CONCURRENT +/* +** A concurrent transaction has conflicted with external frame iExternal. +** Transform this value to the one required by SQLITE_COMMIT_CONFLICT_FRAME - +** the frame offset within its wal file, with the 0x80000000 bit set for +** wal2, clear for the default wal file. +*/ +static u32 walConflictFrame(Wal *pWal, u32 iExternal){ + u32 iRet = iExternal; + if( isWalMode2(pWal) ){ + int bFile = walExternalDecode(iExternal, &iRet); + iRet = (iRet | (bFile ? 0x80000000 : 0)); } + return iRet; +} - /* Only one writer allowed at a time. Get the write lock. Return - ** SQLITE_BUSY if unable. - */ - rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1); - if( rc ){ - return rc; - } - pWal->writeLock = 1; +/* +** This function does the work of sqlite3WalLockForCommit(). The difference +** between this function and sqlite3WalLockForCommit() is that the latter +** encloses everything in a SEH_TRY {} block. +*/ +static int walLockForCommit( + Wal *pWal, + PgHdr *pPg1, + Bitvec *pAllRead, + u32 *aConflict +){ + int rc = walWriteLock(pWal); - /* If another connection has written to the database file since the - ** time the read transaction on this connection was started, then - ** the write is disallowed. + /* If the database has been modified since this transaction was started, + ** check if it is still possible to commit. The transaction can be + ** committed if: + ** + ** a) None of the pages in pList have been modified since the + ** transaction opened, and + ** + ** b) The database schema cookie has not been modified since the + ** transaction was started. */ - SEH_TRY { - if( memcmp(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr))!=0 ){ + if( rc==SQLITE_OK ){ + WalIndexHdr head; + + if( walIndexLoadHdr(pWal, &head) ){ + /* This branch is taken if the wal-index header is corrupted. This + ** occurs if some other writer has crashed while committing a + ** transaction to this database since the current concurrent transaction + ** was opened. */ rc = SQLITE_BUSY_SNAPSHOT; - } - } - SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; ) + }else if( memcmp(&pWal->hdr, (void*)&head, sizeof(WalIndexHdr))!=0 ){ + int bWal2 = isWalMode2(pWal); + int iHash; + int nLoop = 1+(bWal2 && walidxGetFile(&head)!=walidxGetFile(&pWal->hdr)); + int iLoop; + + if( pPg1==0 ){ + /* If pPg1==0, then the current transaction modified the database + ** schema. This means it conflicts with all other transactions. */ + u32 bFile = walidxGetFile(&pWal->hdr); + u32 iFrame = walidxGetMxFrame(&head, bFile) | (bFile << 31); + aConflict[SQLITE_COMMIT_CONFLICT_PGNO] = 1; + aConflict[SQLITE_COMMIT_CONFLICT_FRAME] = iFrame; + rc = SQLITE_BUSY_SNAPSHOT; + } - if( rc!=SQLITE_OK ){ - walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1); - pWal->writeLock = 0; + assert( nLoop==1 || nLoop==2 ); + for(iLoop=0; rc==SQLITE_OK && iLoophdr.mxFrame (which will be + ** set to the size of the old, now overwritten, wal file). This + ** doesn't come up in wal2 mode, as in wal2 mode the client always + ** has a PART lock on one of the wal files, preventing it from being + ** checkpointed or overwritten. */ + iFirst = pWal->hdr.mxFrame+1; + if( memcmp(pWal->hdr.aSalt, (u32*)head.aSalt, sizeof(u32)*2) ){ + assert( pWal->readLock==0 ); + iFirst = 1; + } + mxFrame = head.mxFrame; + }else{ + int iA = walidxGetFile(&pWal->hdr); + if( iLoop==0 ){ + iFirst = walExternalEncode(iA, 1+walidxGetMxFrame(&pWal->hdr, iA)); + mxFrame = walExternalEncode(iA, walidxGetMxFrame(&head, iA)); + }else{ + iFirst = walExternalEncode(!iA, 1); + mxFrame = walExternalEncode(!iA, walidxGetMxFrame(&head, !iA)); + } + } + iLastHash = walFramePage(mxFrame); + + for(iHash=walFramePage(iFirst); iHash<=iLastHash; iHash += (1+bWal2)){ + WalHashLoc sLoc; + + rc = walHashGet(pWal, iHash, &sLoc); + if( rc==SQLITE_OK ){ + u32 i, iMin, iMax; + assert( mxFrame>=sLoc.iZero ); + iMin = (sLoc.iZero >= iFirst) ? 1 : (iFirst - sLoc.iZero); + iMax = (iHash==0) ? HASHTABLE_NPAGE_ONE : HASHTABLE_NPAGE; + if( iMax>(mxFrame-sLoc.iZero) ) iMax = (mxFrame-sLoc.iZero); + for(i=iMin; rc==SQLITE_OK && i<=iMax; i++){ + PgHdr *pPg; + if( sLoc.aPgno[i-1]==1 ){ + /* Check that the schema cookie has not been modified. If + ** it has not, the commit can proceed. */ + u8 aNew[4]; + u8 *aOld = &((u8*)pPg1->pData)[40]; + int sz; + i64 iOff; + u32 iFrame = sLoc.iZero + i; + int iWal = 0; + if( bWal2 ){ + iWal = walExternalDecode(iFrame, &iFrame); + } + sz = head.szPage; + sz = (sz&0xfe00) + ((sz&0x0001)<<16); + iOff = walFrameOffset(iFrame, sz) + WAL_FRAME_HDRSIZE + 40; + rc = sqlite3OsRead(pWal->apWalFd[iWal],aNew,sizeof(aNew),iOff); + if( rc==SQLITE_OK && memcmp(aOld, aNew, sizeof(aNew)) ){ + u32 iFrame = walConflictFrame(pWal, sLoc.iZero+i); + aConflict[SQLITE_COMMIT_CONFLICT_PGNO] = 1; + aConflict[SQLITE_COMMIT_CONFLICT_FRAME] = iFrame; + rc = SQLITE_BUSY_SNAPSHOT; + } + }else if( sqlite3BitvecTestNotNull(pAllRead, sLoc.aPgno[i-1]) ){ + u32 iFrame = walConflictFrame(pWal, sLoc.iZero+i); + aConflict[SQLITE_COMMIT_CONFLICT_PGNO] = sLoc.aPgno[i-1]; + aConflict[SQLITE_COMMIT_CONFLICT_FRAME] = iFrame; + rc = SQLITE_BUSY_SNAPSHOT; + }else + if( (pPg = sqlite3PagerLookup(pPg1->pPager, sLoc.aPgno[i-1])) ){ + /* Page aPgno[i], which is present in the pager cache, has been + ** modified since the current CONCURRENT transaction was + ** started. However it was not read by the current + ** transaction, so is not a conflict. There are two + ** possibilities: (a) the page was allocated at the of the file + ** by the current transaction or (b) was present in the cache + ** at the start of the transaction. + ** + ** For case (a), do nothing. This page will be moved within the + ** database file by the commit code to avoid the conflict. The + ** call to PagerUnref() is to release the reference grabbed by + ** the sqlite3PagerLookup() above. + ** + ** In case (b), drop the page from the cache - otherwise + ** following the snapshot upgrade the cache would be + ** inconsistent with the database as stored on disk. */ + if( sqlite3PagerIswriteable(pPg) ){ + sqlite3PagerUnref(pPg); + }else{ + sqlite3PcacheDrop(pPg); + } + } + } + } + if( rc!=SQLITE_OK ) break; + } + } + } } + pWal->nPriorFrame = walGetPriorFrame(&pWal->hdr); return rc; }