[tracker/wip/carlosg/notifier-service-queries: 12/12] libtracker-sparql: Use TrackerSparqlStatement in TrackerNotifier
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [tracker/wip/carlosg/notifier-service-queries: 12/12] libtracker-sparql: Use TrackerSparqlStatement in TrackerNotifier
- Date: Sun, 21 Jun 2020 21:31:54 +0000 (UTC)
commit 74ce2d178b0e2731938c4c8c3be931e73a21a49f
Author: Carlos Garnacho <carlosg gnome org>
Date: Sun Jun 21 23:24:17 2020 +0200
libtracker-sparql: Use TrackerSparqlStatement in TrackerNotifier
Keep one prepared statement for queries on the local connection, plus
one prepared statement per DBus subscription. Use the corresponding one
when querying URNs for a set of IDs.
Since prepared statements have a fixed number of arguments, keep the
maximum ever used, and add ID=0 as padding for the unused ones (since
they must be bound).
src/libtracker-sparql/tracker-notifier.c | 160 ++++++++++++++++++++++---------
1 file changed, 115 insertions(+), 45 deletions(-)
---
diff --git a/src/libtracker-sparql/tracker-notifier.c b/src/libtracker-sparql/tracker-notifier.c
index 25dff678a..fd9a4eaed 100644
--- a/src/libtracker-sparql/tracker-notifier.c
+++ b/src/libtracker-sparql/tracker-notifier.c
@@ -80,6 +80,8 @@ typedef struct _TrackerNotifierEventCache TrackerNotifierEventCache;
struct _TrackerNotifierSubscription {
GDBusConnection *connection;
TrackerNotifier *notifier;
+ TrackerSparqlStatement *statement;
+ gint n_statement_slots;
gchar *service;
gchar *object_path;
guint handler_id;
@@ -89,6 +91,8 @@ struct _TrackerNotifierPrivate {
TrackerSparqlConnection *connection;
GHashTable *subscriptions; /* guint -> TrackerNotifierSubscription */
GCancellable *cancellable;
+ TrackerSparqlStatement *local_statement;
+ gint n_local_statement_slots;
};
struct _TrackerNotifierEventCache {
@@ -146,6 +150,7 @@ tracker_notifier_subscription_free (TrackerNotifierSubscription *subscription)
g_dbus_connection_signal_unsubscribe (subscription->connection,
subscription->handler_id);
g_object_unref (subscription->connection);
+ g_clear_object (&subscription->statement);
g_free (subscription->service);
g_free (subscription->object_path);
g_free (subscription);
@@ -379,33 +384,12 @@ tracker_notifier_emit_events_in_idle (TrackerNotifierEventCache *cache)
static gchar *
create_extra_info_query (TrackerNotifier *notifier,
- TrackerNotifierEventCache *cache)
+ TrackerNotifierEventCache *cache,
+ gint n_slots)
{
- GString *sparql, *filter;
- gboolean has_elements = FALSE;
+ GString *sparql;
gchar *service;
- GSequenceIter *iter;
-
- filter = g_string_new (NULL);
-
- for (iter = g_sequence_get_begin_iter (cache->sequence);
- !g_sequence_iter_is_end (iter);
- iter = g_sequence_iter_next (iter)) {
- TrackerNotifierEvent *event;
-
- event = g_sequence_get (iter);
-
- if (has_elements)
- g_string_append_c (filter, ' ');
-
- g_string_append_printf (filter, "%" G_GINT64_FORMAT, event->id);
- has_elements = TRUE;
- }
-
- if (!has_elements) {
- g_string_free (filter, TRUE);
- return NULL;
- }
+ gint i;
sparql = g_string_new ("SELECT ?id ?uri ");
@@ -417,11 +401,16 @@ create_extra_info_query (TrackerNotifier *notifier,
service);
}
- g_string_append_printf (sparql,
- "{ VALUES ?id { %s }"
- " BIND (tracker:uri(?id) AS ?uri)"
- "}", filter->str);
- g_string_free (filter, TRUE);
+ g_string_append (sparql, "{ VALUES ?id { ");
+
+ for (i = 0; i < n_slots; i++) {
+ g_string_append_printf (sparql, "~arg%d ", i + 1);
+ }
+
+ g_string_append (sparql,
+ " } ."
+ " BIND (tracker:uri(xsd:integer(?id)) AS ?uri)"
+ "} ");
if (service)
g_string_append (sparql, "} ");
@@ -433,22 +422,68 @@ create_extra_info_query (TrackerNotifier *notifier,
return g_string_free (sparql, FALSE);
}
+static TrackerSparqlStatement *
+ensure_extra_info_statement (TrackerNotifier *notifier,
+ TrackerNotifierEventCache *cache,
+ gint *n_slots_out)
+{
+ TrackerSparqlStatement **ptr;
+ TrackerNotifierPrivate *priv;
+ gchar *sparql;
+ gint *n_slots, new_slots;
+ GError *error = NULL;
+
+ priv = tracker_notifier_get_instance_private (notifier);
+
+ if (cache->subscription) {
+ ptr = &cache->subscription->statement;
+ n_slots = &cache->subscription->n_statement_slots;
+ } else {
+ ptr = &priv->local_statement;
+ n_slots = &priv->n_local_statement_slots;
+ }
+
+ if (*ptr && *n_slots >= g_sequence_get_length (cache->sequence)) {
+ *n_slots_out = *n_slots;
+ return *ptr;
+ }
+
+ g_clear_object (ptr);
+ new_slots = g_sequence_get_length (cache->sequence);
+ sparql = create_extra_info_query (notifier, cache, new_slots);
+ *ptr = tracker_sparql_connection_query_statement (priv->connection,
+ sparql,
+ priv->cancellable,
+ &error);
+ g_free (sparql);
+
+ if (error) {
+ g_warning ("Error querying notifier info: %s\n", error->message);
+ g_error_free (error);
+ return NULL;
+ }
+
+ *n_slots = new_slots;
+ *n_slots_out = new_slots;
+
+ return *ptr;
+}
+
static void
query_extra_info_cb (GObject *object,
GAsyncResult *res,
gpointer user_data)
{
TrackerNotifierEventCache *cache = user_data;
- TrackerSparqlConnection *conn;
+ TrackerSparqlStatement *statement;
TrackerSparqlCursor *cursor;
TrackerNotifierEvent *event;
GSequenceIter *iter;
GError *error = NULL;
- gint col;
gint64 id;
- conn = TRACKER_SPARQL_CONNECTION (object);
- cursor = tracker_sparql_connection_query_finish (conn, res, &error);
+ statement = TRACKER_SPARQL_STATEMENT (object);
+ cursor = tracker_sparql_statement_execute_finish (statement, res, &error);
if (!cursor) {
if (!g_error_matches (error,
@@ -470,8 +505,10 @@ query_extra_info_cb (GObject *object,
* clause.
*/
while (tracker_sparql_cursor_next (cursor, NULL, NULL)) {
- col = 0;
- id = tracker_sparql_cursor_get_integer (cursor, col++);
+ id = tracker_sparql_cursor_get_integer (cursor, 0);
+ if (id == 0)
+ continue;
+
event = g_sequence_get (iter);
iter = g_sequence_iter_next (iter);
@@ -481,7 +518,7 @@ query_extra_info_cb (GObject *object,
break;
}
- event->urn = g_strdup (tracker_sparql_cursor_get_string (cursor, col++, NULL));
+ event->urn = g_strdup (tracker_sparql_cursor_get_string (cursor, 1, NULL));
}
g_object_unref (cursor);
@@ -489,23 +526,55 @@ query_extra_info_cb (GObject *object,
tracker_notifier_emit_events_in_idle (cache);
}
+static void
+bind_arguments (TrackerSparqlStatement *statement,
+ TrackerNotifierEventCache *cache,
+ gint n_slots)
+{
+ GSequenceIter *iter;
+ gchar *arg_name;
+ gint i = 0;
+
+ for (iter = g_sequence_get_begin_iter (cache->sequence);
+ !g_sequence_iter_is_end (iter);
+ iter = g_sequence_iter_next (iter)) {
+ TrackerNotifierEvent *event;
+
+ event = g_sequence_get (iter);
+
+ arg_name = g_strdup_printf ("arg%d", i + 1);
+ tracker_sparql_statement_bind_int (statement, arg_name, event->id);
+ g_free (arg_name);
+ i++;
+ }
+
+ /* Fill in missing slots with 0's */
+ while (i < n_slots) {
+ arg_name = g_strdup_printf ("arg%d", i + 1);
+ tracker_sparql_statement_bind_int (statement, arg_name, 0);
+ g_free (arg_name);
+ i++;
+ }
+}
+
static void
tracker_notifier_query_extra_info (TrackerNotifier *notifier,
TrackerNotifierEventCache *cache)
{
TrackerNotifierPrivate *priv;
- gchar *sparql;
+ TrackerSparqlStatement *statement;
+ gint n_slots;
- sparql = create_extra_info_query (notifier, cache);
- if (!sparql)
+ statement = ensure_extra_info_statement (notifier, cache, &n_slots);
+ if (!statement)
return;
+ bind_arguments (statement, cache, n_slots);
priv = tracker_notifier_get_instance_private (notifier);
- tracker_sparql_connection_query_async (priv->connection, sparql,
- priv->cancellable,
- query_extra_info_cb,
- cache);
- g_free (sparql);
+ tracker_sparql_statement_execute_async (statement,
+ priv->cancellable,
+ query_extra_info_cb,
+ cache);
}
void
@@ -592,6 +661,7 @@ tracker_notifier_finalize (GObject *object)
g_cancellable_cancel (priv->cancellable);
g_clear_object (&priv->cancellable);
+ g_clear_object (&priv->local_statement);
if (priv->connection)
g_object_unref (priv->connection);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]