Commit 399ca329 authored by Sam Thursfield's avatar Sam Thursfield
Browse files

Merge branch 'wip/carlosg/remote-conn-rewrite' into 'master'

libtracker-sparql: Rewrite TrackerRemoteConnection

Closes tracker-miners#220

See merge request !512
parents 44ea8dbc 30b66198
Pipeline #396153 passed with stages
in 19 minutes and 47 seconds
......@@ -2,8 +2,7 @@ remote_files = files(
'tracker-http.c',
'tracker-remote-statement.c',
'tracker-remote-namespaces.c',
'tracker-remote.vapi',
'tracker-remote.vala',
'tracker-remote.c',
)
module_sources = files('tracker-http-module.c')
......
/*
* Copyright (C) 2016 Carlos Garnacho <carlosg@gnome.org>
*
* 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.h"
#include "tracker-http.h"
#include "tracker-remote-namespaces.h"
#include "tracker-remote-statement.h"
struct _TrackerRemoteConnection
{
TrackerSparqlConnection parent_instance;
};
typedef struct _TrackerRemoteConnectionPrivate TrackerRemoteConnectionPrivate;
struct _TrackerRemoteConnectionPrivate
{
TrackerHttpClient *client;
TrackerNamespaceManager *namespaces;
gchar *base_uri;
};
enum {
PROP_0,
PROP_BASE_URI,
N_PROPS
};
static GParamSpec *props[N_PROPS];
G_DEFINE_TYPE_WITH_PRIVATE (TrackerRemoteConnection, tracker_remote_connection,
TRACKER_TYPE_SPARQL_CONNECTION)
static void
tracker_remote_connection_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
TrackerRemoteConnection *remote =
TRACKER_REMOTE_CONNECTION (object);
TrackerRemoteConnectionPrivate *priv =
tracker_remote_connection_get_instance_private (remote);
switch (prop_id) {
case PROP_BASE_URI:
priv->base_uri = g_value_dup_string (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
tracker_remote_connection_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
TrackerRemoteConnection *remote =
TRACKER_REMOTE_CONNECTION (object);
TrackerRemoteConnectionPrivate *priv =
tracker_remote_connection_get_instance_private (remote);
switch (prop_id) {
case PROP_BASE_URI:
g_value_set_string (value, priv->base_uri);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
tracker_remote_connection_finalize (GObject *object)
{
TrackerRemoteConnection *remote =
TRACKER_REMOTE_CONNECTION (object);
TrackerRemoteConnectionPrivate *priv =
tracker_remote_connection_get_instance_private (remote);
g_object_unref (priv->client);
g_free (priv->base_uri);
G_OBJECT_CLASS (tracker_remote_connection_parent_class)->finalize (object);
}
static TrackerSparqlCursor *
tracker_remote_connection_query (TrackerSparqlConnection *connection,
const gchar *sparql,
GCancellable *cancellable,
GError **error)
{
TrackerRemoteConnection *remote =
TRACKER_REMOTE_CONNECTION (connection);
TrackerRemoteConnectionPrivate *priv =
tracker_remote_connection_get_instance_private (remote);
TrackerSerializerFormat format;
TrackerSparqlCursor *deserializer;
GInputStream *stream;
guint formats =
(1 << TRACKER_SERIALIZER_FORMAT_JSON) ||
(1 << TRACKER_SERIALIZER_FORMAT_XML);
stream = tracker_http_client_send_message (priv->client,
priv->base_uri,
sparql, formats,
cancellable,
&format,
error);
if (!stream)
return NULL;
deserializer = tracker_deserializer_new (stream, NULL, format);
g_object_unref (stream);
return deserializer;
}
static void
query_message_cb (GObject *source,
GAsyncResult *res,
gpointer user_data)
{
TrackerSerializerFormat format;
TrackerSparqlCursor *deserializer;
GInputStream *stream;
GTask *task = user_data;
GError *error = NULL;
stream = tracker_http_client_send_message_finish (TRACKER_HTTP_CLIENT (source),
res,
&format,
&error);
if (stream) {
deserializer = tracker_deserializer_new (stream, NULL, format);
g_object_unref (stream);
g_task_return_pointer (task, deserializer, g_object_unref);
} else {
g_task_return_error (task, error);
}
g_object_unref (task);
}
static void
tracker_remote_connection_query_async (TrackerSparqlConnection *connection,
const gchar *sparql,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
TrackerRemoteConnection *remote =
TRACKER_REMOTE_CONNECTION (connection);
TrackerRemoteConnectionPrivate *priv =
tracker_remote_connection_get_instance_private (remote);
GTask *task;
guint flags =
(1 << TRACKER_SERIALIZER_FORMAT_JSON) ||
(1 << TRACKER_SERIALIZER_FORMAT_XML);
task = g_task_new (connection, cancellable, callback, user_data);
tracker_http_client_send_message_async (priv->client,
priv->base_uri,
sparql, flags,
cancellable,
query_message_cb,
task);
}
static TrackerSparqlCursor *
tracker_remote_connection_query_finish (TrackerSparqlConnection *connection,
GAsyncResult *res,
GError **error)
{
return g_task_propagate_pointer (G_TASK (res), error);
}
static TrackerSparqlStatement *
tracker_remote_connection_query_statement (TrackerSparqlConnection *connection,
const gchar *sparql,
GCancellable *cancellable,
GError **error)
{
return tracker_remote_statement_new (connection, sparql, error);
}
static void
tracker_remote_connection_close (TrackerSparqlConnection *connection)
{
}
static void
tracker_remote_connection_close_async (TrackerSparqlConnection *connection,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GTask *task;
task = g_task_new (connection, cancellable, callback, user_data);
g_task_return_boolean (task, TRUE);
g_object_unref (task);
}
static gboolean
tracker_remote_connection_close_finish (TrackerSparqlConnection *connection,
GAsyncResult *res,
GError **error)
{
return g_task_propagate_boolean (G_TASK (res), error);
}
static void
serialize_message_cb (GObject *source,
GAsyncResult *res,
gpointer user_data)
{
GInputStream *stream;
GTask *task = user_data;
GError *error = NULL;
stream = tracker_http_client_send_message_finish (TRACKER_HTTP_CLIENT (source),
res,
NULL,
&error);
if (stream)
g_task_return_pointer (task, stream, g_object_unref);
else
g_task_return_error (task, error);
g_object_unref (task);
}
static void
tracker_remote_connection_serialize_async (TrackerSparqlConnection *connection,
TrackerSerializeFlags flags,
TrackerRdfFormat format,
const gchar *query,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
TrackerRemoteConnection *remote =
TRACKER_REMOTE_CONNECTION (connection);
TrackerRemoteConnectionPrivate *priv =
tracker_remote_connection_get_instance_private (remote);
GTask *task;
guint formats = 0;
if (format == TRACKER_RDF_FORMAT_TURTLE)
formats = 1 << TRACKER_SERIALIZER_FORMAT_TTL;
else if (format == TRACKER_RDF_FORMAT_TRIG)
formats = 1 << TRACKER_SERIALIZER_FORMAT_TRIG;
task = g_task_new (connection, cancellable, callback, user_data);
tracker_http_client_send_message_async (priv->client,
priv->base_uri,
query, formats,
cancellable,
serialize_message_cb,
task);
}
static GInputStream *
tracker_remote_connection_serialize_finish (TrackerSparqlConnection *connection,
GAsyncResult *res,
GError **error)
{
return g_task_propagate_pointer (G_TASK (res), error);
}
static TrackerNamespaceManager *
tracker_remote_connection_get_namespace_manager (TrackerSparqlConnection *connection)
{
TrackerRemoteConnection *remote =
TRACKER_REMOTE_CONNECTION (connection);
TrackerRemoteConnectionPrivate *priv =
tracker_remote_connection_get_instance_private (remote);
if (!priv->namespaces) {
priv->namespaces =
tracker_remote_namespace_manager_new (connection);
}
return priv->namespaces;
}
static void
tracker_remote_connection_class_init (TrackerRemoteConnectionClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
TrackerSparqlConnectionClass *conn_class =
TRACKER_SPARQL_CONNECTION_CLASS (klass);
object_class->set_property = tracker_remote_connection_set_property;
object_class->get_property = tracker_remote_connection_get_property;
object_class->finalize = tracker_remote_connection_finalize;
conn_class->query = tracker_remote_connection_query;
conn_class->query_async = tracker_remote_connection_query_async;
conn_class->query_finish = tracker_remote_connection_query_finish;
conn_class->query_statement = tracker_remote_connection_query_statement;
conn_class->close = tracker_remote_connection_close;
conn_class->close_async = tracker_remote_connection_close_async;
conn_class->close_finish = tracker_remote_connection_close_finish;
conn_class->serialize_async = tracker_remote_connection_serialize_async;
conn_class->serialize_finish = tracker_remote_connection_serialize_finish;
conn_class->get_namespace_manager = tracker_remote_connection_get_namespace_manager;
props[PROP_BASE_URI] =
g_param_spec_string ("base-uri",
"Base URI",
"Base URI",
NULL,
G_PARAM_STATIC_STRINGS |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_READWRITE);
g_object_class_install_properties (object_class, N_PROPS, props);
}
static void
tracker_remote_connection_init (TrackerRemoteConnection *remote)
{
TrackerRemoteConnectionPrivate *priv =
tracker_remote_connection_get_instance_private (remote);
priv->client = tracker_http_client_new ();
}
TrackerRemoteConnection *
tracker_remote_connection_new (const gchar *base_uri)
{
return g_object_new (TRACKER_TYPE_REMOTE_CONNECTION,
"base-uri", base_uri,
NULL);
}
/*
* Copyright (C) 2016 Carlos Garnacho <carlosg@gnome.org>
*
* 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_H__
#define __TRACKER_REMOTE_H__
#include <libtracker-sparql/tracker-sparql.h>
#define TRACKER_TYPE_REMOTE_CONNECTION (tracker_remote_connection_get_type())
G_DECLARE_FINAL_TYPE (TrackerRemoteConnection,
tracker_remote_connection,
TRACKER, REMOTE_CONNECTION,
TrackerSparqlConnection)
GType tracker_remote_connection_get_type (void) G_GNUC_CONST;
TrackerRemoteConnection *tracker_remote_connection_new (const gchar *base_uri);
#endif /* __TRACKER_REMOTE_H__ */
/*
* Copyright (C) 2016 Carlos Garnacho <carlosg@gnome.org>
*
* 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.Remote.Connection : Tracker.Sparql.Connection {
internal HttpClient _client;
internal string _base_uri;
internal NamespaceManager _namespaces;
public Connection (string base_uri) {
Object ();
_base_uri = base_uri;
_client = new HttpClient();
}
public override Sparql.Cursor query (string sparql, Cancellable? cancellable) throws GLib.Error, Sparql.Error, IOError {
uint flags =
(1 << SerializerFormat.JSON) |
(1 << SerializerFormat.XML);
SerializerFormat format;
var istream = _client.send_message (_base_uri, sparql, flags, cancellable, out format);
return new Tracker.Deserializer(istream, null, format);
}
public async override Sparql.Cursor query_async (string sparql, Cancellable? cancellable) throws GLib.Error, Sparql.Error, IOError {
uint flags =
(1 << SerializerFormat.JSON) |
(1 << SerializerFormat.XML);
SerializerFormat format;
var istream = yield _client.send_message_async (_base_uri, sparql, flags, cancellable, out format);
return new Tracker.Deserializer(istream, null, format);
}
public override Sparql.Statement? query_statement (string sparql, GLib.Cancellable? cancellable = null) throws Sparql.Error {
return new Remote.Statement (this, sparql);
}
public override void close () {
}
public async override bool close_async () throws GLib.IOError {
return true;
}
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 {
uint formats = 0;
if (format == RdfFormat.TURTLE)
formats = 1 << SerializerFormat.TTL;
else if (format == RdfFormat.TRIG)
formats = 1 << SerializerFormat.TRIG;
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;
}
}
namespace Tracker {
[CCode (cheader_filename = "libtracker-sparql/remote/tracker-remote-statement.h")]
class Remote.Statement : Sparql.Statement {
public Statement (Sparql.Connection conn, string query) throws Sparql.Error;
}
[CCode (cheader_filename = "libtracker-sparql/remote/tracker-http.h")]
class HttpClient : GLib.Object {
public HttpClient ();
public async GLib.InputStream send_message_async (string uri, string query, uint formats, GLib.Cancellable? cancellable, out SerializerFormat format) throws GLib.Error;
public GLib.InputStream send_message (string uri, string query, uint formats, GLib.Cancellable? cancellable, out SerializerFormat format) throws GLib.Error;
}
[CCode (cheader_filename = "libtracker-sparql/tracker-enums-private.h")]
enum SerializerFormat {
JSON,
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 {
public Deserializer (GLib.InputStream stream, NamespaceManager? namespaces, SerializerFormat format);
}
}
......@@ -82,8 +82,3 @@ public static async Tracker.Sparql.Connection tracker_sparql_connection_new_asyn
yield conn.init_async (Priority.DEFAULT, cancellable);
return conn;
}
public static Tracker.Sparql.Connection tracker_sparql_connection_remote_new (string uri_base) {
Tracker.get_debug_flags ();
return new Tracker.Remote.Connection (uri_base);
}
......@@ -60,6 +60,9 @@
#include "tracker-connection.h"
#include "tracker-private.h"
#include "tracker-debug.h"
#include "remote/tracker-remote.h"
G_DEFINE_ABSTRACT_TYPE (TrackerSparqlConnection, tracker_sparql_connection,
G_TYPE_OBJECT)
......@@ -83,6 +86,9 @@ tracker_sparql_connection_class_init (TrackerSparqlConnectionClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = tracker_sparql_connection_dispose;
/* Initialize debug flags */
tracker_get_debug_flags ();
}
gboolean
......@@ -216,17 +222,6 @@ tracker_sparql_connection_lookup_dbus_service (TrackerSparqlConnection *connect
* Since: 3.1
*/
/**
* tracker_sparql_connection_remote_new:
* @uri_base: Base URI of the remote connection
*
* Connects to a remote SPARQL endpoint. The connection is made using the libsoup
* HTTP library. The connection will normally use the http:// or https:// protocol.
*
* Returns: (transfer full): a new remote #TrackerSparqlConnection. Call
* g_object_unref() on the object when no longer used.
*/
/**
* tracker_sparql_connection_query:
* @connection: a #TrackerSparqlConnection
......@@ -988,3 +983,19 @@ tracker_sparql_connection_map_connection (TrackerSparqlConnection *connection,
handle_name,
service_connection);
}
/**
* tracker_sparql_connection_remote_new:
* @uri_base: Base URI of the remote connection
*
* Connects to a remote SPARQL endpoint. The connection is made using the libsoup
* HTTP library. The connection will normally use the http:// or https:// protocol.
*
* Returns: (transfer full): a new remote #TrackerSparqlConnection. Call
* g_object_unref() on the object when no longer used.
*/
TrackerSparqlConnection *
tracker_sparql_connection_remote_new (const gchar *uri_base)
{
return TRACKER_SPARQL_CONNECTION (tracker_remote_connection_new (uri_base));
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment