[tracker/extraction-improvements: 1/3] libtracker-extract: Add tracker-extract-client API



commit 0df5f8f95fe95901ca4f55d03250f760e2bff4f2
Author: Carlos Garnacho <carlosg gnome org>
Date:   Wed May 4 14:37:44 2011 +0200

    libtracker-extract: Add tracker-extract-client API
    
    This API is meant to replace the code in TrackerMinerFiles to
    deal with the communication with the extractor.

 src/libtracker-extract/Makefile.am              |    3 +
 src/libtracker-extract/tracker-extract-client.c |  406 ++++++++++++++++++++++
 src/libtracker-extract/tracker-extract-client.h |   49 +++
 src/libtracker-extract/tracker-extract.h        |    1 +
 src/miners/fs/tracker-miner-files.c             |  412 +---------------------
 5 files changed, 478 insertions(+), 393 deletions(-)
---
diff --git a/src/libtracker-extract/Makefile.am b/src/libtracker-extract/Makefile.am
index 5335269..6007011 100644
--- a/src/libtracker-extract/Makefile.am
+++ b/src/libtracker-extract/Makefile.am
@@ -17,6 +17,8 @@ libtracker_extract_ TRACKER_API_VERSION@_la_SOURCES =  \
 	tracker-encoding.c                             \
 	tracker-exif.c                                 \
 	tracker-exif.h                                 \
+	tracker-extract-client.c                       \
+	tracker-extract-client.h                       \
 	tracker-guarantee.c                            \
 	tracker-guarantee.h                            \
 	tracker-iptc.c                                 \
@@ -33,6 +35,7 @@ libtracker_extractinclude_HEADERS =                    \
 	tracker-data.h                                 \
 	tracker-encoding.h                             \
 	tracker-exif.h                                 \
+	tracker-extract-client.h                       \
 	tracker-extract.h                              \
 	tracker-guarantee.h                            \
 	tracker-iptc.h                                 \
