[tracker/extractor-dbus-fd: 1/2] tracker-extract: Add a GetMetadataFast method



commit 9eae263943202cad8a2475c4bbccb439959035b0
Author: Adrien Bustany <abustany gnome org>
Date:   Wed Jun 30 12:16:19 2010 +0200

    tracker-extract: Add a GetMetadataFast method
    
    The GetMetadataFast method uses DBus FD passing to transfer the
    resulting SPARQL query. The client passes a FD when calling the method,
    and the resulting queries will be written to that FD.

 src/tracker-extract/Makefile.am       |    1 +
 src/tracker-extract/tracker-dbus.c    |   19 +++
 src/tracker-extract/tracker-dbus.h    |    5 +
 src/tracker-extract/tracker-extract.c |  222 +++++++++++++++++++++++++++++++++
 src/tracker-extract/tracker-extract.h |    6 +
 src/tracker-extract/tracker-main.c    |    5 +
 6 files changed, 258 insertions(+), 0 deletions(-)
---
diff --git a/src/tracker-extract/Makefile.am b/src/tracker-extract/Makefile.am
index d512f08..ac02995 100644
--- a/src/tracker-extract/Makefile.am
+++ b/src/tracker-extract/Makefile.am
@@ -13,6 +13,7 @@ INCLUDES = 								\
 	-I$(top_builddir)/src/libtracker-client				\
 	$(WARN_CFLAGS)							\
 	$(GLIB2_CFLAGS)							\
+	$(GIO_CFLAGS)							\
 	$(GCOV_CFLAGS)							\
 	$(GDKPIXBUF_CFLAGS)						\
 	$(GMODULE_CFLAGS) 						\
diff --git a/src/tracker-extract/tracker-dbus.c b/src/tracker-extract/tracker-dbus.c
index 0270ad2..b2a0702 100644
--- a/src/tracker-extract/tracker-dbus.c
+++ b/src/tracker-extract/tracker-dbus.c
@@ -177,6 +177,25 @@ tracker_dbus_register_objects (gpointer object)
 	return TRUE;
 }
 
+#ifdef HAVE_DBUS_FD_PASSING
+gboolean
+tracker_dbus_connection_add_filter (DBusHandleMessageFunction  function,
+                                    void                      *user_data)
+{
+	if (!connection) {
+		g_critical ("D-Bus support must be initialized before adding connection filters!");
+		return FALSE;
+	}
+
+	dbus_connection_add_filter (dbus_g_connection_get_connection (connection),
+	                            function,
+	                            user_data,
+	                            NULL);
+
+	return TRUE;
+}
+#endif /* HAVE_DBUS_FD_PASSING */
+
 GObject *
 tracker_dbus_get_object (GType type)
 {
diff --git a/src/tracker-extract/tracker-dbus.h b/src/tracker-extract/tracker-dbus.h
index 7ffd5cc..1b6ee6c 100644
--- a/src/tracker-extract/tracker-dbus.h
+++ b/src/tracker-extract/tracker-dbus.h
@@ -24,12 +24,17 @@
 #include <glib.h>
 
 #include <dbus/dbus-glib-bindings.h>
+#include <dbus/dbus.h>
 
 G_BEGIN_DECLS
 
 gboolean tracker_dbus_init             (void);
 void     tracker_dbus_shutdown         (void);
 gboolean tracker_dbus_register_objects (gpointer object);
+#ifdef HAVE_DBUS_FD_PASSING
+gboolean tracker_dbus_connection_add_filter (DBusHandleMessageFunction  function,
+                                             void                      *user_data);
+#endif /* HAVE_DBUS_FD_PASSING */
 GObject *tracker_dbus_get_object       (GType    type);
 
 G_END_DECLS
diff --git a/src/tracker-extract/tracker-extract.c b/src/tracker-extract/tracker-extract.c
index ab9c8a9..f5d87eb 100644
--- a/src/tracker-extract/tracker-extract.c
+++ b/src/tracker-extract/tracker-extract.c
@@ -25,6 +25,9 @@
 #include <gmodule.h>
 #include <gio/gio.h>
 
+#include <gio/gunixoutputstream.h>
+#include <gio/gunixinputstream.h>
+
 #include <libtracker-common/tracker-dbus.h>
 #include <libtracker-common/tracker-log.h>
 
@@ -45,6 +48,9 @@
 
 #define MAX_EXTRACT_TIME 10
 
+#define UNKNOWN_METHOD_MESSAGE "Method \"%s\" with signature \"%s\" on " \
+                               "interface \"%s\" doesn't exist, expected \"%s\""
+
 #define TRACKER_EXTRACT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TRACKER_TYPE_EXTRACT, TrackerExtractPrivate))
 
 extern gboolean debug;
@@ -615,3 +621,219 @@ tracker_extract_get_metadata (TrackerExtract         *object,
 		alarm (0);
 	}
 }
