[tracker/direct-access: 37/122] libtracker-bus: Implemented D-Bus FD passing using TrackerSparqlCursor API



commit 49312ea016254399c3cd9dc90b0820193f61e1a8
Author: Martyn Russell <martyn lanedo com>
Date:   Wed Jul 14 17:42:34 2010 +0100

    libtracker-bus: Implemented D-Bus FD passing using TrackerSparqlCursor API

 src/libtracker-bus/Makefile.am          |    6 +-
 src/libtracker-bus/tracker-bus-cursor.c |  263 +++++++++++++++++++++++++++++++
 src/libtracker-bus/tracker-bus.vala     |   35 ++++-
 tests/functional-tests/Makefile.am      |   35 ++++-
 tests/functional-tests/bus-test.vala    |   41 +++++
 tests/functional-tests/direct-test.vala |   38 +++--
 6 files changed, 395 insertions(+), 23 deletions(-)
---
diff --git a/src/libtracker-bus/Makefile.am b/src/libtracker-bus/Makefile.am
index e9c2f4e..1d95674 100644
--- a/src/libtracker-bus/Makefile.am
+++ b/src/libtracker-bus/Makefile.am
@@ -7,6 +7,7 @@ INCLUDES =								\
 	-I$(top_srcdir)/src/libtracker-sparql				\
 	-I$(top_builddir)/src						\
 	$(WARN_CFLAGS)							\
+	$(DBUS_CFLAGS)							\
 	$(GLIB2_CFLAGS)							\
 	$(GCOV_CFLAGS)
 
@@ -19,7 +20,8 @@ libtracker_bus_la_VALASOURCES = \
 
 libtracker_bus_ TRACKER_API_VERSION@_la_SOURCES = 	\
 	libtracker-bus.vala.stamp			\
-	$(libtracker_bus_la_VALASOURCES:.vala=.c)
+	$(libtracker_bus_la_VALASOURCES:.vala=.c) \
+	tracker-bus-cursor.c
 
 libtracker_bus_ TRACKER_API_VERSION@_la_LDFLAGS = 	\
 	-shared -fPIC -module -avoid-version
@@ -41,7 +43,7 @@ vapi_DATA = \
 	tracker-bus-$(TRACKER_API_VERSION).vapi
 
 libtracker-bus.vala.stamp: $(libtracker_bus_la_VALASOURCES) $(vapi_sources)
-	$(AM_V_GEN)$(VALAC) $(GCOV_VALAFLAGS) -C $(VALAFLAGS) --pkg gio-2.0 -H tracker-bus.h --vapi tracker-bus-$(TRACKER_API_VERSION).vapi $^
+	$(AM_V_GEN)$(VALAC) $(GCOV_VALAFLAGS) -C $(VALAFLAGS) --pkg gio-2.0 --pkg dbus-glib-1 -H tracker-bus.h --vapi tracker-bus-$(TRACKER_API_VERSION).vapi $^
 	$(AM_V_GEN)touch $@
 
 libtracker_bus_ TRACKER_API_VERSION@_la_LIBADD = 						\