diff --git a/src/libtracker-extract/tracker-extract-client.c b/src/libtracker-extract/tracker-extract-client.c
new file mode 100644
index 0000000..8aabcca
--- /dev/null
+++ b/src/libtracker-extract/tracker-extract-client.c
@@ -0,0 +1,406 @@
+/*
+ * Copyright (C) 2010, Nokia <ivan frade nokia com>
+ *
+ * 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 "tracker-extract-client.h"
+
+#include <string.h>
+#include <gio/gunixfdlist.h>
+#include <gio/gunixinputstream.h>
+
+/* Size of buffers used when sending data over a pipe, using DBus FD passing */
+#define DBUS_PIPE_BUFFER_SIZE      65536
+
+#define DBUS_SERVICE_EXTRACT       "org.freedesktop.Tracker1.Extract"
+#define DBUS_PATH_EXTRACT          "/org/freedesktop/Tracker1/Extract"
+#define DBUS_INTERFACE_EXTRACT     "org.freedesktop.Tracker1.Extract"
+
+struct TrackerExtractInfo {
+	gchar *preupdate;
+	gchar *update;
+	gchar *where;
+};
+
+typedef void (* SendAndSpliceCallback) (void     *buffer,
+                                        gssize    buffer_size,
+                                        GError   *error, /* Don't free */
+                                        gpointer  user_data);
+
+typedef struct {
+	GInputStream *unix_input_stream;
+	GInputStream *buffered_input_stream;
+	GOutputStream *output_stream;
+	SendAndSpliceCallback callback;
+	GCancellable *cancellable;
+	GSimpleAsyncResult *res;
+	gboolean splice_finished;
+	gboolean dbus_finished;
+	GError *error;
+} SendAndSpliceData;
+
+static TrackerExtractInfo *
+tracker_extract_info_new (const gchar *preupdate,
+                          const gchar *update,
+                          const gchar *where)
+{
+	TrackerExtractInfo *info;
+
+	info = g_slice_new0 (TrackerExtractInfo);
+	info->preupdate = g_strdup (preupdate);
+	info->update = g_strdup (update);
+	info->where = g_strdup (where);
+
+	return info;
+}
+
+static void
+tracker_extract_info_free (TrackerExtractInfo *info)
+{
+	g_free (info->preupdate);
+	g_free (info->update);
+	g_free (info->where);
+
+	g_slice_free (TrackerExtractInfo, info);
+}
+
+static SendAndSpliceData *
+send_and_splice_data_new (GInputStream          *unix_input_stream,
+                          GInputStream          *buffered_input_stream,
+                          GOutputStream         *output_stream,
+                          GCancellable          *cancellable,
+                          SendAndSpliceCallback  callback,
+                          GSimpleAsyncResult    *res)
+{
+	SendAndSpliceData *data;
+
+	data = g_slice_new0 (SendAndSpliceData);
+	data->unix_input_stream = unix_input_stream;
+	data->buffered_input_stream = buffered_input_stream;
+	data->output_stream = output_stream;
+
+	if (cancellable) {
+		data->cancellable = g_object_ref (cancellable);
+	}
+
+	data->callback = callback;
+	data->res = g_object_ref (res);
+
+	return data;
+}
+
+static void
+send_and_splice_data_free (SendAndSpliceData *data)
+{
+	g_object_unref (data->unix_input_stream);
+	g_object_unref (data->buffered_input_stream);
+	g_object_unref (data->output_stream);
+
+	if (data->cancellable) {
+		g_object_unref (data->cancellable);
+	}
+
+	if (data->error) {
+		g_error_free (data->error);
+	}
+
+	if (data->res) {
+		g_object_unref (data->res);
+	}
+
+	g_slice_free (SendAndSpliceData, data);
+}
+
+static void
+dbus_send_and_splice_async_finish (SendAndSpliceData *data)
+{
+	if (!data->error) {
+		(* data->callback) (g_memory_output_stream_get_data (G_MEMORY_OUTPUT_STREAM (data->output_stream)),
+		                    g_memory_output_stream_get_data_size (G_MEMORY_OUTPUT_STREAM (data->output_stream)),
+		                    NULL,
+		                    data->res);
+	} else {
+		(* data->callback) (NULL, -1, data->error, data->res);
+	}
+
+	send_and_splice_data_free (data);
+}
+
+static void
+send_and_splice_splice_callback (GObject      *source,
+                                 GAsyncResult *result,
+                                 gpointer      user_data)
+{
+	SendAndSpliceData *data = user_data;
+	GError *error = NULL;
+
+	g_output_stream_splice_finish (G_OUTPUT_STREAM (source), result, &error);
+
+	if (error) {
+		if (!data->error) {
+			data->error = error;
+		} else {
+			g_error_free (error);
+		}
+	}
+
+	data->splice_finished = TRUE;
+
+	if (data->dbus_finished) {
+		dbus_send_and_splice_async_finish (data);
+	}
+}
+
+static void
+send_and_splice_dbus_callback (GObject      *source,
+                               GAsyncResult *result,
+                               gpointer      user_data)
+{
+	SendAndSpliceData *data = user_data;
+	GDBusMessage *reply;
+	GError *error = NULL;
+
+	reply = g_dbus_connection_send_message_with_reply_finish (G_DBUS_CONNECTION (source),
+	                                                          result, &error);
+
+	if (reply) {
+		if (g_dbus_message_get_message_type (reply) == G_DBUS_MESSAGE_TYPE_ERROR) {
+			g_dbus_message_to_gerror (reply, &error);
+		}
+
+		g_object_unref (reply);
+	}
+
+	if (error) {
+		if (!data->error) {
+			data->error = error;
+		} else {
+			g_error_free (error);
+		}
+	}
+
+	data->dbus_finished = TRUE;
+
+	if (data->splice_finished) {
+		dbus_send_and_splice_async_finish (data);
+	}
+}
+
+static void
+dbus_send_and_splice_async (GDBusConnection       *connection,
+                            GDBusMessage          *message,
+                            int                    fd,
+                            GCancellable          *cancellable,
+                            SendAndSpliceCallback  callback,
+                            GSimpleAsyncResult    *res)
+{
+	SendAndSpliceData *data;
+	GInputStream *unix_input_stream;
+	GInputStream *buffered_input_stream;
+	GOutputStream *output_stream;
+
+	unix_input_stream = g_unix_input_stream_new (fd, TRUE);
+	buffered_input_stream = g_buffered_input_stream_new_sized (unix_input_stream,
+	                                                           DBUS_PIPE_BUFFER_SIZE);
+	output_stream = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
+
+	data = send_and_splice_data_new (unix_input_stream,
+	                                 buffered_input_stream,
+	                                 output_stream,
+	                                 cancellable,
+	                                 callback,
+	                                 res);
+
+	g_dbus_connection_send_message_with_reply (connection,
+	                                           message,
+	                                           G_DBUS_SEND_MESSAGE_FLAGS_NONE,
+	                                           -1,
+	                                           NULL,
+	                                           cancellable,
+	                                           send_and_splice_dbus_callback,
+	                                           data);
+
+	g_output_stream_splice_async (data->output_stream,
+	                              data->buffered_input_stream,
+	                              G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE |
+	                              G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
+	                              0,
+	                              cancellable,
+	                              send_and_splice_splice_callback,
+	                              data);
+}
+
+static void
+get_metadata_fast_cb (void     *buffer,
+                      gssize    buffer_size,
+                      GError   *error,
+                      gpointer  user_data)
+{
+	GSimpleAsyncResult *res;
+
+	res = user_data;
+
+	if (G_UNLIKELY (error)) {
+		g_simple_async_result_set_from_error (res, error);
+	} else {
+		const gchar *preupdate, *sparql, *where, *end;
+		TrackerExtractInfo *info;
+		gsize len;
+
+		preupdate = sparql = where = NULL;
+		end = (gchar *) buffer + buffer_size;
+
+		if (buffer) {
+			preupdate = buffer;
+			len = strlen (preupdate);
+
+			if (preupdate + len < end) {
+				buffer_size -= len;
+				sparql = preupdate + len + 1;
+				len = strlen (sparql);
+
+				if (sparql + len < end) {
+					where = sparql + len + 1;
+				}
+			}
+		}
+
+		info = tracker_extract_info_new (preupdate, sparql, where);
+		g_simple_async_result_set_op_res_gpointer (res, info,
+		                                           (GDestroyNotify) tracker_extract_info_free);
+	}
+
+	g_simple_async_result_complete_in_idle (res);
+}
+
+static void
+get_metadata_fast_async (GDBusConnection    *connection,
+                         const gchar        *uri,
+                         const gchar        *mime_type,
+                         GCancellable       *cancellable,
+                         GSimpleAsyncResult *res)
+{
+	GDBusMessage *message;
+	GUnixFDList *fd_list;
+	int pipefd[2];
+
+	if (pipe (pipefd) < 0) {
+		g_critical ("Coudln't open pipe");
+		/* FIXME: Report async error */
+		return;
+	}
+
+	message = g_dbus_message_new_method_call (DBUS_SERVICE_EXTRACT,
+	                                          DBUS_PATH_EXTRACT,
+	                                          DBUS_INTERFACE_EXTRACT,
+	                                          "GetMetadataFast");
+
+	fd_list = g_unix_fd_list_new ();
+
+	g_dbus_message_set_body (message,
+	                         g_variant_new ("(ssh)",
+	                                        uri,
+	                                        mime_type,
+	                                        g_unix_fd_list_append (fd_list,
+	                                                               pipefd[1],
+	                                                               NULL)));
+	g_dbus_message_set_unix_fd_list (message, fd_list);
+
+	/* We need to close the fd as g_unix_fd_list_append duplicates the fd */
+
+	close (pipefd[1]);
+
+	g_object_unref (fd_list);
+
+	dbus_send_and_splice_async (connection,
+	                            message,
+	                            pipefd[0],
+	                            cancellable,
+	                            get_metadata_fast_cb,
+	                            res);
+	g_object_unref (message);
+}
+
+void
+tracker_extract_client_get_metadata (GFile               *file,
+                                     const gchar         *mime_type,
+                                     GCancellable        *cancellable,
+                                     GAsyncReadyCallback  callback,
+                                     gpointer             user_data)
+{
+	static GDBusConnection *connection = NULL;
+	GSimpleAsyncResult *res;
+	GError *error = NULL;
+	gchar *uri;
+
+	g_return_if_fail (G_IS_FILE (file));
+	g_return_if_fail (mime_type != NULL);
+	g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+	g_return_if_fail (callback != NULL);
+
+	if (G_UNLIKELY (!connection)) {
+		connection = g_bus_get_sync (G_BUS_TYPE_SESSION, cancellable, &error);
+
+		if (error) {
+			g_simple_async_report_gerror_in_idle (G_OBJECT (file), callback, user_data, error);
+			g_error_free (error);
+			return;
+		}
+	}
+
+	uri = g_file_get_uri (file);
+
+	res = g_simple_async_result_new (G_OBJECT (file), callback, user_data, NULL);
+	g_simple_async_result_set_handle_cancellation (res, TRUE);
+
+	get_metadata_fast_async (connection, uri, mime_type, cancellable, res);
+}
+
+TrackerExtractInfo *
+tracker_extract_client_get_metadata_finish (GFile         *file,
+                                            GAsyncResult  *res,
+                                            GError       **error)
+{
+	g_return_val_if_fail (G_IS_FILE (file), NULL);
+	g_return_val_if_fail (G_IS_ASYNC_RESULT (res), NULL);
+	g_return_val_if_fail (!error || !*error, NULL);
+
+	if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error)) {
+		return NULL;
+	}
+
+	return g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res));
+}
+
+G_CONST_RETURN gchar *
+tracker_extract_info_get_preupdate (TrackerExtractInfo *info)
+{
+	return info->preupdate;
+}
+
+G_CONST_RETURN gchar *
+tracker_extract_info_get_update (TrackerExtractInfo *info)
+{
+	return info->update;
+}
+
+G_CONST_RETURN gchar *
+tracker_extract_info_get_where_clause (TrackerExtractInfo *info)
+{
+	return info->where;
+}
diff --git a/src/libtracker-extract/tracker-extract-client.h b/src/libtracker-extract/tracker-extract-client.h
new file mode 100644
index 0000000..bd72a2d
--- /dev/null
+++ b/src/libtracker-extract/tracker-extract-client.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2011, Nokia <ivan frade nokia com>
+ *
+ * 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_EXTRACT_CLIENT_H__
+#define __TRACKER_EXTRACT_CLIENT_H__
+
+#if !defined (__LIBTRACKER_EXTRACT_INSIDE__) && !defined (TRACKER_COMPILATION)
+#error "only <libtracker-extract/tracker-extract.h> must be included directly."
+#endif
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+typedef struct TrackerExtractInfo TrackerExtractInfo;
+
+void                 tracker_extract_client_get_metadata        (GFile               *file,
+                                                                 const gchar         *mime_type,
+                                                                 GCancellable        *cancellable,
+                                                                 GAsyncReadyCallback  callback,
+                                                                 gpointer             user_data);
+
+TrackerExtractInfo * tracker_extract_client_get_metadata_finish (GFile               *uri,
+                                                                 GAsyncResult        *res,
+                                                                 GError             **error);
+
+G_CONST_RETURN gchar * tracker_extract_info_get_preupdate    (TrackerExtractInfo *info);
+G_CONST_RETURN gchar * tracker_extract_info_get_update       (TrackerExtractInfo *info);
+G_CONST_RETURN gchar * tracker_extract_info_get_where_clause (TrackerExtractInfo *info);
+
+G_END_DECLS
+
+#endif /* __TRACKER_EXTRACT_CLIENT_H__ */
diff --git a/src/libtracker-extract/tracker-extract.h b/src/libtracker-extract/tracker-extract.h
index e66f2b2..8463b5d 100644
--- a/src/libtracker-extract/tracker-extract.h
+++ b/src/libtracker-extract/tracker-extract.h
@@ -27,6 +27,7 @@
 #include "tracker-data.h"
 #include "tracker-encoding.h"
 #include "tracker-exif.h"
