[tracker/wip/carlosg/rewrite-bus-impl: 1/2] libtracker-sparql: Reimplement all bus connection objects




commit affcc203a5fc6a3de20048e787e76b3ebf4d348a
Author: Carlos Garnacho <carlosg gnome org>
Date:   Fri Jul 15 18:50:11 2022 +0200

    libtracker-sparql: Reimplement all bus connection objects
    
    Historically the set of objects that provide the bus implementation
    were written in Vala, this commit ends with that and rewrites all of
    these objects in C. This is mostly a 1:1 port with one exception,
    cursors are now based on TrackerDeserializer and input streams, they
    were given a memory buffer previously.
    
    The use of Vala here had a few indirect effects:
    
    - Vala code could not be introspected by our gcovr infrastructure for
      code coverage. This made this central piece of our library invisible
      to coverage stats entirely.
    
    - Since our library code and vala contend for the use of visibility
      attributes for public functions, we ended up with a few symbols from
      this Vala code that was never intended to be public API.
    
    - The async code generated by Vala triggers reports about unreachable
      code in Coverity. This has proven very imbued in Vala and hard to
      fix without breaking something else there.
    
    Moving away from Vala fixes all 3. For the sake of maintainability,
    this is seen as a net improvement, despite the more verbose code and
    the async operation daisy chaning at places. Now all untested code,
    leaked symbols and dead code will be a responsibility of our own.

 src/libtracker-common/libtracker-common.vapi       |  120 --
 src/libtracker-sparql/bus/.gitignore               |    5 -
 src/libtracker-sparql/bus/meson.build              |    9 +-
 src/libtracker-sparql/bus/tracker-bus-batch.c      |  192 +++
 src/libtracker-sparql/bus/tracker-bus-batch.h      |   37 +
 src/libtracker-sparql/bus/tracker-bus-batch.vala   |   63 -
 src/libtracker-sparql/bus/tracker-bus-cursor.c     |  361 +++++
 ...tracker-namespace.vala => tracker-bus-cursor.h} |   24 +-
 .../bus/tracker-bus-fd-cursor.vala                 |  150 --
 src/libtracker-sparql/bus/tracker-bus-statement.c  |  289 ++++
 src/libtracker-sparql/bus/tracker-bus-statement.h  |   38 +
 .../bus/tracker-bus-statement.vala                 |  100 --
 src/libtracker-sparql/bus/tracker-bus.c            | 1703 ++++++++++++++++++++
 src/libtracker-sparql/bus/tracker-bus.h            |   77 +
 src/libtracker-sparql/bus/tracker-bus.vala         |  444 -----
 src/libtracker-sparql/meson.build                  |    2 -
 src/libtracker-sparql/tracker-backend.vala         |   70 -
 src/libtracker-sparql/tracker-connection.c         |  162 +-
 18 files changed, 2830 insertions(+), 1016 deletions(-)
---
diff --git a/src/libtracker-sparql/bus/meson.build b/src/libtracker-sparql/bus/meson.build
index 6852171d0..28534e006 100644
--- a/src/libtracker-sparql/bus/meson.build
+++ b/src/libtracker-sparql/bus/meson.build
@@ -1,7 +1,6 @@
 bus_files = files(
-    'tracker-bus.vala',
-    'tracker-namespace.vala',
-    'tracker-bus-batch.vala',
-    'tracker-bus-fd-cursor.vala',
-    'tracker-bus-statement.vala',
+    'tracker-bus.c',
+    'tracker-bus-batch.c',
+    'tracker-bus-cursor.c',
+    'tracker-bus-statement.c',
 )
