Commit f76d0869 authored by Adrien Bustany's avatar Adrien Bustany Committed by Martyn Russell

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.
parent 13327be6
...@@ -13,6 +13,7 @@ INCLUDES = \ ...@@ -13,6 +13,7 @@ INCLUDES = \
-I$(top_builddir)/src/libtracker-client \ -I$(top_builddir)/src/libtracker-client \
$(WARN_CFLAGS) \ $(WARN_CFLAGS) \
$(GLIB2_CFLAGS) \ $(GLIB2_CFLAGS) \
$(GIO_CFLAGS) \
$(GCOV_CFLAGS) \ $(GCOV_CFLAGS) \
$(GDKPIXBUF_CFLAGS) \ $(GDKPIXBUF_CFLAGS) \
$(GMODULE_CFLAGS) \ $(GMODULE_CFLAGS) \
......
...@@ -177,6 +177,25 @@ tracker_dbus_register_objects (gpointer object) ...@@ -177,6 +177,25 @@ tracker_dbus_register_objects (gpointer object)
return TRUE; 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 * GObject *
tracker_dbus_get_object (GType type) tracker_dbus_get_object (GType type)
{ {
......
...@@ -24,12 +24,17 @@ ...@@ -24,12 +24,17 @@
#include <glib.h> #include <glib.h>
#include <dbus/dbus-glib-bindings.h> #include <dbus/dbus-glib-bindings.h>
#include <dbus/dbus.h>
G_BEGIN_DECLS G_BEGIN_DECLS
gboolean tracker_dbus_init (void); gboolean tracker_dbus_init (void);
void tracker_dbus_shutdown (void); void tracker_dbus_shutdown (void);
gboolean tracker_dbus_register_objects (gpointer object); 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); GObject *tracker_dbus_get_object (GType type);
G_END_DECLS G_END_DECLS
......
...@@ -25,6 +25,9 @@ ...@@ -25,6 +25,9 @@
#include <gmodule.h> #include <gmodule.h>
#include <gio/gio.h> #include <gio/gio.h>
#include <gio/gunixoutputstream.h>
#include <gio/gunixinputstream.h>
#include <libtracker-common/tracker-dbus.h> #include <libtracker-common/tracker-dbus.h>
#include <libtracker-common/tracker-log.h> #include <libtracker-common/tracker-log.h>
...@@ -45,6 +48,9 @@ ...@@ -45,6 +48,9 @@
#define MAX_EXTRACT_TIME 10 #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)) #define TRACKER_EXTRACT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TRACKER_TYPE_EXTRACT, TrackerExtractPrivate))
extern gboolean debug; extern gboolean debug;
...@@ -615,3 +621,219 @@ tracker_extract_get_metadata (TrackerExtract *object, ...@@ -615,3 +621,219 @@ tracker_extract_get_metadata (TrackerExtract *object,
alarm (0); 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 */
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <glib-object.h> #include <glib-object.h>
#include <dbus/dbus-glib-bindings.h> #include <dbus/dbus-glib-bindings.h>
#include <dbus/dbus.h>
#define TRACKER_EXTRACT_SERVICE "org.freedesktop.Tracker1.Extract" #define TRACKER_EXTRACT_SERVICE "org.freedesktop.Tracker1.Extract"
#define TRACKER_EXTRACT_PATH "/org/freedesktop/Tracker1/Extract" #define TRACKER_EXTRACT_PATH "/org/freedesktop/Tracker1/Extract"
...@@ -60,6 +61,11 @@ void tracker_extract_get_metadata (TrackerExtract ...@@ -60,6 +61,11 @@ void tracker_extract_get_metadata (TrackerExtract
const gchar *mime, const gchar *mime,
DBusGMethodInvocation *context, DBusGMethodInvocation *context,
GError **error); 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 */ /* Not DBus API */
void tracker_extract_get_metadata_by_cmdline (TrackerExtract *object, void tracker_extract_get_metadata_by_cmdline (TrackerExtract *object,
......
...@@ -453,6 +453,11 @@ main (int argc, char *argv[]) ...@@ -453,6 +453,11 @@ main (int argc, char *argv[])
return EXIT_FAILURE; 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..."); g_message ("Waiting for D-Bus requests...");
tracker_albumart_init (); tracker_albumart_init ();
......
Markdown is supported
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