- C Merge\schanges\sfrom\strunk,\sincluding\sall\sthe\s3.24.0\schanges\splus\ssome\nlater\senhancements.
- D 2018-06-06T17:03:53.789
-C Fix\sa\sharmless\swarning\sabout\scomment\sformatting\sin\sthe\sprevious\ncheck-in.\s\sSimplify\sthe\sORDER\sBY\sdereferencing\slogic\sso\sthat\sit\savoids\nunreachable\sbranches.
-D 2018-07-10T07:39:23.889
++C Merge\slatest\strunk\schanges\sinto\sthis\sbranch.
++D 2018-07-10T15:45:54.355
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
- F Makefile.in bfc40f350586923e0419d2ea4b559c37ec10ee4b6e210e08c14401f8e340f0da
+ F Makefile.in 0a3a6c81e6fcb969ff9106e882f0a08547014ba463cb6beca4c4efaecc924ee6
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
- F Makefile.msc 681fb88cccf1fd58c0b9648f6a09b75332206ef72ca76012ad11699c320cec5f
+ F Makefile.msc c1646e8f86c30ea63e56176deacef192ac87c663ce2c9083f459c45a7268934f
F README.md 7764d56778d567913ef11c82da9ab94aefa0826f7c243351e4e2d7adaef6f373
F VERSION d3e3afdec1165a5e593dcdfffd8e0f33a2b0186067eb51a073ef6c4aec34923d
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
- F main.mk 1e357c4e2852effdec3d1a8361ffb9c7e4747ecee09150dceab0994559fff65e
-F main.mk d9872d31efa4a02e177f6d43b7fdae2a5f822e50d1eb72907f6575a567b85378
++F main.mk bbc479e219c733541c511031a4299b1562f2ab57e07a4917e9b3d029c31f2924
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
- F src/alter.c cf7a8af45cb0ace672f47a1b29ab24092a9e8cd8d945a9974e3b5d925f548594
- F src/analyze.c 71fbbeb7b25417592f54d869fe90c28b48e4cecb9926ef9b06d90fb0aec48941
- F src/attach.c 4a3138bd771d5426ae4344d8d5e900440af29fabc5ec2f39f69a45010dfbccd7
+ F src/alter.c 6beb476095a4cfeb95ebedb2e5e17894d1687b24fddd5b8761a4de120e0392c6
+ F src/analyze.c 41f0b8d638fc2a7309477904ac38e535f2aabea3256da3251e529730e099df77
+ F src/attach.c 4bd5b92633671d3e8ce431153ebb1893b50335818423b5373f3f27969f79769a
F src/auth.c a38f3c63c974787ecf75e3213f8cac6568b9a7af7591fb0372ec0517dd16dca8
F src/backup.c 78d3cecfbe28230a3a9a1793e2ead609f469be43e8f486ca996006be551857ab
-F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
+F src/bitvec.c 8433d9e98dd6f2ea3286e0d2fe5d65de1bfc18a706486eb2026b01be066b5806
F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
- F src/btree.c c0c5ce45d2de13f75176d07f69744f535a0bad05a46cf836ceaf718028ad18e0
- F src/btree.h 1d6402daa3c50b9af145dc15ff6ef0c4d2cc6e1734155646667c59b06e76182b
-F src/btree.c d9dcccd604aa8b128a20b195001570a46c354525d7abe165b1256ba1ffc307d1
-F src/btree.h febb2e817be499570b7a2e32a9bbb4b607a9234f6b84bb9ae84916d4806e96f2
-F src/btreeInt.h 620ab4c7235f43572cf3ac2ac8723cbdf68073be4d29da24897c7b77dda5fd96
-F src/build.c d8f6ac1e9e484eb3f3921a8336d3dc6c87273d9db8729702162ef045997a1463
++F src/btree.c 23bad79f6ad51249aabb90314aa4a75282f9ff3f7f8dcaad7521fa44c2a7eab8
++F src/btree.h 1ed41c71481a1196a520064f2282bc13d768bbd8ae2850e319a3048f8ee7cb3d
+F src/btreeInt.h 6c65e6c96f561596f6870c79a64d4706af81613881d7947e3f063e923f14115f
- F src/build.c 3c182a684dc7bdade57d09073613e246431cc1dbe2e0c214fe9adebcc72f9e86
++F src/build.c da448a48fc8f4020a9ddcdea0ded1d35513f95e0fca7fdd28beef5b349e88110
F src/callback.c 36caff1e7eb7deb58572d59c41cee8f064a11d00297616995c5050ea0cfc1288
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c 849d4cebe008cfc6e4799b034a172b4eaf8856b100739632a852732ba66eee48
F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4
F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
- F src/insert.c 76b1dc902e4c3930d9a17a40cd8ee2e94b1fd8cce766672caef164a6d5d4df1d
+ F src/insert.c bcacf6a0d277f8fa0e4f9ffecda544a2330ca4478f904cd89564c2dd86d0b16b
F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e
F src/loadext.c 6aae5739198d96c51ae6eb97c4a5b1744c22ed7a5a565a5399a717780d48a36b
- F src/main.c 53ef4fe3ceeca4ef8bdb986badbf875734d54936785bc73513d708a55cf5abd5
-F src/main.c db7d550fad3a95403f50d25cbdd8ec33037ed100e676f2481d58e0d9cf0f15dc
++F src/main.c 176af447d71fc10e87d14ad155297bad2e8a68ca9b95153d726761b3f1e5595c
F src/malloc.c 07295435093ce354c6d9063ac05a2eeae28bd251d2e63c48b3d67c12c76f7e18
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
F src/os.h 48388821692e87da174ea198bf96b1b2d9d83be5dfc908f673ee21fafbe0d432
F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85
F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
-F src/os_unix.c c230a7a24766320d8414afd087edcd43e499fb45e86361f6f4f464f343d965a9
+F src/os_unix.c 2c6a5a60cd4009863bb56bcb12a60d48c63e27b60809989dc4f5f71ef88e1a7f
F src/os_win.c ac29c25cde4cfb4adacc59cdec4aa45698ca0e29164ea127859585ccd9faa354
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
-F src/pager.c 1bb6a57fa0465296a4d6109a1a64610a0e7adde1f3acf3ef539a9d972908ce8f
-F src/pager.h c571b064df842ec8f2e90855dead9acf4cbe0d1b2c05afe0ef0d0145f7fd0388
-F src/parse.y 2eee45f4c80cc442b29ae6ca5f174a70cdb669bd0dc25a1a9cad3228a3b01c3d
+F src/pager.c 5feea9c9e681f9150fd1735c003825b32185df0bfa517870d69d4bacd51c4104
+F src/pager.h abf96ba73094af7095f45495734f162642542d841ca563998795fc9447a01e1f
- F src/parse.y 161e5d85041247781b192fb41244fe3ffba84f599ac270ca67747108247d7f1d
++F src/parse.y 2578339a1402c25ecfd270a8c9747424aea35f9d1280e3082757d05970a1b991
F src/pcache.c 135ef0bc6fb2e3b7178d49ab5c9176254c8a691832c1bceb1156b2fbdd0869bd
F src/pcache.h 072f94d29281cffd99e46c1539849f248c4b56ae7684c1f36626797fee375170
F src/pcache1.c 716975564c15eb6679e97f734cec1bfd6c16ac3d4010f05f1f8e509fc7d19880
F src/prepare.c e966ecc97c3671ff0e96227c8c877b83f2d33ea371ee190bbf1698b36b5605c0
F src/printf.c 7f6f3cba8e0c49c19e30a1ff4e9aeda6e06814dcbad4b664a69e1b6cb6e7e365
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
- F src/resolve.c 14602f46800ba182ea6a490e0f304127d29ac1f724bdadcc639e25d3223fcf6e
+ F src/resolve.c 797088662ed61102485e3070ba3b3f7828bd5ef6a588223ba6865d77d52f6cea
F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
- F src/select.c 8d3176c5258cc83942815ebe75b4c1f8dcf62b5e0f4d37373a14ebf23c046f9f
- F src/shell.c.in 099edadacd82abbe38472e2995b140560bb9826cd4af611e6bab662cfba8fbda
- F src/sqlite.h.in 1228a3296d1a691107d29c75891dcbeb31c4643ff5f16231fa7845c691cc6966
+ F src/select.c c06d56c1d5931456b2507ac8cf8205e83492a309b685e3978953f0b0156af191
+ F src/shell.c.in f1c79c537117ee61317a5ed85cdbcb854998cd690eb34ab803779358a2ace780
-F src/sqlite.h.in 36f0b3f88241863530f4b7e57e673e19311dd609ec4edad83b23291928cdf853
++F src/sqlite.h.in 3818a7a023edbca14c433d85ca098e423120b403c89db7179a7dd47748054f31
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 9887b27e69c01e79c2cbe74ef73bf01af5b5703d6a7f0a4371e386d7249cb1c7
- F src/sqliteInt.h 61275d2b6c4b96840aa4c9a75831422b3303b98053b66b349d3eb37068bd17e2
-F src/sqliteInt.h 7e24bfe3bf22df5516062f229fe181f9532ff44335d702c525420e060aad78da
++F src/sqliteInt.h 1cea90fe375c3c4bff5d68161bbfaeab79952e86689996382c128af774f7f1bd
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
F src/tclsqlite.c 916a92de77ec5cbe27818ca194d8cf0c58aa7ad5b87527098f6aa5a6068800ce
- F src/test1.c f49d75aeaa20284d60e3aa3c00f2b5bba40b27d11f7703664f6dcb18c4cb17f9
-F src/test1.c b5e21f2ec8386cabb67346c9399603ddb33f76094a0941f280b403aa93631717
++F src/test1.c dac8c86fe74879f91931665e786b17cbd90f318423e5f4500e68ab0644655f6b
F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5
F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644
F src/test4.c 18ec393bb4d0ad1de729f0b94da7267270f3d8e6
F src/test_bestindex.c 78809f11026f18a93fcfd798d9479cba37e1201c830260bf1edc674b2fa9b857
F src/test_blob.c ae4a0620b478548afb67963095a7417cd06a4ec0a56adb453542203bfdcb31ce
F src/test_btree.c 8b2dc8b8848cf3a4db93f11578f075e82252a274
- F src/test_config.c 7f049288c6174ba7038f37b68c809897426790170b25c178bf18d7358e6eed69
-F src/test_config.c 6c3f341ece48020c4ddbce055643a91c653283b3a6853c46ea18d22e5c72847d
++F src/test_config.c eda1e2518177fb2e3ab02df563006b5f83da895c3e2efb582705aeb0b0ddfe07
F src/test_delete.c e2fe07646dff6300b48d49b2fee2fe192ed389e834dd635e3b3bac0ce0bf9f8f
F src/test_demovfs.c a0c3bdd45ed044115c2c9f7779e56eafff18741e
F src/test_devsym.c 1960abbb234b97e9b920f07e99503fc04b443f62bbc3c6ff2c2cea2133e3b8a2
F src/upsert.c 47edd408cc73f8d3c00a140550d1ad180b407c146285947969dd09874802bf88
F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5
F src/util.c d9eb0a6c4aae1b00a7369eadd7ca0bbe946cb4c953b6751aa20d357c2f482157
-F src/vacuum.c 36e7d21a20c0bf6ef4ef7c399d192b5239410b7c4d3c1070fba4e30810d0b855
-F src/vdbe.c 800c69a80609b4837d3403e15092e585f356711823529ad1c04fe5ca8e9f9aec
+F src/vacuum.c 4879e47105cea12bae7731d353cdee6cba6834e83f1f649483c34719750656ed
- F src/vdbe.c e74bd7487be55244861c383578b5e701ffd6ca202ac7fa49215f3c8d9fe0105e
- F src/vdbe.h e3f43bcc27ff30b0f25a6104d0cb5657e1c4b5e1b5cd2dd2216d5bcc2156a746
- F src/vdbeInt.h 42d3e65ea0c664f6d9bc9a53de645c0baf8566ff0188409ff3b8d2abc327bc17
- F src/vdbeapi.c 765a0bbe01311626417de6cb743f7f25f9f98435c98a9df4bb0714d11014633d
- F src/vdbeaux.c a41de57f1f774c05e41ecac0974728c6cd01d132b62d734d77541b31836967b1
++F src/vdbe.c 5040613bad982c0e93e8bcf54e19b9b953ca59e7a752e7f4f1741232e4f7948d
+ F src/vdbe.h 9c8c245fa3785266c269ab02c135c836ff49a307612186686bcdae500f409945
+ F src/vdbeInt.h 6b5cbd338dc9aaad343fb11b455e47463b0474d9f79710f50e647158941146e0
+ F src/vdbeapi.c af4a3de00d1851bcbc55b85dfbe52849aa2b1e17b4a5a1f3d9c257df7af361ff
-F src/vdbeaux.c c2d65c763b0811afe409e02e9d0d1f300c6e97892474fc94eec3da71955cd418
++F src/vdbeaux.c 82a912312d2c0fea4d03016634b674944fbf04e2d58eb1e23d33b93fb3e32c07
F src/vdbeblob.c f5c70f973ea3a9e915d1693278a5f890dc78594300cf4d54e64f2b0917c94191
- F src/vdbemem.c 803323406d8623a7619ea5d5f74016697eeaed19c02b98ce9c3013e77dbe1c38
+ F src/vdbemem.c a699a1d7ccc3f94cdff69ddf35d5f7540dbf52ca44cf040eda3c87520e67858c
F src/vdbesort.c 731a09e5cb9e96b70c394c1b7cf3860fbe84acca7682e178615eb941a3a0ef2f
F src/vdbetrace.c 79d6dbbc479267b255a7de8080eee6e729928a0ef93ed9b0bfa5618875b48392
F src/vtab.c 10ea07dec111de6fb0a4fc87a7ffa4c65fdc088a19dbfaf7d6f2b128f2e8eb7b
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
- F src/wal.c 05d9364fefacdff639b7fb63b1113317e045e2ae5c7908fa50157f9f24883257
-F src/wal.c d44a0811afd2155b1157c38b33141d4ac028fda6232485bed664015bb05819ca
-F src/wal.h 8de5d2d3de0956d6f6cb48c83a4012d5f227b8fe940f3a349a4b7e85ebcb492a
++F src/wal.c a49089219d0421ad172918ec8d7a3c637ee6f1c56026e45f0678073d9e346097
+F src/wal.h 1713fefe4587678c295bbeb91c4e7442998ad74f19249869ce49dda9e8ce5d53
- F src/walker.c da987a20d40145c0a03c07d8fefcb2ed363becc7680d0500d9c79915591f5b1f
- F src/where.c 60ec752fcbe9f9e0271ac60548d159a540a1ee47a4f9fedc85e88a3d0e392dd1
- F src/whereInt.h cbae2bcd37cfebdb7812a8b188cdb19634ced2b9346470d1c270556b0c33ea53
- F src/wherecode.c 728c7f70731430ccdac807a79969873e1af6968bf1c4745dff3f9dd35f636cc8
- F src/whereexpr.c e90b2e76dcabc81edff56633bf281bc01d93b71e0c81482dc06925ce39f5844a
+ F src/walker.c ba7225773931760cf60bf22f34d0cce2588df7ce5ce0f215a52eb88234b55ac4
+ F src/where.c 0bcbf9e191ca07f9ea2008aa80e70ded46bcdffd26560c83397da501f00aece6
+ F src/whereInt.h b90ef9b9707ef750eab2a7a080c48fb4900315033274689def32d0cf5a81ebe4
+ F src/wherecode.c 3317f2b083a66d3e65a03edf316ade4ccb0a99c9956273282ebb579b95d4ba96
+ F src/whereexpr.c 571618c67a3eb5ce0f1158c2792c1aee9b4a4a264392fc4fb1b35467f80abf9a
+ F src/window.c df2bc08168ec3d7509d4674b0e52f90f83011425e0d6519240cec051d16cbd62
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d
F tool/mkautoconfamal.sh 422fc365358a2e92876ffc62971a0ff28ed472fc8bcf9de0df921c736fdeca5e
F tool/mkccode.tcl 86463e68ce9c15d3041610fedd285ce32a5cf7a58fc88b3202b8b76837650dbe x
F tool/mkctimec.tcl dd183b73ae1c28249669741c250525f0407e579a70482371668fd5f130d9feb3
- F tool/mkkeywordhash.c d4ce28d8f485b247af20489c9813a1409e1950ea6e0cc6a64380c0f51ff54491
-F tool/mkkeywordhash.c 1f7f2ac1d9f262c08b67faaca47e6a68262ff39113fa4b27d1db2843b4c33e73
++F tool/mkkeywordhash.c 1e5cfcf4cd692ae21e7555604218097a1ee79dad3e366496e5236876255bfcc1
F tool/mkmsvcmin.tcl cad0c7b54d7dd92bc87d59f36d4cc4f070eb2e625f14159dc2f5c4204e6a13ea
F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c
F tool/mkopcodeh.tcl 17d1ccc05a926e19e3a9679ea3e4d1aaa15ba753e2fa7363e6e81c80e0ef8b86
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
- P ae86cf60b6648a7ec789e233c9b0cc826efbbb0f301140b4848dc84d691ccd4f a10662aa915ae2b5a78b3e10920350d32255b2d6b1a8aac0aba1ad173b07ed2b
- R 36fc8295204ff42f76d67b24d638703a
-P 52559ad58ce412af40f1f34e80bfe9fadc6a93f3ca0cfaf69f94d615bbb99831
-R af867e8f2830341644b32312137b8d37
--U drh
- Z eb5435ab41fb96e776ef538a27cf0946
-Z 9b7ea72c6158564396d1f1dc7cb1a0c3
++P d7299bfeb1eb031d6106b46139715047fe759d27b34b617ca43f2cd377b8188e 0f6ec605e131ab3d53b9df32af0a3207146a9abbd22dcabd6ef050b92f96735d
++R 0d6f4d8287e317704b4a5f08da2d9f1e
++U dan
++Z f474088e9eb99b2bb00c76e557edc5ba
** There can only be a single writer active at a time.
*/
int sqlite3WalBeginWriteTransaction(Wal *pWal){
+ int 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;
+}
+
+/*
+** 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 );
+ 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;
+}
- /* Cannot start a write transaction without first holding a read
- ** transaction. */
- assert( pWal->readLock>=0 );
- assert( pWal->writeLock==0 && pWal->iReCksum==0 );
- if( pWal->readOnly ){
- return SQLITE_READONLY;
- }
+#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 *pPage1,
+ Bitvec *pAllRead,
+ Pgno *piConflict
+){
+ Pager *pPager = pPage1->pPager;
+ int rc = walWriteLock(pWal);
- /* Only one writer allowed at a time. Get the write lock. Return
- ** SQLITE_BUSY if unable.
+ /* 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.
*/
- rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1);
- if( rc ){
- return rc;
- }
- pWal->writeLock = 1;
+ 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 iHash;
+ int iLastHash = walFramePage(head.mxFrame);
+ u32 iFirst = pWal->hdr.mxFrame+1; /* First wal frame to check */
+ if( memcmp(pWal->hdr.aSalt, (u32*)head.aSalt, sizeof(u32)*2) ){
+ assert( pWal->readLock==0 );
+ iFirst = 1;
+ }
+ for(iHash=walFramePage(iFirst); iHash<=iLastHash; iHash++){
- volatile ht_slot *aHash;
- volatile u32 *aPgno;
- u32 iZero;
++ WalHashLoc sLoc;
- rc = walHashGet(pWal, iHash, &aHash, &aPgno, &iZero);
- /* 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( memcmp(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr))!=0 ){
- walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
- pWal->writeLock = 0;
- rc = SQLITE_BUSY_SNAPSHOT;
++ rc = walHashGet(pWal, iHash, &sLoc);
+ if( rc==SQLITE_OK ){
+ u32 i, iMin, iMax;
- assert( head.mxFrame>=iZero );
- iMin = (iZero >= iFirst) ? 1 : (iFirst - iZero);
++ assert( head.mxFrame>=sLoc.iZero );
++ iMin = (sLoc.iZero >= iFirst) ? 1 : (iFirst - sLoc.iZero);
+ iMax = (iHash==0) ? HASHTABLE_NPAGE_ONE : HASHTABLE_NPAGE;
- if( iMax>(head.mxFrame-iZero) ) iMax = (head.mxFrame-iZero);
++ if( iMax>(head.mxFrame-sLoc.iZero) ) iMax = (head.mxFrame-sLoc.iZero);
+ for(i=iMin; rc==SQLITE_OK && i<=iMax; i++){
+ PgHdr *pPg;
- if( aPgno[i]==1 ){
++ if( sLoc.aPgno[i]==1 ){
+ /* Check that the schema cookie has not been modified. If
+ ** it has not, the commit can proceed. */
+ u8 aNew[4];
+ u8 *aOld = &((u8*)pPage1->pData)[40];
+ int sz;
+ i64 iOffset;
+ sz = pWal->hdr.szPage;
+ sz = (sz&0xfe00) + ((sz&0x0001)<<16);
- iOffset = walFrameOffset(i+iZero, sz) + WAL_FRAME_HDRSIZE + 40;
++ iOffset = walFrameOffset(i+sLoc.iZero, sz) + WAL_FRAME_HDRSIZE+40;
+ rc = sqlite3OsRead(pWal->pWalFd, aNew, sizeof(aNew), iOffset);
+ if( rc==SQLITE_OK && memcmp(aOld, aNew, sizeof(aNew)) ){
+ rc = SQLITE_BUSY_SNAPSHOT;
+ }
- }else if( sqlite3BitvecTestNotNull(pAllRead, aPgno[i]) ){
- *piConflict = aPgno[i];
++ }else if( sqlite3BitvecTestNotNull(pAllRead, sLoc.aPgno[i]) ){
++ *piConflict = sLoc.aPgno[i];
+ rc = SQLITE_BUSY_SNAPSHOT;
- }else if( (pPg = sqlite3PagerLookup(pPager, aPgno[i])) ){
++ }else if( (pPg = sqlite3PagerLookup(pPager, sLoc.aPgno[i])) ){
+ /* 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;
+}
+
+/* !defined(SQLITE_OMIT_CONCURRENT)
+**
+** This function is called as part of committing an CONCURRENT transaction.
+** It is assumed that sqlite3WalLockForCommit() has already been successfully
+** called and so (a) the WRITER lock is held and (b) it is known that the
+** wal-index-header stored in shared memory is not corrupt.
+**
+** Before returning, this function upgrades the client so that it is
+** operating on the database snapshot currently at the head of the wal file
+** (even if the CONCURRENT transaction ran against an older snapshot).
+**
+** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
+*/
+int sqlite3WalUpgradeSnapshot(Wal *pWal){
+ int rc = SQLITE_OK;
+ assert( pWal->writeLock );
+ memcpy(&pWal->hdr, (void*)walIndexHdr(pWal), sizeof(WalIndexHdr));
+
+ /* If this client has its read-lock on slot aReadmark[0] and the entire
+ ** wal has not been checkpointed, switch it to a different slot. Otherwise
+ ** any reads performed between now and committing the transaction will
+ ** read from the old snapshot - not the one just upgraded to. */
+ if( pWal->readLock==0 && pWal->hdr.mxFrame!=walCkptInfo(pWal)->nBackfill ){
+ rc = walUpgradeReadlock(pWal);
+ }
return rc;
}
+#endif /* SQLITE_OMIT_CONCURRENT */
/*
** End a write transaction. The commit has already been done. This