diff options
author | Carlos Garnacho <carlosg@gnome.org> | 2017-07-05 11:05:33 +0200 |
---|---|---|
committer | Carlos Garnacho <carlosg@gnome.org> | 2017-08-05 21:52:00 +0200 |
commit | 57ed3ddc74099b9c75cd83d4f531c4d6782a549b (patch) | |
tree | 781f1098a65c42698bd8308ebf05d667c5963576 | |
parent | b16727dc7d5dd42fc788c7e93dd6dda0d68719d0 (diff) | |
download | tracker-wip/carlosg/resource-leak-fix.tar.gz |
libtracker-data: Perform trimming of unused resource URNs on shutdownwip/carlosg/resource-leak-fix
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)
-rw-r--r-- | 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 f957fd784..4aa7df708 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); } |