[tracker/dbus-fd-experiment: 1/5] Add Tracker Steroids interface



commit 59d4ce0cb3750d4cd6ac4297740bc86423bc8cf6
Author: Adrien Bustany <abustany gnome org>
Date:   Thu May 20 17:55:31 2010 -0400

    Add Tracker Steroids interface
    
    The Steroids interface uses a local pipe to transfer query results,
    instead of sending them over DBus. To do so, it uses a new feature in
    DBus 1.3 which allows passing UNIX file descriptors in messages.
    
    This commit introduces a new DBus object exported on the store at path
    /org/freedesktop/Tracker1/Steroids. Methods are in the interface
    org.freedesktop.Tracker1.Steroids.
    
    The DBus interface is composed of two methods:
    PrepareQuery <- SPARQL query
                 -> UNIX file descriptors where results will be written
                 -> Query identifier
    The PrepareQuery call initiates a query in Tracker. The query is not
    really prepared, in the sense that a PrepareQuery with an erroneous
    query will succeed. It's the Fetch call which will fail in that case.
    The returned query identifier can be used to initiate the Fetch.
    
    Fetch        <- Query identifier
    The Fetch call executes the query with the given identifier, and returns
    the results over the pipe returned by PrepareQuery.
    
    Note that while results are being fetched, a DB cursor is left open,
    blocking other concurrent INSERTs. It is therefore important to fetch
    the results and free the iterator as fast as possible.

 configure.ac                         |   30 ++
 src/tracker-store/Makefile.am        |    6 +
 src/tracker-store/tracker-dbus.c     |   19 ++
 src/tracker-store/tracker-steroids.c |  594 ++++++++++++++++++++++++++++++++++
 src/tracker-store/tracker-steroids.h |   65 ++++
 5 files changed, 714 insertions(+), 0 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 0a0580d..d2135d9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1690,6 +1690,35 @@ fi
 
 AM_CONDITIONAL(HAVE_TOTEM_PL_PARSER, test "x$have_playlist" = "xyes")
 