diff --git a/src/libtracker-bus/tracker-bus-cursor.c b/src/libtracker-bus/tracker-bus-cursor.c
new file mode 100644
index 0000000..b48c9cc
--- /dev/null
+++ b/src/libtracker-bus/tracker-bus-cursor.c
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 2006, Jamie McCracken <jamiemcc gnome org>
+ * Copyright (C) 2008-2010, Nokia <ivan frade nokia com>
+ * Copyright (C) 2010, Codeminded BVBA <abustany 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.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <libtracker-common/tracker-common.h>
+
+#include <libtracker-sparql/tracker-sparql.h>
+
+#include "tracker-bus.h"
+
+#define TRACKER_TYPE_BUS_CURSOR           (tracker_bus_cursor_get_type ())
+#define TRACKER_BUS_CURSOR(obj)           (G_TYPE_CHECK_INSTANCE_CAST ((obj), TRACKER_TYPE_BUS_CURSOR, TrackerBusCursor))
+#define TRACKER_BUS_CURSOR_CLASS(c)       (G_TYPE_CHECK_CLASS_CAST ((c),      TRACKER_TYPE_BUS_CURSOR, TrackerBusCursorClass))
+#define TRACKER_IS_BUS_CURSOR(obj)        (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TRACKER_TYPE_BUS_CURSOR))
+#define TRACKER_IS_BUS_CURSOR_CLASS(c)    (G_TYPE_CHECK_CLASS_TYPE ((o),      TRACKER_TYPE_BUS_CURSOR))
+#define TRACKER_BUS_CURSOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),  TRACKER_TYPE_BUS_CURSOR, TrackerBusCursorClass))
+
+typedef struct TrackerBusCursor TrackerBusCursor;
+typedef struct TrackerBusCursorClass TrackerBusCursorClass;
+
+struct TrackerBusCursor {
+	TrackerSparqlCursor parent_instance;
+
+	char *buffer;
+	int buffer_index;
+	long buffer_size;
+
+	guint n_columns;
+	int *offsets;
+	char *data;
+};
+
+struct TrackerBusCursorClass {
+	TrackerSparqlCursorClass parent_class;
+};
+
+GType tracker_bus_cursor_get_type (void);
+void  tracker_bus_cursor_finalize (GObject *object);
+
+G_DEFINE_TYPE (TrackerBusCursor, tracker_bus_cursor, TRACKER_SPARQL_TYPE_CURSOR)
+
+static void
+tracker_bus_cursor_rewind (TrackerBusCursor *cursor)
+{
+	/* FIXME: Implement */
+}
+
+static inline int
+buffer_read_int (TrackerBusCursor *cursor)
+{
+	int v = *((int *)(cursor->buffer + cursor->buffer_index));
+
+	cursor->buffer_index += 4;
+
+	return v;
+}
+
+static gboolean
+tracker_bus_cursor_iter_next (TrackerBusCursor  *cursor,
+              	              GCancellable      *cancellable,
+              	              GError           **error)
+{
+	int last_offset;
+
+	if (cursor->buffer_index >= cursor->buffer_size) {
+		return FALSE;
+	}
+
+	/* So, the make up on each cursor segment is:
+	 *
+	 * iteration = [4 bytes for number of columns,
+	 *              4 bytes for last offset]
+	 */
+	cursor->n_columns = buffer_read_int (cursor);
+	cursor->offsets = (int *)(cursor->buffer + cursor->buffer_index);
+	cursor->buffer_index += sizeof (int) * (cursor->n_columns - 1);
+
+	last_offset = buffer_read_int (cursor);
+	cursor->data = cursor->buffer + cursor->buffer_index;
+	cursor->buffer_index += last_offset + 1;
+	
+	return TRUE;
+}
+
+static void
+tracker_bus_cursor_iter_next_thread (GSimpleAsyncResult *res,
+                                     GObject            *object,
+                                     GCancellable       *cancellable)
+{
+	/* This is stolen from the direct access work, 
+	 * do we REALLY need to do this in the next thread? 
+	 */
+
+	GError *error = NULL;
+	gboolean result;
+
+	result = tracker_bus_cursor_iter_next (TRACKER_BUS_CURSOR (object), cancellable, &error);
+	if (error) {
+		g_simple_async_result_set_from_error (res, error);
+	} else {
+		g_simple_async_result_set_op_res_gboolean (res, result);
+	}
+}
+
+static void
+tracker_bus_cursor_iter_next_async (TrackerBusCursor    *cursor,
+                                    GCancellable        *cancellable,
+                                    GAsyncReadyCallback  callback,
+                                    gpointer             user_data)
+{
+	GSimpleAsyncResult *res;
+
+	res = g_simple_async_result_new (G_OBJECT (cursor), callback, user_data, tracker_bus_cursor_iter_next_async);
+	g_simple_async_result_run_in_thread (res, tracker_bus_cursor_iter_next_thread, 0, cancellable);
+}
+
+static gboolean
+tracker_bus_cursor_iter_next_finish (TrackerBusCursor *cursor,
+                                     GAsyncResult     *res,
+                                     GError          **error)
+{
+	if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error)) {
+		return FALSE;
+	}
+	return g_simple_async_result_get_op_res_gboolean (G_SIMPLE_ASYNC_RESULT (res));
+}
+
+static guint
+tracker_bus_cursor_get_n_columns (TrackerBusCursor *cursor)
+{
+	return cursor->n_columns;
+}
+
+static const gchar *
+tracker_bus_cursor_get_string (TrackerBusCursor *cursor, 
+	                           guint             column,
+	                           gint             *length)
+{
+	g_return_val_if_fail (column < tracker_bus_cursor_get_n_columns (cursor), NULL);
+
+	if (column == 0) {
+		return cursor->data;
+	} else {
+		return cursor->data + cursor->offsets[column - 1] + 1;
+	}
+}
+
+static void
+tracker_bus_cursor_class_init (TrackerBusCursorClass *class)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (class);
+        TrackerSparqlCursorClass *sparql_cursor_class = TRACKER_SPARQL_CURSOR_CLASS (class);
+
+        object_class->finalize = tracker_bus_cursor_finalize;
+
+        sparql_cursor_class->get_n_columns = (gint (*) (TrackerSparqlCursor *)) tracker_bus_cursor_get_n_columns;
+        sparql_cursor_class->get_string = (const gchar * (*) (TrackerSparqlCursor *, gint, gint*)) tracker_bus_cursor_get_string;
+        sparql_cursor_class->next = (gboolean (*) (TrackerSparqlCursor *, GCancellable *, GError **)) tracker_bus_cursor_iter_next;
+        sparql_cursor_class->next_async = (void (*) (TrackerSparqlCursor *, GCancellable *, GAsyncReadyCallback, gpointer)) tracker_bus_cursor_iter_next_async;
+        sparql_cursor_class->next_finish = (gboolean (*) (TrackerSparqlCursor *, GAsyncResult *, GError **)) tracker_bus_cursor_iter_next_finish;
+        sparql_cursor_class->rewind = (void (*) (TrackerSparqlCursor *)) tracker_bus_cursor_rewind;
+}
+
+void
+tracker_bus_cursor_init (TrackerBusCursor *cursor)
+{
+}
+
+void
+tracker_bus_cursor_finalize (GObject *object)
+{
+	TrackerBusCursor *cursor;
+
+	cursor = TRACKER_BUS_CURSOR (object);
+
+	g_free (cursor->buffer);
+
+	G_OBJECT_CLASS (tracker_bus_cursor_parent_class)->finalize (object);
+}
+
+
+// Public API
+
+TrackerSparqlCursor *
+tracker_bus_query (DBusGConnection  *gconnection,
+                   const gchar     *query,
+                   GError         **error)
+{
+#ifdef HAVE_DBUS_FD_PASSING
+	TrackerBusCursor *cursor;
+	DBusConnection *connection;
+	DBusMessage *message;
+	DBusMessageIter iter;
+	int pipefd[2];
+	GError *inner_error = NULL;
+
+	g_return_val_if_fail (query, NULL);
+
+	if (pipe (pipefd) < 0) {
+		/* FIXME: Use proper error domain/code */
+		g_set_error (error, 0, 0, "Cannot open pipe");
+		return NULL;
+	}
+
+	connection = dbus_g_connection_get_connection (gconnection);
+
+	message = dbus_message_new_method_call (TRACKER_DBUS_SERVICE,
+	                                        TRACKER_DBUS_OBJECT_STEROIDS,
+	                                        TRACKER_DBUS_INTERFACE_STEROIDS,
+	                                        "Query");
+
+	dbus_message_iter_init_append (message, &iter);
+	dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &query);
+	dbus_message_iter_append_basic (&iter, DBUS_TYPE_UNIX_FD, &pipefd[1]);
+	close (pipefd[1]);
+
+	cursor = g_object_new (TRACKER_TYPE_BUS_CURSOR, NULL);
+
+	tracker_dbus_send_and_splice (connection,
+	                              message,
+	                              pipefd[0],
+	                              NULL,
+	                              (void **) &cursor->buffer,
+	                              &cursor->buffer_size,
+	                              &inner_error);
+	/* message is destroyed by tracker_dbus_send_and_splice */
+
+	if (G_UNLIKELY (inner_error)) {
+		g_propagate_error (error, inner_error);
+		g_object_unref (cursor);
+		cursor = NULL;
+	}
+
+	return TRACKER_SPARQL_CURSOR (cursor);
+#else  /* HAVE_DBUS_FD_PASSING */
+	return NULL;
+#endif /* HAVE_DBUS_FD_PASSING */
+}
+
diff --git a/src/libtracker-bus/tracker-bus.vala b/src/libtracker-bus/tracker-bus.vala
index 91c60f2..bc4a11b 100644
--- a/src/libtracker-bus/tracker-bus.vala
+++ b/src/libtracker-bus/tracker-bus.vala
@@ -17,26 +17,55 @@
  * Boston, MA  02110-1301, USA.
  */
 
