[tracker/wip/carlosg/libtracker-data-fixes: 1/3] libtracker-data: Handle SQLITE_LOCKED_SHAREDCACHE in the update thread




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]