diff --git a/src/libtracker-sparql/bus/tracker-bus-batch.c b/src/libtracker-sparql/bus/tracker-bus-batch.c
new file mode 100644
index 000000000..b2f144ca3
--- /dev/null
+++ b/src/libtracker-sparql/bus/tracker-bus-batch.c
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2021, Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ *
+ * Author: Carlos Garnacho <carlosg gnome org>
+ */
+
+#include "config.h"
+
+#include "tracker-bus-batch.h"
+
+struct _TrackerBusBatch
+{
+       TrackerBatch parent_instance;
+       GPtrArray *updates;
+};
+
+typedef struct {
+       GMainLoop *loop;
+       gboolean retval;
+       GError *error;
+} ExecuteAsyncData;
+
+G_DEFINE_TYPE (TrackerBusBatch, tracker_bus_batch, TRACKER_TYPE_BATCH)
+
+static void
+tracker_bus_batch_finalize (GObject *object)
+{
+       TrackerBusBatch *bus_batch = TRACKER_BUS_BATCH (object);
+
+       g_ptr_array_unref (bus_batch->updates);
+
+       G_OBJECT_CLASS (tracker_bus_batch_parent_class)->finalize (object);
+}
+
+static void
+tracker_bus_batch_add_sparql (TrackerBatch *batch,
+                              const gchar  *sparql)
+{
+       TrackerBusBatch *bus_batch = TRACKER_BUS_BATCH (batch);
+
+       g_ptr_array_add (bus_batch->updates, g_strdup (sparql));
+}
+
+static void
+tracker_bus_batch_add_resource (TrackerBatch    *batch,
+                                const gchar     *graph,
+                                TrackerResource *resource)
+{
+       TrackerBusBatch *bus_batch = TRACKER_BUS_BATCH (batch);
+       TrackerSparqlConnection *conn;
+       TrackerNamespaceManager *namespaces;
+       gchar *sparql;
+
+       conn = tracker_batch_get_connection (batch);
+       namespaces = tracker_sparql_connection_get_namespace_manager (conn);
+       sparql = tracker_resource_print_sparql_update (resource, namespaces, graph);
+       g_ptr_array_add (bus_batch->updates, sparql);
+}
+
+static void
+execute_cb (GObject      *source,
+            GAsyncResult *res,
+            gpointer      user_data)
+{
+       ExecuteAsyncData *data = user_data;
+
+       data->retval =
+               tracker_batch_execute_finish (TRACKER_BATCH (source),
+                                             res, &data->error);
+       g_main_loop_quit (data->loop);
+}
+
+static gboolean
+tracker_bus_batch_execute (TrackerBatch  *batch,
+                           GCancellable  *cancellable,
+                           GError       **error)
+{
+       GMainContext *context;
+       ExecuteAsyncData data = { 0, };
+
+       context = g_main_context_new ();
+       data.loop = g_main_loop_new (context, FALSE);
+       g_main_context_push_thread_default (context);
+
+       tracker_batch_execute_async (batch,
+                                    cancellable,
+                                    execute_cb,
+                                    &data);
+
+       g_main_loop_run (data.loop);
+
+       g_main_context_pop_thread_default (context);
+
+       g_main_loop_unref (data.loop);
+
+       if (data.error) {
+               g_propagate_error (error, data.error);
+               return FALSE;
+       }
+
+       return data.retval;
+}
+
+static void
+update_array_cb (GObject      *source,
+                 GAsyncResult *res,
+                 gpointer      user_data)
+{
+       GTask *task = user_data;
+       GError *error = NULL;
+
+       if (!tracker_sparql_connection_update_array_finish (TRACKER_SPARQL_CONNECTION (source),
+                                                           res, &error))
+               g_task_return_error (task, error);
+       else
+               g_task_return_boolean (task, TRUE);
+
+       g_object_unref (task);
+}
+
+static void
+tracker_bus_batch_execute_async (TrackerBatch        *batch,
+                                 GCancellable        *cancellable,
+                                 GAsyncReadyCallback  callback,
+                                 gpointer             user_data)
+{
+       TrackerBusBatch *bus_batch = TRACKER_BUS_BATCH (batch);
+       TrackerSparqlConnection *conn;
+       GTask *task;
+
+       task = g_task_new (batch, cancellable, callback, user_data);
+       conn = tracker_batch_get_connection (batch);
+       tracker_sparql_connection_update_array_async (conn,
+                                                     (gchar **) bus_batch->updates->pdata,
+                                                     bus_batch->updates->len,
+                                                     cancellable,
+                                                     update_array_cb,
+                                                     task);
+}
+
+static gboolean
+tracker_bus_batch_execute_finish (TrackerBatch  *batch,
+                                  GAsyncResult  *res,
+                                  GError       **error)
+{
+       return g_task_propagate_boolean (G_TASK (res), error);
+}
+
+static void
+tracker_bus_batch_class_init (TrackerBusBatchClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+       TrackerBatchClass *batch_class = TRACKER_BATCH_CLASS (klass);
+
+       object_class->finalize = tracker_bus_batch_finalize;
+
+       batch_class->add_sparql = tracker_bus_batch_add_sparql;
+       batch_class->add_resource = tracker_bus_batch_add_resource;
+       batch_class->execute = tracker_bus_batch_execute;
+       batch_class->execute_async = tracker_bus_batch_execute_async;
+       batch_class->execute_finish = tracker_bus_batch_execute_finish;
+}
+
+static void
+tracker_bus_batch_init (TrackerBusBatch *batch)
+{
+       batch->updates = g_ptr_array_new ();
+       g_ptr_array_set_free_func (batch->updates, g_free);
+}
+
+TrackerBatch *
+tracker_bus_batch_new (TrackerBusConnection *connection)
+{
+       return g_object_new (TRACKER_TYPE_BUS_BATCH,
+                            "connection", connection,
+                            NULL);
+}
diff --git a/src/libtracker-sparql/bus/tracker-bus-batch.h b/src/libtracker-sparql/bus/tracker-bus-batch.h
new file mode 100644
index 000000000..97be326c9
--- /dev/null
+++ b/src/libtracker-sparql/bus/tracker-bus-batch.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2021, Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ *
+ * Author: Carlos Garnacho <carlosg gnome org>
+ */
+
+#ifndef __TRACKER_BUS_BATCH_H__
+#define __TRACKER_BUS_BATCH_H__
+
+#include "tracker-bus.h"
+
+#include <libtracker-sparql/tracker-private.h>
+
+#define TRACKER_TYPE_BUS_BATCH (tracker_bus_batch_get_type ())
+G_DECLARE_FINAL_TYPE (TrackerBusBatch,
+                      tracker_bus_batch,
+                      TRACKER, BUS_BATCH,
+                      TrackerBatch)
+
+TrackerBatch * tracker_bus_batch_new (TrackerBusConnection *connection);
+
+#endif /* __TRACKER_BUS_BATCH_H__ */
diff --git a/src/libtracker-sparql/bus/tracker-bus-cursor.c b/src/libtracker-sparql/bus/tracker-bus-cursor.c
new file mode 100644
index 000000000..0a006683e
--- /dev/null
+++ b/src/libtracker-sparql/bus/tracker-bus-cursor.c
@@ -0,0 +1,361 @@
+/*
+ * Copyright (C) 2010, Nokia <ivan frade nokia com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ */
+
+#include "config.h"
+
+#include "tracker-bus-cursor.h"
+
+struct _TrackerBusCursor
+{
+       TrackerDeserializer parent_instance;
+       GDataInputStream *data_stream;
+       GVariant *variables;
+       const gchar **variable_names;
+       gint n_columns;
+       TrackerSparqlValueType *types;
+       gchar *row_data;
+       const gchar **values;
+       gboolean finished;
+};
+
+enum {
+       PROP_0,
+       PROP_VARIABLES,
+       N_PROPS
+};
+
+static GParamSpec *props[N_PROPS] = { 0, };
+
+G_DEFINE_TYPE (TrackerBusCursor,
+               tracker_bus_cursor,
+               TRACKER_TYPE_DESERIALIZER)
+
+static void
+tracker_bus_cursor_finalize (GObject *object)
+{
+       TrackerBusCursor *bus_cursor = TRACKER_BUS_CURSOR (object);
+
+       g_clear_object (&bus_cursor->data_stream);
+       g_clear_pointer (&bus_cursor->variables, g_variant_unref);
+       g_clear_pointer (&bus_cursor->types, g_free);
+       g_clear_pointer (&bus_cursor->row_data, g_free);
+       g_clear_pointer (&bus_cursor->values, g_free);
+       g_clear_pointer (&bus_cursor->variable_names, g_free);
+
+       G_OBJECT_CLASS (tracker_bus_cursor_parent_class)->finalize (object);
+}
+
+static void
+tracker_bus_cursor_constructed (GObject *object)
+{
+       TrackerDeserializer *deserializer = TRACKER_DESERIALIZER (object);
+       TrackerBusCursor *cursor = TRACKER_BUS_CURSOR (object);
+
+       G_OBJECT_CLASS (tracker_bus_cursor_parent_class)->constructed (object);
+
+       cursor->variable_names = g_variant_get_strv (cursor->variables, NULL);
+       cursor->n_columns = g_strv_length ((gchar **) cursor->variable_names);
+       cursor->data_stream =
+               g_data_input_stream_new (tracker_deserializer_get_stream (deserializer));
+       g_data_input_stream_set_byte_order (cursor->data_stream,
+                                           G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN);
+}
+
+static void
+tracker_bus_cursor_set_property (GObject      *object,
+                                guint         prop_id,
+                                const GValue *value,
+                                GParamSpec   *pspec)
+{
+       TrackerBusCursor *cursor = TRACKER_BUS_CURSOR (object);
+
+       switch (prop_id) {
+       case PROP_VARIABLES:
+               cursor->variables = g_value_dup_variant (value);
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+               break;
+       }
+}
+
+static void
+tracker_bus_cursor_get_property (GObject    *object,
+                                guint       prop_id,
+                                GValue     *value,
+                                GParamSpec *pspec)
+{
+       TrackerBusCursor *cursor = TRACKER_BUS_CURSOR (object);
+
+       switch (prop_id) {
+       case PROP_VARIABLES:
+               g_value_set_variant (value, cursor->variables);
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+               break;
+       }
+}
+
+static gint
+tracker_bus_cursor_get_n_columns (TrackerSparqlCursor *cursor)
+{
+       TrackerBusCursor *bus_cursor = TRACKER_BUS_CURSOR (cursor);
+
+       return bus_cursor->n_columns;
+}
+
+static TrackerSparqlValueType
+tracker_bus_cursor_get_value_type (TrackerSparqlCursor *cursor,
+                                   gint                 column)
+{
+       TrackerBusCursor *bus_cursor = TRACKER_BUS_CURSOR (cursor);
+
+       if (bus_cursor->finished)
+               return TRACKER_SPARQL_VALUE_TYPE_UNBOUND;
+       if (column < 0 || column >= bus_cursor->n_columns)
+               return TRACKER_SPARQL_VALUE_TYPE_UNBOUND;
+       if (!bus_cursor->types)
+               return TRACKER_SPARQL_VALUE_TYPE_UNBOUND;
+
+       return bus_cursor->types[column];
+}
+
+static const gchar *
+tracker_bus_cursor_get_variable_name (TrackerSparqlCursor *cursor,
+                                      gint                 column)
+{
+       TrackerBusCursor *bus_cursor = TRACKER_BUS_CURSOR (cursor);
+
+       if (bus_cursor->finished)
+               return NULL;
+       if (column < 0 || column >= bus_cursor->n_columns)
+               return NULL;
+
+       return bus_cursor->variable_names[column];
+}
+
+static const gchar *
+tracker_bus_cursor_get_string (TrackerSparqlCursor *cursor,
+                               gint                 column,
+                              glong               *len)
+{
+       TrackerBusCursor *bus_cursor = TRACKER_BUS_CURSOR (cursor);
+       const gchar *str;
+
+       if (bus_cursor->finished)
+               return NULL;
+       if (column < 0 || column >= bus_cursor->n_columns)
+               return NULL;
+       if (!bus_cursor->types)
+               return NULL;
+
+       /* Return null instead of empty string for unbound values */
+       if (bus_cursor->types[column] == TRACKER_SPARQL_VALUE_TYPE_UNBOUND)
+               return NULL;
+
+       str = bus_cursor->values[column];
+
+       if (len)
+               *len = strlen (str);
+
+       return str;
+}
+
+static gboolean
+tracker_bus_cursor_next (TrackerSparqlCursor  *cursor,
+                         GCancellable         *cancellable,
+                         GError              **error)
+{
+       TrackerBusCursor *bus_cursor = TRACKER_BUS_CURSOR (cursor);
+       gint32 *offsets, n_columns, i;
+
+       if (bus_cursor->finished)
+               return FALSE;
+       if (g_cancellable_set_error_if_cancelled (cancellable, error))
+               return FALSE;
+
+       /* So, the make up on each cursor segment is:
+        *
+        * iteration = [4 bytes for number of columns,
+        *              columns x 4 bytes for types
+        *              columns x 4 bytes for offsets]
+        */
+       n_columns = g_data_input_stream_read_int32 (bus_cursor->data_stream,
+                                                   NULL, NULL);
+
+       if (n_columns == 0) {
+               bus_cursor->finished = TRUE;
+               return FALSE;
+       }
+
+       g_clear_pointer (&bus_cursor->types, g_free);
+       bus_cursor->types = g_new0 (TrackerSparqlValueType, n_columns);
+       g_input_stream_read_all (G_INPUT_STREAM (bus_cursor->data_stream),
+                                bus_cursor->types,
+                                n_columns * sizeof (gint32),
+                                NULL, NULL, NULL);
+
+       offsets = g_new0 (gint32, n_columns);
+       g_input_stream_read_all (G_INPUT_STREAM (bus_cursor->data_stream),
+                                offsets,
+                                n_columns * sizeof (gint32),
+                                NULL, NULL, NULL);
+
+       /* The last offset says how long we have to go to read
+        * the whole row data.
+        */
+       g_clear_pointer (&bus_cursor->row_data, g_free);
+       bus_cursor->row_data =
+               g_new0 (gchar, offsets[n_columns - 1] + 1);
+       g_input_stream_read_all (G_INPUT_STREAM (bus_cursor->data_stream),
+                                bus_cursor->row_data,
+                                offsets[n_columns - 1] + 1,
+                                NULL, NULL, NULL);
+
+       g_clear_pointer (&bus_cursor->values, g_free);
+       bus_cursor->values = g_new0 (const gchar *, n_columns);
+
+       for (i = 0; i < n_columns; i++) {
+               if (i == 0)
+                       bus_cursor->values[i] = bus_cursor->row_data;
+               else
+                       bus_cursor->values[i] = &bus_cursor->row_data[offsets[i - 1]] + 1;
+       }
+
+       g_free (offsets);
+
+       return TRUE;
+}
+
+static void
+next_in_thread (GTask        *task,
+               gpointer      source_object,
+               gpointer      task_data,
+               GCancellable *cancellable)
+{
+       GError *error = NULL;
+       gboolean retval;
+
+       retval = tracker_sparql_cursor_next (source_object, cancellable, &error);
+
+       if (error)
+               g_task_return_error (task, error);
+       else
+               g_task_return_boolean (task, retval);
+}
+
+static void
+tracker_bus_cursor_next_async (TrackerSparqlCursor  *cursor,
+                               GCancellable         *cancellable,
+                               GAsyncReadyCallback   cb,
+                               gpointer              user_data)
+{
+       GTask *task;
+
+       task = g_task_new (cursor, cancellable, cb, user_data);
+       g_task_run_in_thread (task, next_in_thread);
+}
+
+static gboolean
+tracker_bus_cursor_next_finish (TrackerSparqlCursor  *cursor,
+                                GAsyncResult         *res,
+                                GError              **error)
+{
+       return g_task_propagate_boolean (G_TASK (res), error);
+}
+
+static void
+tracker_bus_cursor_rewind (TrackerSparqlCursor *cursor)
+{
+       TrackerBusCursor *bus_cursor = TRACKER_BUS_CURSOR (cursor);
+
+       g_clear_pointer (&bus_cursor->types, g_free);
+       g_clear_pointer (&bus_cursor->row_data, g_free);
+
+       if (g_seekable_can_seek (G_SEEKABLE (bus_cursor->data_stream))) {
+               g_seekable_seek (G_SEEKABLE (bus_cursor->data_stream),
+                                0, G_SEEK_SET, NULL, NULL);
+       }
+
+       bus_cursor->finished = FALSE;
+}
+
+static void
+tracker_bus_cursor_close (TrackerSparqlCursor *cursor)
+{
+       TrackerBusCursor *bus_cursor = TRACKER_BUS_CURSOR (cursor);
+
+       g_input_stream_close (G_INPUT_STREAM (bus_cursor->data_stream),
+                             NULL, NULL);
+
+       TRACKER_SPARQL_CURSOR_CLASS (tracker_bus_cursor_parent_class)->close (cursor);
+}
+
+static void
+tracker_bus_cursor_class_init (TrackerBusCursorClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+       TrackerSparqlCursorClass *cursor_class =
+               TRACKER_SPARQL_CURSOR_CLASS (klass);
+
+       object_class->finalize = tracker_bus_cursor_finalize;
+       object_class->constructed = tracker_bus_cursor_constructed;
+       object_class->set_property = tracker_bus_cursor_set_property;
+       object_class->get_property = tracker_bus_cursor_get_property;
+
+       cursor_class->get_n_columns = tracker_bus_cursor_get_n_columns;
+       cursor_class->get_value_type = tracker_bus_cursor_get_value_type;
+       cursor_class->get_variable_name = tracker_bus_cursor_get_variable_name;
+       cursor_class->get_string = tracker_bus_cursor_get_string;
+       cursor_class->next = tracker_bus_cursor_next;
+       cursor_class->next_async = tracker_bus_cursor_next_async;
+       cursor_class->next_finish = tracker_bus_cursor_next_finish;
+       cursor_class->rewind = tracker_bus_cursor_rewind;
+       cursor_class->close = tracker_bus_cursor_close;
+
+       props[PROP_VARIABLES] =
+               g_param_spec_variant ("variables",
+                                     "Variables",
+                                     "Variables",
+                                     G_VARIANT_TYPE ("as"),
+                                     NULL,
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_STATIC_STRINGS |
+                                     G_PARAM_CONSTRUCT_ONLY);
+
+       g_object_class_install_properties (object_class, N_PROPS, props);
+
+}
+
+static void
+tracker_bus_cursor_init (TrackerBusCursor *cursor)
+{
+}
+
+TrackerSparqlCursor *
+tracker_bus_cursor_new (GInputStream *stream,
+                       GVariant     *variables)
+
+{
+       return g_object_new (TRACKER_TYPE_BUS_CURSOR,
+                            "stream", stream,
+                            "variables", variables,
+                            NULL);
+}
diff --git a/src/libtracker-sparql/bus/tracker-namespace.vala b/src/libtracker-sparql/bus/tracker-bus-cursor.h
similarity index 58%
rename from src/libtracker-sparql/bus/tracker-namespace.vala
rename to src/libtracker-sparql/bus/tracker-bus-cursor.h
index 9e0a404de..d5b6532cc 100644
--- a/src/libtracker-sparql/bus/tracker-namespace.vala
+++ b/src/libtracker-sparql/bus/tracker-bus-cursor.h
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2015 Collabora Ltd.
+ * Copyright (C) 2010, Nokia <ivan frade nokia com>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -16,14 +16,18 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA  02110-1301, USA.
  */
+#ifndef __TRACKER_BUS_CURSOR_H__
+#define __TRACKER_BUS_CURSOR_H__
 
-/*
- * This file serves as the representation for the Tracker namespace, mostly
- * so that we can set its namespace and version attributes for GIR.
- */
+#include <libtracker-sparql/tracker-sparql.h>
+
+#define TRACKER_TYPE_BUS_CURSOR (tracker_bus_cursor_get_type ())
+G_DECLARE_FINAL_TYPE (TrackerBusCursor,
+                      tracker_bus_cursor,
+                      TRACKER, BUS_CURSOR,
+                      TrackerDeserializer);
+
+TrackerSparqlCursor *tracker_bus_cursor_new (GInputStream *stream,
+                                            GVariant     *variables);
 