+public const string TRACKER_DBUS_SERVICE = "org.freedesktop.Tracker1";
+public const string TRACKER_DBUS_INTERFACE_RESOURCES = TRACKER_DBUS_SERVICE + ".Resources";
+public const string TRACKER_DBUS_OBJECT_RESOURCES = "/org/freedesktop/Tracker1/Resources";
+public const string TRACKER_DBUS_INTERFACE_STEROIDS = TRACKER_DBUS_SERVICE + ".Steroids";
+public const string TRACKER_DBUS_OBJECT_STEROIDS = "/org/freedesktop/Tracker1/Steroids";
+
+[DBus (name = TRACKER_SERVICE_RESOURCES)]
+private interface Tracker.Bus.Resources : GLib.Object {
+	public abstract string[,] SparqlQuery (string query) throws DBus.Error;
+}
+
+// Imported DBus FD API until we have support with Vala
+public extern Tracker.Sparql.Cursor tracker_bus_query (DBus.Connection connection, string query) throws GLib.Error;
+
+// Actual class definition
 public class Tracker.Bus.Connection : Tracker.Sparql.Connection {
+	static DBus.Connection connection;
 	static bool initialized;
 
 	public Connection ()
 	requires (!initialized) {
 		initialized = true;
+		
+		try {
+			connection = DBus.Bus.get (DBus.BusType.SESSION);
 
-		// FIXME: Implement DBus stuff
+			// FIXME: Test for steroids and resources interfaces?			
+//			resources = (Resources) c.get_object (TRACKER_DBUS_SERVICE,
+//			                                      TRACKER_DBUS_OBJECT_RESOURCES,
+//			                                      TRACKER_DBUS_INTERFACE_RESOURCES);
+		} catch (DBus.Error e) {
+			warning ("Could not connect to D-Bus service:'%s': %s", TRACKER_DBUS_INTERFACE_RESOURCES, e.message);
+			initialized = false;
+			return;
+		}
+		
+		initialized = true;
 	}
 
 	~Connection () {
-		// Clean up connection
 		initialized = false;
 	}
 
 	public override Sparql.Cursor? query (string sparql, Cancellable? cancellable) throws GLib.Error {
-		return null;
+		return tracker_bus_query (connection, sparql);
 	}
 
 	public async override Sparql.Cursor? query_async (string sparql, Cancellable? cancellable = null) throws GLib.Error {
+		// FIXME: Implement
 		return null;
 	}
 }
