From: drh Date: Mon, 10 Oct 2011 23:53:48 +0000 (+0000) Subject: Forward port the Apple-specific changes from [db5b7b778c] in the X-Git-Tag: mountain-lion~17 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cc40f4ceb19cccd973c15bbee57a005dfb9dc45a;p=thirdparty%2Fsqlite.git Forward port the Apple-specific changes from [db5b7b778c] in the apple-osx-377 branch. Fix this up so that it will compile and run on Linux. FossilOrigin-Name: 6cb43f6c6e9d8054e00acab378b8af0d82d3084c --- cc40f4ceb19cccd973c15bbee57a005dfb9dc45a diff --cc manifest index 88d43531c2,f5f83fd9dd..042043c905 --- a/manifest +++ b/manifest @@@ -1,12 -1,12 +1,12 @@@ - C Merge\sin\sall\strunk\schanges\sthrough\sthe\s3.7.8\srelease. - D 2011-09-19T20:32:36.507 -C Merging\sin\scherry\spicked\sdiffs\sfor\spersist\swal,\salloc\spadding,\swal-safe\svacuum\sand\ssqlite3_file_control\sbased\slockstate\schecking -D 2011-10-10T22:11:44.216 ++C Forward\sport\sthe\sApple-specific\schanges\sfrom\s[db5b7b778c]\sin\sthe\napple-osx-377\sbranch.\s\sFix\sthis\sup\sso\sthat\sit\swill\scompile\sand\srun\son\sLinux. ++D 2011-10-10T23:53:48.384 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f -F Makefile.in 8410b02448997eb43bdf0ffa482c9bc2d2624e45 +F Makefile.in 55bbee3ada084d4aa4dab9e1e0d90a21aab8bbcf F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 -F Makefile.msc 11082f65b452b908d93013292c17850378c39284 -F Makefile.vxworks c85ec1d8597fe2f7bc225af12ac1666e21379151 +F Makefile.msc b5e917439d5ed42364173d1648aae1d418e323ea +F Makefile.vxworks 1deb39c8bb047296c30161ffa10c1b5423e632f9 F README cd04a36fbc7ea56932a4052d7d0b7f09f27c33d6 -F VERSION 3fcdd7fbe3eb282df3978fe77288544543767961 +F VERSION f724de7326e87b7f3b0a55f16ef4b4d993680d54 F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 F addopcodes.awk 17dc593f791f874d2c23a0f9360850ded0286531 F art/2005osaward.gif 0d1851b2a7c1c9d0ccce545f3e14bca42d7fd248 @@@ -124,23 -124,23 +124,23 @@@ F src/alter.c ac80a0f31189f8b4a524ebf66 F src/analyze.c a425d62e8fa9ebcb4359ab84ff0c62c6563d2e2a F src/attach.c 12c6957996908edc31c96d7c68d4942c2474405f F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 - F src/backup.c 28a4fe55327ff708bfaf9d4326d02686f7a553c3 -F src/backup.c 1cf56cc81b035e0a9884ddac13442edefcb0cb46 ++F src/backup.c 5774963f44ed38c56561033694d3a5ad516c556b F src/bitvec.c af50f1c8c0ff54d6bdb7a80e2fceca5a93670bef F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 -F src/btree.c 1870b70e376c5c9ff31e1235e4e4434212709265 +F src/btree.c 71a65f9bbdc3c93bd0f043aa9148b751474cea5e F src/btree.h f5d775cd6cfc7ac32a2535b70e8d2af48ef5f2ce F src/btreeInt.h 67978c014fa4f7cc874032dd3aacadd8db656bc3 -F src/build.c 5a428625d21ad409514afb40ad083bee25dd957a +F src/build.c 851e81f26a75abbb98bd99a7c5f10e8670d867bb F src/callback.c 0425c6320730e6d3981acfb9202c1bed9016ad1a F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac -F src/ctime.c 7deec4534f3b5a0c3b4a4cbadf809d321f64f9c4 -F src/date.c d3c11de76392ea62637bfac0f4655889fc2f5a85 -F src/delete.c 4925f9121525fc871f5d8d13c1f7dcc91abb38bb -F src/expr.c ab46ab0f0c44979a8164ca31728d7d10ae5e8106 +F src/ctime.c e3132ec65240b2e2f3d50831021eac387f27584d +F src/date.c a3c6842bad7ae632281811de112a8ba63ff08ab3 +F src/delete.c ff68e5ef23aee08c0ff528f699a19397ed8bbed8 +F src/expr.c f4dcaeb8252c4b16fcdc245660f70ed366bc6cdd F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb -F src/fkey.c 9fabba17a4d4778dc660f0cb9d781fc86d7b9d41 +F src/fkey.c 9f00ea98f6b360d477b5a78b5b59a1fbde82431c F src/func.c 1b9d471b632d8529e0f86b7bd2b918dcc2cb1097 -F src/global.c c70a46f28680f8d7c097dbc0430ccf3b932e90b0 +F src/global.c e230227de13601714b29f9363028514aada5ae2f F src/hash.c 458488dcc159c301b8e7686280ab209f1fb915af F src/hash.h 2894c932d84d9f892d4b4023a75e501f83050970 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 @@@ -148,13 -148,13 +148,13 @@@ F src/insert.c 3eea5a53d2644116fb865afa F src/journal.c 552839e54d1bf76fb8f7abe51868b66acacf6a0e F src/legacy.c 015826a958f690302d27e096a68d50b3657e4201 F src/lempar.c 7f026423f4d71d989e719a743f98a1cbd4e6d99e -F src/loadext.c 3ae0d52da013a6326310655be6473fd472347b85 -F src/main.c f3d35af74fdccb20f7edb31d842006d99887cf2e +F src/loadext.c 99a161b27a499fc8ad40745b7b1900a26f0a5f51 - F src/main.c 242eaa584e256364f81f2aef97d3eca283d94073 ++F src/main.c 4aabaa8d510c08d59595be5d83c4d630e8200982 F src/malloc.c 591aedb20ae40813f1045f2ef253438a334775d9 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 - F src/mem1.c 46095d62b241466ef51970e592aa3a7a87e443e1 -F src/mem1.c 1abe5a2c20d981e050504684bfdd3a126356e6d9 ++F src/mem1.c c390a8fce10912a770ebe6fa031f5f463649e7ae F src/mem2.c e307323e86b5da1853d7111b68fd6b84ad6f09cf -F src/mem3.c 9b237d911ba9904142a804be727cc6664873f8a3 +F src/mem3.c 61c9d47b792908c532ca3a62b999cf21795c6534 F src/mem5.c c2c63b7067570b00bf33d751c39af24182316f7f F src/memjournal.c 0ebce851677a7ac035ba1512a7e65851b34530c6 F src/mutex.c 6949180803ff05a7d0e2b9334a95b4fb5a00e23f @@@ -164,13 -164,13 +164,13 @@@ F src/mutex_os2.c 882d735098c07c8c6a547 F src/mutex_unix.c b4f4e923bb8de93ec3f251fadb50855f23df9579 F src/mutex_w32.c 5e54f3ba275bcb5d00248b8c23107df2e2f73e33 F src/notify.c 976dd0f6171d4588e89e874fcc765e92914b6d30 -F src/os.c 1663f3754a3da185369a121a4f417762f77880b6 +F src/os.c 0668c16ae226cd58cef8240e5edbd0c93248739e F src/os.h 9dbed8c2b9c1f2f2ebabc09e49829d4777c26bf9 -F src/os_common.h a8f95b81eca8a1ab8593d23e94f8a35f35d4078f +F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04 F src/os_os2.c 4a75888ba3dfc820ad5e8177025972d74d7f2440 - F src/os_unix.c 6fdce4067dc5796b358bd9cf55cf5dd62d580945 - F src/os_win.c 0fc0f46c94b0385a940b0ee32992a833019a5985 - F src/pager.c 984dc40d797d8d822d6ce1d184287600d94a289f -F src/os_unix.c 8f60f53930d4c9e781c46d803b3534d004282442 -F src/os_win.c daa67fe04bd162fbcc387214e9614a7faa6b90b1 -F src/pager.c 4bee5b51c33855cd8de4094709912b000f2bccff ++F src/os_unix.c ed727d5822235e16519e82ba8bb355426381e1be ++F src/os_win.c 3fc8f4bb69dd71b2dc6b48e8d5fb411748197470 ++F src/pager.c 5cafaf3833fceefd21bfa4dd2254b71461663286 F src/pager.h 3f8c783de1d4706b40b1ac15b64f5f896bcc78d1 F src/parse.y 12b7ebd61ea54f0e1b1083ff69cc2c8ce9353d58 F src/pcache.c 49e718c095810c6b3334e3a6d89970aceaddefce @@@ -180,19 -180,19 +180,19 @@@ F src/pragma.c 66661dbe8428dd3215bd4c8f F src/prepare.c 9d7403fe75fefa134351b41400d09ba1b189134b F src/printf.c 585a36b6a963df832cfb69505afa3a34ed5ef8a1 F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50 -F src/resolve.c 1c0f32b64f8e3f555fe1f732f9d6f501a7f05706 +F src/resolve.c 36368f44569208fa074e61f4dd0b6c4fb60ca2b4 F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697 -F src/select.c 75b7dd8c6a5ff9b8ec3f7ed51d31af8b30f114bc -F src/shell.c 0e0173b3e79d956368013e759f084caa7995ecb1 -F src/sqlite.h.in 05e72174ea58476dc71db4bb6816f5b79a100f76 +F src/select.c f3971442d59d06801ac3c712f2851ece8d1cdead +F src/shell.c 13fe2aeddc3cc90d6a273831d1f63736d1596f81 - F src/sqlite.h.in 175065018323ca082092f92873e074647d00bec2 - F src/sqlite3_private.h 1d18557420cb0cc51ff31ec0a3fcce11e5cd6f5a ++F src/sqlite.h.in 9b74f2d71c15cc9e3f78c16474e2096a707ceba5 + F src/sqlite3_private.h e3b586e0aa329075d99be7198df9bc80c5b19e2d -F src/sqlite3ext.h c90bd5507099f62043832d73f6425d8d5c5da754 -F src/sqliteInt.h 2f4919d0105a821f04433a181f877c8a70201f9a +F src/sqlite3ext.h 1a1a4f784aa9c3b00edd287940197de52487cd93 - F src/sqliteInt.h 751564e4eb28a49d4f53f7bd2a211a48115d01d7 ++F src/sqliteInt.h e9a32825290cee916e3e0939c857a13801afc700 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 7ac64842c86cec2fc1a1d0e5c16d3beb8ad332bf F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e -F src/tclsqlite.c 5db825be61708b1a2b3f8f6e185e9b753829acef -F src/test1.c 1ce078b76ff2876c32b6ae4d1bbf754f704c87cb +F src/tclsqlite.c 3ef1dda2f1dc207c792eaadebf9d8adc44648581 - F src/test1.c 48759e7898dd7af7ae2b01de12045814583e15c6 ++F src/test1.c 63a00ab722cc49025a6f675bcda39bed83663a48 F src/test2.c 80d323d11e909cf0eb1b6fbb4ac22276483bcf31 F src/test3.c 124ff9735fb6bb7d41de180d6bac90e7b1509432 F src/test4.c d1e5a5e904d4b444cf572391fdcb017638e36ff7 @@@ -237,35 -237,34 +237,35 @@@ F src/test_vfstrace.c 0b884e06094a746da F src/test_wholenumber.c 6129adfbe7c7444f2e60cc785927f3aa74e12290 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/tokenize.c c819d9f72168a035d545a5bdafe9b085b20df705 -F src/trigger.c c836a6caac16ba96611558922106858f6ca3d6bf -F src/update.c 80d77311d91ebc06b27149e75701f1b3e9356622 +F src/trigger.c 1cfb80e2290ef66ea89cb4e821caae65a02c0d56 +F src/update.c 74a6cfb34e9732c1e2a86278b229913b4b51eeec F src/utf.c c53eb7404b3eb5c1cbb5655c6a7a0e0ce6bd50f0 -F src/util.c 0f33bbbdfcc4a2d8cf20c3b2a16ffc3b57c58a70 +F src/util.c 06302ffd2b80408d4f6c7af71f7090e0cf8d8ff7 F src/vacuum.c 05513dca036a1e7848fe18d5ed1265ac0b32365e -F src/vdbe.c 80d511d7096918f4f6be6a63988a885c54dd1048 -F src/vdbe.h 5cf09e7ee8a3f7d93bc51f196a96550786afe7a1 -F src/vdbeInt.h ad84226cc0adcb1185c22b70696b235a1678bb45 -F src/vdbeapi.c 7f01db7d26758b2be316116f8325a0b9f0d8edd6 -F src/vdbeaux.c cfb5207d13d0bc3d2753bba67900c462b60ecb08 -F src/vdbeblob.c f024f0bf420f36b070143c32b15cc7287341ffd3 -F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b +F src/vdbe.c 26deb38f5bd32ebeb2cb60853a52f2bf33d71641 +F src/vdbe.h f0725ee997db869ecae5bb70a71612aabeca7755 +F src/vdbeInt.h 693d6ac6810298fc6b4c503cfbe3f99a240f40af +F src/vdbeapi.c 335435e65443f38d3073b5043e80cbbb7090c2d9 - F src/vdbeaux.c 49be7a5ce6a1b7df9ef5791133c3e4e6ab2a1ffe ++F src/vdbeaux.c 669fe607968e058ef49f7ed7846efde4fece5848 +F src/vdbeblob.c 32f2a4899d67f69634ea4dd93e3f651936d732cb +F src/vdbemem.c 5e6effb96dd53d233361cbfaa3f0a43b9af689e9 +F src/vdbesort.c 468d43c057063e54da4f1988b38b4f46d60e7790 F src/vdbetrace.c 4b92fe7355f682368203d29b2be7125cbab85e79 F src/vtab.c 901791a47318c0562cd0c676a2c6ff1bc530e582 - F src/wal.c 92c7c876b026d5e38fab3ce332e49266ffcf8b2b + F src/wal.c eea77c324942f7e31ce9c3a5e6e86c4a0424fa09 F src/wal.h e75d87752bd5df3dc4152ee2cb3b0dcd0b309e5e F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f -F src/where.c 55403ce19c506be6a321c7f129aff693d6103db5 -F test/8_3_names.test b93687beebd17f6ebf812405a6833bae5d1f4199 +F src/where.c b641d399cfd8588d0e20d9790d1582b663a732a8 +F test/8_3_names.test 631ea964a3edb091cf73c3b540f6bcfdb36ce823 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87 -F test/all.test 51756962d522e474338e9b2ebb26e7364d4aa125 -F test/alter.test a3f570072b53d7c0fe463bab3f5affa8e113c487 -F test/alter2.test 75f731508f1bf27ba09a6075c66cd02216ba464b -F test/alter3.test 8677e48d95536f7a6ed86a1a774744dadcc22b07 -F test/alter4.test 1e5dd6b951e9f65ca66422edff02e56df82dd403 +F test/all.test 52fc8dee494092031a556911d404ca30a749a30b +F test/alter.test 5314fc01ef51ab8af0b8890725b710ed48d4806b +F test/alter2.test 7ea05c7d92ac99349a802ef7ada17294dd647060 +F test/alter3.test 49c9d9fba2b8fcdce2dedeca97bbf1f369cc548d +F test/alter4.test b2debc14d8cbe4c1d12ccd6a41eef88a8c1f15d5 F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc -F test/analyze.test c8cb89e8736336f1f0646c8123e6028a14c7b55e +F test/analyze.test 68b43c1f9cd6ffc3bbb30d27a23712b38c413eca F test/analyze2.test 8f2b1534d43f5547ce9a6b736c021d4192c75be3 F test/analyze3.test d61f55d8b472fc6e713160b1e577f7a68e63f38b F test/analyze4.test 757b37875cf9bb528d46f74497bc789c88365045 @@@ -964,11 -951,11 +964,11 @@@ F tool/speedtest2.tcl ee2149167303ba8e9 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c -F tool/symbols.sh bc2a3709940d47c8ac8e0a1fdf17ec801f015a00 -F tool/tostr.awk 11760e1b94a5d3dcd42378f3cc18544c06cfa576 +F tool/symbols.sh caaf6ccc7300fd43353318b44524853e222557d5 +F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -F tool/warnings.sh 347d974d143cf132f953b565fbc03026f19fcb4d -P aef7945c423a8338374572eeda9444866c64569b -R d7448c6862ea7b8b001f5bf968511903 -U adam -Z 39deebc534cda2d5bd1c84327ddbee27 +F tool/warnings.sh b7fdb2cc525f5ef4fa43c80e771636dd3690f9d2 - P ffed86bf969b98d196ac50bb5e5faddecab4fc59 3e0da808d2f5b4d12046e05980ca04578f581177 - R fab0c6c716ebe505f8c308159e4b4eab ++P ade72b1874c7672ae8d62b9ebac8e4d63fee80cc db5b7b778c09c57501cb8266895a0ea4f2de7649 ++R 492a1b6738940e27b5c3378a18dde5be +U drh - Z 7d1fe25483dc7359b7f468acf5aa09ab ++Z 7f2d52c0164fc6fa32a2a1d8b7959b0c diff --cc manifest.uuid index 09073088a7,1d16fcb865..fb06f2d625 --- a/manifest.uuid +++ b/manifest.uuid @@@ -1,1 -1,1 +1,1 @@@ - ade72b1874c7672ae8d62b9ebac8e4d63fee80cc -db5b7b778c09c57501cb8266895a0ea4f2de7649 ++6cb43f6c6e9d8054e00acab378b8af0d82d3084c diff --cc src/backup.c index 70a782665b,322ff87af6..ab2555a080 --- a/src/backup.c +++ b/src/backup.c @@@ -410,106 -410,111 +410,115 @@@ int sqlite3_backup_step(sqlite3_backup ** the case where the source and destination databases have the ** same schema version. */ - if( rc==SQLITE_DONE - && (rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1))==SQLITE_OK - ){ - int nDestTruncate; - - if( p->pDestDb ){ - sqlite3ResetInternalSchema(p->pDestDb, -1); + if( rc==SQLITE_DONE ){ + rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1); + if( rc==SQLITE_OK ){ + if( p->pDestDb ){ + sqlite3ResetInternalSchema(p->pDestDb, -1); + } + if( destMode==PAGER_JOURNALMODE_WAL ){ + rc = sqlite3BtreeSetVersion(p->pDest, 2); + } + } + + if( destMode==PAGER_JOURNALMODE_WAL ){ + /* This call cannot fail. The success of the BtreeUpdateMeta() - ** method above indicates that a write transaction has been opened - ** and page 1 is already dirty. Therefore this always succeeds. - */ ++ ** method above indicates that a write transaction has been opened ++ ** and page 1 is already dirty. Therefore this always succeeds. ++ */ + TESTONLY(int rc2 =) sqlite3BtreeSetVersion(p->pDest, 2); + assert( rc2==SQLITE_OK ); } - - /* Set nDestTruncate to the final number of pages in the destination - ** database. The complication here is that the destination page - ** size may be different to the source page size. - ** - ** If the source page size is smaller than the destination page size, - ** round up. In this case the call to sqlite3OsTruncate() below will - ** fix the size of the file. However it is important to call - ** sqlite3PagerTruncateImage() here so that any pages in the - ** destination file that lie beyond the nDestTruncate page mark are - ** journalled by PagerCommitPhaseOne() before they are destroyed - ** by the file truncation. - */ - assert( pgszSrc==sqlite3BtreeGetPageSize(p->pSrc) ); - assert( pgszDest==sqlite3BtreeGetPageSize(p->pDest) ); - if( pgszSrcpDest->pBt) ){ - nDestTruncate--; - } - }else{ - nDestTruncate = nSrcPage * (pgszSrc/pgszDest); - } - sqlite3PagerTruncateImage(pDestPager, nDestTruncate); - - if( pgszSrc= iSize || ( - nDestTruncate==(int)(PENDING_BYTE_PAGE(p->pDest->pBt)-1) - && iSize>=PENDING_BYTE && iSize<=PENDING_BYTE+pgszDest - )); - - /* This call ensures that all data required to recreate the original - ** database has been stored in the journal for pDestPager and the - ** journal synced to disk. So at this point we may safely modify - ** the database file in any way, knowing that if a power failure - ** occurs, the original database will be reconstructed from the - ** journal file. */ - rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 1); - - /* Write the extra pages and truncate the database file as required. */ - iEnd = MIN(PENDING_BYTE + pgszDest, iSize); - for( - iOff=PENDING_BYTE+pgszSrc; - rc==SQLITE_OK && iOffpSrc) ); + assert( pgszDest==sqlite3BtreeGetPageSize(p->pDest) ); + if( pgszSrcpDest->pBt) ){ + nDestTruncate--; } - sqlite3PagerUnref(pSrcPg); - } - if( rc==SQLITE_OK ){ - rc = backupTruncateFile(pFile, iSize); + }else{ + nDestTruncate = nSrcPage * (pgszSrc/pgszDest); } + sqlite3PagerTruncateImage(pDestPager, nDestTruncate); + + if( pgszSrc= iSize || ( + nDestTruncate==(int)(PENDING_BYTE_PAGE(p->pDest->pBt)-1) + && iSize>=PENDING_BYTE && iSize<=PENDING_BYTE+pgszDest + )); + + /* This call ensures that all data required to recreate the original + ** database has been stored in the journal for pDestPager and the + ** journal synced to disk. So at this point we may safely modify + ** the database file in any way, knowing that if a power failure + ** occurs, the original database will be reconstructed from the + ** journal file. */ + rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 1); + + /* Write the extra pages and truncate the database file as required */ + iEnd = MIN(PENDING_BYTE + pgszDest, iSize); + for( + iOff=PENDING_BYTE+pgszSrc; + rc==SQLITE_OK && iOffpDest, 0)) + ){ + rc = SQLITE_DONE; } - }else{ - rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 0); - } - - /* Finish committing the transaction to the destination database. */ - if( SQLITE_OK==rc - && SQLITE_OK==(rc = sqlite3BtreeCommitPhaseTwo(p->pDest, 0)) - ){ - rc = SQLITE_DONE; } } diff --cc src/mem1.c index 6b1c30afb5,43a463d447..a845b292f7 --- a/src/mem1.c +++ b/src/mem1.c @@@ -32,7 -32,7 +32,6 @@@ #define SQLITE_FREE(x) free(x) #define SQLITE_REALLOC(x,y) realloc((x),(y)) -- #else @@@ -60,14 -61,11 +60,22 @@@ static void *sqlite3MemMalloc(int nByte sqlite3_int64 *p; assert( nByte>0 ); nByte = ROUND8(nByte); - p = SQLITE_MALLOC( nByte+8 ); ++#ifndef SQLITE_MALLOCSIZE ++ p = SQLITE_MALLOC( nByte + 8 ); + if( p ){ + p[0] = nByte; + p++; + }else{ + testcase( sqlite3GlobalConfig.xLog!=0 ); + sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte); + } ++#else + p = SQLITE_MALLOC( nByte ); + if( !p ){ + testcase( sqlite3GlobalConfig.xLog!=0 ); + sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte); + } ++#endif return (void *)p; } @@@ -82,7 -80,6 +90,9 @@@ static void sqlite3MemFree(void *pPrior){ sqlite3_int64 *p = (sqlite3_int64*)pPrior; assert( pPrior!=0 ); ++#ifndef SQLITE_MALLOCSIZE + p--; ++#endif SQLITE_FREE(p); } @@@ -91,11 -88,9 +101,15 @@@ ** or xRealloc(). */ static int sqlite3MemSize(void *pPrior){ ++#ifndef SQLITE_MALLOCSIZE sqlite3_int64 *p; if( pPrior==0 ) return 0; + p = (sqlite3_int64*)pPrior; + p--; + return (int)p[0]; ++#else + return (int)SQLITE_MALLOCSIZE(pPrior); ++#endif } /* @@@ -112,17 -107,13 +126,27 @@@ static void *sqlite3MemRealloc(void *pP sqlite3_int64 *p = (sqlite3_int64*)pPrior; assert( pPrior!=0 && nByte>0 ); assert( nByte==ROUND8(nByte) ); /* EV: R-46199-30249 */ ++#ifndef SQLITE_MALLOCSIZE + p--; + p = SQLITE_REALLOC(p, nByte+8 ); + if( p ){ + p[0] = nByte; + p++; + }else{ ++ testcase( sqlite3GlobalConfig.xLog!=0 ); ++ sqlite3_log(SQLITE_NOMEM, ++ "failed memory resize %u to %u bytes", ++ sqlite3MemSize(pPrior), nByte); ++ } ++#else + p = SQLITE_REALLOC(p, nByte ); + if( !p ){ testcase( sqlite3GlobalConfig.xLog!=0 ); sqlite3_log(SQLITE_NOMEM, "failed memory resize %u to %u bytes", sqlite3MemSize(pPrior), nByte); } ++#endif return (void*)p; } diff --cc src/os_unix.c index f38258124e,9ec16348a5..009b79a5c8 --- a/src/os_unix.c +++ b/src/os_unix.c @@@ -1574,8 -1561,16 +1574,8 @@@ static int unixCheckReservedLock(sqlite ** Zero is returned if the call completes successfully, or -1 if a call ** to fcntl() fails. In this case, errno is set appropriately (by fcntl()). */ --static int unixFileLock(unixFile *pFile, struct flock *pLock){ - return _unixFileLock(pFile, pLock, 0); -} - -static int unixFileLock2(unixFile *pFile, struct flock *pLock){ - return _unixFileLock(pFile, pLock, 10); -} - -static int _unixFileLock(unixFile *pFile, struct flock *pLock, int retry) { - int rc = 0; ++static int unixFileLock(unixFile *pFile, struct flock *pLock, int nRetry){ + int rc; unixInodeInfo *pInode = pFile->pInode; assert( unixMutexHeld() ); assert( pInode!=0 ); @@@ -1594,6 -1589,6 +1594,13 @@@ pInode->bProcessLock = 1; pInode->nLock++; }else{ ++ int i = 0; ++ do { ++ rc = osFcntl(pFile->h, F_SETLK, pLock); ++ if( rc && nRetry ){ ++ usleep(100 * (++i)); ++ } ++ }while( !rc && nRetry-- ); rc = 0; } }else{ @@@ -1737,7 -1738,7 +1744,7 @@@ static int unixLock(sqlite3_file *id, i ){ lock.l_type = (eFileLock==SHARED_LOCK?F_RDLCK:F_WRLCK); lock.l_start = PENDING_BYTE; -- if( unixFileLock(pFile, &lock) ){ ++ if( unixFileLock(pFile, &lock, 0) ){ tErrno = errno; rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK); if( IS_LOCK_ERROR(rc) ){ @@@ -1759,7 -1760,7 +1766,7 @@@ /* Now get the read-lock */ lock.l_start = SHARED_FIRST; lock.l_len = SHARED_SIZE; -- if( unixFileLock(pFile, &lock) ){ ++ if( unixFileLock(pFile, &lock, 0) ){ tErrno = errno; rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK); } @@@ -1768,7 -1769,7 +1775,7 @@@ lock.l_start = PENDING_BYTE; lock.l_len = 1L; lock.l_type = F_UNLCK; - if( unixFileLock(pFile, &lock) && rc==SQLITE_OK ){ - if( unixFileLock2(pFile, &lock) && rc==SQLITE_OK ){ ++ if( unixFileLock(pFile, &lock, 10) && rc==SQLITE_OK ){ /* This could happen with a network mount */ tErrno = errno; #if OSLOCKING_CHECK_BUSY_IOERR @@@ -1809,7 -1810,7 +1816,7 @@@ lock.l_len = SHARED_SIZE; } -- if( unixFileLock(pFile, &lock) ){ ++ if( unixFileLock(pFile, &lock, 0) ){ tErrno = errno; rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK); if( rc!=SQLITE_BUSY ){ @@@ -1930,21 -1931,21 +1937,21 @@@ static int posixUnlock(sqlite3_file *id ** 4: [RRRR.] */ if( eFileLock==SHARED_LOCK ){ ++ int tErrno; /* Error code from system call errors */ #if !defined(__APPLE__) || !SQLITE_ENABLE_LOCKING_STYLE (void)handleNFSUnlock; assert( handleNFSUnlock==0 ); #endif #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE - int tErrno; /* Error code from system call errors */ if( handleNFSUnlock ){ - int tErrno; /* Error code from system call errors */ off_t divSize = SHARED_SIZE - 1; lock.l_type = F_UNLCK; lock.l_whence = SEEK_SET; lock.l_start = SHARED_FIRST; lock.l_len = divSize; - if( unixFileLock(pFile, &lock)==(-1) ){ - if( unixFileLock2(pFile, &lock)==(-1) ){ ++ if( unixFileLock(pFile, &lock, 10)==(-1) ){ tErrno = errno; #if OSLOCKING_CHECK_BUSY_IOERR rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK); @@@ -1960,9 -1961,13 +1967,9 @@@ lock.l_whence = SEEK_SET; lock.l_start = SHARED_FIRST; lock.l_len = divSize; - if( unixFileLock(pFile, &lock)==(-1) ){ - if( unixFileLock2(pFile, &lock)==(-1) ){ ++ if( unixFileLock(pFile, &lock, 10)==(-1) ){ tErrno = errno; -#if OSLOCKING_CHECK_BUSY_IOERR rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK); -#else - rc = SQLITE_IOERR_UNLOCK; -#endif if( IS_LOCK_ERROR(rc) ){ pFile->lastErrno = tErrno; } @@@ -1972,7 -1977,7 +1979,7 @@@ lock.l_whence = SEEK_SET; lock.l_start = SHARED_FIRST+divSize; lock.l_len = SHARED_SIZE-divSize; - if( unixFileLock(pFile, &lock)==(-1) ){ - if( unixFileLock2(pFile, &lock)==(-1) ){ ++ if( unixFileLock(pFile, &lock, 10)==(-1) ){ tErrno = errno; #if OSLOCKING_CHECK_BUSY_IOERR rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK); @@@ -1991,13 -1996,10 +1998,10 @@@ lock.l_whence = SEEK_SET; lock.l_start = SHARED_FIRST; lock.l_len = SHARED_SIZE; - if( unixFileLock(pFile, &lock) ){ - #if OSLOCKING_CHECK_BUSY_IOERR - if( unixFileLock2(pFile, &lock) ){ ++ if( unixFileLock(pFile, &lock, 10) ){ tErrno = errno; + #if OSLOCKING_CHECK_BUSY_IOERR rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK); - if( IS_LOCK_ERROR(rc) ){ - pFile->lastErrno = tErrno; - } #else /* In theory, the call to unixFileLock() cannot fail because another ** process is holding an incompatible lock. If it does, this @@@ -2016,7 -2021,7 +2023,7 @@@ lock.l_whence = SEEK_SET; lock.l_start = PENDING_BYTE; lock.l_len = 2L; assert( PENDING_BYTE+1==RESERVED_BYTE ); - if( unixFileLock(pFile, &lock)==0 ){ - if( unixFileLock2(pFile, &lock)==0 ){ ++ if( unixFileLock(pFile, &lock, 10)==0 ){ pInode->eFileLock = SHARED_LOCK; }else{ #if OSLOCKING_CHECK_BUSY_IOERR @@@ -2045,7 -2050,7 +2052,7 @@@ SimulateIOErrorBenign(1); SimulateIOError( h=(-1) ) SimulateIOErrorBenign(0); - if( unixFileLock(pFile, &lock)==0 ){ - if( unixFileLock2(pFile, &lock)==0 ){ ++ if( unixFileLock(pFile, &lock, 10)==0 ){ pInode->eFileLock = NO_LOCK; }else{ #if OSLOCKING_CHECK_BUSY_IOERR @@@ -3887,317 -3866,307 +3894,491 @@@ static int getDbPathForUnixFile(unixFil #endif static int isProxyLockingMode(unixFile *); + #if (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__) -static int unixTruncateDatabase(unixFile *, int); ++static int unixTruncateDatabase(unixFile *pFile, int bFlags) { ++ sqlite3_file *id = (sqlite3_file *)pFile; ++ int rc = SQLITE_OK; ++ void *pLock = NULL; ++ int flags = 0; ++ int corruptFileLock = 0; ++ int isCorrupt = 0; ++ ++#if SQLITE_ENABLE_DATA_PROTECTION ++ flags |= pFile->protFlags; ++#endif ++#if SQLITE_ENABLE_LOCKING_STYLE ++ if( isProxyLockingMode(pFile) ){ ++ flags |= SQLITE_OPEN_AUTOPROXY; ++ } ++#endif ++ ++ rc = sqlite3demo_superlock(pFile->zPath, 0, flags, 0, 0, &pLock); ++ if( rc ){ ++ if( rc==SQLITE_CORRUPT || rc==SQLITE_NOTADB ){ ++ isCorrupt = 1; ++ rc = sqlite3demo_superlock_corrupt(id, SQLITE_LOCK_EXCLUSIVE, &corruptFileLock); ++ } ++ if( rc ){ ++ return rc; ++ } ++ } ++ rc = pFile->pMethod->xTruncate(id, ((pFile->fsFlags & SQLITE_FSFLAGS_IS_MSDOS) != 0) ? 1L : 0L); ++ if( rc==SQLITE_OK ){ ++ unixInvalidateSupportFiles(pFile, 0); ++ } ++ pFile->pMethod->xSync(id, SQLITE_SYNC_FULL); ++ ++ ++ if( isCorrupt ){ ++ sqlite3demo_superunlock_corrupt(id, corruptFileLock); ++ }else{ ++ sqlite3demo_superunlock(pLock); ++ } ++ return rc; ++} + -static int unixInvalidateSupportFiles(unixFile *, int); ++static int unixInvalidateSupportFiles(unixFile *pFile, int skipWAL) { ++ char jPath[MAXPATHLEN+9]; ++ int zLen = strlcpy(jPath, pFile->zPath, MAXPATHLEN+9); ++ if( zLenpInode is shared across threads */ ++ unixShmNode *pShmNode = pFile->pInode->pShmNode; ++ if( pShmNode && !pShmNode->isReadonly ){ ++ struct stat sStat; ++ sqlite3_mutex_enter(pShmNode->mutex); ++ ++ if( pShmNode->h>=0 && !osFstat(pShmNode->h, &sStat) ){ ++ unsigned long size = (sStat.st_size<4) ? sStat.st_size : 4; ++ if( size>0 ){ ++ bzero(pShmNode->apRegion[0], size); ++ sqlite3_mutex_leave(pShmNode->mutex); ++ unixLeaveMutex(); ++ continue; ++ } ++ } ++ sqlite3_mutex_leave(pShmNode->mutex); ++ } ++ unixLeaveMutex(); ++ } ++ jLen = strlcpy(&jPath[zLen], extensions[j], 9); ++ if( jLen < 9 ){ ++ int jflags = (j<2) ? O_TRUNC : O_RDWR; ++ int jfd = open(jPath, jflags); ++ if( jfd==(-1) ){ ++ if( errno!=ENOENT ){ ++ perror(jPath); ++ } ++ } else { ++ if( j==2 ){ ++ struct stat sStat; ++ if( !osFstat(jfd, &sStat) ){ ++ unsigned long size = (sStat.st_size<4) ? sStat.st_size : 4; ++ if( size>0 ){ ++ uint32_t zero = 0; ++ pwrite(jfd, &zero, (size_t)size, 0); ++ } ++ } ++ } ++ fsync(jfd); ++ close(jfd); ++ } ++ } ++ } ++ } ++ return SQLITE_OK; ++} + + static int unixReplaceDatabase(unixFile *pFile, sqlite3 *srcdb) { + sqlite3_file *id = (sqlite3_file *)pFile; + Btree *pSrcBtree = NULL; + sqlite3_file *src_file = NULL; + unixFile *pSrcFile = NULL; + char srcWalPath[MAXPATHLEN+5]; + int srcWalFD = -1; + int rc = SQLITE_OK; + void *pLock = NULL; + int flags = 0; + sqlite3 *srcdb2 = NULL; + copyfile_state_t s; + int corruptSrcFileLock = 0; + int corruptDstFileLock = 0; + int isSrcCorrupt = 0; + int isDstCorrupt = 0; + + if( !sqlite3SafetyCheckOk(srcdb) ){ + return SQLITE_MISUSE; + } + + #if SQLITE_ENABLE_DATA_PROTECTION + flags |= pFile->protFlags; + #endif + #if SQLITE_ENABLE_LOCKING_STYLE + if( isProxyLockingMode(pFile) ){ + flags |= SQLITE_OPEN_AUTOPROXY; + } + #endif + + rc = sqlite3demo_superlock(pFile->zPath, 0, flags, 0, 0, &pLock); + if( rc ){ + if( rc==SQLITE_CORRUPT || rc==SQLITE_NOTADB ){ + isDstCorrupt = 1; + rc = sqlite3demo_superlock_corrupt(id, SQLITE_LOCK_EXCLUSIVE, &corruptDstFileLock); + } + if( rc ){ + return rc; + } + } + /* get the src file descriptor adhering to the db struct access rules + ** this code is modeled after sqlite3_file_control() in main.c + */ + sqlite3_mutex_enter(srcdb->mutex); + if( srcdb->nDb>0 ){ + pSrcBtree = srcdb->aDb[0].pBt; + } + if( pSrcBtree ){ + Pager *pSrcPager; + sqlite3BtreeEnter(pSrcBtree); + pSrcPager = sqlite3BtreePager(pSrcBtree); + assert( pSrcPager!=0 ); + src_file = sqlite3PagerFile(pSrcPager); + assert( src_file!=0 ); + if( src_file->pMethods ){ + int srcFlags = 0; + pSrcFile = (unixFile *)src_file; + /* wal mode db cannot be opened readonly */ + if ((pSrcFile->openFlags & O_RDWR) == O_RDWR) { + srcFlags = SQLITE_OPEN_READWRITE; + } else { + srcFlags = SQLITE_OPEN_READONLY; + } + #if SQLITE_ENABLE_DATA_PROTECTION + srcFlags |= pSrcFile->protFlags; + #endif + #if SQLITE_ENABLE_LOCKING_STYLE + if( isProxyLockingMode(pSrcFile) ){ + srcFlags |= SQLITE_OPEN_AUTOPROXY; + } + #endif + rc = sqlite3_open_v2(pSrcFile->zPath, &srcdb2, srcFlags, 0); + if( rc==SQLITE_OK ){ + /* start a deferred transaction and read to establish a read lock */ + rc = sqlite3_exec(srcdb2, "BEGIN DEFERRED; PRAGMA schema_version", 0, 0, 0); + if( rc==SQLITE_CORRUPT || rc==SQLITE_NOTADB ){ + isSrcCorrupt = 1; + rc = sqlite3demo_superlock_corrupt(src_file, SQLITE_LOCK_SHARED, &corruptSrcFileLock); + } + } + } + } + if( !srcdb2 || pSrcFile==NULL || pSrcFile->h<0){ + rc = SQLITE_INTERNAL; + } + if( rc!=SQLITE_OK ){ + goto end_replace_database; + } + /* both databases are locked appropriately, copy the src wal journal if + ** one exists and then the actual database file + */ + strlcpy(srcWalPath, pSrcFile->zPath, MAXPATHLEN+5); + strlcat(srcWalPath, "-wal", MAXPATHLEN+5); + srcWalFD = open(srcWalPath, O_RDONLY); + if( !(srcWalFD<0) ){ + char dstWalPath[MAXPATHLEN+5]; + int dstWalFD = -1; + strlcpy(dstWalPath, pFile->zPath, MAXPATHLEN+5); + strlcat(dstWalPath, "-wal", MAXPATHLEN+5); + dstWalFD = open(dstWalPath, O_RDWR|O_CREAT, SQLITE_DEFAULT_FILE_PERMISSIONS); + if( !(dstWalFD<0) ){ + s = copyfile_state_alloc(); + lseek(srcWalFD, 0, SEEK_SET); + lseek(dstWalFD, 0, SEEK_SET); + if( fcopyfile(srcWalFD, dstWalFD, s, COPYFILE_ALL) ){ + int err=errno; + switch(err) { + case ENOMEM: + rc = SQLITE_NOMEM; + break; + default: + pFile->lastErrno = err; + rc = SQLITE_IOERR; + } + } + copyfile_state_free(s); + close(dstWalFD); + } + close(srcWalFD); + } + if( rc==SQLITE_OK ){ + /* before we copy, ensure that the file change counter will be modified */ + uint32_t srcChange = 0; + uint32_t dstChange = 0; + pread(pSrcFile->h, &srcChange, 4, 24); + pread(pFile->h, &dstChange, 4, 24); + + /* copy the actual database */ + s = copyfile_state_alloc(); + lseek(pSrcFile->h, 0, SEEK_SET); + lseek(pFile->h, 0, SEEK_SET); + if( fcopyfile(pSrcFile->h, pFile->h, s, COPYFILE_ALL) ){ + int err=errno; + switch(err) { + case ENOMEM: + rc = SQLITE_NOMEM; + break; + default: + pFile->lastErrno = err; + rc = SQLITE_IOERR; + } + } + copyfile_state_free(s); + + if (srcChange == dstChange) { + /* modify the change counter to force page zero to be reloaded */ + dstChange ++; + pwrite(pFile->h, &dstChange, 4, 24); + } + } + if( isSrcCorrupt ){ + sqlite3demo_superunlock_corrupt(src_file, corruptSrcFileLock); + }else{ + /* done with the source db so end the transaction */ + sqlite3_exec(srcdb2, "COMMIT", 0, 0, 0); + } + /* zero out any old journal clutter */ + if( rc==SQLITE_OK ){ + int skipWAL = (srcWalFD<0)?0:1; + unixInvalidateSupportFiles(pFile, skipWAL); + } + + end_replace_database: + if( pSrcBtree ){ + sqlite3_close(srcdb2); + sqlite3BtreeLeave(pSrcBtree); + } + sqlite3_mutex_leave(srcdb->mutex); + if( isDstCorrupt ){ + sqlite3demo_superunlock_corrupt(id, corruptDstFileLock); + }else{ + sqlite3demo_superunlock(pLock); + } + return rc; + } - + #define SQLITE_FILE_HEADER_LEN 16 + #include "btreeInt.h" + /* Check for a conflicting lock. If one is found, print an this + ** on standard output using the format string given and return 1. + ** If there are no conflicting locks, return 0. + */ + static int unixIsLocked( + pid_t pid, /* PID to test for lock owner */ + int h, /* File descriptor to check */ + int type, /* F_RDLCK or F_WRLCK */ + unsigned int iOfst, /* First byte of the lock */ + unsigned int iCnt, /* Number of bytes in the lock range */ + const char *zType /* Type of lock */ + ){ + struct flock lk; + int err; + + memset(&lk, 0, sizeof(lk)); + lk.l_type = type; + lk.l_whence = SEEK_SET; + lk.l_start = iOfst; + lk.l_len = iCnt; + + if( pid!=SQLITE_LOCKSTATE_ANYPID ){ + #ifndef F_GETLKPID + # warning F_GETLKPID undefined, _sqlite3_lockstate falling back to F_GETLK + err = fcntl(h, F_GETLK, &lk); + #else + lk.l_pid = pid; + err = fcntl(h, F_GETLKPID, &lk); + #endif + }else{ + err = fcntl(h, F_GETLK, &lk); + } + + if( err==(-1) ){ + fprintf(stderr, "fcntl(%d) failed: errno=%d\n", h, errno); + return -1; + } + + if( lk.l_type!=F_UNLCK && (pid==SQLITE_LOCKSTATE_ANYPID || lk.l_pid==pid) ){ + #ifdef SQLITE_DEBUG + fprintf(stderr, "%s lock held by %d\n", zType, (int)lk.l_pid); + #endif + return 1; + } + return 0; + } + -static int unixLockstatePid(unixFile *, pid_t, int *); - -#endif /* (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__) */ - + /* -** Information and control of an open file handle. ++** This test only works for lock testing on unix/posix VFS. ++** Adapted from tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce + */ -static int unixFileControl(sqlite3_file *id, int op, void *pArg){ - unixFile *pFile = (unixFile*)id; - switch( op ){ - case SQLITE_FCNTL_LOCKSTATE: { - *(int*)pArg = pFile->eFileLock; - return SQLITE_OK; - } - case SQLITE_FCNTL_LAST_ERRNO: { - *(int*)pArg = pFile->lastErrno; - return SQLITE_OK; - } - case SQLITE_FCNTL_CHUNK_SIZE: { - pFile->szChunk = *(int *)pArg; - return SQLITE_OK; - } - case SQLITE_FCNTL_SIZE_HINT: { - return fcntlSizeHint(pFile, *(i64 *)pArg); - } - case SQLITE_FCNTL_PERSIST_WAL: { - int bPersist = *(int*)pArg; - if( bPersist<0 ){ - *(int*)pArg = (pFile->ctrlFlags & UNIXFILE_PERSIST_WAL)!=0; - }else if( bPersist==0 ){ - pFile->ctrlFlags &= ~UNIXFILE_PERSIST_WAL; - }else{ - pFile->ctrlFlags |= UNIXFILE_PERSIST_WAL; - } - return SQLITE_OK; - } -#ifndef NDEBUG - /* The pager calls this method to signal that it has done - ** a rollback and that the database is therefore unchanged and - ** it hence it is OK for the transaction change counter to be - ** unchanged. - */ - case SQLITE_FCNTL_DB_UNCHANGED: { - ((unixFile*)id)->dbUpdate = 0; - return SQLITE_OK; - } -#endif -#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) - case SQLITE_FCNTL_SET_LOCKPROXYFILE: - case SQLITE_FCNTL_GET_LOCKPROXYFILE: { - return proxyFileControl(id,op,pArg); - } -#endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */ -#if (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__) - case SQLITE_FCNTL_TRUNCATE_DATABASE: { - return unixTruncateDatabase(pFile, (pArg ? (*(int *)pArg) : 0)); - } - case SQLITE_FCNTL_REPLACE_DATABASE: { - return unixReplaceDatabase(pFile, (sqlite3 *)pArg); - } - case SQLITE_FCNTL_LOCKSTATE_PID: { - LockstatePID *pLockstate; - int rc; - - if( pArg==NULL ){ - return SQLITE_MISUSE; - } - pLockstate = (LockstatePID *)pArg; - rc = unixLockstatePid(pFile, pLockstate->pid, &(pLockstate->state)); - return rc; ++static int unixLockstatePid(unixFile *pFile, pid_t pid, int *pLockstate){ ++ int hDb; /* File descriptor for the open database file */ ++ int hShm = -1; /* File descriptor for WAL shared-memory file */ ++ ssize_t got; /* Bytes read from header */ ++ int isWal; /* True if in WAL mode */ ++ int nLock = 0; /* Number of locks held */ ++ unsigned char aHdr[100]; /* Database header */ ++ ++ assert(pLockstate); ++ ++ /* make sure we are dealing with a database file */ ++ hDb = pFile->h; ++ if( hDb<0 ){ ++ *pLockstate = SQLITE_LOCKSTATE_ERROR; ++ return SQLITE_ERROR; ++ } ++ assert( (strlen(SQLITE_FILE_HEADER)+1)==SQLITE_FILE_HEADER_LEN ); ++ got = pread(hDb, aHdr, 100, 0); ++ if( got<0 ){ ++ *pLockstate = SQLITE_LOCKSTATE_ERROR; ++ return SQLITE_ERROR; ++ } ++ if( got!=100 || memcmp(aHdr, SQLITE_FILE_HEADER, SQLITE_FILE_HEADER_LEN)!=0 ){ ++ *pLockstate = SQLITE_LOCKSTATE_NOTADB; ++ return SQLITE_NOTADB; ++ } ++ ++ /* First check for an exclusive lock */ ++ nLock += unixIsLocked(pid, hDb, F_RDLCK, SHARED_FIRST, SHARED_SIZE, "EXCLUSIVE"); ++ isWal = aHdr[18]==2; ++ if( nLock==0 && isWal==0 ){ ++ /* Rollback mode */ ++ nLock += unixIsLocked(pid, hDb, F_WRLCK, PENDING_BYTE, SHARED_SIZE+2, "PENDING|RESERVED|SHARED"); ++ } ++ if( nLock==0 && isWal!=0 ){ ++ /* lookup the file descriptor for the shared memory file if we have it open in this process */ ++ unixEnterMutex(); /* Because pFile->pInode is shared across threads */ ++ unixShmNode *pShmNode = pFile->pInode->pShmNode; ++ if( pShmNode ){ ++ sqlite3_mutex_enter(pShmNode->mutex); ++ ++ hShm = pShmNode->h; ++ if( hShm >= 0){ ++ if( unixIsLocked(pid, hShm, F_RDLCK, SHM_RECOVER, 1, "WAL-RECOVERY") || ++ unixIsLocked(pid, hShm, F_RDLCK, SHM_WRITE, 1, "WAL-WRITE") ){ ++ nLock = 1; ++ } ++ } ++ ++ sqlite3_mutex_leave(pShmNode->mutex); ++ } ++ ++ if( hShm<0 ){ ++ /* the shared memory file isn't open in this process space, open our own FD */ ++ char zShm[MAXPATHLEN]; ++ ++ /* WAL mode */ ++ strlcpy(zShm, pFile->zPath, MAXPATHLEN); ++ strlcat(zShm, "-shm", MAXPATHLEN); ++ hShm = open(zShm, O_RDONLY, 0); ++ if( hShm<0 ){ ++ *pLockstate = SQLITE_LOCKSTATE_OFF; ++ unixLeaveMutex(); ++ return SQLITE_OK; ++ } ++ if( unixIsLocked(pid, hShm, F_RDLCK, SHM_RECOVER, 1, "WAL-RECOVERY") || ++ unixIsLocked(pid, hShm, F_RDLCK, SHM_WRITE, 1, "WAL-WRITE") ){ ++ nLock = 1; ++ } ++ close(hShm); ++ } ++ unixLeaveMutex(); ++ } ++ if( nLock>0 ){ ++ *pLockstate = SQLITE_LOCKSTATE_ON; ++ } else { ++ *pLockstate = SQLITE_LOCKSTATE_OFF; ++ } ++ return SQLITE_OK; ++} ++ ++#endif /* (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__) */ ++ ++ +/* +** Information and control of an open file handle. +*/ +static int unixFileControl(sqlite3_file *id, int op, void *pArg){ + unixFile *pFile = (unixFile*)id; + switch( op ){ + case SQLITE_FCNTL_LOCKSTATE: { + *(int*)pArg = pFile->eFileLock; + return SQLITE_OK; + } + case SQLITE_LAST_ERRNO: { + *(int*)pArg = pFile->lastErrno; + return SQLITE_OK; + } + case SQLITE_FCNTL_CHUNK_SIZE: { + pFile->szChunk = *(int *)pArg; + return SQLITE_OK; + } + case SQLITE_FCNTL_SIZE_HINT: { + int rc; + SimulateIOErrorBenign(1); + rc = fcntlSizeHint(pFile, *(i64 *)pArg); + SimulateIOErrorBenign(0); + return rc; + } + case SQLITE_FCNTL_PERSIST_WAL: { + int bPersist = *(int*)pArg; + if( bPersist<0 ){ + *(int*)pArg = (pFile->ctrlFlags & UNIXFILE_PERSIST_WAL)!=0; + }else if( bPersist==0 ){ + pFile->ctrlFlags &= ~UNIXFILE_PERSIST_WAL; + }else{ + pFile->ctrlFlags |= UNIXFILE_PERSIST_WAL; + } + return SQLITE_OK; + } +#ifndef NDEBUG + /* The pager calls this method to signal that it has done + ** a rollback and that the database is therefore unchanged and + ** it hence it is OK for the transaction change counter to be + ** unchanged. + */ + case SQLITE_FCNTL_DB_UNCHANGED: { + ((unixFile*)id)->dbUpdate = 0; + return SQLITE_OK; } +#endif +#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) - case SQLITE_SET_LOCKPROXYFILE: - case SQLITE_GET_LOCKPROXYFILE: { ++ case SQLITE_FCNTL_SET_LOCKPROXYFILE: ++ case SQLITE_FCNTL_GET_LOCKPROXYFILE: { + return proxyFileControl(id,op,pArg); + } +#endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */ +#if (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__) - case SQLITE_TRUNCATE_DATABASE: { - unixFile *pFile = (unixFile*)id; - int rc = SQLITE_OK; - void *pLock = NULL; - int flags = 0; - int corruptFileLock = 0; - int isCorrupt = 0; - - #if SQLITE_ENABLE_DATA_PROTECTION - flags |= pFile->protFlags; - #endif - #if SQLITE_ENABLE_LOCKING_STYLE - if( isProxyLockingMode(pFile) ){ - flags |= SQLITE_OPEN_AUTOPROXY; - } - #endif - - rc = sqlite3demo_superlock(pFile->zPath, 0, flags, 0, 0, &pLock); - if( rc ){ - if( rc==SQLITE_CORRUPT || rc==SQLITE_NOTADB ){ - isCorrupt = 1; - rc = sqlite3demo_superlock_corrupt(id, SQLITE_LOCK_EXCLUSIVE, &corruptFileLock); - } - if( rc ){ - return rc; - } - } - rc = pFile->pMethod->xTruncate(id, ((pFile->fsFlags & SQLITE_FSFLAGS_IS_MSDOS) != 0) ? 1L : 0L); - - if( rc==SQLITE_OK ){ - char jPath[MAXPATHLEN+9]; - int zLen = strlcpy(jPath, pFile->zPath, MAXPATHLEN+9); - if( zLenpMethod->xSync(id, SQLITE_SYNC_FULL); - } - if( isCorrupt ){ - sqlite3demo_superunlock_corrupt(id, corruptFileLock); - }else{ - sqlite3demo_superunlock(pLock); - } - return rc; ++ case SQLITE_FCNTL_TRUNCATE_DATABASE: { ++ return unixTruncateDatabase(pFile, (pArg ? (*(int *)pArg) : 0)); + } ++ case SQLITE_FCNTL_REPLACE_DATABASE: { ++ return unixReplaceDatabase(pFile, (sqlite3 *)pArg); ++ } ++ case SQLITE_FCNTL_LOCKSTATE_PID: { ++ LockstatePID *pLockstate; ++ int rc; + - case SQLITE_REPLACE_DATABASE: { - unixFile *pFile = (unixFile*)id; - sqlite3 *srcdb = (sqlite3 *)pArg; - Btree *pSrcBtree = NULL; - sqlite3_file *src_file = NULL; - unixFile *pSrcFile = NULL; - char srcWalPath[MAXPATHLEN+5]; - int srcWalFD = -1; - int rc = SQLITE_OK; - void *pLock = NULL; - int flags = 0; - sqlite3 *srcdb2 = NULL; - copyfile_state_t s; - int corruptSrcFileLock = 0; - int corruptDstFileLock = 0; - int isSrcCorrupt = 0; - int isDstCorrupt = 0; - - if( !sqlite3SafetyCheckOk(srcdb) ){ ++ if( pArg==NULL ){ + return SQLITE_MISUSE; + } - - #if SQLITE_ENABLE_DATA_PROTECTION - flags |= pFile->protFlags; - #endif - #if SQLITE_ENABLE_LOCKING_STYLE - if( isProxyLockingMode(pFile) ){ - flags |= SQLITE_OPEN_AUTOPROXY; - } - #endif - - rc = sqlite3demo_superlock(pFile->zPath, 0, flags, 0, 0, &pLock); - if( rc ){ - if( rc==SQLITE_CORRUPT || rc==SQLITE_NOTADB ){ - isDstCorrupt = 1; - rc = sqlite3demo_superlock_corrupt(id, SQLITE_LOCK_EXCLUSIVE, &corruptDstFileLock); - } - if( rc ){ - return rc; - } - } - /* get the src file descriptor adhering to the db struct access rules - ** this code is modeled after sqlite3_file_control() in main.c - */ - sqlite3_mutex_enter(srcdb->mutex); - if( srcdb->nDb>0 ){ - pSrcBtree = srcdb->aDb[0].pBt; - } - if( pSrcBtree ){ - Pager *pSrcPager; - sqlite3BtreeEnter(pSrcBtree); - pSrcPager = sqlite3BtreePager(pSrcBtree); - assert( pSrcPager!=0 ); - src_file = sqlite3PagerFile(pSrcPager); - assert( src_file!=0 ); - if( src_file->pMethods ){ - int srcFlags = 0; - pSrcFile = (unixFile *)src_file; - /* wal mode db cannot be opened readonly */ - if ((pSrcFile->openFlags & O_RDWR) == O_RDWR) { - srcFlags = SQLITE_OPEN_READWRITE; - } else { - srcFlags = SQLITE_OPEN_READONLY; - } - #if SQLITE_ENABLE_DATA_PROTECTION - srcFlags |= pSrcFile->protFlags; - #endif - #if SQLITE_ENABLE_LOCKING_STYLE - if( isProxyLockingMode(pSrcFile) ){ - srcFlags |= SQLITE_OPEN_AUTOPROXY; - } - #endif - rc = sqlite3_open_v2(pSrcFile->zPath, &srcdb2, srcFlags, 0); - if( rc==SQLITE_OK ){ - /* start a deferred transaction and read to establish a read lock */ - rc = sqlite3_exec(srcdb2, "BEGIN DEFERRED; PRAGMA schema_version", 0, 0, 0); - if( rc==SQLITE_CORRUPT || rc==SQLITE_NOTADB ){ - isSrcCorrupt = 1; - rc = sqlite3demo_superlock_corrupt(src_file, SQLITE_LOCK_SHARED, &corruptSrcFileLock); - } - } - } - } - if( !srcdb2 || pSrcFile==NULL || pSrcFile->h<0){ - rc = SQLITE_INTERNAL; - } - if( rc!=SQLITE_OK ){ - goto end_replace_database; - } - /* both databases are locked appropriately, copy the src wal journal if - ** one exists and then the actual database file - */ - strlcpy(srcWalPath, pSrcFile->zPath, MAXPATHLEN+5); - strlcat(srcWalPath, "-wal", MAXPATHLEN+5); - srcWalFD = open(srcWalPath, O_RDONLY); - if( !(srcWalFD<0) ){ - char dstWalPath[MAXPATHLEN+5]; - int dstWalFD = -1; - strlcpy(dstWalPath, pFile->zPath, MAXPATHLEN+5); - strlcat(dstWalPath, "-wal", MAXPATHLEN+5); - dstWalFD = open(dstWalPath, O_RDWR|O_CREAT, SQLITE_DEFAULT_FILE_PERMISSIONS); - if( !(dstWalFD<0) ){ - s = copyfile_state_alloc(); - lseek(srcWalFD, 0, SEEK_SET); - lseek(dstWalFD, 0, SEEK_SET); - if( fcopyfile(srcWalFD, dstWalFD, s, COPYFILE_ALL) ){ - int err=errno; - switch(err) { - case ENOMEM: - rc = SQLITE_NOMEM; - break; - default: - pFile->lastErrno = err; - rc = SQLITE_IOERR; - } - } - copyfile_state_free(s); - close(dstWalFD); - } - close(srcWalFD); - } - if( rc==SQLITE_OK ){ - /* before we copy, ensure that the file change counter will be modified */ - uint32_t srcChange = 0; - uint32_t dstChange = 0; - pread(pSrcFile->h, &srcChange, 4, 24); - pread(pFile->h, &dstChange, 4, 24); - - /* copy the actual database */ - s = copyfile_state_alloc(); - lseek(pSrcFile->h, 0, SEEK_SET); - lseek(pFile->h, 0, SEEK_SET); - if( fcopyfile(pSrcFile->h, pFile->h, s, COPYFILE_ALL) ){ - int err=errno; - switch(err) { - case ENOMEM: - rc = SQLITE_NOMEM; - break; - default: - pFile->lastErrno = err; - rc = SQLITE_IOERR; - } - } - copyfile_state_free(s); - - if (srcChange == dstChange) { - /* modify the change counter to force page zero to be reloaded */ - dstChange ++; - pwrite(pFile->h, &dstChange, 4, 24); - } - } - if( isSrcCorrupt ){ - sqlite3demo_superunlock_corrupt(src_file, corruptSrcFileLock); - }else{ - /* done with the source db so end the transaction */ - sqlite3_exec(srcdb2, "COMMIT", 0, 0, 0); - } - /* zero out any old journal clutter */ - if( rc==SQLITE_OK ){ - char jPath[MAXPATHLEN+9]; - int zLen = strlcpy(jPath, pFile->zPath, MAXPATHLEN+9); - if( zLenpMethod->xSync(id, SQLITE_SYNC_FULL); - } - - end_replace_database: - if( pSrcBtree ){ - sqlite3_close(srcdb2); - sqlite3BtreeLeave(pSrcBtree); - } - sqlite3_mutex_leave(srcdb->mutex); - if( isDstCorrupt ){ - sqlite3demo_superunlock_corrupt(id, corruptDstFileLock); - }else{ - sqlite3demo_superunlock(pLock); - } ++ pLockstate = (LockstatePID *)pArg; ++ rc = unixLockstatePid(pFile, pLockstate->pid, &(pLockstate->state)); + return rc; + } ++ #endif /* (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__) */ case SQLITE_FCNTL_SYNC_OMITTED: { return SQLITE_OK; /* A no-op */ diff --cc src/os_win.c index 33ca96c92c,88db683dbc..f91a6a5c2f --- a/src/os_win.c +++ b/src/os_win.c @@@ -1613,30 -1292,21 +1613,39 @@@ static int winFileControl(sqlite3_file return SQLITE_OK; } case SQLITE_FCNTL_SIZE_HINT: { - sqlite3_int64 sz = *(sqlite3_int64*)pArg; - SimulateIOErrorBenign(1); - winTruncate(id, sz); - SimulateIOErrorBenign(0); + if( pFile->szChunk>0 ){ + sqlite3_int64 oldSz; + int rc = winFileSize(id, &oldSz); + if( rc==SQLITE_OK ){ + sqlite3_int64 newSz = *(sqlite3_int64*)pArg; + if( newSz>oldSz ){ + SimulateIOErrorBenign(1); + rc = winTruncate(id, newSz); + SimulateIOErrorBenign(0); + } + } + return rc; + } + return SQLITE_OK; + } + case SQLITE_FCNTL_PERSIST_WAL: { + int bPersist = *(int*)pArg; + if( bPersist<0 ){ + *(int*)pArg = pFile->bPersistWal; + }else{ + pFile->bPersistWal = bPersist!=0; + } return SQLITE_OK; } + case SQLITE_FCNTL_PERSIST_WAL: { + int bPersist = *(int*)pArg; + if( bPersist<0 ){ + *(int*)pArg = pFile->bPersistWal; + }else{ + pFile->bPersistWal = bPersist!=0; + } + return SQLITE_OK; + } case SQLITE_FCNTL_SYNC_OMITTED: { return SQLITE_OK; } diff --cc src/sqlite.h.in index 952905b32d,6cba1ca76a..c6ec1e2285 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@@ -767,18 -751,21 +767,22 @@@ struct sqlite3_io_methods ** That integer is 0 to disable persistent WAL mode or 1 to enable persistent ** WAL mode. If the integer is -1, then it is overwritten with the current ** WAL persistence setting. - ** -** */ - #define SQLITE_FCNTL_LOCKSTATE 1 - #define SQLITE_GET_LOCKPROXYFILE 2 - #define SQLITE_SET_LOCKPROXYFILE 3 - #define SQLITE_LAST_ERRNO 4 - #define SQLITE_FCNTL_SIZE_HINT 5 - #define SQLITE_FCNTL_CHUNK_SIZE 6 - #define SQLITE_FCNTL_FILE_POINTER 7 - #define SQLITE_FCNTL_SYNC_OMITTED 8 - #define SQLITE_FCNTL_WIN32_AV_RETRY 9 - #define SQLITE_FCNTL_PERSIST_WAL 10 -#define SQLITE_FCNTL_LOCKSTATE 1 -#define SQLITE_FCNTL_GET_LOCKPROXYFILE 2 -#define SQLITE_FCNTL_SET_LOCKPROXYFILE 3 -#define SQLITE_FCNTL_LAST_ERRNO 4 -#define SQLITE_FCNTL_SIZE_HINT 5 -#define SQLITE_FCNTL_CHUNK_SIZE 6 -#define SQLITE_FCNTL_FILE_POINTER 7 -#define SQLITE_FCNTL_SYNC_OMITTED 8 -#define SQLITE_FCNTL_PERSIST_WAL 10 ++#define SQLITE_FCNTL_LOCKSTATE 1 ++#define SQLITE_FCNTL_GET_LOCKPROXYFILE 2 ++#define SQLITE_FCNTL_SET_LOCKPROXYFILE 3 ++#define SQLITE_FCNTL_LAST_ERRNO 4 ++#define SQLITE_FCNTL_SIZE_HINT 5 ++#define SQLITE_FCNTL_CHUNK_SIZE 6 ++#define SQLITE_FCNTL_FILE_POINTER 7 ++#define SQLITE_FCNTL_SYNC_OMITTED 8 ++#define SQLITE_FCNTL_WIN32_AV_RETRY 9 ++#define SQLITE_FCNTL_PERSIST_WAL 10 ++ + /* deprecated names */ + #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE + #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE + #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO /* ** CAPI3REF: Mutex Handle diff --cc src/test1.c index 0e8968d57a,d7b7a010da..a5a4a8a241 --- a/src/test1.c +++ b/src/test1.c @@@ -5205,7 -5210,7 +5209,6 @@@ static int path_is_local int objc, /* Number of arguments */ Tcl_Obj *CONST objv[] /* Command arguments */ ){ -- sqlite3 *db; const char *zPath; int nPath; @@@ -5247,7 -5252,7 +5250,6 @@@ static int path_is_dos int objc, /* Number of arguments */ Tcl_Obj *CONST objv[] /* Command arguments */ ){ -- sqlite3 *db; const char *zPath; int nPath; @@@ -6170,9 -6030,8 +6172,10 @@@ int Sqlitetest1_Init(Tcl_Interp *interp { "file_control_replace_test", file_control_replace_test, 0 }, #endif { "file_control_chunksize_test", file_control_chunksize_test, 0 }, - { "file_control_sizehint_test", file_control_sizehint_test, 0 }, + { "file_control_sizehint_test", file_control_sizehint_test, 0 }, + { "file_control_win32_av_retry", file_control_win32_av_retry, 0 }, + { "file_control_persist_wal", file_control_persist_wal, 0 }, + { "file_control_persist_wal", file_control_persist_wal, 0 }, { "sqlite3_vfs_list", vfs_list, 0 }, { "sqlite3_create_function_v2", test_create_function_v2, 0 }, { "path_is_local", path_is_local, 0 }, diff --cc src/vdbeaux.c index 1d5f713af6,cf0ec69e7f..561dd3ed82 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@@ -1509,8 -1507,9 +1511,10 @@@ void sqlite3VdbeMakeReady memset(zCsr, 0, zEnd-zCsr); zCsr += (zCsr - (u8*)0)&7; assert( EIGHT_BYTE_ALIGNMENT(zCsr) ); + p->expired = 0; + p->expired = 0; + /* Memory for registers, parameters, cursor, etc, is allocated in two ** passes. On the first pass, we try to reuse unused space at the ** end of the opcode array. If we are unable to satisfy all memory