- C Merge\strunk\senhancements\sinto\sthe\sbegin-concurrent-pnu-wal2\sbranch.
- D 2021-10-21T14:24:24.912
-C Merge\sthe\slatest\strunk\senhancements\sinto\sthe\swal2\sbranch.
-D 2021-11-09T13:52:20.080
++C Merge\sall\srecent\strunk\senhancements\sinto\sthe\sbegin-concurrent-pnu-wal2\sbranch.
++D 2021-11-09T15:18:21.391
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
- F Makefile.in ba064f023a5a402081a198e16ca1aa0ae020cf32492529be8071cb2f503bd0cc
-F Makefile.in f05f45ead829c1c49b8f016022c133276c0eda5498e04dfeefc27720007d9b2e
++F Makefile.in 51fc06b371261469b0e18b61533fc8b523fedf0096bcacdf5afac96b65c58e88
F Makefile.linux-gcc f609543700659711fbd230eced1f01353117621dccae7b9fb70daa64236c5241
- F Makefile.msc 527b829960ac21d5489fadb5d8fe52a00dc81137c8cd67aba38a7de89a7ea80a
+ F Makefile.msc 1f9a608925602339e7e9e542659f36255ceec5f1e0803d08b062f0351c88fd4e
F README.md 27fb76aa7eb57ed63a53bbba7292b6bf71f51125554f79f16b5d040edd1e6110
F VERSION c6595fef606851f2bc3ebed6a7386c73751835fc909feab7c093739fa4b3c1d1
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
F src/attach.c e3f9d9a2a4a844750f3f348f37afb244535f21382cbfcd840152cb21cb41cfaf
F src/auth.c f4fa91b6a90bbc8e0d0f738aa284551739c9543a367071f55574681e0f24f8cf
F src/backup.c 3014889fa06e20e6adfa0d07b60097eec1f6e5b06671625f476a714d2356513d
-F src/bitvec.c 7c849aac407230278445cb069bebc5f89bf2ddd87c5ed9459b070a9175707b3d
+F src/bitvec.c 3907fcbe8a0c8c2db58d97087d15cdabbf2842adb9125df9ab9ff87d3db16775
F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
- F src/btree.c 0d9794d3bd7569afc7585e37ee740cbe549ab7ed6f976faf819859f11e3d4c96
-F src/btree.c c69775cb3b7ff6e5a48ea0f6f78de2df9549879c4f43ad81f18b0f6cd658b3e3
-F src/btree.h 74d64b8f28cfa4a894d14d4ed64fa432cd697b98b61708d4351482ae15913e22
-F src/btreeInt.h ee9348c4cb9077243b049edc93a82c1f32ca48baeabf2140d41362b9f9139ff7
-F src/build.c 1b41a6417e5bb260a5988588764863229905b07b3e9a47878030a1c92d49010f
++F src/btree.c 5fa29b79523fbea1dc6b2259be137192b3032e296f2374a63b8980354c15d3a4
+F src/btree.h 900067641b64d619e6e2a93bd115c952a52f41d3bee32e551e2a4ceee05fc431
+F src/btreeInt.h 3f19f0be5af0b68cff55e58df4b11e7a0692d9e8a820ceaeba4084659a86cf28
- F src/build.c d4aa88855609a36e3785a061b9416ba7225d09e93b859f5f29cf58edf7183fa2
++F src/build.c f0cd84c6186df95fb679471ff8a52ecf6dba4df340891755b2e28a89128a732f
F src/callback.c 106b585da1edd57d75fa579d823a5218e0bf37f191dbf7417eeb4a8a9a267dbc
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c 8159d5f706551861c18ec6c8f6bdf105e15ea00367f05d9ab65d31a1077facc1
F src/dbpage.c 8a01e865bf8bc6d7b1844b4314443a6436c07c3efe1d488ed89e81719047833a
F src/dbstat.c 861e08690fcb0f2ee1165eff0060ea8d4f3e2ea10f80dab7d32ad70443a6ff2d
F src/delete.c 0c151975fa99560767d7747f9b60543d0093d9f8b89f13d2d6058e9c83ad19e7
- F src/expr.c 529f7eca2821e874a375b1b318e697d62cb28f56069677c93f587f2de5dceb54
+ F src/expr.c 5c021ca2495b1e908610276cf5d462133d63ec47863235c8958d36e61841c72d
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 187b67af20c5795953a592832c5d985e4313fe503ebd8f95e3e9e9ad5a730bb5
-F src/func.c 1cfb09d7ffca81238eccefdb0293e1f5b7cfebbd1816dfad5ec6024742a7496b
+F src/func.c a5dce8a8ff85310e2c88262a25bcded0a7e92be9a4bda24bbf6eab78e99c2f13
- F src/global.c 59bfd5705a623f0b45e91622699953cfd1be2c176e78d8ff610463f2ea4ec51b
+ F src/global.c 1f56aead86e8a18c4415638f5e6c4d0a0550427f4b3f5d065ba5164cc09c22e8
F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19
- F src/hash.h 9d56a9079d523b648774c1784b74b89bd93fac7b365210157482e4319a468f38
+ F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51
F src/hwtime.h cb1d7e3e1ed94b7aa6fde95ae2c2daccc3df826be26fc9ed7fd90d1750ae6144
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
- F src/insert.c b32e2dcbca838cb8acd4777a59243db4bcea53089e3181b0ea3e4dc75b43aeff
+ F src/insert.c 7fcbbe9114ac402ea3c0c6a3810f13fc89cae8131ea1659ec472be7caac10192
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
- F src/loadext.c 0aa9e7f08e168e3874cb54984408e3976dafdf5616d511952c425b5ac088ea3e
- F src/main.c 7128184e581e79689a283647e804dbbbaff88bdf1fe7e77046adbb39b1d37b38
+ F src/loadext.c e1dcff1c916bf6834e150b492eddda5d9792453182d2ad64294d2266b6e93c4c
-F src/main.c 5ed1babdec5bbf935fb4586fcb12debbff760c301948ac46cf90e720b4405a8b
++F src/main.c 8dd12c04918305f5fb27bacbaca65505824d4eaf5e74605d6809362f6d23b020
F src/malloc.c ef796bcc0e81d845d59a469f1cf235056caf9024172fd524e32136e65593647b
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
F src/os.h 26890f540b475598cd9881dcc68931377b8d429d3ea3e2eeb64470cde64199f8
F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85
F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
- F src/os_unix.c 63d998a28fc6d71e4333db3bf42ddbf674b375826ad1bad2f4305552bb4a5a25
-F src/os_unix.c 8e14b40fd02f70e234030c2bee45215ff8835293adc13a08e9718c29bff61401
++F src/os_unix.c 7cc2a76b867cc3a7e9de7923e90485ee566cc06a60b2047231791ad769939c31
F src/os_win.c 77d39873836f1831a9b0b91894fec45ab0e9ca8e067dc8c549e1d1eca1566fe9
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
- F src/pager.c bdb6b50eb01ad554b40234695cf4ad8b2cbe1be70e333f7e32394fd109a5b65a
-F src/pager.c 144c2111216d51a34646824c77612ce997a79a77d2dca2afc8bb3ac323fc3390
-F src/pager.h 9d38ac4b9f0e1361f7ddb6aa0675a54f5e4f085703108d3aafe7868872113f92
-F src/parse.y 0bd7971a7489bbf6c3726f1b50da6e508bdff8fa493e9cc3f5a96b12cbb2361e
++F src/pager.c 17e8d78f77faa53bd91f7ee148315135c867636ac182b08eb29ce37d1df9b802
+F src/pager.h 034a193e53d6649bdb641aa996e38094dbb7cbe365d8c10eba871a38a0f5ebb3
+F src/parse.y 59631359574901cc5cd4780939a6740f6bc597bd473334e744c1a1c32d9adef3
F src/pcache.c 084e638432c610f95aea72b8509f0845d2791293f39d1b82f0c0a7e089c3bb6b
F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
F src/pcache1.c 54881292a9a5db202b2c0ac541c5e3ef9a5e8c4f1c1383adb2601d5499a60e65
- F src/pragma.c fdcc0d3350cbfa54b21f506f9b0fd87171d86ca661a32413097c3d55660f55c4
+ F src/pragma.c cb0cc54e1ae56082f6eabc4c0013ee3fd31844bda83e9c5aaf95616572db2439
-F src/pragma.h 87330ed2fbfa2a1274de93ca0ab850fba336189228cb256089202c3b52766fad
+F src/pragma.h f98354c48571c490927029510566839bf9e7242569bfbb48032dafeb008481d2
- F src/prepare.c 8f07616db04337057b8498b72d051ee90f73c54615c2e908c05404cef1e060b7
+ F src/prepare.c 7520a371f1de8a53e3023eba75bc0d3473196833c6363d285cad8d002eabef0b
F src/printf.c 5901672228f305f7d493cbc4e7d76a61a5caecdbc1cd06b1f9ec42ea4265cf8d
-F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c
+F src/random.c c6e61d041f230d46c658e6dfe7165fc1ecb0093d5fe28cfe74f389d261dc3af8
- F src/resolve.c ae65c88f5d0d4bc0052b203773d407efa2387c2bd6b202f87178006c7bb8632c
+ F src/resolve.c 4a1db4aadd802683db40ca2dbbb268187bd195f10cbdb7206dbd8ac988795571
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
- F src/select.c 8c2341a9802e0979092d920544823a778f4c2bddf59d323d5e4ed6204ab50550
- F src/shell.c.in e80fe5118fc3b942c1becc67ebfca6a887dbab9295e0bd5b6da61c4375baa637
- F src/sqlite.h.in 024a062670b27cd9ff7aeb5f63d341a6d32b95ebf5eff08c13bb07322f3d004a
-F src/select.c b4b3a0f32e70d93efbb357783846853dbd8b266ec0d7035aa0a245c33eecf72d
++F src/select.c 1f188fd3aa15d8cb5e5397b8ba91102b3b9b2803cc50e5df770929aa82a34a1c
+ F src/shell.c.in f8854bcb0d14707d661732698d5210d7f01694000c46e8014b323ad18f575be6
-F src/sqlite.h.in 5cd209ac7dc4180f0e19292846f40440b8488015849ca0110c70b906b57d68f0
++F src/sqlite.h.in 32f7d112cb85d3f2fd56500e11a6bd6d19a969306650200dcde97c2638cfecfc
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
- F src/sqlite3ext.h e97f4e9b509408fea4c4e9bef5a41608dfac343b4d3c7a990dedde1e19af9510
- F src/sqliteInt.h d8a5d7c8d55454e56c92e873bd6b0388d8cff335c8cd95713c8abc844de5c024
+ F src/sqlite3ext.h 8ff2fd2c166150b2e48639f5e506fb44e29f1a3f65031710b9e89d1c126ac839
-F src/sqliteInt.h 8e770859062a87254dabd183b3f7bd29f89fd5905515beac00877958e88e06ce
++F src/sqliteInt.h d5e9880fb0b512d2e0b73192d7fdb147288c5c7865db8bc4bbf2a1b890e8c425
F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657
F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
F src/tclsqlite.c 428e813dabf82804bc13196af35a0c3c6ef4347fe557fa6717c5c66bba6e8520
- F src/test1.c 5d61bf9d984188b64ee7a4346856633ec5555028137f5f3a332bf5ef36c4a0a3
-F src/test1.c d6c945a8bb211ed72ea515f0b9743caeaf38c66da6418a7b1dcf3764e1368bbb
++F src/test1.c 2785b6fd05e4810f7215bf8de01c15670f39a19e49e3d927045f5e72ab08b4cd
F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5
F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644
F src/test4.c 7c4420e01c577b5c4add2cb03119743b1a357543d347773b9e717195ea967159
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
F src/tokenize.c bae853ad129d1129c063de8630a3e99e306283bc40146f359b1bb91be2c08f1e
F src/treeview.c 9dfdb7ff7f6645d0a6458dbdf4ffac041c071c4533a6db8bb6e502b979ac67bc
- F src/trigger.c 3f612ce5f0858b6c23460a3c799d01f408b49b0b29d931d8b8e6fc224a8667de
+ F src/trigger.c 2ef56f0b7b75349a5557d0604b475126329c2e1a02432e7d49c4c710613e8254
-F src/update.c 69c4c10bc6873a80c0a77cb578f9fc60ee90003d03f9530bc3370fa24615772d
+F src/update.c dc362b5c6b459cb1915cadb94270f1f0de68657a82293eb5ce9aaf880d0af1ba
F src/upsert.c 8789047a8f0a601ea42fa0256d1ba3190c13746b6ba940fe2d25643a7e991937
F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
F src/util.c 30df8356e231dad33be10bb27897655002668343280004ba28c734489414a167
- F src/vacuum.c a02ce4cb7c45741675bac31528b4bb7b8821727cf3306ade2b06361b4704b248
- F src/vdbe.c 2f180b062f09334c61b76a2bd3c7054f99643d3be85d2e28558e4bbcb2a301c8
-F src/vacuum.c 6c38ddc52f0619865c91dae9c441d4d48bf3040d7dc1bc5b22da1e45547ed0b3
-F src/vdbe.c 03227424bdd3265be61d03f5725ba33add35fd716e40af5f158e73199f7bac59
++F src/vacuum.c 72867c740476d13f1c397015e4d3168b4e96a237a80b9afa67e1bb8500bfeeab
++F src/vdbe.c c403995aed4a9293f10e53b111aebcfdb9c3349e442c7df337cec083f5b7cdae
F src/vdbe.h 25dabb25c7e157b84e59260cfb5b466c3ac103ede9f36f4db371332c47601abe
- F src/vdbeInt.h 38206c8dd6b60ff03d9fd4f626b1b4fd0eef7cdc44f2fc2c1973b0f932a3f26b
- F src/vdbeapi.c 7b83468feb1d42a09d4c2e5241a3eaa3d1f138e289a843cba9fd3f1dad95ca67
+ F src/vdbeInt.h 31fbabdc1ed61d9695337dfe5269ea94e1cf615c17f5cafeaa1bb01066820bab
+ F src/vdbeapi.c f4bd14b42d9717a35baac5f20c0c4bfccbf3691d64dc6ec02fc0ef19374d3c92
-F src/vdbeaux.c a57c760d1897f1b72f6fae26983df363db7a2c42d88721187e907f2c84862b42
+F src/vdbeaux.c ec21bd1475c69543d961b241b51ad4321342ae1ec1d64969063efbb3db7d23a0
F src/vdbeblob.c 292e96c01c4219fca71d74e1002906d43eb232af4bd83f7552a3faec741f3eb8
- F src/vdbemem.c 8be0af1060012520381d3296fcb1718e80cd5b99ce04f51f7e1c4dba4072caac
- F src/vdbesort.c cd5130f683706c1a43e165a74187745fb3351cb56052cf9dc91de820634bbde2
+ F src/vdbemem.c a3d91dc9bb9ef725db77e4e9de7e1acef43192c9f8406c307665d503e3c2837c
+ F src/vdbesort.c 513b481c8bab4a6578c92194a60cf3bc3b48736e4a53f8d2d7918121c5b594e7
F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf823
F src/vdbevtab.c f99b275366c5fc5e2d99f734729880994ab9500bdafde7fae3b02d562b9d323c
- F src/vtab.c d07cc24dd84b0b51bf05adb187b0d2e6b0cac56cfbc0197995a26d4f8fa5c7e2
+ F src/vtab.c 9d5c3f49d3a6959b6eef287bb8fa773563102a80a835c3314c57144412709e78
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
- F src/wal.c 8e8fb6d6451ca8fa6b633d3bd8625214c8eab925de09fe9314a43f997f534872
-F src/wal.c b4b8fa75897fe5229cc30725345db656e122b65c394dfc5d279bf49e422481ed
-F src/wal.h d01234e828943e002040c22a7e017642962f9fd9b2dc142fa599769ae4e459e9
++F src/wal.c ae1ac0b2c5ca25fadff417cec4b55876ba21c52b6d0ed6ddd5a1b6975a668bcd
+F src/wal.h 7a733af13b966ecb81872ce397e862116b3575ea53245b90b139a2873ee87825
F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b
- F src/where.c ecabef93b0f14442a73eca205fc960428984d75fbdc7d60226b7fc9cac127187
+ F src/where.c de0d4ff409c7b62a8803f9f267cc2c7fedddbc00de9ab7b5382c507383c18665
F src/whereInt.h 83877a75a1bce056ea44aff02f1dfa958ad1d6038c213ddadb8652003b45151d
- F src/wherecode.c a1d79cc5a11f44b079bf2352e542ddb265f84cfa6c835d40a9f195dbe5fff83e
+ F src/wherecode.c 1f5b62f46d284c8886945eb7438415bc27e23e87bb60b9ee468fa6bd31268f33
F src/whereexpr.c 17bdbf4f5b490e70a18635498f0b910a558f953a9bf80af7f19cbde6e60e6825
- F src/window.c 0dff6fedf61493490d21ced5d7a7b4321d4c0db6c8123f0179c46080a860850a
+ F src/window.c 5d3b397b0c026d0ff5890244ac41359e524c01ae31e78782e1ff418c3e271a9e
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627
F test/affinity3.test eecb0dabee4b7765a8465439d5e99429279ffba23ca74a7eae270a452799f9e7
F test/corruptK.test 5b4212fe346699831c5ad559a62c54e11c0611bdde1ea8423a091f9c01aa32af
F test/corruptL.test 7d3440831ca24ba64305583c4d4506d417d3f89f5775c0b7cc8102db078f8ff5
F test/corruptM.test 7d574320e08c1b36caa3e47262061f186367d593a7e305d35f15289cc2c3e067
- F test/corruptN.test 89d078b7c5c5197f4fca14b4ed1d45196fcad52aa22439ffbc61baac758a56b6
-F test/corruptN.test 60b5a62944b4f0029ba07edaa5fd8e670539d6b0a8d99db26c068d435675cbfe
++F test/corruptN.test f0b26fda7556581af9667904ce2fa1e5749cd018b56c8fb77bda143d3ab6ccbf
F test/cost.test b11cdbf9f11ffe8ef99c9881bf390e61fe92baf2182bad1dbe6de59a7295c576
F test/count.test 5364003488249957750a5f15ee42ca1cd7b100b1131c2dc71fff266a1250bf55
F test/countofview.test e17d6e6688cf74f22783c9ec6e788c0790ee4fbbaee713affd00b1ac0bb39b86
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
- P bce02eaa0c379d9b90bfaa766fd24d7dd2f009f840ee18cc4f2c7d7b6f7aa368 7e2bc836f6aedfd69588f5723f8797f11ee6437d3b63ffc43c88d40e3baadb1c
- R f4152daac42142b94ccc7b507134c638
-P 700876b79c47017cfbf42b8710ec0b50d7a987864db7599593817b962763bc71 de10795a1cf70925088e9652998e813665b2e147ffa4a4edab18c7e2c66bf5ae
-R 490a6a01f17478b9fef91dcfb9c1e660
++P 1958e6facaaca8e695ae3d7e79acdba0025d6221653397ea45f9b8daa56c8d9b 0894f59569378c41207b6cef43dbff9a4873582709d954c809c18f42d918aa03
++R d51c1503abf10965a7f6b01b91b3b4a0
U drh
- Z 1e248306ce0f5d31350280fb98581cfa
-Z 8dd449c2a68fd4220a8dac9d19d7295f
++Z 909ec6a0986c60628db195c4c35452d9
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. */
+ if( memcmp(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr))!=0 ){
+ walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
+ pWal->writeLock = 0;
+ rc = SQLITE_BUSY_SNAPSHOT;
+ }
+ }
+ 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 );
+/*
+** 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);
+ }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;
+}
- if( pWal->readOnly ){
- return SQLITE_READONLY;
- }
- /* 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;
+#ifndef SQLITE_OMIT_CONCURRENT
+/*
+** This function is only ever called when committing a "BEGIN CONCURRENT"
+** transaction. It may be assumed that no frames have been written to
+** the wal file. The second parameter is a pointer to the in-memory
+** representation of page 1 of the database (which may or may not be
+** dirty). The third is a bitvec with a bit set for each page in the
+** database file that was read by the current concurrent transaction.
+**
+** This function performs three tasks:
+**
+** 1) It obtains the WRITER lock on the wal file,
+**
+** 2) It checks that there are no conflicts between the current
+** transaction and any transactions committed to the wal file since
+** it was opened, and
+**
+** 3) It ejects any non-dirty pages from the page-cache that have been
+** written by another client since the CONCURRENT transaction was started
+** (so as to avoid ending up with an inconsistent cache after the
+** current transaction is committed).
+**
+** If no error occurs and the caller may proceed with committing the
+** transaction, SQLITE_OK is returned. SQLITE_BUSY is returned if the WRITER
+** lock cannot be obtained. Or, if the WRITER lock can be obtained but there
+** are conflicts with a committed transaction, SQLITE_BUSY_SNAPSHOT. Finally,
+** if an error (i.e. an OOM condition or IO error), an SQLite error code
+** is returned.
+*/
+int sqlite3WalLockForCommit(
+ Wal *pWal,
+ PgHdr *pPg1,
+ Bitvec *pAllRead,
+ Pgno *piConflict
+){
+ 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.
*/
- if( memcmp(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr))!=0 ){
- walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
- pWal->writeLock = 0;
- rc = SQLITE_BUSY_SNAPSHOT;
+ 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;
+ }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. */
+ *piConflict = 1;
+ rc = SQLITE_BUSY_SNAPSHOT;
+ }
+
+ assert( nLoop==1 || nLoop==2 );
+ for(iLoop=0; rc==SQLITE_OK && iLoop<nLoop; iLoop++){
+ u32 iFirst; /* First (external) wal frame to check */
+ u32 iLastHash; /* Last hash to check this loop */
+ u32 mxFrame; /* Last (external) wal frame to check */
+
+ if( bWal2==0 ){
+ assert( iLoop==0 );
+ /* Special case for wal mode. If this concurrent transaction was
+ ** opened after the entire wal file had been checkpointed, and
+ ** another connection has since wrapped the wal file, then we wish to
+ ** iterate through every frame in the new wal file - not just those
+ ** that follow the current value of pWal->hdr.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 ){
++ 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 = pWal->hdr.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)) ){
+ rc = SQLITE_BUSY_SNAPSHOT;
+ }
- }else if( sqlite3BitvecTestNotNull(pAllRead, sLoc.aPgno[i]) ){
- *piConflict = sLoc.aPgno[i];
++ }else if( sqlite3BitvecTestNotNull(pAllRead, sLoc.aPgno[i-1]) ){
++ *piConflict = sLoc.aPgno[i-1];
+ rc = SQLITE_BUSY_SNAPSHOT;
- }else if( (pPg = sqlite3PagerLookup(pPg1->pPager, sLoc.aPgno[i])) ){
++ }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 = pWal->hdr.mxFrame;
return rc;
}