diff --git a/tests/functional-tests/Makefile.am b/tests/functional-tests/Makefile.am
index 37b4754..ca76516 100644
--- a/tests/functional-tests/Makefile.am
+++ b/tests/functional-tests/Makefile.am
@@ -5,6 +5,7 @@ SUBDIRS = data
 INCLUDES =					\
 	-I$(top_builddir)/src/libtracker-sparql	\
 	-I$(top_builddir)/src/libtracker-direct	\
+	-I$(top_builddir)/src/libtracker-bus	\
 	$(WARN_CFLAGS)				\
 	$(DBUS_CFLAGS)				\
 	$(GLIB2_CFLAGS)				\
@@ -49,7 +50,7 @@ bashscripts_SCRIPTS = 				\
 	@sed -e "s|@topsrcdir[ ]|${top_srcdir}|" \
 	     -e "s|@libexecdir[ ]|${libexecdir}|" $< > $@
 
-noinst_PROGRAMS = busy-handling-test direct-test
+noinst_PROGRAMS = busy-handling-test direct-test bus-test
 
 busy_handling_test_VALASOURCES = busy-handling-test.vala
 
@@ -72,22 +73,46 @@ direct_test_SOURCES = \
 	direct_test.vala.stamp \
 	$(direct_test_VALASOURCES:.vala=.c)
 
-vapi_sources = \
-	$(top_srcdir)/src/libtracker-sparql/tracker-sparql-$(TRACKER_API_VERSION).vapi	\
+bus_test_VALASOURCES = bus-test.vala
+
+bus_test_SOURCES = \
+	bus_test.vala.stamp \
+	$(bus_test_VALASOURCES:.vala=.c)
+
+direct_vapi_sources = \
+	$(top_srcdir)/src/libtracker-sparql/tracker-sparql-$(TRACKER_API_VERSION).vapi \
 	$(top_srcdir)/src/libtracker-direct/tracker-direct-$(TRACKER_API_VERSION).vapi
 
-direct-test.vala.stamp: $(direct_test_VALASOURCES) $(vapi_sources)
+direct-test.vala.stamp: $(direct_test_VALASOURCES) $(direct_vapi_sources)
 	$(AM_V_GEN)$(VALAC) $(GCOV_VALAFLAGS) -C $(VALAFLAGS) --pkg gio-2.0 $^
 	$(AM_V_GEN)touch $@
 
 direct_test_LDADD = \
 	$(top_builddir)/src/libtracker-direct/libtracker-direct-$(TRACKER_API_VERSION).la \
 	$(top_builddir)/src/libtracker-sparql/libtracker-sparql-$(TRACKER_API_VERSION).la \
