-C Merge\sall\sthe\slatest\strunk\schanges\sinto\sthe\sapple-osx\sbranch.
-D 2012-03-31T02:46:20.444
+C Merge\sin\slatest\schanges,\sautologging\soptions,\sread\sonly\sfile\ssystem\swal\ssupport,\stest\sconfig\sconditionalization,\sWAL\sframe\swrite\sprebuffering
+D 2012-04-02T23:35:45.151
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 7bd2fa7753fc9de38994b8d4fa7f10deb19966a5
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F src/legacy.c 015826a958f690302d27e096a68d50b3657e4201
F src/lempar.c 0ee69fca0be54cd93939df98d2aca4ca46f44416
F src/loadext.c f20382fbaeec832438a1ba7797bee3d3c8a6d51d
-F src/main.c d61d7eacf656b19b353e2cab34daf4eba4ba8c8f
+F src/main.c 2ba24071c42849fde838c32f1b508712c51dd758
F src/malloc.c 15afac5e59b6584efe072e9933aefb4230e74f97
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c b3677415e69603d6a0e7c5410a1b3731d55beda1
F src/os.h 59beba555b65a450bd1d804220532971d4299f60
F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04
F src/os_os2.c 4a75888ba3dfc820ad5e8177025972d74d7f2440
-F src/os_unix.c c008584c899e9c6b702078fbb9cb59839a0a66d3
+F src/os_unix.c 5e6ead4f8f4236f0ed016ca4518300985daddf7e
F src/os_win.c 12e76b4aa5426022939f92e894a5c20dd40be7f4
F src/pager.c ce4fde5951bf71b4f5316ff5afd0219ff7e99b3f
F src/pager.h ef1eaf8593e78f73885c1dfac27ad83bee23bdc5
F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697
F src/select.c 36d5ed5c4504fd37c024141ce2b699148b231a8d
F src/shell.c abf18d6ee54f2631860a98fdd7ab1327f470db67
-F src/sqlite.h.in 5538b920986b8c1f8385b97b7ae31b74a39a9ca5
-F src/sqlite3_private.h e3b586e0aa329075d99be7198df9bc80c5b19e2d
+F src/sqlite.h.in 8714ac9f594717d667fb0c1149f97332bebce8e0
+F src/sqlite3_private.h 77bebe843a3eabfb7994990aab780d34d25819c7
F src/sqlite3ext.h 6904f4aadf976f95241311fbffb00823075d9477
F src/sqliteInt.h efee04f7c9e000b77d89f87baf77397b4025246c
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
F src/status.c 35939e7e03abf1b7577ce311f48f682c40de3208
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
F src/tclsqlite.c 086dfdd72e5892de223968a258e1ccbd9693e717
-F src/test1.c fa09748bbcd6c3efa076e45648857e922ce97224
+F src/test1.c a23a59fb8aaa49f94fe5d214907618264f05b923
F src/test2.c 711555927f1f7e8db9aab86b512bc6934a774abe
F src/test3.c f82399ec50d9cd7378bf9d6db6c1409d5e77b042
F src/test4.c d1e5a5e904d4b444cf572391fdcb017638e36ff7
F src/vdbesort.c b25814d385895544ebc8118245c8311ded7f81c9
F src/vdbetrace.c 2405f68d14c49d2e0a798d71e35d62b8569bfb65
F src/vtab.c ab90fb600a3f5e4b7c48d22a4cdb2d6b23239847
-F src/wal.c 8a89f4f60097c88e3b5c3baeb5f4942035411a29
+F src/wal.c c13ee6f76871d33a2c33be3959d2281a77233a53
F src/wal.h a8ade3069ab75e3c79e9ca067a5ac7e1dbaf93a6
F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
F src/where.c 2112422a404dcca5d47f6630bdf180bccd36c62b
-F test/8_3_names.test 631ea964a3edb091cf73c3b540f6bcfdb36ce823
+F test/8_3_names.test 0ed0f6711fefac33829ef9f1d6ca3c56c48ef1c7
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
F test/all.test 52fc8dee494092031a556911d404ca30a749a30b
F test/attach.test 63033baa59be42c811ef0d4e73ebd2d6dba4805c
F test/attach2.test e54436ed956d3d88bdee61221da59bf3935a0966
F test/attach3.test d89ccfe4fe6e2b5e368d480fcdfe4b496c54cf4e
-F test/attach4.test 53bf502f17647c6d6c5add46dda6bac8b6f4665c
+F test/attach4.test faaaf33fa51f986b414520cb03cecdc7999df108
F test/attachmalloc.test 3a4bfca9545bfe906a8d2e622de10fbac5b711b0
F test/auth.test 304e82f31592820d3bde26ab6b75deaa123e1a6f
F test/auth2.test 270baddc8b9c273682760cffba6739d907bd2882
F test/busy.test 76b4887f8b9160ba903c1ac22e8ff406ad6ae2f0
F test/cache.test f64136b0893c293d0b910ed057b3b711249099a7
F test/capi2.test 835d4cee9f542ea50fa8d01f3fe6de80b0627360
-F test/capi3.test 9c8b58b6a6aeb14e69bd8c8c7721b47d640464d1
+F test/capi3.test 468b750927dd6b8ed487232bb8ea93ce03edd605
F test/capi3b.test efb2b9cfd127efa84433cd7a2d72ce0454ae0dc4
-F test/capi3c.test 1b5424d2ac57b7b443b5de5b9a287642c02279b6
+F test/capi3c.test 7f45970fb0ae10d04cb957030fef725758a48898
F test/capi3d.test 17b57ca28be3e37e14c2ba8f787d292d84b724a1
F test/capi3e.test f7408dda65c92b9056199fdc180f893015f83dde
F test/cast.test 4c275cbdc8202d6f9c54a3596701719868ac7dc3
F test/incrblob_err.test d2562d2771ebffd4b3af89ef64c140dd44371597
F test/incrblobfault.test 917c0292224c64a56ef7215fd633a3a82f805be0
F test/incrvacuum.test d2a6ddf5e429720b5fe502766af747915ccf6c32
-F test/incrvacuum2.test c776f80c2b20d4088f9ff3fd0177ff76af9f51b7
+F test/incrvacuum2.test a1828b6165af6c248c4eb80aeaee2bcbb45768c1
F test/incrvacuum_ioerr.test 22f208d01c528403240e05beecc41dc98ed01637
F test/index.test b5429732b3b983fa810e3ac867d7ca85dae35097
F test/index2.test ee83c6b5e3173a3d7137140d945d9a5d4fdfb9d6
F test/null.test a8b09b8ed87852742343b33441a9240022108993
F test/openv2.test 0d3040974bf402e19b7df4b783e447289d7ab394
F test/oserror.test 50417780d0e0d7cd23cf12a8277bb44024765df3
-F test/pager1.test 34fb695debe94ba64d9b949cc6da11dbcc786e3d
+F test/pager1.test 4fbf634d26661578af38db830bd3442287aed91d
F test/pager2.test 745b911dde3d1f24ae0870bd433dfa83d7c658c1
F test/pager3.test 3856d9c80839be0668efee1b74811b1b7f7fc95f
F test/pagerfault.test a15ef77c8495882d7debb43794e87b6e46174c8a
F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b
F test/sqllimits1.test b1aae27cc98eceb845e7f7adf918561256e31298
-F test/stat.test 08e8185b3fd5b010c90d7ad82b9dd4ea1cbf14b0
+F test/stat.test 4ce96d67f6a0bc9647a042c7140cf1c56e049a69
F test/stmt.test 78a6764439cfa5abdcbf98d4d084739e81eeec4f
F test/subquery.test b524f57c9574b2c0347045b4510ef795d4686796
F test/subquery2.test edcad5c118f0531c2e21bf16a09bbb105252d4cd
F test/subselect.test d24fd8757daf97dafd2e889c73ea4c4272dcf4e4
F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a
-F test/superlock.test d69dcf1cd52c52c38dbb2df432233e1ecb62fd09
+F test/superlock.test 2b27b4ae7c6b9d534b0412e0d99f989aa1f3b9cf
F test/sync.test a34cd43e98b7fb84eabbf38f7ed8f7349b3f3d85
F test/syscall.test bea9bf329bff733c791310244617c2a76974e64a
F test/sysfault.test c79441d88d23696fbec7b147dba98d42a04f523f
F test/threadtest3.c 0ed13e09690f6204d7455fac3b0e8ece490f6eef
F test/tkt-02a8e81d44.test 6c80d9c7514e2a42d4918bf87bf6bc54f379110c
F test/tkt-26ff0c2d1e.test 888324e751512972c6e0d1a09df740d8f5aaf660
-F test/tkt-2d1a5c67d.test b028a811049eb472cb2d3a43fc8ce4f6894eebda
+F test/tkt-2d1a5c67d.test 0e23cbbbecda6ce453ffb560fdac28489d491d36
F test/tkt-2ea2425d34.test 1cf13e6f75d149b3209a0cb32927a82d3d79fb28
F test/tkt-31338dca7e.test 1f714c14b6682c5db715e0bda347926a3456f7a9
-F test/tkt-313723c356.test c47f8a9330523e6f35698bf4489bcb29609b53ac
+F test/tkt-313723c356.test 54a1558d2719e171bd88967d66c73be4c617ec55
F test/tkt-38cb5df375.test f3cc8671f1eb604d4ae9cf886ed4366bec656678
F test/tkt-3998683a16.test 6d1d04d551ed1704eb3396ca87bb9ccc8c5c1eb7
F test/tkt-3a77c9714e.test 32bb28afa8c63fc76e972e996193139b63551ed9
F test/tkt-3fe897352e.test 10de1a67bd5c66b238a4c96abe55531b37bb4f00
F test/tkt-4a03edc4c8.test 2865e4edbc075b954daa82f8da7cc973033ec76e
F test/tkt-54844eea3f.test a12b851128f46a695e4e378cca67409b9b8f5894
-F test/tkt-5d863f876e.test 884072c2de496ddbb90c387c9ebc0d4f44a91b8e
+F test/tkt-5d863f876e.test b4b58f9e14ddd29f6e7577aad16b2d43b1237429
F test/tkt-5e10420e8d.test 904d1687b3c06d43e5b3555bbcf6802e7c0ffd84
F test/tkt-5ee23731f.test 9db6e1d7209dc0794948b260d6f82b2b1de83a9f
F test/tkt-752e1646fc.test ea78d88d14fe9866bdd991c634483334639e13bf
F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8
F test/vtab_shared.test 82f463886e18d7f8395a4b6167c91815efe54839
F test/wal.test 9c29891ca329de5bba41dfa26b855ca82950e01c
-F test/wal2.test 8871e7fd2c86711ff415a5817d68ea3101a15312
-F test/wal3.test 6504bbf348b2d6dfade64a064f1050fd617e8706
+F test/wal2.test ea811f7bc9abbc4282700c8969b175c31e884045
+F test/wal3.test ae86a92d41d81730278fca0b71368f3e78e9c64a
F test/wal4.test 5755887f321baa4c55de0b91066fa7d0cafcac9d
-F test/wal5.test f58ed4b8b542f71c7441da12fbd769d99b362437
+F test/wal5.test 46a422956ec203bc5899dad5e70d9e655b1c91e4
F test/wal6.test c561d1e44c89f9cb458a7b03003ed4baac08ba07
-F test/wal7.test 2ae8f427d240099cc4b2dfef63cff44e2a68a1bd
-F test/wal8.test 5ab217d21f7e5e86af2933a4ffd0d8357cc2c0bd
+F test/wal7.test 18cf68ab8010ae0a2baaa48e5b59567a9503e63e
+F test/wal8.test a0b7dee73fc3d3bbf167e04533d37df379a0b7d1
F test/wal_common.tcl 15f152fd55703975878741beca6cfa4209d5b3b3
-F test/walbak.test b30cbbb2996947c96a2e562020dff61013a17a96
-F test/walbig.test 65699b66911a681e194eec280d45c6ee715e48b4
-F test/walcksum.test 3dff8817d31a4207d1ad31e7da06073a34e7fe1c
-F test/walcrash.test 5f749f38e4a5ee1f862c88a73286b35cf05031a0
+F test/walbak.test 8edea4daad739587f049633071d0f063fa808049
+F test/walbig.test 3ca3d94751b80054eed5bda20a1339ae1f619483
+F test/walcksum.test 6510e82303f6fffc2c55bb77a7774cd0eed21a6e
+F test/walcrash.test a8fa8d8a9a50a49b7abaf8a4a7e2c7ea352c49be
F test/walcrash2.test c032d0040374ae28b41f99fc0cc290b4e2e34f17
-F test/walcrash3.test 595e44c6197f0d0aa509fc135be2fd0209d11a2c
-F test/walfault.test a16ad4987e6ff433e9dc760fec91f95c174c8e51
-F test/walhook.test c934ac5219fee2b4e7653d291db9107b8dc73bba
+F test/walcrash3.test 97e775404f4c76e5c46f71fbd09691c7e9c25c68
+F test/walfault.test e5309befcaf4ab08151c35dba20cc5b8a5846748
+F test/walhook.test 9716f865303130d7fcda61bcabb863090be9cca2
F test/walmode.test 9308ffc25555a1c4eaa44a863792240406637496
-F test/walnoshm.test 84ca10c544632a756467336b7c3b864d493ee496
-F test/walpersist.test 8c6b7e3ec1ba91b5e4dc4e0921d6d3f87cd356a6
-F test/walro.test e6bb27762c9f22601cbb8bff6e0acfd124e74b63
-F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417
-F test/walslow.test 3c2475d7672511380d33cef1924a065d2ad62ff0
-F test/walthread.test 3decc7e72594e0270dc1a1cc0984d6db7165b4cc
+F test/walnoshm.test b1337ce99aabdf4da7a4a3f0c5ce1f05450bc3cc
+F test/walpersist.test 12d1a54a5d5e06af0ec4bbd5421608a957ed8630
+F test/walro.test 04d6382b2a87cfc82b87336eb8d8a8e9afd8bcf8
+F test/walshared.test 04590b10c677f75318701818c50bc0dda5da64ab
+F test/walslow.test 658066419a92d3bd85be71a11ce477af4ffe9153
+F test/walthread.test c3aaf9ef7ad21ae79c2345425bfddb39cdac954f
F test/where.test de337a3fe0a459ec7c93db16a519657a90552330
F test/where2.test 43d4becaf5a5df854e6c21d624a1cb84c6904554
F test/where3.test 667e75642102c97a00bf9b23d3cb267db321d006
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
-P f999197b75465a1f71ac1dab8f22ba2167fc0c67 f9a7e179cbbeeab5e57bbf392bef89750215546b
-R 82541a9eaf4a147ff8f864155ac5fc2d
-U drh
-Z ccad7cece0bf00c1026435d33943b52d
+P 18ec60cacd37a70d598ac1af5e50faffa73bb134
+R 73390db6e66a079b7d6e56cc27ecf8d0
+U adam
+Z d6996fec7b0aa226442af546de346566
-18ec60cacd37a70d598ac1af5e50faffa73bb134
\ No newline at end of file
+d51c086e5c006821e2ab932f229649a729d914b2
\ No newline at end of file
return oldLimit; /* IMP: R-53341-35419 */
}
#if defined(SQLITE_ENABLE_AUTO_PROFILE)
+/* stderr logging */
void _sqlite_auto_profile(void *aux, const char *sql, u64 ns);
void _sqlite_auto_trace(void *aux, const char *sql);
void _sqlite_auto_profile(void *aux, const char *sql, u64 ns) {
void _sqlite_auto_trace(void *aux, const char *sql) {
fprintf(stderr, "TraceSQL(%p): %s\n", aux, sql);
}
+
+/* syslog logging */
+#include <asl.h>
+static aslclient autolog_client = NULL;
+static void _close_asl_log() {
+ if( NULL!=autolog_client ){
+ asl_close(autolog_client);
+ autolog_client = NULL;
+ }
+}
+static void _open_asl_log() {
+ if( NULL==autolog_client ){
+ autolog_client = asl_open("SQLite", NULL, 0);
+ atexit(_close_asl_log);
+ }
+}
+
+void _sqlite_auto_profile_syslog(void *aux, const char *sql, u64 ns);
+void _sqlite_auto_trace_syslog(void *aux, const char *sql);
+void _sqlite_auto_profile_syslog(void *aux, const char *sql, u64 ns) {
+#pragma unused(aux)
+ asl_log(autolog_client, NULL, ASL_LEVEL_NOTICE, "Query: %s\n Execution Time: %llu ms\n", sql, ns / 1000000);
+}
+void _sqlite_auto_trace_syslog(void *aux, const char *sql) {
+ asl_log(autolog_client, NULL, ASL_LEVEL_NOTICE, "TraceSQL(%p): %s\n", aux, sql);
+}
#endif
/*
return rc;
}
+#if defined(SQLITE_ENABLE_AUTO_PROFILE)
+#define SQLITE_AUTOLOGGING_STDERR 1
+#define SQLITE_AUTOLOGGING_SYSLOG 2
+static void enableAutoLogging(
+ sqlite3 *db
+){
+ char *envprofile = getenv("SQLITE_AUTO_PROFILE");
+
+ if( envprofile!=NULL ){
+ int where = 0;
+ if( !strncasecmp("1", envprofile, 1) ){
+ if( isatty(STDERR_FILENO) ){
+ where = SQLITE_AUTOLOGGING_STDERR;
+ }else{
+ where = SQLITE_AUTOLOGGING_SYSLOG;
+ }
+ } else if( !strncasecmp("stderr", envprofile, 6) ){
+ where = SQLITE_AUTOLOGGING_STDERR;
+ } else if( !strncasecmp("syslog", envprofile, 6) ){
+ where = SQLITE_AUTOLOGGING_SYSLOG;
+ }
+ if( where==SQLITE_AUTOLOGGING_STDERR ){
+ sqlite3_profile(db, _sqlite_auto_profile, db);
+ }else if( where==SQLITE_AUTOLOGGING_SYSLOG ){
+ _open_asl_log();
+ sqlite3_profile(db, _sqlite_auto_profile_syslog, db);
+ }
+ }
+ char *envtrace = getenv("SQLITE_AUTO_TRACE");
+ if( envtrace!=NULL ){
+ int where = 0;
+ if( !strncasecmp("1", envtrace, 1) ){
+ if( isatty(STDERR_FILENO) ){
+ where = SQLITE_AUTOLOGGING_STDERR;
+ }else{
+ where = SQLITE_AUTOLOGGING_SYSLOG;
+ }
+ } else if( !strncasecmp("stderr", envtrace, 6) ){
+ where = SQLITE_AUTOLOGGING_STDERR;
+ } else if( !strncasecmp("syslog", envtrace, 6) ){
+ where = SQLITE_AUTOLOGGING_SYSLOG;
+ }
+ if( where==SQLITE_AUTOLOGGING_STDERR ){
+ sqlite3_trace(db, _sqlite_auto_trace, db);
+ }else if( where==SQLITE_AUTOLOGGING_SYSLOG ){
+ _open_asl_log();
+ sqlite3_trace(db, _sqlite_auto_trace_syslog, db);
+ }
+ }
+}
+#endif
/*
** This routine does the work of opening a database on behalf of
}else if( rc!=SQLITE_OK ){
db->magic = SQLITE_MAGIC_SICK;
}
-#if defined(SQLITE_ENABLE_AUTO_PROFILE)
+#if defined(__APPLE__) && ENABLE_FORCE_WAL
if( db && !rc ){
- char *envprofile = getenv("SQLITE_AUTO_PROFILE");
- char *envtrace = getenv("SQLITE_AUTO_TRACE");
-
- if( envprofile!=NULL ){
- sqlite3_profile(db, _sqlite_auto_profile, db);
- }
- if( envtrace!=NULL ){
- sqlite3_trace(db, _sqlite_auto_trace, db);
+ if ((0 == access("/var/db/enableForceWAL", R_OK))) {
+#ifdef SQLITE_DEBUG
+ fprintf(stderr, "SQLite WAL journal_mode ENABLED by default.\n");
+#endif
+
+ sqlite3_exec(db, "pragma journal_mode=wal", NULL, NULL, NULL);
+#ifdef SQLITE_DEBUG
+// } else {
+// fprintf(stderr, "SQLite WAL journal_mode NOT ENABLED by default.\n");
+#endif
}
}
+#endif
+#if defined(SQLITE_ENABLE_AUTO_PROFILE)
+ if( db && !rc ){
+ enableAutoLogging(db);
+ }
#endif
*ppDb = db;
#ifdef SQLITE_ENABLE_SQLRR
int state = lockstate.state;
return state;
}
+ if( NULL!=db ){
+ sqlite3_close(db); /* need to close even if open returns an error */
+ }
return SQLITE_LOCKSTATE_ERROR;
}
lock.l_len = divSize;
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;
}
** Close the file.
*/
static int nolockClose(sqlite3_file *id) {
- return closeUnixFile(id);
+ int rc = SQLITE_OK;
+ unixFile *pFile = (unixFile *)id;
+ unixEnterMutex();
+
+ /* unixFile.pInode is always valid here. Otherwise, a different close
+ ** routine (e.g. nolockClose()) would be called instead.
+ */
+ assert( pFile->pInode->nLock>0 || pFile->pInode->bProcessLock==0 );
+ if( ALWAYS(pFile->pInode) && pFile->pInode->nLock ){
+ /* If there are outstanding locks, do not actually close the file just
+ ** yet because that would clear those locks. Instead, add the file
+ ** descriptor to pInode->pUnused list. It will be automatically closed
+ ** when the last lock is cleared.
+ */
+ setPendingFd(pFile);
+ }
+ releaseInodeInfo(pFile);
+ rc = closeUnixFile(id);
+ unixLeaveMutex();
+ return rc;
}
/******************* End of the no-op lock implementation *********************
return SQLITE_OK;
}
+
#if (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__)
#include "sqlite3_private.h"
#include <copyfile.h>
static int isProxyLockingMode(unixFile *);
#if (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__)
-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);
-
+static int unixTruncateDatabase(unixFile *, int);
- if( isCorrupt ){
- sqlite3demo_superunlock_corrupt(id, corruptFileLock);
- }else{
- sqlite3demo_superunlock(pLock);
- }
- return rc;
-}
-
-static int unixInvalidateSupportFiles(unixFile *pFile, int skipWAL) {
- char jPath[MAXPATHLEN+9];
- int zLen = strlcpy(jPath, pFile->zPath, MAXPATHLEN+9);
- if( zLen<MAXPATHLEN ){
- size_t jLen;
- const char extensions[3][9] = { "-wal", "-journal", "-shm" };
- int j = (skipWAL ? 1 : 0);
- for( ; j<3; j++ ){
-
- /* Check to see if the shm file is already opened for this pFile */
- if( j==2 ){
- unixEnterMutex(); /* Because pFile->pInode 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 unixInvalidateSupportFiles(unixFile *, int);
static int unixReplaceDatabase(unixFile *pFile, sqlite3 *srcdb) {
sqlite3_file *id = (sqlite3_file *)pFile;
return 0;
}
-/*
-** This test only works for lock testing on unix/posix VFS.
-** Adapted from tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
-*/
-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;
-}
+static int unixLockstatePid(unixFile *, pid_t, int *);
#endif /* (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__) */
*(int*)pArg = pFile->eFileLock;
return SQLITE_OK;
}
- case SQLITE_LAST_ERRNO: {
+ case SQLITE_FCNTL_LAST_ERRNO: {
*(int*)pArg = pFile->lastErrno;
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__) */
assert( pShmNode->nRef>0 );
pShmNode->nRef--;
if( pShmNode->nRef==0 ){
- if( deleteFlag && pShmNode->h>=0 ) osUnlink(pShmNode->zFilename);
+ if( deleteFlag && pShmNode->h>=0 ) {
+ if (deleteFlag == 1) {
+ unlink(pShmNode->zFilename);
+ } else if (deleteFlag == 2) {
+ //ftruncate(pShmNode->h, 32 * 1024);
+ }
+ }
+
unixShmPurge(pDbFd);
}
unixLeaveMutex();
# define unixShmUnmap 0
#endif /* #ifndef SQLITE_OMIT_WAL */
+#if (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__)
+static const char *unixTempFileDir(void);
+
+static int unixInvalidateSupportFiles(unixFile *pFile, int skipWAL) {
+ char jPath[MAXPATHLEN+9];
+ int zLen = strlcpy(jPath, pFile->zPath, MAXPATHLEN+9);
+ if( zLen<MAXPATHLEN ){
+ size_t jLen;
+ const char extensions[3][9] = { "-wal", "-journal", "-shm" };
+ int j = (skipWAL ? 1 : 0);
+ for( ; j<3; j++ ){
+
+ /* Check to see if the shm file is already opened for this pFile */
+ if( j==2 ){
+ unixEnterMutex(); /* Because pFile->pInode 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 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;
+ }
+ }
+ if( bFlags!=0 ){
+ /* initialize a new database in TMPDIR and copy the contents over */
+ const char *tDir = unixTempFileDir();
+ int tLen = sizeof(char) * (strlen(tDir) + 11);
+ char *tDbPath = (char *)malloc(tLen);
+ int tFd = -1;
+
+ strlcpy(tDbPath, tDir, tLen);
+ strlcat(tDbPath, "tmpdbXXXXX", tLen);
+ tFd = mkstemp(tDbPath);
+ if( tFd==-1 ){
+ pFile->lastErrno=errno;
+ rc = SQLITE_IOERR;
+ }else{
+ sqlite3 *tDb = NULL;
+ copyfile_state_t s;
+ int trc = sqlite3_open_v2(tDbPath, &tDb, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_AUTOPROXY, NULL);
+ char *errmsg = NULL;
+ const char *sql = "";
+ if( !trc && (bFlags&SQLITE_TRUNCATE_PAGESIZE_MASK) ){
+ const char pagesize_sql[4][22] = { "pragma page_size=1024", "pragma page_size=2048", "pragma page_size=4096", "pragma page_size=8192" };
+ int iPagesize = (((bFlags&SQLITE_TRUNCATE_PAGESIZE_MASK) >> 4) - 1);
+ assert( iPagesize>=0 && iPagesize<=4 );
+ sql = pagesize_sql[iPagesize];
+ trc = sqlite3_exec(tDb, sql, 0, 0, &errmsg);
+ }
+ if( !trc ){
+ const char autovacuum_sql[3][21] = { "pragma auto_vacuum=0", "pragma auto_vacuum=1", "pragma auto_vacuum=2" };
+ int iAutovacuum = 2; /* default to incremental */
+ if( (bFlags&SQLITE_TRUNCATE_AUTOVACUUM_MASK) ){
+ iAutovacuum = (((bFlags&SQLITE_TRUNCATE_AUTOVACUUM_MASK) >> 2) - 1);
+ }
+ assert( iAutovacuum>=0 && iAutovacuum<=2 );
+ sql = autovacuum_sql[iAutovacuum];
+ trc = sqlite3_exec(tDb, sql, 0, 0, &errmsg);
+ }
+ if( !trc && (bFlags&SQLITE_TRUNCATE_JOURNALMODE_WAL) ){
+ sql = "pragma journal_mode=wal";
+ trc = sqlite3_exec(tDb, sql, 0, 0, &errmsg);
+ }
+ if( trc ){
+ if( !tDb ){
+ fprintf(stderr, "failed to open temp database '%s' to reset truncated database %s with flags %x: %d\n", tDbPath, pFile->zPath, bFlags, trc);
+ }else{
+ fprintf(stderr, "failed to set '%s' on truncated database %s, %d: %s\n", sql, pFile->zPath, trc, errmsg);
+ }
+ }
+ if( tDb ){
+ sqlite3_close(tDb);
+ }
+ s = copyfile_state_alloc();
+ lseek(tFd, 0, SEEK_SET);
+ lseek(pFile->h, 0, SEEK_SET);
+ if( fcopyfile(tFd, 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);
+ fsync(pFile->h);
+ close(tFd);
+ unlink(tDbPath);
+ }
+ free(tDbPath);
+ } else {
+ 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;
+}
+
+/*
+ ** Lock locations for shared-memory locks used by WAL mode.
+ */
+#ifndef SHM_BASE
+# define SHM_BASE 120
+# define SHM_WRITE SHM_BASE
+# define SHM_CHECKPOINT (SHM_BASE+1)
+# define SHM_RECOVER (SHM_BASE+2)
+# define SHM_READ_FIRST (SHM_BASE+3)
+# define SHM_READ_SIZE 5
+#endif /* SHM_BASE */
+
+/*
+** This test only works for lock testing on unix/posix VFS.
+** Adapted from tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
+*/
+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__) */
+
+
+
/*
** Here ends the implementation of all sqlite3_file methods.
**
IOMETHODS(
nolockIoFinder, /* Finder function name */
nolockIoMethods, /* sqlite3_io_methods object name */
- 1, /* shared memory is disabled */
+ 2, /* shared memory is enabled */
nolockClose, /* xClose method */
nolockLock, /* xLock method */
nolockUnlock, /* xUnlock method */
#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
|| pLockingStyle == &nfsIoMethods
#endif
+ /* support WAL mode on read only mounted filesystem */
+ || pLockingStyle == &nolockIoMethods
){
unixEnterMutex();
rc = findInodeInfo(pNew, &pNew->pInode);
if( envforce!=NULL ){
useProxy = atoi(envforce)>0;
}else{
- if( statfs(zPath, &fsInfo) == -1 ){
- /* In theory, the close(fd) call is sub-optimal. If the file opened
- ** with fd is a database file, and there are other connections open
- ** on that file that are currently holding advisory locks on it,
- ** then the call to close() will cancel those locks. In practice,
- ** we're assuming that statfs() doesn't fail very often. At least
- ** not while other file descriptors opened by the same process on
- ** the same file are working. */
- p->lastErrno = errno;
- robust_close(p, fd, __LINE__);
- rc = SQLITE_IOERR_ACCESS;
- goto open_finished;
- }
useProxy = !(fsInfo.f_flags&MNT_LOCAL);
}
if( useProxy ){
** </ul>
*/
#define SQLITE_FCNTL_LOCKSTATE 1
-#define SQLITE_GET_LOCKPROXYFILE 2
-#define SQLITE_SET_LOCKPROXYFILE 3
-#define SQLITE_LAST_ERRNO 4
+#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_VFSNAME 12
#define SQLITE_FCNTL_POWERSAFE_OVERWRITE 13
#define SQLITE_FCNTL_PRAGMA 14
+/* 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
/*
** Pass the SQLITE_TRUNCATE_DATABASE operation code to sqlite3_file_control()
-** to truncate a database and its associated journal file to zero length.
+** to truncate a database and its associated journal file to zero length. The
+** SQLITE_TRUNCATE_* flags represent optional flags to safely initialize an
+** empty database in the place of the truncated database, the flags are passed
+** into sqlite3_file_control via the fourth argument using a pointer to an integer
+** configured with the ORed flags. If the fourth argument is NULL, the default
+** behavior is applied and the database file is truncated to zero bytes, a rollback
+** journal (if present) is unlinked, a WAL journal (if present) is truncated to zero
+** bytes and the first few bytes of the -shm file is scrambled to trigger existing
+** connections to rebuild the index from the database file contents.
*/
#define SQLITE_FCNTL_TRUNCATE_DATABASE 101
#define SQLITE_TRUNCATE_DATABASE SQLITE_FCNTL_TRUNCATE_DATABASE
+#define SQLITE_TRUNCATE_JOURNALMODE_WAL (0x1<<0)
+#define SQLITE_TRUNCATE_AUTOVACUUM_MASK (0x3<<2)
+#define SQLITE_TRUNCATE_AUTOVACUUM_OFF (0x1<<2)
+#define SQLITE_TRUNCATE_AUTOVACUUM_FULL (0x2<<2)
+#define SQLITE_TRUNCATE_AUTOVACUUM_INCREMENTAL (0x3<<2)
+#define SQLITE_TRUNCATE_PAGESIZE_MASK (0x7<<4)
+#define SQLITE_TRUNCATE_PAGESIZE_1024 (0x1<<4)
+#define SQLITE_TRUNCATE_PAGESIZE_2048 (0x2<<4)
+#define SQLITE_TRUNCATE_PAGESIZE_4096 (0x3<<4)
+#define SQLITE_TRUNCATE_PAGESIZE_8192 (0x4<<4)
/*
** Pass the SQLITE_REPLACE_DATABASE operation code to sqlite3_file_control()
/* From sqlite3_priavet.h */
# ifndef SQLITE_TRUNCATE_DATABASE
# define SQLITE_TRUNCATE_DATABASE 101
+# define SQLITE_TRUNCATE_JOURNALMODE_WAL (0x1<<0)
+# define SQLITE_TRUNCATE_AUTOVACUUM_MASK (0x3<<2)
+# define SQLITE_TRUNCATE_AUTOVACUUM_OFF (0x1<<2)
+# define SQLITE_TRUNCATE_AUTOVACUUM_FULL (0x2<<2)
+# define SQLITE_TRUNCATE_AUTOVACUUM_INCREMENTAL (0x3<<2)
+# define SQLITE_TRUNCATE_PAGESIZE_MASK (0x7<<4)
+# define SQLITE_TRUNCATE_PAGESIZE_1024 (0x1<<4)
+# define SQLITE_TRUNCATE_PAGESIZE_2048 (0x2<<4)
+# define SQLITE_TRUNCATE_PAGESIZE_4096 (0x3<<4)
+# define SQLITE_TRUNCATE_PAGESIZE_8192 (0x4<<4)
# endif
# ifndef SQLITE_REPLACE_DATABASE
# define SQLITE_REPLACE_DATABASE 102
sqlite3_int64 iSyncPoint; /* Fsync at this offset */
int syncFlags; /* Flags for the fsync */
int szPage; /* Size of one page */
+#if defined(SQLITE_WRITE_WALFRAME_PREBUFFERED)
+ void *aFrameBuf; /* Frame buffer */
+ size_t szFrameBuf; /* Size of frame buffer */
+#endif
} WalWriter;
/*
){
int rc; /* Result code from subfunctions */
void *pData; /* Data actually written */
+#if defined(SQLITE_WRITE_WALFRAME_PREBUFFERED)
+ void *aFrame;
+
+ assert(sizeof(p->aFrameBuf) == (p->szPage + WAL_FRAME_HDRSIZE));
+ aFrame = p->aFrameBuf;
+#else
u8 aFrame[WAL_FRAME_HDRSIZE]; /* Buffer to assemble frame-header in */
+#endif
+
#if defined(SQLITE_HAS_CODEC)
if( (pData = sqlite3PagerCodec(pPage))==0 ) return SQLITE_NOMEM;
#else
pData = pPage->pData;
#endif
+
walEncodeFrame(p->pWal, pPage->pgno, nTruncate, pData, aFrame);
+
+#if defined(SQLITE_WRITE_WALFRAME_PREBUFFERED)
+ memcpy(&aFrame[WAL_FRAME_HDRSIZE], pData, p->szPage);
+ rc = walWriteToLog(p, aFrame, (p->szPage + WAL_FRAME_HDRSIZE), iOffset);
+#else
rc = walWriteToLog(p, aFrame, sizeof(aFrame), iOffset);
if( rc ) return rc;
/* Write the page data */
rc = walWriteToLog(p, pData, p->szPage, iOffset+sizeof(aFrame));
+#endif
return rc;
}
w.szPage = szPage;
iOffset = walFrameOffset(iFrame+1, szPage);
szFrame = szPage + WAL_FRAME_HDRSIZE;
+#if defined(SQLITE_WRITE_WALFRAME_PREBUFFERED)
+ w.aFrameBuf = (void *)malloc(szFrame);
+ if( NULL==w.aFrameBuf ){
+ return SQLITE_NOMEM;
+ }
+#endif
+
/* Write all frames into the log file exactly once */
for(p=pList; p; p=p->pDirty){
}
}
+#if defined(SQLITE_WRITE_WALFRAME_PREBUFFERED)
+ free(w.aFrameBuf);
+#endif
/* If this frame set completes the first transaction in the WAL and
** if PRAGMA journal_size_limit is set, then truncate the WAL to the
** journal size limit, if possible.
finish_test
return
}
+if ![wal_is_ok] { finish_test; return }
+
db close
forcedelete test.db
do_test 8_3_names-5.0 {
set mode wal
}
ifcapable !wal { set mode delete }
+ if ![wal_is_ok] { set mode delete }
lappend L $mode
append S "
PRAGMA $name.journal_mode = WAL;
do_test capi3-11.10 {
sqlite3_step $STMT
} {SQLITE_ERROR}
-do_test capi3-11.11 {
- sqlite3_step $STMT
-} {SQLITE_ROW}
-do_test capi3-11.12 {
- sqlite3_step $STMT
- sqlite3_step $STMT
-} {SQLITE_DONE}
-do_test capi3-11.13 {
- sqlite3_finalize $STMT
-} {SQLITE_OK}
+ifcapable {autoreset} {
+ do_test capi3-11.11 {
+ sqlite3_step $STMT
+ } {SQLITE_ROW}
+ do_test capi3-11.12 {
+ sqlite3_step $STMT
+ sqlite3_step $STMT
+ } {SQLITE_DONE}
+ do_test capi3-11.13 {
+ sqlite3_finalize $STMT
+ } {SQLITE_OK}
+}
do_test capi3-11.14 {
execsql {
SELECT a FROM t2;
do_test capi3c-11.10 {
sqlite3_step $STMT
} {SQLITE_ABORT}
-do_test capi3c-11.11 {
- sqlite3_step $STMT
-} {SQLITE_ROW}
-do_test capi3c-11.12 {
- sqlite3_step $STMT
- sqlite3_step $STMT
-} {SQLITE_DONE}
-do_test capi3c-11.13 {
- sqlite3_finalize $STMT
-} {SQLITE_OK}
+ifcapable {autoreset} {
+ do_test capi3c-11.11 {
+ sqlite3_step $STMT
+ } {SQLITE_ROW}
+ do_test capi3c-11.12 {
+ sqlite3_step $STMT
+ sqlite3_step $STMT
+ } {SQLITE_DONE}
+ do_test capi3c-11.13 {
+ sqlite3_finalize $STMT
+ } {SQLITE_OK}
+}
do_test capi3c-11.14 {
execsql {
SELECT a FROM t2;
integrity_check incrvacuum2-3.3
+if ![wal_is_ok] { finish_test; return }
+
ifcapable wal {
# At one point, when a specific page was being extracted from the b-tree
# free-list (e.g. during an incremental-vacuum), all trunk pages that
# $ws: The expected size of the WAL file, in bytes, after executing
# the SQL script. Or -1 if the WAL is not expected to exist.
#
-ifcapable wal {
+if {$::sqlite_options(wal) && [wal_is_ok]} {
faultsim_delete_and_reopen
foreach {tn sql res js ws} [subst {
}
} {}
-ifcapable wal {
+if {$::sqlite_options(wal) && [wal_is_ok]} {
do_test pager1-20.3.1 {
faultsim_delete_and_reopen
db func a_string a_string
# pager1-21.1.*: The VFS has an iVersion less than 2, or
# pager1-21.2.*: The VFS does not provide xShmXXX() methods.
#
-ifcapable wal {
+if {$::sqlite_options(wal) && [wal_is_ok]} {
do_test pager1-21.0 {
faultsim_delete_and_reopen
execsql {
# the same database.
#
catch { db close }
-ifcapable wal {
+if {$::sqlite_options(wal) && [wal_is_ok]} {
do_multiclient_test tn {
do_test pager1-28.$tn.1 {
sql1 {
SELECT * FROM stat;
} {}
-ifcapable wal {
+if {$::sqlite_options(wal) && [wal_is_ok]} {
do_execsql_test stat-0.1 {
PRAGMA journal_mode = WAL;
PRAGMA journal_mode = delete;
#
#
+if {[forced_proxy_locking]} {
+ finish_test
+ return
+}
+
do_execsql_test 1.1 {
CREATE TABLE t1(a, b);
INSERT INTO t1 VALUES(1, 2);
set testprefix tkt-2d1a5c67d
ifcapable {!wal || !vtab} {finish_test; return}
+if {![wal_is_ok]} {finish_test; return}
for {set ii 1} {$ii<=10} {incr ii} {
do_test tkt-2d1a5c67d.1.$ii {
source $testdir/malloc_common.tcl
ifcapable !wal { finish_test ; return }
+if ![wal_is_ok] { finish_test; return }
do_execsql_test tkt-313723c356.1 {
PRAGMA page_size = 1024;
source $testdir/tester.tcl
source $testdir/lock_common.tcl
+ifcapable !wal { finish_test; return }
+if ![wal_is_ok] { finish_test; return }
+
+
do_multiclient_test tn {
do_test $tn.1 {
sql1 {
set testprefix wal2
ifcapable !wal {finish_test ; return }
+if ![wal_is_ok] {finish_test ; return }
set sqlite_sync_count 0
proc cond_incr_sync_count {adj} {
set_tvfs_hdr $file $ints
}
+set shmpath test.db-shm
+if {[forced_proxy_locking]} {
+ sqlite3 db test.db
+ set shmpath [execsql { pragma lock_proxy_file }]-shm
+ db close
+}
+
#-------------------------------------------------------------------------
# Test case wal2-1.*:
INSERT INTO t1 VALUES(1, 2);
INSERT INTO t1 VALUES(3, 4);
}
+ if {[forced_proxy_locking]} {
+ forcecopy $shmpath sv_test.db-shm
+ }
faultsim_save_and_close
} {}
do_test wal2-10.1.2 {
# file itself. Test this.
#
if {$::tcl_platform(platform) == "unix"} {
+ if {[forced_proxy_locking]} {
+ # faultsim_delete_and_reopen doesn't know about the shm file redirect...
+ forcedelete $shmpath
+ }
+
faultsim_delete_and_reopen
# Changed on 2012-02-13: umask is deliberately ignored for -wal files.
#set umask [exec /bin/sh -c umask]
PRAGMA journal_mode = WAL;
}
db close
- list [file exists test.db-wal] [file exists test.db-shm]
+ list [file exists test.db-wal] [file exists $shmpath]
} {0 0}
foreach {tn permissions} {
file attributes test.db -permissions
} $permissions
do_test wal2-12.2.$tn.2 {
- list [file exists test.db-wal] [file exists test.db-shm]
+ list [file exists test.db-wal] [file exists $shmpath]
} {0 0}
do_test wal2-12.2.$tn.3 {
sqlite3 db test.db
execsql { INSERT INTO tx DEFAULT VALUES }
- list [file exists test.db-wal] [file exists test.db-shm]
+ list [file exists test.db-wal] [file exists $shmpath]
} {1 1}
do_test wal2-12.2.$tn.4 {
- list [file attr test.db-wal -perm] [file attr test.db-shm -perm]
+ list [file attr test.db-wal -perm] [file attr $shmpath -perm]
} [list $effective $effective]
do_test wal2-12.2.$tn.5 {
db close
- list [file exists test.db-wal] [file exists test.db-shm]
+ list [file exists test.db-wal] [file exists $shmpath]
} {0 0}
}
}
if {$::tcl_platform(platform) == "unix"} {
proc perm {} {
set L [list]
- foreach f {test.db test.db-wal test.db-shm} {
+ foreach f {test.db test.db-wal $shmpath} {
if {[file exists $f]} {
lappend L [file attr $f -perm]
} else {
set L
}
+ if {[forced_proxy_locking]} {
+ # faultsim_delete_and_reopen doesn't know about the shm file redirect...
+ forcedelete $shmpath
+ }
faultsim_delete_and_reopen
execsql {
PRAGMA journal_mode = WAL;
INSERT INTO t1 VALUES('3.14', '2.72');
}
do_test wal2-13.1.1 {
- list [file exists test.db-shm] [file exists test.db-wal]
+ list [file exists $shmpath] [file exists test.db-wal]
} {1 1}
+ if {[forced_proxy_locking]} {
+ forcecopy $shmpath proxysv_test.db-shm
+ }
faultsim_save_and_close
foreach {tn db_perm wal_perm shm_perm can_open can_read can_write} {
9 00000 00644 00644 0 0 0
} {
faultsim_restore
+ if {[forced_proxy_locking]} {
+ forcecopy proxysv_test.db-shm $shmpath
+ }
do_test wal2-13.$tn.1 {
file attr test.db -perm $db_perm
file attr test.db-wal -perm $wal_perm
- file attr test.db-shm -perm $shm_perm
+ file attr $shmpath -perm $shm_perm
set L [file attr test.db -perm]
lappend L [file attr test.db-wal -perm]
- lappend L [file attr test.db-shm -perm]
+ lappend L [file attr $shmpath -perm]
} [list $db_perm $wal_perm $shm_perm]
# If $can_open is true, then it should be possible to open a database
#-------------------------------------------------------------------------
# Test that "PRAGMA checkpoint_fullsync" appears to be working.
#
-foreach {tn sql reslist} {
- 1 { } {10 0 4 0 6 0}
- 2 { PRAGMA checkpoint_fullfsync = 1 } {10 4 4 2 6 2}
- 3 { PRAGMA checkpoint_fullfsync = 0 } {10 0 4 0 6 0}
+foreach {tn sql reslist altreslist} {
+ 1 { } {10 0 4 0 6 0} {7 4 3 2 3 2}
+ 2 { PRAGMA checkpoint_fullfsync = 1 } {10 4 4 2 6 2} {7 4 3 2 3 2}
+ 3 { PRAGMA checkpoint_fullfsync = 0 } {10 0 4 0 6 0} {7 0 3 0 3 0}
} {
faultsim_delete_and_reopen
set sqlite_sync_count 0
set sqlite_fullsync_count 0
+ set useres $reslist
+ if $::sqlite_options(default_wal_safetylevel) {
+ set useres $altreslist
+ }
+
do_execsql_test wal2-14.$tn.2 {
PRAGMA wal_autocheckpoint = 10;
CREATE TABLE t1(a, b); -- 2 wal syncs
do_test wal2-14.$tn.3 {
cond_incr_sync_count 1
list $sqlite_sync_count $sqlite_fullsync_count
- } [lrange $reslist 0 1]
+ } [lrange $useres 0 1]
set sqlite_sync_count 0
set sqlite_fullsync_count 0
do_test wal2-14.$tn.4 {
execsql { INSERT INTO t1 VALUES(7, zeroblob(12*4096)) }
list $sqlite_sync_count $sqlite_fullsync_count
- } [lrange $reslist 2 3]
+ } [lrange $useres 2 3]
set sqlite_sync_count 0
set sqlite_fullsync_count 0
execsql { INSERT INTO t1 VALUES(13, 14) }
db close
list $sqlite_sync_count $sqlite_fullsync_count
- } [lrange $reslist 4 5]
+ } [lrange $useres 4 5]
}
catch { db close }
source $testdir/wal_common.tcl
source $testdir/malloc_common.tcl
ifcapable !wal {finish_test ; return }
+if ![wal_is_ok] {finish_test ; return }
set a_string_counter 1
proc a_string {n} {
# in WAL mode the xSync method is invoked as expected for each of
# synchronous=off, synchronous=normal and synchronous=full.
#
-foreach {tn syncmode synccount} {
+foreach {tn syncmode synccount altsynccount} {
1 off
{}
+ {}
2 normal
{test.db-wal normal test.db normal}
+ {test.db-wal full test.db full}
3 full
{test.db-wal normal test.db-wal normal test.db-wal normal test.db normal}
+ {test.db-wal normal test.db-wal normal test.db-wal full test.db full}
} {
proc sync_counter {args} {
foreach {method filename id flags} $args break
lappend ::syncs [file tail $filename] $flags
}
+ set usecount $synccount
+ if $::sqlite_options(default_wal_safetylevel) {
+ set usecount $altsynccount
+ }
+
do_test wal3-3.$tn {
forcedelete test.db test.db-wal test.db-journal
}
T filter {}
set ::syncs
- } $synccount
+ } $usecount
db close
T delete
source $testdir/lock_common.tcl
source $testdir/wal_common.tcl
ifcapable !wal {finish_test ; return }
+if ![wal_is_ok] { finish_test; return }
set testprefix wal5
set testdir [file dirname $argv0]
source $testdir/tester.tcl
ifcapable !wal {finish_test ; return }
+if ![wal_is_ok] { finish_test; return }
# Case 1: No size limit. Journal can get large.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set ::testprefix wal8
+ifcapable !wal {finish_test ; return }
+if ![wal_is_ok] { finish_test; return }
db close
forcedelete test.db test.db-wal
do_not_use_codec
ifcapable !wal {finish_test ; return }
-if { ![wal_is_ok] } {
- finish_test
- return
-}
+if { ![wal_is_ok] } { finish_test ; return }
# Test organization:
finish_test
return
}
+if ![wal_is_ok] { finish_test; return }
# Do not use a codec for this file, as the database is manipulated using
# external methods (the [fake_big_file] and [hexio_write] commands).
source $testdir/wal_common.tcl
ifcapable !wal {finish_test ; return }
-if { ![wal_is_ok] } {
- finish_test
- return
-}
+if ![wal_is_ok] { finish_test; return }
# Read and return the contents of file $filename. Treat the content as
# binary data.
set testdir [file dirname $argv0]
source $testdir/tester.tcl
ifcapable !wal {finish_test ; return }
-if { ![wal_is_ok] } {
- finish_test
- return
-}
+if ![wal_is_ok] { finish_test; return }
db close
source $testdir/tester.tcl
ifcapable !wal {finish_test ; return }
+if ![wal_is_ok] { finish_test; return }
+
set testprefix walcrash3
db close
source $testdir/lock_common.tcl
ifcapable !wal {finish_test ; return }
-if { ![wal_is_ok] } {
- finish_test
- return
-}
+if ![wal_is_ok] { finish_test; return }
#-------------------------------------------------------------------------
# This test case, walfault-1-*, simulates faults while executing a
source $testdir/wal_common.tcl
ifcapable !wal {finish_test ; return }
-if { ![wal_is_ok] } {
- finish_test
- return
-}
+if ![wal_is_ok] { finish_test; return }
set ::wal_hook [list]
proc wal_hook {zDb nEntry} {
source $testdir/tester.tcl
set testprefix walnoshm
ifcapable !wal {finish_test ; return }
+if ![wal_is_ok] { finish_test; return }
db close
testvfs tvfsshm
finish_test
return
}
+if ![wal_is_ok] { finish_test; return }
+
+set shmpath test.db-shm
+if {[forced_proxy_locking]} {
+ set shmpath [execsql { pragma lock_proxy_file }]-shm
+}
do_test walpersist-1.0 {
db eval {
file exists test.db-wal
} {1}
do_test walpersist-1.1 {
- file exists test.db-shm
+ file exists $shmpath
} {1}
do_test walpersist-1.2 {
db close
- list [file exists test.db] [file exists test.db-wal] [file exists test.db-shm]
+ list [file exists test.db] [file exists test.db-wal] [file exists $shmpath]
} {1 0 0}
do_test walpersist-1.3 {
sqlite3 db test.db
db eval {SELECT length(a) FROM t1}
} {5000}
do_test walpersist-1.4 {
- list [file exists test.db] [file exists test.db-wal] [file exists test.db-shm]
+ list [file exists test.db] [file exists test.db-wal] [file exists $shmpath]
} {1 1 1}
do_test walpersist-1.5 {
file_control_persist_wal db -1
} {0 1}
do_test walpersist-1.11 {
db close
- list [file exists test.db] [file exists test.db-wal] [file exists test.db-shm]
+ list [file exists test.db] [file exists test.db-wal] [file exists $shmpath]
} {1 1 1}
# Make sure the journal_size_limit works to limit the size of the
# journal_size_limit causes the WAL file to be truncated to zero bytes
# when closing.
#
-forcedelete test.db test.db-shm test.db-wal
+forcedelete test.db $shmpath test.db-wal
do_test walpersist-2.1 {
sqlite3 db test.db
db eval {
do_test 3.1 {
catch {db close}
- forcedelete test.db test.db-shm test.db-wal
+ forcedelete test.db $shmpath test.db-wal
sqlite3 db test.db
execsql {
PRAGMA page_size = 1024;
finish_test
return
}
+if ![wal_is_ok] { finish_test; return }
+
+set shmpath test.db-shm
+if {[forced_proxy_locking]} {
+ sqlite3 db test.db
+ set shmpath [execsql { pragma lock_proxy_file }]-shm
+ db close
+}
do_multiclient_test tn {
# Do not run tests with the connections in the same process.
CREATE TABLE t1(x, y);
INSERT INTO t1 VALUES('a', 'b');
}
- file exists test.db-shm
+ file exists $shmpath
} {1}
do_test 1.1.2 {
- file attributes test.db-shm -permissions r--r--r--
+ file attributes $shmpath -permissions r--r--r--
code1 { sqlite3 db file:test.db?readonly_shm=1 }
} {}
do_test 1.2.1 {
code2 { db2 close }
code1 { db close }
- list [file exists test.db-wal] [file exists test.db-shm]
+ list [file exists test.db-wal] [file exists $shmpath]
} {1 1}
do_test 1.2.2 {
code1 { sqlite3 db file:test.db?readonly_shm=1 }
do_test 1.2.3 {
code1 { db close }
- file attributes test.db-shm -permissions rw-r--r--
- hexio_write test.db-shm 0 01020304
- file attributes test.db-shm -permissions r--r--r--
+ file attributes $shmpath -permissions rw-r--r--
+ hexio_write $shmpath 0 01020304
+ file attributes $shmpath -permissions r--r--r--
code1 { sqlite3 db file:test.db?readonly_shm=1 }
csql1 { SELECT * FROM t1 }
} {1 {attempt to write a readonly database}}
} {SQLITE_READONLY_RECOVERY}
do_test 1.2.5 {
- file attributes test.db-shm -permissions rw-r--r--
+ file attributes $shmpath -permissions rw-r--r--
code2 { sqlite3 db2 test.db }
sql2 "SELECT * FROM t1"
} {a b c d e f g h i j}
- file attributes test.db-shm -permissions r--r--r--
+ file attributes $shmpath -permissions r--r--r--
do_test 1.2.6 { sql1 "SELECT * FROM t1" } {a b c d e f g h i j}
do_test 1.2.7 {
do_test 1.3.2.1 {
code1 { db close }
code2 { db2 close }
- file exists test.db-shm
+ file exists $shmpath
} {0}
do_test 1.3.2.2 {
code1 { sqlite3 db file:test.db?readonly_shm=1 }
} {1 {unable to open database file}}
do_test 1.3.2.3 {
code1 { db close }
- close [open test.db-shm w]
- file attributes test.db-shm -permissions r--r--r--
+ close [open $shmpath w]
+ file attributes $shmpath -permissions r--r--r--
code1 { sqlite3 db file:test.db?readonly_shm=1 }
csql1 { SELECT * FROM t1 }
} {1 {attempt to write a readonly database}}
} {SQLITE_READONLY_RECOVERY}
}
+forcedelete $shmpath
+
finish_test
source $testdir/tester.tcl
ifcapable !wal {finish_test ; return }
+if ![wal_is_ok] { finish_test; return }
db close
set ::enable_shared_cache [sqlite3_enable_shared_cache 1]
source $testdir/tester.tcl
ifcapable !wal {finish_test ; return }
-if { ![wal_is_ok] } {
- finish_test
- return
-}
+if ![wal_is_ok] { finish_test; return }
proc reopen_db {} {
catch { db close }
source $testdir/lock_common.tcl
if {[run_thread_tests]==0} { finish_test ; return }
ifcapable !wal { finish_test ; return }
-if { ![wal_is_ok] } {
- finish_test
- return
-}
+if ![wal_is_ok] { finish_test; return }
set sqlite_walsummary_mmap_incr 64