+####################################################################
+# Check for DBus > 1.3 for Steroids (query over pipe) support
+####################################################################
+
+AC_ARG_ENABLE(dbus-fd-passing,
+	      AS_HELP_STRING([--enable-dbus-fd-passing],
+			     [enable DBus FD passing for faster IPC [[default=yes]]]),,
+	      [enable_dbus_fd_passing=yes])
+
+if test "x$enable_dbus_fd_passing" != "xno" ; then
+    PKG_CHECK_EXISTS([dbus-1 >= 1.3],
+                     [have_dbus_fd_passing=yes],
+                     [have_dbus_fd_passing=no])
+
+    if test "x$have_dbus_fd_passing" = "xyes"; then
+       AC_DEFINE(HAVE_DBUS_FD_PASSING, [], [Define if we have DBus >= 1.3 and want DBus FD passing])
+    fi
+else
+    have_dbus_fd_passing="no  (disabled)"
+fi
+
+if test "x$enable_dbus_fd_passing" = "xyes"; then
+   if test "x$have_dbus_fd_passing" != "xyes"; then
+      AC_MSG_ERROR([Couldn't find a recent enough DBus for FD passing.])
+   fi
+fi
+
+AM_CONDITIONAL(HAVE_DBUS_FD_PASSING, test "x$have_dbus_fd_passing" = "xyes")
+
 ##################################################################
 # Enable mockup extractor module?
 ##################################################################
@@ -1967,6 +1996,7 @@ Build Configuration:
 	Support for Cyrillic languages (enca):  $have_enca
 	Support for network status detection:   $have_network_manager
 	Unicode support library:                $with_unicode_support
+	Support for DBus FD passing:		$have_dbus_fd_passing
 
 Applications:
 
diff --git a/src/tracker-store/Makefile.am b/src/tracker-store/Makefile.am
index edf3ed8..a5b986f 100644
--- a/src/tracker-store/Makefile.am
+++ b/src/tracker-store/Makefile.am
@@ -54,6 +54,12 @@ tracker_store_SOURCES =							\
 	tracker-status.c						\
 	tracker-status.h
 
+if HAVE_DBUS_FD_PASSING
+tracker_store_SOURCES +=						\
+	tracker-steroids.c						\
+	tracker-steroids.h
+endif
+
 if OS_WIN32
 tracker_store_win_libs = -lws2_32 -lkernel32
 endif
diff --git a/src/tracker-store/tracker-dbus.c b/src/tracker-store/tracker-dbus.c
index 440c48e..310f804 100644
--- a/src/tracker-store/tracker-dbus.c
+++ b/src/tracker-store/tracker-dbus.c
@@ -43,6 +43,10 @@
 #include "tracker-backup-glue.h"
 #include "tracker-marshal.h"
 
+#ifdef HAVE_DBUS_FD_PASSING
+#include "tracker-steroids.h"
+#endif
+
 static DBusGConnection *connection;
 static DBusGProxy      *gproxy;
 static GSList          *objects;
@@ -289,6 +293,21 @@ tracker_dbus_register_objects (void)
 	                      TRACKER_RESOURCES_PATH);
 	objects = g_slist_prepend (objects, object);
 
+#ifdef HAVE_DBUS_FD_PASSING
+	/* Add org.freedesktop.Tracker1.Steroids */
+	object = tracker_steroids_new ();
+	if (!object) {
+		g_critical ("Could not create TrackerSteroids object to register");
+		return FALSE;
+	}
+
+	dbus_connection_add_filter (dbus_g_connection_get_connection (connection),
+	                            tracker_steroids_connection_filter,
+	                            object,
+	                            NULL);
+	objects = g_slist_prepend (objects, object);
+#endif
+
 	/* Reverse list since we added objects at the top each time */
 	objects = g_slist_reverse (objects);
 
diff --git a/src/tracker-store/tracker-steroids.c b/src/tracker-store/tracker-steroids.c
new file mode 100644
index 0000000..f3134fc
--- /dev/null
+++ b/src/tracker-store/tracker-steroids.c
@@ -0,0 +1,594 @@
+/* 
+ * 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 <errno.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <gio/gunixoutputstream.h>
+#include <gio/gunixinputstream.h>
+
+#include "tracker-dbus.h"
+#include "tracker-steroids.h"
+#include "tracker-store.h"
+
+#define DBUS_ERROR_UNKNOWN_METHOD_NAME "org.freedesktop.DBus.Error.UnknownMethod"
+#define DBUS_ERROR_UNKNOWN_METHOD_MESSAGE "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist"
+
+/**
+ * /!\ IMPORTANT WARNING /!\
+ *
+ * DBus 1.3 is required for this feature to work, since UNIX FD passing is not
+ * present in earlier versions. However, using UNIX FD passing with DBus will
+ * make Valgrind stop, since the fcntl command F_DUPFD_CLOEXEC is not supported
+ * as of version 3.5.
+ * This has been reported here: https://bugs.kde.org/show_bug.cgi?id=238696
+ */
+
+G_DEFINE_TYPE (TrackerSteroids, tracker_steroids, G_TYPE_OBJECT)
+
+#define TRACKER_STEROIDS_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TRACKER_TYPE_STEROIDS, TrackerSteroidsPrivate))
+
+typedef struct {
+	GHashTable *clients;
+} TrackerSteroidsPrivate;
+
+typedef struct {
+	TrackerSteroids *parent;
+	DBusMessage *call_message;
+	int fd;
+	unsigned int send_buffer_index;
+	char send_buffer[TRACKER_STEROIDS_BUFFER_SIZE];
+	guint request_id;
+	DBusConnection *connection;
+} ClientInfo;
+
+typedef struct {
+	GError *error;
+	gpointer user_data;
+} InThreadPtr;
+
+static void tracker_steroids_finalize (GObject *object);
+
+static void
+tracker_steroids_class_init (TrackerSteroidsClass *klass)
+{
+	GObjectClass *object_class;
+
+	object_class = G_OBJECT_CLASS (klass);
+
+	object_class->finalize = tracker_steroids_finalize;
+
+	g_type_class_add_private (object_class, sizeof (TrackerSteroidsPrivate));
+}
+
+static void
+tracker_steroids_init (TrackerSteroids *object)
+{
+	TrackerSteroidsPrivate *priv = TRACKER_STEROIDS_GET_PRIVATE (object);
+
+	priv->clients = g_hash_table_new (g_direct_hash, g_direct_equal);
+}
+
+TrackerSteroids*
+tracker_steroids_new (void)
+{
+	return g_object_new (TRACKER_TYPE_STEROIDS, NULL);
+}
+
+static void
+destroy_client_info (gpointer user_data)
+{
+	ClientInfo *info = user_data;
+
+	dbus_message_unref (info->call_message);
+	dbus_connection_unref (info->connection);
+
+	if (info->fd) {
+		close (info->fd);
+	}
+
+	g_slice_free (ClientInfo, user_data);
+}
+
+static void
+query_callback (gpointer  inthread_data,
+                GError   *error,
+                gpointer  user_data)
+{
+	InThreadPtr *ptr  = inthread_data;
+	ClientInfo  *info = user_data;
+	DBusMessage *reply;
+
+	if (ptr && ptr->error) {
+		/* Client is still there, but query failed */
+		tracker_dbus_request_failed (info->request_id,
+		                             NULL,
+		                             &ptr->error,
+		                             NULL);
+		reply = dbus_message_new_error (info->call_message,
+		                                TRACKER_STEROIDS_INTERFACE ".QueryError",
+		                                ptr->error->message);
+		dbus_connection_send (info->connection, reply, NULL);
+		dbus_message_unref (reply);
+		g_error_free (ptr->error);
+	} else if (error) {
+		/* Client has disappeared */
+		tracker_dbus_request_failed (info->request_id,
+		                             NULL,
+		                             &error,
+		                             NULL);
+		reply = dbus_message_new_error (info->call_message,
+		                                TRACKER_STEROIDS_INTERFACE ".QueryError",
+		                                error->message);
+		dbus_connection_send (info->connection, reply, NULL);
+		dbus_message_unref (reply);
+	} else {
+		tracker_dbus_request_success (info->request_id,
+		                              NULL);
+		reply = dbus_message_new_method_return (info->call_message);
+		dbus_connection_send (info->connection, reply, NULL);
+		dbus_message_unref (reply);
+	}
+
+	if (ptr) {
+		g_slice_free (InThreadPtr, ptr);
+	}
+}
+
+static void
+update_callback (GError *error, gpointer user_data)
+{
+	ClientInfo *info = user_data;
+	DBusMessage *reply;
+
+	if (error) {
+		tracker_dbus_request_failed (info->request_id,
+		                             NULL,
+		                             &error,
+		                             NULL);
+		reply = dbus_message_new_error (info->call_message,
+		                                TRACKER_STEROIDS_INTERFACE ".UpdateError",
+		                                error->message);
+		dbus_connection_send (info->connection, reply, NULL);
+		dbus_message_unref (reply);
+		return;
+	}
+
+	tracker_dbus_request_success (info->request_id,
+	                              NULL);
+	reply = dbus_message_new_method_return (info->call_message);
+	dbus_connection_send (info->connection, reply, NULL);
+	dbus_message_unref (reply);
+}
+
+static void
+marshall_hash_table_item (gpointer key, gpointer value, gpointer user_data)
+{
+	DBusMessageIter *iter = user_data;
+	DBusMessageIter subiter;
+
+	dbus_message_iter_open_container (iter, DBUS_TYPE_DICT_ENTRY, NULL, &subiter);
+	dbus_message_iter_append_basic (&subiter, DBUS_TYPE_STRING, &key);
+	dbus_message_iter_append_basic (&subiter, DBUS_TYPE_STRING, &value);
+	dbus_message_iter_close_container (iter, &subiter);
+}
+
+static void
+marshall_hash_table (DBusMessageIter *iter, GHashTable *hash)
+{
+	DBusMessageIter subiter;
+
+	dbus_message_iter_open_container (iter, DBUS_TYPE_ARRAY, "{ss}", &subiter);
+	g_hash_table_foreach (hash, marshall_hash_table_item, &subiter);
+	dbus_message_iter_close_container (iter, &subiter);
+}
+
+static void
+update_blank_callback (GPtrArray *blank_nodes, GError *error, gpointer user_data)
+{
+	ClientInfo *info = user_data;
+	DBusMessage *reply;
+	int i, j;
+	/* Reply type is aaa{ss} */
+	DBusMessageIter iter;
+	DBusMessageIter subiter;
+	DBusMessageIter subsubiter;
+
+	if (info->fd) {
+		close (info->fd);
+	}
+
+	if (error) {
+		tracker_dbus_request_failed (info->request_id,
+		                             NULL,
+		                             &error,
+		                             NULL);
+		reply = dbus_message_new_error (info->call_message,
+		                                TRACKER_STEROIDS_INTERFACE ".UpdateBlankError",
+		                                error->message);
+		dbus_connection_send (info->connection, reply, NULL);
+		dbus_message_unref (reply);
+		return;
+	}
+
+	tracker_dbus_request_success (info->request_id,
+	                              NULL);
+	reply = dbus_message_new_method_return (info->call_message);
+	dbus_message_iter_init_append (reply, &iter);
+
+	dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "aa{ss}", &subiter);
+	for (i = 0; i < blank_nodes->len; i++) {
+		GPtrArray *inner_array;
+		inner_array = g_ptr_array_index (blank_nodes, i);
+
+		dbus_message_iter_open_container (&subiter, DBUS_TYPE_ARRAY, "a{ss}", &subsubiter);
+		for (j = 0; j < inner_array->len; j++) {
+			GHashTable *hash = g_ptr_array_index (inner_array, j);
+
+			marshall_hash_table (&subsubiter, hash);
+		}
+		dbus_message_iter_close_container (&subiter, &subsubiter);
+	}
+	dbus_message_iter_close_container (&iter, &subiter);
+
+	dbus_connection_send (info->connection, reply, NULL);
+	dbus_message_unref (reply);
+}
+
+static gpointer
+query_inthread (TrackerDBCursor *cursor,
+                GError          *error,
+                gpointer         user_data)
+{
+	InThreadPtr *ptr  = g_slice_new0 (InThreadPtr);
+	ClientInfo  *info = user_data;
+	GError *loop_error = NULL;
+	GOutputStream *output_stream;
+	GDataOutputStream *data_output_stream;
+	guint n_columns;
+	int *column_sizes;
+	int *column_offsets;
+	const gchar **column_data;
+
+	output_stream = g_buffered_output_stream_new_sized (g_unix_output_stream_new (info->fd, TRUE),
+	                                                    TRACKER_STEROIDS_BUFFER_SIZE);
+	data_output_stream = g_data_output_stream_new (output_stream);
+
+	if (error) {
+		g_data_output_stream_put_int32 (data_output_stream,
+		                                TRACKER_STEROIDS_RC_ERROR,
+		                                NULL,
+		                                NULL);
+		g_object_unref (data_output_stream);
+		g_object_unref (output_stream);
+		ptr->error = g_error_copy (error);
+		return ptr;
+	}
+
+	n_columns = tracker_db_cursor_get_n_columns (cursor);
+
+	column_sizes = g_malloc (n_columns * sizeof (int));
+	column_offsets = g_malloc (n_columns * sizeof (int));
+	column_data = g_malloc (n_columns * sizeof (char*));
+
+	while (tracker_db_cursor_iter_next (cursor, &loop_error)) {
+		int i;
+		guint last_offset = -1;
+
+		if (loop_error != NULL) {
+			goto end_query_inthread;
+		}
+
+		for (i = 0; i < n_columns ; i++) {
+			const gchar *str;
+
+			str = tracker_db_cursor_get_string (cursor, i);
+
+			column_sizes[i] = str ? strlen (str) : 0;
+			column_data[i]  = str;
+
+			last_offset += column_sizes[i] + 1;
+			column_offsets[i] = last_offset;
+		}
+
+		g_data_output_stream_put_int32 (data_output_stream,
+		                                TRACKER_STEROIDS_RC_ROW,
+		                                NULL,
+		                                &loop_error);
+
+		if (loop_error) {
+			goto end_query_inthread;
+		}
+
+		g_data_output_stream_put_int32 (data_output_stream,
+		                                n_columns,
+		                                NULL,
+		                                &loop_error);
+
+		if (loop_error) {
+			goto end_query_inthread;
+		}
+
+		for (i = 0; i < n_columns; i++) {
+			g_data_output_stream_put_int32 (data_output_stream,
+			                                column_offsets[i],
+			                                NULL,
+			                                &loop_error);
+			if (loop_error) {
+				goto end_query_inthread;
+			}
+		}
+
+		for (i = 0; i < n_columns; i++) {
+			g_data_output_stream_put_string (data_output_stream,
+			                                 column_data[i] ? column_data[i] : "",
+			                                 NULL,
+			                                 &loop_error);
+			g_data_output_stream_put_byte (data_output_stream,
+			                               0,
+			                               NULL,
+			                               &loop_error);
+
+			if (loop_error) {
+				goto end_query_inthread;
+			}
+		}
+	}
+end_query_inthread:
+
+	if (!loop_error) {
+		g_data_output_stream_put_int32 (data_output_stream,
+		                                TRACKER_STEROIDS_RC_DONE,
+		                                NULL,
+		                                &loop_error);
+	}
+
+	/* Will force flushing */
+	g_object_unref (data_output_stream);
+	g_object_unref (output_stream);
+
+	if (loop_error) {
+		ptr->error = loop_error;
+	}
+
+	g_free (column_sizes);
+	g_free (column_offsets);
+	g_free (column_data);
+
+	return ptr;
+}
+
+static void
+tracker_steroids_query (TrackerSteroids *steroids,
+						DBusConnection  *connection,
+						DBusMessage     *message)
+{
+	ClientInfo  *info;
+	guint        request_id;
+	const gchar *sender;
+	DBusMessage *reply;
+	DBusError    dbus_error;
+	gchar       *query;
+
+	if (g_strcmp0 (dbus_message_get_signature (message), DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_UNIX_FD_AS_STRING)) {
+		reply = dbus_message_new_error_printf (message,
+		                                       DBUS_ERROR_UNKNOWN_METHOD_NAME,
+		                                       DBUS_ERROR_UNKNOWN_METHOD_MESSAGE,
+		                                       "Query",
+		                                       dbus_message_get_signature (message),
+		                                       dbus_message_get_interface (message));
+		dbus_connection_send (connection, reply, NULL);
+		dbus_message_unref (reply);
+		return;
+	}
+
+	request_id = tracker_dbus_get_next_request_id ();
+
+	tracker_dbus_request_new (request_id,
+	                          NULL,
+	                          "%s()",
+	                          __FUNCTION__);
+
+	info = g_slice_new0 (ClientInfo);
+	info->parent = steroids;
+	info->connection = dbus_connection_ref (connection);
+	info->call_message = dbus_message_ref (message);
+	info->request_id = request_id;
+
+	dbus_error_init (&dbus_error);
+
+	dbus_message_get_args (message,
+	                       &dbus_error,
+	                       DBUS_TYPE_STRING, &query,
+	                       DBUS_TYPE_UNIX_FD, &info->fd,
+	                       DBUS_TYPE_INVALID);
+
+	sender = dbus_message_get_sender (message);
+
+	tracker_store_sparql_query (query, TRACKER_STORE_PRIORITY_HIGH,
+	                            query_inthread, query_callback, sender,
+	                            info, destroy_client_info);
+}
+
+static void
+tracker_steroids_update (TrackerSteroids *steroids,
+                         DBusConnection  *connection,
+                         DBusMessage     *message,
+                         gboolean         batch,
+                         gboolean         update_blank)
+{
+	DBusError               dbus_error;
+	ClientInfo             *info;
+	GInputStream           *input_stream;
+	GDataInputStream       *data_input_stream;
+	GError                 *error = NULL;
+	gsize                   bytes_read;
+	guint                   request_id;
+	const gchar            *sender;
+	int                     query_size;
+	DBusMessage            *reply;
+	gchar                  *query;
+
+	if (g_strcmp0 (dbus_message_get_signature (message), DBUS_TYPE_UNIX_FD_AS_STRING)) {
+		reply = dbus_message_new_error_printf (message,
+		                                       DBUS_ERROR_UNKNOWN_METHOD_NAME,
+		                                       DBUS_ERROR_UNKNOWN_METHOD_MESSAGE,
+		                                       "Update",
+		                                       dbus_message_get_signature (message),
+		                                       dbus_message_get_interface (message));
+		dbus_connection_send (connection, reply, NULL);
+		dbus_message_unref (reply);
+		return;
+	}
+
+	request_id = tracker_dbus_get_next_request_id ();
+
+	tracker_dbus_request_new (request_id,
+	                          NULL,
+	                          "%s()",
+	                          __FUNCTION__);
+
+	info = g_slice_new0 (ClientInfo);
+	info->parent = steroids;
+	info->connection = dbus_connection_ref (connection);
+	info->call_message = dbus_message_ref (message);
+
+	dbus_error_init (&dbus_error);
+
+	dbus_message_get_args (message,
+	                       &dbus_error,
+	                       DBUS_TYPE_UNIX_FD, &info->fd,
+	                       DBUS_TYPE_INVALID);
+
+	info->request_id = request_id;
+
+	sender = dbus_message_get_sender (message);
+
+	input_stream = g_buffered_input_stream_new_sized (g_unix_input_stream_new (info->fd, TRUE),
+	                                                  TRACKER_STEROIDS_BUFFER_SIZE);
+	data_input_stream = g_data_input_stream_new (input_stream);
+
+	query_size = g_data_input_stream_read_int32 (data_input_stream,
+	                                             NULL,
+	                                             &error);
+
+	if (error) {
+		reply = dbus_message_new_error (info->call_message,
+		                                TRACKER_STEROIDS_INTERFACE ".UpdateError",
+		                                error->message);
+		dbus_connection_send (connection, reply, NULL);
+		dbus_message_unref (reply);
+
+		g_object_unref (data_input_stream);
+		g_object_unref (input_stream);
+		g_error_free (error);
+		destroy_client_info (info);
+
+		return;
+	}
+
+	/* We malloc one more char to ensure string is 0 terminated */
+	query = g_malloc0 ((1 + query_size) * sizeof (char));
+
+	g_input_stream_read_all (input_stream,
+	                         query,
+	                         query_size,
+	                         &bytes_read,
+	                         NULL,
+	                         &error);
+
+	if (error) {
+		reply = dbus_message_new_error (info->call_message,
+		                                TRACKER_STEROIDS_INTERFACE ".UpdateError",
+		                                error->message);
+		dbus_connection_send (connection, reply, NULL);
+		dbus_message_unref (reply);
+
+		g_free (query);
+		g_object_unref (data_input_stream);
+		g_object_unref (input_stream);
+		g_error_free (error);
+		destroy_client_info (info);
+
+		return;
+	}
+
+	g_object_unref (data_input_stream);
+	g_object_unref (input_stream);
+
+	if (update_blank) {
+		tracker_store_sparql_update_blank (query, TRACKER_STORE_PRIORITY_HIGH,
+		                                   update_blank_callback, sender,
+		                                   info, destroy_client_info);
+	} else {
+		tracker_store_sparql_update (query,
+		                             batch ? TRACKER_STORE_PRIORITY_LOW : TRACKER_STORE_PRIORITY_HIGH,
+		                             FALSE,
+		                             update_callback, sender,
+		                             info, destroy_client_info);
+	}
+}
+
+DBusHandlerResult
+tracker_steroids_connection_filter (DBusConnection *connection,
+                                    DBusMessage    *message,
+                                    void           *user_data)
+{
+	TrackerSteroids *steroids = user_data;
+
+	g_return_val_if_fail (TRACKER_IS_STEROIDS (steroids), DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
+
+	if (g_strcmp0 (TRACKER_STEROIDS_PATH, dbus_message_get_path (message))) {
+		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+	}
+
+	if (g_strcmp0 (TRACKER_STEROIDS_INTERFACE, dbus_message_get_interface (message))) {
+		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+	}
+
+	if (!g_strcmp0 ("Query", dbus_message_get_member (message))) {
+		tracker_steroids_query (steroids, connection, message);
+		return DBUS_HANDLER_RESULT_HANDLED;
+	}
+
+	if (!g_strcmp0 ("Update", dbus_message_get_member (message))) {
+		tracker_steroids_update (steroids, connection, message, FALSE, FALSE);
+		return DBUS_HANDLER_RESULT_HANDLED;
+	}
+
+	if (!g_strcmp0 ("UpdateBlank", dbus_message_get_member (message))) {
+		tracker_steroids_update (steroids, connection, message, FALSE, TRUE);
+		return DBUS_HANDLER_RESULT_HANDLED;
+	}
+
+	if (!g_strcmp0 ("BatchUpdate", dbus_message_get_member (message))) {
+		tracker_steroids_update (steroids, connection, message, TRUE, FALSE);
+		return DBUS_HANDLER_RESULT_HANDLED;
+	}
+
+	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static void
+tracker_steroids_finalize (GObject *object)
+{
+	TrackerSteroidsPrivate *priv = TRACKER_STEROIDS_GET_PRIVATE (object);
+
+	g_hash_table_unref (priv->clients);
+}
diff --git a/src/tracker-store/tracker-steroids.h b/src/tracker-store/tracker-steroids.h
new file mode 100644
index 0000000..5191fab
--- /dev/null
+++ b/src/tracker-store/tracker-steroids.h
@@ -0,0 +1,65 @@
+/* 
+ * 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.
+ */
+
+#ifndef __TRACKER_STEROIDS_H__
+#define __TRACKER_STEROIDS_H__
+
+#include <glib-object.h>
+
+#define TRACKER_STEROIDS_SERVICE   "org.freedesktop.Tracker1"
+#define TRACKER_STEROIDS_PATH      "/org/freedesktop/Tracker1/Steroids"
+#define TRACKER_STEROIDS_INTERFACE "org.freedesktop.Tracker1.Steroids"
+
+G_BEGIN_DECLS
+
+#define TRACKER_TYPE_STEROIDS            (tracker_steroids_get_type ())
+#define TRACKER_STEROIDS(object)         (G_TYPE_CHECK_INSTANCE_CAST ((object), TRACKER_TYPE_STEROIDS, TrackerSteroids))
+#define TRACKER_STEROIDS_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), TRACKER_TYPE_DBUS_STEROIDS, TrackerSteroidsClass))
+#define TRACKER_IS_STEROIDS(object)      (G_TYPE_CHECK_INSTANCE_TYPE ((object), TRACKER_TYPE_STEROIDS))
+#define TRACKER_IS_STEROIDS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TRACKER_TYPE_STEROIDS))
+#define TRACKER_STEROIDS_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), TRACKER_TYPE_STEROIDS, TrackerSteroidsClass))
+
+#define TRACKER_STEROIDS_BUFFER_SIZE 65536
+
+#define TRACKER_STEROIDS_RC_ERROR 0
+#define TRACKER_STEROIDS_RC_ROW   1
+#define TRACKER_STEROIDS_RC_DONE  2
+#define TRACKER_STEROIDS_RC_LARGEROW 3
+
+#define TRACKER_STEROIDS_EOP      0xFF
+
+typedef struct TrackerSteroids      TrackerSteroids;
+typedef struct TrackerSteroidsClass TrackerSteroidsClass;
+
+struct TrackerSteroids {
+	GObject parent;
+};
+
+struct TrackerSteroidsClass {
+	GObjectClass parent;
+};
+
+GType            tracker_steroids_get_type (void) G_GNUC_CONST;
+TrackerSteroids* tracker_steroids_new      (void);
+DBusHandlerResult
+        tracker_steroids_connection_filter (DBusConnection *connection,
+                                            DBusMessage    *message,
+                                            void           *user_data);
+
+#endif /* __TRACKER_STEROIDS_H__ */



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