aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordan <Dan Kennedy>2025-01-27 11:50:03 +0000
committerdan <Dan Kennedy>2025-01-27 11:50:03 +0000
commit43aad25b1b535f1c8c44ae964bf53e40eb351378 (patch)
treeec100dbfb1530d4108ff295db8a9d503a1808c5d /src
parent2539fb2bc57adebef779a13c18f788e14461f7c8 (diff)
downloadsqlite-43aad25b1b535f1c8c44ae964bf53e40eb351378.tar.gz
sqlite-43aad25b1b535f1c8c44ae964bf53e40eb351378.zip
Add the sqlite3_setlk_timeout() API. For setting the timeout used by SQLITE_ENABLE_SETLK_TIMEOUT blocking locks without also setting the regular retry-based busy-timeout.
FossilOrigin-Name: 4a7eb492797abb47b18b7dfc557aeae43a0dea5b861efc203398d5059b10d131
Diffstat (limited to 'src')
-rw-r--r--src/main.c16
-rw-r--r--src/sqlite.h.in24
-rw-r--r--src/sqliteInt.h3
-rw-r--r--src/test1.c26
-rw-r--r--src/wal.c2
5 files changed, 70 insertions, 1 deletions
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 },
diff --git a/src/wal.c b/src/wal.c
index 707acfca5..5d6c0c62c 100644
--- a/src/wal.c
+++ b/src/wal.c
@@ -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);
}