+	$(GIO_LIBS) \
 	$(GLIB2_LIBS)
 
+bus_vapi_sources = \
+	$(top_srcdir)/src/libtracker-sparql/tracker-sparql-$(TRACKER_API_VERSION).vapi \
+	$(top_srcdir)/src/libtracker-bus/tracker-bus-$(TRACKER_API_VERSION).vapi
+
+bus-test.vala.stamp: $(bus_test_VALASOURCES) $(bus_vapi_sources)
+	$(AM_V_GEN)$(VALAC) $(GCOV_VALAFLAGS) -C $(VALAFLAGS) --pkg gio-2.0 --pkg dbus-glib-1 $^
+	$(AM_V_GEN)touch $@
+
+bus_test_LDADD = \
+	$(top_builddir)/src/libtracker-bus/libtracker-bus-$(TRACKER_API_VERSION).la \
+	$(top_builddir)/src/libtracker-sparql/libtracker-sparql-$(TRACKER_API_VERSION).la \
+	$(top_builddir)/src/libtracker-common/libtracker-common.la \
+	$(GIO_LIBS) \
+	$(GLIB2_LIBS) \
+	$(DBUS_LIBS)
+
 BUILT_SOURCES = \
 	busy-handling-test.vala.stamp \
-	direct-test.vala.stamp
+	direct-test.vala.stamp \
+	bus-test.vala.stamp
 
 EXTRA_DIST = 					\
 	$(config_SCRIPTS) 			\
diff --git a/tests/functional-tests/bus-test.vala b/tests/functional-tests/bus-test.vala
new file mode 100644
index 0000000..68ad63a
--- /dev/null
+++ b/tests/functional-tests/bus-test.vala
@@ -0,0 +1,41 @@
+using Tracker;
+using Tracker.Sparql;
+
+int
+main( string[] args )
+{
+	Sparql.Connection con = new Tracker.Bus.Connection ();
+	Cursor cursor;
+
+	try {
+		cursor = con.query ("SELECT ?u WHERE { ?u a rdfs:Class }");
+	} catch (GLib.Error e) {
+		warning ("Couldn't perform query: %s", e.message);
+		return -1;
+	}
+
+	try {
+		while (cursor.next()) {
+			int i;
+
+			for (i = 0; i < cursor.n_columns; i++) {
+				print ("%s%s", i != 0 ? ",":"", cursor.get_string (i));
+			}
+
+			print ("\n");
+		}
+	} catch (GLib.Error e) {
+		warning ("Couldn't iterate query results: %s", e.message);
+		return -1;
+	}
+
+	// Testing new API with GModule
+	
+//	print ("\n\n");
+
+//	Lookup foo = new Lookup ();
+
+
+	return( 0 );
+}
+
diff --git a/tests/functional-tests/direct-test.vala b/tests/functional-tests/direct-test.vala
index f00d8ce..b73581a 100644
--- a/tests/functional-tests/direct-test.vala
+++ b/tests/functional-tests/direct-test.vala
@@ -1,28 +1,40 @@
 using Tracker;
 using Tracker.Sparql;
-using Tracker.Direct;
 
 int
 main( string[] args )
 {
-//	Sparql.Connection con = new Direct.Connection ();
-//	Cursor cursor = con.query ("SELECT ?u WHERE { ?u a rdfs:Class }");
+	Sparql.Connection con = new Tracker.Direct.Connection ();
+	Cursor cursor;
+	
+	try {
+		cursor = con.query ("SELECT ?u WHERE { ?u a rdfs:Class }");
+	} catch (GLib.Error e) {
+		warning ("Couldn't perform query: %s", e.message);
+		return -1;
+	}
 
-//	while (cursor.next()) {
-//		int i;
+	try {
+		while (cursor.next()) {
+			int i;
 
-//		for (i = 0; i < cursor.n_columns; i++) {
-//			print ("%s%s", i != 0 ? ",":"", cursor.get_string (i));
-//		}
+			for (i = 0; i < cursor.n_columns; i++) {
+				print ("%s%s", i != 0 ? ",":"", cursor.get_string (i));
+			}
 
-//		print ("\n");
-//	}
-	
+			print ("\n");
+		}
+	} catch (GLib.Error e) {
+		warning ("Couldn't iterate query results: %s", e.message);
+		return -1;
+	}
+		
 	// Testing new API with GModule
 	
-	print ("\n\n");
+//	print ("\n\n");
+
+//	Lookup foo = new Lookup ();
 
-	Lookup foo = new Lookup ();
 
 	return( 0 );
 }



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