-[CCode (cprefix = "TrackerBus", gir_namespace = "TrackerBus",
-        gir_version = "2.0", lower_case_cprefix = "tracker_bus_")]
-namespace Tracker
-{
-}
+#endif /* __TRACKER_BUS_CURSOR_H__ */
diff --git a/src/libtracker-sparql/bus/tracker-bus-statement.c 
b/src/libtracker-sparql/bus/tracker-bus-statement.c
new file mode 100644
index 000000000..5ec6a7c2c
--- /dev/null
+++ b/src/libtracker-sparql/bus/tracker-bus-statement.c
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2020, Red Hat Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ *
+ * Author: Carlos Garnacho <carlosg gnome org>
+ */
+
+#include "config.h"
+
+#include <libtracker-common/tracker-common.h>
+
+#include "tracker-bus-statement.h"
+
+struct _TrackerBusStatement
+{
+       TrackerSparqlStatement parent_instance;
+       GHashTable *arguments;
+};
+
+G_DEFINE_TYPE (TrackerBusStatement,
+               tracker_bus_statement,
+              TRACKER_TYPE_SPARQL_STATEMENT)
+
+static void
+tracker_bus_statement_finalize (GObject *object)
+{
+       TrackerBusStatement *bus_stmt = TRACKER_BUS_STATEMENT (object);
+
+       g_hash_table_unref (bus_stmt->arguments);
+
+       G_OBJECT_CLASS (tracker_bus_statement_parent_class)->finalize (object);
+}
+
+static void
+tracker_bus_statement_bind_string (TrackerSparqlStatement *stmt,
+                                  const gchar            *name,
+                                  const gchar            *value)
+{
+       TrackerBusStatement *bus_stmt = TRACKER_BUS_STATEMENT (stmt);
+
+       g_hash_table_insert (bus_stmt->arguments,
+                            g_strdup (name),
+                            g_variant_new_string (value));
+}
+
+static void
+tracker_bus_statement_bind_boolean (TrackerSparqlStatement *stmt,
+                                    const gchar            *name,
+                                    gboolean                value)
+{
+       TrackerBusStatement *bus_stmt = TRACKER_BUS_STATEMENT (stmt);
+
+       g_hash_table_insert (bus_stmt->arguments,
+                            g_strdup (name),
+                            g_variant_new_boolean (value));
+}
+
+static void
+tracker_bus_statement_bind_double (TrackerSparqlStatement *stmt,
+                                   const gchar            *name,
+                                   gdouble                 value)
+{
+       TrackerBusStatement *bus_stmt = TRACKER_BUS_STATEMENT (stmt);
+
+       g_hash_table_insert (bus_stmt->arguments,
+                            g_strdup (name),
+                            g_variant_new_double (value));
+}
+
+static void
+tracker_bus_statement_bind_int (TrackerSparqlStatement *stmt,
+                                const gchar            *name,
+                                gint64                  value)
+{
+       TrackerBusStatement *bus_stmt = TRACKER_BUS_STATEMENT (stmt);
+
+       g_hash_table_insert (bus_stmt->arguments,
+                            g_strdup (name),
+                            g_variant_new_int64 (value));
+}
+
+static void
+tracker_bus_statement_bind_datetime (TrackerSparqlStatement *stmt,
+                                     const gchar            *name,
+                                     GDateTime              *value)
+{
+       TrackerBusStatement *bus_stmt = TRACKER_BUS_STATEMENT (stmt);
+       gchar *date_str;
+
+       date_str = tracker_date_format_iso8601 (value);
+       g_hash_table_insert (bus_stmt->arguments,
+                            g_strdup (name),
+                            g_variant_new_string (date_str));
+       g_free (date_str);
+}
+
+static void
+tracker_bus_statement_clear_bindings (TrackerSparqlStatement *stmt)
+{
+       TrackerBusStatement *bus_stmt = TRACKER_BUS_STATEMENT (stmt);
+
+       g_hash_table_remove_all (bus_stmt->arguments);
+}
+
+static GVariant *
+get_arguments (TrackerBusStatement *bus_stmt)
+{
+       GVariantBuilder builder;
+       GHashTableIter iter;
+       gpointer key, value;
+
+       if (g_hash_table_size (bus_stmt->arguments) == 0)
+               return NULL;
+
+       g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
+       g_hash_table_iter_init (&iter, bus_stmt->arguments);
+
+       while (g_hash_table_iter_next (&iter, &key, &value))
+               g_variant_builder_add (&builder, "{sv}", key, g_variant_ref_sink (value));
+
+       return g_variant_builder_end (&builder);
+}
+
+static TrackerSparqlCursor *
+tracker_bus_statement_execute (TrackerSparqlStatement  *stmt,
+                               GCancellable            *cancellable,
+                               GError                 **error)
+{
+       TrackerBusStatement *bus_stmt = TRACKER_BUS_STATEMENT (stmt);
+       TrackerSparqlConnection *conn;
+
+       conn = tracker_sparql_statement_get_connection (stmt);
+
+       return tracker_bus_connection_perform_query (TRACKER_BUS_CONNECTION (conn),
+                                                    tracker_sparql_statement_get_sparql (stmt),
+                                                    get_arguments (bus_stmt),
+                                                    cancellable, error);
+}
+
+static void
+execute_cb (GObject      *source,
+           GAsyncResult *res,
+           gpointer      user_data)
+{
+       TrackerSparqlCursor *cursor;
+       GError *error = NULL;
+       GTask *task = user_data;
+
+       cursor = tracker_bus_connection_perform_query_finish (TRACKER_BUS_CONNECTION (source),
+                                                             res, &error);
+       if (cursor)
+               g_task_return_pointer (task, cursor, g_object_unref);
+       else
+               g_task_return_error (task, error);
+
+       g_object_unref (task);
+}
+
+static void
+tracker_bus_statement_execute_async (TrackerSparqlStatement *stmt,
+                                     GCancellable           *cancellable,
+                                     GAsyncReadyCallback     callback,
+                                     gpointer                user_data)
+{
+       TrackerBusStatement *bus_stmt = TRACKER_BUS_STATEMENT (stmt);
+       TrackerSparqlConnection *conn;
+       GTask *task;
+
+       task = g_task_new (stmt, cancellable, callback, user_data);
+       conn = tracker_sparql_statement_get_connection (stmt);
+       tracker_bus_connection_perform_query_async (TRACKER_BUS_CONNECTION (conn),
+                                                   tracker_sparql_statement_get_sparql (stmt),
+                                                   get_arguments (bus_stmt),
+                                                   cancellable,
+                                                   execute_cb,
+                                                   task);
+}
+
+static TrackerSparqlCursor *
+tracker_bus_statement_execute_finish (TrackerSparqlStatement  *stmt,
+                                      GAsyncResult            *res,
+                                      GError                 **error)
+{
+       return g_task_propagate_pointer (G_TASK (res), error);
+}
+
+static void
+serialize_cb (GObject      *source,
+             GAsyncResult *res,
+             gpointer      user_data)
+{
+       GInputStream *istream;
+       GError *error = NULL;
+       GTask *task = user_data;
+
+       istream = tracker_bus_connection_perform_serialize_finish (TRACKER_BUS_CONNECTION (source),
+                                                                  res, &error);
+       if (istream)
+               g_task_return_pointer (task, istream, g_object_unref);
+       else
+               g_task_return_error (task, error);
+
+       g_object_unref (task);
+}
+
+static void
+tracker_bus_statement_serialize_async (TrackerSparqlStatement *stmt,
+                                       TrackerSerializeFlags   flags,
+                                       TrackerRdfFormat        format,
+                                       GCancellable           *cancellable,
+                                       GAsyncReadyCallback     callback,
+                                       gpointer                user_data)
+{
+       TrackerBusStatement *bus_stmt = TRACKER_BUS_STATEMENT (stmt);
+       TrackerSparqlConnection *conn;
+       GTask *task;
+
+       task = g_task_new (stmt, cancellable, callback, user_data);
+       conn = tracker_sparql_statement_get_connection (stmt);
+       tracker_bus_connection_perform_serialize_async (TRACKER_BUS_CONNECTION (conn),
+                                                       flags, format,
+                                                       tracker_sparql_statement_get_sparql (stmt),
+                                                       get_arguments (bus_stmt),
+                                                       cancellable,
+                                                       serialize_cb,
+                                                       task);
+}
+
+static GInputStream *
+tracker_bus_statement_serialize_finish (TrackerSparqlStatement  *stmt,
+                                        GAsyncResult            *res,
+                                        GError                 **error)
+{
+       return g_task_propagate_pointer (G_TASK (res), error);
+}
+
+static void
+tracker_bus_statement_class_init (TrackerBusStatementClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+       TrackerSparqlStatementClass *stmt_class =
+               TRACKER_SPARQL_STATEMENT_CLASS (klass);
+
+       object_class->finalize = tracker_bus_statement_finalize;
+
+       stmt_class->bind_boolean = tracker_bus_statement_bind_boolean;
+       stmt_class->bind_double = tracker_bus_statement_bind_double;
+       stmt_class->bind_int = tracker_bus_statement_bind_int;
+       stmt_class->bind_string = tracker_bus_statement_bind_string;
+       stmt_class->bind_datetime = tracker_bus_statement_bind_datetime;
+       stmt_class->clear_bindings = tracker_bus_statement_clear_bindings;
+       stmt_class->execute = tracker_bus_statement_execute;
+       stmt_class->execute_async = tracker_bus_statement_execute_async;
+       stmt_class->execute_finish = tracker_bus_statement_execute_finish;
+       stmt_class->serialize_async = tracker_bus_statement_serialize_async;
+       stmt_class->serialize_finish = tracker_bus_statement_serialize_finish;
+}
+
+static void
+tracker_bus_statement_init (TrackerBusStatement *stmt)
+{
+       stmt->arguments = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                                g_free,
+                                                (GDestroyNotify) g_variant_unref);
+}
+
+TrackerSparqlStatement *
+tracker_bus_statement_new (TrackerBusConnection *conn,
+                           const gchar          *query)
+{
+       return g_object_new (TRACKER_TYPE_BUS_STATEMENT,
+                            "connection", conn,
+                            "sparql", query,
+                            NULL);
+}
diff --git a/src/libtracker-sparql/bus/tracker-bus-statement.h 
b/src/libtracker-sparql/bus/tracker-bus-statement.h
new file mode 100644
index 000000000..31c7ea95d
--- /dev/null
+++ b/src/libtracker-sparql/bus/tracker-bus-statement.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2020, Red Hat Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ *
+ * Author: Carlos Garnacho <carlosg gnome org>
+ */
+
+#ifndef __TRACKER_BUS_STATEMENT_H__
+#define __TRACKER_BUS_STATEMENT_H__
+
+#include "tracker-bus.h"
+
+#include <libtracker-sparql/tracker-private.h>
+
+#define TRACKER_TYPE_BUS_STATEMENT (tracker_bus_statement_get_type ())
+G_DECLARE_FINAL_TYPE (TrackerBusStatement,
+                      tracker_bus_statement,
+                      TRACKER, BUS_STATEMENT,
+                      TrackerSparqlStatement)
+
+TrackerSparqlStatement * tracker_bus_statement_new (TrackerBusConnection *conn,
+                                                   const gchar          *sparql);
+
+#endif /* __TRACKER_BUS_STATEMENT_H__ */
diff --git a/src/libtracker-sparql/bus/tracker-bus.c b/src/libtracker-sparql/bus/tracker-bus.c
new file mode 100644
index 000000000..7dcf645c6
--- /dev/null
+++ b/src/libtracker-sparql/bus/tracker-bus.c
@@ -0,0 +1,1703 @@
+/*
+ * Copyright (C) 2010, Nokia <ivan frade nokia com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ */
+
+#include "config.h"
+
+#include "tracker-bus.h"
+
+#include <gio/gunixfdlist.h>
+#include <gio/gunixinputstream.h>
+#include <gio/gunixoutputstream.h>
+#include <libtracker-common/tracker-common.h>
+
+#include "tracker-bus-batch.h"
+#include "tracker-bus-cursor.h"
+#include "tracker-bus-statement.h"
+
+#define DBUS_PEER_IFACE "org.freedesktop.DBus.Peer"
+
+#define PORTAL_NAME "org.freedesktop.portal.Tracker"
+#define PORTAL_PATH "/org/freedesktop/portal/Tracker"
+#define PORTAL_IFACE "org.freedesktop.portal.Tracker"
+
+#define ENDPOINT_IFACE "org.freedesktop.Tracker3.Endpoint"
+
+#define DBUS_TIMEOUT 30000
+
+struct _TrackerBusConnection {
+       TrackerSparqlConnection parent_instance;
+
+       GDBusConnection *dbus_conn;
+       TrackerNamespaceManager *namespaces;
+       gchar *dbus_name;
+       gchar *object_path;
+       gboolean sandboxed;
+};
+
+enum {
+       PROP_0,
+       PROP_BUS_NAME,
+       PROP_BUS_OBJECT_PATH,
+       PROP_BUS_CONNECTION,
+       N_PROPS
+};
+
+static GParamSpec *props[N_PROPS] = { 0, };
+
+typedef struct {
+       GMainLoop *loop;
+       gpointer retval;
+       GError *error;
+} AsyncData;
+
+typedef struct {
+       struct {
+               GError *error;
+               gboolean finished;
+       } dbus, splice;
+} DeserializeTaskData;
+
+static void tracker_bus_connection_async_initable_iface_init (GAsyncInitableIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (TrackerBusConnection, tracker_bus_connection,
+                         TRACKER_TYPE_SPARQL_CONNECTION,
+                         G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE,
+                                                tracker_bus_connection_async_initable_iface_init))
+
+static GDBusMessage *
+create_portal_create_session_message (TrackerBusConnection *conn)
+{
+       GDBusMessage *message;
+       gchar *dbus_uri;
+       const gchar *object_path;
+
+       object_path = conn->object_path;
+       if (g_strcmp0 (object_path, "/org/freedesktop/Tracker3/Endpoint") == 0)
+               object_path = NULL;
+
+       dbus_uri = tracker_util_build_dbus_uri (G_BUS_TYPE_SESSION,
+                                               conn->dbus_name,
+                                               object_path);
+       message = g_dbus_message_new_method_call (PORTAL_NAME,
+                                                 PORTAL_PATH,
+                                                 PORTAL_IFACE,
+                                                 "CreateSession");
+       g_dbus_message_set_body (message, g_variant_new ("(s)", dbus_uri));
+       g_free (dbus_uri);
+
+       return message;
+}
+
+static GDBusMessage *
+create_portal_close_session_message (TrackerBusConnection *bus)
+{
+       GDBusMessage *message;
+
+       message = g_dbus_message_new_method_call (PORTAL_NAME,
+                                                 PORTAL_PATH,
+                                                 PORTAL_IFACE,
+                                                 "CloseSession");
+       g_dbus_message_set_body (message,
+                                g_variant_new ("(o)", bus->object_path));
+
+       return message;
+}
+
+static GDBusMessage *
+create_query_message (TrackerBusConnection *conn,
+                     const gchar          *sparql,
+                     GVariant             *arguments,
+                     GUnixFDList          *fd_list,
+                     int                   fd_idx)
+{
+       GDBusMessage *message;
+       GVariant *body;
+
+       if (!arguments)
+               arguments = g_variant_new ("a{sv}", NULL);
+
+       message = g_dbus_message_new_method_call (conn->dbus_name,
+                                                 conn->object_path,
+                                                 ENDPOINT_IFACE,
+                                                 "Query");
+       body = g_variant_new ("(sh@a{sv})", sparql, fd_idx, arguments);
+       g_dbus_message_set_body (message, body);
+       g_dbus_message_set_unix_fd_list (message, fd_list);
+
+       return message;
+}
+
+static GDBusMessage *
+create_serialize_message (TrackerBusConnection  *conn,
+                         const gchar           *sparql,
+                         TrackerSerializeFlags  flags,
+                         TrackerRdfFormat       format,
+                         GVariant              *arguments,
+                         GUnixFDList           *fd_list,
+                         int                    fd_idx)
+{
+       GDBusMessage *message;
+       GVariant *body;
+
+       if (!arguments)
+               arguments = g_variant_new ("a{sv}", NULL);
+
+       message = g_dbus_message_new_method_call (conn->dbus_name,
+                                                 conn->object_path,
+                                                 ENDPOINT_IFACE,
+                                                 "Serialize");
+       body = g_variant_new ("(shii@a{sv})",
+                             sparql, fd_idx,
+                             flags, format, arguments);
+       g_dbus_message_set_body (message, body);
+       g_dbus_message_set_unix_fd_list (message, fd_list);
+
+       return message;
+}
+
+static GDBusMessage *
+create_update_message (TrackerBusConnection *conn,
+                      const gchar          *request,
+                      GUnixFDList          *fd_list,
+                      int                   fd_idx)
+{
+       GDBusMessage *message;
+       GVariant *body;
+
+       message = g_dbus_message_new_method_call (conn->dbus_name,
+                                                 conn->object_path,
+                                                 ENDPOINT_IFACE,
+                                                 request);
+       body = g_variant_new ("(h)", fd_idx);
+       g_dbus_message_set_body (message, body);
+       g_dbus_message_set_unix_fd_list (message, fd_list);
+
+       return message;
+}
+
+static GDBusMessage *
+create_deserialize_message (TrackerBusConnection    *conn,
+                           TrackerDeserializeFlags  flags,
+                           TrackerRdfFormat         format,
+                           const gchar             *default_graph,
+                           GUnixFDList             *fd_list,
+                           int                      fd_idx)
+{
+       GDBusMessage *message;
+       GVariant *body;
+
+       message = g_dbus_message_new_method_call (conn->dbus_name,
+                                                 conn->object_path,
+                                                 ENDPOINT_IFACE,
+                                                 "Deserialize");
+       body = g_variant_new ("(hiisa{sv})",
+                             fd_idx, flags, format,
+                             default_graph ? default_graph : "",
+                             NULL);
+       g_dbus_message_set_body (message, body);
+       g_dbus_message_set_unix_fd_list (message, fd_list);
+
+       return message;
+}
+
+static gboolean
+write_sparql_query (GOutputStream  *ostream,
+                   const gchar    *query,
+                   GError        **error)
+{
+       GDataOutputStream *data;
+       int len;
+
+       len = strlen (query);
+       data = g_data_output_stream_new (ostream);
+       g_data_output_stream_set_byte_order (data, G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN);
+       if (!g_data_output_stream_put_int32 (data, len, NULL, error))
+               goto error;
+       if (!g_data_output_stream_put_string (data, query, NULL, error))
+               goto error;
+
+       g_object_unref (data);
+       return TRUE;
+ error:
+       g_object_unref (data);
+       return FALSE;
+}
+
+static gboolean
+write_sparql_queries (GOutputStream  *ostream,
+                     const gchar   **queries,
+                     gint            n_queries,
+                     GError        **error)
+{
+       GDataOutputStream *data;
+       int len, i;
+
+       data = g_data_output_stream_new (ostream);
+       g_data_output_stream_set_byte_order (data, G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN);
+
+       if (!g_data_output_stream_put_int32 (data, n_queries, NULL, error))
+               goto error;
+
+       for (i = 0; i < n_queries; i++) {
+               len = strlen (queries[i]);
+               if (!g_data_output_stream_put_int32 (data, len, NULL, error))
+                       goto error;
+               if (!g_data_output_stream_put_string (data, queries[i],
+                                                     NULL, error))
+                       goto error;
+       }
+
+       g_output_stream_close (G_OUTPUT_STREAM (data), NULL, NULL);
+       g_object_unref (data);
+       return TRUE;
+ error:
+       g_object_unref (data);
+       return FALSE;
+}
+
+static void
+query_namespaces_cb (GObject      *source,
+                     GAsyncResult *res,
+                     gpointer      user_data)
+{
+       TrackerBusConnection *bus = TRACKER_BUS_CONNECTION (source);
+       TrackerSparqlCursor *cursor;
+       GError *error = NULL;
+       GTask *task = user_data;
+
+       cursor = tracker_sparql_connection_query_finish (TRACKER_SPARQL_CONNECTION (source),
+                                                        res, &error);
+       if (cursor) {
+               bus->namespaces = tracker_namespace_manager_new ();
+
+               while (tracker_sparql_cursor_next (cursor, NULL, NULL)) {
+                       const gchar *prefix, *uri;
+
+                       prefix = tracker_sparql_cursor_get_string (cursor, 0, NULL);
+                       uri = tracker_sparql_cursor_get_string (cursor, 1, NULL);
+
+                       tracker_namespace_manager_add_prefix (bus->namespaces,
+                                                             prefix, uri);
+               }
+
+               tracker_namespace_manager_seal (bus->namespaces);
+               tracker_sparql_cursor_close (cursor);
+               g_task_return_boolean (task, TRUE);
+               g_object_unref (cursor);
+       } else {
+               g_task_return_error (task, error);
+       }
+
+       g_object_unref (task);
+}
+
+static void
+init_namespaces (TrackerBusConnection *conn,
+                 GTask                *task)
+{
+       tracker_sparql_connection_query_async (TRACKER_SPARQL_CONNECTION (conn),
+                                              "SELECT ?prefix ?name { ?name nrl:prefix ?prefix }",
+                                              NULL,
+                                              query_namespaces_cb,
+                                              task);
+}
+
+static void
+create_portal_session_cb (GObject      *source,
+                          GAsyncResult *res,
+                          gpointer      user_data)
+{
+       TrackerBusConnection *bus;
+       GTask *task = user_data;
+       GDBusMessage *reply;
+       GError *error = NULL;
+       GVariant *body;
+
+       bus = g_task_get_source_object (task);
+       reply = g_dbus_connection_send_message_with_reply_finish (G_DBUS_CONNECTION (source),
+                                                                 res, &error);
+
+       if (reply && !g_dbus_message_to_gerror (reply, &error)) {
+               body = g_dbus_message_get_body (reply);
+
+               /* We have now access through the portal, replace bus name/path */
+               bus->sandboxed = TRUE;
+               g_clear_pointer (&bus->object_path, g_free);
+               g_variant_get_child (body, 0, "o", &bus->object_path);
+               g_clear_pointer (&bus->dbus_name, g_free);
+               bus->dbus_name = g_strdup (PORTAL_NAME);
+
+               init_namespaces (bus, task);
+       } else {
+               g_task_return_error (task, error);
+               g_object_unref (task);
+       }
+
+       g_clear_object (&reply);
+}
+
+static void
+init_sandbox (TrackerBusConnection *conn,
+              GTask                *task)
+{
+       GDBusMessage *message;
+
+       /* We are in a flatpak sandbox, check going through the portal */
+       message = create_portal_create_session_message (conn);
+       g_dbus_connection_send_message_with_reply (conn->dbus_conn,
+                                                  message,
+                                                  G_DBUS_SEND_MESSAGE_FLAGS_NONE,
+                                                  DBUS_TIMEOUT,
+                                                  NULL,
+                                                  g_task_get_cancellable (task),
+                                                  create_portal_session_cb,
+                                                  task);
+       g_object_unref (message);
+}
+
+static void
+ping_peer_cb (GObject      *source,
+              GAsyncResult *res,
+              gpointer      user_data)
+{
+       TrackerBusConnection *bus;
+       GTask *task = user_data;
+       GError *error = NULL;
+       GDBusMessage *reply;
+
+       bus = g_task_get_source_object (task);
+       reply = g_dbus_connection_send_message_with_reply_finish (G_DBUS_CONNECTION (source),
+                                                                 res, &error);
+
+       if (!reply || g_dbus_message_to_gerror (reply, &error)) {
+               if (g_file_test ("/.flatpak-info", G_FILE_TEST_EXISTS)) {
+                       /* We do not see the endpoint directly but this is a sandbox.
+                        * Check for portal existence.
+                        */
+                       g_clear_error (&error);
+                       init_sandbox (bus, task);
+               } else {
+                       /* We do not see the endpoint, and this is not a sandboxed situation */
+                       g_dbus_error_strip_remote_error (error);
+                       g_task_return_error (task, error);
+                       g_object_unref (task);
+               }
+       } else {
+               init_namespaces (bus, task);
+       }
+
+       g_clear_object (&reply);
+}
+
+static void
+ping_peer (TrackerBusConnection *bus,
+          GTask                *task)
+{
+       /* If this environment variable is present, we always go via the portal */
+       if (g_getenv ("TRACKER_TEST_PORTAL_FLATPAK_INFO") == NULL) {
+               GDBusMessage *message;
+
+               message = g_dbus_message_new_method_call (bus->dbus_name,
+                                                         bus->object_path,
+                                                         DBUS_PEER_IFACE,
+                                                         "Ping");
+               g_dbus_connection_send_message_with_reply (bus->dbus_conn,
+                                                          message,
+                                                          G_DBUS_SEND_MESSAGE_FLAGS_NONE,
+                                                          DBUS_TIMEOUT,
+                                                          NULL,
+                                                          g_task_get_cancellable (task),
+                                                          ping_peer_cb,
+                                                          task);
+               g_object_unref (message);
+       } else {
+               init_sandbox (bus, task);
+       }
+}
+
+static void
+get_bus_cb (GObject      *source,
+           GAsyncResult *res,
+           gpointer      user_data)
+{
+       TrackerBusConnection *bus;
+       GTask *task = user_data;
+       GError *error = NULL;
+
+       bus = g_task_get_source_object (task);
+       bus->dbus_conn = g_bus_get_finish (res, &error);
+
+       if (bus->dbus_conn) {
+               ping_peer (bus, task);
+       } else {
+               g_task_return_error (task, error);
+               g_object_unref (task);
+       }
+}
+
+static void
+tracker_bus_connection_async_initable_init_async (GAsyncInitable      *async_initable,
+                                                  gint                 priority,
+                                                  GCancellable        *cancellable,
+                                                  GAsyncReadyCallback  callback,
+                                                  gpointer             user_data)
+{
+       TrackerBusConnection *bus;
+       GTask *task;
+
+       bus = TRACKER_BUS_CONNECTION (async_initable);
+       task = g_task_new (async_initable, cancellable, callback, user_data);
+       g_task_set_priority (task, priority);
+
+       if (!bus->dbus_conn)
+               g_bus_get (G_BUS_TYPE_SESSION, cancellable, get_bus_cb, task);
+       else
+               ping_peer (bus, task);
+}
+
+static gboolean
+tracker_bus_connection_async_initable_init_finish (GAsyncInitable  *async_initable,
+                                                   GAsyncResult    *res,
+                                                   GError         **error)
+{
+       return g_task_propagate_boolean (G_TASK (res), error);
+}
+
+static void
+tracker_bus_connection_async_initable_iface_init (GAsyncInitableIface *iface)
+{
+       iface->init_async = tracker_bus_connection_async_initable_init_async;
+       iface->init_finish = tracker_bus_connection_async_initable_init_finish;
+}
+
+static void
+tracker_bus_connection_finalize (GObject *object)
+{
+       TrackerBusConnection *bus = TRACKER_BUS_CONNECTION (object);
+
+       g_clear_object (&bus->dbus_conn);
+       g_clear_pointer (&bus->dbus_name, g_free);
+       g_clear_pointer (&bus->object_path, g_free);
+       g_clear_object (&bus->namespaces);
+
+       G_OBJECT_CLASS (tracker_bus_connection_parent_class)->finalize (object);
+}
+
+static void
+tracker_bus_connection_set_property (GObject      *object,
+                                     guint         prop_id,
+                                     const GValue *value,
+                                     GParamSpec   *pspec)
+{
+       TrackerBusConnection *bus = TRACKER_BUS_CONNECTION (object);
+
+       switch (prop_id) {
+       case PROP_BUS_NAME:
+               bus->dbus_name = g_value_dup_string (value);
+               break;
+       case PROP_BUS_OBJECT_PATH:
+               bus->object_path = g_value_dup_string (value);
+               break;
+       case PROP_BUS_CONNECTION:
+               bus->dbus_conn = g_value_dup_object (value);
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+               break;
+       }
+}
+
+static void
+tracker_bus_connection_get_property (GObject    *object,
+                                     guint       prop_id,
+                                     GValue     *value,
+                                     GParamSpec *pspec)
+{
+       TrackerBusConnection *bus = TRACKER_BUS_CONNECTION (object);
+
+       switch (prop_id) {
+       case PROP_BUS_NAME:
+               g_value_set_string (value, bus->dbus_name);
+               break;
+       case PROP_BUS_OBJECT_PATH:
+               g_value_set_string (value, bus->object_path);
+               break;
+       case PROP_BUS_CONNECTION:
+               g_value_set_object (value, bus->dbus_conn);
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+               break;
+       }
+}
+
+static gboolean
+create_pipe (int     *input,
+             int     *output,
+             GError **error)
+{
+       int fds[2];
+
+       if (pipe (fds) < 0) {
+               g_set_error (error,
+                            G_IO_ERROR,
+                            g_io_error_from_errno (errno),
+                            "Pipe creation failed: %m");
+               return FALSE;
+       }
+
+       *input = fds[0];
+       *output = fds[1];
+       return TRUE;
+}
+
+static gboolean
+create_pipe_for_write (GOutputStream **ostream,
+                      GUnixFDList   **fd_list,
+                      int            *fd_idx,
+                      GError        **error)
+{
+       int input, output, idx;
+       GUnixFDList *list;
+
+       if (!create_pipe (&input, &output, error))
+               return FALSE;
+
+       list = g_unix_fd_list_new ();
+       idx = g_unix_fd_list_append (list, input, error);
+       close (input);
+
+       if (idx < 0) {
+               g_object_unref (list);
+               close (output);
+               return FALSE;
+       }
+
+       *fd_list = list;
+       *fd_idx = idx;
+       *ostream = g_unix_output_stream_new (output, TRUE);
+
+       return TRUE;
+}
+
+static gboolean
+create_pipe_for_read (GInputStream **istream,
+                     GUnixFDList   **fd_list,
+                     int            *fd_idx,
+                     GError        **error)
+{
+       int input, output, idx;
+       GUnixFDList *list;
+
+       if (!create_pipe (&input, &output, error))
+               return FALSE;
+
+       list = g_unix_fd_list_new ();
+       idx = g_unix_fd_list_append (list, output, error);
+       close (output);
+
+       if (idx < 0) {
+               g_object_unref (list);
+               close (input);
+               return FALSE;
+       }
+
+       *fd_list = list;
+       *fd_idx = idx;
+       *istream = g_unix_input_stream_new (input, TRUE);
+
+       return TRUE;
+}
+
+static TrackerSparqlCursor *
+tracker_bus_connection_query (TrackerSparqlConnection  *self,
+                              const gchar              *sparql,
+                              GCancellable             *cancellable,
+                              GError                  **error)
+{
+       return tracker_bus_connection_perform_query (TRACKER_BUS_CONNECTION (self),
+                                                    sparql, NULL,
+                                                    cancellable, error);
+}
+
+static void
+query_async_cb (GObject      *source,
+                GAsyncResult *res,
+                gpointer      user_data)
+{
+       TrackerSparqlCursor *cursor;
+       GTask *task = user_data;
+       GError *error = NULL;
+
+       cursor = tracker_bus_connection_perform_query_finish (TRACKER_BUS_CONNECTION (source),
+                                                             res, &error);
+
+       if (cursor)
+               g_task_return_pointer (task, cursor, g_object_unref);
+       else
+               g_task_return_error (task, error);
+
+       g_object_unref (task);
+}
+
+static void
+tracker_bus_connection_query_async (TrackerSparqlConnection *self,
+                                    const gchar             *sparql,
+                                    GCancellable            *cancellable,
+                                    GAsyncReadyCallback      callback,
+                                    gpointer                 user_data)
+{
+       GTask *task;
+
+       task = g_task_new (self, cancellable, callback, user_data);
+       tracker_bus_connection_perform_query_async (TRACKER_BUS_CONNECTION (self),
+                                                   sparql,
+                                                   NULL,
+                                                   cancellable,
+                                                   query_async_cb,
+                                                   task);
+}
+
+static TrackerSparqlCursor *
+tracker_bus_connection_query_finish (TrackerSparqlConnection  *self,
+                                     GAsyncResult             *res,
+                                     GError                  **error)
+{
+       return g_task_propagate_pointer (G_TASK (res), error);
+}
+
+static TrackerSparqlStatement *
+tracker_bus_connection_query_statement (TrackerSparqlConnection  *self,
+                                        const gchar              *query,
+                                        GCancellable             *cancellable,
+                                        GError                  **error)
+{
+       return tracker_bus_statement_new (TRACKER_BUS_CONNECTION (self), query);
+}
+
+static void
+update_dbus_call_cb (GObject      *source,
+                    GAsyncResult *res,
+                    gpointer      user_data)
+{
+       GTask *task = user_data;
+       GDBusMessage *reply;
+       GError *error = NULL;
+
+       reply = g_dbus_connection_send_message_with_reply_finish (G_DBUS_CONNECTION (source),
+                                                                 res, &error);
+       if (reply && !g_dbus_message_to_gerror (reply, &error)) {
+               GVariant *body;
+
+               body = g_dbus_message_get_body (reply);
+               g_task_return_pointer (task,
+                                      body ? g_variant_ref (body) : NULL,
+                                      (GDestroyNotify) g_variant_unref);
+       } else {
+               g_dbus_error_strip_remote_error (error);
+               g_task_return_error (task, error);
+       }
+
+       g_object_unref (task);
+       g_clear_object (&reply);
+}
+
+static void
+perform_update_async (TrackerBusConnection *bus,
+                     const gchar          *request,
+                     GUnixFDList          *fd_list,
+                     int                   fd_idx,
+                     GCancellable         *cancellable,
+                     GAsyncReadyCallback   callback,
+                     gpointer              user_data)
+{
+       GDBusMessage *message;
+       GTask *task;
+
+       task = g_task_new (bus, cancellable, callback, user_data);
+       message = create_update_message (bus, request, fd_list, fd_idx);
+       g_dbus_connection_send_message_with_reply (bus->dbus_conn,
+                                                  message,
+                                                  G_DBUS_SEND_MESSAGE_FLAGS_NONE,
+                                                  G_MAXINT,
+                                                  NULL,
+                                                  cancellable,
+                                                  update_dbus_call_cb,
+                                                  task);
+       g_object_unref (message);
+}
+
+static GVariant *
+perform_update_finish (TrackerBusConnection  *conn,
+                      GAsyncResult          *res,
+                      GError               **error)
+{
+       return g_task_propagate_pointer (G_TASK (res), error);
+}
+
+static void
+update_sync_cb (GObject      *source,
+               GAsyncResult *res,
+               gpointer      user_data)
+{
+       AsyncData *data = user_data;
+
+       tracker_sparql_connection_update_finish (TRACKER_SPARQL_CONNECTION (source),
+                                                res, &data->error);
+       g_main_loop_quit (data->loop);
+}
+
+static void
+tracker_bus_connection_update (TrackerSparqlConnection  *self,
+                               const gchar              *sparql,
+                               GCancellable             *cancellable,
+                               GError                  **error)
+{
+       GMainContext *context;
+       AsyncData data = { 0, };
+
+       context = g_main_context_new ();
+       data.loop = g_main_loop_new (context, FALSE);
+       g_main_context_push_thread_default (context);
+
+       tracker_sparql_connection_update_async (self,
+                                               sparql,
+                                               cancellable,
+                                               update_sync_cb,
+                                               &data);
+       g_main_loop_run (data.loop);
+
+       g_main_context_pop_thread_default (context);
+
+       g_main_loop_unref (data.loop);
+       g_main_context_unref (context);
+
+       if (data.error)
+               g_propagate_error (error, data.error);
+}
+
+static void
+update_cb (GObject      *object,
+          GAsyncResult *res,
+          gpointer      user_data)
+{
+       GTask *task = user_data;
+       GError *error = NULL;
+       GVariant *retval;
+
+       retval = perform_update_finish (TRACKER_BUS_CONNECTION (object),
+                                       res, &error);
+       if (error)
+               g_task_return_error (task, error);
+       else
+               g_task_return_pointer (task, retval, (GDestroyNotify) g_variant_unref);
+
+       g_object_unref (task);
+}
+
+static void
+tracker_bus_connection_update_async (TrackerSparqlConnection *self,
+                                     const gchar             *sparql,
+                                     GCancellable            *cancellable,
+                                     GAsyncReadyCallback      callback,
+                                     gpointer                 user_data)
+{
+       GUnixFDList *fd_list;
+       GOutputStream *ostream;
+       GError *error = NULL;
+       GTask *task;
+       int fd_idx;
+
+       task = g_task_new (self, cancellable, callback, user_data);
+
+       if (!create_pipe_for_write (&ostream, &fd_list, &fd_idx, &error)) {
+               g_task_return_error (task, error);
+               g_object_unref (task);
+               return;
+       }
+
+       perform_update_async (TRACKER_BUS_CONNECTION (self),
+                             "Update",
+                             fd_list, fd_idx,
+                             cancellable,
+                             update_cb,
+                             task);
+
+       write_sparql_query (ostream, sparql, NULL);
+       g_output_stream_close (ostream, NULL, NULL);
+       g_object_unref (ostream);
+       g_object_unref (fd_list);
+}
+
+static void
+tracker_bus_connection_update_finish (TrackerSparqlConnection  *self,
+                                      GAsyncResult             *res,
+                                      GError                  **error)
+{
+       GVariant *retval;
+
+       retval = g_task_propagate_pointer (G_TASK (res), error);
+       g_clear_pointer (&retval, g_variant_unref);
+}
+
+static void
+tracker_bus_connection_update_array_async (TrackerSparqlConnection  *self,
+                                           gchar                   **updates,
+                                           gint                      n_updates,
+                                           GCancellable             *cancellable,
+                                           GAsyncReadyCallback       callback,
+                                           gpointer                  user_data)
+{
+       GUnixFDList *fd_list;
+       GOutputStream *ostream;
+       GError *error = NULL;
+       GTask *task;
+       int fd_idx;
+
+       task = g_task_new (self, cancellable, callback, user_data);
+
+       if (n_updates == 0) {
+               g_task_return_pointer (task, NULL, NULL);
+               g_object_unref (task);
+               return;
+       }
+
+       if (!create_pipe_for_write (&ostream, &fd_list, &fd_idx, &error)) {
+               g_task_return_error (task, error);
+               g_object_unref (task);
+               return;
+       }
+
+       perform_update_async (TRACKER_BUS_CONNECTION (self),
+                             "UpdateArray",
+                             fd_list, fd_idx,
+                             cancellable,
+                             update_cb,
+                             task);
+
+       write_sparql_queries (ostream, (const gchar **) updates, n_updates, NULL);
+       g_output_stream_close (ostream, NULL, NULL);
+       g_object_unref (ostream);
+       g_object_unref (fd_list);
+}
+
+static gboolean
+tracker_bus_connection_update_array_finish (TrackerSparqlConnection  *self,
+                                            GAsyncResult             *res,
+                                            GError                  **error)
+{
+       GError *inner_error = NULL;
+       GVariant *retval;
+
+       retval = g_task_propagate_pointer (G_TASK (res), &inner_error);
+       g_clear_pointer (&retval, g_variant_unref);
+
+       if (inner_error) {
+               g_propagate_error (error, inner_error);
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+static void
+update_blank_sync_cb (GObject      *source,
+                     GAsyncResult *res,
+                     gpointer      user_data)
+{
+       AsyncData *data = user_data;
+
+       data->retval =
+               tracker_sparql_connection_update_blank_finish (TRACKER_SPARQL_CONNECTION (source),
+                                                              res, &data->error);
+       g_main_loop_quit (data->loop);
+}
+
+static GVariant *
+tracker_bus_connection_update_blank (TrackerSparqlConnection  *self,
+                                     const gchar              *sparql,
+                                     GCancellable             *cancellable,
+                                     GError                  **error)
+{
+       GMainContext *context;
+       AsyncData data = { 0, };
+
+       context = g_main_context_new ();
+       data.loop = g_main_loop_new (context, FALSE);
+       g_main_context_push_thread_default (context);
+
+       tracker_sparql_connection_update_blank_async (self,
+                                                     sparql,
+                                                     cancellable,
+                                                     update_blank_sync_cb,
+                                                     &data);
+       g_main_loop_run (data.loop);
+
+       g_main_context_pop_thread_default (context);
+
+       g_main_loop_unref (data.loop);
+       g_main_context_unref (context);
+
+       if (data.error) {
+               g_propagate_error (error, data.error);
+               return NULL;
+       }
+
+       return data.retval;
+}
+
+static void
+tracker_bus_connection_update_blank_async (TrackerSparqlConnection *self,
+                                           const gchar             *sparql,
+                                           GCancellable            *cancellable,
+                                           GAsyncReadyCallback      callback,
+                                           gpointer                 user_data)
+{
+       GUnixFDList *fd_list;
+       GOutputStream *ostream;
+       GError *error = NULL;
+       GTask *task;
+       int fd_idx;
+
+       task = g_task_new (self, cancellable, callback, user_data);
+
+       if (!create_pipe_for_write (&ostream, &fd_list, &fd_idx, &error)) {
+               g_task_return_error (task, error);
+               g_object_unref (task);
+               return;
+       }
+
+       perform_update_async (TRACKER_BUS_CONNECTION (self),
+                             "UpdateBlank",
+                             fd_list, fd_idx,
+                             cancellable,
+                             update_cb,
+                             task);
+
+       write_sparql_query (ostream, sparql, NULL);
+       g_output_stream_close (ostream, NULL, NULL);
+       g_object_unref (ostream);
+       g_object_unref (fd_list);
+}
+
+static GVariant *
+tracker_bus_connection_update_blank_finish (TrackerSparqlConnection  *self,
+                                            GAsyncResult             *res,
+                                            GError                  **error)
+{
+       GVariant *retval;
+
+       retval = g_task_propagate_pointer (G_TASK (res), error);
+
+       if (retval) {
+               GVariant *child;
+
+               child = g_variant_get_child_value (retval, 0);
+               g_variant_unref (retval);
+               return child;
+       }
+
+       return NULL;
+}
+
+static TrackerNamespaceManager *
+tracker_bus_connection_get_namespace_manager (TrackerSparqlConnection *self)
+{
+       TrackerBusConnection *bus = TRACKER_BUS_CONNECTION (self);
+
+       return bus->namespaces;
+}
+
+static TrackerNotifier *
+tracker_bus_connection_create_notifier (TrackerSparqlConnection *self)
+{
+       TrackerBusConnection *bus = TRACKER_BUS_CONNECTION (self);
+       TrackerNotifier *notifier;
+
+       notifier = g_object_new (TRACKER_TYPE_NOTIFIER,
+                                "connection", self,
+                                NULL);
+
+       tracker_notifier_signal_subscribe (notifier,
+                                          bus->dbus_conn,
+                                          bus->dbus_name,
+                                          bus->object_path,
+                                          NULL);
+
+       return notifier;
+}
+
+static void
+tracker_bus_connection_close (TrackerSparqlConnection *self)
+{
+       TrackerBusConnection *bus = TRACKER_BUS_CONNECTION (self);
+
+       if (bus->sandboxed) {
+               GDBusMessage *message;
+
+               message = create_portal_close_session_message (bus);
+               g_dbus_connection_send_message (bus->dbus_conn,
+                                               message,
+                                               G_DBUS_SEND_MESSAGE_FLAGS_NONE,
+                                               NULL, NULL);
+               g_object_unref (message);
+       }
+}
+
+static void
+tracker_bus_connection_close_async (TrackerSparqlConnection *connection,
+                                    GCancellable            *cancellable,
+                                    GAsyncReadyCallback      callback,
+                                    gpointer                 user_data)
+{
+       TrackerBusConnection *bus = TRACKER_BUS_CONNECTION (connection);
+       GTask *task;
+
+       task = g_task_new (connection, cancellable, callback, user_data);
+
+       if (bus->sandboxed) {
+               GDBusMessage *message;
+               GError *error = NULL;
+
+               message = create_portal_close_session_message (bus);
+
+               if (!g_dbus_connection_send_message (bus->dbus_conn,
+                                                    message,
+                                                    G_DBUS_SEND_MESSAGE_FLAGS_NONE,
+                                                    NULL, &error))
+                       g_task_return_error (task, error);
+               else
+                       g_task_return_boolean (task, TRUE);
+
+               g_object_unref (message);
+       } else {
+               g_task_return_boolean (task, TRUE);
+       }
+
+       g_object_unref (task);
+}
+
+static gboolean
+tracker_bus_connection_close_finish (TrackerSparqlConnection  *connection,
+                                     GAsyncResult             *res,
+                                     GError                  **error)
+{
+       return g_task_propagate_boolean (G_TASK (res), error);
+}
+
+static gboolean
+tracker_bus_connection_update_resource (TrackerSparqlConnection  *self,
+                                        const gchar              *graph,
+                                        TrackerResource          *resource,
+                                        GCancellable             *cancellable,
+                                        GError                  **error)
+{
+       TrackerBatch *batch;
+       gboolean retval;
+
+       batch = tracker_sparql_connection_create_batch (self);
+       tracker_batch_add_resource (batch, graph, resource);
+       retval = tracker_batch_execute (batch, cancellable, error);
+       g_object_unref (batch);
+
+       return retval;
+}
+
+static void
+update_resource_cb (GObject      *source,
+                    GAsyncResult *res,
+                    gpointer      user_data)
+{
+       GTask *task = user_data;
+       GError *error = NULL;
+       gboolean retval;
+
+       retval = tracker_batch_execute_finish (TRACKER_BATCH (source),
+                                              res, &error);
+
+       if (!retval)
+               g_task_return_error (task, error);
+       else
+               g_task_return_boolean (task, retval);
+
+       g_object_unref (task);
+}
+
+static void
+tracker_bus_connection_update_resource_async (TrackerSparqlConnection *self,
+                                              const gchar             *graph,
+                                              TrackerResource         *resource,
+                                              GCancellable            *cancellable,
+                                              GAsyncReadyCallback      callback,
+                                              gpointer                 user_data)
+{
+       TrackerBatch *batch;
+       GTask *task;
+
+       task = g_task_new (self, cancellable, callback, user_data);
+
+       batch = tracker_sparql_connection_create_batch (self);
+       tracker_batch_add_resource (batch, graph, resource);
+       tracker_batch_execute_async (batch, cancellable, update_resource_cb, task);
+       g_object_unref (batch);
+}
+
+static gboolean
+tracker_bus_connection_update_resource_finish (TrackerSparqlConnection  *connection,
+                                               GAsyncResult             *res,
+                                               GError                  **error)
+{
+       return g_task_propagate_boolean (G_TASK (res), error);
+}
+
+static TrackerBatch *
+tracker_bus_connection_create_batch (TrackerSparqlConnection *connection)
+{
+       TrackerBusConnection *bus = TRACKER_BUS_CONNECTION (connection);
+
+       return tracker_bus_batch_new (bus);
+}
+
+static void
+perform_serialize_cb (GObject      *source,
+                     GAsyncResult *res,
+                     gpointer      user_data)
+{
+       GInputStream *istream;
+       GError *error = NULL;
+       GTask *task = user_data;
+
+       istream = tracker_bus_connection_perform_serialize_finish (TRACKER_BUS_CONNECTION (source),
+                                                                  res, &error);
+       if (istream)
+               g_task_return_pointer (task, istream, g_object_unref);
+       else
+               g_task_return_error (task, error);
+
+       g_object_unref (task);
+}
+
+static void
+tracker_bus_connection_serialize_async (TrackerSparqlConnection  *self,
+                                        TrackerSerializeFlags     flags,
+                                        TrackerRdfFormat          format,
+                                        const gchar              *query,
+                                        GCancellable             *cancellable,
+                                        GAsyncReadyCallback       callback,
+                                        gpointer                  user_data)
+{
+       GTask *task;
+
+       task = g_task_new (self, cancellable, callback, user_data);
+       tracker_bus_connection_perform_serialize_async (TRACKER_BUS_CONNECTION (self),
+                                                       flags, format, query, NULL,
+                                                       cancellable,
+                                                       perform_serialize_cb,
+                                                       task);
+}
+
+static GInputStream *
+tracker_bus_connection_serialize_finish (TrackerSparqlConnection  *connection,
+                                         GAsyncResult             *res,
+                                         GError                  **error)
+{
+       return g_task_propagate_pointer (G_TASK (res), error);
+}
+
+static void
+check_finish_deserialize (GTask *task)
+{
+       DeserializeTaskData *data;
+
+       data = g_task_get_task_data (task);
+
+       if (!data->dbus.finished || !data->splice.finished)
+               return;
+
+       if (data->dbus.error) {
+               g_dbus_error_strip_remote_error (data->dbus.error);
+               g_task_return_error (task, data->dbus.error);
+       } else if (data->splice.error) {
+               g_task_return_error (task, data->splice.error);
+       } else {
+               g_task_return_boolean (task, TRUE);
+       }
+}
+
+static void
+deserialize_cb (GObject      *source,
+               GAsyncResult *res,
+               gpointer      user_data)
+{
+       GDBusMessage *reply;
+       GTask *task = user_data;
+       DeserializeTaskData *data;
+       GError *error = NULL;
+
+       data = g_task_get_task_data (task);
+
+       reply = g_dbus_connection_send_message_with_reply_finish (G_DBUS_CONNECTION (source),
+                                                                 res, &error);
+       if (reply)
+               g_dbus_message_to_gerror (reply, &error);
+
+       g_clear_object (&reply);
+
+       data->dbus.finished = TRUE;
+       data->dbus.error = error;
+       check_finish_deserialize (task);
+}
+
+static void
+splice_cb (GObject      *source,
+          GAsyncResult *res,
+          gpointer      user_data)
+{
+       GTask *task = user_data;
+       DeserializeTaskData *data;
+       GError *error = NULL;
+
+       data = g_task_get_task_data (task);
+
+       g_output_stream_splice_finish (G_OUTPUT_STREAM (source),
+                                      res, &error);
+       data->splice.finished = TRUE;
+       data->splice.error = error;
+       check_finish_deserialize (task);
+}
+
+static void
+deserialize_task_data_free (gpointer data)
+{
+       DeserializeTaskData *task_data = data;
+
+       g_clear_error (&task_data->dbus.error);
+       g_clear_error (&task_data->splice.error);
+       g_free (task_data);
+}
+
+static void
+tracker_bus_connection_deserialize_async (TrackerSparqlConnection *self,
+                                          TrackerDeserializeFlags  flags,
+                                          TrackerRdfFormat         format,
+                                          const gchar             *default_graph,
+                                          GInputStream            *istream,
+                                          GCancellable            *cancellable,
+                                          GAsyncReadyCallback      callback,
+                                          gpointer                 user_data)
+{
+       TrackerBusConnection *bus = TRACKER_BUS_CONNECTION (self);
+       GDBusMessage *message;
+       GUnixFDList *fd_list;
+       GOutputStream *ostream;
+       DeserializeTaskData *data;
+       GError *error = NULL;
+       GTask *task;
+       int fd_idx;
+
+       task = g_task_new (self, cancellable, callback, user_data);
+
+       data = g_new0 (DeserializeTaskData, 1);
+       g_task_set_task_data (task, data, deserialize_task_data_free);
+
+       if (!create_pipe_for_write (&ostream, &fd_list, &fd_idx, &error)) {
+               g_task_return_error (task, error);
+               g_object_unref (task);
+               return;
+       }
+
+       message = create_deserialize_message (bus, flags, format,
+                                             default_graph,
+                                             fd_list, fd_idx);
+
+       g_dbus_connection_send_message_with_reply (bus->dbus_conn,
+                                                  message,
+                                                  G_DBUS_SEND_MESSAGE_FLAGS_NONE,
+                                                  G_MAXINT,
+                                                  NULL,
+                                                  cancellable,
+                                                  deserialize_cb,
+                                                  task);
+       g_output_stream_splice_async (ostream, istream,
+                                     G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE |
+                                     G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
+                                     G_PRIORITY_DEFAULT,
+                                     cancellable,
+                                     splice_cb,
+                                     task);
+
+       g_object_unref (message);
+       g_object_unref (fd_list);
+       g_object_unref (ostream);
+}
+
+static gboolean
+tracker_bus_connection_deserialize_finish (TrackerSparqlConnection  *connection,
+                                           GAsyncResult             *res,
+                                           GError                  **error)
+{
+       return g_task_propagate_boolean (G_TASK (res), error);
+}
+
+static void
+tracker_bus_connection_class_init (TrackerBusConnectionClass *klass)
+{
+       TrackerSparqlConnectionClass *sparql_connection_class;
+       GObjectClass *object_class;
+
+       object_class = G_OBJECT_CLASS (klass);
+       sparql_connection_class = TRACKER_SPARQL_CONNECTION_CLASS (klass);
+
+       object_class->finalize = tracker_bus_connection_finalize;
+       object_class->set_property = tracker_bus_connection_set_property;
+       object_class->get_property = tracker_bus_connection_get_property;
+
+       sparql_connection_class->query = tracker_bus_connection_query;
+       sparql_connection_class->query_async = tracker_bus_connection_query_async;
+       sparql_connection_class->query_finish = tracker_bus_connection_query_finish;
+       sparql_connection_class->query_statement = tracker_bus_connection_query_statement;
+       sparql_connection_class->update = tracker_bus_connection_update;
+       sparql_connection_class->update_async = tracker_bus_connection_update_async;
+       sparql_connection_class->update_finish = tracker_bus_connection_update_finish;
+       sparql_connection_class->update_array_async = tracker_bus_connection_update_array_async;
+       sparql_connection_class->update_array_finish = tracker_bus_connection_update_array_finish;
+       sparql_connection_class->update_blank = tracker_bus_connection_update_blank;
+       sparql_connection_class->update_blank_async = tracker_bus_connection_update_blank_async;
+       sparql_connection_class->update_blank_finish = tracker_bus_connection_update_blank_finish;
+       sparql_connection_class->get_namespace_manager = tracker_bus_connection_get_namespace_manager;
+       sparql_connection_class->create_notifier = tracker_bus_connection_create_notifier;
+       sparql_connection_class->close = tracker_bus_connection_close;
+       sparql_connection_class->close_async = tracker_bus_connection_close_async;
+       sparql_connection_class->close_finish = tracker_bus_connection_close_finish;
+       sparql_connection_class->update_resource = tracker_bus_connection_update_resource;
+       sparql_connection_class->update_resource_async = tracker_bus_connection_update_resource_async;
+       sparql_connection_class->update_resource_finish = tracker_bus_connection_update_resource_finish;
+       sparql_connection_class->create_batch = tracker_bus_connection_create_batch;
+       sparql_connection_class->serialize_async = tracker_bus_connection_serialize_async;
+       sparql_connection_class->serialize_finish = tracker_bus_connection_serialize_finish;
+       sparql_connection_class->deserialize_async = tracker_bus_connection_deserialize_async;
+       sparql_connection_class->deserialize_finish = tracker_bus_connection_deserialize_finish;
+
+       props[PROP_BUS_NAME] =
+               g_param_spec_string ("bus-name",
+                                    "Bus name",
+                                    "Bus name",
+                                    NULL,
+                                    G_PARAM_READWRITE |
+                                    G_PARAM_STATIC_STRINGS |
+                                    G_PARAM_CONSTRUCT_ONLY);
+       props[PROP_BUS_OBJECT_PATH] =
+               g_param_spec_string ("bus-object-path",
+                                    "Bus object path",
+                                    "Bus object path",
+                                    NULL,
+                                    G_PARAM_READWRITE |
+                                    G_PARAM_STATIC_STRINGS |
+                                    G_PARAM_CONSTRUCT_ONLY);
+       props[PROP_BUS_CONNECTION] =
+               g_param_spec_object ("bus-connection",
+                                    "Bus connection",
+                                    "Bus connection",
+                                    G_TYPE_DBUS_CONNECTION,
+                                    G_PARAM_READWRITE |
+                                    G_PARAM_STATIC_STRINGS |
+                                    G_PARAM_CONSTRUCT_ONLY);
+
+       g_object_class_install_properties (object_class, N_PROPS, props);
+}
+
+static void
+tracker_bus_connection_init (TrackerBusConnection *conn)
+{
+}
+
+static void
+bus_new_cb (GObject      *source,
+            GAsyncResult *res,
+            gpointer      user_data)
+{
+       AsyncData *data = user_data;
+
+       data->retval = tracker_bus_connection_new_finish (res, &data->error);
+       g_main_loop_quit (data->loop);
+}
+
+TrackerSparqlConnection *
+tracker_bus_connection_new (const gchar      *service,
+                            const gchar      *object_path,
+                            GDBusConnection  *conn,
+                            GError          **error)
+{
+       GMainContext *context;
+       AsyncData data = { 0, };
+
+       context = g_main_context_new ();
+       data.loop = g_main_loop_new (context, FALSE);
+       g_main_context_push_thread_default (context);
+
+       tracker_bus_connection_new_async (service,
+                                         object_path,
+                                         conn,
+                                         NULL,
+                                         bus_new_cb,
+                                         &data);
+
+       g_main_loop_run (data.loop);
+
+       g_main_context_pop_thread_default (context);
+
+       g_main_loop_unref (data.loop);
+       g_main_context_unref (context);
+
+       if (data.error) {
+               g_propagate_error (error, data.error);
+               return NULL;
+       }
+
+       return TRACKER_SPARQL_CONNECTION (data.retval);
+}
+
+void
+tracker_bus_connection_new_async (const gchar         *service,
+                                  const gchar         *object_path,
+                                  GDBusConnection     *conn,
+                                  GCancellable        *cancellable,
+                                  GAsyncReadyCallback  cb,
+                                  gpointer             user_data)
+{
+       g_async_initable_new_async (TRACKER_TYPE_BUS_CONNECTION,
+                                   G_PRIORITY_DEFAULT,
+                                   cancellable,
+                                   cb,
+                                   user_data,
+                                   "bus-name", service,
+                                   "bus-object-path", object_path,
+                                   "bus-connection", conn,
+                                   NULL);
+}
+
+TrackerSparqlConnection *
+tracker_bus_connection_new_finish (GAsyncResult  *res,
+                                   GError       **error)
+{
+       GAsyncInitable *initable;
+
+       initable = g_task_get_source_object (G_TASK (res));
+
+       return TRACKER_SPARQL_CONNECTION (g_async_initable_new_finish (initable,
+                                                                      res,
+                                                                      error));
+}
+
+static void
+query_dbus_call_cb (GObject      *source,
+                    GAsyncResult *res,
+                    gpointer      user_data)
+{
+       GTask *task = user_data;
+       GDBusMessage *reply;
+       GError *error = NULL;
+
+       reply = g_dbus_connection_send_message_with_reply_finish (G_DBUS_CONNECTION (source),
+                                                                 res, &error);
+       if (reply && !g_dbus_message_to_gerror (reply, &error)) {
+               TrackerSparqlCursor *cursor;
+               GVariant *body;
+               GInputStream *istream;
+
+               body = g_dbus_message_get_body (reply);
+               istream = g_task_get_task_data (task);
+               cursor = tracker_bus_cursor_new (istream, g_variant_get_child_value (body, 0));
+               g_task_return_pointer (task, cursor, g_object_unref);
+       } else {
+               g_dbus_error_strip_remote_error (error);
+               g_task_return_error (task, error);
+       }
+
+       g_object_unref (task);
+       g_clear_object (&reply);
+}
+
+void
+tracker_bus_connection_perform_query_async (TrackerBusConnection *bus,
+                                           const gchar          *sparql,
+                                           GVariant             *arguments,
+                                           GCancellable         *cancellable,
+                                           GAsyncReadyCallback   callback,
+                                           gpointer              user_data)
+{
+       GDBusMessage *message;
+       GUnixFDList *fd_list;
+       GInputStream *istream;
+       GError *error = NULL;
+       GTask *task;
+       int fd_idx;
+
+       task = g_task_new (bus, cancellable, callback, user_data);
+
+       if (!create_pipe_for_read (&istream, &fd_list, &fd_idx, &error)) {
+               g_task_return_error (task, error);
+               g_object_unref (task);
+               return;
+       }
+
+       g_task_set_task_data (task, istream, g_object_unref);
+
+       message = create_query_message (bus, sparql, arguments,
+                                       fd_list, fd_idx);
+       g_dbus_connection_send_message_with_reply (bus->dbus_conn,
+                                                  message,
+                                                  G_DBUS_SEND_MESSAGE_FLAGS_NONE,
+                                                  G_MAXINT,
+                                                  NULL,
+                                                  cancellable,
+                                                  query_dbus_call_cb,
+                                                  task);
+       g_object_unref (message);
+       g_object_unref (fd_list);
+}
+
+TrackerSparqlCursor *
+tracker_bus_connection_perform_query_finish (TrackerBusConnection  *conn,
+                                            GAsyncResult          *res,
+                                            GError               **error)
+{
+       return g_task_propagate_pointer (G_TASK (res), error);
+}
+
+static void
+perform_query_call_cb (GObject      *source,
+                      GAsyncResult *res,
+                      gpointer      user_data)
+{
+       AsyncData *data = user_data;
+
+       data->retval = tracker_bus_connection_perform_query_finish (TRACKER_BUS_CONNECTION (source),
+                                                                   res, &data->error);
+       g_main_loop_quit (data->loop);
+}
+
+TrackerSparqlCursor *
+tracker_bus_connection_perform_query (TrackerBusConnection  *conn,
+                                     const gchar           *sparql,
+                                     GVariant              *arguments,
+                                     GCancellable          *cancellable,
+                                     GError               **error)
+{
+       GMainContext *context;
+       AsyncData data = { 0, };
+
+       context = g_main_context_new ();
+       data.loop = g_main_loop_new (context, FALSE);
+       g_main_context_push_thread_default (context);
+
+       tracker_bus_connection_perform_query_async (conn,
+                                                   sparql,
+                                                   arguments,
+                                                   cancellable,
+                                                   perform_query_call_cb,
+                                                   &data);
+       g_main_loop_run (data.loop);
+
+       g_main_context_pop_thread_default (context);
+
+       g_main_loop_unref (data.loop);
+       g_main_context_unref (context);
+
+       if (data.error) {
+               g_propagate_error (error, data.error);
+               return NULL;
+       }
+
+       return TRACKER_SPARQL_CURSOR (data.retval);
+}
+
+static void
+serialize_call_cb (GObject      *source,
+                  GAsyncResult *res,
+                  gpointer      user_data)
+{
+       GTask *task = user_data;
+       GDBusMessage *reply;
+       GError *error = NULL;
+
+       reply = g_dbus_connection_send_message_with_reply_finish (G_DBUS_CONNECTION (source),
+                                                                 res, &error);
+       if (reply && !g_dbus_message_to_gerror (reply, &error)) {
+               GInputStream *istream;
+
+               istream = g_task_get_task_data (task);
+               g_task_return_pointer (task, g_object_ref (istream), g_object_unref);
+               g_object_unref (task);
+       } else {
+               g_dbus_error_strip_remote_error (error);
+               g_task_return_error (task, error);
+               g_object_unref (task);
+       }
+
+       g_clear_object (&reply);
+}
+
+void
+tracker_bus_connection_perform_serialize_async (TrackerBusConnection  *bus,
+                                               TrackerSerializeFlags  flags,
+                                               TrackerRdfFormat       format,
+                                               const gchar           *query,
+                                               GVariant              *arguments,
+                                               GCancellable          *cancellable,
+                                               GAsyncReadyCallback    callback,
+                                               gpointer               user_data)
+{
+       GDBusMessage *message;
+       GUnixFDList *fd_list;
+       GInputStream *istream;
+       GError *error = NULL;
+       GTask *task;
+       int fd_idx;
+
+       task = g_task_new (bus, cancellable, callback, user_data);
+
+       if (!create_pipe_for_read (&istream, &fd_list, &fd_idx, &error)) {
+               g_task_return_error (task, error);
+               g_object_unref (task);
+               return;
+       }
+
+       g_task_set_task_data (task, istream, g_object_unref);
+       message = create_serialize_message (bus, query, flags, format,
+                                           arguments, fd_list, fd_idx);
+       g_dbus_connection_send_message_with_reply (bus->dbus_conn,
+                                                  message,
+                                                  G_DBUS_SEND_MESSAGE_FLAGS_NONE,
+                                                  G_MAXINT,
+                                                  NULL,
+                                                  cancellable,
+                                                  serialize_call_cb,
+                                                  task);
+       g_object_unref (message);
+       g_object_unref (fd_list);
+}
+
+GInputStream *
+tracker_bus_connection_perform_serialize_finish (TrackerBusConnection  *conn,
+                                                GAsyncResult          *res,
+                                                GError               **error)
+{
+       return g_task_propagate_pointer (G_TASK (res), error);
+}
diff --git a/src/libtracker-sparql/bus/tracker-bus.h b/src/libtracker-sparql/bus/tracker-bus.h
new file mode 100644
index 000000000..122f773c9
--- /dev/null
+++ b/src/libtracker-sparql/bus/tracker-bus.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2010, Nokia <ivan frade nokia com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ */
+
+#ifndef __TRACKER_BUS_H__
+#define __TRACKER_BUS_H__
+
+#include <libtracker-sparql/tracker-sparql.h>
+#include <libtracker-sparql/tracker-private.h>
+
+#define TRACKER_TYPE_BUS_CONNECTION (tracker_bus_connection_get_type ())
+G_DECLARE_FINAL_TYPE (TrackerBusConnection,
+                      tracker_bus_connection,
+                      TRACKER, BUS_CONNECTION,
+                      TrackerSparqlConnection)
+
+TrackerSparqlConnection * tracker_bus_connection_new (const gchar      *service,
+                                                      const gchar      *object_path,
+                                                      GDBusConnection  *conn,
+                                                      GError          **error);
+
+void tracker_bus_connection_new_async (const gchar         *service,
+                                       const gchar         *object_path,
+                                       GDBusConnection     *conn,
+                                       GCancellable        *cancellable,
+                                       GAsyncReadyCallback  cb,
+                                       gpointer             user_data);
+
+TrackerSparqlConnection * tracker_bus_connection_new_finish (GAsyncResult  *res,
+                                                             GError       **error);
+
+void tracker_bus_connection_perform_query_async (TrackerBusConnection *conn,
+                                                const gchar          *sparql,
+                                                GVariant             *arguments,
+                                                GCancellable         *cancellable,
+                                                GAsyncReadyCallback   callback,
+                                                gpointer              user_data);
+
+TrackerSparqlCursor * tracker_bus_connection_perform_query_finish (TrackerBusConnection  *conn,
+                                                                  GAsyncResult          *res,
+                                                                  GError               **error);
+
+TrackerSparqlCursor * tracker_bus_connection_perform_query (TrackerBusConnection  *conn,
+                                                           const gchar           *sparql,
+                                                           GVariant              *arguments,
+                                                           GCancellable          *cancellable,
+                                                           GError               **error);
+
+void tracker_bus_connection_perform_serialize_async (TrackerBusConnection  *conn,
+                                                    TrackerSerializeFlags  flags,
+                                                    TrackerRdfFormat       format,
+                                                    const gchar           *query,
+                                                    GVariant              *arguments,
+                                                    GCancellable          *cancellable,
+                                                    GAsyncReadyCallback    callback,
+                                                    gpointer               user_data);
+
+GInputStream * tracker_bus_connection_perform_serialize_finish (TrackerBusConnection  *conn,
+                                                               GAsyncResult          *res,
+                                                               GError               **error);
+
+#endif /* __TRACKER_BUS_H__ */
diff --git a/src/libtracker-sparql/meson.build b/src/libtracker-sparql/meson.build
index ce3dedb0f..149dfd33d 100644
--- a/src/libtracker-sparql/meson.build
+++ b/src/libtracker-sparql/meson.build
@@ -105,8 +105,6 @@ libtracker_sparql_private = static_library('tracker-sparql-private',
     bus_files,
     direct_files,
     remote_files,
-    '../libtracker-common/libtracker-common.vapi',
-    'tracker-backend.vala',
     tracker_gresources,
 
     c_args: [
diff --git a/src/libtracker-sparql/tracker-connection.c b/src/libtracker-sparql/tracker-connection.c
index b9e4a9cd3..f97b4cca6 100644
--- a/src/libtracker-sparql/tracker-connection.c
+++ b/src/libtracker-sparql/tracker-connection.c
@@ -62,6 +62,7 @@
 #include "tracker-private.h"
 #include "tracker-debug.h"
 
+#include "bus/tracker-bus.h"
 #include "direct/tracker-direct.h"
 #include "remote/tracker-remote.h"
 
@@ -115,53 +116,6 @@ tracker_sparql_connection_lookup_dbus_service (TrackerSparqlConnection  *connect
                                                                                      path);
 }
 
-/* The constructor functions are defined in the libtracker-sparql-backend, but
- * documented here. */
-
-/**
- * tracker_sparql_connection_bus_new:
- * @service_name: The name of the D-Bus service to connect to.
- * @object_path: (nullable): The path to the object, or %NULL to use the default.
- * @dbus_connection: (nullable): The #GDBusConnection to use, or %NULL to use the session bus
- * @error: pointer to a #GError
- *
- * Connects to a database owned by another process on the
- * local machine.
- *
- * Returns: (transfer full): a new #TrackerSparqlConnection. Call g_object_unref() on the
- * object when no longer used.
- *
- * Since: 3.0
- */
-
-/**
- * tracker_sparql_connection_bus_new_async:
- * @service_name: The name of the D-Bus service to connect to.
- * @object_path: (nullable): The path to the object, or %NULL to use the default.
- * @dbus_connection: (nullable): The #GDBusConnection to use, or %NULL to use the session bus
- * @cancellable: (nullable): a #GCancellable, or %NULL
- * @callback: the #GAsyncReadyCallback called when the operation completes
- * @user_data: data passed to @callback
- *
- * Connects to a database owned by another process on the
- * local machine. This is an asynchronous operation.
- *
- * Since: 3.1
- */
-
-/**
- * tracker_sparql_connection_bus_new_finish:
- * @result: the #GAsyncResult
- * @error: pointer to a #GError
- *
- * Completion function for tracker_sparql_connection_bus_new_async().
- *
- * Returns: (transfer full): a new #TrackerSparqlConnection. Call g_object_unref() on the
- * object when no longer used.
- *
- * Since: 3.1
- */
-
 /**
  * tracker_sparql_connection_query:
  * @connection: a #TrackerSparqlConnection
@@ -1143,3 +1097,117 @@ tracker_sparql_connection_new_finish (GAsyncResult  *res,
 
        return g_task_propagate_pointer (G_TASK (res), error);
 }
+
+/**
+ * tracker_sparql_connection_bus_new:
+ * @service_name: The name of the D-Bus service to connect to.
+ * @object_path: (nullable): The path to the object, or %NULL to use the default.
+ * @dbus_connection: (nullable): The #GDBusConnection to use, or %NULL to use the session bus
+ * @error: pointer to a #GError
+ *
+ * Connects to a database owned by another process on the
+ * local machine.
+ *
+ * Returns: (transfer full): a new #TrackerSparqlConnection. Call g_object_unref() on the
+ * object when no longer used.
+ *
+ * Since: 3.0
+ */
+TrackerSparqlConnection *
+tracker_sparql_connection_bus_new (const gchar      *service,
+                                  const gchar      *object_path,
+                                  GDBusConnection  *conn,
+                                  GError          **error)
+{
+       g_return_val_if_fail (service != NULL, NULL);
+       g_return_val_if_fail (!conn || G_IS_DBUS_CONNECTION (conn), NULL);
+       g_return_val_if_fail (!error || !*error, NULL);
+
+       if (!object_path)
+               object_path = "/org/freedesktop/Tracker3/Endpoint";
+
+       return tracker_bus_connection_new (service, object_path, conn, error);
+}
+
+static void
+bus_new_cb (GObject      *source,
+           GAsyncResult *res,
+           gpointer      user_data)
+{
+       TrackerSparqlConnection *conn;
+       GTask *task = user_data;
+       GError *error = NULL;
+
+       conn = tracker_bus_connection_new_finish (res, &error);
+
+       if (conn)
+               g_task_return_pointer (task, conn, g_object_unref);
+       else
+               g_task_return_error (task, error);
+
+       g_object_unref (task);
+}
+
+/**
+ * tracker_sparql_connection_bus_new_async:
+ * @service_name: The name of the D-Bus service to connect to.
+ * @object_path: (nullable): The path to the object, or %NULL to use the default.
+ * @dbus_connection: (nullable): The #GDBusConnection to use, or %NULL to use the session bus
+ * @cancellable: (nullable): a #GCancellable, or %NULL
+ * @callback: the #GAsyncReadyCallback called when the operation completes
+ * @user_data: data passed to @callback
+ *
+ * Connects to a database owned by another process on the
+ * local machine. This is an asynchronous operation.
+ *
+ * Since: 3.1
+ */
+void
+tracker_sparql_connection_bus_new_async (const gchar         *service,
+                                        const gchar         *object_path,
+                                        GDBusConnection     *conn,
+                                        GCancellable        *cancellable,
+                                        GAsyncReadyCallback  callback,
+                                        gpointer             user_data)
+{
+       GTask *task;
+
+       g_return_if_fail (service != NULL);
+       g_return_if_fail (!conn || G_IS_DBUS_CONNECTION (conn));
+       g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+       task = g_task_new (NULL, cancellable, callback, user_data);
+       g_task_set_source_tag (task, tracker_sparql_connection_bus_new_async);
+
+       if (!object_path)
+               object_path = "/org/freedesktop/Tracker3/Endpoint";
+
+       tracker_bus_connection_new_async (service, object_path, conn,
+                                         cancellable, bus_new_cb,
+                                         task);
+}
+
+/**
+ * tracker_sparql_connection_bus_new_finish:
+ * @result: the #GAsyncResult
+ * @error: pointer to a #GError
+ *
+ * Completion function for tracker_sparql_connection_bus_new_async().
+ *
+ * Returns: (transfer full): a new #TrackerSparqlConnection. Call g_object_unref() on the
+ * object when no longer used.
+ *
+ * Since: 3.1
+ */
+TrackerSparqlConnection *
+tracker_sparql_connection_bus_new_finish (GAsyncResult  *result,
+                                         GError       **error)
+{
+       g_return_val_if_fail (G_IS_TASK (result), NULL);
+       g_return_val_if_fail (!error || !*error, NULL);
+       g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) ==
+                             tracker_sparql_connection_bus_new_async,
+                             NULL);
+
+       return g_task_propagate_pointer (G_TASK (result), error);
+}


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