diff options
| author | Jacob McDonnell <jacob@jacobmcdonnell.com> | 2026-04-25 19:55:15 -0400 |
|---|---|---|
| committer | Jacob McDonnell <jacob@jacobmcdonnell.com> | 2026-04-25 19:55:15 -0400 |
| commit | 253e67c8b3a72b3a4757fdbc5845297628db0a4a (patch) | |
| tree | adf53b66087aa30dfbf8bf391a1dadb044c3bf4d /static/netbsd/man3/sqlite3_unlock_notify.3 | |
| parent | a9157ce950dfe2fc30795d43b9d79b9d1bffc48b (diff) | |
docs: Added All NetBSD Manuals
Diffstat (limited to 'static/netbsd/man3/sqlite3_unlock_notify.3')
| -rw-r--r-- | static/netbsd/man3/sqlite3_unlock_notify.3 | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/static/netbsd/man3/sqlite3_unlock_notify.3 b/static/netbsd/man3/sqlite3_unlock_notify.3 new file mode 100644 index 00000000..ce43a6ef --- /dev/null +++ b/static/netbsd/man3/sqlite3_unlock_notify.3 @@ -0,0 +1,150 @@ +.Dd January 24, 2024 +.Dt SQLITE3_UNLOCK_NOTIFY 3 +.Os +.Sh NAME +.Nm sqlite3_unlock_notify +.Nd unlock notification +.Sh SYNOPSIS +.In sqlite3.h +.Ft int +.Fo sqlite3_unlock_notify +.Fa "sqlite3 *pBlocked" +.Fa "void (*xNotify)(void **apArg, int nArg)" +.Fa "void *pNotifyArg" +.Fc +.Sh DESCRIPTION +When running in shared-cache mode, a database operation may fail with +an SQLITE_LOCKED error if the required locks on the shared-cache +or individual tables within the shared-cache cannot be obtained. +See SQLite Shared-Cache Mode for a description +of shared-cache locking. +This API may be used to register a callback that SQLite will invoke +when the connection currently holding the required lock relinquishes +it. +This API is only available if the library was compiled with the SQLITE_ENABLE_UNLOCK_NOTIFY +C-preprocessor symbol defined. +.Pp +Shared-cache locks are released when a database connection concludes +its current transaction, either by committing it or rolling it back. +.Pp +When a connection (known as the blocked connection) fails to obtain +a shared-cache lock and SQLITE_LOCKED is returned to the caller, the +identity of the database connection (the blocking connection) that +has locked the required resource is stored internally. +After an application receives an SQLITE_LOCKED error, it may call the +sqlite3_unlock_notify() method with the blocked connection handle as +the first argument to register for a callback that will be invoked +when the blocking connections current transaction is concluded. +The callback is invoked from within the sqlite3_step or +sqlite3_close call that concludes the blocking connection's +transaction. +.Pp +If sqlite3_unlock_notify() is called in a multi-threaded application, +there is a chance that the blocking connection will have already concluded +its transaction by the time sqlite3_unlock_notify() is invoked. +If this happens, then the specified callback is invoked immediately, +from within the call to sqlite3_unlock_notify(). +.Pp +If the blocked connection is attempting to obtain a write-lock on a +shared-cache table, and more than one other connection currently holds +a read-lock on the same table, then SQLite arbitrarily selects one +of the other connections to use as the blocking connection. +.Pp +There may be at most one unlock-notify callback registered by a blocked +connection. +If sqlite3_unlock_notify() is called when the blocked connection already +has a registered unlock-notify callback, then the new callback replaces +the old. +If sqlite3_unlock_notify() is called with a NULL pointer as its second +argument, then any existing unlock-notify callback is canceled. +The blocked connections unlock-notify callback may also be canceled +by closing the blocked connection using +.Fn sqlite3_close . +The unlock-notify callback is not reentrant. +If an application invokes any sqlite3_xxx API functions from within +an unlock-notify callback, a crash or deadlock may be the result. +.Pp +Unless deadlock is detected (see below), sqlite3_unlock_notify() always +returns SQLITE_OK. +.Pp +\fBCallback Invocation Details\fP +.Pp +When an unlock-notify callback is registered, the application provides +a single void* pointer that is passed to the callback when it is invoked. +However, the signature of the callback function allows SQLite to pass +it an array of void* context pointers. +The first argument passed to an unlock-notify callback is a pointer +to an array of void* pointers, and the second is the number of entries +in the array. +.Pp +When a blocking connection's transaction is concluded, there may be +more than one blocked connection that has registered for an unlock-notify +callback. +If two or more such blocked connections have specified the same callback +function, then instead of invoking the callback function multiple times, +it is invoked once with the set of void* context pointers specified +by the blocked connections bundled together into an array. +This gives the application an opportunity to prioritize any actions +related to the set of unblocked database connections. +.Pp +\fBDeadlock Detection\fP +.Pp +Assuming that after registering for an unlock-notify callback a database +waits for the callback to be issued before taking any further action +(a reasonable assumption), then using this API may cause the application +to deadlock. +For example, if connection X is waiting for connection Y's transaction +to be concluded, and similarly connection Y is waiting on connection +X's transaction, then neither connection will proceed and the system +may remain deadlocked indefinitely. +.Pp +To avoid this scenario, the sqlite3_unlock_notify() performs deadlock +detection. +If a given call to sqlite3_unlock_notify() would put the system in +a deadlocked state, then SQLITE_LOCKED is returned and no unlock-notify +callback is registered. +The system is said to be in a deadlocked state if connection A has +registered for an unlock-notify callback on the conclusion of connection +B's transaction, and connection B has itself registered for an unlock-notify +callback when connection A's transaction is concluded. +Indirect deadlock is also detected, so the system is also considered +to be deadlocked if connection B has registered for an unlock-notify +callback on the conclusion of connection C's transaction, where connection +C is waiting on connection A. +Any number of levels of indirection are allowed. +.Pp +\fBThe "DROP TABLE" Exception\fP +.Pp +When a call to +.Fn sqlite3_step +returns SQLITE_LOCKED, it is almost always appropriate to call sqlite3_unlock_notify(). +There is however, one exception. +When executing a "DROP TABLE" or "DROP INDEX" statement, SQLite checks +if there are any currently executing SELECT statements that belong +to the same connection. +If there are, SQLITE_LOCKED is returned. +In this case there is no "blocking connection", so invoking sqlite3_unlock_notify() +results in the unlock-notify callback being invoked immediately. +If the application then re-attempts the "DROP TABLE" or "DROP INDEX" +query, an infinite loop might be the result. +.Pp +One way around this problem is to check the extended error code returned +by an sqlite3_step() call. +If there is a blocking connection, then the extended error code is +set to SQLITE_LOCKED_SHAREDCACHE. +Otherwise, in the special "DROP TABLE/INDEX" case, the extended error +code is just SQLITE_LOCKED. +.Sh IMPLEMENTATION NOTES +These declarations were extracted from the +interface documentation at line 9316. +.Bd -literal +SQLITE_API int sqlite3_unlock_notify( + sqlite3 *pBlocked, /* Waiting connection */ + void (*xNotify)(void **apArg, int nArg), /* Callback function to invoke */ + void *pNotifyArg /* Argument to pass to xNotify */ +); +.Ed +.Sh SEE ALSO +.Xr sqlite3_close 3 , +.Xr sqlite3_step 3 , +.Xr SQLITE_OK 3 |
