[tracker/wip/carlosg/resource-leak-fix: 38/38] libtracker-data: Perform trimming of unused resource URNs on shutdown



commit 57ed3ddc74099b9c75cd83d4f531c4d6782a549b
Author: Carlos Garnacho <carlosg gnome org>
Date:   Wed Jul 5 11:05:33 2017 +0200

    libtracker-data: Perform trimming of unused resource URNs on shutdown
    
    On shutdown it will now delete all elements in the Resource table that
    are not contained too in the Graph table (thus are graph URNs) and have
    a refcounting of 0 (meaning that they are not used in any class/property
    table).
    
    As the migration to refcounted Resource table doesn't result in graph
    URNs being added to the Graph table, database cleanup won't be performed
    until the Graph table has been populated (presumably by miners indexing
    anything)

 src/libtracker-data/tracker-data-manager.c |   82 +++++++++++++++++++++++++++-
 1 files changed, 81 insertions(+), 1 deletions(-)
---
diff --git a/src/libtracker-data/tracker-data-manager.c b/src/libtracker-data/tracker-data-manager.c
index f957fd7..4aa7df7 100644
--- a/src/libtracker-data/tracker-data-manager.c
+++ b/src/libtracker-data/tracker-data-manager.c
@@ -4744,12 +4744,92 @@ skip_ontology_check:
        return TRUE;
 }
 
+static gboolean
+data_manager_check_perform_cleanup (TrackerDataManager *manager)
+{
+       TrackerDBStatement *stmt;
+       TrackerDBInterface *iface;
+       TrackerDBCursor *cursor;
+       guint count = 0;
+
+       iface = tracker_db_manager_get_writable_db_interface (manager->db_manager);
+       stmt = tracker_db_interface_create_statement (iface, TRACKER_DB_STATEMENT_CACHE_TYPE_NONE,
+                                                     NULL, "SELECT COUNT(*) FROM Graph");
+       if (stmt) {
+               cursor = tracker_db_statement_start_cursor (stmt, NULL);
+               g_object_unref (stmt);
+       }
+
+       if (cursor && tracker_db_cursor_iter_next (cursor, NULL, NULL))
+               count = tracker_db_cursor_get_int (cursor, 0);
+
+       g_clear_object (&cursor);
+
+       /* We need to be sure the data is coherent, so we'll refrain from
+        * doing any clean ups till there are elements in the Graph table.
+        *
+        * A database that's been freshly updated to the refcounted
+        * resources will have an empty Graph table, so we might
+        * unintentionally delete graph URNs if we clean up in this state.
+        */
+       if (count == 0)
+               return FALSE;
+
+       count = 0;
+       stmt = tracker_db_interface_create_statement (iface, TRACKER_DB_STATEMENT_CACHE_TYPE_NONE, NULL,
+                                                     "SELECT COUNT(*) FROM Resource WHERE Refcount <= 0 "
+                                                     "AND Resource.ID NOT IN (SELECT ID FROM Graph)");
+       if (stmt) {
+               cursor = tracker_db_statement_start_cursor (stmt, NULL);
+               g_object_unref (stmt);
+       }
+
+       if (cursor && tracker_db_cursor_iter_next (cursor, NULL, NULL))
+               count = tracker_db_cursor_get_int (cursor, 0);
+
+       g_clear_object (&cursor);
+
+       return count > 0;
+}
+
 void
 tracker_data_manager_dispose (GObject *object)
 {
        TrackerDataManager *manager = TRACKER_DATA_MANAGER (object);
+       TrackerDBStatement *stmt;
+       TrackerDBInterface *iface;
+       GError *error = NULL;
+       gboolean readonly = TRUE;
+
+       if (manager->db_manager) {
+               readonly = (tracker_db_manager_get_flags (manager->db_manager, NULL, NULL) & 
TRACKER_DB_MANAGER_READONLY) != 0;
+
+               if (!readonly && data_manager_check_perform_cleanup (manager)) {
+                       /* Delete stale URIs in the Resource table */
+                       g_debug ("Cleaning up stale resource URIs");
+
+                       iface = tracker_db_manager_get_writable_db_interface (manager->db_manager);
+                       stmt = tracker_db_interface_create_statement (iface, 
TRACKER_DB_STATEMENT_CACHE_TYPE_UPDATE,
+                                                                     &error,
+                                                                     "DELETE FROM Resource WHERE Refcount <= 
0 "
+                                                                     "AND Resource.ID NOT IN (SELECT ID FROM 
Graph)");
 
-       g_clear_pointer (&manager->db_manager, tracker_db_manager_free);
+                       if (stmt) {
+                               tracker_db_statement_execute (stmt, &error);
+                               g_object_unref (stmt);
+                       }
+
+                       if (error) {
+                               g_warning ("Could not clean up stale resource URIs: %s\n",
+                                          error->message);
+                               g_clear_error (&error);
+                       }
+
+                       tracker_db_interface_execute_query (iface, NULL, "VACUUM");
+               }
+
+               g_clear_pointer (&manager->db_manager, tracker_db_manager_free);
+       }
 
        G_OBJECT_CLASS (tracker_data_manager_parent_class)->finalize (object);
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]