+#include "tracker-extract-client.h"
 #include "tracker-module-manager.h"
 #include "tracker-guarantee.h"
 #include "tracker-iptc.h"
diff --git a/src/miners/fs/tracker-miner-files.c b/src/miners/fs/tracker-miner-files.c
index 3dd67c5..7551862 100644
--- a/src/miners/fs/tracker-miner-files.c
+++ b/src/miners/fs/tracker-miner-files.c
@@ -43,25 +43,16 @@
 #include <libtracker-data/tracker-db-manager.h>
 
 #include <libtracker-extract/tracker-module-manager.h>
+#include <libtracker-extract/tracker-extract-client.h>
 
 #include "tracker-power.h"
 #include "tracker-miner-files.h"
 #include "tracker-config.h"
 #include "tracker-marshal.h"
 
-/* Size of buffers used when sending data over a pipe, using DBus FD passing */
-#define DBUS_PIPE_BUFFER_SIZE      65536
-
-#define DBUS_SERVICE_EXTRACT       "org.freedesktop.Tracker1.Extract"
-#define DBUS_PATH_EXTRACT          "/org/freedesktop/Tracker1/Extract"
-#define DBUS_INTERFACE_EXTRACT     "org.freedesktop.Tracker1.Extract"
-
 #define DISK_SPACE_CHECK_FREQUENCY 10
 #define SECONDS_PER_DAY 86400
 
