summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Garnacho <carlosg@gnome.org>2020-08-30 19:33:12 +0200
committerCarlos Garnacho <carlosg@gnome.org>2020-08-30 23:31:52 +0200
commit7683955ebcbb9cb81a0a859fb0737522149bb60e (patch)
tree8281e5bac24ab9494d7053b1c604c6f9760d6707
parenta763f16a94e3c80dda4a5087d92aee28c86b1c9c (diff)
downloadtracker-7683955ebcbb9cb81a0a859fb0737522149bb60e.tar.gz
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.
-rw-r--r--src/libtracker-sparql/direct/tracker-direct-statement.c5
-rw-r--r--src/libtracker-sparql/direct/tracker-direct.c69
-rw-r--r--src/libtracker-sparql/direct/tracker-direct.h2
3 files changed, 76 insertions, 0 deletions
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);