[tracker/wip/carlosg/libtracker-data-fixes: 1/3] libtracker-data: Handle SQLITE_LOCKED_SHAREDCACHE in the update thread
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [tracker/wip/carlosg/libtracker-data-fixes: 1/3] libtracker-data: Handle SQLITE_LOCKED_SHAREDCACHE in the update thread
- Date: Thu, 23 Dec 2021 23:09:36 +0000 (UTC)
commit 1176fcb37be28287b05eebfc4aaadd83b1641620
Author: Carlos Garnacho <carlosg gnome org>
Date: Wed Dec 22 23:30:49 2021 +0100
libtracker-data: Handle SQLITE_LOCKED_SHAREDCACHE in the update thread
Handling this while executing update statements turns out necessary in the
case of in-memory databases, as it seems the (single) writing thread can
get this SQLITE_LOCKED extended error if there are already existing read
locks. This can be seen (or not, it's quite racy) running
"tracker-miner-fs-3 --dry-run" so it uses an in-memory database.
If this condition happens, we simply retry until we get something else
than SQLITE_LOCKED (i.e. all readers finished). Handling of
this error condition could get fancier (e.g. via sqlite3_unlock_notify()),
but this is already enough to avoid the ill effects.
In order to ensure that this only applies to in-memory connections, check
that we specifically get SQLITE_LOCKED_SHAREDCACHE, since we only use shared
caches for in-memory databases. Getting SQLITE_LOCKED in any other
circumstance is still unexpected and is an error situation, most notably
WAL databases in disk are not affected by this situation.
src/libtracker-data/tracker-db-interface-sqlite.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
---
diff --git a/src/libtracker-data/tracker-db-interface-sqlite.c
b/src/libtracker-data/tracker-db-interface-sqlite.c
index b73d10b3a..13a7861a7 100644
--- a/src/libtracker-data/tracker-db-interface-sqlite.c
+++ b/src/libtracker-data/tracker-db-interface-sqlite.c
@@ -2894,7 +2894,8 @@ execute_stmt (TrackerDBInterface *interface,
#endif
while (result == SQLITE_OK ||
- result == SQLITE_ROW) {
+ result == SQLITE_ROW ||
+ result == SQLITE_LOCKED) {
if (g_cancellable_is_cancelled (cancellable)) {
result = SQLITE_INTERRUPT;
@@ -2913,6 +2914,15 @@ execute_stmt (TrackerDBInterface *interface,
break;
case SQLITE_ROW:
break;
+ case SQLITE_LOCKED:
+ /* In-memory databases use a shared cache where readers
+ * can temporarily block the writer thread, keep stepping
+ * in this case until the database is no longer blocked.
+ */
+ if (sqlite3_extended_errcode (interface->db) == SQLITE_LOCKED_SHAREDCACHE)
+ continue;
+ else
+ break;
default:
break;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]