-/* Default DBus timeout to be used in requests to extractor (milliseconds) */
-#define EXTRACTOR_DBUS_TIMEOUT 60000
-
 #define TRACKER_MINER_FILES_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TRACKER_TYPE_MINER_FILES, TrackerMinerFilesPrivate))
 
 static GQuark miner_files_error_quark = 0;
@@ -75,34 +66,6 @@ struct ProcessFileData {
 	GFile *file;
 };
 
-typedef void (*fast_async_cb) (const gchar *preupdate,
-                               const gchar *sparql,
-                               const gchar *where,
-                               GError      *error,
-                               gpointer     user_data);
-
-typedef void (*TrackerDBusSendAndSpliceCallback) (void     *buffer,
-                                                  gssize    buffer_size,
-                                                  GError   *error, /* Don't free */
-                                                  gpointer  user_data);
-
-typedef struct {
-	GInputStream *unix_input_stream;
-	GInputStream *buffered_input_stream;
-	GOutputStream *output_stream;
-	TrackerDBusSendAndSpliceCallback callback;
-	GCancellable *cancellable;
-	gpointer user_data;
-	gboolean splice_finished;
-	gboolean dbus_finished;
-	GError *error;
-} SendAndSpliceData;
-
-typedef struct {
-	fast_async_cb callback;
-	gpointer user_data;
-} FastAsyncData;
-
 struct TrackerMinerFilesPrivate {
 	TrackerConfig *config;
 	TrackerStorage *storage;
@@ -228,9 +191,6 @@ static gboolean    miner_files_ignore_next_update_file  (TrackerMinerFS       *f
                                                          GCancellable         *cancellable);
 static void        miner_files_finished                 (TrackerMinerFS       *fs);
 
-static void        extractor_get_embedded_metadata_cancel (GCancellable    *cancellable,
-                                                           ProcessFileData *data);
-
 static void        miner_finished_cb                    (TrackerMinerFS *fs,
                                                          gdouble         seconds_elapsed,
                                                          guint           total_directories_found,
@@ -1937,10 +1897,6 @@ miner_files_add_to_datasource (TrackerMinerFiles    *mf,
 static void
 process_file_data_free (ProcessFileData *data)
 {
-	g_signal_handlers_disconnect_by_func (data->cancellable,
-	                                      extractor_get_embedded_metadata_cancel,
-	                                      data);
-
 	g_object_unref (data->miner);
 	g_object_unref (data->sparql);
 	g_object_unref (data->cancellable);
@@ -1949,15 +1905,18 @@ process_file_data_free (ProcessFileData *data)
 }
 
 static void
-extractor_get_embedded_metadata_cb (const gchar *preupdate,
-                                    const gchar *sparql,
-                                    const gchar *where,
-                                    GError      *error,
-                                    gpointer     user_data)
+extractor_get_embedded_metadata_cb (GObject      *object,
+                                    GAsyncResult *res,
+                                    gpointer      user_data)
 {
 	ProcessFileData *data = user_data;
+	const gchar *preupdate, *sparql, *where;
+	TrackerExtractInfo *info;
+	GError *error = NULL;
 	const gchar *uuid;
 
+	info = tracker_extract_client_get_metadata_finish (G_FILE (object), res, &error);
+
 	if (error) {
 		/* Something bad happened, notify about the error */
 		tracker_miner_fs_file_notify (TRACKER_MINER_FS (data->miner), data->file, error);
@@ -1965,6 +1924,10 @@ extractor_get_embedded_metadata_cb (const gchar *preupdate,
 		return;
 	}
 
+	preupdate = tracker_extract_info_get_preupdate (info);
+	sparql = tracker_extract_info_get_update (info);
+	where = tracker_extract_info_get_where_clause (info);
+
 	if (sparql && *sparql) {
 		gboolean is_iri;
 		const gchar *urn;
@@ -2042,347 +2005,6 @@ extractor_get_embedded_metadata_cb (const gchar *preupdate,
 }
 
 static void
-extractor_get_embedded_metadata_cancel (GCancellable    *cancellable,
-                                        ProcessFileData *data)
-{
-	GError *error;
-
-	/* TODO: Cancel extractor call
-	 * Isn't this as simple as g_cancellable_cancel (cancellable) now after the
-	 * GDBus port? The original dbus-glib code didn't have this so I have not
-	 * yet implemented it as part of the GDBus port. */
-
-	error = g_error_new_literal (miner_files_error_quark, 0,
-	                             "Embedded metadata extraction was cancelled");
-	tracker_miner_fs_file_notify (TRACKER_MINER_FS (data->miner), data->file, error);
-
-	process_file_data_free (data);
-	g_error_free (error);
-}
-
-static gboolean
-extractor_skip_embedded_metadata_idle (gpointer user_data)
-{
-	extractor_get_embedded_metadata_cb (NULL, NULL, NULL, NULL, user_data);
-	return FALSE;
-}
-
-static SendAndSpliceData *
-send_and_splice_data_new (GInputStream                     *unix_input_stream,
-                          GInputStream                     *buffered_input_stream,
-                          GOutputStream                    *output_stream,
-                          GCancellable                     *cancellable,
-                          TrackerDBusSendAndSpliceCallback  callback,
-                          gpointer                          user_data)
-{
-	SendAndSpliceData *data;
-
-	data = g_slice_new0 (SendAndSpliceData);
-	data->unix_input_stream = unix_input_stream;
-	data->buffered_input_stream = buffered_input_stream;
-	data->output_stream = output_stream;
-	if (cancellable) {
-		data->cancellable = g_object_ref (cancellable);
-	}
-	data->callback = callback;
-	data->user_data = user_data;
-
-	return data;
-}
-
-static void
-send_and_splice_data_free (SendAndSpliceData *data)
-{
-	g_object_unref (data->unix_input_stream);
-	g_object_unref (data->buffered_input_stream);
-	g_object_unref (data->output_stream);
-	if (data->cancellable) {
-		g_object_unref (data->cancellable);
-	}
-	if (data->error) {
-		g_error_free (data->error);
-	}
-	g_slice_free (SendAndSpliceData, data);
-}
-
-static void
-dbus_send_and_splice_async_finish (SendAndSpliceData *data)
-{
-	if (!data->error) {
-		(* data->callback) (g_memory_output_stream_get_data (G_MEMORY_OUTPUT_STREAM (data->output_stream)),
-		                    g_memory_output_stream_get_data_size (G_MEMORY_OUTPUT_STREAM (data->output_stream)),
-		                    NULL,
-		                    data->user_data);
-	} else {
-		(* data->callback) (NULL, -1, data->error, data->user_data);
-	}
-
-	send_and_splice_data_free (data);
-}
-
-static void
-send_and_splice_splice_callback (GObject      *source,
-                                 GAsyncResult *result,
-                                 gpointer      user_data)
-{
-	SendAndSpliceData *data = user_data;
-	GError *error = NULL;
-
-	g_output_stream_splice_finish (G_OUTPUT_STREAM (source), result, &error);
-
-	if (error) {
-		if (!data->error) {
-			data->error = error;
-		} else {
-			g_error_free (error);
-		}
-	}
-
-	data->splice_finished = TRUE;
-
-	if (data->dbus_finished) {
-		dbus_send_and_splice_async_finish (data);
-	}
-}
-
-static void
-send_and_splice_dbus_callback (GObject      *source,
-                               GAsyncResult *result,
-                               gpointer      user_data)
-{
-	SendAndSpliceData *data = user_data;
-	GDBusMessage *reply;
-	GError *error = NULL;
-
-	reply = g_dbus_connection_send_message_with_reply_finish (G_DBUS_CONNECTION (source),
-	                                                          result, &error);
-
-	if (reply) {
-		if (g_dbus_message_get_message_type (reply) == G_DBUS_MESSAGE_TYPE_ERROR) {
-			g_dbus_message_to_gerror (reply, &error);
-		}
-
-		g_object_unref (reply);
-	}
-
-	if (error) {
-		if (!data->error) {
-			data->error = error;
-		} else {
-			g_error_free (error);
-		}
-	}
-
-	data->dbus_finished = TRUE;
-
-	if (data->splice_finished) {
-		dbus_send_and_splice_async_finish (data);
-	}
-}
-
-static gboolean
-dbus_send_and_splice_async (GDBusConnection                  *connection,
-                            GDBusMessage                     *message,
-                            int                               fd,
-                            GCancellable                     *cancellable,
-                            TrackerDBusSendAndSpliceCallback  callback,
-                            gpointer                          user_data)
-{
-	SendAndSpliceData *data;
-	GInputStream *unix_input_stream;
-	GInputStream *buffered_input_stream;
-	GOutputStream *output_stream;
-
-	g_return_val_if_fail (connection != NULL, FALSE);
-	g_return_val_if_fail (message != NULL, FALSE);
-	g_return_val_if_fail (fd > 0, FALSE);
-	g_return_val_if_fail (callback != NULL, FALSE);
-
-	unix_input_stream = g_unix_input_stream_new (fd, TRUE);
-	buffered_input_stream = g_buffered_input_stream_new_sized (unix_input_stream,
-	                                                           DBUS_PIPE_BUFFER_SIZE);
-	output_stream = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
-
-	data = send_and_splice_data_new (unix_input_stream,
-	                                 buffered_input_stream,
-	                                 output_stream,
-	                                 cancellable,
-	                                 callback,
-	                                 user_data);
-
-	g_dbus_connection_send_message_with_reply (connection,
-	                                           message,
-	                                           G_DBUS_SEND_MESSAGE_FLAGS_NONE,
-	                                           -1,
-	                                           NULL,
-	                                           cancellable,
-	                                           send_and_splice_dbus_callback,
-	                                           data);
-
-	g_output_stream_splice_async (data->output_stream,
-	                              data->buffered_input_stream,
-	                              G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE |
-	                              G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
-	                              0,
-	                              data->cancellable,
-	                              send_and_splice_splice_callback,
-	                              data);
-
-	return TRUE;
-}
-
-static FastAsyncData*
-fast_async_data_new (fast_async_cb  callback,
-                     gpointer       user_data)
-{
-	FastAsyncData *data;
-
-	data = g_slice_new0 (FastAsyncData);
-
-	data->callback = callback;
-	data->user_data = user_data;
-
-	return data;
-}
-
-static void
-fast_async_data_free (FastAsyncData *data)
-{
-	g_slice_free (FastAsyncData, data);
-}
-
-static void
-get_metadata_fast_cb (void     *buffer,
-                      gssize    buffer_size,
-                      GError   *error,
-                      gpointer  user_data)
-{
-	FastAsyncData *data;
-	ProcessFileData *process_data;
-	gboolean valid_input = FALSE;
-	gboolean free_error = FALSE;
-	const gchar *preupdate = NULL;
-	const gchar *sparql = NULL;
-	const gchar *where = NULL;
-
-	data = user_data;
-	process_data = data->user_data;
-
-	if (!error && buffer_size) {
-		gsize preupdate_length, sparql_length, where_length;
-
-		preupdate = buffer;
-		preupdate_length = strnlen (preupdate, buffer_size - 1);
-		if (preupdate[preupdate_length] == '\0') {
-			/* sparql is stored just after preupdate in the original buffer */
-			sparql = preupdate + preupdate_length + 1;
-			sparql_length = strnlen (sparql, preupdate + buffer_size - 1 - sparql);
-			if (sparql[sparql_length] == '\0') {
-				/* where is stored just after sparql in the original buffer */
-				where = sparql + sparql_length + 1;
-				where_length = strnlen (where, preupdate + buffer_size - 1 - where);
-				if (where[where_length] == '\0') {
-					valid_input = TRUE;
-				}
-			}
-		}
-
-		if (!valid_input) {
-			error = g_error_new_literal (miner_files_error_quark,
-			                             0,
-			                             "Invalid data received from GetMetadataFast");
-			free_error = TRUE;
-		}
-	}
-
-	if (G_UNLIKELY (error)) {
-		if (error->code != G_IO_ERROR_CANCELLED) {
-			(* data->callback) (NULL, NULL, NULL, error, process_data);
-		}
-		if (free_error) {
-			g_error_free (error);
-		}
-	} else {
-		(* data->callback) (preupdate, sparql, where, NULL, data->user_data);
-	}
-
-	fast_async_data_free (data);
-}
-
-static void
-get_metadata_fast_async (GDBusConnection *connection,
-                         const gchar     *uri,
-                         const gchar     *mime_type,
-                         GCancellable    *cancellable,
-                         fast_async_cb    callback,
-                         ProcessFileData *user_data)
-{
-	GDBusMessage *message;
-	GUnixFDList *fd_list;
-	FastAsyncData *data;
-	int pipefd[2];
-
-	g_return_if_fail (connection);
-	g_return_if_fail (uri);
-	g_return_if_fail (mime_type);
-	g_return_if_fail (callback);
-
-	if (pipe (pipefd) < 0) {
-		g_critical ("Coudln't open pipe");
-		return;
-	}
-
-	message = g_dbus_message_new_method_call (DBUS_SERVICE_EXTRACT,
-	                                          DBUS_PATH_EXTRACT,
-	                                          DBUS_INTERFACE_EXTRACT,
-	                                          "GetMetadataFast");
-
-	fd_list = g_unix_fd_list_new ();
-
-	g_dbus_message_set_body (message, g_variant_new ("(ssh)",
-	                                                 uri,
-	                                                 mime_type,
-	                                                 g_unix_fd_list_append (fd_list,
-	                                                                        pipefd[1],
-	                                                                        NULL)));
-	g_dbus_message_set_unix_fd_list (message, fd_list);
-
-	/* We need to close the fd as g_unix_fd_list_append duplicates the fd */
-
-	close (pipefd[1]);
-
-	g_object_unref (fd_list);
-
-	data = fast_async_data_new (callback,
-	                            user_data);
-
-	dbus_send_and_splice_async (connection,
-	                            message,
-	                            pipefd[0],
-	                            cancellable,
-	                            get_metadata_fast_cb,
-	                            data);
-
-	g_object_unref (message);
-}
-
-static void
-extractor_get_embedded_metadata (ProcessFileData *data,
-                                 const gchar     *uri,
-                                 const gchar     *mime_type)
-{
-	get_metadata_fast_async (data->miner->private->connection,
-	                         uri,
-	                         mime_type,
-	                         data->cancellable,
-	                         extractor_get_embedded_metadata_cb,
-	                         data);
-
-	g_signal_connect (data->cancellable, "cancelled",
-	                  G_CALLBACK (extractor_get_embedded_metadata_cancel), data);
-}
-
-static void
 process_file_cb (GObject      *object,
                  GAsyncResult *result,
                  gpointer      user_data)
@@ -2474,12 +2096,16 @@ process_file_cb (GObject      *object,
 
 	if (tracker_extract_module_manager_mimetype_is_handled (mime_type)) {
 		/* Next step, if handled by the extractor, get embedded metadata */
-		extractor_get_embedded_metadata (data, uri, mime_type);
+		tracker_extract_client_get_metadata (data->file,
+		                                     mime_type,
+		                                     data->cancellable,
+		                                     extractor_get_embedded_metadata_cb,
+		                                     data);
 	} else {
 		/* Otherwise, don't request embedded metadata extraction.
 		 * We setup an idle so that we keep the previous behavior. */
 		g_debug ("Avoiding embedded metadata request for uri '%s'", uri);
-		g_idle_add (extractor_skip_embedded_metadata_idle, data);
+		tracker_miner_fs_file_notify (TRACKER_MINER_FS (data->miner), data->file, NULL);
 	}
 
 	g_object_unref (file_info);



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