[tracker/extractor-controller-thread: 1/4] tracker-extract: Add controller thread
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [tracker/extractor-controller-thread: 1/4] tracker-extract: Add controller thread
- Date: Fri, 8 Apr 2011 12:42:36 +0000 (UTC)
commit e4fd078dfecc87a1e3d6cddb484e5a0d6f3afb7c
Author: Carlos Garnacho <carlosg gnome org>
Date: Wed Mar 30 15:52:21 2011 +0200
tracker-extract: Add controller thread
This thread takes care of DBus dispatching and extractor lifetime
control, the main thread still carries out metadata extraction in
a synchronous manner.
src/tracker-extract/Makefile.am | 2 +
src/tracker-extract/tracker-controller.c | 731 ++++++++++++++++++++++++++++++
src/tracker-extract/tracker-controller.h | 57 +++
src/tracker-extract/tracker-extract.c | 568 +++++------------------
src/tracker-extract/tracker-extract.h | 18 +-
src/tracker-extract/tracker-main.c | 66 +--
6 files changed, 950 insertions(+), 492 deletions(-)
---
diff --git a/src/tracker-extract/Makefile.am b/src/tracker-extract/Makefile.am
index 12bebd3..4e052a7 100644
--- a/src/tracker-extract/Makefile.am
+++ b/src/tracker-extract/Makefile.am
@@ -433,6 +433,8 @@ tracker_extract_SOURCES = \
tracker-albumart.h \
tracker-config.c \
tracker-config.h \
+ tracker-controller.c \
+ tracker-controller.h \
tracker-extract.c \
tracker-extract.h \
tracker-read.c \
diff --git a/src/tracker-extract/tracker-controller.c b/src/tracker-extract/tracker-controller.c
new file mode 100644
index 0000000..5487c08
--- /dev/null
+++ b/src/tracker-extract/tracker-controller.c
@@ -0,0 +1,731 @@
+/*
+ * 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.
+ */
+
+#include "tracker-controller.h"
+#include "tracker-extract.h"
+
+#include <gio/gunixoutputstream.h>
+#include <gio/gunixinputstream.h>
+#include <gio/gunixfdlist.h>
+
+#include <libtracker-common/tracker-common.h>
+#include <libtracker-extract/tracker-extract.h>
+#include <libtracker-miner/tracker-miner.h>
+#include <gio/gio.h>
+
+typedef struct TrackerControllerPrivate TrackerControllerPrivate;
+typedef struct GetMetadataData GetMetadataData;
+
+struct TrackerControllerPrivate {
+ GMainContext *context;
+ GMainLoop *main_loop;
+
+ TrackerStorage *storage;
+ TrackerExtract *extractor;
+
+ GDBusConnection *connection;
+ GDBusNodeInfo *introspection_data;
+ guint registration_id;
+
+ guint shutdown_timeout;
+ guint shutdown_timeout_id;
+
+ GCond *initialization_cond;
+ GMutex *initialization_mutex;
+ GError *initialization_error;
+
+ guint initialized : 1;
+};
+
+struct GetMetadataData {
+ TrackerController *controller;
+ GCancellable *cancellable;
+ GDBusMethodInvocation *invocation;
+ TrackerDBusRequest *request;
+ gchar *uri;
+ gchar *mimetype;
+ gint fd; /* Only for fast queries */
+};
+
+#define TRACKER_EXTRACT_SERVICE "org.freedesktop.Tracker1.Extract"
+#define TRACKER_EXTRACT_PATH "/org/freedesktop/Tracker1/Extract"
+#define TRACKER_EXTRACT_INTERFACE "org.freedesktop.Tracker1.Extract"
+
+#define MAX_EXTRACT_TIME 10
+
+static const gchar *introspection_xml =
+ "<node>"
+ " <interface name='org.freedesktop.Tracker1.Extract'>"
+ " <method name='GetPid'>"
+ " <arg type='i' name='value' direction='out' />"
+ " </method>"
+ " <method name='GetMetadata'>"
+ " <arg type='s' name='uri' direction='in' />"
+ " <arg type='s' name='mime' direction='in' />"
+ " <arg type='s' name='preupdate' direction='out' />"
+ " <arg type='s' name='embedded' direction='out' />"
+ " <arg type='s' name='where' direction='out' />"
+ " </method>"
+ " <method name='GetMetadataFast'>"
+ " <arg type='s' name='uri' direction='in' />"
+ " <arg type='s' name='mime' direction='in' />"
+ " <arg type='h' name='fd' direction='in' />"
+ " </method>"
+ " </interface>"
+ "</node>";
+
+enum {
+ PROP_0,
+ PROP_SHUTDOWN_TIMEOUT,
+ PROP_EXTRACTOR
+};
+
+static void tracker_controller_initable_iface_init (GInitableIface *iface);
+static gboolean tracker_controller_dbus_start (TrackerController *controller,
+ GError **error);
+static void tracker_controller_dbus_stop (TrackerController *controller);
+
+
+G_DEFINE_TYPE_WITH_CODE (TrackerController, tracker_controller, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
+ tracker_controller_initable_iface_init));
+
+static gboolean
+tracker_controller_initable_init (GInitable *initable,
+ GCancellable *cancellable,
+ GError **error)
+{
+ return tracker_controller_start (TRACKER_CONTROLLER (initable), error);
+}
+
+static void
+tracker_controller_initable_iface_init (GInitableIface *iface)
+{
+ iface->init = tracker_controller_initable_init;
+}
+
+
+static void
+tracker_controller_finalize (GObject *object)
+{
+ TrackerControllerPrivate *priv;
+ TrackerController *controller;
+
+ controller = TRACKER_CONTROLLER (object);
+ priv = controller->priv;
+
+ if (priv->shutdown_timeout_id) {
+ g_source_remove (priv->shutdown_timeout_id);
+ priv->shutdown_timeout_id = 0;
+ }
+
+ tracker_controller_dbus_stop (controller);
+
+ g_object_unref (priv->storage);
+
+ g_main_loop_unref (priv->main_loop);
+ g_main_context_unref (priv->context);
+
+ g_cond_free (priv->initialization_cond);
+ g_mutex_free (priv->initialization_mutex);
+
+ G_OBJECT_CLASS (tracker_controller_parent_class)->finalize (object);
+}
+
+static void
+tracker_controller_get_property (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ TrackerControllerPrivate *priv = TRACKER_CONTROLLER (object)->priv;
+
+ switch (param_id) {
+ case PROP_SHUTDOWN_TIMEOUT:
+ g_value_set_uint (value, priv->shutdown_timeout);
+ break;
+ case PROP_EXTRACTOR:
+ g_value_set_object (value, priv->extractor);
+ break;
+ }
+}
+
+static void
+tracker_controller_set_property (GObject *object,
+ guint param_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ TrackerControllerPrivate *priv = TRACKER_CONTROLLER (object)->priv;
+
+ switch (param_id) {
+ case PROP_SHUTDOWN_TIMEOUT:
+ priv->shutdown_timeout = g_value_get_uint (value);
+ break;
+ case PROP_EXTRACTOR:
+ priv->extractor = g_value_get_object (value);
+ break;
+ }
+}
+
+static void
+tracker_controller_class_init (TrackerControllerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = tracker_controller_finalize;
+ object_class->get_property = tracker_controller_get_property;
+ object_class->set_property = tracker_controller_set_property;
+
+ g_object_class_install_property (object_class,
+ PROP_SHUTDOWN_TIMEOUT,
+ g_param_spec_uint ("shutdown-timeout",
+ "Shutdown timeout",
+ "Shutdown timeout, 0 to disable",
+ 0, 1000, 0,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (object_class,
+ PROP_EXTRACTOR,
+ g_param_spec_object ("extractor",
+ "Extractor",
+ "Extractor",
+ TRACKER_TYPE_EXTRACT,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_type_class_add_private (object_class, sizeof (TrackerControllerPrivate));
+}
+
+static GetMetadataData *
+metadata_data_new (TrackerController *controller,
+ const gchar *uri,
+ const gchar *mime,
+ GDBusMethodInvocation *invocation,
+ TrackerDBusRequest *request)
+{
+ GetMetadataData *data;
+
+ data = g_slice_new (GetMetadataData);
+ data->cancellable = g_cancellable_new ();
+ data->controller = controller;
+ data->uri = g_strdup (uri);
+ data->mimetype = g_strdup (mime);
+ data->invocation = invocation;
+ data->request = request;
+
+ return data;
+}
+
+static void
+metadata_data_free (GetMetadataData *data)
+{
+ /* We rely on data->invocation being freed through
+ * the g_dbus_method_invocation_return_* methods
+ */
+ g_free (data->uri);
+ g_free (data->mimetype);
+ g_object_unref (data->cancellable);
+ g_slice_free (GetMetadataData, data);
+}
+
+static gboolean
+reset_shutdown_timeout_cb (gpointer user_data)
+{
+ TrackerControllerPrivate *priv;
+
+ g_message ("Extractor lifetime has expired");
+
+ priv = TRACKER_CONTROLLER (user_data)->priv;
+ g_main_loop_quit (priv->main_loop);
+
+ return TRUE;
+}
+
+static void
+reset_shutdown_timeout (TrackerController *controller)
+{
+ TrackerControllerPrivate *priv;
+ GSource *source;
+
+ priv = controller->priv;
+
+ if (priv->shutdown_timeout == 0) {
+ return;
+ }
+
+ g_message ("(Re)setting shutdown timeout");
+
+ if (priv->shutdown_timeout_id != 0) {
+ g_source_remove (priv->shutdown_timeout_id);
+ }
+
+ source = g_timeout_source_new_seconds (priv->shutdown_timeout);
+ g_source_set_callback (source,
+ reset_shutdown_timeout_cb,
+ controller, NULL);
+
+ priv->shutdown_timeout_id = g_source_attach (source, priv->context);
+}
+
+static void
+tracker_controller_init (TrackerController *controller)
+{
+ TrackerControllerPrivate *priv;
+
+ priv = controller->priv = G_TYPE_INSTANCE_GET_PRIVATE (controller,
+ TRACKER_TYPE_CONTROLLER,
+ TrackerControllerPrivate);
+
+ priv->context = g_main_context_new ();
+ priv->main_loop = g_main_loop_new (priv->context, FALSE);
+
+ priv->storage = tracker_storage_new ();
+
+ priv->initialization_cond = g_cond_new ();
+ priv->initialization_mutex = g_mutex_new ();
+}
+
+static void
+handle_method_call_get_pid (TrackerController *controller,
+ GDBusMethodInvocation *invocation,
+ GVariant *parameters)
+{
+ TrackerDBusRequest *request;
+ pid_t value;
+
+ request = tracker_g_dbus_request_begin (invocation,
+ "%s()",
+ __FUNCTION__);
+
+ reset_shutdown_timeout (controller);
+ value = getpid ();
+ tracker_dbus_request_debug (request,
+ "PID is %d",
+ value);
+
+ tracker_dbus_request_end (request, NULL);
+
+ g_dbus_method_invocation_return_value (invocation,
+ g_variant_new ("(i)", (gint) value));
+}
+
+static void
+get_metadata_cb (GObject *object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GetMetadataData *data;
+ TrackerExtractInfo *info;
+
+ data = user_data;
+ info = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res));
+
+ if (info) {
+ if (tracker_sparql_builder_get_length (info->statements) > 0) {
+ const gchar *preupdate_str = NULL;
+
+ if (tracker_sparql_builder_get_length (info->preupdate) > 0) {
+ preupdate_str = tracker_sparql_builder_get_result (info->preupdate);
+ }
+
+ g_dbus_method_invocation_return_value (data->invocation,
+ g_variant_new ("(sss)",
+ preupdate_str ? preupdate_str : "",
+ tracker_sparql_builder_get_result (info->statements),
+ info->where ? info->where : ""));
+ } else {
+ g_dbus_method_invocation_return_value (data->invocation,
+ g_variant_new ("(sss)", "", "", ""));
+ }
+
+ tracker_dbus_request_end (data->request, NULL);
+ } else {
+ GError *error = NULL;
+
+ g_message ("Controller thread (%p) got error back", g_thread_self ());
+ g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), &error);
+ tracker_dbus_request_end (data->request, error);
+ g_dbus_method_invocation_return_gerror (data->invocation, error);
+ g_error_free (error);
+ }
+
+ metadata_data_free (data);
+}
+
+static void
+handle_method_call_get_metadata (TrackerController *controller,
+ GDBusMethodInvocation *invocation,
+ GVariant *parameters)
+{
+ TrackerControllerPrivate *priv;
+ GetMetadataData *data;
+ TrackerDBusRequest *request;
+ const gchar *uri, *mime;
+
+ priv = controller->priv;
+ g_variant_get (parameters, "(&s&s)", &uri, &mime);
+
+ reset_shutdown_timeout (controller);
+ request = tracker_dbus_request_begin (NULL, "%s (%s, %s)", __FUNCTION__, uri, mime);
+
+ data = metadata_data_new (controller, uri, mime, invocation, request);
+ tracker_extract_file (priv->extractor, uri, mime, data->cancellable,
+ get_metadata_cb, data);
+}
+
+static void
+get_metadata_fast_cb (GObject *object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GetMetadataData *data;
+ TrackerExtractInfo *info;
+
+ data = user_data;
+ info = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res));
+
+ if (info) {
+ GOutputStream *unix_output_stream;
+ GOutputStream *buffered_output_stream;
+ GDataOutputStream *data_output_stream;
+ GError *error = NULL;
+
+ g_message ("Controller thread (%p) got metadata back", g_thread_self ());
+
+ unix_output_stream = g_unix_output_stream_new (data->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 (info->statements) > 0) {
+ const gchar *preupdate_str = NULL;
+
+ if (tracker_sparql_builder_get_length (info->preupdate) > 0) {
+ preupdate_str = tracker_sparql_builder_get_result (info->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 (info->statements),
+ NULL,
+ &error);
+ }
+
+ if (!error) {
+ g_data_output_stream_put_byte (data_output_stream,
+ 0,
+ NULL,
+ &error);
+ }
+
+ if (!error && info->where) {
+ g_data_output_stream_put_string (data_output_stream,
+ info->where,
+ NULL,
+ &error);
+ }
+
+ if (!error) {
+ g_data_output_stream_put_byte (data_output_stream,
+ 0,
+ NULL,
+ &error);
+ }
+ }
+
+ g_object_unref (data_output_stream);
+ g_object_unref (buffered_output_stream);
+ g_object_unref (unix_output_stream);
+
+ if (error) {
+ tracker_dbus_request_end (data->request, error);
+ g_dbus_method_invocation_return_gerror (data->invocation, error);
+ g_error_free (error);
+ } else {
+ tracker_dbus_request_end (data->request, NULL);
+ g_dbus_method_invocation_return_value (data->invocation, NULL);
+ }
+ } else {
+ GError *error = NULL;
+
+ g_message ("Controller thread (%p) got error back", g_thread_self ());
+ g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), &error);
+ tracker_dbus_request_end (data->request, error);
+ g_dbus_method_invocation_return_gerror (data->invocation, error);
+ g_error_free (error);
+
+ close (data->fd);
+ }
+
+ metadata_data_free (data);
+}
+
+static void
+handle_method_call_get_metadata_fast (TrackerController *controller,
+ GDBusMethodInvocation *invocation,
+ GVariant *parameters)
+{
+ GDBusConnection *connection;
+ GDBusMessage *method_message;
+ TrackerDBusRequest *request;
+
+ connection = g_dbus_method_invocation_get_connection (invocation);
+ method_message = g_dbus_method_invocation_get_message (invocation);
+
+ reset_shutdown_timeout (controller);
+ request = tracker_dbus_request_begin (NULL, "%s", __FUNCTION__);
+
+ if (g_dbus_connection_get_capabilities (connection) & G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING) {
+ TrackerControllerPrivate *priv;
+ GetMetadataData *data;
+ const gchar *uri, *mime;
+ gint index_fd, fd;
+ GUnixFDList *fd_list;
+ GError *error = NULL;
+
+ priv = controller->priv;
+ g_variant_get (parameters, "(&s&sh)", &uri, &mime, &index_fd);
+
+ fd_list = g_dbus_message_get_unix_fd_list (method_message);
+
+ if ((fd = g_unix_fd_list_get (fd_list, index_fd, &error)) != -1) {
+ data = metadata_data_new (controller, uri, mime, invocation, request);
+ data->fd = fd;
+
+ tracker_extract_file (priv->extractor, uri, mime, data->cancellable,
+ get_metadata_fast_cb, data);
+ } else {
+ tracker_dbus_request_end (request, error);
+ g_dbus_method_invocation_return_dbus_error (invocation,
+ TRACKER_EXTRACT_SERVICE ".GetMetadataFastError",
+ "No FD list");
+ g_error_free (error);
+ }
+ } else {
+ tracker_dbus_request_end (request, NULL);
+ g_dbus_method_invocation_return_dbus_error (invocation,
+ TRACKER_EXTRACT_SERVICE ".GetMetadataFastError",
+ "No FD passing capabilities");
+ }
+}
+
+static void
+handle_method_call (GDBusConnection *connection,
+ const gchar *sender,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *method_name,
+ GVariant *parameters,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data)
+{
+ TrackerController *controller = user_data;
+
+ if (g_strcmp0 (method_name, "GetPid") == 0) {
+ handle_method_call_get_pid (controller, invocation, parameters);
+ } else if (g_strcmp0 (method_name, "GetMetadataFast") == 0) {
+ handle_method_call_get_metadata_fast (controller, invocation, parameters);
+ } else if (g_strcmp0 (method_name, "GetMetadata") == 0) {
+ handle_method_call_get_metadata (controller, invocation, parameters);
+ } else {
+ g_warning ("Unknown method '%s' called", method_name);
+ }
+}
+
+static gboolean
+tracker_controller_dbus_start (TrackerController *controller,
+ GError **error)
+{
+ TrackerControllerPrivate *priv;
+ GError *err = NULL;
+ GDBusInterfaceVTable interface_vtable = {
+ handle_method_call,
+ NULL, NULL
+ };
+
+ priv = controller->priv;
+ priv->connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &err);
+
+ if (!priv->connection) {
+ g_critical ("Could not connect to the D-Bus session bus, %s",
+ err ? err->message : "no error given.");
+ g_propagate_error (error, err);
+ return FALSE;
+ }
+
+ priv->introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, &err);
+ if (!priv->introspection_data) {
+ g_critical ("Could not create node info from introspection XML, %s",
+ err ? err->message : "no error given.");
+ g_propagate_error (error, err);
+ return FALSE;
+ }
+
+ g_message ("Registering D-Bus object...");
+ g_message (" Path:'" TRACKER_EXTRACT_PATH "'");
+ g_message (" Object Type:'%s'", G_OBJECT_TYPE_NAME (controller));
+
+ g_bus_own_name_on_connection (priv->connection,
+ TRACKER_EXTRACT_SERVICE,
+ G_BUS_NAME_OWNER_FLAGS_NONE,
+ NULL, NULL, NULL, NULL);
+
+ priv->registration_id =
+ g_dbus_connection_register_object (priv->connection,
+ TRACKER_EXTRACT_PATH,
+ priv->introspection_data->interfaces[0],
+ &interface_vtable,
+ controller,
+ NULL,
+ &err);
+
+ if (err) {
+ g_critical ("Could not register the D-Bus object "TRACKER_EXTRACT_PATH", %s",
+ err ? err->message : "no error given.");
+ g_propagate_error (error, err);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+tracker_controller_dbus_stop (TrackerController *controller)
+{
+ TrackerControllerPrivate *priv;
+
+ priv = controller->priv;
+
+ if (priv->registration_id != 0) {
+ g_dbus_connection_unregister_object (priv->connection,
+ priv->registration_id);
+ }
+
+ if (priv->introspection_data) {
+ g_dbus_node_info_unref (priv->introspection_data);
+ }
+
+ if (priv->connection) {
+ g_object_unref (priv->connection);
+ }
+}
+
+TrackerController *
+tracker_controller_new (TrackerExtract *extractor,
+ guint shutdown_timeout,
+ GError **error)
+{
+ return g_initable_new (TRACKER_TYPE_CONTROLLER,
+ NULL, error,
+ "extractor", extractor,
+ "shutdown-timeout", shutdown_timeout,
+ NULL);
+}
+
+static gpointer
+tracker_controller_thread_func (gpointer user_data)
+{
+ TrackerController *controller;
+ TrackerControllerPrivate *priv;
+ gboolean success;
+
+ g_message ("Controller thread '%p' created, dispatching...", g_thread_self ());
+
+ controller = user_data;
+ priv = controller->priv;
+ g_main_context_push_thread_default (priv->context);
+
+ reset_shutdown_timeout (controller);
+
+ success = tracker_controller_dbus_start (controller, &priv->initialization_error);
+ priv->initialized = TRUE;
+
+ /* Notify about the initialization */
+ g_mutex_lock (priv->initialization_mutex);
+ g_cond_signal (priv->initialization_cond);
+ g_mutex_unlock (priv->initialization_mutex);
+
+ if (!success) {
+ /* Return here, the main thread will
+ * be notified about the error and exit
+ */
+ return NULL;
+ }
+
+ g_main_loop_run (priv->main_loop);
+
+ g_message ("Shutting down...");
+
+ g_object_unref (controller);
+
+ /* This is where tracker-extract exits, be it
+ * either through umount events on monitored
+ * files' volumes or the timeout being reached
+ */
+ exit (0);
+ return NULL;
+}
+
+gboolean
+tracker_controller_start (TrackerController *controller,
+ GError **error)
+{
+ TrackerControllerPrivate *priv;
+
+ if (!g_thread_create (tracker_controller_thread_func,
+ controller, FALSE, error)) {
+ return FALSE;
+ }
+
+ priv = controller->priv;
+
+ g_message ("Waiting for controller thread to initialize...");
+
+ /* Wait for the controller thread to notify initialization */
+ g_mutex_lock (priv->initialization_mutex);
+
+ while (!priv->initialized) {
+ g_cond_wait (priv->initialization_cond, priv->initialization_mutex);
+ }
+
+ g_mutex_unlock (priv->initialization_mutex);
+
+ /* If there was any error resulting from initialization, propagate it */
+ if (priv->initialization_error != NULL) {
+ g_propagate_error (error, priv->initialization_error);
+ return FALSE;
+ }
+
+ g_message ("Controller thread initialized");
+
+ return TRUE;
+}
diff --git a/src/tracker-extract/tracker-controller.h b/src/tracker-extract/tracker-controller.h
new file mode 100644
index 0000000..67ef5d5
--- /dev/null
+++ b/src/tracker-extract/tracker-controller.h
@@ -0,0 +1,57 @@
+/*
+ * 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_CONTROLLER_H__
+#define __TRACKER_CONTROLLER_H__
+
+#include "tracker-extract.h"
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define TRACKER_TYPE_CONTROLLER (tracker_controller_get_type ())
+#define TRACKER_CONTROLLER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_CONTROLLER, TrackerController))
+#define TRACKER_CONTROLLER_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), TRACKER_TYPE_CONTROLLER, TrackerControllerClass))
+#define TRACKER_IS_CONTROLLER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TRACKER_TYPE_CONTROLLER))
+#define TRACKER_IS_CONTROLLER_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), TRACKER_TYPE_CONTROLLER))
+#define TRACKER_CONTROLLER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TRACKER_TYPE_CONTROLLER, TrackerControllerClass))
+
+typedef struct TrackerController TrackerController;
+typedef struct TrackerControllerClass TrackerControllerClass;
+
+struct TrackerController {
+ GObject parent_instance;
+ gpointer priv;
+};
+
+struct TrackerControllerClass {
+ GObjectClass parent_class;
+};
+
+GType tracker_controller_get_type (void) G_GNUC_CONST;
+
+TrackerController * tracker_controller_new (TrackerExtract *extractor,
+ guint shutdown_timeout,
+ GError **error);
+gboolean tracker_controller_start (TrackerController *controller,
+ GError **error);
+
+G_END_DECLS
+
+#endif /* __TRACKER_CONTROLLER_H__ */
diff --git a/src/tracker-extract/tracker-extract.c b/src/tracker-extract/tracker-extract.c
index 67b705e..66aa320 100644
--- a/src/tracker-extract/tracker-extract.c
+++ b/src/tracker-extract/tracker-extract.c
@@ -82,13 +82,18 @@ typedef struct {
gboolean disable_shutdown;
gboolean force_internal_extractors;
gboolean disable_summary_on_finalize;
- GDBusConnection *d_connection;
- GDBusNodeInfo *introspection_data;
- guint registration_id;
gint unhandled_count;
} TrackerExtractPrivate;
+typedef struct {
+ TrackerExtract *extract;
+ GCancellable *cancellable;
+ GAsyncResult *res;
+ gchar *file;
+ gchar *mimetype;
+} TrackerExtractTask;
+
static void tracker_extract_finalize (GObject *object);
static void report_statistics (GObject *object);
@@ -205,8 +210,6 @@ tracker_extract_new (gboolean disable_shutdown,
static gboolean
get_file_metadata (TrackerExtract *extract,
- TrackerDBusRequest *request,
- GDBusMethodInvocation *invocation,
const gchar *uri,
const gchar *mime,
TrackerSparqlBuilder **preupdate_out,
@@ -288,9 +291,7 @@ get_file_metadata (TrackerExtract *extract,
&error);
if (error || !info) {
- tracker_dbus_request_comment (request,
- " Could not create GFileInfo for file size check, %s",
- error ? error->message : "no error given");
+ /* FIXME: Propagate error */
g_error_free (error);
if (info) {
@@ -307,11 +308,6 @@ get_file_metadata (TrackerExtract *extract,
mime_used = g_strdup (g_file_info_get_content_type (info));
- tracker_dbus_request_comment (request,
- " Guessing mime type as '%s' for uri:'%s'",
- mime_used,
- uri);
-
g_object_unref (info);
g_object_unref (file);
}
@@ -333,10 +329,6 @@ get_file_metadata (TrackerExtract *extract,
items = tracker_sparql_builder_get_length (statements);
- tracker_dbus_request_comment (request,
- " Found %d metadata items",
- items);
-
data = g_hash_table_lookup (priv->statistics_data, module);
if (!data) {
@@ -360,14 +352,6 @@ get_file_metadata (TrackerExtract *extract,
} else {
priv->unhandled_count++;
}
-
- tracker_dbus_request_comment (request,
- " Could not find any extractors to handle metadata type "
- "(mime: %s)",
- mime_used);
- } else {
- tracker_dbus_request_comment (request,
- " No mime available, not extracting data");
}
if (tracker_sparql_builder_get_length (statements) > 0) {
@@ -378,474 +362,156 @@ get_file_metadata (TrackerExtract *extract,
*statements_out = statements;
*where_out = g_string_free (where, FALSE);
- return TRUE;
+ return FALSE;
}
-void
-tracker_extract_get_metadata_by_cmdline (TrackerExtract *object,
- const gchar *uri,
- const gchar *mime)
+static void
+tracker_extract_info_free (TrackerExtractInfo *info)
{
- TrackerDBusRequest *request;
- TrackerSparqlBuilder *statements, *preupdate;
- gchar *where;
- TrackerExtractPrivate *priv;
-
- priv = TRACKER_EXTRACT_GET_PRIVATE (object);
- priv->disable_summary_on_finalize = TRUE;
-
- g_return_if_fail (uri != NULL);
-
- request = tracker_dbus_request_begin (NULL,
- "%s(uri:'%s', mime:%s)",
- __FUNCTION__,
- uri,
- mime);
-
- /* NOTE: Don't reset the timeout to shutdown here */
-
- if (get_file_metadata (object, request,
- NULL, uri, mime,
- &preupdate, &statements, &where)) {
- const gchar *preupdate_str, *statements_str;
-
- preupdate_str = statements_str = NULL;
-
- if (tracker_sparql_builder_get_length (statements) > 0) {
- statements_str = tracker_sparql_builder_get_result (statements);
- }
-
- if (tracker_sparql_builder_get_length (preupdate) > 0) {
- preupdate_str = tracker_sparql_builder_get_result (preupdate);
- }
-
- tracker_dbus_request_info (request, "%s",
- preupdate_str ? preupdate_str : "");
- tracker_dbus_request_info (request, "%s",
- statements_str ? statements_str : "");
- tracker_dbus_request_info (request, "%s",
- where ? where : "");
+ if (info->statements) {
+ g_object_unref (info->statements);
+ }
- g_object_unref (statements);
- g_object_unref (preupdate);
- g_free (where);
+ if (info->preupdate) {
+ g_object_unref (info->preupdate);
}
- tracker_dbus_request_end (request, NULL);
+ g_free (info->where);
+ g_slice_free (TrackerExtractInfo, info);
}
-static void
-handle_method_call_get_pid (TrackerExtract *object,
- GDBusMethodInvocation *invocation,
- GVariant *parameters)
+static TrackerExtractTask *
+extract_task_new (TrackerExtract *extract,
+ const gchar *file,
+ const gchar *mimetype,
+ GCancellable *cancellable,
+ GAsyncResult *res)
{
- TrackerDBusRequest *request;
- pid_t value;
-
- request = tracker_g_dbus_request_begin (invocation,
- "%s()",
- __FUNCTION__);
+ TrackerExtractTask *task;
- value = getpid ();
- tracker_dbus_request_debug (request,
- "PID is %d",
- value);
+ task = g_slice_new0 (TrackerExtractTask);
+ task->cancellable = cancellable;
+ task->res = g_object_ref (res);
+ task->file = g_strdup (file);
+ task->mimetype = g_strdup (mimetype);
+ task->extract = extract;
- tracker_dbus_request_end (request, NULL);
-
- g_dbus_method_invocation_return_value (invocation,
- g_variant_new ("(i)", (gint) value));
+ return task;
}
static void
-handle_method_call_get_metadata (TrackerExtract *object,
- GDBusMethodInvocation *invocation,
- GVariant *parameters)
+extract_task_free (TrackerExtractTask *task)
{
- TrackerDBusRequest *request;
- TrackerExtractPrivate *priv;
- TrackerSparqlBuilder *sparql, *preupdate;
- gchar *where;
- gboolean extracted = FALSE;
- const gchar *uri = NULL, *mime = NULL;
-
- g_variant_get (parameters, "(&s&s)", &uri, &mime);
-
- tracker_gdbus_async_return_if_fail (uri != NULL, invocation);
-
- request = tracker_g_dbus_request_begin (invocation,
- "%s(uri:'%s', mime:%s)",
- __FUNCTION__,
- uri,
- mime);
-
- tracker_dbus_request_debug (request,
- " 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,
- invocation,
- uri,
- mime,
- &preupdate,
- &sparql,
- &where);
-
- if (extracted) {
- tracker_dbus_request_end (request, NULL);
-
- 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_dbus_method_invocation_return_value (invocation,
- g_variant_new ("(sss)",
- preupdate_str ? preupdate_str : "",
- tracker_sparql_builder_get_result (sparql),
- where ? where : ""));
- } else {
- g_dbus_method_invocation_return_value (invocation,
- g_variant_new ("(sss)", "", "", ""));
- }
-
- g_object_unref (sparql);
- g_object_unref (preupdate);
- g_free (where);
- } else {
- GError *actual_error;
-
- actual_error = g_error_new (TRACKER_DBUS_ERROR, 0,
- "Could not get any metadata for uri:'%s' and mime:'%s'",
- uri,
- mime);
- tracker_dbus_request_end (request, actual_error);
- g_dbus_method_invocation_return_gerror (invocation, actual_error);
- g_error_free (actual_error);
- }
-
- if (!priv->disable_shutdown) {
- /* Unset alarm so the extractor doesn't die when it's idle */
- alarm (0);
- }
+ g_object_unref (task->res);
+ g_free (task->file);
+ g_free (task->mimetype);
+ g_slice_free (TrackerExtractTask, task);
}
-static void
-handle_method_call_get_metadata_fast (TrackerExtract *object,
- GDBusMethodInvocation *invocation,
- GVariant *parameters)
+static gboolean
+get_metadata_cb (gpointer user_data)
{
- TrackerDBusRequest *request;
- TrackerExtractPrivate *priv;
- GDBusMessage *reply;
- const gchar *uri, *mime;
- int fd, index_fd;
- GOutputStream *unix_output_stream;
- GOutputStream *buffered_output_stream;
- GDataOutputStream *data_output_stream;
- GError *error = NULL;
- TrackerSparqlBuilder *sparql, *preupdate;
- gchar *where;
- gboolean extracted = FALSE;
- GDBusMessage *method_message;
- GDBusConnection *connection;
- GUnixFDList *fd_list;
-
- connection = g_dbus_method_invocation_get_connection (invocation);
- method_message = g_dbus_method_invocation_get_message (invocation);
-
- g_variant_get (parameters, "(&s&sh)", &uri, &mime, &index_fd);
-
- fd_list = g_dbus_message_get_unix_fd_list (method_message);
-
- request = tracker_g_dbus_request_begin (invocation,
- "%s(uri:'%s', mime:%s)",
- __FUNCTION__,
- uri,
- mime);
-
- if ((fd = g_unix_fd_list_get (fd_list, index_fd, &error)) == -1) {
- tracker_dbus_request_end (request, error);
- reply = g_dbus_message_new_method_error_literal (method_message,
- TRACKER_EXTRACT_SERVICE ".GetMetadataFastError",
- error->message);
- g_error_free (error);
- goto bail_out;
+ TrackerExtractTask *task = user_data;
+ TrackerExtractInfo *info;
+
+ g_message ("Main thread (%p) got file to get metadata from: %s", g_thread_self (), task->file);
+
+ if (task->cancellable &&
+ g_cancellable_is_cancelled (task->cancellable)) {
+ g_simple_async_result_set_error ((GSimpleAsyncResult *) task->res,
+ TRACKER_DBUS_ERROR, 0,
+ "Extraction of '%s' was cancelled",
+ task->file);
+ extract_task_free (task);
+ return FALSE;
}
- tracker_dbus_request_debug (request,
- " Resetting shutdown timeout");
-
- priv = TRACKER_EXTRACT_GET_PRIVATE (object);
+ info = g_slice_new (TrackerExtractInfo);
- tracker_main_quit_timeout_reset ();
- if (!priv->disable_shutdown) {
- alarm (MAX_EXTRACT_TIME);
- }
-
- extracted = get_file_metadata (object, request, NULL, uri, mime, &preupdate, &sparql, &where);
-
- 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);
- }
-
- if (!error && where) {
- g_data_output_stream_put_string (data_output_stream,
- where,
- 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_free (where);
- g_object_unref (data_output_stream);
- g_object_unref (buffered_output_stream);
- g_object_unref (unix_output_stream);
-
- if (error) {
- tracker_dbus_request_end (request, error);
- reply = g_dbus_message_new_method_error_literal (method_message,
- TRACKER_EXTRACT_SERVICE ".GetMetadataFastError",
- error->message);
- g_error_free (error);
- } else {
- tracker_dbus_request_end (request, NULL);
- reply = g_dbus_message_new_method_reply (method_message);
- }
+ if (get_file_metadata (task->extract,
+ task->file, task->mimetype,
+ &info->preupdate,
+ &info->statements,
+ &info->where)) {
+ g_simple_async_result_set_op_res_gpointer ((GSimpleAsyncResult *) task->res, info,
+ (GDestroyNotify) tracker_extract_info_free);
} else {
- error = g_error_new (TRACKER_DBUS_ERROR, 0,
- "Could not get any metadata for uri:'%s' and mime:'%s'", uri, mime);
- tracker_dbus_request_end (request, error);
- reply = g_dbus_message_new_method_error_literal (method_message,
- TRACKER_EXTRACT_SERVICE ".GetMetadataFastError",
- error->message);
- g_error_free (error);
- close (fd);
+ g_simple_async_result_set_error ((GSimpleAsyncResult *) task->res,
+ TRACKER_DBUS_ERROR, 0,
+ "Could not get any metadata for uri:'%s' and mime:'%s'",
+ task->file, task->mimetype);
+ tracker_extract_info_free (info);
}
-bail_out:
-
- g_dbus_connection_send_message (connection, reply,
- G_DBUS_SEND_MESSAGE_FLAGS_NONE,
- NULL, NULL);
+ g_simple_async_result_complete_in_idle ((GSimpleAsyncResult *) task->res);
+ extract_task_free (task);
- g_object_unref (fd_list);
- g_object_unref (reply);
-
- /* We are replying ourselves to the
- * message, so just unref the invocation
- */
- g_object_unref (invocation);
-
- if (!priv->disable_shutdown) {
- /* Unset alarm so the extractor doesn't die when it's idle */
- alarm (0);
- }
+ return FALSE;
}
-static void
-handle_method_call (GDBusConnection *connection,
- const gchar *sender,
- const gchar *object_path,
- const gchar *interface_name,
- const gchar *method_name,
- GVariant *parameters,
- GDBusMethodInvocation *invocation,
- gpointer user_data)
+/* This function can be called in any thread */
+void
+tracker_extract_file (TrackerExtract *extract,
+ const gchar *file,
+ const gchar *mimetype,
+ GCancellable *cancellable,
+ GAsyncReadyCallback cb,
+ gpointer user_data)
{
- TrackerExtract *extract = user_data;
-
- if (g_strcmp0 (method_name, "GetPid") == 0) {
- handle_method_call_get_pid (extract, invocation, parameters);
- } else
- if (g_strcmp0 (method_name, "GetMetadataFast") == 0) {
- handle_method_call_get_metadata_fast (extract, invocation, parameters);
- } else
- if (g_strcmp0 (method_name, "GetMetadata") == 0) {
- handle_method_call_get_metadata (extract, invocation, parameters);
- } else {
- g_assert_not_reached ();
- }
-}
+ GSimpleAsyncResult *res;
+ TrackerExtractTask *task;
-static GVariant *
-handle_get_property (GDBusConnection *connection,
- const gchar *sender,
- const gchar *object_path,
- const gchar *interface_name,
- const gchar *property_name,
- GError **error,
- gpointer user_data)
-{
- g_assert_not_reached ();
- return NULL;
-}
+ g_return_if_fail (TRACKER_IS_EXTRACT (extract));
+ g_return_if_fail (file != NULL);
+ g_return_if_fail (cb != NULL);
-static gboolean
-handle_set_property (GDBusConnection *connection,
- const gchar *sender,
- const gchar *object_path,
- const gchar *interface_name,
- const gchar *property_name,
- GVariant *value,
- GError **error,
- gpointer user_data)
-{
- g_assert_not_reached ();
- return TRUE;
+ g_message ("Extract file on thread %p\n", g_thread_self ());
+ res = g_simple_async_result_new (G_OBJECT (extract), cb, user_data, NULL);
+
+ task = extract_task_new (extract, file, mimetype, cancellable,
+ G_ASYNC_RESULT (res));
+ g_idle_add (get_metadata_cb, task);
+
+ /* task takes a ref */
+ g_object_unref (res);
}
void
-tracker_extract_dbus_start (TrackerExtract *extract)
+tracker_extract_get_metadata_by_cmdline (TrackerExtract *object,
+ const gchar *uri,
+ const gchar *mime)
{
+ TrackerSparqlBuilder *statements, *preupdate;
+ gchar *where;
TrackerExtractPrivate *priv;
- GVariant *reply;
- guint32 rval;
- GError *error = NULL;
- GDBusInterfaceVTable interface_vtable = {
- handle_method_call,
- handle_get_property,
- handle_set_property
- };
-
- priv = TRACKER_EXTRACT_GET_PRIVATE (extract);
-
- priv->d_connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
- if (!priv->d_connection) {
- g_critical ("Could not connect to the D-Bus session bus, %s",
- error ? error->message : "no error given.");
- g_clear_error (&error);
- return;
- }
- priv->introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, &error);
- if (!priv->introspection_data) {
- g_critical ("Could not create node info from introspection XML, %s",
- error ? error->message : "no error given.");
- g_clear_error (&error);
- return;
- }
-
- g_message ("Registering D-Bus object...");
- g_message (" Path:'" TRACKER_EXTRACT_PATH "'");
- g_message (" Object Type:'%s'", G_OBJECT_TYPE_NAME (extract));
-
- priv->registration_id =
- g_dbus_connection_register_object (priv->d_connection,
- TRACKER_EXTRACT_PATH,
- priv->introspection_data->interfaces[0],
- &interface_vtable,
- extract,
- NULL,
- &error);
-
- if (error) {
- g_critical ("Could not register the D-Bus object "TRACKER_EXTRACT_PATH", %s",
- error ? error->message : "no error given.");
- g_clear_error (&error);
- return;
- }
-
- reply = g_dbus_connection_call_sync (priv->d_connection,
- "org.freedesktop.DBus",
- "/org/freedesktop/DBus",
- "org.freedesktop.DBus",
- "RequestName",
- g_variant_new ("(su)", TRACKER_EXTRACT_SERVICE, 0x4 /* DBUS_NAME_FLAG_DO_NOT_QUEUE */),
- G_VARIANT_TYPE ("(u)"),
- 0, -1, NULL, &error);
-
- if (error) {
- g_critical ("Could not acquire name:'%s', %s",
- TRACKER_EXTRACT_SERVICE,
- error->message);
- g_clear_error (&error);
- return;
- }
+ priv = TRACKER_EXTRACT_GET_PRIVATE (object);
+ priv->disable_summary_on_finalize = TRUE;
- g_variant_get (reply, "(u)", &rval);
- g_variant_unref (reply);
+ g_return_if_fail (uri != NULL);
- if (rval != 1 /* DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER */) {
- g_critical ("D-Bus service name:'%s' is already taken, "
- "perhaps the application is already running?",
- TRACKER_EXTRACT_SERVICE);
- return;
- }
-}
+ if (get_file_metadata (object, uri, mime,
+ &preupdate, &statements, &where)) {
+ const gchar *preupdate_str, *statements_str;
-void
-tracker_extract_dbus_stop (TrackerExtract *extract)
-{
- TrackerExtractPrivate *priv;
+ preupdate_str = statements_str = NULL;
- priv = TRACKER_EXTRACT_GET_PRIVATE (extract);
+ if (tracker_sparql_builder_get_length (statements) > 0) {
+ statements_str = tracker_sparql_builder_get_result (statements);
+ }
- if (priv->registration_id != 0) {
- g_dbus_connection_unregister_object (priv->d_connection,
- priv->registration_id);
- }
+ if (tracker_sparql_builder_get_length (preupdate) > 0) {
+ preupdate_str = tracker_sparql_builder_get_result (preupdate);
+ }
- if (priv->introspection_data) {
- g_dbus_node_info_unref (priv->introspection_data);
- }
+ g_print ("Preupdate SPARQL:\n%s\n",
+ preupdate_str ? preupdate_str : "");
+ g_print ("Item SPARQL:\n%s\n",
+ statements_str ? statements_str : "");
+ g_print ("Where clause: %s\n", where ? where : "");
- if (priv->d_connection) {
- g_object_unref (priv->d_connection);
+ g_object_unref (statements);
+ g_object_unref (preupdate);
+ g_free (where);
}
}
diff --git a/src/tracker-extract/tracker-extract.h b/src/tracker-extract/tracker-extract.h
index 9cc0132..77c3680 100644
--- a/src/tracker-extract/tracker-extract.h
+++ b/src/tracker-extract/tracker-extract.h
@@ -20,7 +20,9 @@
#ifndef __TRACKERD_EXTRACT_H__
#define __TRACKERD_EXTRACT_H__
-#include <glib-object.h>
+#include <gio/gio.h>
+#include <libtracker-common/tracker-common.h>
+#include <libtracker-extract/tracker-extract.h>
#define TRACKER_EXTRACT_SERVICE "org.freedesktop.Tracker1.Extract"
#define TRACKER_EXTRACT_PATH "/org/freedesktop/Tracker1/Extract"
@@ -37,6 +39,7 @@ G_BEGIN_DECLS
typedef struct TrackerExtract TrackerExtract;
typedef struct TrackerExtractClass TrackerExtractClass;
+typedef struct TrackerExtractInfo TrackerExtractInfo;
struct TrackerExtract {
GObject parent;
@@ -46,11 +49,24 @@ struct TrackerExtractClass {
GObjectClass parent;
};
+struct TrackerExtractInfo {
+ TrackerSparqlBuilder *preupdate;
+ TrackerSparqlBuilder *statements;
+ gchar *where;
+};
+
GType tracker_extract_get_type (void);
TrackerExtract *tracker_extract_new (gboolean disable_shutdown,
gboolean force_internal_extractors,
const gchar *force_module);
+void tracker_extract_file (TrackerExtract *extract,
+ const gchar *file,
+ const gchar *mimetype,
+ GCancellable *cancellable,
+ GAsyncReadyCallback cb,
+ gpointer user_data);
+
void tracker_extract_dbus_start (TrackerExtract *extract);
void tracker_extract_dbus_stop (TrackerExtract *extract);
diff --git a/src/tracker-extract/tracker-main.c b/src/tracker-extract/tracker-main.c
index 6c23309..e0adfc0 100644
--- a/src/tracker-extract/tracker-main.c
+++ b/src/tracker-extract/tracker-main.c
@@ -52,6 +52,7 @@
#include "tracker-config.h"
#include "tracker-main.h"
#include "tracker-extract.h"
+#include "tracker-controller.h"
#define ABOUT \
"Tracker " PACKAGE_VERSION "\n"
@@ -66,7 +67,6 @@
#define QUIT_TIMEOUT 30 /* 1/2 minutes worth of seconds */
static GMainLoop *main_loop;
-static guint quit_timeout_id = 0;
static gint verbosity = -1;
static gchar *filename;
@@ -113,34 +113,6 @@ static GOptionEntry entries[] = {
{ NULL }
};
-static gboolean
-quit_timeout_cb (gpointer user_data)
-{
- quit_timeout_id = 0;
-
- if (!disable_shutdown) {
- if (main_loop) {
- g_main_loop_quit (main_loop);
- }
- } else {
- g_debug ("Would have quit the mainloop");
- }
-
- return FALSE;
-}
-
-void
-tracker_main_quit_timeout_reset (void)
-{
- if (quit_timeout_id != 0) {
- g_source_remove (quit_timeout_id);
- }
-
- quit_timeout_id = g_timeout_add_seconds (QUIT_TIMEOUT,
- quit_timeout_cb,
- NULL);
-}
-
static void
initialize_priority (void)
{
@@ -202,7 +174,8 @@ signal_handler (int signo)
case SIGINT:
in_loop = TRUE;
disable_shutdown = FALSE;
- quit_timeout_cb (NULL);
+ g_main_loop_quit (main_loop);
+
/* Fall through */
default:
if (g_strsignal (signo)) {
@@ -319,8 +292,10 @@ main (int argc, char *argv[])
GOptionContext *context;
GError *error = NULL;
TrackerExtract *object;
+ TrackerController *controller;
gchar *log_filename = NULL;
GMainLoop *my_main_loop;
+ guint shutdown_timeout;
bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
@@ -371,7 +346,7 @@ main (int argc, char *argv[])
g_print ("Initializing tracker-extract...\n");
if (!filename) {
- g_print (" Shutdown after 30 seconds of inactivitiy is %s\n",
+ g_print (" Shutdown after 30 seconds of inactivity is %s\n",
disable_shutdown ? "disabled" : "enabled");
}
@@ -379,10 +354,6 @@ main (int argc, char *argv[])
g_type_init ();
- if (!g_thread_supported ()) {
- g_thread_init (NULL);
- }
-
g_set_application_name ("tracker-extract");
setlocale (LC_ALL, "");
@@ -408,6 +379,13 @@ main (int argc, char *argv[])
/* This makes sure we don't steal all the system's resources */
initialize_priority ();
+ tracker_memory_setrlimits ();
+
+ if (disable_shutdown) {
+ shutdown_timeout = 0;
+ } else {
+ shutdown_timeout = QUIT_TIMEOUT;
+ }
object = tracker_extract_new (disable_shutdown,
force_internal_extractors,
@@ -419,18 +397,26 @@ main (int argc, char *argv[])
return EXIT_FAILURE;
}
- tracker_memory_setrlimits ();
+ controller = tracker_controller_new (object, shutdown_timeout, &error);
+
+ if (!controller) {
+ g_critical ("Controller thread failed to initialize: %s\n", error->message);
- tracker_extract_dbus_start (object);
+ g_error_free (error);
+ g_object_unref (config);
+ g_object_unref (object);
+ tracker_log_shutdown ();
+
+ return EXIT_FAILURE;
+ }
- g_message ("Waiting for D-Bus requests...");
+ g_message ("Main thread (%p) waiting for extract requests...", g_thread_self ());
tracker_locale_init ();
tracker_albumart_init ();
/* Main loop */
main_loop = g_main_loop_new (NULL, FALSE);
- tracker_main_quit_timeout_reset ();
g_main_loop_run (main_loop);
my_main_loop = main_loop;
@@ -443,8 +429,8 @@ main (int argc, char *argv[])
tracker_albumart_shutdown ();
tracker_locale_shutdown ();
- tracker_extract_dbus_stop (object);
g_object_unref (object);
+ g_object_unref (controller);
tracker_log_shutdown ();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]