summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libtracker-common/libtracker-common.vapi120
-rw-r--r--src/libtracker-sparql/bus/.gitignore5
-rw-r--r--src/libtracker-sparql/bus/meson.build9
-rw-r--r--src/libtracker-sparql/bus/tracker-bus-batch.c192
-rw-r--r--src/libtracker-sparql/bus/tracker-bus-batch.h37
-rw-r--r--src/libtracker-sparql/bus/tracker-bus-batch.vala63
-rw-r--r--src/libtracker-sparql/bus/tracker-bus-cursor.c361
-rw-r--r--src/libtracker-sparql/bus/tracker-bus-cursor.h (renamed from src/libtracker-sparql/bus/tracker-namespace.vala)24
-rw-r--r--src/libtracker-sparql/bus/tracker-bus-fd-cursor.vala150
-rw-r--r--src/libtracker-sparql/bus/tracker-bus-statement.c289
-rw-r--r--src/libtracker-sparql/bus/tracker-bus-statement.h38
-rw-r--r--src/libtracker-sparql/bus/tracker-bus-statement.vala100
-rw-r--r--src/libtracker-sparql/bus/tracker-bus.c1703
-rw-r--r--src/libtracker-sparql/bus/tracker-bus.h77
-rw-r--r--src/libtracker-sparql/bus/tracker-bus.vala444
-rw-r--r--src/libtracker-sparql/meson.build2
-rw-r--r--src/libtracker-sparql/tracker-backend.vala70
-rw-r--r--src/libtracker-sparql/tracker-connection.c162
18 files changed, 2830 insertions, 1016 deletions
diff --git a/src/libtracker-common/libtracker-common.vapi b/src/libtracker-common/libtracker-common.vapi
deleted file mode 100644
index 9e4298897..000000000
--- a/src/libtracker-common/libtracker-common.vapi
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (C) 2008-2009, Nokia
- *
- * 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.
- */
-
-[CCode (cprefix = "Tracker", gir_namespace = "Tracker",
- gir_version = "2.0", lower_case_cprefix = "tracker_")]
-namespace Tracker {
- [CCode (cheader_filename = "libtracker-common/tracker-date-time.h")]
- public double string_to_date (string date_string, out int offset) throws DateError;
-
- [CCode (cheader_filename = "libtracker-common/tracker-utils.h")]
- public string? util_build_dbus_uri (GLib.BusType bus_type, string service, string? path);
-
- [CCode (cheader_filename = "libtracker-common/tracker-date-time.h")]
- public errordomain DateError {
- OFFSET,
- INVALID_ISO8601
- }
-
- [CCode (cheader_filename = "libtracker-common/tracker-common.h")]
- public class ConfigFile : GLib.Object {
- [CCode (has_construct_function = false)]
- public ConfigFile ();
- [NoAccessorMethod]
- public string domain { get; construct; }
- public bool save ();
- public virtual signal void changed ();
- public GLib.File file;
- public GLib.FileMonitor monitor;
- public bool file_exists;
- public GLib.KeyFile key_file;
- }
-
- [CCode (cheader_filename = "libtracker-common/tracker-common.h")]
- public class KeyfileObject {
- public static string blurb (void *object, string property);
- public static bool default_boolean (void *object, string property);
- public static int default_int (void *object, string property);
- public static bool validate_int (void *object, string propery, int value);
- public static void load_int (void *object, string property, GLib.KeyFile key_file, string group, string key);
- public static void load_boolean (void *object, string property, GLib.KeyFile key_file, string group, string key);
- public static void load_string (void *object, string property, GLib.KeyFile key_file, string group, string key);
- public static void load_string_list (void *object, string property, GLib.KeyFile key_file, string group, string key, out GLib.SList return_instead);
- public static void load_directory_list (void *object, string property, GLib.KeyFile key_file, string group, string key, bool is_recursive, out GLib.SList return_instead);
- public static void save_int (void *object, string property, GLib.KeyFile key_file, string group, string key);
- public static void save_boolean (void *object, string property, GLib.KeyFile key_file, string group, string key);
- public static void save_string (void *object, string property, GLib.KeyFile key_file, string group, string key);
- public static void save_string_list (void *object, string property, GLib.KeyFile key_file, string group, string key);
- public static void save_directory_list (void *object, string property, GLib.KeyFile key_file, string group, string key);
- }
-
- [CCode (cheader_filename = "libtracker-common/tracker-locale.h")]
- namespace Locale {
- public void sanity_check ();
- }
-
- [Compact]
- [CCode (cheader_filename = "libtracker-common/tracker-common.h")]
- namespace IPC {
- public GLib.BusType bus ();
- }
-
- [Compact]
- [CCode (ref_function = "", unref_function = "", cheader_filename = "libtracker-common/tracker-common.h")]
- public class DBusRequest {
- public static DBusRequest begin (string? sender, string format,...);
- public void debug (string format,...);
- public void end (GLib.Error? e = null);
- [CCode (cname = "tracker_dbus_enable_client_lookup")]
- public static void enable_client_lookup (bool enable);
- }
-
- [CCode (ref_function = "tracker_domain_ontology_ref", unref_function = "tracker_domain_ontology_unref", cheader_filename = "libtracker-common/tracker-domain-ontology.h")]
- public class DomainOntology {
- public DomainOntology (string? name, GLib.Cancellable? cancellable) throws GLib.Error;
- public GLib.File get_cache ();
- public GLib.File? get_journal ();
- public GLib.File get_ontology ();
- public string get_domain (string? suffix = null);
- }
-
- [CCode (cheader_filename = "libtracker-common/tracker-common.h")]
- public void ioprio_init ();
-
- [CCode (cheader_filename = "libtracker-common/tracker-debug.h")]
- public uint get_debug_flags ();
-
- [CCode (cname = "g_message", cheader_filename = "glib.h")]
- [PrintfFormat]
- public void message (string format, ...);
- [CCode (cname = "g_warning", cheader_filename = "glib.h")]
- [PrintfFormat]
- public void warning (string format, ...);
- [CCode (cname = "g_critical", cheader_filename = "glib.h")]
- [PrintfFormat]
- public void critical (string format, ...);
- [CCode (cname = "g_error", cheader_filename = "glib.h")]
- [PrintfFormat]
- [NoReturn]
- public void error (string format, ...);
- [CCode (cname = "g_debug", cheader_filename = "glib.h")]
- [PrintfFormat]
- public void debug (string format, ...);
-}
-
diff --git a/src/libtracker-sparql/bus/.gitignore b/src/libtracker-sparql/bus/.gitignore
deleted file mode 100644
index c34fe4c56..000000000
--- a/src/libtracker-sparql/bus/.gitignore
+++ /dev/null
@@ -1,5 +0,0 @@
-tracker-namespace.c
-tracker-bus.[ch]
-tracker-bus*.vapi
-tracker-array-cursor.c
-tracker-bus-fd-cursor.c
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-batch.vala b/src/libtracker-sparql/bus/tracker-bus-batch.vala
deleted file mode 100644
index 1993775b3..000000000
--- a/src/libtracker-sparql/bus/tracker-bus-batch.vala
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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>
- */
-
-public class Tracker.Bus.Batch : Tracker.Batch {
- private DBusConnection bus;
- private string dbus_name;
- private string object_path;
- private string[] updates;
-
- public Batch (DBusConnection bus, string dbus_name, string object_path) {
- Object ();
- this.bus = bus;
- this.dbus_name = dbus_name;
- this.object_path = object_path;
- }
-
- public override void add_sparql (string sparql) {
- updates += sparql;
- }
-
- public override void add_resource (string? graph, Resource resource) {
- var namespaces = this.connection.get_namespace_manager ();
- var sparql = resource.print_sparql_update (namespaces, graph);
- updates += sparql;
- }
-
- public override bool execute (GLib.Cancellable? cancellable) throws Sparql.Error, GLib.Error, GLib.IOError, GLib.DBusError {
- // use separate main context for sync operation
- var context = new MainContext ();
- var loop = new MainLoop (context, false);
- context.push_thread_default ();
- AsyncResult async_res = null;
- execute_async.begin (cancellable, (o, res) => {
- async_res = res;
- loop.quit ();
- });
- loop.run ();
- context.pop_thread_default ();
- return execute_async.end (async_res);
- }
-
- public async override bool execute_async (GLib.Cancellable? cancellable) throws Sparql.Error, GLib.Error, GLib.IOError, GLib.DBusError {
- return yield Tracker.Bus.Connection.perform_update_array (bus, dbus_name, object_path, updates, cancellable);
- }
-}
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
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-fd-cursor.vala b/src/libtracker-sparql/bus/tracker-bus-fd-cursor.vala
deleted file mode 100644
index 954ad1ec7..000000000
--- a/src/libtracker-sparql/bus/tracker-bus-fd-cursor.vala
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * 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.
- */
-
-class Tracker.Bus.FDCursor : Tracker.Sparql.Cursor {
- internal char* buffer;
- internal ulong buffer_index;
- internal ulong buffer_size;
-
- internal int _n_columns;
- internal int* offsets;
- internal int* types;
- internal char* data;
- internal string[] variable_names;
- internal bool cursor_finished;
-
- public FDCursor (char* buffer, ulong buffer_size, string[] variable_names) {
- Object ();
- this.buffer = buffer;
- this.buffer_size = buffer_size;
- this.variable_names = variable_names;
- this.cursor_finished = true;
- _n_columns = variable_names.length;
- }
-
- ~FDCursor () {
- free (buffer);
- }
-
- inline int buffer_read_int () {
- int v = *((int*) (buffer + buffer_index));
-
- buffer_index += 4;
-
- return v;
- }
-
- public override int n_columns {
- get { return _n_columns; }
- }
-
- public override Sparql.ValueType get_value_type (int column)
- requires (types != null) {
- if (column >= n_columns) {
- return Sparql.ValueType.UNBOUND;
- }
-
- /* Cast from int to enum */
- return (Sparql.ValueType) types[column];
- }
-
- public override unowned string? get_variable_name (int column)
- requires (variable_names != null) {
- return variable_names[column];
- }
-
- public override unowned string? get_string (int column, out long length = null)
- requires (cursor_finished == false) {
- unowned string str = null;
-
- if (column >= n_columns) {
- length = 0;
- return null;
- }
-
- // return null instead of empty string for unbound values
- if (types[column] == Sparql.ValueType.UNBOUND) {
- length = 0;
- return null;
- }
-
- if (column == 0) {
- str = (string) data;
- } else {
- str = (string) (data + offsets[column - 1] + 1);
- }
-
- length = str.length;
-
- return str;
- }
-
- public override bool next (Cancellable? cancellable = null) throws GLib.Error {
- int last_offset;
-
- if (cancellable != null && cancellable.is_cancelled ()) {
- throw new IOError.CANCELLED ("Operation was cancelled");
- }
-
- if (buffer_index >= buffer_size) {
- cursor_finished = true;
- data = null;
- 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 = buffer_read_int ();
-
- /* Storage of ints that will be cast to TrackerSparqlValueType enums,
- * also see get_value_type */
- types = (int*) (buffer + buffer_index);
- buffer_index += sizeof (int) * n_columns;
-
- offsets = (int*) (buffer + buffer_index);
- buffer_index += sizeof (int) * (n_columns - 1);
- last_offset = buffer_read_int ();
-
- data = buffer + buffer_index;
- cursor_finished = false;
-
- buffer_index += last_offset + 1;
-
- return true;
- }
-
- public override async bool next_async (Cancellable? cancellable = null) throws GLib.Error {
- // next never blocks
- return next (cancellable);
- }
-
- public override void rewind () {
- buffer_index = 0;
- data = buffer;
- cursor_finished = false;
- }
-
- public override void close () {
- }
-}
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-statement.vala b/src/libtracker-sparql/bus/tracker-bus-statement.vala
deleted file mode 100644
index 7a2472135..000000000
--- a/src/libtracker-sparql/bus/tracker-bus-statement.vala
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * 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>
- */
-
-public class Tracker.Bus.Statement : Tracker.Sparql.Statement {
- private DBusConnection bus;
- private string query;
- private string dbus_name;
- private string object_path;
- private HashTable<string,GLib.Variant> arguments;
-
- public Statement (Sparql.Connection connection, DBusConnection bus, string dbus_name, string object_path, string query) {
- Object (connection: connection);
- this.bus = bus;
- this.dbus_name = dbus_name;
- this.object_path = object_path;
- this.query = query;
- this.arguments = new HashTable<string, GLib.Variant> (str_hash, str_equal);
- }
-
- public override void bind_boolean (string name, bool value) {
- this.arguments.insert (name, new GLib.Variant.boolean (value));
- }
-
- public override void bind_double (string name, double value) {
- this.arguments.insert (name, new GLib.Variant.double (value));
- }
-
- public override void bind_int (string name, int64 value) {
- this.arguments.insert (name, new GLib.Variant.int64 (value));
- }
-
- public override void bind_string (string name, string value) {
- this.arguments.insert (name, new GLib.Variant.string (value));
- }
-
- public override void bind_datetime (string name, DateTime value) {
- string date_time = value.to_string ();
- this.arguments.insert (name, new GLib.Variant.string (date_time));
- }
-
- public override void clear_bindings () {
- this.arguments.remove_all ();
- }
-
- private VariantBuilder? get_arguments () {
- if (this.arguments.size () == 0)
- return null;
-
- VariantBuilder builder = new VariantBuilder (new VariantType ("a{sv}"));
- HashTableIter<string, Variant> iter = HashTableIter<string, Variant> (this.arguments);
- unowned string arg;
- unowned GLib.Variant value;
-
- while (iter.next (out arg, out value))
- builder.add ("{sv}", arg, value);
-
- return builder;
- }
-
- public override Sparql.Cursor execute (GLib.Cancellable? cancellable) throws Sparql.Error, GLib.Error, GLib.IOError, GLib.DBusError {
- // use separate main context for sync operation
- var context = new MainContext ();
- var loop = new MainLoop (context, false);
- context.push_thread_default ();
- AsyncResult async_res = null;
- execute_async.begin (cancellable, (o, res) => {
- async_res = res;
- loop.quit ();
- });
- loop.run ();
- context.pop_thread_default ();
- return execute_async.end (async_res);
- }
-
- public async override Sparql.Cursor execute_async (GLib.Cancellable? cancellable) throws Sparql.Error, GLib.Error, GLib.IOError, GLib.DBusError {
- return yield Tracker.Bus.Connection.perform_query_call (bus, dbus_name, object_path, query, get_arguments (), cancellable);
- }
-
- public async override GLib.InputStream serialize_async (SerializeFlags flags, RdfFormat format, GLib.Cancellable? cancellable) throws Sparql.Error, GLib.Error, GLib.IOError, GLib.DBusError {
- return yield Tracker.Bus.Connection.perform_serialize (bus, dbus_name, object_path, flags, format, query, get_arguments (), cancellable);
- }
-}
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/bus/tracker-bus.vala b/src/libtracker-sparql/bus/tracker-bus.vala
deleted file mode 100644
index 93f4b9f05..000000000
--- a/src/libtracker-sparql/bus/tracker-bus.vala
+++ /dev/null
@@ -1,444 +0,0 @@
-/*
- * 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.
- */
-
-public class Tracker.Bus.Connection : Tracker.Sparql.Connection {
- DBusConnection bus;
- string dbus_name;
- string object_path;
- bool sandboxed;
- NamespaceManager namespaces;
-
- private const string DBUS_PEER_IFACE = "org.freedesktop.DBus.Peer";
-
- private const string PORTAL_NAME = "org.freedesktop.portal.Tracker";
- private const string PORTAL_PATH = "/org/freedesktop/portal/Tracker";
- private const string PORTAL_IFACE = "org.freedesktop.portal.Tracker";
-
- private const string ENDPOINT_IFACE = "org.freedesktop.Tracker3.Endpoint";
-
- private const int timeout = 30000;
-
- public string bus_name {
- get { return dbus_name; }
- }
-
- public string bus_object_path {
- get { return object_path; }
- }
-
- public async Connection (string dbus_name, string object_path, DBusConnection? dbus_connection, Cancellable? cancellable) throws Sparql.Error, IOError, DBusError, GLib.Error {
- Object ();
- this.sandboxed = false;
- this.bus = dbus_connection;
-
- // ensure that error domain is registered with GDBus
- new Sparql.Error.INTERNAL ("");
-
- // If this environment variable is present, we always go via the portal,
- if (Environment.get_variable("TRACKER_TEST_PORTAL_FLATPAK_INFO") == null) {
- var message = new DBusMessage.method_call (dbus_name, object_path, DBUS_PEER_IFACE, "Ping");
-
- try {
- var reply = yield this.bus.send_message_with_reply (message, 0, timeout, cancellable);
- reply.to_gerror ();
- this.dbus_name = dbus_name;
- this.object_path = object_path;
- yield this.init_namespaces ();
- return;
- } catch (GLib.Error e) {
- if (!GLib.FileUtils.test ("/.flatpak-info", GLib.FileTest.EXISTS)) {
- throw e;
- }
- }
- }
-
- /* We are in a flatpak sandbox, check going through the portal */
- if (object_path == "/org/freedesktop/Tracker3/Endpoint")
- object_path = null;
-
- string uri = Tracker.util_build_dbus_uri (GLib.BusType.SESSION, dbus_name, object_path);
- var message = new DBusMessage.method_call (PORTAL_NAME, PORTAL_PATH, PORTAL_IFACE, "CreateSession");
- message.set_body (new Variant ("(s)", uri));
-
- var reply = yield this.bus.send_message_with_reply (message, 0, timeout, cancellable);
- reply.to_gerror ();
-
- var variant = reply.get_body ();
- variant.get_child(0, "o", out object_path);
-
- this.dbus_name = PORTAL_NAME;
- this.object_path = object_path;
- this.sandboxed = true;
-
- yield this.init_namespaces ();
- }
-
- private async void init_namespaces () throws Sparql.Error, IOError, DBusError, GLib.Error {
- this.namespaces = new NamespaceManager ();
- var cursor = yield this.query_async ("SELECT ?prefix ?name { ?name nrl:prefix ?prefix }", null);
- while (cursor.next ())
- this.namespaces.add_prefix(cursor.get_string(0), cursor.get_string(1));
- cursor.close ();
- }
-
- static void pipe (out UnixInputStream input, out UnixOutputStream output) throws IOError {
- int pipefd[2];
- if (Posix.pipe (pipefd) < 0) {
- throw new IOError.FAILED ("Pipe creation failed");
- }
- input = new UnixInputStream (pipefd[0], true);
- output = new UnixOutputStream (pipefd[1], true);
- }
-
- static void handle_error_reply (DBusMessage message) throws Sparql.Error, IOError, DBusError {
- try {
- message.to_gerror ();
- } catch (IOError e_io) {
- GLib.DBusError.strip_remote_error (e_io);
- throw e_io;
- } catch (DBusError e_dbus) {
- GLib.DBusError.strip_remote_error (e_dbus);
- throw e_dbus;
- } catch (Sparql.Error e_sparql) {
- GLib.DBusError.strip_remote_error (e_sparql);
- throw e_sparql;
- } catch (Error e) {
- GLib.DBusError.strip_remote_error (e);
- throw new IOError.FAILED (e.message);
- }
- }
-
- static void send_query (DBusConnection bus, string dbus_name, string object_path, string sparql, VariantBuilder? arguments, UnixOutputStream output, Cancellable? cancellable, AsyncReadyCallback? callback) throws GLib.IOError, GLib.Error {
- var message = new DBusMessage.method_call (dbus_name, object_path, ENDPOINT_IFACE, "Query");
- var fd_list = new UnixFDList ();
- message.set_body (new Variant ("(sha{sv})", sparql, fd_list.append (output.fd), arguments));
- message.set_unix_fd_list (fd_list);
-
- bus.send_message_with_reply.begin (message, DBusSendMessageFlags.NONE, int.MAX, null, cancellable, callback);
- }
-
- public static async Sparql.Cursor perform_query_call (DBusConnection bus, string dbus_name, string object_path, string sparql, VariantBuilder? arguments, Cancellable? cancellable) throws GLib.IOError, GLib.Error {
- UnixInputStream input;
- UnixOutputStream output;
- pipe (out input, out output);
-
- // send D-Bus request
- AsyncResult dbus_res = null;
- bool received_result = false;
- send_query (bus, dbus_name, object_path, sparql, arguments, output, cancellable, (o, res) => {
- dbus_res = res;
- if (received_result) {
- perform_query_call.callback ();
- }
- });
-
- output = null;
-
- // receive query results via FD
- var mem_stream = new MemoryOutputStream (null, GLib.realloc, GLib.free);
-
- try {
- yield mem_stream.splice_async (input, OutputStreamSpliceFlags.CLOSE_SOURCE | OutputStreamSpliceFlags.CLOSE_TARGET, Priority.DEFAULT, cancellable);
- } finally {
- // wait for D-Bus reply
- received_result = true;
- if (dbus_res == null) {
- yield;
- }
- }
-
- var reply = bus.send_message_with_reply.end (dbus_res);
- handle_error_reply (reply);
-
- string[] variable_names = (string[]) reply.get_body ().get_child_value (0);
- mem_stream.close ();
- return new FDCursor (mem_stream.steal_data (), mem_stream.data_size, variable_names);
- }
-
- public override Sparql.Cursor query (string sparql, Cancellable? cancellable) throws Sparql.Error, GLib.Error, GLib.IOError, DBusError {
- // use separate main context for sync operation
- var context = new MainContext ();
- var loop = new MainLoop (context, false);
- context.push_thread_default ();
- AsyncResult async_res = null;
- query_async.begin (sparql, cancellable, (o, res) => {
- async_res = res;
- loop.quit ();
- });
- loop.run ();
- context.pop_thread_default ();
- return query_async.end (async_res);
- }
-
- public async override Sparql.Cursor query_async (string sparql, Cancellable? cancellable = null) throws Sparql.Error, GLib.Error, GLib.IOError, DBusError {
- return yield perform_query_call (bus, dbus_name, object_path, sparql, null, cancellable);
- }
-
- public override Sparql.Statement? query_statement (string sparql, GLib.Cancellable? cancellable = null) throws Sparql.Error {
- return new Bus.Statement (this, bus, dbus_name, object_path, sparql);
- }
-
- static void send_update (DBusConnection bus, string dbus_name, string object_path, string method, UnixInputStream input, Cancellable? cancellable, AsyncReadyCallback? callback) throws GLib.Error, GLib.IOError {
- var message = new DBusMessage.method_call (dbus_name, object_path, ENDPOINT_IFACE, method);
- var fd_list = new UnixFDList ();
- message.set_body (new Variant ("(h)", fd_list.append (input.fd)));
- message.set_unix_fd_list (fd_list);
-
- bus.send_message_with_reply.begin (message, DBusSendMessageFlags.NONE, int.MAX, null, cancellable, callback);
- }
-
- public override void update (string sparql, Cancellable? cancellable = null) throws Sparql.Error, GLib.Error, GLib.IOError, DBusError {
- // use separate main context for sync operation
- var context = new MainContext ();
- var loop = new MainLoop (context, false);
- context.push_thread_default ();
- AsyncResult async_res = null;
- update_async.begin (sparql, cancellable, (o, res) => {
- async_res = res;
- loop.quit ();
- });
- loop.run ();
- context.pop_thread_default ();
- update_async.end (async_res);
- }
-
- public async override void update_async (string sparql, Cancellable? cancellable = null) throws Sparql.Error, GLib.Error, GLib.IOError, DBusError {
- UnixInputStream input;
- UnixOutputStream output;
- pipe (out input, out output);
-
- // send D-Bus request
- AsyncResult dbus_res = null;
- bool sent_update = false;
- send_update (bus, dbus_name, object_path, "Update", input, cancellable, (o, res) => {
- dbus_res = res;
- if (sent_update) {
- update_async.callback ();
- }
- });
-
- // send sparql string via fd
- var data_stream = new DataOutputStream (output);
- data_stream.set_byte_order (DataStreamByteOrder.HOST_ENDIAN);
- data_stream.put_int32 ((int32) sparql.length);
- data_stream.put_string (sparql);
- data_stream = null;
-
- // wait for D-Bus reply
- sent_update = true;
- if (dbus_res == null) {
- yield;
- }
-
- var reply = bus.send_message_with_reply.end (dbus_res);
- handle_error_reply (reply);
- }
-
- public static async bool perform_update_array (DBusConnection bus, string dbus_name, string object_path, string[] sparql, Cancellable? cancellable) throws GLib.IOError, GLib.Error {
- if (sparql.length == 0)
- return true;
-
- UnixInputStream input;
- UnixOutputStream output;
- pipe (out input, out output);
-
- // send D-Bus request
- AsyncResult dbus_res = null;
- bool sent_update = false;
- send_update (bus, dbus_name, object_path, "UpdateArray", input, cancellable, (o, res) => {
- dbus_res = res;
- if (sent_update) {
- perform_update_array.callback ();
- }
- });
-
- // send sparql strings via fd
- var data_stream = new DataOutputStream (output);
- data_stream.set_byte_order (DataStreamByteOrder.HOST_ENDIAN);
- data_stream.put_int32 ((int32) sparql.length);
- for (int i = 0; i < sparql.length; i++) {
- data_stream.put_int32 ((int32) sparql[i].length);
- data_stream.put_string (sparql[i]);
- }
- data_stream = null;
-
- // wait for D-Bus reply
- sent_update = true;
- if (dbus_res == null) {
- yield;
- }
-
- var reply = bus.send_message_with_reply.end (dbus_res);
- handle_error_reply (reply);
-
- return true;
- }
-
- public async override bool update_array_async (string[] sparql, Cancellable? cancellable = null) throws Sparql.Error, GLib.Error, GLib.IOError, DBusError {
- return yield perform_update_array (bus, dbus_name, object_path, sparql, cancellable);
- }
-
- public override GLib.Variant? update_blank (string sparql, Cancellable? cancellable = null) throws Sparql.Error, GLib.Error, GLib.IOError, DBusError {
- // use separate main context for sync operation
- var context = new MainContext ();
- var loop = new MainLoop (context, false);
- context.push_thread_default ();
- AsyncResult async_res = null;
- update_blank_async.begin (sparql, cancellable, (o, res) => {
- async_res = res;
- loop.quit ();
- });
- loop.run ();
- context.pop_thread_default ();
- return update_blank_async.end (async_res);
- }
-
- public async override GLib.Variant? update_blank_async (string sparql, Cancellable? cancellable = null) throws Sparql.Error, GLib.Error, GLib.IOError, DBusError {
- UnixInputStream input;
- UnixOutputStream output;
- pipe (out input, out output);
-
- // send D-Bus request
- AsyncResult dbus_res = null;
- bool sent_update = false;
- send_update (bus, dbus_name, object_path, "UpdateBlank", input, cancellable, (o, res) => {
- dbus_res = res;
- if (sent_update) {
- update_blank_async.callback ();
- }
- });
-
- // send sparql strings via fd
- var data_stream = new DataOutputStream (output);
- data_stream.set_byte_order (DataStreamByteOrder.HOST_ENDIAN);
- data_stream.put_int32 ((int32) sparql.length);
- data_stream.put_string (sparql);
- data_stream = null;
-
- // wait for D-Bus reply
- sent_update = true;
- if (dbus_res == null) {
- yield;
- }
-
- var reply = bus.send_message_with_reply.end (dbus_res);
- handle_error_reply (reply);
- return reply.get_body ().get_child_value (0);
- }
-
- public override bool update_resource (string? graph, Resource resource, GLib.Cancellable? cancellable = null) throws Sparql.Error, GLib.Error, GLib.IOError, GLib.DBusError {
- var batch = this.create_batch ();
- batch.add_resource (graph, resource);
- return batch.execute (cancellable);
- }
-
- public async override bool update_resource_async (string? graph, Resource resource, GLib.Cancellable? cancellable = null) throws Sparql.Error, GLib.Error, GLib.IOError, GLib.DBusError {
- var batch = this.create_batch ();
- batch.add_resource (graph, resource);
- return yield batch.execute_async (cancellable);
- }
-
- public override Tracker.Notifier? create_notifier () {
- var notifier = (Tracker.Notifier) Object.new (typeof (Tracker.Notifier),
- "connection", this,
- null);
-
- notifier.signal_subscribe (this.bus, this.dbus_name, null, null);
-
- return notifier;
- }
-
- public override void close () {
- if (this.sandboxed) {
- var message = new DBusMessage.method_call (PORTAL_NAME, PORTAL_PATH, PORTAL_IFACE, "CloseSession");
- message.set_body (new Variant ("(o)", this.object_path));
-
- try {
- this.bus.send_message (message, 0, null);
- } catch (GLib.Error e) {
- }
- }
- }
-
- public async override bool close_async () throws GLib.IOError {
- this.close ();
- return true;
- }
-
- public override Tracker.NamespaceManager? get_namespace_manager () {
- return namespaces;
- }
-
- public override Tracker.Batch? create_batch () {
- var batch = (Tracker.Batch) Object.new (typeof (Tracker.Bus.Batch),
- "connection", this,
- null);
- return batch;
- }
-
- public static async GLib.InputStream perform_serialize (DBusConnection bus, string dbus_name, string object_path, SerializeFlags flags, RdfFormat format, string sparql, VariantBuilder? arguments, Cancellable? cancellable) throws GLib.IOError, GLib.Error {
- UnixInputStream input;
- UnixOutputStream output;
- pipe (out input, out output);
-
- var message = new DBusMessage.method_call (dbus_name, object_path, ENDPOINT_IFACE, "Serialize");
- var fd_list = new UnixFDList ();
- message.set_body (new Variant ("(shiia{sv})", sparql, fd_list.append (output.fd), flags, format, arguments));
- message.set_unix_fd_list (fd_list);
-
- var reply = yield bus.send_message_with_reply (message, DBusSendMessageFlags.NONE, int.MAX, null, cancellable);
- handle_error_reply (reply);
-
- return input;
- }
-
- public async override GLib.InputStream serialize_async (SerializeFlags flags, RdfFormat format, string sparql, GLib.Cancellable? cancellable = null) throws Sparql.Error, GLib.Error, GLib.IOError, GLib.DBusError {
- return yield perform_serialize (bus, dbus_name, object_path, flags, format, sparql, null, cancellable);
- }
-
- public static async bool perform_deserialize (DBusConnection bus, string dbus_name, string object_path, DeserializeFlags flags, RdfFormat format, string? default_graph, GLib.InputStream istream, VariantBuilder? arguments, Cancellable? cancellable) throws GLib.IOError, GLib.Error {
- UnixInputStream input;
- UnixOutputStream output;
- pipe (out input, out output);
-
- var message = new DBusMessage.method_call (dbus_name, object_path, ENDPOINT_IFACE, "Deserialize");
- var fd_list = new UnixFDList ();
- DBusMessage? reply = null;
- message.set_body (new Variant ("(hiisa{sv})", fd_list.append (input.fd), flags, format, default_graph != null ? default_graph : "", arguments));
- message.set_unix_fd_list (fd_list);
-
- bus.send_message_with_reply.begin (message, DBusSendMessageFlags.NONE, int.MAX, null, cancellable, (o, res) => {
- reply = bus.send_message_with_reply.end(res);
- perform_deserialize.callback();
- });
-
- output.splice_async.begin (istream, OutputStreamSpliceFlags.CLOSE_SOURCE | OutputStreamSpliceFlags.CLOSE_TARGET, Priority.DEFAULT, cancellable);
-
- yield;
-
- if (reply != null)
- handle_error_reply (reply);
-
- return true;
- }
-
- public async override bool deserialize_async (DeserializeFlags flags, RdfFormat format, string? default_graph, GLib.InputStream istream, Cancellable? cancellable) throws GLib.IOError, GLib.Error {
- return yield perform_deserialize (bus, dbus_name, object_path, flags, format, default_graph, istream, null, cancellable);
- }
-}
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-backend.vala b/src/libtracker-sparql/tracker-backend.vala
deleted file mode 100644
index 1657ab25e..000000000
--- a/src/libtracker-sparql/tracker-backend.vala
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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.
- */
-
-/* All apps using libtracker-sparql will call one of these constructors, so
- * we take the opportunity to call tracker_get_debug_flags(). This has the
- * effect of printing the 'help' message if TRACKER_DEBUG=help is set.
- */
-
-public static Tracker.Sparql.Connection tracker_sparql_connection_bus_new (string service, string? object_path, DBusConnection? conn) throws Tracker.Sparql.Error, IOError, DBusError, GLib.Error {
- Tracker.get_debug_flags ();
-
- var context = new GLib.MainContext ();
- var loop = new GLib.MainLoop(context);
- GLib.Error? error = null;
- Tracker.Sparql.Connection? sparql_conn = null;
-
- context.push_thread_default ();
-
- tracker_sparql_connection_bus_new_async.begin(service, object_path, conn, null, (o, res) => {
- try {
- sparql_conn = tracker_sparql_connection_bus_new_async.end(res);
- } catch (Error e) {
- error = e;
- }
- loop.quit();
- });
- loop.run ();
-
- context.pop_thread_default ();
-
- if (error != null)
- throw error;
-
- return sparql_conn;
-}
-
-public static async Tracker.Sparql.Connection tracker_sparql_connection_bus_new_async (string service, string? object_path, DBusConnection? conn, Cancellable? cancellable) throws Tracker.Sparql.Error, IOError, DBusError, GLib.Error {
- GLib.DBusConnection dbus_conn;
- string path;
-
- Tracker.get_debug_flags ();
-
- if (conn != null)
- dbus_conn = conn;
- else
- dbus_conn = yield GLib.Bus.get (GLib.BusType.SESSION, cancellable);
-
- if (object_path != null)
- path = object_path;
- else
- path = "/org/freedesktop/Tracker3/Endpoint";
-
- return yield new Tracker.Bus.Connection (service, path, dbus_conn, cancellable);
-}
diff --git a/src/libtracker-sparql/tracker-connection.c b/src/libtracker-sparql/tracker-connection.c
index db9c02371..6f83d7abe 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);
+}