+
+#ifdef HAVE_DBUS_FD_PASSING
+static void
+get_metadata_fast (TrackerExtract *object,
+                   DBusConnection *connection,
+                   DBusMessage    *message)
+{
+	guint request_id;
+	const gchar *expected_signature;
+	TrackerExtractPrivate *priv;
+	DBusError dbus_error;
+	DBusMessage *reply;
+	const gchar *uri, *mime;
+	int fd;
+	GOutputStream *unix_output_stream;
+	GOutputStream *buffered_output_stream;
+	GDataOutputStream *data_output_stream;
+	GError *error = NULL;
+	TrackerSparqlBuilder *sparql, *preupdate;
+	gboolean extracted = FALSE;
+
+	request_id = tracker_dbus_get_next_request_id ();
+
+	expected_signature = DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_UNIX_FD_AS_STRING;
+
+	if (g_strcmp0 (dbus_message_get_signature (message), expected_signature)) {
+		gchar *error_message = g_strdup_printf (UNKNOWN_METHOD_MESSAGE,
+		                                        "GetMetadataFast",
+		                                        dbus_message_get_signature (message),
+		                                        dbus_message_get_interface (message),
+		                                        expected_signature);
+		tracker_dbus_request_new (request_id,
+		                          NULL,
+		                          "%s()",
+		                          __FUNCTION__);
+
+		reply = dbus_message_new_error (message,
+		                                DBUS_ERROR_UNKNOWN_METHOD,
+		                                error_message);
+		dbus_connection_send (connection, reply, NULL);
+
+		tracker_dbus_request_failed (request_id,
+		                             NULL,
+		                             NULL,
+		                             error_message);
+
+		dbus_message_unref (reply);
+		g_free (error_message);
+
+		return;
+	}
+
+	dbus_error_init (&dbus_error);
+
+	dbus_message_get_args (message,
+	                       &dbus_error,
+	                       DBUS_TYPE_STRING, &uri,
+	                       DBUS_TYPE_STRING, &mime,
+	                       DBUS_TYPE_UNIX_FD, &fd,
+	                       DBUS_TYPE_INVALID);
+
+	if (dbus_error_is_set (&dbus_error)) {
+		tracker_dbus_request_new (request_id,
+		                          NULL,
+		                          "%s()",
+		                          __FUNCTION__);
+
+		reply = dbus_message_new_error (message, dbus_error.name, dbus_error.message);
+		dbus_connection_send (connection, reply, NULL);
+
+		tracker_dbus_request_failed (request_id,
+		                             NULL,
+		                             NULL,
+		                             dbus_error.message);
+
+		dbus_message_unref (reply);
+		dbus_error_free (&dbus_error);
+
+		return;
+	}
+
+	tracker_dbus_request_new (request_id,
+	                          NULL,
+	                          "%s(uri:'%s', mime:%s)",
+	                          __FUNCTION__,
+	                          uri,
+	                          mime);
+
+	tracker_dbus_request_debug (request_id,
+	                            NULL,
+	                            "  Resetting shutdown timeout");
+
+	priv = TRACKER_EXTRACT_GET_PRIVATE (object);
+
+	tracker_main_quit_timeout_reset ();
+	if (!priv->disable_shutdown) {
+		alarm (MAX_EXTRACT_TIME);
+	}
+
+	extracted = get_file_metadata (object, request_id, NULL, uri, mime, &preupdate, &sparql);
+
+	if (extracted) {
+		unix_output_stream = g_unix_output_stream_new (fd, TRUE);
+		buffered_output_stream = g_buffered_output_stream_new_sized (unix_output_stream,
+		                                                             64*1024);
+		data_output_stream = g_data_output_stream_new (buffered_output_stream);
+		g_data_output_stream_set_byte_order (G_DATA_OUTPUT_STREAM (data_output_stream),
+		                                     G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN);
+
+		if (tracker_sparql_builder_get_length (sparql) > 0) {
+			const gchar *preupdate_str = NULL;
+
+			if (tracker_sparql_builder_get_length (preupdate) > 0) {
+				preupdate_str = tracker_sparql_builder_get_result (preupdate);
+			}
+
+			g_data_output_stream_put_string (data_output_stream,
+			                                 preupdate_str ? preupdate_str : "",
+			                                 NULL,
+			                                 &error);
+
+			if (!error) {
+				g_data_output_stream_put_byte (data_output_stream,
+				                               0,
+				                               NULL,
+				                               &error);
+			}
+
+			if (!error) {
+				g_data_output_stream_put_string (data_output_stream,
+				                                 tracker_sparql_builder_get_result (sparql),
+				                                 NULL,
+				                                 &error);
+			}
+
+			if (!error) {
+				g_data_output_stream_put_byte (data_output_stream,
+				                               0,
+				                               NULL,
+				                               &error);
+			}
+		}
+
+		g_object_unref (sparql);
+		g_object_unref (preupdate);
+		g_object_unref (data_output_stream);
+		g_object_unref (buffered_output_stream);
+		g_object_unref (unix_output_stream);
+
+		if (error) {
+			tracker_dbus_request_failed (request_id,
+			                             NULL,
+			                             &error,
+			                             NULL);
+			reply = dbus_message_new_error (message,
+			                                TRACKER_EXTRACT_SERVICE ".GetMetadataFastError",
+			                                error->message);
+			dbus_connection_send (connection, reply, NULL);
+			dbus_message_unref (reply);
+			g_error_free (error);
+		} else {
+			tracker_dbus_request_success (request_id, NULL);
+			reply = dbus_message_new_method_return (message);
+			dbus_connection_send (connection, reply, NULL);
+			dbus_message_unref (reply);
+		}
+	} else {
+		gchar *error_message = g_strdup_printf ("Could not get any metadata for uri:'%s' and mime:'%s'", uri, mime);
+		tracker_dbus_request_failed (request_id,
+		                             NULL,
+		                             NULL,
+		                             error_message);
+		reply = dbus_message_new_error (message,
+		                                TRACKER_EXTRACT_SERVICE ".GetMetadataFastError",
+		                                error_message);
+		close (fd);
+		dbus_connection_send (connection, reply, NULL);
+		dbus_message_unref (reply);
+		g_free (error_message);
+	}
+
+	if (!priv->disable_shutdown) {
+		/* Unset alarm so the extractor doesn't die when it's idle */
+		alarm (0);
+	}
+}
+
+DBusHandlerResult
+tracker_extract_connection_filter (DBusConnection *connection,
+                                   DBusMessage    *message,
+                                   void           *user_data)
+{
+	TrackerExtract *extract;
+
+	g_return_val_if_fail (connection != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
+	g_return_val_if_fail (message != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
+
+	extract = user_data;
+	g_return_val_if_fail (TRACKER_IS_EXTRACT (extract), DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
+
+	if (g_strcmp0 (TRACKER_EXTRACT_PATH, dbus_message_get_path (message))) {
+		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+	}
+
+	if (g_strcmp0 (TRACKER_EXTRACT_INTERFACE, dbus_message_get_interface (message))) {
+		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+	}
+
+	if (!g_strcmp0 ("GetMetadataFast", dbus_message_get_member (message))) {
+		get_metadata_fast (extract, connection, message);
+		return DBUS_HANDLER_RESULT_HANDLED;
+	}
+
+	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+#endif /* HAVE_DBUS_FD_PASSING */
diff --git a/src/tracker-extract/tracker-extract.h b/src/tracker-extract/tracker-extract.h
index 25bd889..2542a41 100644
--- a/src/tracker-extract/tracker-extract.h
+++ b/src/tracker-extract/tracker-extract.h
@@ -23,6 +23,7 @@
 #include <glib-object.h>
 
 #include <dbus/dbus-glib-bindings.h>
+#include <dbus/dbus.h>
 
 #define TRACKER_EXTRACT_SERVICE        "org.freedesktop.Tracker1.Extract"
 #define TRACKER_EXTRACT_PATH           "/org/freedesktop/Tracker1/Extract"
@@ -60,6 +61,11 @@ void            tracker_extract_get_metadata            (TrackerExtract
                                                          const gchar            *mime,
                                                          DBusGMethodInvocation  *context,
                                                          GError                **error);
+#ifdef HAVE_DBUS_FD_PASSING
+DBusHandlerResult tracker_extract_connection_filter     (DBusConnection         *connection,
+                                                         DBusMessage            *message,
+                                                         void                   *user_data);
+#endif /* HAVE_DBUS_FD_PASSING */
 
 /* Not DBus API */
 void            tracker_extract_get_metadata_by_cmdline (TrackerExtract         *object,
diff --git a/src/tracker-extract/tracker-main.c b/src/tracker-extract/tracker-main.c
index 394cd7f..2640931 100644
--- a/src/tracker-extract/tracker-main.c
+++ b/src/tracker-extract/tracker-main.c
@@ -453,6 +453,11 @@ main (int argc, char *argv[])
 		return EXIT_FAILURE;
 	}
 
+#ifdef HAVE_DBUS_FD_PASSING
+	tracker_dbus_connection_add_filter (tracker_extract_connection_filter,
+	                                    object);
+#endif
+
 	g_message ("Waiting for D-Bus requests...");
 
 	tracker_albumart_init ();



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