1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-08 14:02:16 +03:00

Take advantage of atomic-write capabilities in the F2FS filesystem when the

database is stored on such a filesystem.  This is a compile-time option
activated using SQLITE_ENABLE_BATCH_ATOMIC_WRITE.

FossilOrigin-Name: 24190b221f73472dafaead6de101b4debc2c91c1ca28d70b45a38df5bb61fb39
This commit is contained in:
drh
2017-08-01 14:16:15 +00:00
19 changed files with 740 additions and 183 deletions

View File

@@ -1,5 +1,5 @@
C Allow\sATTACH\sand\sDETACH\sinside\sof\sa\stransaction. C Take\sadvantage\sof\satomic-write\scapabilities\sin\sthe\sF2FS\sfilesystem\swhen\sthe\ndatabase\sis\sstored\son\ssuch\sa\sfilesystem.\s\sThis\sis\sa\scompile-time\soption\nactivated\susing\sSQLITE_ENABLE_BATCH_ATOMIC_WRITE.
D 2017-08-01T00:20:34.182 D 2017-08-01T14:16:15.157
F Makefile.in d9873c9925917cca9990ee24be17eb9613a668012c85a343aef7e5536ae266e8 F Makefile.in d9873c9925917cca9990ee24be17eb9613a668012c85a343aef7e5536ae266e8
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc 02b469e9dcd5b7ee63fc1fb05babc174260ee4cfa4e0ef2e48c3c6801567a016 F Makefile.msc 02b469e9dcd5b7ee63fc1fb05babc174260ee4cfa4e0ef2e48c3c6801567a016
@@ -401,7 +401,7 @@ F src/btreeInt.h 97700795edf8a43245720414798b7b29d8e465aef46bf301ffacd431910c0da
F src/build.c f65f86520aa877853125565e42c59c5c49851a4733392931777fb1aace4aedfd F src/build.c f65f86520aa877853125565e42c59c5c49851a4733392931777fb1aace4aedfd
F src/callback.c 930648a084a3adc741c6471adfbdc50ba47ba3542421cb80a26f259f467de65e F src/callback.c 930648a084a3adc741c6471adfbdc50ba47ba3542421cb80a26f259f467de65e
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c 928954802b1397d9fb1378c7eb702c94b4735bbab1d5793e21b6a77734f56a1b F src/ctime.c ff1be3eed7bdd75aaca61ca8dc848f7c9f850ef2fb9cb56f2734e922a098f9c0
F src/date.c 48f743d88bbe88f848532d333cca84f26e52a4f217e86f86be7fc1b919c33d74 F src/date.c 48f743d88bbe88f848532d333cca84f26e52a4f217e86f86be7fc1b919c33d74
F src/dbstat.c 7a4ba8518b6369ef3600c49cf9c918ad979acba610b2aebef1b656d649b96720 F src/dbstat.c 7a4ba8518b6369ef3600c49cf9c918ad979acba610b2aebef1b656d649b96720
F src/delete.c 939bd15e6b54b82b951e1c0ffc2ff2b4ab579196780a1f6d394e47bd6f799b6c F src/delete.c 939bd15e6b54b82b951e1c0ffc2ff2b4ab579196780a1f6d394e47bd6f799b6c
@@ -424,7 +424,7 @@ F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3 F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3
F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a
F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944 F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944
F src/memjournal.c 95752936c11dc6995672d1dd783cd633eea0cc95 F src/memjournal.c 6f3d36a0a8f72f48f6c3c722f04301ac64f2515435fa42924293e46fc7994661
F src/msvc.h 4942752b6a253116baaa8de75256c51a459a5e81 F src/msvc.h 4942752b6a253116baaa8de75256c51a459a5e81
F src/mutex.c 8e45800ee78e0cd1f1f3fe8e398853307f4a085c F src/mutex.c 8e45800ee78e0cd1f1f3fe8e398853307f4a085c
F src/mutex.h 779d588e3b7756ec3ecf7d78cde1d84aba414f85 F src/mutex.h 779d588e3b7756ec3ecf7d78cde1d84aba414f85
@@ -436,10 +436,10 @@ F src/os.c add02933b1dce7a39a005b00a2f5364b763e9a24
F src/os.h 8e976e59eb4ca1c0fca6d35ee803e38951cb0343 F src/os.h 8e976e59eb4ca1c0fca6d35ee803e38951cb0343
F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85 F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85
F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586 F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
F src/os_unix.c 30e2c43e4955db990e5b5a81e901f8aa74cc8820 F src/os_unix.c 0681c6ef336fcb6a111f45b60a5faea38992ed6c4ae9fbd57a6f8e247724fa68
F src/os_win.c 2a6c73eef01c51a048cc4ddccd57f981afbec18a F src/os_win.c 2a6c73eef01c51a048cc4ddccd57f981afbec18a
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
F src/pager.c 14f6982c470c05b8e85575c69e9c1712010602e20400f8670d8699e21283e0e4 F src/pager.c 1e63b0299cf123cf38c48413ec03190f56c1e7d0ccc6573c467d8ac240b898e9
F src/pager.h f2a99646c5533ffe11afa43e9e0bea74054e4efa F src/pager.h f2a99646c5533ffe11afa43e9e0bea74054e4efa
F src/parse.y e384cb73f99e1b074085c974b37f4d830e885359e4b60837e30f7d67c16ba65b F src/parse.y e384cb73f99e1b074085c974b37f4d830e885359e4b60837e30f7d67c16ba65b
F src/pcache.c 62835bed959e2914edd26afadfecce29ece0e870 F src/pcache.c 62835bed959e2914edd26afadfecce29ece0e870
@@ -455,20 +455,20 @@ F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
F src/select.c 31b35ddf55f1021f7148a01306984b057c11ebb6e3463d94677225e0a1e301a3 F src/select.c 31b35ddf55f1021f7148a01306984b057c11ebb6e3463d94677225e0a1e301a3
F src/shell.c bd6a37cbe8bf64ef6a6a74fdc50f067d3148149b4ce2b4d03154663e66ded55f F src/shell.c bd6a37cbe8bf64ef6a6a74fdc50f067d3148149b4ce2b4d03154663e66ded55f
F src/shell.c.in b5725acacba95ccefa57b6d068f710e29ba8239c3aa704628a1902a1f729c175 F src/shell.c.in b5725acacba95ccefa57b6d068f710e29ba8239c3aa704628a1902a1f729c175
F src/sqlite.h.in 0e2603c23f0747c5660669f946e231730af000c76d1653b153dcf2c26fce0a6b F src/sqlite.h.in 72f1775c7a134f9e358eedafe1ebc703c28b0d705d976464ddbf6a9219448952
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 0f9f72b86a3792314f5db7a1dfbc2c82376bcd8d0919ceb80637bca126ec3c68 F src/sqlite3ext.h 0f9f72b86a3792314f5db7a1dfbc2c82376bcd8d0919ceb80637bca126ec3c68
F src/sqliteInt.h a1b8df420e8fa80fda9414ab7784d6e62271e1f7d65034ffd3e906ee6f014def F src/sqliteInt.h fe648fe59c71f7f44b5e89cf7cff0b96d81bd718263517c6895014632357df7b
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
F src/status.c a9e66593dfb28a9e746cba7153f84d49c1ddc4b1 F src/status.c a9e66593dfb28a9e746cba7153f84d49c1ddc4b1
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
F src/tclsqlite.c 487951d81f9704800fd9f0ffdaa2f935a83ccb6be3575c2c4ef83e4789b4c828 F src/tclsqlite.c 487951d81f9704800fd9f0ffdaa2f935a83ccb6be3575c2c4ef83e4789b4c828
F src/test1.c cfb78b728b37ae3a2b14fe1b3a6c766e0da41370eda112594e698c94011b622e F src/test1.c 8513b17ca4a7a9ba28748535d178b6e472ec7394ae0eea53907f2d3bcdbab2df
F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5 F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5
F src/test3.c b8434949dfb8aff8dfa082c8b592109e77844c2135ed3c492113839b6956255b F src/test3.c b8434949dfb8aff8dfa082c8b592109e77844c2135ed3c492113839b6956255b
F src/test4.c 18ec393bb4d0ad1de729f0b94da7267270f3d8e6 F src/test4.c 18ec393bb4d0ad1de729f0b94da7267270f3d8e6
F src/test5.c 328aae2c010c57a9829d255dc099d6899311672d F src/test5.c 328aae2c010c57a9829d255dc099d6899311672d
F src/test6.c 004ad42f121f693b8cbe060d1a330678abc61620 F src/test6.c e8d839fbc552ce044bec8234561a2d5b8819b48e29548ad0ba400471697946a8
F src/test7.c 5612e9aecf934d6df7bba6ce861fdf5ba5456010 F src/test7.c 5612e9aecf934d6df7bba6ce861fdf5ba5456010
F src/test8.c 4f4904721167b32f7a4fa8c7b32a07a673d6cc86 F src/test8.c 4f4904721167b32f7a4fa8c7b32a07a673d6cc86
F src/test9.c 12e5ba554d2d1cbe0158f6ab3f7ffcd7a86ee4e5 F src/test9.c 12e5ba554d2d1cbe0158f6ab3f7ffcd7a86ee4e5
@@ -481,7 +481,7 @@ F src/test_btree.c 8b2dc8b8848cf3a4db93f11578f075e82252a274
F src/test_config.c abf6fc1fe9d041b699578c42e3db81f8831c4f5b804f1927958102ee8f2b773e F src/test_config.c abf6fc1fe9d041b699578c42e3db81f8831c4f5b804f1927958102ee8f2b773e
F src/test_delete.c e2fe07646dff6300b48d49b2fee2fe192ed389e834dd635e3b3bac0ce0bf9f8f F src/test_delete.c e2fe07646dff6300b48d49b2fee2fe192ed389e834dd635e3b3bac0ce0bf9f8f
F src/test_demovfs.c a0c3bdd45ed044115c2c9f7779e56eafff18741e F src/test_demovfs.c a0c3bdd45ed044115c2c9f7779e56eafff18741e
F src/test_devsym.c 4e58dec2602d8e139ca08659f62a62450587cb58 F src/test_devsym.c 1960abbb234b97e9b920f07e99503fc04b443f62bbc3c6ff2c2cea2133e3b8a2
F src/test_fs.c 35a2f7dd8a915900873386331386d9ba1ae1b5026d74fd20c2807bc76221f291 F src/test_fs.c 35a2f7dd8a915900873386331386d9ba1ae1b5026d74fd20c2807bc76221f291
F src/test_func.c a4fdab3363b436c1b12660e9362ce3f3782b7b5e F src/test_func.c a4fdab3363b436c1b12660e9362ce3f3782b7b5e
F src/test_hexio.c 1d4469ca61ab202a1fcec6543f584d2407205e8d F src/test_hexio.c 1d4469ca61ab202a1fcec6543f584d2407205e8d
@@ -572,6 +572,7 @@ F test/async3.test d73a062002376d7edc1fe3edff493edbec1fc2f7
F test/async4.test 1787e3952128aa10238bf39945126de7ca23685a F test/async4.test 1787e3952128aa10238bf39945126de7ca23685a
F test/async5.test 383ab533fdb9f7ad228cc99ee66e1acb34cc0dc0 F test/async5.test 383ab533fdb9f7ad228cc99ee66e1acb34cc0dc0
F test/atof1.test ff0b0156fd705b67c506e1f2bfe9e26102bea9bd F test/atof1.test ff0b0156fd705b67c506e1f2bfe9e26102bea9bd
F test/atomic.test 065a453dde33c77ff586d91ccaa6ed419829d492dbb1a5694b8a09f3f9d7d061
F test/attach.test f4b8918ba2f3e88e6883b8452340545f10a1388af808343c37fc5c577be8281c F test/attach.test f4b8918ba2f3e88e6883b8452340545f10a1388af808343c37fc5c577be8281c
F test/attach2.test 567047a7607aae8ebb3794642ebb168abe66b4af366fcd0cf7f616a1495cd43f F test/attach2.test 567047a7607aae8ebb3794642ebb168abe66b4af366fcd0cf7f616a1495cd43f
F test/attach3.test c59d92791070c59272e00183b7353eeb94915976 F test/attach3.test c59d92791070c59272e00183b7353eeb94915976
@@ -754,7 +755,7 @@ F test/exists.test 79a75323c78f02bbe9c251ea502a092f9ef63dac
F test/expr.test 66a2c9ac34f74f036faa4092f5402c7d3162fc93 F test/expr.test 66a2c9ac34f74f036faa4092f5402c7d3162fc93
F test/extension01.test 00d13cec817f331a687a243e0e5a2d87b0e358c9 F test/extension01.test 00d13cec817f331a687a243e0e5a2d87b0e358c9
F test/extraquick.test cb254400bd42bfb777ff675356aabf3287978f79 F test/extraquick.test cb254400bd42bfb777ff675356aabf3287978f79
F test/fallocate.test 3e979af17dfa7e5e9dda5eba1a696c04fa9d47f7 F test/fallocate.test 87b5e43c872b7e69cd80b7b8813eb102b571a75d45dda24e38b65537bcc85733
F test/filectrl.test 6e871c2d35dead1d9a88e176e8d2ca094fec6bb3 F test/filectrl.test 6e871c2d35dead1d9a88e176e8d2ca094fec6bb3
F test/filefmt.test f393e80c4b8d493b7a7f8f3809a8425bbf4292af1f5140f01cb1427798a2bbd4 F test/filefmt.test f393e80c4b8d493b7a7f8f3809a8425bbf4292af1f5140f01cb1427798a2bbd4
F test/fkey1.test ba64806ff9a04eecab2679caad377ae99a5e94e4 F test/fkey1.test ba64806ff9a04eecab2679caad377ae99a5e94e4
@@ -1029,7 +1030,7 @@ F test/minmax.test 6751e87b409fe11b02e70a306d846fa544e25a41
F test/minmax2.test b44bae787fc7b227597b01b0ca5575c7cb54d3bc F test/minmax2.test b44bae787fc7b227597b01b0ca5575c7cb54d3bc
F test/minmax3.test cc1e8b010136db0d01a6f2a29ba5a9f321034354 F test/minmax3.test cc1e8b010136db0d01a6f2a29ba5a9f321034354
F test/minmax4.test 936941484ebdceb8adec7c86b6cd9b6e5e897c1f F test/minmax4.test 936941484ebdceb8adec7c86b6cd9b6e5e897c1f
F test/misc1.test 6430dabfb4b4fa480633590118964201f94d3ccc F test/misc1.test 51ec3f56a2a7965de226964cff856695e743186826561536647f1e8b7d1d0eb3
F test/misc2.test 00d7de54eda90e237fc9a38b9e5ccc769ebf6d4d F test/misc2.test 00d7de54eda90e237fc9a38b9e5ccc769ebf6d4d
F test/misc3.test cf3dda47d5dda3e53fc5804a100d3c82be736c9d F test/misc3.test cf3dda47d5dda3e53fc5804a100d3c82be736c9d
F test/misc4.test 0d8be3466adf123a7791a66ba2bc8e8d229e87f3 F test/misc4.test 0d8be3466adf123a7791a66ba2bc8e8d229e87f3
@@ -1087,7 +1088,7 @@ F test/parser1.test 391b9bf9a229547a129c61ac345ed1a6f5eb1854
F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b
F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442 F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
F test/permutations.test 5e2e5439642898e0947ced066ad09b82bd817ddfb83dc71291b4c957efc84b62 F test/permutations.test 3b94f8fd431d39fac4952eb5dc38e1bb2b4518e1ac967d66f5abc815c104aeb6
F test/pragma.test f274259d6393b6681eb433beb8dd39a26ec06a4431052a4880b43b84912a3f58 F test/pragma.test f274259d6393b6681eb433beb8dd39a26ec06a4431052a4880b43b84912a3f58
F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
F test/pragma3.test 14c12bc5352b1e100e0b6b44f371053a81ccf8ed F test/pragma3.test 14c12bc5352b1e100e0b6b44f371053a81ccf8ed
@@ -1113,7 +1114,7 @@ F test/regexp2.test 40e894223b3d6672655481493f1be12012f2b33c
F test/reindex.test 44edd3966b474468b823d481eafef0c305022254 F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
F test/releasetest.tcl 7bb585433ce7fb2a2c255ae4b5e24f1bc27fe177ec1120f886cc4852f48f5ee9 x F test/releasetest.tcl 7bb585433ce7fb2a2c255ae4b5e24f1bc27fe177ec1120f886cc4852f48f5ee9 x
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
F test/rollback.test 458fe73eb3ffdfdf9f6ba3e9b7350a6220414dea F test/rollback.test f580934279800d480a19176c6b44909df31ce7ad45267ea475a541daa522f3d3
F test/rollback2.test 8435d6ff0f13f51d2a4181c232e706005fa90fc5 F test/rollback2.test 8435d6ff0f13f51d2a4181c232e706005fa90fc5
F test/rollbackfault.test 0e646aeab8840c399cfbfa43daab46fd609cf04a F test/rollbackfault.test 0e646aeab8840c399cfbfa43daab46fd609cf04a
F test/rowallock.test 3f88ec6819489d0b2341c7a7528ae17c053ab7cc F test/rowallock.test 3f88ec6819489d0b2341c7a7528ae17c053ab7cc
@@ -1233,7 +1234,7 @@ F test/superlock.test ec94f0556b6488d97f71c79f9061ae08d9ab8f12
F test/symlink.test c9ebe7330d228249e447038276bfc8a7b22f4849 F test/symlink.test c9ebe7330d228249e447038276bfc8a7b22f4849
F test/sync.test 2f84bdbc2b2df1fcb0220575b4b9f8cea94b7529 F test/sync.test 2f84bdbc2b2df1fcb0220575b4b9f8cea94b7529
F test/sync2.test 6be8ed007fa063b147773c1982b5bdba97a32badc536bdc6077eff5cf8710ece F test/sync2.test 6be8ed007fa063b147773c1982b5bdba97a32badc536bdc6077eff5cf8710ece
F test/syscall.test 7a60601770172a8014a4d222d5f3d95a5d2b5c47fbb0374e2698e89c99e37256 F test/syscall.test a39d9a36f852ae6e4800f861bc2f2e83f68bbc2112d9399931ecfadeabd2d69d
F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04 F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04
F test/tabfunc01.test c47171c36b3d411df2bd49719dcaa5d034f8d277477fd41d253940723b969a51 F test/tabfunc01.test c47171c36b3d411df2bd49719dcaa5d034f8d277477fd41d253940723b969a51
F test/table.test b708f3e5fa2542fa51dfab21fc07b36ea445cb2f F test/table.test b708f3e5fa2542fa51dfab21fc07b36ea445cb2f
@@ -1247,7 +1248,7 @@ F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
F test/temptable2.test cd396beb41117a5302fff61767c35fa4270a0d5e F test/temptable2.test cd396beb41117a5302fff61767c35fa4270a0d5e
F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637 F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
F test/tester.tcl 581f0185434daf7026ccede4c07e8d1479186ec5 F test/tester.tcl eb7ec55fe074a909423c1de701f7c545417b8aa96787b8c3e7a79203f2cebec8
F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5 F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5
F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58 F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7 F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
@@ -1543,6 +1544,7 @@ F test/without_rowid4.test 4e08bcbaee0399f35d58b5581881e7a6243d458a
F test/without_rowid5.test 89b1c587bd92a0590e440da33e7666bf4891572a F test/without_rowid5.test 89b1c587bd92a0590e440da33e7666bf4891572a
F test/without_rowid6.test 1f99644e6508447fb050f73697350c7ceca3392e F test/without_rowid6.test 1f99644e6508447fb050f73697350c7ceca3392e
F test/wordcount.c 06efb84b7c48a4973c2c24ea06c93d00bce24389 F test/wordcount.c 06efb84b7c48a4973c2c24ea06c93d00bce24389
F test/writecrash.test f1da7f7adfe8d7f09ea79b42e5ca6dcc41102f27f8e334ad71539501ddd910cc
F test/zeroblob.test 3857870fe681b8185654414a9bccfde80b62a0fa F test/zeroblob.test 3857870fe681b8185654414a9bccfde80b62a0fa
F test/zerodamage.test e59a56443d6298ecf7435f618f0b27654f0c849e F test/zerodamage.test e59a56443d6298ecf7435f618f0b27654f0c849e
F tool/GetFile.cs a15e08acb5dd7539b75ba23501581d7c2b462cb5 F tool/GetFile.cs a15e08acb5dd7539b75ba23501581d7c2b462cb5
@@ -1638,8 +1640,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 0c77935cf9949099d834ec51384c1d4dcdaf7b4422c859c9fce6d3cb3bde2645 ac1fd6beb6c804af5faf1e06a51177a8316007ff9e718c398bd7a24d2ecc4ed3 P 95e8f31658254dd2df3eeaae337aff0fe2125d170ae966c74f4fc70400e099b1 4c0520d4df7473eb4cc764774df7d99bb96cf067ac224755e09f0df47fb2a810
R 0baf627cb47530fd453d60ae728f6e16 R 785ca20553bf2e0c19860d1453d0c98e
T +closed ac1fd6beb6c804af5faf1e06a51177a8316007ff9e718c398bd7a24d2ecc4ed3
U drh U drh
Z 5c8b473184a93b34c81627bf252d49c0 Z 2380a4cbd6dbbedaa37eda54fb01fd11

