summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Garnacho <carlosg@gnome.org>2017-11-17 00:33:26 +0100
committerCarlos Garnacho <carlosg@gnome.org>2018-07-20 18:27:32 +0200
commita5332e937e25d45cbfb3af90a557776a7280cbdb (patch)
tree23604fdae433ac9b7a0239ad366dc596f7d2fde6
parent2f7ade534a452153ab9f0faa10e403b30e845c75 (diff)
downloadtracker-a5332e937e25d45cbfb3af90a557776a7280cbdb.tar.gz
libtracker-direct: Rewrite in C
In today's chapter of gratuituous rewrites. The instigator of this rewrite is vala's bug https://bugzilla.gnome.org/show_bug.cgi?id=789249. One might argue that bugs are bugs and eventually get fixed, but there's two things that make me think it won't happen soon: - Vala behavior of possibly iterating the main loop from the async task until the task is complete is very much deliberate in order to support the Generator pattern without a main loop, as seen at: https://wiki.gnome.org/Projects/Vala/AsyncSamples#Generator_example - OTOH, glib docs specify that a GAsyncReadyCallback must happen at a later iteration of the main context, presumably to ensure the task is not finished before the async function dispatching the task returns. This is precisely what trips Vala into starting the same task again. I don't see either changing anytime soon, and in the mean time Tracker is largely affected by it, both in perceived bugs (All those nie:url constraint warnings out of the blue had a reason, this) and in real bugs (It's sometimes attempting to insert things twice, and it may even succeed if the query does not break any cardinality/unique constraints). This affects Tracker in too fundamental ways to just shrug it away, unlike the Vala code this C/glib code works just as it looks. Now about the code... It's a pretty boring rewrite, there's a thread pool to dispatch select queries, and a single exclusive thread to handle updates. The WAL hook can possibly use an additional thread to perform non-blocking writes. All very much alike the older code. Future commits will make tracker-store use this connection implementation, so there's only this piece of code handling SPARQL updates.
-rw-r--r--src/libtracker-direct/.gitignore3
-rw-r--r--src/libtracker-direct/Makefile.am17
-rw-r--r--src/libtracker-direct/tracker-direct.c830
-rw-r--r--src/libtracker-direct/tracker-direct.h52
-rw-r--r--src/libtracker-direct/tracker-direct.vala405
-rw-r--r--src/libtracker-direct/tracker-direct.vapi10
-rw-r--r--src/libtracker-direct/tracker-namespace.vala29
7 files changed, 893 insertions, 453 deletions
diff --git a/src/libtracker-direct/.gitignore b/src/libtracker-direct/.gitignore
deleted file mode 100644
index b55dd251a..000000000
--- a/src/libtracker-direct/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-tracker-namespace.c
-tracker-direct.[ch]
-tracker-direct*.vapi
diff --git a/src/libtracker-direct/Makefile.am b/src/libtracker-direct/Makefile.am
index 5e9a42f46..7960bae6c 100644
--- a/src/libtracker-direct/Makefile.am
+++ b/src/libtracker-direct/Makefile.am
@@ -1,16 +1,5 @@
noinst_LTLIBRARIES = libtracker-direct.la
-AM_VALAFLAGS = \
- --includedir=libtracker-direct \
- --header tracker-direct.h \
- --vapi tracker-direct.vapi \
- --pkg gio-2.0 \
- $(BUILD_VALAFLAGS) \
- $(top_srcdir)/src/libtracker-data/libtracker-data.vapi \
- $(top_srcdir)/src/libtracker-data/tracker-sparql-query.vapi \
- $(top_srcdir)/src/libtracker-common/libtracker-common.vapi \
- $(top_srcdir)/src/libtracker-sparql/tracker-sparql-$(TRACKER_API_VERSION).vapi
-
AM_CPPFLAGS = \
$(BUILD_VALACFLAGS) \
-I$(top_srcdir)/src \
@@ -19,8 +8,7 @@ AM_CPPFLAGS = \
$(LIBTRACKER_DIRECT_CFLAGS)
libtracker_direct_la_SOURCES = \
- tracker-namespace.vala \
- tracker-direct.vala
+ tracker-direct.c
libtracker_direct_la_LIBADD = \
$(top_builddir)/src/libtracker-data/libtracker-data.la \
@@ -30,7 +18,4 @@ libtracker_direct_la_LIBADD = \
noinst_HEADERS = \
tracker-direct.h
-BUILT_SOURCES = \
- libtracker_direct_la_vala.stamp
-
EXTRA_DIST = meson.build
diff --git a/src/libtracker-direct/tracker-direct.c b/src/libtracker-direct/tracker-direct.c
new file mode 100644
index 000000000..7c3b42568
--- /dev/null
+++ b/src/libtracker-direct/tracker-direct.c
@@ -0,0 +1,830 @@
+/*
+ * Copyright (C) 2010, Nokia <ivan.frade@nokia.com>
+ * Copyright (C) 2017, 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.
+ */
+
+#include "config.h"
+
+#include "tracker-direct.h"
+#include <libtracker-data/tracker-data.h>
+
+typedef struct _TrackerDirectConnectionPrivate TrackerDirectConnectionPrivate;
+
+struct _TrackerDirectConnectionPrivate
+{
+ TrackerSparqlConnectionFlags flags;
+ GFile *store;
+ GFile *journal;
+ GFile *ontology;
+
+ TrackerNamespaceManager *namespace_manager;
+ TrackerDataManager *data_manager;
+ GMutex mutex;
+
+ GThreadPool *update_thread; /* Contains 1 exclusive thread */
+ GThreadPool *select_pool;
+
+ guint initialized : 1;
+};
+
+enum {
+ PROP_0,
+ PROP_FLAGS,
+ PROP_STORE_LOCATION,
+ PROP_JOURNAL_LOCATION,
+ PROP_ONTOLOGY_LOCATION,
+ N_PROPS
+};
+
+static GParamSpec *props[N_PROPS] = { NULL };
+
+typedef enum {
+ TASK_TYPE_QUERY,
+ TASK_TYPE_UPDATE,
+ TASK_TYPE_UPDATE_BLANK,
+ TASK_TYPE_TURTLE
+} TaskType;
+
+typedef struct {
+ TaskType type;
+ union {
+ gchar *query;
+ GFile *turtle_file;
+ } data;
+} TaskData;
+
+static void tracker_direct_connection_initable_iface_init (GInitableIface *iface);
+static void tracker_direct_connection_async_initable_iface_init (GAsyncInitableIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (TrackerDirectConnection, tracker_direct_connection,
+ TRACKER_SPARQL_TYPE_CONNECTION,
+ G_ADD_PRIVATE (TrackerDirectConnection)
+ G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
+ tracker_direct_connection_initable_iface_init)
+ G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE,
+ tracker_direct_connection_async_initable_iface_init))
+
+static TaskData *
+task_data_query_new (TaskType type,
+ const gchar *sparql)
+{
+ TaskData *data;
+
+ g_assert (type != TASK_TYPE_TURTLE);
+ data = g_new0 (TaskData, 1);
+ data->type = type;
+ data->data.query = g_strdup (sparql);
+
+ return data;
+}
+
+static TaskData *
+task_data_turtle_new (GFile *file)
+{
+ TaskData *data;
+
+ data = g_new0 (TaskData, 1);
+ data->type = TASK_TYPE_TURTLE;
+ g_set_object (&data->data.turtle_file, file);
+
+ return data;
+}
+
+static void
+task_data_free (TaskData *task)
+{
+ if (task->type == TASK_TYPE_TURTLE)
+ g_object_unref (task->data.turtle_file);
+ else
+ g_free (task->data.query);
+
+ g_free (task);
+}
+
+static void
+update_thread_func (gpointer data,
+ gpointer user_data)
+{
+ TrackerDirectConnectionPrivate *priv;
+ TrackerDirectConnection *conn;
+ GTask *task = data;
+ TaskData *task_data = g_task_get_task_data (task);
+ TrackerData *tracker_data;
+ GError *error = NULL;
+ gpointer retval = NULL;
+ GDestroyNotify destroy_notify = NULL;
+
+ conn = user_data;
+ priv = tracker_direct_connection_get_instance_private (conn);
+
+ g_mutex_lock (&priv->mutex);
+ tracker_data = tracker_data_manager_get_data (priv->data_manager);
+
+ switch (task_data->type) {
+ case TASK_TYPE_QUERY:
+ g_warning ("Queries don't go through this thread");
+ break;
+ case TASK_TYPE_UPDATE:
+ tracker_data_update_sparql (tracker_data, task_data->data.query, &error);
+ break;
+ case TASK_TYPE_UPDATE_BLANK:
+ retval = tracker_data_update_sparql_blank (tracker_data, task_data->data.query, &error);
+ destroy_notify = (GDestroyNotify) g_variant_unref;
+ break;
+ case TASK_TYPE_TURTLE:
+ tracker_data_load_turtle_file (tracker_data, task_data->data.turtle_file, &error);
+ break;
+ }
+
+ if (error)
+ g_task_return_error (task, error);
+ else if (retval)
+ g_task_return_pointer (task, retval, destroy_notify);
+ else
+ g_task_return_boolean (task, TRUE);
+
+ g_mutex_unlock (&priv->mutex);
+}
+
+static void
+query_thread_pool_func (gpointer data,
+ gpointer user_data)
+{
+ TrackerSparqlCursor *cursor;
+ GTask *task = data;
+ TaskData *task_data = g_task_get_task_data (task);
+ GError *error = NULL;
+
+ g_assert (task_data->type == TASK_TYPE_QUERY);
+ cursor = tracker_sparql_connection_query (TRACKER_SPARQL_CONNECTION (g_task_get_source_object (task)),
+ task_data->data.query,
+ g_task_get_cancellable (task),
+ &error);
+ if (cursor)
+ g_task_return_pointer (task, cursor, g_object_unref);
+ else
+ g_task_return_error (task, error);
+}
+
+static void
+wal_checkpoint (TrackerDBInterface *iface,
+ gboolean blocking)
+{
+ GError *error = NULL;
+
+ g_debug ("Checkpointing database...");
+ tracker_db_interface_sqlite_wal_checkpoint (iface, blocking, &error);
+
+ if (error) {
+ g_warning ("Error in WAL checkpoint: %s", error->message);
+ g_error_free (error);
+ }
+
+ g_debug ("Checkpointing complete");
+}
+
+static gpointer
+wal_checkpoint_thread (gpointer data)
+{
+ TrackerDBInterface *wal_iface = data;
+
+ wal_checkpoint (wal_iface, FALSE);
+ g_object_unref (wal_iface);
+ return NULL;
+}
+
+static void
+wal_hook (TrackerDBInterface *iface,
+ gint n_pages)
+{
+ TrackerDataManager *data_manager = tracker_db_interface_get_user_data (iface);
+ TrackerDBInterface *wal_iface = tracker_data_manager_get_wal_db_interface (data_manager);
+
+ if (n_pages >= 10000) {
+ /* Do immediate checkpointing (blocking updates) to
+ * prevent excessive WAL file growth.
+ */
+ wal_checkpoint (wal_iface, TRUE);
+ } else {
+ /* Defer non-blocking checkpoint to thread */
+ g_thread_try_new ("wal-checkpoint", wal_checkpoint_thread,
+ g_object_ref (wal_iface), NULL);
+ }
+}
+
+static gint
+task_compare_func (GTask *a,
+ GTask *b,
+ gpointer user_data)
+{
+ return g_task_get_priority (b) - g_task_get_priority (a);
+}
+
+static gboolean
+tracker_direct_connection_initable_init (GInitable *initable,
+ GCancellable *cancellable,
+ GError **error)
+{
+ TrackerDirectConnectionPrivate *priv;
+ TrackerDirectConnection *conn;
+ TrackerDBManagerFlags db_flags = TRACKER_DB_MANAGER_ENABLE_MUTEXES;
+ TrackerDBInterface *iface;
+ GHashTable *namespaces;
+ GHashTableIter iter;
+ gchar *prefix, *ns;
+
+ conn = TRACKER_DIRECT_CONNECTION (initable);
+ priv = tracker_direct_connection_get_instance_private (conn);
+
+ tracker_locale_sanity_check ();
+
+ priv->select_pool = g_thread_pool_new (query_thread_pool_func,
+ conn, 16, FALSE, error);
+ if (!priv->select_pool)
+ return FALSE;
+
+ priv->update_thread = g_thread_pool_new (update_thread_func,
+ conn, 1, TRUE, error);
+ if (!priv->update_thread)
+ return FALSE;
+
+ g_thread_pool_set_sort_function (priv->select_pool,
+ (GCompareDataFunc) task_compare_func,
+ conn);
+ g_thread_pool_set_sort_function (priv->update_thread,
+ (GCompareDataFunc) task_compare_func,
+ conn);
+
+ /* Init data manager */
+ if (priv->flags & TRACKER_SPARQL_CONNECTION_FLAGS_READONLY)
+ db_flags |= TRACKER_DB_MANAGER_READONLY;
+
+ priv->data_manager = tracker_data_manager_new (db_flags, priv->store,
+ priv->journal, priv->ontology,
+ FALSE, FALSE, 100, 100);
+ if (!g_initable_init (G_INITABLE (priv->data_manager), cancellable, error))
+ return FALSE;
+
+ /* Set up WAL hook on our connection */
+ iface = tracker_data_manager_get_writable_db_interface (priv->data_manager);
+ tracker_db_interface_sqlite_wal_hook (iface, wal_hook);
+
+ /* Initialize namespace manager */
+ priv->namespace_manager = tracker_namespace_manager_new ();
+ namespaces = tracker_data_manager_get_namespaces (priv->data_manager);
+ g_hash_table_iter_init (&iter, namespaces);
+
+ while (g_hash_table_iter_next (&iter, (gpointer*) &prefix, (gpointer*) &ns)) {
+ tracker_namespace_manager_add_prefix (priv->namespace_manager,
+ prefix, ns);
+ }
+
+ return TRUE;
+}
+
+static void
+tracker_direct_connection_initable_iface_init (GInitableIface *iface)
+{
+ iface->init = tracker_direct_connection_initable_init;
+}
+
+static void
+async_initable_thread_func (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ GError *error = NULL;
+
+ if (!g_initable_init (G_INITABLE (source_object), cancellable, &error))
+ g_task_return_error (task, error);
+ else
+ g_task_return_boolean (task, TRUE);
+}
+
+static void
+tracker_direct_connection_async_initable_init_async (GAsyncInitable *async_initable,
+ gint priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GTask *task;
+
+ task = g_task_new (async_initable, cancellable, callback, user_data);
+ g_task_set_priority (task, priority);
+ g_task_run_in_thread (task, async_initable_thread_func);
+}
+
+static gboolean
+tracker_direct_connection_async_initable_init_finish (GAsyncInitable *async_initable,
+ GAsyncResult *res,
+ GError **error)
+{
+ return g_task_propagate_boolean (G_TASK (res), error);
+}
+
+static void
+tracker_direct_connection_async_initable_iface_init (GAsyncInitableIface *iface)
+{
+ iface->init_async = tracker_direct_connection_async_initable_init_async;
+ iface->init_finish = tracker_direct_connection_async_initable_init_finish;
+}
+
+static void
+tracker_direct_connection_init (TrackerDirectConnection *conn)
+{
+}
+
+static void
+tracker_direct_connection_finalize (GObject *object)
+{
+ TrackerDirectConnectionPrivate *priv;
+ TrackerDirectConnection *conn;
+
+ conn = TRACKER_DIRECT_CONNECTION (object);
+ priv = tracker_direct_connection_get_instance_private (conn);
+
+ if (priv->update_thread)
+ g_thread_pool_free (priv->update_thread, TRUE, TRUE);
+ if (priv->select_pool)
+ g_thread_pool_free (priv->select_pool, TRUE, FALSE);
+
+ if (priv->data_manager) {
+ TrackerDBInterface *wal_iface;
+ wal_iface = tracker_data_manager_get_wal_db_interface (priv->data_manager);
+ tracker_db_interface_sqlite_wal_checkpoint (wal_iface, TRUE, NULL);
+ }
+
+ g_clear_object (&priv->store);
+ g_clear_object (&priv->journal);
+ g_clear_object (&priv->ontology);
+ g_clear_object (&priv->data_manager);
+
+ G_OBJECT_CLASS (tracker_direct_connection_parent_class)->finalize (object);
+}
+
+static void
+tracker_direct_connection_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ TrackerDirectConnectionPrivate *priv;
+ TrackerDirectConnection *conn;
+
+ conn = TRACKER_DIRECT_CONNECTION (object);
+ priv = tracker_direct_connection_get_instance_private (conn);
+
+ switch (prop_id) {
+ case PROP_FLAGS:
+ priv->flags = g_value_get_enum (value);
+ break;
+ case PROP_STORE_LOCATION:
+ priv->store = g_value_dup_object (value);
+ break;
+ case PROP_JOURNAL_LOCATION:
+ priv->journal = g_value_dup_object (value);
+ break;
+ case PROP_ONTOLOGY_LOCATION:
+ priv->ontology = g_value_dup_object (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+tracker_direct_connection_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ TrackerDirectConnectionPrivate *priv;
+ TrackerDirectConnection *conn;
+
+ conn = TRACKER_DIRECT_CONNECTION (object);
+ priv = tracker_direct_connection_get_instance_private (conn);
+
+ switch (prop_id) {
+ case PROP_FLAGS:
+ g_value_set_enum (value, priv->flags);
+ break;
+ case PROP_STORE_LOCATION:
+ g_value_set_object (value, priv->store);
+ break;
+ case PROP_JOURNAL_LOCATION:
+ g_value_set_object (value, priv->journal);
+ break;
+ case PROP_ONTOLOGY_LOCATION:
+ g_value_set_object (value, priv->ontology);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static TrackerSparqlCursor *
+tracker_direct_connection_query (TrackerSparqlConnection *self,
+ const gchar *sparql,
+ GCancellable *cancellable,
+ GError **error)
+{
+ TrackerDirectConnectionPrivate *priv;
+ TrackerDirectConnection *conn;
+ TrackerSparqlQuery *query;
+ TrackerSparqlCursor *cursor;
+
+ conn = TRACKER_DIRECT_CONNECTION (self);
+ priv = tracker_direct_connection_get_instance_private (conn);
+
+ g_mutex_lock (&priv->mutex);
+ query = tracker_sparql_query_new (priv->data_manager, sparql);
+ cursor = TRACKER_SPARQL_CURSOR (tracker_sparql_query_execute_cursor (query, error));
+ if (cursor)
+ tracker_sparql_cursor_set_connection (cursor, self);
+ g_mutex_unlock (&priv->mutex);
+
+ return cursor;
+}
+
+static void
+tracker_direct_connection_query_async (TrackerSparqlConnection *self,
+ const gchar *sparql,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ TrackerDirectConnectionPrivate *priv;
+ TrackerDirectConnection *conn;
+ GError *error = NULL;
+ GTask *task;
+
+ conn = TRACKER_DIRECT_CONNECTION (self);
+ priv = tracker_direct_connection_get_instance_private (conn);
+
+ task = g_task_new (self, cancellable, callback, user_data);
+ g_task_set_task_data (task,
+ task_data_query_new (TASK_TYPE_QUERY, sparql),
+ (GDestroyNotify) task_data_free);
+
+ if (!g_thread_pool_push (priv->select_pool, task, &error))
+ g_task_return_error (task, error);
+}
+
+static TrackerSparqlCursor *
+tracker_direct_connection_query_finish (TrackerSparqlConnection *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ return g_task_propagate_pointer (G_TASK (res), error);
+}
+
+static void
+tracker_direct_connection_update (TrackerSparqlConnection *self,
+ const gchar *sparql,
+ gint priority,
+ GCancellable *cancellable,
+ GError **error)
+{
+ TrackerDirectConnectionPrivate *priv;
+ TrackerDirectConnection *conn;
+ TrackerData *data;
+ GTask *task;
+
+ conn = TRACKER_DIRECT_CONNECTION (self);
+ priv = tracker_direct_connection_get_instance_private (conn);
+
+ g_mutex_lock (&priv->mutex);
+ data = tracker_data_manager_get_data (priv->data_manager);
+ tracker_data_update_sparql (data, sparql, error);
+ g_mutex_unlock (&priv->mutex);
+}
+
+static void
+tracker_direct_connection_update_async (TrackerSparqlConnection *self,
+ const gchar *sparql,
+ gint priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ TrackerDirectConnectionPrivate *priv;
+ TrackerDirectConnection *conn;
+ GTask *task;
+
+ conn = TRACKER_DIRECT_CONNECTION (self);
+ priv = tracker_direct_connection_get_instance_private (conn);
+
+ task = g_task_new (self, cancellable, callback, user_data);
+ g_task_set_priority (task, priority);
+ g_task_set_task_data (task,
+ task_data_query_new (TASK_TYPE_UPDATE, sparql),
+ (GDestroyNotify) task_data_free);
+
+ g_thread_pool_push (priv->update_thread, task, NULL);
+}
+
+static void
+tracker_direct_connection_update_finish (TrackerSparqlConnection *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ g_task_propagate_boolean (G_TASK (res), error);
+}
+
+static void
+error_free (GError *error)
+{
+ if (error)
+ g_error_free (error);
+}
+
+static void
+update_array_async_thread_func (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ gchar **updates = task_data;
+ gchar *concatenated;
+ GPtrArray *errors;
+ GError *error = NULL;
+ gint i;
+
+ errors = g_ptr_array_new_with_free_func ((GDestroyNotify) error_free);
+ g_ptr_array_set_size (errors, g_strv_length (updates));
+
+ /* Fast path, perform everything as a single update */
+ concatenated = g_strjoinv (" ", updates);
+ tracker_sparql_connection_update (source_object, concatenated,
+ g_task_get_priority (task),
+ cancellable, &error);
+
+ if (!error) {
+ g_task_return_pointer (task, errors,
+ (GDestroyNotify) g_ptr_array_unref);
+ return;
+ }
+
+ /* Slow path, perform updates one by one */
+ for (i = 0; updates[i]; i++) {
+ GError *err = NULL;
+
+ err = g_ptr_array_index (errors, i);
+ tracker_sparql_connection_update (source_object, updates[i],
+ g_task_get_priority (task),
+ cancellable, &err);
+ }
+
+ g_task_return_pointer (task, errors,
+ (GDestroyNotify) g_ptr_array_unref);
+}
+
+static void
+tracker_direct_connection_update_array_async (TrackerSparqlConnection *self,
+ gchar **updates,
+ gint n_updates,
+ gint priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GTask *task;
+ gchar **copy;
+ gint i = 0, idx = 0;
+
+ copy = g_new0 (gchar*, n_updates + 1);
+
+ for (i = 0; i < n_updates; i++) {
+ g_return_if_fail (updates[i] != NULL);
+ copy[i] = g_strdup (updates[i]);
+ }
+
+ task = g_task_new (self, cancellable, callback, user_data);
+ g_task_set_priority (task, priority);
+ g_task_set_task_data (task, copy, (GDestroyNotify) g_strfreev);
+
+ g_task_run_in_thread (task, update_array_async_thread_func);
+}
+
+static GPtrArray *
+tracker_direct_connection_update_array_finish (TrackerSparqlConnection *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ return g_task_propagate_pointer (G_TASK (res), error);
+}
+
+static GVariant *
+tracker_direct_connection_update_blank (TrackerSparqlConnection *self,
+ const gchar *sparql,
+ gint priority,
+ GCancellable *cancellable,
+ GError **error)
+{
+ TrackerDirectConnectionPrivate *priv;
+ TrackerDirectConnection *conn;
+ TrackerData *data;
+ GVariant *blank_nodes;
+
+ conn = TRACKER_DIRECT_CONNECTION (self);
+ priv = tracker_direct_connection_get_instance_private (conn);
+
+ g_mutex_lock (&priv->mutex);
+ data = tracker_data_manager_get_data (priv->data_manager);
+ blank_nodes = tracker_data_update_sparql_blank (data, sparql, error);
+ g_mutex_unlock (&priv->mutex);
+
+ return blank_nodes;
+}
+
+static void
+tracker_direct_connection_update_blank_async (TrackerSparqlConnection *self,
+ const gchar *sparql,
+ gint priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ TrackerDirectConnectionPrivate *priv;
+ TrackerDirectConnection *conn;
+ GTask *task;
+
+ conn = TRACKER_DIRECT_CONNECTION (self);
+ priv = tracker_direct_connection_get_instance_private (conn);
+
+ task = g_task_new (self, cancellable, callback, user_data);
+ g_task_set_priority (task, priority);
+ g_task_set_task_data (task,
+ task_data_query_new (TASK_TYPE_UPDATE_BLANK, sparql),
+ (GDestroyNotify) task_data_free);
+
+ g_thread_pool_push (priv->update_thread, task, NULL);
+}
+
+static GVariant *
+tracker_direct_connection_update_blank_finish (TrackerSparqlConnection *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ return g_task_propagate_pointer (G_TASK (res), error);
+}
+
+static void
+tracker_direct_connection_load (TrackerSparqlConnection *self,
+ GFile *file,
+ GCancellable *cancellable,
+ GError **error)
+{
+ TrackerDirectConnectionPrivate *priv;
+ TrackerDirectConnection *conn;
+ TrackerData *data;
+
+ conn = TRACKER_DIRECT_CONNECTION (self);
+ priv = tracker_direct_connection_get_instance_private (conn);
+
+ g_mutex_lock (&priv->mutex);
+ data = tracker_data_manager_get_data (priv->data_manager);
+ tracker_data_load_turtle_file (data, file, error);
+ g_mutex_unlock (&priv->mutex);
+}
+
+static void
+tracker_direct_connection_load_async (TrackerSparqlConnection *self,
+ GFile *file,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ TrackerDirectConnectionPrivate *priv;
+ TrackerDirectConnection *conn;
+ GTask *task;
+
+ conn = TRACKER_DIRECT_CONNECTION (self);
+ priv = tracker_direct_connection_get_instance_private (conn);
+
+ task = g_task_new (self, cancellable, callback, user_data);
+ g_task_set_task_data (task,
+ task_data_turtle_new (file),
+ (GDestroyNotify) task_data_free);
+
+ g_thread_pool_push (priv->update_thread, task, NULL);
+}
+
+static void
+tracker_direct_connection_load_finish (TrackerSparqlConnection *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ g_task_propagate_pointer (G_TASK (res), error);
+}
+
+static TrackerNamespaceManager *
+tracker_direct_connection_get_namespace_manager (TrackerSparqlConnection *self)
+{
+ TrackerDirectConnectionPrivate *priv;
+
+ priv = tracker_direct_connection_get_instance_private (TRACKER_DIRECT_CONNECTION (self));
+
+ return priv->namespace_manager;
+}
+
+static void
+tracker_direct_connection_class_init (TrackerDirectConnectionClass *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_direct_connection_finalize;
+ object_class->set_property = tracker_direct_connection_set_property;
+ object_class->get_property = tracker_direct_connection_get_property;
+
+ sparql_connection_class->query = tracker_direct_connection_query;
+ sparql_connection_class->query_async = tracker_direct_connection_query_async;
+ sparql_connection_class->query_finish = tracker_direct_connection_query_finish;
+ sparql_connection_class->update = tracker_direct_connection_update;
+ sparql_connection_class->update_async = tracker_direct_connection_update_async;
+ sparql_connection_class->update_finish = tracker_direct_connection_update_finish;
+ sparql_connection_class->update_array_async = tracker_direct_connection_update_array_async;
+ sparql_connection_class->update_array_finish = tracker_direct_connection_update_array_finish;
+ sparql_connection_class->update_blank = tracker_direct_connection_update_blank;
+ sparql_connection_class->update_blank_async = tracker_direct_connection_update_blank_async;
+ sparql_connection_class->update_blank_finish = tracker_direct_connection_update_blank_finish;
+ sparql_connection_class->load = tracker_direct_connection_load;
+ sparql_connection_class->load_async = tracker_direct_connection_load_async;
+ sparql_connection_class->load_finish = tracker_direct_connection_load_finish;
+ sparql_connection_class->get_namespace_manager = tracker_direct_connection_get_namespace_manager;
+
+ props[PROP_FLAGS] =
+ g_param_spec_enum ("flags",
+ "Flags",
+ "Flags",
+ TRACKER_SPARQL_TYPE_CONNECTION_FLAGS,
+ TRACKER_SPARQL_CONNECTION_FLAGS_NONE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY);
+ props[PROP_STORE_LOCATION] =
+ g_param_spec_object ("store-location",
+ "Store location",
+ "Store location",
+ G_TYPE_FILE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY);
+ props[PROP_JOURNAL_LOCATION] =
+ g_param_spec_object ("journal-location",
+ "Journal location",
+ "Journal location",
+ G_TYPE_FILE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY);
+ props[PROP_ONTOLOGY_LOCATION] =
+ g_param_spec_object ("ontology-location",
+ "Ontology location",
+ "Ontology location",
+ G_TYPE_FILE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY);
+
+ g_object_class_install_properties (object_class, N_PROPS, props);
+}
+
+TrackerDirectConnection *
+tracker_direct_connection_new (TrackerSparqlConnectionFlags flags,
+ GFile *store,
+ GFile *journal,
+ GFile *ontology,
+ GError **error)
+{
+ g_return_val_if_fail (G_IS_FILE (store), NULL);
+ g_return_val_if_fail (G_IS_FILE (journal), NULL);
+ g_return_val_if_fail (G_IS_FILE (ontology), NULL);
+ g_return_val_if_fail (!error || !*error, NULL);
+
+ return g_object_new (TRACKER_TYPE_DIRECT_CONNECTION,
+ "flags", flags,
+ "store-location", store,
+ "journal-location", journal,
+ "ontology-location", ontology,
+ NULL);
+}
diff --git a/src/libtracker-direct/tracker-direct.h b/src/libtracker-direct/tracker-direct.h
new file mode 100644
index 000000000..105602b2a
--- /dev/null
+++ b/src/libtracker-direct/tracker-direct.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2010, Nokia <ivan.frade@nokia.com>
+ * Copyright (C) 2017, 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.
+ */
+
+#ifndef __TRACKER_LOCAL_CONNECTION_H__
+#define __TRACKER_LOCAL_CONNECTION_H__
+
+#include <libtracker-sparql/tracker-sparql.h>
+
+#define TRACKER_TYPE_DIRECT_CONNECTION (tracker_direct_connection_get_type())
+#define TRACKER_DIRECT_CONNECTION(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_DIRECT_CONNECTION, TrackerDirectConnection))
+#define TRACKER_DIRECT_CONNECTION_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), TRACKER_TYPE_DIRECT_CONNECTION, TrackerDirectConnectionClass))
+#define TRACKER_IS_DIRECT_CONNECTION(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TRACKER_TYPE_DIRECT_CONNECTION))
+#define TRACKER_IS_DIRECT_CONNECTION_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), TRACKER_TYPE_DIRECT_CONNECTION))
+#define TRACKER_DIRECT_CONNECTION_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TRACKER_TYPE_DIRECT_CONNECTION, TrackerDirectConnectionClass))
+
+typedef struct _TrackerDirectConnection TrackerDirectConnection;
+typedef struct _TrackerDirectConnectionClass TrackerDirectConnectionClass;
+
+struct _TrackerDirectConnectionClass
+{
+ TrackerSparqlConnectionClass parent_class;
+};
+
+struct _TrackerDirectConnection
+{
+ TrackerSparqlConnection parent_instance;
+};
+
+TrackerDirectConnection *tracker_direct_connection_new (TrackerSparqlConnectionFlags flags,
+ GFile *store,
+ GFile *journal,
+ GFile *ontology,
+ GError **error);
+
+#endif /* __TRACKER_LOCAL_CONNECTION_H__ */
diff --git a/src/libtracker-direct/tracker-direct.vala b/src/libtracker-direct/tracker-direct.vala
deleted file mode 100644
index b149b6806..000000000
--- a/src/libtracker-direct/tracker-direct.vala
+++ /dev/null
@@ -1,405 +0,0 @@
-/*
- * Copyright (C) 2010, Nokia <ivan.frade@nokia.com>
- * Copyright (C) 2017, 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.
- */
-
-public class Tracker.Direct.Connection : Tracker.Sparql.Connection, AsyncInitable, Initable {
- File? database_loc;
- File? journal_loc;
- File? ontology_loc;
- Sparql.ConnectionFlags flags;
-
- Data.Manager data_manager;
-
- // Mutex to hold datamanager
- private Mutex mutex = Mutex ();
- Thread<void*> thread;
-
- // Initialization stuff, both sync and async
- private Mutex init_mutex = Mutex ();
- private Cond init_cond = Cond ();
- private bool initialized;
- private Error init_error;
- public SourceFunc init_callback;
-
- private AsyncQueue<Task> update_queue;
- private NamespaceManager namespace_manager;
-
- [CCode (cname = "SHAREDIR")]
- extern const string SHAREDIR;
-
- enum TaskType {
- QUERY,
- UPDATE,
- UPDATE_BLANK,
- TURTLE,
- }
-
- abstract class Task {
- public TaskType type;
- public int priority;
- public Cancellable? cancellable;
- public SourceFunc callback;
- public Error error;
- }
-
- private class UpdateTask : Task {
- public string sparql;
- public Variant blank_nodes;
-
- private void set (TaskType type, string sparql, int priority = Priority.DEFAULT, Cancellable? cancellable = null) {
- this.type = type;
- this.sparql = sparql;
- this.priority = priority;
- this.cancellable = cancellable;
- }
-
- public UpdateTask (string sparql, int priority = Priority.DEFAULT, Cancellable? cancellable) {
- this.set (TaskType.UPDATE, sparql, priority, cancellable);
- }
-
- public UpdateTask.blank (string sparql, int priority = Priority.DEFAULT, Cancellable? cancellable) {
- this.set (TaskType.UPDATE_BLANK, sparql, priority, cancellable);
- }
- }
-
- private class TurtleTask : Task {
- public File file;
-
- public TurtleTask (File file, Cancellable? cancellable) {
- this.type = TaskType.TURTLE;
- this.file = file;
- this.priority = Priority.DEFAULT;
- this.cancellable = cancellable;
- }
- }
-
- static void wal_checkpoint (DBInterface iface, bool blocking) {
- try {
- debug ("Checkpointing database...");
- iface.sqlite_wal_checkpoint (blocking);
- debug ("Checkpointing complete...");
- } catch (Error e) {
- warning (e.message);
- }
- }
-
- static void wal_checkpoint_on_thread (DBInterface iface) {
- new Thread<void*> ("wal-checkpoint", () => {
- wal_checkpoint (iface, false);
- return null;
- });
- }
-
- static void wal_hook (DBInterface iface, int n_pages) {
- var manager = (Data.Manager) iface.get_user_data ();
- var wal_iface = manager.get_wal_db_interface ();
-
- if (n_pages >= 10000) {
- // do immediate checkpointing (blocking updates)
- // to prevent excessive wal file growth
- wal_checkpoint (wal_iface, true);
- } else if (n_pages >= 1000) {
- wal_checkpoint_on_thread (wal_iface);
- }
- }
-
- private void* thread_func () {
- init_mutex.lock ();
-
- try {
- Locale.sanity_check ();
- DBManagerFlags db_flags = DBManagerFlags.ENABLE_MUTEXES;
- if ((flags & Sparql.ConnectionFlags.READONLY) != 0)
- db_flags |= DBManagerFlags.READONLY;
-
- data_manager = new Data.Manager (db_flags,
- database_loc, journal_loc, ontology_loc,
- false, false, 100, 100);
- data_manager.init ();
-
- var iface = data_manager.get_writable_db_interface ();
- iface.sqlite_wal_hook (wal_hook);
- } catch (Error e) {
- init_error = e;
- } finally {
- if (init_callback != null) {
- init_callback ();
- } else {
- initialized = true;
- init_cond.signal ();
- init_mutex.unlock ();
- }
- }
-
- while (true) {
- var task = update_queue.pop();
-
- try {
- switch (task.type) {
- case TaskType.UPDATE:
- UpdateTask update_task = (UpdateTask) task;
- update (update_task.sparql, update_task.priority, update_task.cancellable);
- break;
- case TaskType.UPDATE_BLANK:
- UpdateTask update_task = (UpdateTask) task;
- update_task.blank_nodes = update_blank (update_task.sparql, update_task.priority, update_task.cancellable);
- break;
- case TaskType.TURTLE:
- TurtleTask turtle_task = (TurtleTask) task;
- load (turtle_task.file, turtle_task.cancellable);
- break;
- default:
- break;
- }
- } catch (Error e) {
- task.error = e;
- }
-
- task.callback ();
- }
- }
-
- public async bool init_async (int io_priority, Cancellable? cancellable) throws Error {
- init_callback = init_async.callback;
- thread = new Thread<void*> ("database", thread_func);
-
- return initialized;
- }
-
- public bool init (Cancellable? cancellable) throws Error {
- try {
- thread = new Thread<void*> ("database", thread_func);
-
- init_mutex.lock ();
- while (!initialized)
- init_cond.wait(init_mutex);
- init_mutex.unlock ();
-
- if (init_error != null)
- throw init_error;
- } catch (Error e) {
- throw new Sparql.Error.INTERNAL (e.message);
- }
-
- return true;
- }
-
- public Connection (Sparql.ConnectionFlags connection_flags, File loc, File? journal, File? ontology) throws Sparql.Error, IOError, DBusError {
- database_loc = loc;
- journal_loc = journal;
- ontology_loc = ontology;
- flags = connection_flags;
-
- if (journal_loc == null)
- journal_loc = database_loc;
- if (ontology_loc == null)
- ontology_loc = File.new_for_path (Path.build_filename (SHAREDIR, "tracker", "ontologies", "nepomuk"));
-
- update_queue = new AsyncQueue<Task> ();
- }
-
- public override void dispose () {
- data_manager.shutdown ();
- base.dispose ();
- }
-
- Sparql.Cursor query_unlocked (string sparql) throws Sparql.Error, DBusError {
- try {
- var query_object = new Sparql.Query (data_manager, sparql);
- var cursor = query_object.execute_cursor ();
- cursor.connection = this;
- return cursor;
- } catch (DBInterfaceError e) {
- throw new Sparql.Error.INTERNAL (e.message);
- } catch (DateError e) {
- throw new Sparql.Error.PARSE (e.message);
- }
- }
-
- public override Sparql.Cursor query (string sparql, Cancellable? cancellable) throws Sparql.Error, IOError, DBusError {
- // Check here for early cancellation, just in case
- // the operation can be entirely avoided
- if (cancellable != null && cancellable.is_cancelled ()) {
- throw new IOError.CANCELLED ("Operation was cancelled");
- }
-
- mutex.lock ();
- try {
- return query_unlocked (sparql);
- } finally {
- mutex.unlock ();
- }
- }
-
- public async override Sparql.Cursor query_async (string sparql, Cancellable? cancellable) throws Sparql.Error, IOError, DBusError {
- // run in a separate thread
- Sparql.Error sparql_error = null;
- IOError io_error = null;
- DBusError dbus_error = null;
- GLib.Error error = null;
- Sparql.Cursor result = null;
- var context = MainContext.get_thread_default ();
-
- IOSchedulerJob.push ((job, cancellable) => {
- try {
- result = query (sparql, cancellable);
- } catch (IOError e_io) {
- io_error = e_io;
- } catch (Sparql.Error e_spql) {
- sparql_error = e_spql;
- } catch (DBusError e_dbus) {
- dbus_error = e_dbus;
- } catch (GLib.Error e) {
- error = e;
- }
-
- context.invoke (() => {
- query_async.callback ();
- return false;
- });
-
- return false;
- }, Priority.DEFAULT, cancellable);
-
- yield;
-
- if (cancellable != null && cancellable.is_cancelled ()) {
- throw new IOError.CANCELLED ("Operation was cancelled");
- } else if (sparql_error != null) {
- throw sparql_error;
- } else if (io_error != null) {
- throw io_error;
- } else if (dbus_error != null) {
- throw dbus_error;
- } else {
- return result;
- }
- }
-
- public override void update (string sparql, int priority = GLib.Priority.DEFAULT, Cancellable? cancellable = null) throws Sparql.Error, IOError, DBusError, GLib.Error {
- mutex.lock ();
- try {
- var data = data_manager.get_data ();
- data.update_sparql (sparql);
- } finally {
- mutex.unlock ();
- }
- }
-
- public async override void update_async (string sparql, int priority = GLib.Priority.DEFAULT, Cancellable? cancellable = null) throws Sparql.Error, IOError, DBusError, GLib.Error {
- var task = new UpdateTask (sparql, priority, cancellable);
- task.callback = update_async.callback;
- update_queue.push (task);
- yield;
-
- if (task.error != null)
- throw task.error;
- }
-
- public override GLib.Variant? update_blank (string sparql, int priority = GLib.Priority.DEFAULT, Cancellable? cancellable = null) throws Sparql.Error, IOError, DBusError, GLib.Error {
- GLib.Variant? blank_nodes = null;
- mutex.lock ();
- try {
- var data = data_manager.get_data ();
- blank_nodes = data.update_sparql_blank (sparql);
- } finally {
- mutex.unlock ();
- }
-
- return blank_nodes;
- }
-
- public async override GLib.Variant? update_blank_async (string sparql, int priority = GLib.Priority.DEFAULT, Cancellable? cancellable = null) throws Sparql.Error, IOError, DBusError, GLib.Error {
- var task = new UpdateTask.blank (sparql, priority, cancellable);
- task.callback = update_blank_async.callback;
- update_queue.push (task);
- yield;
-
- if (task.error != null)
- throw task.error;
-
- return task.blank_nodes;
- }
-
- public async override GenericArray<Sparql.Error?>? update_array_async (string[] sparql, int priority = GLib.Priority.DEFAULT, Cancellable? cancellable = null) throws Sparql.Error, GLib.Error, GLib.IOError, DBusError {
- var combined_query = new StringBuilder ();
- var n_updates = sparql.length;
- int i;
-
- for (i = 0; i < n_updates; i++)
- combined_query.append (sparql[i]);
-
- var task = new UpdateTask (combined_query.str, priority, cancellable);
- task.callback = update_array_async.callback;
- update_queue.push (task);
- yield;
-
- var errors = new GenericArray<Sparql.Error?> (n_updates);
-
- if (task.error == null) {
- for (i = 0; i < n_updates; i++)
- errors.add (null);
- } else {
- // combined query was not successful, try queries one by one
- for (i = 0; i < n_updates; i++) {
- try {
- yield update_async (sparql[i], priority, cancellable);
- errors.add (null);
- } catch (Sparql.Error e) {
- errors.add (e);
- }
- }
- }
-
- return errors;
- }
-
- public override void load (File file, Cancellable? cancellable = null) throws Sparql.Error, IOError, DBusError {
- mutex.lock ();
- try {
- var data = data_manager.get_data ();
- data.load_turtle_file (file);
- } finally {
- mutex.unlock ();
- }
- }
-
- public async override void load_async (File file, Cancellable? cancellable = null) throws Sparql.Error, IOError, DBusError {
- var task = new TurtleTask (file, cancellable);
- task.callback = load_async.callback;
- update_queue.push (task);
- yield;
-
- if (task.error != null)
- throw new Sparql.Error.INTERNAL (task.error.message);
- }
-
- public override NamespaceManager? get_namespace_manager () {
- if (namespace_manager == null && data_manager != null) {
- var ht = data_manager.get_namespaces ();
- namespace_manager = new NamespaceManager ();
-
- foreach (var prefix in ht.get_keys ()) {
- namespace_manager.add_prefix (prefix, ht.lookup (prefix));
- }
- }
-
- return namespace_manager;
- }
-}
diff --git a/src/libtracker-direct/tracker-direct.vapi b/src/libtracker-direct/tracker-direct.vapi
new file mode 100644
index 000000000..d1678f353
--- /dev/null
+++ b/src/libtracker-direct/tracker-direct.vapi
@@ -0,0 +1,10 @@
+[CCode (cprefix = "Tracker", gir_namespace = "Tracker", gir_version = "2.0", lower_case_cprefix = "tracker_")]
+namespace Tracker {
+ namespace Direct {
+ [CCode (cheader_filename = "libtracker-direct/tracker-direct.h")]
+ public class Connection : Tracker.Sparql.Connection, GLib.Initable, GLib.AsyncInitable {
+ public Connection (Tracker.Sparql.ConnectionFlags connection_flags, GLib.File loc, GLib.File? journal, GLib.File? ontology) throws Tracker.Sparql.Error, GLib.IOError, GLib.DBusError;
+ public Tracker.Data.Manager get_data_manager ();
+ }
+ }
+}
diff --git a/src/libtracker-direct/tracker-namespace.vala b/src/libtracker-direct/tracker-namespace.vala
deleted file mode 100644
index 24d7b2ee8..000000000
--- a/src/libtracker-direct/tracker-namespace.vala
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright © 2015 Collabora 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.
- */
-
-/*
- * This file serves as the representation for the Tracker namespace, mostly
- * so that we can set its namespace and version attributes for GIR.
- */
-
-[CCode (cprefix = "TrackerDirect", gir_namespace = "TrackerDirect",
- gir_version = "2.0", lower_case_cprefix = "tracker_direct_")]
-namespace Tracker
-{
-}