[tracker/wip/carlosg/remote-namespace-manager: 5/6] libtracker-sparql: Implement get_namespace_manager() in remote connections




commit 1943495371c04929780c8786cd8830f08fac57c4
Author: Carlos Garnacho <carlosg gnome org>
Date:   Sun Apr 17 00:00:02 2022 +0200

    libtracker-sparql: Implement get_namespace_manager() in remote connections
    
    Add a TrackerNamespaceManager implementation that figures out the relevant
    prefixes from a DESCRIBE query on an empty URI, since the produced Turtle will
    contain the prefixes relevant to the connection, we can populate the
    namespace manager from there.

 src/libtracker-sparql/remote/meson.build           |   1 +
 .../remote/tracker-remote-namespaces.c             | 270 +++++++++++++++++++++
 .../remote/tracker-remote-namespaces.h             |  42 ++++
 src/libtracker-sparql/remote/tracker-remote.vala   |   8 +
 src/libtracker-sparql/remote/tracker-remote.vapi   |   5 +
 src/libtracker-sparql/tracker-namespace-manager.c  |   4 -
 src/libtracker-sparql/tracker-private.h            |   4 +
 7 files changed, 330 insertions(+), 4 deletions(-)
---
diff --git a/src/libtracker-sparql/remote/meson.build b/src/libtracker-sparql/remote/meson.build
index cf5b29e9c..d41c96509 100644
--- a/src/libtracker-sparql/remote/meson.build
+++ b/src/libtracker-sparql/remote/meson.build
@@ -1,6 +1,7 @@
 remote_files = files(
     'tracker-http.c',
     'tracker-remote-statement.c',
+    'tracker-remote-namespaces.c',
     'tracker-remote.vapi',
     'tracker-remote.vala',
 )