View File

@@ -1 +1 @@
95e8f31658254dd2df3eeaae337aff0fe2125d170ae966c74f4fc70400e099b1 24190b221f73472dafaead6de101b4debc2c91c1ca28d70b45a38df5bb61fb39

View File

@@ -184,6 +184,9 @@ static const char * const sqlite3azCompileOpt[] = {
#if SQLITE_ENABLE_ATOMIC_WRITE #if SQLITE_ENABLE_ATOMIC_WRITE
"ENABLE_ATOMIC_WRITE", "ENABLE_ATOMIC_WRITE",
#endif #endif
#if SQLITE_ENABLE_BATCH_ATOMIC_WRITE
"ENABLE_BATCH_ATOMIC_WRITE",
#endif
#if SQLITE_ENABLE_CEROD #if SQLITE_ENABLE_CEROD
"ENABLE_CEROD", "ENABLE_CEROD",
#endif #endif

View File

@@ -96,7 +96,8 @@ static int memjrnlRead(
int iChunkOffset; int iChunkOffset;
FileChunk *pChunk; FileChunk *pChunk;
#ifdef SQLITE_ENABLE_ATOMIC_WRITE #if defined(SQLITE_ENABLE_ATOMIC_WRITE) \
|| defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
if( (iAmt+iOfst)>p->endpoint.iOffset ){ if( (iAmt+iOfst)>p->endpoint.iOffset ){
return SQLITE_IOERR_SHORT_READ; return SQLITE_IOERR_SHORT_READ;
} }
@@ -215,7 +216,8 @@ static int memjrnlWrite(
** atomic-write optimization. In this case the first 28 bytes of the ** atomic-write optimization. In this case the first 28 bytes of the
** journal file may be written as part of committing the transaction. */ ** journal file may be written as part of committing the transaction. */
assert( iOfst==p->endpoint.iOffset || iOfst==0 ); assert( iOfst==p->endpoint.iOffset || iOfst==0 );
#ifdef SQLITE_ENABLE_ATOMIC_WRITE #if defined(SQLITE_ENABLE_ATOMIC_WRITE) \
|| defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
if( iOfst==0 && p->pFirst ){ if( iOfst==0 && p->pFirst ){
assert( p->nChunkSize>iAmt ); assert( p->nChunkSize>iAmt );
memcpy((u8*)p->pFirst->zChunk, zBuf, iAmt); memcpy((u8*)p->pFirst->zChunk, zBuf, iAmt);
@@ -384,17 +386,31 @@ void sqlite3MemJournalOpen(sqlite3_file *pJfd){
sqlite3JournalOpen(0, 0, pJfd, 0, -1); sqlite3JournalOpen(0, 0, pJfd, 0, -1);
} }
#ifdef SQLITE_ENABLE_ATOMIC_WRITE #if defined(SQLITE_ENABLE_ATOMIC_WRITE) \
|| defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
/* /*
** If the argument p points to a MemJournal structure that is not an ** If the argument p points to a MemJournal structure that is not an
** in-memory-only journal file (i.e. is one that was opened with a +ve ** in-memory-only journal file (i.e. is one that was opened with a +ve
** nSpill parameter), and the underlying file has not yet been created, ** nSpill parameter or as SQLITE_OPEN_MAIN_JOURNAL), and the underlying
** create it now. ** file has not yet been created, create it now.
*/ */
int sqlite3JournalCreate(sqlite3_file *p){ int sqlite3JournalCreate(sqlite3_file *pJfd){
int rc = SQLITE_OK; int rc = SQLITE_OK;
if( p->pMethods==&MemJournalMethods && ((MemJournal*)p)->nSpill>0 ){ MemJournal *p = (MemJournal*)pJfd;
rc = memjrnlCreateFile((MemJournal*)p); if( p->pMethod==&MemJournalMethods && (
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
p->nSpill>0
#else
/* While this appears to not be possible without ATOMIC_WRITE, the
** paths are complex, so it seems prudent to leave the test in as
** a NEVER(), in case our analysis is subtly flawed. */
NEVER(p->nSpill>0)
#endif
#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE
|| (p->flags & SQLITE_OPEN_MAIN_JOURNAL)
#endif
)){
rc = memjrnlCreateFile(p);
} }
return rc; return rc;
} }

View File

@@ -90,6 +90,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h> #include <unistd.h>
#include <time.h> #include <time.h>
#include <sys/time.h> #include <sys/time.h>
@@ -220,10 +221,8 @@ struct unixFile {
sqlite3_int64 mmapSizeMax; /* Configured FCNTL_MMAP_SIZE value */ sqlite3_int64 mmapSizeMax; /* Configured FCNTL_MMAP_SIZE value */
void *pMapRegion; /* Memory mapped region */ void *pMapRegion; /* Memory mapped region */
#endif #endif
#ifdef __QNXNTO__
int sectorSize; /* Device sector size */ int sectorSize; /* Device sector size */
int deviceCharacteristics; /* Precomputed device characteristics */ int deviceCharacteristics; /* Precomputed device characteristics */
#endif
#if SQLITE_ENABLE_LOCKING_STYLE #if SQLITE_ENABLE_LOCKING_STYLE
int openFlags; /* The flags specified at open() */ int openFlags; /* The flags specified at open() */
#endif #endif
@@ -328,6 +327,20 @@ static pid_t randomnessPid = 0;
# define lseek lseek64 # define lseek lseek64
#endif #endif
#ifdef __linux__
/*
** Linux-specific IOCTL magic numbers used for controlling F2FS
*/
#define F2FS_IOCTL_MAGIC 0xf5
#define F2FS_IOC_START_ATOMIC_WRITE _IO(F2FS_IOCTL_MAGIC, 1)
#define F2FS_IOC_COMMIT_ATOMIC_WRITE _IO(F2FS_IOCTL_MAGIC, 2)
#define F2FS_IOC_START_VOLATILE_WRITE _IO(F2FS_IOCTL_MAGIC, 3)
#define F2FS_IOC_ABORT_VOLATILE_WRITE _IO(F2FS_IOCTL_MAGIC, 5)
#define F2FS_IOC_GET_FEATURES _IOR(F2FS_IOCTL_MAGIC, 12, u32)
#define F2FS_FEATURE_ATOMIC_WRITE 0x0004
#endif /* __linux__ */
/* /*
** Different Unix systems declare open() in different ways. Same use ** Different Unix systems declare open() in different ways. Same use
** open(const char*,int,mode_t). Others use open(const char*,int,...). ** open(const char*,int,mode_t). Others use open(const char*,int,...).
@@ -500,6 +513,9 @@ static struct unix_syscall {
#endif #endif
#define osLstat ((int(*)(const char*,struct stat*))aSyscall[27].pCurrent) #define osLstat ((int(*)(const char*,struct stat*))aSyscall[27].pCurrent)
{ "ioctl", (sqlite3_syscall_ptr)ioctl, 0 },
#define osIoctl ((int(*)(int,int,...))aSyscall[28].pCurrent)
}; /* End of the overrideable system calls */ }; /* End of the overrideable system calls */
@@ -3777,6 +3793,21 @@ static int unixGetTempname(int nBuf, char *zBuf);
static int unixFileControl(sqlite3_file *id, int op, void *pArg){ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
unixFile *pFile = (unixFile*)id; unixFile *pFile = (unixFile*)id;
switch( op ){ switch( op ){
#if defined(__linux__) && defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
case SQLITE_FCNTL_BEGIN_ATOMIC_WRITE: {
int rc = osIoctl(pFile->h, F2FS_IOC_START_ATOMIC_WRITE);
return rc ? SQLITE_IOERR_BEGIN_ATOMIC : SQLITE_OK;
}
case SQLITE_FCNTL_COMMIT_ATOMIC_WRITE: {
int rc = osIoctl(pFile->h, F2FS_IOC_COMMIT_ATOMIC_WRITE);
return rc ? SQLITE_IOERR_COMMIT_ATOMIC : SQLITE_OK;
}
case SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE: {
int rc = osIoctl(pFile->h, F2FS_IOC_ABORT_VOLATILE_WRITE);
return rc ? SQLITE_IOERR_ROLLBACK_ATOMIC : SQLITE_OK;
}
#endif /* __linux__ && SQLITE_ENABLE_BATCH_ATOMIC_WRITE */
case SQLITE_FCNTL_LOCKSTATE: { case SQLITE_FCNTL_LOCKSTATE: {
*(int*)pArg = pFile->eFileLock; *(int*)pArg = pFile->eFileLock;
return SQLITE_OK; return SQLITE_OK;
@@ -3860,30 +3891,41 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
} }
/* /*
** Return the sector size in bytes of the underlying block device for ** If pFd->sectorSize is non-zero when this function is called, it is a
** the specified file. This is almost always 512 bytes, but may be ** no-op. Otherwise, the values of pFd->sectorSize and
** larger for some devices. ** pFd->deviceCharacteristics are set according to the file-system
** characteristics.
** **
** SQLite code assumes this function cannot fail. It also assumes that ** There are two versions of this function. One for QNX and one for all
** if two files are created in the same file-system directory (i.e. ** other systems.
** a database and its journal file) that the sector size will be the
** same for both.
*/ */
#ifndef __QNXNTO__ #ifndef __QNXNTO__
static int unixSectorSize(sqlite3_file *NotUsed){ static void setDeviceCharacteristics(unixFile *pFd){
UNUSED_PARAMETER(NotUsed); assert( pFd->deviceCharacteristics==0 || pFd->sectorSize!=0 );
return SQLITE_DEFAULT_SECTOR_SIZE; if( pFd->sectorSize==0 ){
} #if defined(__linux__) && defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
#endif int res;
u32 f = 0;
/* /* Check for support for F2FS atomic batch writes. */
** The following version of unixSectorSize() is optimized for QNX. res = osIoctl(pFd->h, F2FS_IOC_GET_FEATURES, &f);
*/ if( res==0 && (f & F2FS_FEATURE_ATOMIC_WRITE) ){
#ifdef __QNXNTO__ pFd->deviceCharacteristics = SQLITE_IOCAP_BATCH_ATOMIC;
}
#endif /* __linux__ && SQLITE_ENABLE_BATCH_ATOMIC_WRITE */
/* Set the POWERSAFE_OVERWRITE flag if requested. */
if( pFd->ctrlFlags & UNIXFILE_PSOW ){
pFd->deviceCharacteristics |= SQLITE_IOCAP_POWERSAFE_OVERWRITE;
}
pFd->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
}
}
#else
#include <sys/dcmd_blk.h> #include <sys/dcmd_blk.h>
#include <sys/statvfs.h> #include <sys/statvfs.h>
static int unixSectorSize(sqlite3_file *id){ static void setDeviceCharacteristics(unixFile *pFile){
unixFile *pFile = (unixFile*)id;
if( pFile->sectorSize == 0 ){ if( pFile->sectorSize == 0 ){
struct statvfs fsInfo; struct statvfs fsInfo;
@@ -3952,9 +3994,24 @@ static int unixSectorSize(sqlite3_file *id){
pFile->deviceCharacteristics = 0; pFile->deviceCharacteristics = 0;
pFile->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE; pFile->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
} }
return pFile->sectorSize;
} }
#endif /* __QNXNTO__ */ #endif
/*
** Return the sector size in bytes of the underlying block device for
** the specified file. This is almost always 512 bytes, but may be
** larger for some devices.
**
** SQLite code assumes this function cannot fail. It also assumes that
** if two files are created in the same file-system directory (i.e.
** a database and its journal file) that the sector size will be the
** same for both.
*/
static int unixSectorSize(sqlite3_file *id){
unixFile *pFd = (unixFile*)id;
setDeviceCharacteristics(pFd);
return pFd->sectorSize;
}
/* /*
** Return the device characteristics for the file. ** Return the device characteristics for the file.
@@ -3970,16 +4027,9 @@ static int unixSectorSize(sqlite3_file *id){
** available to turn it off and URI query parameter available to turn it off. ** available to turn it off and URI query parameter available to turn it off.
*/ */
static int unixDeviceCharacteristics(sqlite3_file *id){ static int unixDeviceCharacteristics(sqlite3_file *id){
unixFile *p = (unixFile*)id; unixFile *pFd = (unixFile*)id;
int rc = 0; setDeviceCharacteristics(pFd);
#ifdef __QNXNTO__ return pFd->deviceCharacteristics;
if( p->sectorSize==0 ) unixSectorSize(id);
rc = p->deviceCharacteristics;
#endif
if( p->ctrlFlags & UNIXFILE_PSOW ){
rc |= SQLITE_IOCAP_POWERSAFE_OVERWRITE;
}
return rc;
} }
#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 #if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
@@ -7598,7 +7648,7 @@ int sqlite3_os_init(void){
/* Double-check that the aSyscall[] array has been constructed /* Double-check that the aSyscall[] array has been constructed
** correctly. See ticket [bb3a86e890c8e96ab] */ ** correctly. See ticket [bb3a86e890c8e96ab] */
assert( ArraySize(aSyscall)==28 ); assert( ArraySize(aSyscall)==29 );
/* Register all VFSes defined in the aVfs[] array */ /* Register all VFSes defined in the aVfs[] array */
for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){ for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){

View File

@@ -947,6 +947,7 @@ static int assert_pager_state(Pager *p){
assert( isOpen(p->jfd) assert( isOpen(p->jfd)
|| p->journalMode==PAGER_JOURNALMODE_OFF || p->journalMode==PAGER_JOURNALMODE_OFF
|| p->journalMode==PAGER_JOURNALMODE_WAL || p->journalMode==PAGER_JOURNALMODE_WAL
|| (sqlite3OsDeviceCharacteristics(p->fd)&SQLITE_IOCAP_BATCH_ATOMIC)
); );
assert( pPager->dbOrigSize<=pPager->dbHintSize ); assert( pPager->dbOrigSize<=pPager->dbHintSize );
break; break;
@@ -958,6 +959,7 @@ static int assert_pager_state(Pager *p){
assert( isOpen(p->jfd) assert( isOpen(p->jfd)
|| p->journalMode==PAGER_JOURNALMODE_OFF || p->journalMode==PAGER_JOURNALMODE_OFF
|| p->journalMode==PAGER_JOURNALMODE_WAL || p->journalMode==PAGER_JOURNALMODE_WAL
|| (sqlite3OsDeviceCharacteristics(p->fd)&SQLITE_IOCAP_BATCH_ATOMIC)
); );
break; break;
@@ -1168,34 +1170,45 @@ static int pagerLockDb(Pager *pPager, int eLock){
} }
/* /*
** This function determines whether or not the atomic-write optimization ** This function determines whether or not the atomic-write or
** can be used with this pager. The optimization can be used if: ** atomic-batch-write optimizations can be used with this pager. The
** atomic-write optimization can be used if:
** **
** (a) the value returned by OsDeviceCharacteristics() indicates that ** (a) the value returned by OsDeviceCharacteristics() indicates that
** a database page may be written atomically, and ** a database page may be written atomically, and
** (b) the value returned by OsSectorSize() is less than or equal ** (b) the value returned by OsSectorSize() is less than or equal
** to the page size. ** to the page size.
** **
** The optimization is also always enabled for temporary files. It is ** If it can be used, then the value returned is the size of the journal
** an error to call this function if pPager is opened on an in-memory ** file when it contains rollback data for exactly one page.
** database.
** **
** If the optimization cannot be used, 0 is returned. If it can be used, ** The atomic-batch-write optimization can be used if OsDeviceCharacteristics()
** then the value returned is the size of the journal file when it ** returns a value with the SQLITE_IOCAP_BATCH_ATOMIC bit set. -1 is
** contains rollback data for exactly one page. ** returned in this case.
**
** If neither optimization can be used, 0 is returned.
*/ */
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
static int jrnlBufferSize(Pager *pPager){ static int jrnlBufferSize(Pager *pPager){
assert( !MEMDB ); assert( !MEMDB );
if( !pPager->tempFile ){
int dc; /* Device characteristics */
int nSector; /* Sector size */
int szPage; /* Page size */
assert( isOpen(pPager->fd) ); #if defined(SQLITE_ENABLE_ATOMIC_WRITE) \
dc = sqlite3OsDeviceCharacteristics(pPager->fd); || defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
nSector = pPager->sectorSize; int dc; /* Device characteristics */
szPage = pPager->pageSize;
assert( isOpen(pPager->fd) );
dc = sqlite3OsDeviceCharacteristics(pPager->fd);
#endif
#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE
if( dc&SQLITE_IOCAP_BATCH_ATOMIC ){
return -1;
}
#endif
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
{
int nSector = pPager->sectorSize;
int szPage = pPager->pageSize;
assert(SQLITE_IOCAP_ATOMIC512==(512>>8)); assert(SQLITE_IOCAP_ATOMIC512==(512>>8));
assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8)); assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8));
@@ -1205,11 +1218,11 @@ static int jrnlBufferSize(Pager *pPager){
} }
return JOURNAL_HDR_SZ(pPager) + JOURNAL_PG_SZ(pPager); return JOURNAL_HDR_SZ(pPager) + JOURNAL_PG_SZ(pPager);
}
#else
# define jrnlBufferSize(x) 0
#endif #endif
return 0;
}
/* /*
** If SQLITE_CHECK_PAGES is defined then we do some sanity checking ** If SQLITE_CHECK_PAGES is defined then we do some sanity checking
** on the cache using a hash function. This is used for testing ** on the cache using a hash function. This is used for testing
@@ -2012,7 +2025,9 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
} }
releaseAllSavepoints(pPager); releaseAllSavepoints(pPager);
assert( isOpen(pPager->jfd) || pPager->pInJournal==0 ); assert( isOpen(pPager->jfd) || pPager->pInJournal==0
|| (sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_BATCH_ATOMIC)
);
if( isOpen(pPager->jfd) ){ if( isOpen(pPager->jfd) ){
assert( !pagerUseWal(pPager) ); assert( !pagerUseWal(pPager) );
@@ -4567,6 +4582,13 @@ static int pagerStress(void *p, PgHdr *pPg){
rc = pagerWalFrames(pPager, pPg, 0, 0); rc = pagerWalFrames(pPager, pPg, 0, 0);
} }
}else{ }else{
#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE
if( pPager->tempFile==0 ){
rc = sqlite3JournalCreate(pPager->jfd);
if( rc!=SQLITE_OK ) return pager_error(pPager, rc);
}
#endif
/* Sync the journal file if required. */ /* Sync the journal file if required. */
if( pPg->flags&PGHDR_NEED_SYNC if( pPg->flags&PGHDR_NEED_SYNC
@@ -6347,6 +6369,21 @@ int sqlite3PagerCommitPhaseOne(
sqlite3PcacheCleanAll(pPager->pPCache); sqlite3PcacheCleanAll(pPager->pPCache);
} }
}else{ }else{
/* The bBatch boolean is true if the batch-atomic-write commit method
** should be used. No rollback journal is created if batch-atomic-write
** is enabled.
*/
sqlite3_file *fd = pPager->fd;
#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE
const int bBatch = zMaster==0 /* An SQLITE_IOCAP_BATCH_ATOMIC commit */
&& (sqlite3OsDeviceCharacteristics(fd) & SQLITE_IOCAP_BATCH_ATOMIC)
&& !pPager->noSync
&& sqlite3JournalIsInMemory(pPager->jfd);
#else
# define bBatch 0
#endif
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
/* The following block updates the change-counter. Exactly how it /* The following block updates the change-counter. Exactly how it
** does this depends on whether or not the atomic-update optimization ** does this depends on whether or not the atomic-update optimization
** was enabled at compile time, and if this transaction meets the ** was enabled at compile time, and if this transaction meets the
@@ -6370,33 +6407,40 @@ int sqlite3PagerCommitPhaseOne(
** in 'direct' mode. In this case the journal file will never be ** in 'direct' mode. In this case the journal file will never be
** created for this transaction. ** created for this transaction.
*/ */
#ifdef SQLITE_ENABLE_ATOMIC_WRITE if( bBatch==0 ){
PgHdr *pPg; PgHdr *pPg;
assert( isOpen(pPager->jfd) assert( isOpen(pPager->jfd)
|| pPager->journalMode==PAGER_JOURNALMODE_OFF || pPager->journalMode==PAGER_JOURNALMODE_OFF
|| pPager->journalMode==PAGER_JOURNALMODE_WAL || pPager->journalMode==PAGER_JOURNALMODE_WAL
); );
if( !zMaster && isOpen(pPager->jfd) if( !zMaster && isOpen(pPager->jfd)
&& pPager->journalOff==jrnlBufferSize(pPager) && pPager->journalOff==jrnlBufferSize(pPager)
&& pPager->dbSize>=pPager->dbOrigSize && pPager->dbSize>=pPager->dbOrigSize
&& (0==(pPg = sqlite3PcacheDirtyList(pPager->pPCache)) || 0==pPg->pDirty) && (!(pPg = sqlite3PcacheDirtyList(pPager->pPCache)) || 0==pPg->pDirty)
){ ){
/* Update the db file change counter via the direct-write method. The /* Update the db file change counter via the direct-write method. The
** following call will modify the in-memory representation of page 1 ** following call will modify the in-memory representation of page 1
** to include the updated change counter and then write page 1 ** to include the updated change counter and then write page 1
** directly to the database file. Because of the atomic-write ** directly to the database file. Because of the atomic-write
** property of the host file-system, this is safe. ** property of the host file-system, this is safe.
*/ */
rc = pager_incr_changecounter(pPager, 1); rc = pager_incr_changecounter(pPager, 1);
}else{ }else{
rc = sqlite3JournalCreate(pPager->jfd); rc = sqlite3JournalCreate(pPager->jfd);
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
rc = pager_incr_changecounter(pPager, 0); rc = pager_incr_changecounter(pPager, 0);
}
} }
} }
#else #else
#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE
if( zMaster ){
rc = sqlite3JournalCreate(pPager->jfd);
if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
}
#endif
rc = pager_incr_changecounter(pPager, 0); rc = pager_incr_changecounter(pPager, 0);
#endif #endif
if( rc!=SQLITE_OK ) goto commit_phase_one_exit; if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
/* Write the master journal name into the journal file. If a master /* Write the master journal name into the journal file. If a master
@@ -6419,8 +6463,24 @@ int sqlite3PagerCommitPhaseOne(
*/ */
rc = syncJournal(pPager, 0); rc = syncJournal(pPager, 0);
if( rc!=SQLITE_OK ) goto commit_phase_one_exit; if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
if( bBatch ){
/* The pager is now in DBMOD state. But regardless of what happens
** next, attempting to play the journal back into the database would
** be unsafe. Close it now to make sure that does not happen. */
sqlite3OsClose(pPager->jfd);
rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_BEGIN_ATOMIC_WRITE, 0);
if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
}
rc = pager_write_pagelist(pPager,sqlite3PcacheDirtyList(pPager->pPCache)); rc = pager_write_pagelist(pPager,sqlite3PcacheDirtyList(pPager->pPCache));
if( bBatch ){
if( rc==SQLITE_OK ){
rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_COMMIT_ATOMIC_WRITE, 0);
}else{
sqlite3OsFileControl(fd, SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE, 0);
}
}
if( rc!=SQLITE_OK ){ if( rc!=SQLITE_OK ){
assert( rc!=SQLITE_IOERR_BLOCKED ); assert( rc!=SQLITE_IOERR_BLOCKED );
goto commit_phase_one_exit; goto commit_phase_one_exit;

View File

@@ -494,6 +494,9 @@ int sqlite3_exec(
#define SQLITE_IOERR_CONVPATH (SQLITE_IOERR | (26<<8)) #define SQLITE_IOERR_CONVPATH (SQLITE_IOERR | (26<<8))
#define SQLITE_IOERR_VNODE (SQLITE_IOERR | (27<<8)) #define SQLITE_IOERR_VNODE (SQLITE_IOERR | (27<<8))
#define SQLITE_IOERR_AUTH (SQLITE_IOERR | (28<<8)) #define SQLITE_IOERR_AUTH (SQLITE_IOERR | (28<<8))
#define SQLITE_IOERR_BEGIN_ATOMIC (SQLITE_IOERR | (29<<8))
#define SQLITE_IOERR_COMMIT_ATOMIC (SQLITE_IOERR | (30<<8))
#define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8))
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
#define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8)) #define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8))
@@ -580,6 +583,11 @@ int sqlite3_exec(
** SQLITE_IOCAP_IMMUTABLE flag indicates that the file is on ** SQLITE_IOCAP_IMMUTABLE flag indicates that the file is on
** read-only media and cannot be changed even by processes with ** read-only media and cannot be changed even by processes with
** elevated privileges. ** elevated privileges.
**
** The SQLITE_IOCAP_BATCH_ATOMIC property means that the underlying
** filesystem supports doing multiple write operations atomically when those
** write operations are bracketed by [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] and
** [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE].
*/ */
#define SQLITE_IOCAP_ATOMIC 0x00000001 #define SQLITE_IOCAP_ATOMIC 0x00000001
#define SQLITE_IOCAP_ATOMIC512 0x00000002 #define SQLITE_IOCAP_ATOMIC512 0x00000002
@@ -595,6 +603,7 @@ int sqlite3_exec(
#define SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN 0x00000800 #define SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN 0x00000800
#define SQLITE_IOCAP_POWERSAFE_OVERWRITE 0x00001000 #define SQLITE_IOCAP_POWERSAFE_OVERWRITE 0x00001000
#define SQLITE_IOCAP_IMMUTABLE 0x00002000 #define SQLITE_IOCAP_IMMUTABLE 0x00002000
#define SQLITE_IOCAP_BATCH_ATOMIC 0x00004000
/* /*
** CAPI3REF: File Locking Levels ** CAPI3REF: File Locking Levels
@@ -729,6 +738,7 @@ struct sqlite3_file {
** <li> [SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN] ** <li> [SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN]
** <li> [SQLITE_IOCAP_POWERSAFE_OVERWRITE] ** <li> [SQLITE_IOCAP_POWERSAFE_OVERWRITE]
** <li> [SQLITE_IOCAP_IMMUTABLE] ** <li> [SQLITE_IOCAP_IMMUTABLE]
** <li> [SQLITE_IOCAP_BATCH_ATOMIC]
** </ul> ** </ul>
** **
** The SQLITE_IOCAP_ATOMIC property means that all writes of ** The SQLITE_IOCAP_ATOMIC property means that all writes of
@@ -1012,6 +1022,40 @@ struct sqlite3_io_methods {
** The [SQLITE_FCNTL_RBU] opcode is implemented by the special VFS used by ** The [SQLITE_FCNTL_RBU] opcode is implemented by the special VFS used by
** the RBU extension only. All other VFS should return SQLITE_NOTFOUND for ** the RBU extension only. All other VFS should return SQLITE_NOTFOUND for
** this opcode. ** this opcode.
**
** <li>[[SQLITE_FCNTL_BEGIN_ATOMIC_WRITE]]
** If the [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] opcode returns SQLITE_OK, then
** the file descriptor is placed in "batch write mode", which
** means all subsequent write operations will be deferred and done
** atomically at the next [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE]. Systems
** that do not support batch atomic writes will return SQLITE_NOTFOUND.
** ^Following a successful SQLITE_FCNTL_BEGIN_ATOMIC_WRITE and prior to
** the closing [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE] or
** [SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE], SQLite will make
** no VFS interface calls on the same [sqlite3_file] file descriptor
** except for calls to the xWrite method and the xFileControl method
** with [SQLITE_FCNTL_SIZE_HINT].
**
** <li>[[SQLITE_FCNTL_COMMIT_ATOMIC_WRITE]]
** The [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE] opcode causes all write
** operations since the previous successful call to
** [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] to be performed atomically.
** This file control returns [SQLITE_OK] if and only if the writes were
** all performed successfully and have been committed to persistent storage.
** ^Regardless of whether or not it is successful, this file control takes
** the file descriptor out of batch write mode so that all subsequent
** write operations are independent.
** ^SQLite will never invoke SQLITE_FCNTL_COMMIT_ATOMIC_WRITE without
** a prior successful call to [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE].
**
** <li>[[SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE]]
** The [SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE] opcode causes all write
** operations since the previous successful call to
** [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] to be rolled back.
** ^This file control takes the file descriptor out of batch write mode
** so that all subsequent write operations are independent.
** ^SQLite will never invoke SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE without
** a prior successful call to [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE].
** </ul> ** </ul>
*/ */
#define SQLITE_FCNTL_LOCKSTATE 1 #define SQLITE_FCNTL_LOCKSTATE 1
@@ -1043,6 +1087,9 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_JOURNAL_POINTER 28 #define SQLITE_FCNTL_JOURNAL_POINTER 28
#define SQLITE_FCNTL_WIN32_GET_HANDLE 29 #define SQLITE_FCNTL_WIN32_GET_HANDLE 29
#define SQLITE_FCNTL_PDB 30 #define SQLITE_FCNTL_PDB 30
#define SQLITE_FCNTL_BEGIN_ATOMIC_WRITE 31
#define SQLITE_FCNTL_COMMIT_ATOMIC_WRITE 32
#define SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE 33
/* deprecated names */ /* deprecated names */
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE

View File

@@ -630,6 +630,15 @@
# define SQLITE_DEFAULT_PCACHE_INITSZ 20 # define SQLITE_DEFAULT_PCACHE_INITSZ 20
#endif #endif
/*
** The compile-time options SQLITE_MMAP_READWRITE and
** SQLITE_ENABLE_BATCH_ATOMIC_WRITE are not compatible with one another.
** You must choose one or the other (or neither) but not both.
*/
#if defined(SQLITE_MMAP_READWRITE) && defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
#error Cannot use both SQLITE_MMAP_READWRITE and SQLITE_ENABLE_BATCH_ATOMIC_WRITE
#endif
/* /*
** GCC does not define the offsetof() macro so we'll have to do it ** GCC does not define the offsetof() macro so we'll have to do it
** ourselves. ** ourselves.
@@ -4287,7 +4296,8 @@ int sqlite3FindInIndex(Parse *, Expr *, u32, int*, int*);
int sqlite3JournalOpen(sqlite3_vfs *, const char *, sqlite3_file *, int, int); int sqlite3JournalOpen(sqlite3_vfs *, const char *, sqlite3_file *, int, int);
int sqlite3JournalSize(sqlite3_vfs *); int sqlite3JournalSize(sqlite3_vfs *);
#ifdef SQLITE_ENABLE_ATOMIC_WRITE #if defined(SQLITE_ENABLE_ATOMIC_WRITE) \
|| defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
int sqlite3JournalCreate(sqlite3_file *); int sqlite3JournalCreate(sqlite3_file *);
#endif #endif

View File

@@ -2553,6 +2553,46 @@ static int SQLITE_TCLAPI test_delete_database(
return TCL_OK; return TCL_OK;
} }
/*
** Usage: atomic_batch_write PATH
*/
static int SQLITE_TCLAPI test_atomic_batch_write(
void * clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
char *zFile = 0; /* Path to file to test */
sqlite3 *db = 0; /* Database handle */
sqlite3_file *pFd = 0; /* SQLite fd open on zFile */
int bRes = 0; /* Integer result of this command */
int dc = 0; /* Device-characteristics mask */
int rc; /* sqlite3_open() return code */
if( objc!=2 ){
Tcl_WrongNumArgs(interp, 1, objv, "PATH");
return TCL_ERROR;
}
zFile = Tcl_GetString(objv[1]);
rc = sqlite3_open(zFile, &db);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, sqlite3_errmsg(db), 0);
sqlite3_close(db);
return TCL_ERROR;
}
rc = sqlite3_file_control(db, "main", SQLITE_FCNTL_FILE_POINTER, (void*)&pFd);
dc = pFd->pMethods->xDeviceCharacteristics(pFd);
if( dc & SQLITE_IOCAP_BATCH_ATOMIC ){
bRes = 1;
}
Tcl_SetObjResult(interp, Tcl_NewIntObj(bRes));
sqlite3_close(db);
return TCL_OK;
}
/* /*
** Usage: sqlite3_next_stmt DB STMT ** Usage: sqlite3_next_stmt DB STMT
** **
@@ -7645,6 +7685,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "sqlite3_snapshot_cmp_blob", test_snapshot_cmp_blob, 0 }, { "sqlite3_snapshot_cmp_blob", test_snapshot_cmp_blob, 0 },
#endif #endif
{ "sqlite3_delete_database", test_delete_database, 0 }, { "sqlite3_delete_database", test_delete_database, 0 },
{ "atomic_batch_write", test_atomic_batch_write, 0 },
}; };
static int bitmask_size = sizeof(Bitmask)*8; static int bitmask_size = sizeof(Bitmask)*8;
static int longdouble_size = sizeof(LONGDOUBLE_TYPE); static int longdouble_size = sizeof(LONGDOUBLE_TYPE);

View File

@@ -736,6 +736,7 @@ static int processDevSymArgs(
{ "sequential", SQLITE_IOCAP_SEQUENTIAL }, { "sequential", SQLITE_IOCAP_SEQUENTIAL },
{ "safe_append", SQLITE_IOCAP_SAFE_APPEND }, { "safe_append", SQLITE_IOCAP_SAFE_APPEND },
{ "powersafe_overwrite", SQLITE_IOCAP_POWERSAFE_OVERWRITE }, { "powersafe_overwrite", SQLITE_IOCAP_POWERSAFE_OVERWRITE },
{ "batch-atomic", SQLITE_IOCAP_BATCH_ATOMIC },
{ 0, 0 } { 0, 0 }
}; };
@@ -976,7 +977,30 @@ static int SQLITE_TCLAPI devSymObjCmd(
devsym_register(iDc, iSectorSize); devsym_register(iDc, iSectorSize);
return TCL_OK; return TCL_OK;
}
/*
** tclcmd: sqlite3_crash_on_write N
*/
static int SQLITE_TCLAPI writeCrashObjCmd(
void * clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
void devsym_crash_on_write(int);
int nWrite = 0;
if( objc!=2 ){
Tcl_WrongNumArgs(interp, 1, objv, "NWRITE");
return TCL_ERROR;
}
if( Tcl_GetIntFromObj(interp, objv[1], &nWrite) ){
return TCL_ERROR;
}
devsym_crash_on_write(nWrite);
return TCL_OK;
} }
/* /*
@@ -1068,6 +1092,7 @@ int Sqlitetest6_Init(Tcl_Interp *interp){
Tcl_CreateObjCommand(interp, "sqlite3_crashparams", crashParamsObjCmd, 0, 0); Tcl_CreateObjCommand(interp, "sqlite3_crashparams", crashParamsObjCmd, 0, 0);
Tcl_CreateObjCommand(interp, "sqlite3_crash_now", crashNowCmd, 0, 0); Tcl_CreateObjCommand(interp, "sqlite3_crash_now", crashNowCmd, 0, 0);
Tcl_CreateObjCommand(interp, "sqlite3_simulate_device", devSymObjCmd, 0, 0); Tcl_CreateObjCommand(interp, "sqlite3_simulate_device", devSymObjCmd, 0, 0);
Tcl_CreateObjCommand(interp, "sqlite3_crash_on_write", writeCrashObjCmd,0,0);
Tcl_CreateObjCommand(interp, "unregister_devsim", dsUnregisterObjCmd, 0, 0); Tcl_CreateObjCommand(interp, "unregister_devsim", dsUnregisterObjCmd, 0, 0);
Tcl_CreateObjCommand(interp, "register_jt_vfs", jtObjCmd, 0, 0); Tcl_CreateObjCommand(interp, "register_jt_vfs", jtObjCmd, 0, 0);
Tcl_CreateObjCommand(interp, "unregister_jt_vfs", jtUnregisterObjCmd, 0, 0); Tcl_CreateObjCommand(interp, "unregister_jt_vfs", jtUnregisterObjCmd, 0, 0);

View File

@@ -28,6 +28,7 @@
** Name used to identify this VFS. ** Name used to identify this VFS.
*/ */
#define DEVSYM_VFS_NAME "devsym" #define DEVSYM_VFS_NAME "devsym"
#define WRITECRASH_NAME "writecrash"
typedef struct devsym_file devsym_file; typedef struct devsym_file devsym_file;
struct devsym_file { struct devsym_file {
@@ -72,61 +73,13 @@ static int devsymRandomness(sqlite3_vfs*, int nByte, char *zOut);
static int devsymSleep(sqlite3_vfs*, int microseconds); static int devsymSleep(sqlite3_vfs*, int microseconds);
static int devsymCurrentTime(sqlite3_vfs*, double*); static int devsymCurrentTime(sqlite3_vfs*, double*);
static sqlite3_vfs devsym_vfs = {
2, /* iVersion */
sizeof(devsym_file), /* szOsFile */
DEVSYM_MAX_PATHNAME, /* mxPathname */
0, /* pNext */
DEVSYM_VFS_NAME, /* zName */
0, /* pAppData */
devsymOpen, /* xOpen */
devsymDelete, /* xDelete */
devsymAccess, /* xAccess */
devsymFullPathname, /* xFullPathname */
#ifndef SQLITE_OMIT_LOAD_EXTENSION
devsymDlOpen, /* xDlOpen */
devsymDlError, /* xDlError */
devsymDlSym, /* xDlSym */
devsymDlClose, /* xDlClose */
#else
0, /* xDlOpen */
0, /* xDlError */
0, /* xDlSym */
0, /* xDlClose */
#endif /* SQLITE_OMIT_LOAD_EXTENSION */
devsymRandomness, /* xRandomness */
devsymSleep, /* xSleep */
devsymCurrentTime, /* xCurrentTime */
0, /* xGetLastError */
0 /* xCurrentTimeInt64 */
};
static sqlite3_io_methods devsym_io_methods = {
2, /* iVersion */
devsymClose, /* xClose */
devsymRead, /* xRead */
devsymWrite, /* xWrite */
devsymTruncate, /* xTruncate */
devsymSync, /* xSync */
devsymFileSize, /* xFileSize */
devsymLock, /* xLock */
devsymUnlock, /* xUnlock */
devsymCheckReservedLock, /* xCheckReservedLock */
devsymFileControl, /* xFileControl */
devsymSectorSize, /* xSectorSize */
devsymDeviceCharacteristics, /* xDeviceCharacteristics */
devsymShmMap, /* xShmMap */
devsymShmLock, /* xShmLock */
devsymShmBarrier, /* xShmBarrier */
devsymShmUnmap /* xShmUnmap */
};
struct DevsymGlobal { struct DevsymGlobal {
sqlite3_vfs *pVfs; sqlite3_vfs *pVfs;
int iDeviceChar; int iDeviceChar;
int iSectorSize; int iSectorSize;
int nWriteCrash;
}; };
struct DevsymGlobal g = {0, 0, 512}; struct DevsymGlobal g = {0, 0, 512, 0};
/* /*
** Close an devsym-file. ** Close an devsym-file.
@@ -271,6 +224,26 @@ static int devsymOpen(
int flags, int flags,
int *pOutFlags int *pOutFlags
){ ){
static sqlite3_io_methods devsym_io_methods = {
2, /* iVersion */
devsymClose, /* xClose */
devsymRead, /* xRead */
devsymWrite, /* xWrite */
devsymTruncate, /* xTruncate */
devsymSync, /* xSync */
devsymFileSize, /* xFileSize */
devsymLock, /* xLock */
devsymUnlock, /* xUnlock */
devsymCheckReservedLock, /* xCheckReservedLock */
devsymFileControl, /* xFileControl */
devsymSectorSize, /* xSectorSize */
devsymDeviceCharacteristics, /* xDeviceCharacteristics */
devsymShmMap, /* xShmMap */
devsymShmLock, /* xShmLock */
devsymShmBarrier, /* xShmBarrier */
devsymShmUnmap /* xShmUnmap */
};
int rc; int rc;
devsym_file *p = (devsym_file *)pFile; devsym_file *p = (devsym_file *)pFile;
p->pReal = (sqlite3_file *)&p[1]; p->pReal = (sqlite3_file *)&p[1];
@@ -372,6 +345,137 @@ static int devsymCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
return g.pVfs->xCurrentTime(g.pVfs, pTimeOut); return g.pVfs->xCurrentTime(g.pVfs, pTimeOut);
} }
/*
** Return the sector-size in bytes for an writecrash-file.
*/
static int writecrashSectorSize(sqlite3_file *pFile){
devsym_file *p = (devsym_file *)pFile;
return sqlite3OsSectorSize(p->pReal);
}
/*
** Return the device characteristic flags supported by an writecrash-file.
*/
static int writecrashDeviceCharacteristics(sqlite3_file *pFile){
devsym_file *p = (devsym_file *)pFile;
return sqlite3OsDeviceCharacteristics(p->pReal);
}
/*
** Write data to an writecrash-file.
*/
static int writecrashWrite(
sqlite3_file *pFile,
const void *zBuf,
int iAmt,
sqlite_int64 iOfst
){
devsym_file *p = (devsym_file *)pFile;
if( g.nWriteCrash>0 ){
g.nWriteCrash--;
if( g.nWriteCrash==0 ) abort();
}
return sqlite3OsWrite(p->pReal, zBuf, iAmt, iOfst);
}
/*
** Open an writecrash file handle.
*/
static int writecrashOpen(
sqlite3_vfs *pVfs,
const char *zName,
sqlite3_file *pFile,
int flags,
int *pOutFlags
){
static sqlite3_io_methods writecrash_io_methods = {
2, /* iVersion */
devsymClose, /* xClose */
devsymRead, /* xRead */
writecrashWrite, /* xWrite */
devsymTruncate, /* xTruncate */
devsymSync, /* xSync */
devsymFileSize, /* xFileSize */
devsymLock, /* xLock */
devsymUnlock, /* xUnlock */
devsymCheckReservedLock, /* xCheckReservedLock */
devsymFileControl, /* xFileControl */
writecrashSectorSize, /* xSectorSize */
writecrashDeviceCharacteristics, /* xDeviceCharacteristics */
devsymShmMap, /* xShmMap */
devsymShmLock, /* xShmLock */
devsymShmBarrier, /* xShmBarrier */
devsymShmUnmap /* xShmUnmap */
};
int rc;
devsym_file *p = (devsym_file *)pFile;
p->pReal = (sqlite3_file *)&p[1];
rc = sqlite3OsOpen(g.pVfs, zName, p->pReal, flags, pOutFlags);
if( p->pReal->pMethods ){
pFile->pMethods = &writecrash_io_methods;
}
return rc;
}
static sqlite3_vfs devsym_vfs = {
2, /* iVersion */
sizeof(devsym_file), /* szOsFile */
DEVSYM_MAX_PATHNAME, /* mxPathname */
0, /* pNext */
DEVSYM_VFS_NAME, /* zName */
0, /* pAppData */
devsymOpen, /* xOpen */
devsymDelete, /* xDelete */
devsymAccess, /* xAccess */
devsymFullPathname, /* xFullPathname */
#ifndef SQLITE_OMIT_LOAD_EXTENSION
devsymDlOpen, /* xDlOpen */
devsymDlError, /* xDlError */
devsymDlSym, /* xDlSym */
devsymDlClose, /* xDlClose */
#else
0, /* xDlOpen */
0, /* xDlError */
0, /* xDlSym */
0, /* xDlClose */
#endif /* SQLITE_OMIT_LOAD_EXTENSION */
devsymRandomness, /* xRandomness */
devsymSleep, /* xSleep */
devsymCurrentTime, /* xCurrentTime */
0, /* xGetLastError */
0 /* xCurrentTimeInt64 */
};
static sqlite3_vfs writecrash_vfs = {
2, /* iVersion */
sizeof(devsym_file), /* szOsFile */
DEVSYM_MAX_PATHNAME, /* mxPathname */
0, /* pNext */
WRITECRASH_NAME, /* zName */
0, /* pAppData */
writecrashOpen, /* xOpen */
devsymDelete, /* xDelete */
devsymAccess, /* xAccess */
devsymFullPathname, /* xFullPathname */
#ifndef SQLITE_OMIT_LOAD_EXTENSION
devsymDlOpen, /* xDlOpen */
devsymDlError, /* xDlError */
devsymDlSym, /* xDlSym */
devsymDlClose, /* xDlClose */
#else
0, /* xDlOpen */
0, /* xDlError */
0, /* xDlSym */
0, /* xDlClose */
#endif /* SQLITE_OMIT_LOAD_EXTENSION */
devsymRandomness, /* xRandomness */
devsymSleep, /* xSleep */
devsymCurrentTime, /* xCurrentTime */
0, /* xGetLastError */
0 /* xCurrentTimeInt64 */
};
/* /*
** This procedure registers the devsym vfs with SQLite. If the argument is ** This procedure registers the devsym vfs with SQLite. If the argument is
@@ -379,10 +483,13 @@ static int devsymCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
** available function in this file. ** available function in this file.
*/ */
void devsym_register(int iDeviceChar, int iSectorSize){ void devsym_register(int iDeviceChar, int iSectorSize){
if( g.pVfs==0 ){ if( g.pVfs==0 ){
g.pVfs = sqlite3_vfs_find(0); g.pVfs = sqlite3_vfs_find(0);
devsym_vfs.szOsFile += g.pVfs->szOsFile; devsym_vfs.szOsFile += g.pVfs->szOsFile;
writecrash_vfs.szOsFile += g.pVfs->szOsFile;
sqlite3_vfs_register(&devsym_vfs, 0); sqlite3_vfs_register(&devsym_vfs, 0);
sqlite3_vfs_register(&writecrash_vfs, 0);
} }
if( iDeviceChar>=0 ){ if( iDeviceChar>=0 ){
g.iDeviceChar = iDeviceChar; g.iDeviceChar = iDeviceChar;
@@ -403,4 +510,15 @@ void devsym_unregister(){
g.iSectorSize = 0; g.iSectorSize = 0;
} }
void devsym_crash_on_write(int nWrite){
if( g.pVfs==0 ){
g.pVfs = sqlite3_vfs_find(0);
devsym_vfs.szOsFile += g.pVfs->szOsFile;
writecrash_vfs.szOsFile += g.pVfs->szOsFile;
sqlite3_vfs_register(&devsym_vfs, 0);
sqlite3_vfs_register(&writecrash_vfs, 0);
}
g.nWriteCrash = nWrite;
}
#endif #endif

41
test/atomic.test Normal file
View File

@@ -0,0 +1,41 @@
# 2015-11-07
#
# 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.
#
#***********************************************************************
# This file implements regression tests for SQLite library. The
# focus of this file is testing the WITH clause.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set ::testprefix atomic
db close
if {[atomic_batch_write test.db]==0} {
puts "No f2fs atomic-batch-write support. Skipping tests..."
finish_test
return
}
reset_db
do_execsql_test 1.0 {
CREATE TABLE t1(x, y);
BEGIN;
INSERT INTO t1 VALUES(1, 2);
}
do_test 1.1 { file exists test.db-journal } {0}
do_execsql_test 1.2 {
COMMIT;
}
finish_test

View File

@@ -59,7 +59,9 @@ do_test fallocate-1.6 {
# #
do_test fallocate-1.7 { do_test fallocate-1.7 {
execsql { BEGIN; INSERT INTO t1 VALUES(1, 2); } execsql { BEGIN; INSERT INTO t1 VALUES(1, 2); }
if {[permutation] != "inmemory_journal"} { if {[permutation] != "inmemory_journal"
&& [permutation] != "atomic-batch-write"
} {
hexio_get_int [hexio_read test.db-journal 16 4] hexio_get_int [hexio_read test.db-journal 16 4]
} else { } else {
set {} 1024 set {} 1024

View File

@@ -479,26 +479,28 @@ ifcapable curdir {
# Make sure a database connection still works after changing the # Make sure a database connection still works after changing the
# working directory. # working directory.
# #
do_test misc1-14.1 { if {[atomic_batch_write test.db]==0} {
file mkdir tempdir do_test misc1-14.1 {
cd tempdir file mkdir tempdir
execsql {BEGIN} cd tempdir
file exists ./test.db-journal execsql {BEGIN}
} {0} file exists ./test.db-journal
do_test misc1-14.2a { } {0}
execsql {UPDATE t1 SET a=a||'x' WHERE 0} do_test misc1-14.2a {
file exists ../test.db-journal execsql {UPDATE t1 SET a=a||'x' WHERE 0}
} {0} file exists ../test.db-journal
do_test misc1-14.2b { } {0}
execsql {UPDATE t1 SET a=a||'y' WHERE 1} do_test misc1-14.2b {
file exists ../test.db-journal execsql {UPDATE t1 SET a=a||'y' WHERE 1}
} {1} file exists ../test.db-journal
do_test misc1-14.3 { } {1}
cd .. do_test misc1-14.3 {
forcedelete tempdir cd ..
execsql {COMMIT} forcedelete tempdir
file exists ./test.db-journal execsql {COMMIT}
} {0} file exists ./test.db-journal
} {0}
}
} }
# A failed create table should not leave the table in the internal # A failed create table should not leave the table in the internal

View File

@@ -389,6 +389,30 @@ test_suite "vfslog" -prefix "" -description {
wal* mmap* wal* mmap*
] ]
test_suite "atomic-batch-write" -prefix "" -description {
Like veryquick.test, but must be run on a file-system that supports
atomic-batch-writes. Tests that depend on the journal file being present
are omitted.
} -files [
test_set $allquicktests -exclude *malloc* *ioerr* *fault* *bigfile* *_err* \
*fts5corrupt* *fts5big* *fts5aj* \
crash8.test delete_db.test \
exclusive.test journal3.test \
journal1.test \
jrnlmode.test jrnlmode2.test \
lock4.test pager1.test \
pager3.test sharedA.test \
symlink.test stmt.test \
sync.test sync2.test \
tempdb.test tkt3457.test \
vacuum5.test wal2.test \
walmode.test zerodamage.test
] -initialize {
if {[atomic_batch_write test.db]==0} {
error "File system does NOT support atomic-batch-write"
}
}
lappend ::testsuitelist xxx lappend ::testsuitelist xxx
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# Define the coverage related test suites: # Define the coverage related test suites:

View File

@@ -82,6 +82,7 @@ do_test rollback-1.9 {
if {$tcl_platform(platform) == "unix" if {$tcl_platform(platform) == "unix"
&& [permutation] ne "onefile" && [permutation] ne "onefile"
&& [permutation] ne "inmemory_journal" && [permutation] ne "inmemory_journal"
&& [permutation] ne "atomic-batch-write"
} { } {
do_test rollback-2.1 { do_test rollback-2.1 {
execsql { execsql {

View File

@@ -61,7 +61,7 @@ foreach s {
fcntl read pread write pwrite fchmod fallocate fcntl read pread write pwrite fchmod fallocate
pread64 pwrite64 unlink openDirectory mkdir rmdir pread64 pwrite64 unlink openDirectory mkdir rmdir
statvfs fchown geteuid umask mmap munmap mremap statvfs fchown geteuid umask mmap munmap mremap
getpagesize readlink lstat getpagesize readlink lstat ioctl
} { } {
if {[test_syscall exists $s]} {lappend syscall_list $s} if {[test_syscall exists $s]} {lappend syscall_list $s}
} }

View File

@@ -1608,6 +1608,54 @@ proc crashsql {args} {
lappend r $msg lappend r $msg
} }
# crash_on_write ?-devchar DEVCHAR? CRASHDELAY SQL
#
proc crash_on_write {args} {
set nArg [llength $args]
if {$nArg<2 || $nArg%2} {
error "bad args: $args"
}
set zSql [lindex $args end]
set nDelay [lindex $args end-1]
set devchar {}
for {set ii 0} {$ii < $nArg-2} {incr ii 2} {
set opt [lindex $args $ii]
switch -- [lindex $args $ii] {
-devchar {
set devchar [lindex $args [expr $ii+1]]
}
default { error "unrecognized option: $opt" }
}
}
set f [open crash.tcl w]
puts $f "sqlite3_crash_on_write $nDelay"
puts $f "sqlite3_test_control_pending_byte $::sqlite_pending_byte"
puts $f "sqlite3 db test.db -vfs writecrash"
puts $f "db eval {$zSql}"
puts $f "set {} {}"
close $f
set r [catch {
exec [info nameofexec] crash.tcl >@stdout
} msg]
# Windows/ActiveState TCL returns a slightly different
# error message. We map that to the expected message
# so that we don't have to change all of the test
# cases.
if {$::tcl_platform(platform)=="windows"} {
if {$msg=="child killed: unknown signal"} {
set msg "child process exited abnormally"
}
}
lappend r $msg
}
proc run_ioerr_prep {} { proc run_ioerr_prep {} {
set ::sqlite_io_error_pending 0 set ::sqlite_io_error_pending 0
catch {db close} catch {db close}

68
test/writecrash.test Normal file
View File

@@ -0,0 +1,68 @@
# 2009 January 8
#
# 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.
#
#***********************************************************************
#
# Test the outcome of a writer crashing within a call to the VFS
# xWrite function.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix writecrash
do_not_use_codec
if {$tcl_platform(platform)=="windows"} {
finish_test
return
}
do_execsql_test 1.0 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b BLOB UNIQUE);
WITH s(i) AS (
VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<100
)
INSERT INTO t1 SELECT NULL, randomblob(900) FROM s;
} {}
set bGo 1
for {set tn 1} {$bGo} {incr tn} {
db close
sqlite3 db test.db
do_test 1.$tn.1 {
set res [crash_on_write $tn {
UPDATE t1 SET b = randomblob(899) WHERE (a%3)==0
}]
set bGo 0
if {[string match {1 {child killed:*}} $res]} {
set res {0 {}}
set bGo 1
}
set res
} {0 {}}
#db close
#sqlite3 db test.db
do_execsql_test 1.$tn.2 { PRAGMA integrity_check } {ok}
db close
sqlite3 db test.db
do_execsql_test 1.$tn.3 { PRAGMA integrity_check } {ok}
}
finish_test