[tracker/wip/carlosg/release-memory: 2/5] libtracker-sparql/direct: Set up cleanup timeout




commit 7683955ebcbb9cb81a0a859fb0737522149bb60e
Author: Carlos Garnacho <carlosg gnome org>
Date:   Sun Aug 30 19:33:12 2020 +0200

    libtracker-sparql/direct: Set up cleanup timeout
    
    This timeout checks every 30 seconds that the sparql connection has
    been inactive for some time, and triggers memory to be reclaimed in
    the update thread.

 .../direct/tracker-direct-statement.c              |  5 ++
 src/libtracker-sparql/direct/tracker-direct.c      | 69 ++++++++++++++++++++++
 src/libtracker-sparql/direct/tracker-direct.h      |  2 +
 3 files changed, 76 insertions(+)
---
diff --git a/src/libtracker-sparql/direct/tracker-direct-statement.c 
b/src/libtracker-sparql/direct/tracker-direct-statement.c
index 8e1bcdd8a..4a281de5d 100644
--- a/src/libtracker-sparql/direct/tracker-direct-statement.c
+++ b/src/libtracker-sparql/direct/tracker-direct-statement.c
@@ -239,6 +239,7 @@ tracker_direct_statement_execute_finish (TrackerSparqlStatement  *stmt,
                                          GAsyncResult            *res,
                                          GError                 **error)
 {
+       TrackerDirectConnection *conn;
        TrackerSparqlCursor *cursor;
        GError *inner_error = NULL;
 
@@ -246,6 +247,10 @@ tracker_direct_statement_execute_finish (TrackerSparqlStatement  *stmt,
        if (inner_error)
                g_propagate_error (error, _translate_internal_error (inner_error));
 
+       g_object_get (stmt, "connection", &conn, NULL);
+       tracker_direct_connection_update_timestamp (conn);
+       g_object_unref (conn);
+
        return cursor;
 }
 
diff --git a/src/libtracker-sparql/direct/tracker-direct.c b/src/libtracker-sparql/direct/tracker-direct.c
index 07423c47b..3d867283c 100644
--- a/src/libtracker-sparql/direct/tracker-direct.c
+++ b/src/libtracker-sparql/direct/tracker-direct.c
@@ -45,6 +45,11 @@ struct _TrackerDirectConnectionPrivate
 
        GList *notifiers;
 
+       gint64 timestamp;
+       gint64 cleanup_timestamp;
+
+       guint cleanup_timeout_id;
+
        guint initialized : 1;
        guint closing     : 1;
 };
@@ -63,6 +68,7 @@ typedef enum {
        TASK_TYPE_QUERY,
        TASK_TYPE_UPDATE,
        TASK_TYPE_UPDATE_BLANK,
+       TASK_TYPE_RELEASE_MEMORY,
 } TaskType;
 
 typedef struct {
@@ -103,6 +109,37 @@ task_data_free (TaskData *task)
        g_free (task);
 }
 
+static gboolean
+cleanup_timeout_cb (gpointer user_data)
+{
+       TrackerDirectConnection *conn = user_data;
+       TrackerDirectConnectionPrivate *priv;
+       gint64 timestamp;
+       GTask *task;
+
+       priv = tracker_direct_connection_get_instance_private (conn);
+       timestamp = g_get_monotonic_time ();
+
+       /* If we already cleaned up */
+       if (priv->timestamp < priv->cleanup_timestamp)
+               return G_SOURCE_CONTINUE;
+       /* If the connection was used less than 10s ago */
+       if (timestamp - priv->timestamp < 10 * G_USEC_PER_SEC)
+               return G_SOURCE_CONTINUE;
+
+       priv->cleanup_timestamp = timestamp;
+
+       task = g_task_new (conn, NULL, NULL, NULL);
+       g_task_set_task_data (task,
+                             task_data_query_new (TASK_TYPE_RELEASE_MEMORY, NULL),
+                             (GDestroyNotify) task_data_free);
+
+       g_thread_pool_push (priv->update_thread, task, NULL);
+
+       return G_SOURCE_CONTINUE;
+}
+
+
 static void
 update_thread_func (gpointer data,
                     gpointer user_data)