diff --git a/src/libtracker-sparql/remote/tracker-remote-namespaces.c 
b/src/libtracker-sparql/remote/tracker-remote-namespaces.c
new file mode 100644
index 000000000..2c88d48f0
--- /dev/null
+++ b/src/libtracker-sparql/remote/tracker-remote-namespaces.c
@@ -0,0 +1,270 @@
+/*
+ * 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-remote-namespaces.h"
+#include "tracker-private.h"
+
+#include <libtracker-sparql/tracker-deserializer.h>
+
+struct _TrackerRemoteNamespaceManager {
+       TrackerNamespaceManager parent_instance;
+       TrackerSparqlConnection *conn;
+};
+
+typedef struct {
+       TrackerNamespaceManager *manager;
+       GMainLoop *main_loop;
+       GError *error;
+} SerializeSyncData;
+
+enum {
+       PROP_0,
+       PROP_CONNECTION,
+       N_PROPS
+};
+
+static GParamSpec *props[N_PROPS];
+
+static void
+tracker_remote_namespace_manager_async_initable_iface_init (GAsyncInitableIface *iface);
+static void
+tracker_remote_namespace_manager_initable_iface_init (GInitableIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (TrackerRemoteNamespaceManager,
+                         tracker_remote_namespace_manager,
+                         TRACKER_TYPE_NAMESPACE_MANAGER,
+                        G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
+                                               tracker_remote_namespace_manager_initable_iface_init)
+                         G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE,
+                                                tracker_remote_namespace_manager_async_initable_iface_init))
+
+static gboolean
+initialize_namespaces_from_rdf (TrackerNamespaceManager  *manager,
+                               GInputStream             *istream,
+                               GError                  **error)
+{
+       TrackerSparqlCursor *deserializer;
+       GError *inner_error = NULL;
+
+       deserializer = tracker_deserializer_new (istream, manager, TRACKER_SERIALIZER_FORMAT_TTL);
+
+       /* We don't care much about the content, just to have the
+        * prefixes parsed.
+        */
+       tracker_sparql_cursor_next (deserializer, NULL, &inner_error);
+       g_object_unref (deserializer);
+
+       if (inner_error) {
+               g_propagate_error (error, inner_error);
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+static void
+serialize_cb (GObject      *source,
+              GAsyncResult *res,
+              gpointer      user_data)
+{
+       GTask *task = user_data;
+       TrackerNamespaceManager *manager =
+               TRACKER_NAMESPACE_MANAGER (g_task_get_source_object (task));
+       TrackerRemoteNamespaceManager *remote_manager =
+               TRACKER_REMOTE_NAMESPACE_MANAGER (manager);
+       GInputStream *istream;
+       GError *error = NULL;
+
+       istream = tracker_sparql_connection_serialize_finish (remote_manager->conn,
+                                                             res,
+                                                             &error);
+       if (!istream) {
+               g_task_return_error (task, error);
+               g_object_unref (task);
+               return;
+       }
+
+       if (!initialize_namespaces_from_rdf (manager, istream, &error)) {
+               g_task_return_error (task, error);
+               g_object_unref (task);
+               return;
+       }
+
+       g_task_return_boolean (task, TRUE);
+       g_object_unref (task);
+}
+
+static void
+tracker_remote_namespace_manager_init_async (GAsyncInitable      *initable,
+                                             int                  io_priority,
+                                             GCancellable        *cancellable,
+                                             GAsyncReadyCallback  callback,
+                                             gpointer             user_data)
+{
+       TrackerRemoteNamespaceManager *manager =
+               TRACKER_REMOTE_NAMESPACE_MANAGER (initable);
+       GTask *task;
+
+       task = g_task_new (manager, NULL, callback, user_data);
+
+       /* Make a query for an empty URI, we only want the namespaces */
+       tracker_sparql_connection_serialize_async (manager->conn,
+                                                  TRACKER_SERIALIZE_FLAGS_NONE,
+                                                  TRACKER_RDF_FORMAT_TURTLE,
+                                                  "DESCRIBE <>",
+                                                  NULL,
+                                                  serialize_cb,
+                                                  task);
+}
+
+static gboolean
+tracker_remote_namespace_manager_init_finish (GAsyncInitable  *initable,
+                                              GAsyncResult    *res,
+                                              GError         **error)
+{
+       return g_task_propagate_boolean (G_TASK (res), error);
+}
+
+static void
+serialize_sync_cb (GObject      *source,
+                  GAsyncResult *res,
+                  gpointer      user_data)
+{
+       SerializeSyncData *data = user_data;
+
+       g_async_initable_init_finish (G_ASYNC_INITABLE (source), res, &data->error);
+       g_main_loop_quit (data->main_loop);
+}
+
+static gboolean
+tracker_remote_namespace_manager_initable_init (GInitable     *initable,
+                                               GCancellable  *cancellable,
+                                               GError       **error)
+{
+       TrackerRemoteNamespaceManager *manager =
+               TRACKER_REMOTE_NAMESPACE_MANAGER (initable);
+       SerializeSyncData data = { 0 };
+
+       data.manager = TRACKER_NAMESPACE_MANAGER (manager);
+       data.main_loop = g_main_loop_new (g_main_context_get_thread_default (), TRUE);
+       g_async_initable_init_async (G_ASYNC_INITABLE (initable),
+                                    G_PRIORITY_DEFAULT,
+                                    cancellable,
+                                    serialize_sync_cb,
+                                    &data);
+
+       g_main_loop_run (data.main_loop);
+       g_main_loop_unref (data.main_loop);
+
+       if (data.error) {
+               g_propagate_error (error, data.error);
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+static void
+tracker_remote_namespace_manager_async_initable_iface_init (GAsyncInitableIface *iface)
+{
+       iface->init_async = tracker_remote_namespace_manager_init_async;
+       iface->init_finish = tracker_remote_namespace_manager_init_finish;
+}
+
+static void
+tracker_remote_namespace_manager_initable_iface_init (GInitableIface *iface)
+{
+       iface->init = tracker_remote_namespace_manager_initable_init;
+}
+
+static void
+tracker_remote_namespace_manager_set_property (GObject      *object,
+                                               guint         prop_id,
+                                               const GValue *value,
+                                               GParamSpec   *pspec)
+{
+       TrackerRemoteNamespaceManager *manager =
+               TRACKER_REMOTE_NAMESPACE_MANAGER (object);
+
+       switch (prop_id) {
+       case PROP_CONNECTION:
+               manager->conn = g_value_get_object (value);
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+               break;
+       }
+}
+
+static void
+tracker_remote_namespace_manager_get_property (GObject    *object,
+                                               guint       prop_id,
+                                               GValue     *value,
+                                               GParamSpec *pspec)
+{
+       TrackerRemoteNamespaceManager *manager =
+               TRACKER_REMOTE_NAMESPACE_MANAGER (object);
+
+       switch (prop_id) {
+       case PROP_CONNECTION:
+               g_value_set_object (value, manager->conn);
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+               break;
+       }
+}
+
+static void
+tracker_remote_namespace_manager_class_init (TrackerRemoteNamespaceManagerClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+       object_class->set_property = tracker_remote_namespace_manager_set_property;
+       object_class->get_property = tracker_remote_namespace_manager_get_property;
+
+       props[PROP_CONNECTION] =
+               g_param_spec_object ("connection",
+                                    "Connection",
+                                    "Connection",
+                                    TRACKER_TYPE_SPARQL_CONNECTION,
+                                    G_PARAM_READWRITE |
+                                    G_PARAM_CONSTRUCT_ONLY);
+
+       g_object_class_install_properties (object_class, N_PROPS, props);
+
+}
+
+static void
+tracker_remote_namespace_manager_init (TrackerRemoteNamespaceManager *manager)
+{
+}
+
+TrackerNamespaceManager *
+tracker_remote_namespace_manager_new (TrackerSparqlConnection *conn)
+{
+       return g_initable_new (TRACKER_TYPE_REMOTE_NAMESPACE_MANAGER,
+                              NULL, NULL,
+                              "connection", conn,
+                              NULL);
+}
diff --git a/src/libtracker-sparql/remote/tracker-remote-namespaces.h 
b/src/libtracker-sparql/remote/tracker-remote-namespaces.h
new file mode 100644
index 000000000..443691eff
--- /dev/null
+++ b/src/libtracker-sparql/remote/tracker-remote-namespaces.h
@@ -0,0 +1,42 @@
+/*
+ * 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_REMOTE_NAMESPACES_H__
+#define __TRACKER_REMOTE_NAMESPACES_H__
+
+#include <libtracker-sparql/tracker-sparql.h>
+
+#define TRACKER_TYPE_REMOTE_NAMESPACE_MANAGER (tracker_remote_namespace_manager_get_type ())
+G_DECLARE_FINAL_TYPE (TrackerRemoteNamespaceManager,
+                      tracker_remote_namespace_manager,
+                      TRACKER, REMOTE_NAMESPACE_MANAGER,
+                      TrackerNamespaceManager)
+
+TrackerNamespaceManager * tracker_remote_namespace_manager_new (TrackerSparqlConnection *conn);
+
+void tracker_remote_namespace_manager_new_async (TrackerSparqlConnection *conn,
+                                                 GAsyncReadyCallback      callback,
+                                                 gpointer                 user_data);
+
+TrackerNamespaceManager * tracker_remote_namespace_manager_new_finish (GAsyncResult  *res,
+                                                                       GError       **error);
+
+#endif /* __TRACKER_REMOTE_NAMESPACES_H__ */
diff --git a/src/libtracker-sparql/remote/tracker-remote.vala 
b/src/libtracker-sparql/remote/tracker-remote.vala
index c6073b8a2..7fff95e58 100644
--- a/src/libtracker-sparql/remote/tracker-remote.vala
+++ b/src/libtracker-sparql/remote/tracker-remote.vala
@@ -21,6 +21,7 @@
 public class Tracker.Remote.Connection : Tracker.Sparql.Connection {
        internal HttpClient _client;
        internal string _base_uri;
+       internal NamespaceManager _namespaces;
 
        public Connection (string base_uri) {
                Object ();
@@ -69,4 +70,11 @@ public class Tracker.Remote.Connection : Tracker.Sparql.Connection {
                SerializerFormat unused;
                return yield _client.send_message_async (_base_uri, sparql, formats, cancellable, out unused);
        }
+
+       public override Tracker.NamespaceManager? get_namespace_manager () {
+               if (_namespaces == null)
+                       _namespaces = new Tracker.Remote.NamespaceManager (this);
+
+               return _namespaces;
+       }
 }
diff --git a/src/libtracker-sparql/remote/tracker-remote.vapi 
b/src/libtracker-sparql/remote/tracker-remote.vapi
index fdcc62a5d..e4980ce1f 100644
--- a/src/libtracker-sparql/remote/tracker-remote.vapi
+++ b/src/libtracker-sparql/remote/tracker-remote.vapi
@@ -17,6 +17,11 @@ namespace Tracker {
                XML,
                TTL,
                TRIG,
+       }
+
+       [CCode (cheader_filename = "libtracker-sparql/remote/tracker-remote-namespaces.h")]
+       class Remote.NamespaceManager : Tracker.NamespaceManager, GLib.AsyncInitable {
+                public NamespaceManager (Sparql.Connection conn);
         }
 
        class Deserializer : Sparql.Cursor {
diff --git a/src/libtracker-sparql/tracker-namespace-manager.c 
b/src/libtracker-sparql/tracker-namespace-manager.c
index 68935c9c6..377feab81 100644
--- a/src/libtracker-sparql/tracker-namespace-manager.c
+++ b/src/libtracker-sparql/tracker-namespace-manager.c
@@ -30,10 +30,6 @@
 
 #define MAX_PREFIX_LENGTH 100
 
-struct _TrackerNamespaceManager {
-       GObject parent;
-};
-
 typedef struct {
        GHashTable *prefix_to_namespace;
        GHashTable *namespace_to_prefix;
diff --git a/src/libtracker-sparql/tracker-private.h b/src/libtracker-sparql/tracker-private.h
index 5eec82e7c..39b893757 100644
--- a/src/libtracker-sparql/tracker-private.h
+++ b/src/libtracker-sparql/tracker-private.h
@@ -289,6 +289,10 @@ struct _TrackerDeserializerClass {
                                          goffset             *column_no);
 };
 
+struct _TrackerNamespaceManager {
+       GObject parent;
+};
+
 gboolean
 tracker_sparql_connection_lookup_dbus_service (TrackerSparqlConnection  *connection,
                                                const gchar              *dbus_name,


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