diff options
-rw-r--r-- | manifest | 22 | ||||
-rw-r--r-- | manifest.uuid | 2 | ||||
-rw-r--r-- | src/main.c | 16 | ||||
-rw-r--r-- | src/sqlite.h.in | 24 | ||||
-rw-r--r-- | src/sqliteInt.h | 3 | ||||
-rw-r--r-- | src/test1.c | 26 | ||||
-rw-r--r-- | src/wal.c | 2 | ||||
-rw-r--r-- | test/walsetlk2.test | 82 |
8 files changed, 164 insertions, 13 deletions
@@ -1,5 +1,5 @@ -C Fix\sa\srace\scondition\scausing\sSQLite\sto\suse\sa\sbusy-handler\sfor\san\soperation\sthat\sshould\snot. -D 2025-01-24T15:49:47.933 +C Add\sthe\ssqlite3_setlk_timeout()\sAPI.\sFor\ssetting\sthe\stimeout\sused\sby\sSQLITE_ENABLE_SETLK_TIMEOUT\sblocking\slocks\swithout\salso\ssetting\sthe\sregular\sretry-based\sbusy-timeout. +D 2025-01-27T11:50:03.268 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md e108e1e69ae8e8a59e93c455654b8ac9356a11720d3345df2a4743e9590fb20d @@ -740,7 +740,7 @@ F src/insert.c f8d1a0f8ee258411009c6b7f2d93170e351bd19f5ad89d57e1180644297cbe70 F src/json.c 68a98c020c22127f2d65f08855f7fc7460ff352a6ce0b543d8931dde83319c22 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36 -F src/main.c a19dc8b47760ed95f3fbb255cfa8d3f7146b33c263eb4af05ab05e0115d161b9 +F src/main.c 101ea590be76fda296d12e6d8d1e9cc24f350b83cbf53e68b4f04484b90452a4 F src/malloc.c 410e570b30c26cc36e3372577df50f7a96ee3eed5b2b161c6b6b48773c650c5e F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c 3bb59158c38e05f6270e761a9f435bf19827a264c13d1631c58b84bdc96d73b2 @@ -779,16 +779,16 @@ F src/resolve.c c8a5372b97b2a2e972a280676f06ddb5b74e885d3b1f5ce383f839907b57ef68 F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97 F src/select.c 83e88fbb36f89b6703b348777491619554f0fd6f917c9fdf51e4c2e9cda6c04e F src/shell.c.in ee54de10e9bd5572f689a6bc0c8e6fa58a8870e1670978ded44412d2715fd908 -F src/sqlite.h.in 6afbcaae44140216704a6c82e4c4ea4118c46d5f6573d6c5fa4fc901ed9d369e +F src/sqlite.h.in ae301ce156765e2601695375dfc787a53b844a2f1c5d359bb667b081d1b7d2e0 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54 -F src/sqliteInt.h 3f20dfb5ae54e787b2643edc0b5bae0cecddfb89988e28afdc3c0b05892e25cc +F src/sqliteInt.h ff8e68e74a61b4bf676d1a9503be2e6c2bc92699ec358bb5e201b1a466f1aa8e F src/sqliteLimit.h 1bbdbf72bd0411d003267ffebc59a262f061df5653027a75627d03f48ca30523 F src/status.c cb11f8589a6912af2da3bb1ec509a94dd8ef27df4d4c1a97e0bcf2309ece972b F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 F src/tclsqlite.c 90441d3cc16f966a23499d9096a3d2d971e5e8fddb4d1413b096b79c2b2cff07 F src/tclsqlite.h 65e2c761446e1c9fa0342b7d2612a703483643c8b6a316d12a65b745a4727395 -F src/test1.c bed72f092f9aaebf50ee4919a02a26ab99a4f378ab334cb93d77e8adb82e4b77 +F src/test1.c 64df9d5ad54521eb3c103f1253bf33ceddbc5fa931658d3701027a2ac86eb5e9 F src/test2.c 7ebc518e6735939d8979273a6f7b1d9b5702babf059f6ad62499f7f60a9eb9a3 F src/test3.c e7573aa0f78ee4e070a4bc8c3493941c1aa64d5c66d4825c74c0f055451f432b F src/test4.c 13e57ae7ec7a959ee180970aef09deed141252fe9bb07c61054f0dfa4f1dfd5d @@ -858,7 +858,7 @@ F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf8 F src/vdbevtab.c fc46b9cbd759dc013f0b3724549cc0d71379183c667df3a5988f7e2f1bd485f3 F src/vtab.c 316cd48e9320660db3047cd306cd056e4361180cebb4d0f10a39244e10c11422 F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 -F src/wal.c 97c96c4eab27a409d2c710d8977a6b4917aebced14db2d63a451e9ca7b1f69bd +F src/wal.c 20550245b9a82f94736e905ee7df8f549e1301ba40e9f2cb51139e36d49c3c0f F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452 F src/walker.c d5006d6b005e4ea7302ad390957a8d41ed83faa177e412f89bc5600a7462a014 F src/where.c 9ad3dea8003a8913da6a4ca8322e2fe30773f46e88a0d4fbf9db13bdb999efa2 @@ -2022,7 +2022,7 @@ F test/walro2.test 33955a6fd874dd9724005e17f77fef89d334b3171454a1256fe4941a96766 F test/walrofault.test c70cb6e308c443867701856cce92ad8288cd99488fa52afab77cca6cfd51af68 F test/walseh1.test bae700eb99519b6d5cd3f893c04759accc5a59c391d4189fe4dd6995a533442b F test/walsetlk.test 9c5b92f9a20252540fedf9ffa6ee3d1b8af08ea4b80d0144d9b88e6c0c1de80d -F test/walsetlk2.test f32134c673e207e5af3c888448f925d1f92c250bb367f0e5a76e4bce9d56f0af +F test/walsetlk2.test e80cac17de166d5c8e4e0d243452798431aceb76a0abc95bfdd09d718d7c3f3f F test/walshared.test 42e3808582504878af237ea02c42ca793e8a0efaa19df7df26ac573370dbc7a3 F test/walslow.test 0c51843836c9dcf40a5ac05aa781bfb977b396ee2c872d92bd48b79d5dd9aa23 F test/walthread.test 14b20fcfa6ae152f5d8e12f5dc8a8a724b7ef189f5d8ef1e2ceab79f2af51747 @@ -2203,8 +2203,8 @@ F tool/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd7227350 F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7 F tool/warnings.sh 49a486c5069de041aedcbde4de178293e0463ae9918ecad7539eedf0ec77a139 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P daefcafe799ad7613cbdff1fb1e9d40659892906875b28fbc112abd7679e48ea -R a5b314ee32b527d33bb7a6211f7b128a +P 6ab9ed8eef77781898375038ab05fc6e5f46b745e4906691393b8b1d90570eb6 +R 7026d025d771964056775817385cabe6 U dan -Z 09f6f131877fb88e3c0a6b91e64a67d2 +Z d459230a6d531f1d8e43a532fde898d2 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 1506819b5..8adcd56dc 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6ab9ed8eef77781898375038ab05fc6e5f46b745e4906691393b8b1d90570eb6 +4a7eb492797abb47b18b7dfc557aeae43a0dea5b861efc203398d5059b10d131 diff --git a/src/main.c b/src/main.c index 1163deb6e..c8344b43c 100644 --- a/src/main.c +++ b/src/main.c @@ -1766,6 +1766,9 @@ int sqlite3_busy_handler( db->busyHandler.pBusyArg = pArg; db->busyHandler.nBusy = 0; db->busyTimeout = 0; +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT + db->setlkTimeout = 0; +#endif sqlite3_mutex_leave(db->mutex); return SQLITE_OK; } @@ -1815,12 +1818,25 @@ int sqlite3_busy_timeout(sqlite3 *db, int ms){ sqlite3_busy_handler(db, (int(*)(void*,int))sqliteDefaultBusyCallback, (void*)db); db->busyTimeout = ms; +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT + db->setlkTimeout = ms; +#endif }else{ sqlite3_busy_handler(db, 0, 0); } return SQLITE_OK; } +int sqlite3_setlk_timeout(sqlite3 *db, int ms){ +#ifdef SQLITE_ENABLE_API_ARMOR + if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; +#endif +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT + db->setlkTimeout = (ms>0 ? ms : 0); +#endif + return SQLITE_OK; +} + /* ** Cause any pending operation to stop at its earliest opportunity. */ diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 9a117fa54..c2a69bd2f 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -2900,6 +2900,30 @@ int sqlite3_busy_handler(sqlite3*,int(*)(void*,int),void*); int sqlite3_busy_timeout(sqlite3*, int ms); /* +** CAPI3REF: Set the Setlk Timeout +** METHOD: sqlite3 +** +** This routine is only useful in SQLITE_ENABLE_SETLK_TIMEOUT builds. If +** the VFS supports blocking locks, it sets the timeout in ms used by +** eligible locks taken on wal mode databases by the specified database +** handle. In non-SQLITE_ENABLE_SETLK_TIMEOUT builds, or if the VFS does +** not support blocking locks, this function is a no-op. +** +** Passing 0x7FFFFFFF to this function is interpreted by some VFS as "block +** indefinitely". Passing zero or less than zero disables blocking locks +** altogether. +** +** Internally, each SQLite database handle store two timeout values - the +** busy-timeout (used for rollback mode databases, or if the VFS does not +** support blocking locks) and the setlk-timeout (used for blocking locks +** on wal-mode databases). The sqlite3_busy_timeout() method sets both +** values, this function sets only the setlk-timeout value. Therefore, +** to configure separate busy-timeout and setlk-timeout values for a single +** database handle, call sqlite3_busy_timeout() followed by this function. +*/ +int sqlite3_setlk_timeout(sqlite3*, int ms); + +/* ** CAPI3REF: Convenience Routines For Running Queries ** METHOD: sqlite3 ** diff --git a/src/sqliteInt.h b/src/sqliteInt.h index b8c9136a5..aa12b8976 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1744,6 +1744,9 @@ struct sqlite3 { Savepoint *pSavepoint; /* List of active savepoints */ int nAnalysisLimit; /* Number of index rows to ANALYZE */ int busyTimeout; /* Busy handler timeout, in msec */ +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT + int setlkTimeout; /* Blocking lock timeout, in msec */ +#endif int nSavepoint; /* Number of non-transaction savepoints */ int nStatement; /* Number of nested statement-transactions */ i64 nDeferredCons; /* Net deferred constraints this transaction. */ diff --git a/src/test1.c b/src/test1.c index 6a8711677..fb7607f10 100644 --- a/src/test1.c +++ b/src/test1.c @@ -5940,6 +5940,31 @@ static int SQLITE_TCLAPI test_busy_timeout( } /* +** Usage: sqlite3_setlk_timeout DB MS +** +** Set the setlk timeout. +*/ +static int SQLITE_TCLAPI test_setlk_timeout( + void * clientData, + Tcl_Interp *interp, + int argc, + char **argv +){ + int rc, ms; + sqlite3 *db; + if( argc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " DB", 0); + return TCL_ERROR; + } + if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; + if( Tcl_GetInt(interp, argv[2], &ms) ) return TCL_ERROR; + rc = sqlite3_setlk_timeout(db, ms); + Tcl_AppendResult(interp, sqlite3ErrName(rc), 0); + return TCL_OK; +} + +/* ** Usage: tcl_variable_type VARIABLENAME ** ** Return the name of the internal representation for the @@ -8862,6 +8887,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ { "sqlite_delete_collation", (Tcl_CmdProc*)delete_collation }, { "sqlite3_get_autocommit", (Tcl_CmdProc*)get_autocommit }, { "sqlite3_busy_timeout", (Tcl_CmdProc*)test_busy_timeout }, + { "sqlite3_setlk_timeout", (Tcl_CmdProc*)test_setlk_timeout }, { "printf", (Tcl_CmdProc*)test_printf }, { "sqlite3IoTrace", (Tcl_CmdProc*)test_io_trace }, { "clang_sanitize_address", (Tcl_CmdProc*)clang_sanitize_address }, @@ -2027,7 +2027,7 @@ static int walEnableBlockingMs(Wal *pWal, int nMs){ static int walEnableBlocking(Wal *pWal){ int res = 0; if( pWal->db ){ - int tmout = pWal->db->busyTimeout; + int tmout = pWal->db->setlkTimeout; if( tmout ){ res = walEnableBlockingMs(pWal, tmout); } diff --git a/test/walsetlk2.test b/test/walsetlk2.test index 99366571d..3b8e60cd4 100644 --- a/test/walsetlk2.test +++ b/test/walsetlk2.test @@ -85,5 +85,87 @@ do_test 1.5.3 { db close tvfs delete +#------------------------------------------------------------------------- +# Check that if sqlite3_setlk_timeout() is used, blocking locks timeout +# but other operations do not use the retry mechanism. +# +reset_db + +do_execsql_test 2.0 { + CREATE TABLE t1(a, b); + INSERT INTO t1 VALUES(1, 2), (3, 4); +} + +sqlite3_setlk_timeout db 2000 + +# Launch a non-blocking testfixture process to write-lock the +# database for 2000 ms. +testfixture_nb done { + sqlite3 db test.db + db eval { + BEGIN EXCLUSIVE; + INSERT INTO t1 VALUES(5, 6); + } + after 2000 + db eval { + COMMIT + } +} + +after 500 {set ok 1} +vwait ok + +do_catchsql_test 2.1 { + INSERT INTO t1 VALUES(7, 8); +} {1 {database is locked}} + +sqlite3_busy_timeout db 2000 + +do_catchsql_test 2.2 { + INSERT INTO t1 VALUES(7, 8); +} {0 {}} + +do_execsql_test 2.3 { + SELECT * FROM t1 +} {1 2 3 4 5 6 7 8} + +do_execsql_test 2.4 { + PRAGMA journal_mode = wal; +} {wal} + +db close +sqlite3 db test.db + +do_execsql_test 2.5 { + INSERT INTO t1 VALUES(9, 10); +} + +sqlite3_setlk_timeout db 2000 + +# Launch a non-blocking testfixture process to write-lock the +# database for 2000 ms. +testfixture_nb done { + sqlite3 db test.db + db eval { + BEGIN EXCLUSIVE; + INSERT INTO t1 VALUES(11, 12); + } + after 2000 + db eval { + COMMIT + } +} + +after 500 {set ok 1} +vwait ok + +do_catchsql_test 2.6 { + INSERT INTO t1 VALUES(13, 14); +} {0 {}} + +do_execsql_test 2.7 { + SELECT * FROM t1 +} {1 2 3 4 5 6 7 8 9 10 11 12 13 14} + finish_test |