1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-06 15:49:35 +03:00

Merge the PCACHE2 changes into trunk.

FossilOrigin-Name: 457513f21f2438c61b1a214716e338a4e3eeaafa
This commit is contained in:
drh
2011-11-16 18:08:07 +00:00
24 changed files with 606 additions and 437 deletions

View File

@@ -49,6 +49,9 @@ BCC = cl.exe
# #
TCC = cl.exe -W3 -DSQLITE_OS_WIN=1 -I. -I$(TOP)\src -fp:precise TCC = cl.exe -W3 -DSQLITE_OS_WIN=1 -I. -I$(TOP)\src -fp:precise
# We always have the _msize function available when using MSVC.
TCC = $(TCC) -DHAVE_MALLOC_USABLE_SIZE -Dmalloc_usable_size=_msize
# The mksqlite3c.tcl and mksqlite3h.tcl scripts will pull in # The mksqlite3c.tcl and mksqlite3h.tcl scripts will pull in
# any extension header files by default. For non-amalgamation # any extension header files by default. For non-amalgamation
# builds, we need to make sure the compiler can find these. # builds, we need to make sure the compiler can find these.

View File

@@ -33,6 +33,9 @@
/* Define to 1 if you have the `localtime_s' function. */ /* Define to 1 if you have the `localtime_s' function. */
#undef HAVE_LOCALTIME_S #undef HAVE_LOCALTIME_S
/* Define to 1 if you have the `malloc_usable_size' function. */
#undef HAVE_MALLOC_USABLE_SIZE
/* Define to 1 if you have the <memory.h> header file. */ /* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H #undef HAVE_MEMORY_H

387
configure vendored

File diff suppressed because it is too large Load Diff

View File

@@ -127,7 +127,7 @@ AC_CHECK_HEADERS([sys/types.h stdlib.h stdint.h inttypes.h])
######### #########
# Figure out whether or not we have these functions # Figure out whether or not we have these functions
# #
AC_CHECK_FUNCS([usleep fdatasync localtime_r gmtime_r localtime_s utime]) AC_CHECK_FUNCS([usleep fdatasync localtime_r gmtime_r localtime_s utime malloc_usable_size])
######### #########
# By default, we use the amalgamation (this may be changed below...) # By default, we use the amalgamation (this may be changed below...)

View File

@@ -1,9 +1,9 @@
C Remove\scode\smade\sobsolete\sby\sthe\schanges\sto\sindex\sprocessing\sthat\sallow\nrange\ssearch\son\sthe\srowid. C Merge\sthe\sPCACHE2\schanges\sinto\strunk.
D 2011-11-16T16:23:15.780 D 2011-11-16T18:08:07.023
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 5b4a3e12a850b021547e43daf886b25133b44c07 F Makefile.in 5b4a3e12a850b021547e43daf886b25133b44c07
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F Makefile.msc dcad80fa69f17d46fe6778ba873fc108ca16298d F Makefile.msc 3bd3641a345d488a9601c0cc7f9d35aeede5d12b
F Makefile.vxworks 1deb39c8bb047296c30161ffa10c1b5423e632f9 F Makefile.vxworks 1deb39c8bb047296c30161ffa10c1b5423e632f9
F README cd04a36fbc7ea56932a4052d7d0b7f09f27c33d6 F README cd04a36fbc7ea56932a4052d7d0b7f09f27c33d6
F VERSION bb37c274b503bbe73f00ea4f374eb817cba4b171 F VERSION bb37c274b503bbe73f00ea4f374eb817cba4b171
@@ -21,10 +21,10 @@ F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2 F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
F art/src_logo.gif 9341ef09f0e53cd44c0c9b6fc3c16f7f3d6c2ad9 F art/src_logo.gif 9341ef09f0e53cd44c0c9b6fc3c16f7f3d6c2ad9
F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977 F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977
F config.h.in 405a958bdb3af382a809dccb08a44694923ddd61 F config.h.in 31cc8c4943f56e60c4aa4fba929c9d4c70e418b4
F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55 F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
F configure 806c06aef5895860da49600ce098dbe4d5a8435c x F configure 194ed7797c67c24ebbeb001fcfc557116fe5eba9 x
F configure.ac 298a759c086e72c013da459c2aec02a104f4224f F configure.ac 75323bdac56fb0e69f6a3fc5b23f24359550b9d9
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
F doc/lemon.html 3091574143dd3415669b6745843ff8d011d33549 F doc/lemon.html 3091574143dd3415669b6745843ff8d011d33549
F doc/pager-invariants.txt 870107036470d7c419e93768676fae2f8749cf9e F doc/pager-invariants.txt 870107036470d7c419e93768676fae2f8749cf9e
@@ -125,7 +125,7 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
F src/backup.c 4368158da74d4711888e03264105c5c527d76caf F src/backup.c 4368158da74d4711888e03264105c5c527d76caf
F src/bitvec.c af50f1c8c0ff54d6bdb7a80e2fceca5a93670bef F src/bitvec.c af50f1c8c0ff54d6bdb7a80e2fceca5a93670bef
F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
F src/btree.c 80ea65224512884bb72976c93810d2dcaecc1353 F src/btree.c 149cccf2134f555583d0825e47b17104aa06cb84
F src/btree.h f5d775cd6cfc7ac32a2535b70e8d2af48ef5f2ce F src/btree.h f5d775cd6cfc7ac32a2535b70e8d2af48ef5f2ce
F src/btreeInt.h ea863a819224d3e6845ad1e39954d41558b8cd8b F src/btreeInt.h ea863a819224d3e6845ad1e39954d41558b8cd8b
F src/build.c 8915bb6d72ead998f94c2756ea8d143c77709b70 F src/build.c 8915bb6d72ead998f94c2756ea8d143c77709b70
@@ -138,7 +138,7 @@ F src/expr.c fbf116f90cabc917ae50bba24a73a0b55519a0c8
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c 657212460bf5cfd3ae607d12ea62092844c227b5 F src/fkey.c 657212460bf5cfd3ae607d12ea62092844c227b5
F src/func.c 6261ce00aad9c63cd5b4219249b05683979060e9 F src/func.c 6261ce00aad9c63cd5b4219249b05683979060e9
F src/global.c e230227de13601714b29f9363028514aada5ae2f F src/global.c 107ccaacb4b30895cf3a3a39decf417c804acfa1
F src/hash.c 458488dcc159c301b8e7686280ab209f1fb915af F src/hash.c 458488dcc159c301b8e7686280ab209f1fb915af
F src/hash.h 2894c932d84d9f892d4b4023a75e501f83050970 F src/hash.h 2894c932d84d9f892d4b4023a75e501f83050970
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
@@ -147,10 +147,10 @@ F src/journal.c 552839e54d1bf76fb8f7abe51868b66acacf6a0e
F src/legacy.c a199d7683d60cef73089e892409113e69c23a99f F src/legacy.c a199d7683d60cef73089e892409113e69c23a99f
F src/lempar.c 0ee69fca0be54cd93939df98d2aca4ca46f44416 F src/lempar.c 0ee69fca0be54cd93939df98d2aca4ca46f44416
F src/loadext.c d0d2022a5a07274d408820b978b9e549189d314f F src/loadext.c d0d2022a5a07274d408820b978b9e549189d314f
F src/main.c df06f5229b8046f85dde253dfd7fe35ae9e4902e F src/main.c 87dd4f6ee9b1700d54164ab4e14f2f7abc75486f
F src/malloc.c 591aedb20ae40813f1045f2ef253438a334775d9 F src/malloc.c 591aedb20ae40813f1045f2ef253438a334775d9
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c 00bd8265c81abb665c48fea1e0c234eb3b922206 F src/mem1.c 7456e2ca0524609ebc06a9befeda5289d4575ad4
F src/mem2.c e307323e86b5da1853d7111b68fd6b84ad6f09cf F src/mem2.c e307323e86b5da1853d7111b68fd6b84ad6f09cf
F src/mem3.c 61c9d47b792908c532ca3a62b999cf21795c6534 F src/mem3.c 61c9d47b792908c532ca3a62b999cf21795c6534
F src/mem5.c c2c63b7067570b00bf33d751c39af24182316f7f F src/mem5.c c2c63b7067570b00bf33d751c39af24182316f7f
@@ -171,20 +171,20 @@ F src/os_win.c a22b88d2c088c09a678a471abafa8d60dbf56803
F src/pager.c db33d4bf1e3e019c34c220971cc6c3aa07c30f54 F src/pager.c db33d4bf1e3e019c34c220971cc6c3aa07c30f54
F src/pager.h 9f81b08efb06db4ba8be69446e10b005c351373d F src/pager.h 9f81b08efb06db4ba8be69446e10b005c351373d
F src/parse.y 12b7ebd61ea54f0e1b1083ff69cc2c8ce9353d58 F src/parse.y 12b7ebd61ea54f0e1b1083ff69cc2c8ce9353d58
F src/pcache.c 49e718c095810c6b3334e3a6d89970aceaddefce F src/pcache.c b9d52e9f844d91c27c161279234f273fc02abc71
F src/pcache.h c683390d50f856d4cd8e24342ae62027d1bb6050 F src/pcache.h c770382f9fae4ca5025c5523bd0aa13cd6ddc6f8
F src/pcache1.c 24f5e85a78514584b46190260ba7ab0a66312197 F src/pcache1.c 0ac7b63db83a705787f4ababf1e4cff27b5f8064
F src/pragma.c da8ef96b3eec351e81e0061c39810e548bcc96d7 F src/pragma.c 65d1d63d64f8b7350f28d5ee6d40f7985deccdfe
F src/prepare.c e64261559a3187698a3e7e6c8b001a4f4f98dab4 F src/prepare.c ec4989f7f480544bdc4192fe663470d2a2d7d61e
F src/printf.c 03104cbff6959ff45df69dc9060ba6212f60a869 F src/printf.c 03104cbff6959ff45df69dc9060ba6212f60a869
F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50 F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
F src/resolve.c 365ab1c870e38596d6869e76fb544fe6e4ffc809 F src/resolve.c 365ab1c870e38596d6869e76fb544fe6e4ffc809
F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697 F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697
F src/select.c 80f3ac44a8514b1d107b80f5df4a424ae059d2b6 F src/select.c 80f3ac44a8514b1d107b80f5df4a424ae059d2b6
F src/shell.c 6d2ad7f80adc9c8c3195412879af36eb3196c1b6 F src/shell.c 29812a900a780eb0f835c4bc65e216272689def8
F src/sqlite.h.in b7a4e8d428e467d820cbb4c1d275fdda88b4d7ab F src/sqlite.h.in 557f4113a649f15d13e566aaa85820509b4daa52
F src/sqlite3ext.h 6904f4aadf976f95241311fbffb00823075d9477 F src/sqlite3ext.h 6904f4aadf976f95241311fbffb00823075d9477
F src/sqliteInt.h ce631f204a67ae35b817928e3931484bda0963bc F src/sqliteInt.h f412e020e1009163c74be56eaac1bf7f6c0a4515
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
F src/status.c 4568e72dfd36b6a5911f93457364deb072e0b03a F src/status.c 4568e72dfd36b6a5911f93457364deb072e0b03a
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
@@ -202,13 +202,13 @@ F src/test_async.c 0612a752896fad42d55c3999a5122af10dcf22ad
F src/test_autoext.c 30e7bd98ab6d70a62bb9ba572e4c7df347fe645e F src/test_autoext.c 30e7bd98ab6d70a62bb9ba572e4c7df347fe645e
F src/test_backup.c c129c91127e9b46e335715ae2e75756e25ba27de F src/test_backup.c c129c91127e9b46e335715ae2e75756e25ba27de
F src/test_btree.c 47cd771250f09cdc6e12dda5bc71bc0b3abc96e2 F src/test_btree.c 47cd771250f09cdc6e12dda5bc71bc0b3abc96e2
F src/test_config.c bc8826296a7b3a86eeaba1ac2af5551d1c20c35b F src/test_config.c a036a69b550ebc477ab9ca2b37269201f888436e
F src/test_demovfs.c 20a4975127993f4959890016ae9ce5535a880094 F src/test_demovfs.c 20a4975127993f4959890016ae9ce5535a880094
F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
F src/test_func.c cbdec5cededa0761daedde5baf06004a9bf416b5 F src/test_func.c cbdec5cededa0761daedde5baf06004a9bf416b5
F src/test_fuzzer.c f884f6f32e8513d34248d6e1ac8a32047fead254 F src/test_fuzzer.c f884f6f32e8513d34248d6e1ac8a32047fead254
F src/test_hexio.c c4773049603151704a6ab25ac5e936b5109caf5a F src/test_hexio.c c4773049603151704a6ab25ac5e936b5109caf5a
F src/test_init.c 5d624ffd0409d424cf9adbfe1f056b200270077c F src/test_init.c 3cbad7ce525aec925f8fda2192d576d47f0d478a
F src/test_intarray.c d879bbf8e4ce085ab966d1f3c896a7c8b4f5fc99 F src/test_intarray.c d879bbf8e4ce085ab966d1f3c896a7c8b4f5fc99
F src/test_intarray.h 489edb9068bb926583445cb02589344961054207 F src/test_intarray.h 489edb9068bb926583445cb02589344961054207
F src/test_journal.c 03313c693cca72959dcaaf79f8d76f21c01e19ff F src/test_journal.c 03313c693cca72959dcaaf79f8d76f21c01e19ff
@@ -219,7 +219,7 @@ F src/test_multiplex.h e99c571bc4968b7a9363b661481f3934bfead61d
F src/test_mutex.c a6bd7b9cf6e19d989e31392b06ac8d189f0d573e F src/test_mutex.c a6bd7b9cf6e19d989e31392b06ac8d189f0d573e
F src/test_onefile.c 40cf9e212a377a6511469384a64b01e6e34b2eec F src/test_onefile.c 40cf9e212a377a6511469384a64b01e6e34b2eec
F src/test_osinst.c 62b0b8ef21ce754cc94e17bb42377ed8795dba32 F src/test_osinst.c 62b0b8ef21ce754cc94e17bb42377ed8795dba32
F src/test_pcache.c 335285416eb7a5c3a0f4daffb796912011ebbf6e F src/test_pcache.c a5cd24730cb43c5b18629043314548c9169abb00
F src/test_quota.c a391c866217e92986c6f523f05b08aa6956c8419 F src/test_quota.c a391c866217e92986c6f523f05b08aa6956c8419
F src/test_rtree.c 6d06306e29946dc36f528a3a2cdc3add794656f1 F src/test_rtree.c 6d06306e29946dc36f528a3a2cdc3add794656f1
F src/test_schema.c 8c06ef9ddb240c7a0fcd31bc221a6a2aade58bf0 F src/test_schema.c 8c06ef9ddb240c7a0fcd31bc221a6a2aade58bf0
@@ -361,7 +361,7 @@ F test/createtab.test b5de160630b209c4b8925bdcbbaf48cc90b67fe8
F test/cse.test 277350a26264495e86b1785f34d2d0c8600e021c F test/cse.test 277350a26264495e86b1785f34d2d0c8600e021c
F test/ctime.test 7bd009071e242aac4f18521581536b652b789a47 F test/ctime.test 7bd009071e242aac4f18521581536b652b789a47
F test/date.test a18a2ce81add84b17b06559e82ad7bb91bc6ddff F test/date.test a18a2ce81add84b17b06559e82ad7bb91bc6ddff
F test/dbstatus.test 9eb484ba837c6f3f9bbcaecc29e6060a8c3ba6d2 F test/dbstatus.test 179575499759241bf92ca2fb86bd3ccc8a562aac
F test/dbstatus2.test dc57b0d9610851c0ff58a8e1b5b191678398b72a F test/dbstatus2.test dc57b0d9610851c0ff58a8e1b5b191678398b72a
F test/default.test 6faf23ccb300114924353007795aa9a8ec0aa9dc F test/default.test 6faf23ccb300114924353007795aa9a8ec0aa9dc
F test/delete.test a065b05d2ebf60fd16639c579a4adfb7c381c701 F test/delete.test a065b05d2ebf60fd16639c579a4adfb7c381c701
@@ -592,7 +592,7 @@ F test/manydb.test 28385ae2087967aa05c38624cec7d96ec74feb3e
F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f
F test/memdb.test 708a028d6d373e5b3842e4bdc8ba80998c9a4da6 F test/memdb.test 708a028d6d373e5b3842e4bdc8ba80998c9a4da6
F test/memleak.test 10b9c6c57e19fc68c32941495e9ba1c50123f6e2 F test/memleak.test 10b9c6c57e19fc68c32941495e9ba1c50123f6e2
F test/memsubsys1.test c0db8a1e99f4fa07cb858900c55bad9547899aa8 F test/memsubsys1.test a8f9e37567453a5d1d9d37ec102d4d88ab6be33f
F test/memsubsys2.test 3a1c1a9de48e5726faa85108b02459fae8cb9ee9 F test/memsubsys2.test 3a1c1a9de48e5726faa85108b02459fae8cb9ee9
F test/minmax.test 722d80816f7e096bf2c04f4111f1a6c1ba65453d F test/minmax.test 722d80816f7e096bf2c04f4111f1a6c1ba65453d
F test/minmax2.test 33504c01a03bd99226144e4b03f7631a274d66e0 F test/minmax2.test 33504c01a03bd99226144e4b03f7631a274d66e0
@@ -627,7 +627,7 @@ F test/pagesize.test 1dd51367e752e742f58e861e65ed7390603827a0
F test/pcache.test 065aa286e722ab24f2e51792c1f093bf60656b16 F test/pcache.test 065aa286e722ab24f2e51792c1f093bf60656b16
F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025 F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025
F test/permutations.test 522823b47238cb1754198f80817fe9f9158ede55 F test/permutations.test 522823b47238cb1754198f80817fe9f9158ede55
F test/pragma.test 1ea0c85be853135bb7468e6eed48ee12b04794d4 F test/pragma.test 7fa35e53085812dac94c2bfcbb02c2a4ad35df5e
F test/pragma2.test 3a55f82b954242c642f8342b17dffc8b47472947 F test/pragma2.test 3a55f82b954242c642f8342b17dffc8b47472947
F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552 F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552
F test/progress.test 5b075c3c790c7b2a61419bc199db87aaf48b8301 F test/progress.test 5b075c3c790c7b2a61419bc199db87aaf48b8301
@@ -975,7 +975,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
P 888b09dd8fc0a31b69852a2c10eebb5f31fe35de P a5418c7fc216a30abf7b2fa8c579aee586393a91 9f839ac05a9f3cfe587d2ccdccd50dac41baedbe
R e9cdc1916fc67db6e66156ee2c102eee R e41a73511b92616ee76fa30eb271c907
U drh U drh
Z 65f4e24eecf20b0f9a407d4be4414918 Z e97a12a6137cafdd18edeb6857a80579

View File

@@ -1 +1 @@
a5418c7fc216a30abf7b2fa8c579aee586393a91 457513f21f2438c61b1a214716e338a4e3eeaafa

View File

@@ -2482,9 +2482,9 @@ static int newDatabase(BtShared *pBt){
} }
pP1 = pBt->pPage1; pP1 = pBt->pPage1;
assert( pP1!=0 ); assert( pP1!=0 );
data = pP1->aData;
rc = sqlite3PagerWrite(pP1->pDbPage); rc = sqlite3PagerWrite(pP1->pDbPage);
if( rc ) return rc; if( rc ) return rc;
data = pP1->aData;
memcpy(data, zMagicHeader, sizeof(zMagicHeader)); memcpy(data, zMagicHeader, sizeof(zMagicHeader));
assert( sizeof(zMagicHeader)==16 ); assert( sizeof(zMagicHeader)==16 );
data[16] = (u8)((pBt->pageSize>>8)&0xff); data[16] = (u8)((pBt->pageSize>>8)&0xff);
@@ -3782,38 +3782,6 @@ static int getOverflowPage(
return (rc==SQLITE_DONE ? SQLITE_OK : rc); return (rc==SQLITE_DONE ? SQLITE_OK : rc);
} }
/*
** Copy data from a buffer to a page, or from a page to a buffer.
**
** pPayload is a pointer to data stored on database page pDbPage.
** If argument eOp is false, then nByte bytes of data are copied
** from pPayload to the buffer pointed at by pBuf. If eOp is true,
** then sqlite3PagerWrite() is called on pDbPage and nByte bytes
** of data are copied from the buffer pBuf to pPayload.
**
** SQLITE_OK is returned on success, otherwise an error code.
*/
static int copyPayload(
void *pPayload, /* Pointer to page data */
void *pBuf, /* Pointer to buffer */
int nByte, /* Number of bytes to copy */
int eOp, /* 0 -> copy from page, 1 -> copy to page */
DbPage *pDbPage /* Page containing pPayload */
){
if( eOp ){
/* Copy data from buffer to page (a write operation) */
int rc = sqlite3PagerWrite(pDbPage);
if( rc!=SQLITE_OK ){
return rc;
}
memcpy(pPayload, pBuf, nByte);
}else{
/* Copy data from page to buffer (a read operation) */
memcpy(pBuf, pPayload, nByte);
}
return SQLITE_OK;
}
/* /*
** This function is used to read or overwrite payload information ** This function is used to read or overwrite payload information
** for the entry that the pCur cursor is pointing to. If the eOp ** for the entry that the pCur cursor is pointing to. If the eOp
@@ -3861,6 +3829,7 @@ static int accessPayload(
assert( pCur->aiIdx[pCur->iPage]<pPage->nCell ); assert( pCur->aiIdx[pCur->iPage]<pPage->nCell );
assert( cursorHoldsMutex(pCur) ); assert( cursorHoldsMutex(pCur) );
getCellInfo(pCur); getCellInfo(pCur);
aPayload = pCur->info.pCell + pCur->info.nHeader; aPayload = pCur->info.pCell + pCur->info.nHeader;
nKey = (pPage->intKey ? 0 : (int)pCur->info.nKey); nKey = (pPage->intKey ? 0 : (int)pCur->info.nKey);
@@ -3878,7 +3847,14 @@ static int accessPayload(
if( a+offset>pCur->info.nLocal ){ if( a+offset>pCur->info.nLocal ){
a = pCur->info.nLocal - offset; a = pCur->info.nLocal - offset;
} }
rc = copyPayload(&aPayload[offset], pBuf, a, eOp, pPage->pDbPage); if( eOp ){
if( (rc = sqlite3PagerWrite(pPage->pDbPage))!=SQLITE_OK ) return rc;
getCellInfo(pCur);
aPayload = pCur->info.pCell + pCur->info.nHeader;
memcpy(aPayload+offset, pBuf, a);
}else{
memcpy(pBuf, aPayload+offset, a);
}
offset = 0; offset = 0;
pBuf += a; pBuf += a;
amt -= a; amt -= a;
@@ -3989,9 +3965,17 @@ static int accessPayload(
DbPage *pDbPage; DbPage *pDbPage;
rc = sqlite3PagerGet(pBt->pPager, nextPage, &pDbPage); rc = sqlite3PagerGet(pBt->pPager, nextPage, &pDbPage);
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
if( eOp && (rc = sqlite3PagerWrite(pDbPage))!=SQLITE_OK ){
sqlite3PagerUnref(pDbPage);
return rc;
}
aPayload = sqlite3PagerGetData(pDbPage); aPayload = sqlite3PagerGetData(pDbPage);
nextPage = get4byte(aPayload); nextPage = get4byte(aPayload);
rc = copyPayload(&aPayload[offset+4], pBuf, a, eOp, pDbPage); if( eOp ){
memcpy(&aPayload[offset+4], pBuf, a);
}else{
memcpy(pBuf, &aPayload[offset+4], a);
}
sqlite3PagerUnref(pDbPage); sqlite3PagerUnref(pDbPage);
offset = 0; offset = 0;
} }
@@ -7390,16 +7374,14 @@ void sqlite3BtreeGetMeta(Btree *p, int idx, u32 *pMeta){
*/ */
int sqlite3BtreeUpdateMeta(Btree *p, int idx, u32 iMeta){ int sqlite3BtreeUpdateMeta(Btree *p, int idx, u32 iMeta){
BtShared *pBt = p->pBt; BtShared *pBt = p->pBt;
unsigned char *pP1;
int rc; int rc;
assert( idx>=1 && idx<=15 ); assert( idx>=1 && idx<=15 );
sqlite3BtreeEnter(p); sqlite3BtreeEnter(p);
assert( p->inTrans==TRANS_WRITE ); assert( p->inTrans==TRANS_WRITE );
assert( pBt->pPage1!=0 ); assert( pBt->pPage1!=0 );
pP1 = pBt->pPage1->aData;
rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
put4byte(&pP1[36 + idx*4], iMeta); put4byte(&pBt->pPage1->aData[36 + idx*4], iMeta);
#ifndef SQLITE_OMIT_AUTOVACUUM #ifndef SQLITE_OMIT_AUTOVACUUM
if( idx==BTREE_INCR_VACUUM ){ if( idx==BTREE_INCR_VACUUM ){
assert( pBt->autoVacuum || iMeta==0 ); assert( pBt->autoVacuum || iMeta==0 );
@@ -8228,6 +8210,7 @@ int sqlite3BtreeSetVersion(Btree *pBtree, int iVersion){
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
aData = pBt->pPage1->aData;
aData[18] = (u8)iVersion; aData[18] = (u8)iVersion;
aData[19] = (u8)iVersion; aData[19] = (u8)iVersion;
} }

View File

@@ -147,7 +147,7 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
500, /* nLookaside */ 500, /* nLookaside */
{0,0,0,0,0,0,0,0}, /* m */ {0,0,0,0,0,0,0,0}, /* m */
{0,0,0,0,0,0,0,0,0}, /* mutex */ {0,0,0,0,0,0,0,0,0}, /* mutex */
{0,0,0,0,0,0,0,0,0,0,0}, /* pcache */ {0,0,0,0,0,0,0,0,0,0,0}, /* pcache2 */
(void*)0, /* pHeap */ (void*)0, /* pHeap */
0, /* nHeap */ 0, /* nHeap */
0, 0, /* mnHeap, mxHeap */ 0, 0, /* mnHeap, mxHeap */

View File

@@ -365,16 +365,25 @@ int sqlite3_config(int op, ...){
} }
case SQLITE_CONFIG_PCACHE: { case SQLITE_CONFIG_PCACHE: {
/* Specify an alternative page cache implementation */ /* no-op */
sqlite3GlobalConfig.pcache = *va_arg(ap, sqlite3_pcache_methods*); break;
}
case SQLITE_CONFIG_GETPCACHE: {
/* now an error */
rc = SQLITE_ERROR;
break; break;
} }
case SQLITE_CONFIG_GETPCACHE: { case SQLITE_CONFIG_PCACHE2: {
if( sqlite3GlobalConfig.pcache.xInit==0 ){ /* Specify an alternative page cache implementation */
sqlite3GlobalConfig.pcache2 = *va_arg(ap, sqlite3_pcache_methods2*);
break;
}
case SQLITE_CONFIG_GETPCACHE2: {
if( sqlite3GlobalConfig.pcache2.xInit==0 ){
sqlite3PCacheSetDefault(); sqlite3PCacheSetDefault();
} }
*va_arg(ap, sqlite3_pcache_methods*) = sqlite3GlobalConfig.pcache; *va_arg(ap, sqlite3_pcache_methods2*) = sqlite3GlobalConfig.pcache2;
break; break;
} }
@@ -473,21 +482,21 @@ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){
if( db->lookaside.bMalloced ){ if( db->lookaside.bMalloced ){
sqlite3_free(db->lookaside.pStart); sqlite3_free(db->lookaside.pStart);
} }
/* The size of a lookaside slot needs to be larger than a pointer /* The size of a lookaside slot after ROUNDDOWN8 needs to be larger
** to be useful. ** than a pointer to be useful.
*/ */
sz = ROUNDDOWN8(sz); /* IMP: R-33038-09382 */
if( sz<=(int)sizeof(LookasideSlot*) ) sz = 0; if( sz<=(int)sizeof(LookasideSlot*) ) sz = 0;
if( cnt<0 ) cnt = 0; if( cnt<0 ) cnt = 0;
if( sz==0 || cnt==0 ){ if( sz==0 || cnt==0 ){
sz = 0; sz = 0;
pStart = 0; pStart = 0;
}else if( pBuf==0 ){ }else if( pBuf==0 ){
sz = ROUNDDOWN8(sz); /* IMP: R-33038-09382 */
sqlite3BeginBenignMalloc(); sqlite3BeginBenignMalloc();
pStart = sqlite3Malloc( sz*cnt ); /* IMP: R-61949-35727 */ pStart = sqlite3Malloc( sz*cnt ); /* IMP: R-61949-35727 */
sqlite3EndBenignMalloc(); sqlite3EndBenignMalloc();
if( pStart ) cnt = sqlite3MallocSize(pStart)/sz;
}else{ }else{
sz = ROUNDDOWN8(sz); /* IMP: R-33038-09382 */
pStart = pBuf; pStart = pBuf;
} }
db->lookaside.pStart = pStart; db->lookaside.pStart = pStart;
@@ -2889,15 +2898,6 @@ int sqlite3_test_control(int op, ...){
} }
#endif #endif
/* sqlite3_test_control(SQLITE_TESTCTRL_PGHDRSZ)
**
** Return the size of a pcache header in bytes.
*/
case SQLITE_TESTCTRL_PGHDRSZ: {
rc = sizeof(PgHdr);
break;
}
/* sqlite3_test_control(SQLITE_TESTCTRL_SCRATCHMALLOC, sz, &pNew, pFree); /* sqlite3_test_control(SQLITE_TESTCTRL_SCRATCHMALLOC, sz, &pNew, pFree);
** **
** Pass pFree into sqlite3ScratchFree(). ** Pass pFree into sqlite3ScratchFree().

View File

@@ -26,6 +26,10 @@
*/ */
#ifdef SQLITE_SYSTEM_MALLOC #ifdef SQLITE_SYSTEM_MALLOC
#ifdef HAVE_MALLOC_USABLE_SIZE
#include <malloc.h>
#endif
/* /*
** Like malloc(), but remember the size of the allocation ** Like malloc(), but remember the size of the allocation
** so that we can find it later using sqlite3MemSize(). ** so that we can find it later using sqlite3MemSize().
@@ -35,6 +39,14 @@
** routines. ** routines.
*/ */
static void *sqlite3MemMalloc(int nByte){ static void *sqlite3MemMalloc(int nByte){
#ifdef HAVE_MALLOC_USABLE_SIZE
void *p = malloc( nByte );
if( p==0 ){
testcase( sqlite3GlobalConfig.xLog!=0 );
sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte);
}
return p;
#else
sqlite3_int64 *p; sqlite3_int64 *p;
assert( nByte>0 ); assert( nByte>0 );
nByte = ROUND8(nByte); nByte = ROUND8(nByte);
@@ -47,6 +59,7 @@ static void *sqlite3MemMalloc(int nByte){
sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte); sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte);
} }
return (void *)p; return (void *)p;
#endif
} }
/* /*
@@ -58,10 +71,14 @@ static void *sqlite3MemMalloc(int nByte){
** by higher-level routines. ** by higher-level routines.
*/ */
static void sqlite3MemFree(void *pPrior){ static void sqlite3MemFree(void *pPrior){
#if HAVE_MALLOC_USABLE_SIZE
free(pPrior);
#else
sqlite3_int64 *p = (sqlite3_int64*)pPrior; sqlite3_int64 *p = (sqlite3_int64*)pPrior;
assert( pPrior!=0 ); assert( pPrior!=0 );
p--; p--;
free(p); free(p);
#endif
} }
/* /*
@@ -69,11 +86,15 @@ static void sqlite3MemFree(void *pPrior){
** or xRealloc(). ** or xRealloc().
*/ */
static int sqlite3MemSize(void *pPrior){ static int sqlite3MemSize(void *pPrior){
#if HAVE_MALLOC_USABLE_SIZE
return pPrior ? (int)malloc_usable_size(pPrior) : 0;
#else
sqlite3_int64 *p; sqlite3_int64 *p;
if( pPrior==0 ) return 0; if( pPrior==0 ) return 0;
p = (sqlite3_int64*)pPrior; p = (sqlite3_int64*)pPrior;
p--; p--;
return (int)p[0]; return (int)p[0];
#endif
} }
/* /*
@@ -87,6 +108,16 @@ static int sqlite3MemSize(void *pPrior){
** routines and redirected to xFree. ** routines and redirected to xFree.
*/ */
static void *sqlite3MemRealloc(void *pPrior, int nByte){ static void *sqlite3MemRealloc(void *pPrior, int nByte){
#if HAVE_MALLOC_USABLE_SIZE
void *p = realloc(pPrior, nByte);
if( p==0 ){
testcase( sqlite3GlobalConfig.xLog!=0 );
sqlite3_log(SQLITE_NOMEM,
"failed memory resize %u to %u bytes",
malloc_usable_size(pPrior), nByte);
}
return p;
#else
sqlite3_int64 *p = (sqlite3_int64*)pPrior; sqlite3_int64 *p = (sqlite3_int64*)pPrior;
assert( pPrior!=0 && nByte>0 ); assert( pPrior!=0 && nByte>0 );
assert( nByte==ROUND8(nByte) ); /* EV: R-46199-30249 */ assert( nByte==ROUND8(nByte) ); /* EV: R-46199-30249 */
@@ -102,6 +133,7 @@ static void *sqlite3MemRealloc(void *pPrior, int nByte){
sqlite3MemSize(pPrior), nByte); sqlite3MemSize(pPrior), nByte);
} }
return (void*)p; return (void*)p;
#endif
} }
/* /*

View File

@@ -20,7 +20,7 @@ struct PCache {
PgHdr *pDirty, *pDirtyTail; /* List of dirty pages in LRU order */ PgHdr *pDirty, *pDirtyTail; /* List of dirty pages in LRU order */
PgHdr *pSynced; /* Last synced page in dirty page list */ PgHdr *pSynced; /* Last synced page in dirty page list */
int nRef; /* Number of referenced pages */ int nRef; /* Number of referenced pages */
int nMax; /* Configured cache size */ int szCache; /* Configured cache size */
int szPage; /* Size of every page in this cache */ int szPage; /* Size of every page in this cache */
int szExtra; /* Size of extra space for each page */ int szExtra; /* Size of extra space for each page */
int bPurgeable; /* True if pages are on backing store */ int bPurgeable; /* True if pages are on backing store */
@@ -131,7 +131,7 @@ static void pcacheUnpin(PgHdr *p){
if( p->pgno==1 ){ if( p->pgno==1 ){
pCache->pPage1 = 0; pCache->pPage1 = 0;
} }
sqlite3GlobalConfig.pcache.xUnpin(pCache->pCache, p, 0); sqlite3GlobalConfig.pcache2.xUnpin(pCache->pCache, p->pPage, 0);
} }
} }
@@ -141,18 +141,18 @@ static void pcacheUnpin(PgHdr *p){
** functions are threadsafe. ** functions are threadsafe.
*/ */
int sqlite3PcacheInitialize(void){ int sqlite3PcacheInitialize(void){
if( sqlite3GlobalConfig.pcache.xInit==0 ){ if( sqlite3GlobalConfig.pcache2.xInit==0 ){
/* IMPLEMENTATION-OF: R-26801-64137 If the xInit() method is NULL, then the /* IMPLEMENTATION-OF: R-26801-64137 If the xInit() method is NULL, then the
** built-in default page cache is used instead of the application defined ** built-in default page cache is used instead of the application defined
** page cache. */ ** page cache. */
sqlite3PCacheSetDefault(); sqlite3PCacheSetDefault();
} }
return sqlite3GlobalConfig.pcache.xInit(sqlite3GlobalConfig.pcache.pArg); return sqlite3GlobalConfig.pcache2.xInit(sqlite3GlobalConfig.pcache2.pArg);
} }
void sqlite3PcacheShutdown(void){ void sqlite3PcacheShutdown(void){
if( sqlite3GlobalConfig.pcache.xShutdown ){ if( sqlite3GlobalConfig.pcache2.xShutdown ){
/* IMPLEMENTATION-OF: R-26000-56589 The xShutdown() method may be NULL. */ /* IMPLEMENTATION-OF: R-26000-56589 The xShutdown() method may be NULL. */
sqlite3GlobalConfig.pcache.xShutdown(sqlite3GlobalConfig.pcache.pArg); sqlite3GlobalConfig.pcache2.xShutdown(sqlite3GlobalConfig.pcache2.pArg);
} }
} }
@@ -181,7 +181,7 @@ void sqlite3PcacheOpen(
p->bPurgeable = bPurgeable; p->bPurgeable = bPurgeable;
p->xStress = xStress; p->xStress = xStress;
p->pStress = pStress; p->pStress = pStress;
p->nMax = 100; p->szCache = 100;
} }
/* /*
@@ -191,13 +191,24 @@ void sqlite3PcacheOpen(
void sqlite3PcacheSetPageSize(PCache *pCache, int szPage){ void sqlite3PcacheSetPageSize(PCache *pCache, int szPage){
assert( pCache->nRef==0 && pCache->pDirty==0 ); assert( pCache->nRef==0 && pCache->pDirty==0 );
if( pCache->pCache ){ if( pCache->pCache ){
sqlite3GlobalConfig.pcache.xDestroy(pCache->pCache); sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache);
pCache->pCache = 0; pCache->pCache = 0;
pCache->pPage1 = 0; pCache->pPage1 = 0;
} }
pCache->szPage = szPage; pCache->szPage = szPage;
} }
/*
** Compute the number of pages of cache requested.
*/
static int numberOfCachePages(PCache *p){
if( p->szCache>=0 ){
return p->szCache;
}else{
return (-1024*p->szCache)/(p->szPage+p->szExtra);
}
}
/* /*
** Try to obtain a page from the cache. ** Try to obtain a page from the cache.
*/ */
@@ -207,7 +218,8 @@ int sqlite3PcacheFetch(
int createFlag, /* If true, create page if it does not exist already */ int createFlag, /* If true, create page if it does not exist already */
PgHdr **ppPage /* Write the page here */ PgHdr **ppPage /* Write the page here */
){ ){
PgHdr *pPage = 0; sqlite3_pcache_page *pPage = 0;
PgHdr *pPgHdr = 0;
int eCreate; int eCreate;
assert( pCache!=0 ); assert( pCache!=0 );
@@ -219,19 +231,19 @@ int sqlite3PcacheFetch(
*/ */
if( !pCache->pCache && createFlag ){ if( !pCache->pCache && createFlag ){
sqlite3_pcache *p; sqlite3_pcache *p;
int nByte; p = sqlite3GlobalConfig.pcache2.xCreate(
nByte = pCache->szPage + pCache->szExtra + sizeof(PgHdr); pCache->szPage, pCache->szExtra + sizeof(PgHdr), pCache->bPurgeable
p = sqlite3GlobalConfig.pcache.xCreate(nByte, pCache->bPurgeable); );
if( !p ){ if( !p ){
return SQLITE_NOMEM; return SQLITE_NOMEM;
} }
sqlite3GlobalConfig.pcache.xCachesize(p, pCache->nMax); sqlite3GlobalConfig.pcache2.xCachesize(p, numberOfCachePages(pCache));
pCache->pCache = p; pCache->pCache = p;
} }
eCreate = createFlag * (1 + (!pCache->bPurgeable || !pCache->pDirty)); eCreate = createFlag * (1 + (!pCache->bPurgeable || !pCache->pDirty));
if( pCache->pCache ){ if( pCache->pCache ){
pPage = sqlite3GlobalConfig.pcache.xFetch(pCache->pCache, pgno, eCreate); pPage = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, eCreate);
} }
if( !pPage && eCreate==1 ){ if( !pPage && eCreate==1 ){
@@ -258,7 +270,7 @@ int sqlite3PcacheFetch(
"spill page %d making room for %d - cache used: %d/%d", "spill page %d making room for %d - cache used: %d/%d",
pPg->pgno, pgno, pPg->pgno, pgno,
sqlite3GlobalConfig.pcache.xPagecount(pCache->pCache), sqlite3GlobalConfig.pcache.xPagecount(pCache->pCache),
pCache->nMax); numberOfCachePages(pCache));
#endif #endif
rc = pCache->xStress(pCache->pStress, pPg); rc = pCache->xStress(pCache->pStress, pPg);
if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){ if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){
@@ -266,33 +278,36 @@ int sqlite3PcacheFetch(
} }
} }
pPage = sqlite3GlobalConfig.pcache.xFetch(pCache->pCache, pgno, 2); pPage = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, 2);
} }
if( pPage ){ if( pPage ){
if( !pPage->pData ){ pPgHdr = (PgHdr *)pPage->pExtra;
memset(pPage, 0, sizeof(PgHdr));
pPage->pData = (void *)&pPage[1];
pPage->pExtra = (void*)&((char *)pPage->pData)[pCache->szPage];
memset(pPage->pExtra, 0, pCache->szExtra);
pPage->pCache = pCache;
pPage->pgno = pgno;
}
assert( pPage->pCache==pCache );
assert( pPage->pgno==pgno );
assert( pPage->pData==(void *)&pPage[1] );
assert( pPage->pExtra==(void *)&((char *)&pPage[1])[pCache->szPage] );
if( 0==pPage->nRef ){ if( !pPgHdr->pPage ){
memset(pPgHdr, 0, sizeof(PgHdr));
pPgHdr->pPage = pPage;
pPgHdr->pData = pPage->pBuf;
pPgHdr->pExtra = (void *)&pPgHdr[1];
memset(pPgHdr->pExtra, 0, pCache->szExtra);
pPgHdr->pCache = pCache;
pPgHdr->pgno = pgno;
}
assert( pPgHdr->pCache==pCache );
assert( pPgHdr->pgno==pgno );
assert( pPgHdr->pData==pPage->pBuf );
assert( pPgHdr->pExtra==(void *)&pPgHdr[1] );
if( 0==pPgHdr->nRef ){
pCache->nRef++; pCache->nRef++;
} }
pPage->nRef++; pPgHdr->nRef++;
if( pgno==1 ){ if( pgno==1 ){
pCache->pPage1 = pPage; pCache->pPage1 = pPgHdr;
} }
} }
*ppPage = pPage; *ppPage = pPgHdr;
return (pPage==0 && eCreate) ? SQLITE_NOMEM : SQLITE_OK; return (pPgHdr==0 && eCreate) ? SQLITE_NOMEM : SQLITE_OK;
} }
/* /*
@@ -339,7 +354,7 @@ void sqlite3PcacheDrop(PgHdr *p){
if( p->pgno==1 ){ if( p->pgno==1 ){
pCache->pPage1 = 0; pCache->pPage1 = 0;
} }
sqlite3GlobalConfig.pcache.xUnpin(pCache->pCache, p, 1); sqlite3GlobalConfig.pcache2.xUnpin(pCache->pCache, p->pPage, 1);
} }
/* /*
@@ -397,7 +412,7 @@ void sqlite3PcacheMove(PgHdr *p, Pgno newPgno){
PCache *pCache = p->pCache; PCache *pCache = p->pCache;
assert( p->nRef>0 ); assert( p->nRef>0 );
assert( newPgno>0 ); assert( newPgno>0 );
sqlite3GlobalConfig.pcache.xRekey(pCache->pCache, p, p->pgno, newPgno); sqlite3GlobalConfig.pcache2.xRekey(pCache->pCache, p->pPage, p->pgno,newPgno);
p->pgno = newPgno; p->pgno = newPgno;
if( (p->flags&PGHDR_DIRTY) && (p->flags&PGHDR_NEED_SYNC) ){ if( (p->flags&PGHDR_DIRTY) && (p->flags&PGHDR_NEED_SYNC) ){
pcacheRemoveFromDirtyList(p); pcacheRemoveFromDirtyList(p);
@@ -434,7 +449,7 @@ void sqlite3PcacheTruncate(PCache *pCache, Pgno pgno){
memset(pCache->pPage1->pData, 0, pCache->szPage); memset(pCache->pPage1->pData, 0, pCache->szPage);
pgno = 1; pgno = 1;
} }
sqlite3GlobalConfig.pcache.xTruncate(pCache->pCache, pgno+1); sqlite3GlobalConfig.pcache2.xTruncate(pCache->pCache, pgno+1);
} }
} }
@@ -443,7 +458,7 @@ void sqlite3PcacheTruncate(PCache *pCache, Pgno pgno){
*/ */
void sqlite3PcacheClose(PCache *pCache){ void sqlite3PcacheClose(PCache *pCache){
if( pCache->pCache ){ if( pCache->pCache ){
sqlite3GlobalConfig.pcache.xDestroy(pCache->pCache); sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache);
} }
} }
@@ -555,7 +570,7 @@ int sqlite3PcachePageRefcount(PgHdr *p){
int sqlite3PcachePagecount(PCache *pCache){ int sqlite3PcachePagecount(PCache *pCache){
int nPage = 0; int nPage = 0;
if( pCache->pCache ){ if( pCache->pCache ){
nPage = sqlite3GlobalConfig.pcache.xPagecount(pCache->pCache); nPage = sqlite3GlobalConfig.pcache2.xPagecount(pCache->pCache);
} }
return nPage; return nPage;
} }
@@ -565,7 +580,7 @@ int sqlite3PcachePagecount(PCache *pCache){
** Get the suggested cache-size value. ** Get the suggested cache-size value.
*/ */
int sqlite3PcacheGetCachesize(PCache *pCache){ int sqlite3PcacheGetCachesize(PCache *pCache){
return pCache->nMax; return numberOfCachePages(pCache);
} }
#endif #endif
@@ -573,9 +588,10 @@ int sqlite3PcacheGetCachesize(PCache *pCache){
** Set the suggested cache-size value. ** Set the suggested cache-size value.
*/ */
void sqlite3PcacheSetCachesize(PCache *pCache, int mxPage){ void sqlite3PcacheSetCachesize(PCache *pCache, int mxPage){
pCache->nMax = mxPage; pCache->szCache = mxPage;
if( pCache->pCache ){ if( pCache->pCache ){
sqlite3GlobalConfig.pcache.xCachesize(pCache->pCache, mxPage); sqlite3GlobalConfig.pcache2.xCachesize(pCache->pCache,
numberOfCachePages(pCache));
} }
} }

View File

@@ -23,7 +23,8 @@ typedef struct PCache PCache;
** structure. ** structure.
*/ */
struct PgHdr { struct PgHdr {
void *pData; /* Content of this page */ sqlite3_pcache_page *pPage; /* Pcache object page handle */
void *pData; /* Page data */
void *pExtra; /* Extra content */ void *pExtra; /* Extra content */
PgHdr *pDirty; /* Transient list of dirty pages */ PgHdr *pDirty; /* Transient list of dirty pages */
Pgno pgno; /* Page number for this page */ Pgno pgno; /* Page number for this page */

View File

@@ -24,7 +24,6 @@ typedef struct PgHdr1 PgHdr1;
typedef struct PgFreeslot PgFreeslot; typedef struct PgFreeslot PgFreeslot;
typedef struct PGroup PGroup; typedef struct PGroup PGroup;
/* Each page cache (or PCache) belongs to a PGroup. A PGroup is a set /* Each page cache (or PCache) belongs to a PGroup. A PGroup is a set
** of one or more PCaches that are able to recycle each others unpinned ** of one or more PCaches that are able to recycle each others unpinned
** pages when they are under memory pressure. A PGroup is an instance of ** pages when they are under memory pressure. A PGroup is an instance of
@@ -72,6 +71,7 @@ struct PCache1 {
*/ */
PGroup *pGroup; /* PGroup this cache belongs to */ PGroup *pGroup; /* PGroup this cache belongs to */
int szPage; /* Size of allocated pages in bytes */ int szPage; /* Size of allocated pages in bytes */
int szExtra; /* Size of extra space in bytes */
int bPurgeable; /* True if cache is purgeable */ int bPurgeable; /* True if cache is purgeable */
unsigned int nMin; /* Minimum number of pages reserved */ unsigned int nMin; /* Minimum number of pages reserved */
unsigned int nMax; /* Configured "cache_size" value */ unsigned int nMax; /* Configured "cache_size" value */
@@ -90,11 +90,12 @@ struct PCache1 {
/* /*
** Each cache entry is represented by an instance of the following ** Each cache entry is represented by an instance of the following
** structure. A buffer of PgHdr1.pCache->szPage bytes is allocated ** structure. Unless SQLITE_PCACHE_SEPARATE_HEADER is defined, a buffer of
** directly before this structure in memory (see the PGHDR1_TO_PAGE() ** PgHdr1.pCache->szPage bytes is allocated directly before this structure
** macro below). ** in memory.
*/ */
struct PgHdr1 { struct PgHdr1 {
sqlite3_pcache_page page;
unsigned int iKey; /* Key value (page number) */ unsigned int iKey; /* Key value (page number) */
PgHdr1 *pNext; /* Next in hash table chain */ PgHdr1 *pNext; /* Next in hash table chain */
PCache1 *pCache; /* Cache that currently owns this page */ PCache1 *pCache; /* Cache that currently owns this page */
@@ -144,21 +145,6 @@ static SQLITE_WSD struct PCacheGlobal {
*/ */
#define pcache1 (GLOBAL(struct PCacheGlobal, pcache1_g)) #define pcache1 (GLOBAL(struct PCacheGlobal, pcache1_g))
/*
** When a PgHdr1 structure is allocated, the associated PCache1.szPage
** bytes of data are located directly before it in memory (i.e. the total
** size of the allocation is sizeof(PgHdr1)+PCache1.szPage byte). The
** PGHDR1_TO_PAGE() macro takes a pointer to a PgHdr1 structure as
** an argument and returns a pointer to the associated block of szPage
** bytes. The PAGE_TO_PGHDR1() macro does the opposite: its argument is
** a pointer to a block of szPage bytes of data and the return value is
** a pointer to the associated PgHdr1 structure.
**
** assert( PGHDR1_TO_PAGE(PAGE_TO_PGHDR1(pCache, X))==X );
*/
#define PGHDR1_TO_PAGE(p) (void*)(((char*)p) - p->pCache->szPage)
#define PAGE_TO_PGHDR1(c, p) (PgHdr1*)(((char*)p) + c->szPage)
/* /*
** Macros to enter and leave the PCache LRU mutex. ** Macros to enter and leave the PCache LRU mutex.
*/ */
@@ -288,7 +274,6 @@ static int pcache1MemSize(void *p){
** Allocate a new page object initially associated with cache pCache. ** Allocate a new page object initially associated with cache pCache.
*/ */
static PgHdr1 *pcache1AllocPage(PCache1 *pCache){ static PgHdr1 *pcache1AllocPage(PCache1 *pCache){
int nByte = sizeof(PgHdr1) + pCache->szPage;
PgHdr1 *p = 0; PgHdr1 *p = 0;
void *pPg; void *pPg;
@@ -297,16 +282,29 @@ static PgHdr1 *pcache1AllocPage(PCache1 *pCache){
** this mutex is not held. */ ** this mutex is not held. */
assert( sqlite3_mutex_held(pCache->pGroup->mutex) ); assert( sqlite3_mutex_held(pCache->pGroup->mutex) );
pcache1LeaveMutex(pCache->pGroup); pcache1LeaveMutex(pCache->pGroup);
pPg = pcache1Alloc(nByte); #ifdef SQLITE_PCACHE_SEPARATE_HEADER
pPg = pcache1Alloc(pCache->szPage);
p = sqlite3Malloc(sizeof(PgHdr1) + pCache->szExtra);
if( !pPg || !p ){
pcache1Free(pPg);
sqlite3_free(p);
pPg = 0;
}
#else
pPg = pcache1Alloc(sizeof(PgHdr1) + pCache->szPage + pCache->szExtra);
p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage];
#endif
pcache1EnterMutex(pCache->pGroup); pcache1EnterMutex(pCache->pGroup);
if( pPg ){ if( pPg ){
p = PAGE_TO_PGHDR1(pCache, pPg); p->page.pBuf = pPg;
p->page.pExtra = &p[1];
if( pCache->bPurgeable ){ if( pCache->bPurgeable ){
pCache->pGroup->nCurrentPage++; pCache->pGroup->nCurrentPage++;
} }
return p;
} }
return p; return 0;
} }
/* /*
@@ -320,7 +318,10 @@ static void pcache1FreePage(PgHdr1 *p){
if( ALWAYS(p) ){ if( ALWAYS(p) ){
PCache1 *pCache = p->pCache; PCache1 *pCache = p->pCache;
assert( sqlite3_mutex_held(p->pCache->pGroup->mutex) ); assert( sqlite3_mutex_held(p->pCache->pGroup->mutex) );
pcache1Free(PGHDR1_TO_PAGE(p)); pcache1Free(p->page.pBuf);
#ifdef SQLITE_PCACHE_SEPARATE_HEADER
sqlite3_free(p);
#endif
if( pCache->bPurgeable ){ if( pCache->bPurgeable ){
pCache->pGroup->nCurrentPage--; pCache->pGroup->nCurrentPage--;
} }
@@ -361,7 +362,7 @@ void sqlite3PageFree(void *p){
** the heap even further. ** the heap even further.
*/ */
static int pcache1UnderMemoryPressure(PCache1 *pCache){ static int pcache1UnderMemoryPressure(PCache1 *pCache){
if( pcache1.nSlot && pCache->szPage<=pcache1.szSlot ){ if( pcache1.nSlot && (pCache->szPage+pCache->szExtra)<=pcache1.szSlot ){
return pcache1.bUnderPressure; return pcache1.bUnderPressure;
}else{ }else{
return sqlite3HeapNearlyFull(); return sqlite3HeapNearlyFull();
@@ -552,7 +553,7 @@ static void pcache1Shutdown(void *NotUsed){
** **
** Allocate a new cache. ** Allocate a new cache.
*/ */
static sqlite3_pcache *pcache1Create(int szPage, int bPurgeable){ static sqlite3_pcache *pcache1Create(int szPage, int szExtra, int bPurgeable){
PCache1 *pCache; /* The newly created page cache */ PCache1 *pCache; /* The newly created page cache */
PGroup *pGroup; /* The group the new page cache will belong to */ PGroup *pGroup; /* The group the new page cache will belong to */
int sz; /* Bytes of memory required to allocate the new cache */ int sz; /* Bytes of memory required to allocate the new cache */
@@ -575,6 +576,9 @@ static sqlite3_pcache *pcache1Create(int szPage, int bPurgeable){
int separateCache = sqlite3GlobalConfig.bCoreMutex>0; int separateCache = sqlite3GlobalConfig.bCoreMutex>0;
#endif #endif
assert( (szPage & (szPage-1))==0 && szPage>=512 && szPage<=65536 );
assert( szExtra < 300 );
sz = sizeof(PCache1) + sizeof(PGroup)*separateCache; sz = sizeof(PCache1) + sizeof(PGroup)*separateCache;
pCache = (PCache1 *)sqlite3_malloc(sz); pCache = (PCache1 *)sqlite3_malloc(sz);
if( pCache ){ if( pCache ){
@@ -587,6 +591,7 @@ static sqlite3_pcache *pcache1Create(int szPage, int bPurgeable){
} }
pCache->pGroup = pGroup; pCache->pGroup = pGroup;
pCache->szPage = szPage; pCache->szPage = szPage;
pCache->szExtra = szExtra;
pCache->bPurgeable = (bPurgeable ? 1 : 0); pCache->bPurgeable = (bPurgeable ? 1 : 0);
if( bPurgeable ){ if( bPurgeable ){
pCache->nMin = 10; pCache->nMin = 10;
@@ -684,7 +689,11 @@ static int pcache1Pagecount(sqlite3_pcache *p){
** **
** 5. Otherwise, allocate and return a new page buffer. ** 5. Otherwise, allocate and return a new page buffer.
*/ */
static void *pcache1Fetch(sqlite3_pcache *p, unsigned int iKey, int createFlag){ static sqlite3_pcache_page *pcache1Fetch(
sqlite3_pcache *p,
unsigned int iKey,
int createFlag
){
int nPinned; int nPinned;
PCache1 *pCache = (PCache1 *)p; PCache1 *pCache = (PCache1 *)p;
PGroup *pGroup; PGroup *pGroup;
@@ -719,7 +728,6 @@ static void *pcache1Fetch(sqlite3_pcache *p, unsigned int iKey, int createFlag){
pGroup = pCache->pGroup; pGroup = pCache->pGroup;
#endif #endif
/* Step 3: Abort if createFlag is 1 but the cache is nearly full */ /* Step 3: Abort if createFlag is 1 but the cache is nearly full */
nPinned = pCache->nPage - pCache->nRecyclable; nPinned = pCache->nPage - pCache->nRecyclable;
assert( nPinned>=0 ); assert( nPinned>=0 );
@@ -743,16 +751,24 @@ static void *pcache1Fetch(sqlite3_pcache *p, unsigned int iKey, int createFlag){
|| pGroup->nCurrentPage>=pGroup->nMaxPage || pGroup->nCurrentPage>=pGroup->nMaxPage
|| pcache1UnderMemoryPressure(pCache) || pcache1UnderMemoryPressure(pCache)
)){ )){
PCache1 *pOtherCache; PCache1 *pOther;
pPage = pGroup->pLruTail; pPage = pGroup->pLruTail;
pcache1RemoveFromHash(pPage); pcache1RemoveFromHash(pPage);
pcache1PinPage(pPage); pcache1PinPage(pPage);
if( (pOtherCache = pPage->pCache)->szPage!=pCache->szPage ){ pOther = pPage->pCache;
/* We want to verify that szPage and szExtra are the same for pOther
** and pCache. Assert that we can verify this by comparing sums. */
assert( (pCache->szPage & (pCache->szPage-1))==0 && pCache->szPage>=512 );
assert( pCache->szExtra<512 );
assert( (pOther->szPage & (pOther->szPage-1))==0 && pOther->szPage>=512 );
assert( pOther->szExtra<512 );
if( pOther->szPage+pOther->szExtra != pCache->szPage+pCache->szExtra ){
pcache1FreePage(pPage); pcache1FreePage(pPage);
pPage = 0; pPage = 0;
}else{ }else{
pGroup->nCurrentPage -= pGroup->nCurrentPage -= (pOther->bPurgeable - pCache->bPurgeable);
(pOtherCache->bPurgeable - pCache->bPurgeable);
} }
} }
@@ -773,7 +789,7 @@ static void *pcache1Fetch(sqlite3_pcache *p, unsigned int iKey, int createFlag){
pPage->pCache = pCache; pPage->pCache = pCache;
pPage->pLruPrev = 0; pPage->pLruPrev = 0;
pPage->pLruNext = 0; pPage->pLruNext = 0;
*(void **)(PGHDR1_TO_PAGE(pPage)) = 0; *(void **)pPage->page.pExtra = 0;
pCache->apHash[h] = pPage; pCache->apHash[h] = pPage;
} }
@@ -782,7 +798,7 @@ fetch_out:
pCache->iMaxKey = iKey; pCache->iMaxKey = iKey;
} }
pcache1LeaveMutex(pGroup); pcache1LeaveMutex(pGroup);
return (pPage ? PGHDR1_TO_PAGE(pPage) : 0); return &pPage->page;
} }
@@ -791,9 +807,13 @@ fetch_out:
** **
** Mark a page as unpinned (eligible for asynchronous recycling). ** Mark a page as unpinned (eligible for asynchronous recycling).
*/ */
static void pcache1Unpin(sqlite3_pcache *p, void *pPg, int reuseUnlikely){ static void pcache1Unpin(
sqlite3_pcache *p,
sqlite3_pcache_page *pPg,
int reuseUnlikely
){
PCache1 *pCache = (PCache1 *)p; PCache1 *pCache = (PCache1 *)p;
PgHdr1 *pPage = PAGE_TO_PGHDR1(pCache, pPg); PgHdr1 *pPage = (PgHdr1 *)pPg;
PGroup *pGroup = pCache->pGroup; PGroup *pGroup = pCache->pGroup;
assert( pPage->pCache==pCache ); assert( pPage->pCache==pCache );
@@ -829,12 +849,12 @@ static void pcache1Unpin(sqlite3_pcache *p, void *pPg, int reuseUnlikely){
*/ */
static void pcache1Rekey( static void pcache1Rekey(
sqlite3_pcache *p, sqlite3_pcache *p,
void *pPg, sqlite3_pcache_page *pPg,
unsigned int iOld, unsigned int iOld,
unsigned int iNew unsigned int iNew
){ ){
PCache1 *pCache = (PCache1 *)p; PCache1 *pCache = (PCache1 *)p;
PgHdr1 *pPage = PAGE_TO_PGHDR1(pCache, pPg); PgHdr1 *pPage = (PgHdr1 *)pPg;
PgHdr1 **pp; PgHdr1 **pp;
unsigned int h; unsigned int h;
assert( pPage->iKey==iOld ); assert( pPage->iKey==iOld );
@@ -903,7 +923,8 @@ static void pcache1Destroy(sqlite3_pcache *p){
** already provided an alternative. ** already provided an alternative.
*/ */
void sqlite3PCacheSetDefault(void){ void sqlite3PCacheSetDefault(void){
static const sqlite3_pcache_methods defaultMethods = { static const sqlite3_pcache_methods2 defaultMethods = {
1, /* iVersion */
0, /* pArg */ 0, /* pArg */
pcache1Init, /* xInit */ pcache1Init, /* xInit */
pcache1Shutdown, /* xShutdown */ pcache1Shutdown, /* xShutdown */
@@ -916,7 +937,7 @@ void sqlite3PCacheSetDefault(void){
pcache1Truncate, /* xTruncate */ pcache1Truncate, /* xTruncate */
pcache1Destroy /* xDestroy */ pcache1Destroy /* xDestroy */
}; };
sqlite3_config(SQLITE_CONFIG_PCACHE, &defaultMethods); sqlite3_config(SQLITE_CONFIG_PCACHE2, &defaultMethods);
} }
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
@@ -937,7 +958,10 @@ int sqlite3PcacheReleaseMemory(int nReq){
PgHdr1 *p; PgHdr1 *p;
pcache1EnterMutex(&pcache1.grp); pcache1EnterMutex(&pcache1.grp);
while( (nReq<0 || nFree<nReq) && ((p=pcache1.grp.pLruTail)!=0) ){ while( (nReq<0 || nFree<nReq) && ((p=pcache1.grp.pLruTail)!=0) ){
nFree += pcache1MemSize(PGHDR1_TO_PAGE(p)); nFree += pcache1MemSize(p->page.pBuf);
#ifdef SQLITE_PCACHE_SEPARATE_HEADER
nFree += sqlite3MemSize(p);
#endif
pcache1PinPage(p); pcache1PinPage(p);
pcache1RemoveFromHash(p); pcache1RemoveFromHash(p);
pcache1FreePage(p); pcache1FreePage(p);

View File

@@ -346,7 +346,7 @@ void sqlite3Pragma(
goto pragma_out; goto pragma_out;
} }
#ifndef SQLITE_OMIT_PAGER_PRAGMAS #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
/* /*
** PRAGMA [database.]default_cache_size ** PRAGMA [database.]default_cache_size
** PRAGMA [database.]default_cache_size=N ** PRAGMA [database.]default_cache_size=N
@@ -395,7 +395,9 @@ void sqlite3Pragma(
sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size); sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size);
} }
}else }else
#endif /* !SQLITE_OMIT_PAGER_PRAGMAS && !SQLITE_OMIT_DEPRECATED */
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
/* /*
** PRAGMA [database.]page_size ** PRAGMA [database.]page_size
** PRAGMA [database.]page_size=N ** PRAGMA [database.]page_size=N
@@ -416,7 +418,7 @@ void sqlite3Pragma(
** buffer that the pager module resizes using sqlite3_realloc(). ** buffer that the pager module resizes using sqlite3_realloc().
*/ */
db->nextPagesize = sqlite3Atoi(zRight); db->nextPagesize = sqlite3Atoi(zRight);
if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize, -1, 0) ){ if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize,-1,0) ){
db->mallocFailed = 1; db->mallocFailed = 1;
} }
} }
@@ -456,6 +458,10 @@ void sqlite3Pragma(
** second form attempts to change this setting. Both ** second form attempts to change this setting. Both
** forms return the current setting. ** forms return the current setting.
** **
** The absolute value of N is used. This is undocumented and might
** change. The only purpose is to provide an easy way to test
** the sqlite3AbsInt32() function.
**
** PRAGMA [database.]page_count ** PRAGMA [database.]page_count
** **
** Return the number of pages in the specified database. ** Return the number of pages in the specified database.
@@ -470,7 +476,8 @@ void sqlite3Pragma(
if( sqlite3Tolower(zLeft[0])=='p' ){ if( sqlite3Tolower(zLeft[0])=='p' ){
sqlite3VdbeAddOp2(v, OP_Pagecount, iDb, iReg); sqlite3VdbeAddOp2(v, OP_Pagecount, iDb, iReg);
}else{ }else{
sqlite3VdbeAddOp3(v, OP_MaxPgcnt, iDb, iReg, sqlite3Atoi(zRight)); sqlite3VdbeAddOp3(v, OP_MaxPgcnt, iDb, iReg,
sqlite3AbsInt32(sqlite3Atoi(zRight)));
} }
sqlite3VdbeAddOp2(v, OP_ResultRow, iReg, 1); sqlite3VdbeAddOp2(v, OP_ResultRow, iReg, 1);
sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetNumCols(v, 1);
@@ -684,14 +691,11 @@ void sqlite3Pragma(
** PRAGMA [database.]cache_size=N ** PRAGMA [database.]cache_size=N
** **
** The first form reports the current local setting for the ** The first form reports the current local setting for the
** page cache size. The local setting can be different from ** page cache size. The second form sets the local
** the persistent cache size value that is stored in the database ** page cache size value. If N is positive then that is the
** file itself. The value returned is the maximum number of ** number of pages in the cache. If N is negative, then the
** pages in the page cache. The second form sets the local ** number of pages is adjusted so that the cache uses -N kibibytes
** page cache size value. It does not change the persistent ** of memory.
** cache size stored on the disk so the cache size will revert
** to its default value when the database is closed and reopened.
** N should be a positive integer.
*/ */
if( sqlite3StrICmp(zLeft,"cache_size")==0 ){ if( sqlite3StrICmp(zLeft,"cache_size")==0 ){
if( sqlite3ReadSchema(pParse) ) goto pragma_out; if( sqlite3ReadSchema(pParse) ) goto pragma_out;
@@ -699,7 +703,7 @@ void sqlite3Pragma(
if( !zRight ){ if( !zRight ){
returnSingleInt(pParse, "cache_size", pDb->pSchema->cache_size); returnSingleInt(pParse, "cache_size", pDb->pSchema->cache_size);
}else{ }else{
int size = sqlite3AbsInt32(sqlite3Atoi(zRight)); int size = sqlite3Atoi(zRight);
pDb->pSchema->cache_size = size; pDb->pSchema->cache_size = size;
sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size); sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size);
} }

View File

@@ -278,9 +278,13 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
pDb->pSchema->enc = ENC(db); pDb->pSchema->enc = ENC(db);
if( pDb->pSchema->cache_size==0 ){ if( pDb->pSchema->cache_size==0 ){
#ifndef SQLITE_OMIT_DEPRECATED
size = sqlite3AbsInt32(meta[BTREE_DEFAULT_CACHE_SIZE-1]); size = sqlite3AbsInt32(meta[BTREE_DEFAULT_CACHE_SIZE-1]);
if( size==0 ){ size = SQLITE_DEFAULT_CACHE_SIZE; } if( size==0 ){ size = SQLITE_DEFAULT_CACHE_SIZE; }
pDb->pSchema->cache_size = size; pDb->pSchema->cache_size = size;
#else
pDb->pSchema->cache_size = SQLITE_DEFAULT_CACHE_SIZE;
#endif
sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size); sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size);
} }

View File

@@ -2220,7 +2220,6 @@ static int do_meta_command(char *zLine, struct callback_data *p){
{ "reserve", SQLITE_TESTCTRL_RESERVE }, { "reserve", SQLITE_TESTCTRL_RESERVE },
{ "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS }, { "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS },
{ "iskeyword", SQLITE_TESTCTRL_ISKEYWORD }, { "iskeyword", SQLITE_TESTCTRL_ISKEYWORD },
{ "pghdrsz", SQLITE_TESTCTRL_PGHDRSZ },
{ "scratchmalloc", SQLITE_TESTCTRL_SCRATCHMALLOC }, { "scratchmalloc", SQLITE_TESTCTRL_SCRATCHMALLOC },
}; };
int testctrl = -1; int testctrl = -1;
@@ -2265,7 +2264,6 @@ static int do_meta_command(char *zLine, struct callback_data *p){
case SQLITE_TESTCTRL_PRNG_SAVE: case SQLITE_TESTCTRL_PRNG_SAVE:
case SQLITE_TESTCTRL_PRNG_RESTORE: case SQLITE_TESTCTRL_PRNG_RESTORE:
case SQLITE_TESTCTRL_PRNG_RESET: case SQLITE_TESTCTRL_PRNG_RESET:
case SQLITE_TESTCTRL_PGHDRSZ:
if( nArg==2 ){ if( nArg==2 ){
rc = sqlite3_test_control(testctrl); rc = sqlite3_test_control(testctrl);
printf("%d (0x%08x)\n", rc, rc); printf("%d (0x%08x)\n", rc, rc);

View File

@@ -1368,7 +1368,7 @@ struct sqlite3_mem_methods {
** <dd> ^This option specifies a static memory buffer that SQLite can use for ** <dd> ^This option specifies a static memory buffer that SQLite can use for
** the database page cache with the default page cache implementation. ** the database page cache with the default page cache implementation.
** This configuration should not be used if an application-define page ** This configuration should not be used if an application-define page
** cache implementation is loaded using the SQLITE_CONFIG_PCACHE option. ** cache implementation is loaded using the SQLITE_CONFIG_PCACHE2 option.
** There are three arguments to this option: A pointer to 8-byte aligned ** There are three arguments to this option: A pointer to 8-byte aligned
** memory, the size of each page buffer (sz), and the number of pages (N). ** memory, the size of each page buffer (sz), and the number of pages (N).
** The sz argument should be the size of the largest database page ** The sz argument should be the size of the largest database page
@@ -1437,15 +1437,15 @@ struct sqlite3_mem_methods {
** verb to [sqlite3_db_config()] can be used to change the lookaside ** verb to [sqlite3_db_config()] can be used to change the lookaside
** configuration on individual connections.)^ </dd> ** configuration on individual connections.)^ </dd>
** **
** [[SQLITE_CONFIG_PCACHE]] <dt>SQLITE_CONFIG_PCACHE</dt> ** [[SQLITE_CONFIG_PCACHE2]] <dt>SQLITE_CONFIG_PCACHE2</dt>
** <dd> ^(This option takes a single argument which is a pointer to ** <dd> ^(This option takes a single argument which is a pointer to
** an [sqlite3_pcache_methods] object. This object specifies the interface ** an [sqlite3_pcache_methods2] object. This object specifies the interface
** to a custom page cache implementation.)^ ^SQLite makes a copy of the ** to a custom page cache implementation.)^ ^SQLite makes a copy of the
** object and uses it for page cache memory allocations.</dd> ** object and uses it for page cache memory allocations.</dd>
** **
** [[SQLITE_CONFIG_GETPCACHE]] <dt>SQLITE_CONFIG_GETPCACHE</dt> ** [[SQLITE_CONFIG_GETPCACHE2]] <dt>SQLITE_CONFIG_GETPCACHE2</dt>
** <dd> ^(This option takes a single argument which is a pointer to an ** <dd> ^(This option takes a single argument which is a pointer to an
** [sqlite3_pcache_methods] object. SQLite copies of the current ** [sqlite3_pcache_methods2] object. SQLite copies of the current
** page cache implementation into that object.)^ </dd> ** page cache implementation into that object.)^ </dd>
** **
** [[SQLITE_CONFIG_LOG]] <dt>SQLITE_CONFIG_LOG</dt> ** [[SQLITE_CONFIG_LOG]] <dt>SQLITE_CONFIG_LOG</dt>
@@ -1478,6 +1478,11 @@ struct sqlite3_mem_methods {
** database connection is opened. By default, URI handling is globally ** database connection is opened. By default, URI handling is globally
** disabled. The default value may be changed by compiling with the ** disabled. The default value may be changed by compiling with the
** [SQLITE_USE_URI] symbol defined. ** [SQLITE_USE_URI] symbol defined.
**
** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]]
** <dt>SQLITE_CONFIG_PCACHE and SQLITE_CONFNIG_GETPCACHE
** <dd> These options are obsolete and should not be used by new code.
** They are retained for backwards compatibility but are now no-ops.
** </dl> ** </dl>
*/ */
#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
@@ -1493,10 +1498,12 @@ struct sqlite3_mem_methods {
#define SQLITE_CONFIG_GETMUTEX 11 /* sqlite3_mutex_methods* */ #define SQLITE_CONFIG_GETMUTEX 11 /* sqlite3_mutex_methods* */
/* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */ /* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */
#define SQLITE_CONFIG_LOOKASIDE 13 /* int int */ #define SQLITE_CONFIG_LOOKASIDE 13 /* int int */
#define SQLITE_CONFIG_PCACHE 14 /* sqlite3_pcache_methods* */ #define SQLITE_CONFIG_PCACHE 14 /* no-op */
#define SQLITE_CONFIG_GETPCACHE 15 /* sqlite3_pcache_methods* */ #define SQLITE_CONFIG_GETPCACHE 15 /* no-op */
#define SQLITE_CONFIG_LOG 16 /* xFunc, void* */ #define SQLITE_CONFIG_LOG 16 /* xFunc, void* */
#define SQLITE_CONFIG_URI 17 /* int */ #define SQLITE_CONFIG_URI 17 /* int */
#define SQLITE_CONFIG_PCACHE2 18 /* sqlite3_pcache_methods2* */
#define SQLITE_CONFIG_GETPCACHE2 19 /* sqlite3_pcache_methods2* */
/* /*
** CAPI3REF: Database Connection Configuration Options ** CAPI3REF: Database Connection Configuration Options
@@ -4555,7 +4562,7 @@ int sqlite3_release_memory(int);
** [sqlite3_config]([SQLITE_CONFIG_MEMSTATUS],...) start-time option and ** [sqlite3_config]([SQLITE_CONFIG_MEMSTATUS],...) start-time option and
** the [SQLITE_DEFAULT_MEMSTATUS] compile-time option. ** the [SQLITE_DEFAULT_MEMSTATUS] compile-time option.
** <li> An alternative page cache implementation is specified using ** <li> An alternative page cache implementation is specified using
** [sqlite3_config]([SQLITE_CONFIG_PCACHE],...). ** [sqlite3_config]([SQLITE_CONFIG_PCACHE2],...).
** <li> The page cache allocates from its own memory pool supplied ** <li> The page cache allocates from its own memory pool supplied
** by [sqlite3_config]([SQLITE_CONFIG_PAGECACHE],...) rather than ** by [sqlite3_config]([SQLITE_CONFIG_PAGECACHE],...) rather than
** from the heap. ** from the heap.
@@ -5623,10 +5630,9 @@ int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_RESERVE 14 #define SQLITE_TESTCTRL_RESERVE 14
#define SQLITE_TESTCTRL_OPTIMIZATIONS 15 #define SQLITE_TESTCTRL_OPTIMIZATIONS 15
#define SQLITE_TESTCTRL_ISKEYWORD 16 #define SQLITE_TESTCTRL_ISKEYWORD 16
#define SQLITE_TESTCTRL_PGHDRSZ 17 #define SQLITE_TESTCTRL_SCRATCHMALLOC 17
#define SQLITE_TESTCTRL_SCRATCHMALLOC 18 #define SQLITE_TESTCTRL_LOCALTIME_FAULT 18
#define SQLITE_TESTCTRL_LOCALTIME_FAULT 19 #define SQLITE_TESTCTRL_LAST 18
#define SQLITE_TESTCTRL_LAST 19
/* /*
** CAPI3REF: SQLite Runtime Status ** CAPI3REF: SQLite Runtime Status
@@ -5928,17 +5934,33 @@ int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
** sqlite3_pcache object except by holding and passing pointers ** sqlite3_pcache object except by holding and passing pointers
** to the object. ** to the object.
** **
** See [sqlite3_pcache_methods] for additional information. ** See [sqlite3_pcache_methods2] for additional information.
*/ */
typedef struct sqlite3_pcache sqlite3_pcache; typedef struct sqlite3_pcache sqlite3_pcache;
/*
** CAPI3REF: Custom Page Cache Object
**
** The sqlite3_pcache_page object represents a single page in the
** page cache. The page cache will allocate instances of this
** object. Various methods of the page cache use pointers to instances
** of this object as parameters or as their return value.
**
** See [sqlite3_pcache_methods2] for additional information.
*/
typedef struct sqlite3_pcache_page sqlite3_pcache_page;
struct sqlite3_pcache_page {
void *pBuf; /* The content of the page */
void *pExtra; /* Extra information associated with the page */
};
/* /*
** CAPI3REF: Application Defined Page Cache. ** CAPI3REF: Application Defined Page Cache.
** KEYWORDS: {page cache} ** KEYWORDS: {page cache}
** **
** ^(The [sqlite3_config]([SQLITE_CONFIG_PCACHE], ...) interface can ** ^(The [sqlite3_config]([SQLITE_CONFIG_PCACHE2], ...) interface can
** register an alternative page cache implementation by passing in an ** register an alternative page cache implementation by passing in an
** instance of the sqlite3_pcache_methods structure.)^ ** instance of the sqlite3_pcache_methods2 structure.)^
** In many applications, most of the heap memory allocated by ** In many applications, most of the heap memory allocated by
** SQLite is used for the page cache. ** SQLite is used for the page cache.
** By implementing a ** By implementing a
@@ -5952,7 +5974,7 @@ typedef struct sqlite3_pcache sqlite3_pcache;
** extreme measure that is only needed by the most demanding applications. ** extreme measure that is only needed by the most demanding applications.
** The built-in page cache is recommended for most uses. ** The built-in page cache is recommended for most uses.
** **
** ^(The contents of the sqlite3_pcache_methods structure are copied to an ** ^(The contents of the sqlite3_pcache_methods2 structure are copied to an
** internal buffer by SQLite within the call to [sqlite3_config]. Hence ** internal buffer by SQLite within the call to [sqlite3_config]. Hence
** the application may discard the parameter after the call to ** the application may discard the parameter after the call to
** [sqlite3_config()] returns.)^ ** [sqlite3_config()] returns.)^
@@ -5987,18 +6009,16 @@ typedef struct sqlite3_pcache sqlite3_pcache;
** ^SQLite invokes the xCreate() method to construct a new cache instance. ** ^SQLite invokes the xCreate() method to construct a new cache instance.
** SQLite will typically create one cache instance for each open database file, ** SQLite will typically create one cache instance for each open database file,
** though this is not guaranteed. ^The ** though this is not guaranteed. ^The
** first parameter, szPage, is the size in bytes of the pages that must ** parameter parameter, szPage, is the size in bytes of the pages that must
** be allocated by the cache. ^szPage will not be a power of two. ^szPage ** be allocated by the cache. ^szPage will always a power of two. ^The
** will the page size of the database file that is to be cached plus an ** second parameter szExtra is a number of bytes of extra storage
** increment (here called "R") of less than 250. SQLite will use the ** associated with each page cache entry. ^The szExtra parameter will
** extra R bytes on each page to store metadata about the underlying ** a number less than 250. SQLite will use the
** database page on disk. The value of R depends ** extra szExtra bytes on each page to store metadata about the underlying
** database page on disk. The value passed into szExtra depends
** on the SQLite version, the target platform, and how SQLite was compiled. ** on the SQLite version, the target platform, and how SQLite was compiled.
** ^(R is constant for a particular build of SQLite. Except, there are two ** ^The third argument to xCreate(), bPurgeable, is true if the cache being
** distinct values of R when SQLite is compiled with the proprietary ** created will be used to cache database pages of a file stored on disk, or
** ZIPVFS extension.)^ ^The second argument to
** xCreate(), bPurgeable, is true if the cache being created will
** be used to cache database pages of a file stored on disk, or
** false if it is used for an in-memory database. The cache implementation ** false if it is used for an in-memory database. The cache implementation
** does not have to do anything special based with the value of bPurgeable; ** does not have to do anything special based with the value of bPurgeable;
** it is purely advisory. ^On a cache where bPurgeable is false, SQLite will ** it is purely advisory. ^On a cache where bPurgeable is false, SQLite will
@@ -6022,11 +6042,16 @@ typedef struct sqlite3_pcache sqlite3_pcache;
** **
** [[the xFetch() page cache methods]] ** [[the xFetch() page cache methods]]
** The xFetch() method locates a page in the cache and returns a pointer to ** The xFetch() method locates a page in the cache and returns a pointer to
** the page, or a NULL pointer. ** an sqlite3_pcache_page object associated with that page, or a NULL pointer.
** A "page", in this context, means a buffer of szPage bytes aligned at an ** The pBuf element of the returned sqlite3_pcache_page object will be a
** 8-byte boundary. The page to be fetched is determined by the key. ^The ** pointer to a buffer of szPage bytes used to store the content of a
** minimum key value is 1. After it has been retrieved using xFetch, the page ** single database page. The pExtra element of sqlite3_pcache_page will be
** is considered to be "pinned". ** a pointer to the szExtra bytes of extra storage that SQLite has requested
** for each entry in the page cache.
**
** The page to be fetched is determined by the key. ^The minimum key value
** is 1. After it has been retrieved using xFetch, the page is considered
** to be "pinned".
** **
** If the requested page is already in the page cache, then the page cache ** If the requested page is already in the page cache, then the page cache
** implementation must return a pointer to the page buffer with its content ** implementation must return a pointer to the page buffer with its content
@@ -6082,6 +6107,28 @@ typedef struct sqlite3_pcache sqlite3_pcache;
** handle invalid, and will not use it with any other sqlite3_pcache_methods ** handle invalid, and will not use it with any other sqlite3_pcache_methods
** functions. ** functions.
*/ */
typedef struct sqlite3_pcache_methods2 sqlite3_pcache_methods2;
struct sqlite3_pcache_methods2 {
int iVersion;
void *pArg;
int (*xInit)(void*);
void (*xShutdown)(void*);
sqlite3_pcache *(*xCreate)(int szPage, int szExtra, int bPurgeable);
void (*xCachesize)(sqlite3_pcache*, int nCachesize);
int (*xPagecount)(sqlite3_pcache*);
sqlite3_pcache_page *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag);
void (*xUnpin)(sqlite3_pcache*, sqlite3_pcache_page*, int discard);
void (*xRekey)(sqlite3_pcache*, sqlite3_pcache_page*,
unsigned oldKey, unsigned newKey);
void (*xTruncate)(sqlite3_pcache*, unsigned iLimit);
void (*xDestroy)(sqlite3_pcache*);
};
/*
** This is the obsolete pcache_methods object that has now been replaced
** by sqlite3_pcache_methods2. This object is not used by SQLite. It is
** retained in the header file for backwards compatibility only.
*/
typedef struct sqlite3_pcache_methods sqlite3_pcache_methods; typedef struct sqlite3_pcache_methods sqlite3_pcache_methods;
struct sqlite3_pcache_methods { struct sqlite3_pcache_methods {
void *pArg; void *pArg;
@@ -6097,6 +6144,7 @@ struct sqlite3_pcache_methods {
void (*xDestroy)(sqlite3_pcache*); void (*xDestroy)(sqlite3_pcache*);
}; };
/* /*
** CAPI3REF: Online Backup Object ** CAPI3REF: Online Backup Object
** **

View File

@@ -2458,7 +2458,7 @@ struct Sqlite3Config {
int nLookaside; /* Default lookaside buffer count */ int nLookaside; /* Default lookaside buffer count */
sqlite3_mem_methods m; /* Low-level memory allocation interface */ sqlite3_mem_methods m; /* Low-level memory allocation interface */
sqlite3_mutex_methods mutex; /* Low-level mutex interface */ sqlite3_mutex_methods mutex; /* Low-level mutex interface */
sqlite3_pcache_methods pcache; /* Low-level page-cache interface */ sqlite3_pcache_methods2 pcache2; /* Low-level page-cache interface */
void *pHeap; /* Heap storage space */ void *pHeap; /* Heap storage space */
int nHeap; /* Size of pHeap[] */ int nHeap; /* Size of pHeap[] */
int mnReq, mxReq; /* Min and max heap requests sizes */ int mnReq, mxReq; /* Min and max heap requests sizes */

View File

@@ -37,6 +37,14 @@
** procedures use this to determine when tests should be omitted. ** procedures use this to determine when tests should be omitted.
*/ */
static void set_options(Tcl_Interp *interp){ static void set_options(Tcl_Interp *interp){
#ifdef HAVE_MALLOC_USABLE_SIZE
Tcl_SetVar2(interp, "sqlite_options", "malloc_usable_size", "1",
TCL_GLOBAL_ONLY);
#else
Tcl_SetVar2(interp, "sqlite_options", "malloc_usable_size", "0",
TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_32BIT_ROWID #ifdef SQLITE_32BIT_ROWID
Tcl_SetVar2(interp, "sqlite_options", "rowid32", "1", TCL_GLOBAL_ONLY); Tcl_SetVar2(interp, "sqlite_options", "rowid32", "1", TCL_GLOBAL_ONLY);
#else #else

View File

@@ -30,9 +30,9 @@
#include <tcl.h> #include <tcl.h>
static struct Wrapped { static struct Wrapped {
sqlite3_pcache_methods pcache; sqlite3_pcache_methods2 pcache;
sqlite3_mem_methods mem; sqlite3_mem_methods mem;
sqlite3_mutex_methods mutex; sqlite3_mutex_methods mutex;
int mem_init; /* True if mem subsystem is initalized */ int mem_init; /* True if mem subsystem is initalized */
int mem_fail; /* True to fail mem subsystem inialization */ int mem_fail; /* True to fail mem subsystem inialization */
@@ -123,8 +123,8 @@ static void wrPCacheShutdown(void *pArg){
wrapped.pcache_init = 0; wrapped.pcache_init = 0;
} }
static sqlite3_pcache *wrPCacheCreate(int a, int b){ static sqlite3_pcache *wrPCacheCreate(int a, int b, int c){
return wrapped.pcache.xCreate(a, b); return wrapped.pcache.xCreate(a, b, c);
} }
static void wrPCacheCachesize(sqlite3_pcache *p, int n){ static void wrPCacheCachesize(sqlite3_pcache *p, int n){
wrapped.pcache.xCachesize(p, n); wrapped.pcache.xCachesize(p, n);
@@ -132,13 +132,18 @@ static void wrPCacheCachesize(sqlite3_pcache *p, int n){
static int wrPCachePagecount(sqlite3_pcache *p){ static int wrPCachePagecount(sqlite3_pcache *p){
return wrapped.pcache.xPagecount(p); return wrapped.pcache.xPagecount(p);
} }
static void *wrPCacheFetch(sqlite3_pcache *p, unsigned a, int b){ static sqlite3_pcache_page *wrPCacheFetch(sqlite3_pcache *p, unsigned a, int b){
return wrapped.pcache.xFetch(p, a, b); return wrapped.pcache.xFetch(p, a, b);
} }
static void wrPCacheUnpin(sqlite3_pcache *p, void *a, int b){ static void wrPCacheUnpin(sqlite3_pcache *p, sqlite3_pcache_page *a, int b){
wrapped.pcache.xUnpin(p, a, b); wrapped.pcache.xUnpin(p, a, b);
} }
static void wrPCacheRekey(sqlite3_pcache *p, void *a, unsigned b, unsigned c){ static void wrPCacheRekey(
sqlite3_pcache *p,
sqlite3_pcache_page *a,
unsigned b,
unsigned c
){
wrapped.pcache.xRekey(p, a, b, c); wrapped.pcache.xRekey(p, a, b, c);
} }
static void wrPCacheTruncate(sqlite3_pcache *p, unsigned a){ static void wrPCacheTruncate(sqlite3_pcache *p, unsigned a){
@@ -154,8 +159,8 @@ static void installInitWrappers(void){
wrMutexFree, wrMutexEnter, wrMutexTry, wrMutexFree, wrMutexEnter, wrMutexTry,
wrMutexLeave, wrMutexHeld, wrMutexNotheld wrMutexLeave, wrMutexHeld, wrMutexNotheld
}; };
sqlite3_pcache_methods pcachemethods = { sqlite3_pcache_methods2 pcachemethods = {
0, 1, 0,
wrPCacheInit, wrPCacheShutdown, wrPCacheCreate, wrPCacheInit, wrPCacheShutdown, wrPCacheCreate,
wrPCacheCachesize, wrPCachePagecount, wrPCacheFetch, wrPCacheCachesize, wrPCachePagecount, wrPCacheFetch,
wrPCacheUnpin, wrPCacheRekey, wrPCacheTruncate, wrPCacheUnpin, wrPCacheRekey, wrPCacheTruncate,
@@ -173,10 +178,10 @@ static void installInitWrappers(void){
sqlite3_shutdown(); sqlite3_shutdown();
sqlite3_config(SQLITE_CONFIG_GETMUTEX, &wrapped.mutex); sqlite3_config(SQLITE_CONFIG_GETMUTEX, &wrapped.mutex);
sqlite3_config(SQLITE_CONFIG_GETMALLOC, &wrapped.mem); sqlite3_config(SQLITE_CONFIG_GETMALLOC, &wrapped.mem);
sqlite3_config(SQLITE_CONFIG_GETPCACHE, &wrapped.pcache); sqlite3_config(SQLITE_CONFIG_GETPCACHE2, &wrapped.pcache);
sqlite3_config(SQLITE_CONFIG_MUTEX, &mutexmethods); sqlite3_config(SQLITE_CONFIG_MUTEX, &mutexmethods);
sqlite3_config(SQLITE_CONFIG_MALLOC, &memmethods); sqlite3_config(SQLITE_CONFIG_MALLOC, &memmethods);
sqlite3_config(SQLITE_CONFIG_PCACHE, &pcachemethods); sqlite3_config(SQLITE_CONFIG_PCACHE2, &pcachemethods);
} }
static int init_wrapper_install( static int init_wrapper_install(
@@ -218,7 +223,7 @@ static int init_wrapper_uninstall(
sqlite3_shutdown(); sqlite3_shutdown();
sqlite3_config(SQLITE_CONFIG_MUTEX, &wrapped.mutex); sqlite3_config(SQLITE_CONFIG_MUTEX, &wrapped.mutex);
sqlite3_config(SQLITE_CONFIG_MALLOC, &wrapped.mem); sqlite3_config(SQLITE_CONFIG_MALLOC, &wrapped.mem);
sqlite3_config(SQLITE_CONFIG_PCACHE, &wrapped.pcache); sqlite3_config(SQLITE_CONFIG_PCACHE2, &wrapped.pcache);
return TCL_OK; return TCL_OK;
} }

View File

@@ -100,15 +100,16 @@ static void testpcacheShutdown(void *pArg){
typedef struct testpcache testpcache; typedef struct testpcache testpcache;
struct testpcache { struct testpcache {
int szPage; /* Size of each page. Multiple of 8. */ int szPage; /* Size of each page. Multiple of 8. */
int szExtra; /* Size of extra data that accompanies each page */
int bPurgeable; /* True if the page cache is purgeable */ int bPurgeable; /* True if the page cache is purgeable */
int nFree; /* Number of unused slots in a[] */ int nFree; /* Number of unused slots in a[] */
int nPinned; /* Number of pinned slots in a[] */ int nPinned; /* Number of pinned slots in a[] */
unsigned iRand; /* State of the PRNG */ unsigned iRand; /* State of the PRNG */
unsigned iMagic; /* Magic number for sanity checking */ unsigned iMagic; /* Magic number for sanity checking */
struct testpcachePage { struct testpcachePage {
sqlite3_pcache_page page; /* Base class */
unsigned key; /* The key for this page. 0 means unallocated */ unsigned key; /* The key for this page. 0 means unallocated */
int isPinned; /* True if the page is pinned */ int isPinned; /* True if the page is pinned */
void *pData; /* Data for this page */
} a[TESTPCACHE_NPAGE]; /* All pages in the cache */ } a[TESTPCACHE_NPAGE]; /* All pages in the cache */
}; };
@@ -129,27 +130,33 @@ static unsigned testpcacheRandom(testpcache *p){
/* /*
** Allocate a new page cache instance. ** Allocate a new page cache instance.
*/ */
static sqlite3_pcache *testpcacheCreate(int szPage, int bPurgeable){ static sqlite3_pcache *testpcacheCreate(
int szPage,
int szExtra,
int bPurgeable
){
int nMem; int nMem;
char *x; char *x;
testpcache *p; testpcache *p;
int i; int i;
assert( testpcacheGlobal.pDummy!=0 ); assert( testpcacheGlobal.pDummy!=0 );
szPage = (szPage+7)&~7; szPage = (szPage+7)&~7;
nMem = sizeof(testpcache) + TESTPCACHE_NPAGE*szPage; nMem = sizeof(testpcache) + TESTPCACHE_NPAGE*(szPage+szExtra);
p = sqlite3_malloc( nMem ); p = sqlite3_malloc( nMem );
if( p==0 ) return 0; if( p==0 ) return 0;
x = (char*)&p[1]; x = (char*)&p[1];
p->szPage = szPage; p->szPage = szPage;
p->szExtra = szExtra;
p->nFree = TESTPCACHE_NPAGE; p->nFree = TESTPCACHE_NPAGE;
p->nPinned = 0; p->nPinned = 0;
p->iRand = testpcacheGlobal.prngSeed; p->iRand = testpcacheGlobal.prngSeed;
p->bPurgeable = bPurgeable; p->bPurgeable = bPurgeable;
p->iMagic = TESTPCACHE_VALID; p->iMagic = TESTPCACHE_VALID;
for(i=0; i<TESTPCACHE_NPAGE; i++, x += szPage){ for(i=0; i<TESTPCACHE_NPAGE; i++, x += (szPage+szExtra)){
p->a[i].key = 0; p->a[i].key = 0;
p->a[i].isPinned = 0; p->a[i].isPinned = 0;
p->a[i].pData = (void*)x; p->a[i].page.pBuf = (void*)x;
p->a[i].page.pExtra = (void*)&x[szPage];
} }
testpcacheGlobal.nInstance++; testpcacheGlobal.nInstance++;
return (sqlite3_pcache*)p; return (sqlite3_pcache*)p;
@@ -180,7 +187,7 @@ static int testpcachePagecount(sqlite3_pcache *pCache){
/* /*
** Fetch a page. ** Fetch a page.
*/ */
static void *testpcacheFetch( static sqlite3_pcache_page *testpcacheFetch(
sqlite3_pcache *pCache, sqlite3_pcache *pCache,
unsigned key, unsigned key,
int createFlag int createFlag
@@ -199,7 +206,7 @@ static void *testpcacheFetch(
assert( p->nPinned <= TESTPCACHE_NPAGE - p->nFree ); assert( p->nPinned <= TESTPCACHE_NPAGE - p->nFree );
p->a[i].isPinned = 1; p->a[i].isPinned = 1;
} }
return p->a[i].pData; return &p->a[i].page;
} }
} }
@@ -236,11 +243,12 @@ static void *testpcacheFetch(
if( p->a[j].key==0 ){ if( p->a[j].key==0 ){
p->a[j].key = key; p->a[j].key = key;
p->a[j].isPinned = 1; p->a[j].isPinned = 1;
memset(p->a[j].pData, 0, p->szPage); memset(p->a[j].page.pBuf, 0, p->szPage);
memset(p->a[j].page.pExtra, 0, p->szExtra);
p->nPinned++; p->nPinned++;
p->nFree--; p->nFree--;
assert( p->nPinned <= TESTPCACHE_NPAGE - p->nFree ); assert( p->nPinned <= TESTPCACHE_NPAGE - p->nFree );
return p->a[j].pData; return &p->a[j].page;
} }
} }
@@ -262,10 +270,11 @@ static void *testpcacheFetch(
if( p->a[j].key>0 && p->a[j].isPinned==0 ){ if( p->a[j].key>0 && p->a[j].isPinned==0 ){
p->a[j].key = key; p->a[j].key = key;
p->a[j].isPinned = 1; p->a[j].isPinned = 1;
memset(p->a[j].pData, 0, p->szPage); memset(p->a[j].page.pBuf, 0, p->szPage);
memset(p->a[j].page.pExtra, 0, p->szExtra);
p->nPinned++; p->nPinned++;
assert( p->nPinned <= TESTPCACHE_NPAGE - p->nFree ); assert( p->nPinned <= TESTPCACHE_NPAGE - p->nFree );
return p->a[j].pData; return &p->a[j].page;
} }
} }
@@ -279,7 +288,7 @@ static void *testpcacheFetch(
*/ */
static void testpcacheUnpin( static void testpcacheUnpin(
sqlite3_pcache *pCache, sqlite3_pcache *pCache,
void *pOldPage, sqlite3_pcache_page *pOldPage,
int discard int discard
){ ){
testpcache *p = (testpcache*)pCache; testpcache *p = (testpcache*)pCache;
@@ -299,7 +308,7 @@ static void testpcacheUnpin(
} }
for(i=0; i<TESTPCACHE_NPAGE; i++){ for(i=0; i<TESTPCACHE_NPAGE; i++){
if( p->a[i].pData==pOldPage ){ if( &p->a[i].page==pOldPage ){
/* The pOldPage pointer always points to a pinned page */ /* The pOldPage pointer always points to a pinned page */
assert( p->a[i].isPinned ); assert( p->a[i].isPinned );
p->a[i].isPinned = 0; p->a[i].isPinned = 0;
@@ -324,7 +333,7 @@ static void testpcacheUnpin(
*/ */
static void testpcacheRekey( static void testpcacheRekey(
sqlite3_pcache *pCache, sqlite3_pcache *pCache,
void *pOldPage, sqlite3_pcache_page *pOldPage,
unsigned oldKey, unsigned oldKey,
unsigned newKey unsigned newKey
){ ){
@@ -353,7 +362,7 @@ static void testpcacheRekey(
for(i=0; i<TESTPCACHE_NPAGE; i++){ for(i=0; i<TESTPCACHE_NPAGE; i++){
if( p->a[i].key==oldKey ){ if( p->a[i].key==oldKey ){
/* The oldKey and pOldPage parameters match */ /* The oldKey and pOldPage parameters match */
assert( p->a[i].pData==pOldPage ); assert( &p->a[i].page==pOldPage );
/* Page to be rekeyed must be pinned */ /* Page to be rekeyed must be pinned */
assert( p->a[i].isPinned ); assert( p->a[i].isPinned );
p->a[i].key = newKey; p->a[i].key = newKey;
@@ -421,7 +430,8 @@ void installTestPCache(
unsigned prngSeed, /* Seed for the PRNG */ unsigned prngSeed, /* Seed for the PRNG */
unsigned highStress /* Call xStress agressively */ unsigned highStress /* Call xStress agressively */
){ ){
static const sqlite3_pcache_methods testPcache = { static const sqlite3_pcache_methods2 testPcache = {
1,
(void*)&testpcacheGlobal, (void*)&testpcacheGlobal,
testpcacheInit, testpcacheInit,
testpcacheShutdown, testpcacheShutdown,
@@ -434,7 +444,7 @@ void installTestPCache(
testpcacheTruncate, testpcacheTruncate,
testpcacheDestroy, testpcacheDestroy,
}; };
static sqlite3_pcache_methods defaultPcache; static sqlite3_pcache_methods2 defaultPcache;
static int isInstalled = 0; static int isInstalled = 0;
assert( testpcacheGlobal.nInstance==0 ); assert( testpcacheGlobal.nInstance==0 );
@@ -445,12 +455,12 @@ void installTestPCache(
testpcacheGlobal.highStress = highStress; testpcacheGlobal.highStress = highStress;
if( installFlag!=isInstalled ){ if( installFlag!=isInstalled ){
if( installFlag ){ if( installFlag ){
sqlite3_config(SQLITE_CONFIG_GETPCACHE, &defaultPcache); sqlite3_config(SQLITE_CONFIG_GETPCACHE2, &defaultPcache);
assert( defaultPcache.xCreate!=testpcacheCreate ); assert( defaultPcache.xCreate!=testpcacheCreate );
sqlite3_config(SQLITE_CONFIG_PCACHE, &testPcache); sqlite3_config(SQLITE_CONFIG_PCACHE2, &testPcache);
}else{ }else{
assert( defaultPcache.xCreate!=0 ); assert( defaultPcache.xCreate!=0 );
sqlite3_config(SQLITE_CONFIG_PCACHE, &defaultPcache); sqlite3_config(SQLITE_CONFIG_PCACHE2, &defaultPcache);
} }
isInstalled = installFlag; isInstalled = installFlag;
} }

View File

@@ -62,6 +62,11 @@ ifcapable stat3 {
set STAT3 0 set STAT3 0
} }
ifcapable malloc_usable_size {
finish_test
return
}
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
# Run the dbstatus-2 and dbstatus-3 tests with several of different # Run the dbstatus-2 and dbstatus-3 tests with several of different
# lookaside buffer sizes. # lookaside buffer sizes.

View File

@@ -68,7 +68,7 @@ proc reset_highwater_marks {} {
sqlite3_status SQLITE_STATUS_PARSER_STACK 1 sqlite3_status SQLITE_STATUS_PARSER_STACK 1
} }
set xtra_size 272 set xtra_size 290
# Test 1: Both PAGECACHE and SCRATCH are shut down. # Test 1: Both PAGECACHE and SCRATCH are shut down.
# #
@@ -97,9 +97,11 @@ reset_highwater_marks
build_test_db memsubsys1-2 {PRAGMA page_size=1024} build_test_db memsubsys1-2 {PRAGMA page_size=1024}
#show_memstats #show_memstats
set MEMORY_MANAGEMENT $sqlite_options(memorymanage) set MEMORY_MANAGEMENT $sqlite_options(memorymanage)
do_test memsubsys1-2.3 { ifcapable !malloc_usable_size {
set pg_ovfl [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 0] 2] do_test memsubsys1-2.3 {
} [expr ($TEMP_STORE>1 || $MEMORY_MANAGEMENT==0)*1024] set pg_ovfl [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 0] 2]
} [expr ($TEMP_STORE>1 || $MEMORY_MANAGEMENT==0)*1024]
}
do_test memsubsys1-2.4 { do_test memsubsys1-2.4 {
set pg_used [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 2] set pg_used [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 2]
} 20 } 20

View File

@@ -99,7 +99,7 @@ do_test pragma-1.5 {
PRAGMA default_cache_size; PRAGMA default_cache_size;
PRAGMA synchronous; PRAGMA synchronous;
} }
} [list 4321 $DFLT_CACHE_SZ 0] } [list -4321 $DFLT_CACHE_SZ 0]
do_test pragma-1.6 { do_test pragma-1.6 {
execsql { execsql {
PRAGMA synchronous=ON; PRAGMA synchronous=ON;
@@ -107,7 +107,7 @@ do_test pragma-1.6 {
PRAGMA default_cache_size; PRAGMA default_cache_size;
PRAGMA synchronous; PRAGMA synchronous;
} }
} [list 4321 $DFLT_CACHE_SZ 1] } [list -4321 $DFLT_CACHE_SZ 1]
do_test pragma-1.7 { do_test pragma-1.7 {
db close db close
sqlite3 db test.db sqlite3 db test.db