@@ -115,6 +152,7 @@ update_thread_func (gpointer data,
        GError *error = NULL;
        gpointer retval = NULL;
        GDestroyNotify destroy_notify = NULL;
+       gboolean update_timestamp = TRUE;
 
        conn = user_data;
        priv = tracker_direct_connection_get_instance_private (conn);
@@ -133,6 +171,10 @@ update_thread_func (gpointer data,
                retval = tracker_data_update_sparql_blank (tracker_data, task_data->query, &error);
                destroy_notify = (GDestroyNotify) g_variant_unref;
                break;
+       case TASK_TYPE_RELEASE_MEMORY:
+               tracker_data_manager_release_memory (priv->data_manager);
+               update_timestamp = FALSE;
+               break;
        }
 
        if (error)
@@ -143,6 +185,10 @@ update_thread_func (gpointer data,
                g_task_return_boolean (task, TRUE);
 
        g_object_unref (task);
+
+       if (update_timestamp)
+               tracker_direct_connection_update_timestamp (conn);
+
        g_mutex_unlock (&priv->mutex);
 }
 
@@ -284,6 +330,9 @@ tracker_direct_connection_initable_init (GInitable     *initable,
 
        g_hash_table_unref (namespaces);
 
+       priv->cleanup_timeout_id =
+               g_timeout_add_seconds (30, cleanup_timeout_cb, conn);
+
        return TRUE;
 }
 
@@ -542,6 +591,9 @@ tracker_direct_connection_finalize (GObject *object)
        conn = TRACKER_DIRECT_CONNECTION (object);
        priv = tracker_direct_connection_get_instance_private (conn);
 
+       if (!priv->closing)
+               tracker_sparql_connection_close (TRACKER_SPARQL_CONNECTION (object));
+
        g_clear_object (&priv->store);
        g_clear_object (&priv->ontology);
        g_clear_object (&priv->namespace_manager);
@@ -623,6 +675,7 @@ tracker_direct_connection_query (TrackerSparqlConnection  *self,
        g_mutex_lock (&priv->mutex);
        query = tracker_sparql_new (priv->data_manager, sparql);
        cursor = tracker_sparql_execute_cursor (query, NULL, &inner_error);
+       tracker_direct_connection_update_timestamp (conn);
        g_object_unref (query);
 
        if (cursor)
@@ -695,6 +748,7 @@ tracker_direct_connection_update (TrackerSparqlConnection  *self,
        g_mutex_lock (&priv->mutex);
        data = tracker_data_manager_get_data (priv->data_manager);
        tracker_data_update_sparql (data, sparql, &inner_error);
+       tracker_direct_connection_update_timestamp (conn);
        g_mutex_unlock (&priv->mutex);
 
        if (inner_error)
@@ -802,6 +856,7 @@ tracker_direct_connection_update_blank (TrackerSparqlConnection  *self,
        g_mutex_lock (&priv->mutex);
        data = tracker_data_manager_get_data (priv->data_manager);
        blank_nodes = tracker_data_update_sparql_blank (data, sparql, &inner_error);
+       tracker_direct_connection_update_timestamp (conn);
        g_mutex_unlock (&priv->mutex);
 
        if (inner_error)
@@ -899,6 +954,11 @@ tracker_direct_connection_close (TrackerSparqlConnection *self)
        priv = tracker_direct_connection_get_instance_private (conn);
        priv->closing = TRUE;
 
+       if (priv->cleanup_timeout_id) {
+               g_source_remove (priv->cleanup_timeout_id);
+               priv->cleanup_timeout_id = 0;
+       }
+
        if (priv->update_thread) {
                g_thread_pool_free (priv->update_thread, TRUE, TRUE);
                priv->update_thread = NULL;
@@ -1040,3 +1100,12 @@ tracker_direct_connection_get_data_manager (TrackerDirectConnection *conn)
        priv = tracker_direct_connection_get_instance_private (conn);
        return priv->data_manager;
 }
+
+void
+tracker_direct_connection_update_timestamp (TrackerDirectConnection *conn)
+{
+       TrackerDirectConnectionPrivate *priv;
+
+       priv = tracker_direct_connection_get_instance_private (conn);
+       priv->timestamp = g_get_monotonic_time ();
+}
diff --git a/src/libtracker-sparql/direct/tracker-direct.h b/src/libtracker-sparql/direct/tracker-direct.h
index 264f1a2d1..c353b51ca 100644
--- a/src/libtracker-sparql/direct/tracker-direct.h
+++ b/src/libtracker-sparql/direct/tracker-direct.h
@@ -53,6 +53,8 @@ TrackerDirectConnection *tracker_direct_connection_new (TrackerSparqlConnectionF
 
 TrackerDataManager *tracker_direct_connection_get_data_manager (TrackerDirectConnection *conn);
 
+void tracker_direct_connection_update_timestamp (TrackerDirectConnection *conn);
+
 /* Internal helper function */
 GError *translate_db_interface_error (GError *error);
 


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