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



commit 8bc8829dbfd8575d0b22800b4e2e3b2c4a34f5b2
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 |   65 +++++++++++++++++++++++++++-
 1 files changed, 64 insertions(+), 1 deletions(-)
---
diff --git a/src/libtracker-data/tracker-data-manager.c b/src/libtracker-data/tracker-data-manager.c
index 98f732a..1243839 100644
--- a/src/libtracker-data/tracker-data-manager.c
+++ b/src/libtracker-data/tracker-data-manager.c
@@ -4742,12 +4742,75 @@ skip_ontology_check:
        return TRUE;
 }
 
+static guint
+data_manager_get_graph_count (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);
+
+       return count;
+}
+
 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;
+
+               /* 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 (!readonly && data_manager_get_graph_count (manager) > 0) {
+                       /* 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)");
+
+                       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);
+                       }
 
-       g_clear_pointer (&manager->db_manager, tracker_db_manager_free);
+                       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]