tracker r3137 - in trunk: . src/tracker-indexer src/tracker-indexer/modules
- From: carlosg svn gnome org
- To: svn-commits-list gnome org
- Subject: tracker r3137 - in trunk: . src/tracker-indexer src/tracker-indexer/modules
- Date: Wed, 25 Mar 2009 16:43:51 +0000 (UTC)
Author: carlosg
Date: Wed Mar 25 16:43:51 2009
New Revision: 3137
URL: http://svn.gnome.org/viewvc/tracker?rev=3137&view=rev
Log:
2009-03-25 Carlos Garnacho <carlos imendio com>
Make GVolumeMonitor::mount-pre-unmount cancel any ongoing operation in
the indexer on the removable media. This isn't available yet due to
GLib not emitting such signal, but it will soon.
* src/tracker-indexer/tracker-module-file.[ch]
(tracker_module_file_cancel) (tracker_module_file_is_cancelled): Added
new API.
* src/tracker-indexer/tracker-module-metadata-utils.[ch]: Reworked to
have child processes async+killable.
(tracker_module_metadata_utils_cancel): New function to kill all
external processes on a GFile.
* src/tracker-indexer/modules/files.c: Use new metadata utils function
to immediately cancel an operation.
* src/tracker-indexer/tracker-indexer.c (check_mount_removal)
(mount_pre_unmount_cb) (tracker_indexer_finalize)
(tracker_indexer_init): Hook to GVolumeMonitor::mount-pre-unmount, so
any ongoing+future operations on the removable media are cancelled.
(item_add_or_update) (item_move) (item_process) (process_file):
Reworked to have a single point of cancellation.
Modified:
trunk/ChangeLog
trunk/src/tracker-indexer/modules/files.c
trunk/src/tracker-indexer/tracker-indexer.c
trunk/src/tracker-indexer/tracker-module-file.c
trunk/src/tracker-indexer/tracker-module-file.h
trunk/src/tracker-indexer/tracker-module-metadata-utils.c
trunk/src/tracker-indexer/tracker-module-metadata-utils.h
Modified: trunk/src/tracker-indexer/modules/files.c
==============================================================================
--- trunk/src/tracker-indexer/modules/files.c (original)
+++ trunk/src/tracker-indexer/modules/files.c Wed Mar 25 16:43:51 2009
@@ -60,6 +60,7 @@
static const gchar * tracker_regular_file_get_service_type (TrackerModuleFile *file);
static gchar * tracker_regular_file_get_text (TrackerModuleFile *file);
static TrackerModuleMetadata * tracker_regular_file_get_metadata (TrackerModuleFile *file);
+static void tracker_regular_file_cancel (TrackerModuleFile *file);
G_DEFINE_DYNAMIC_TYPE (TrackerRegularFile, tracker_regular_file, TRACKER_TYPE_MODULE_FILE);
@@ -73,6 +74,7 @@
file_class->get_service_type = tracker_regular_file_get_service_type;
file_class->get_text = tracker_regular_file_get_text;
file_class->get_metadata = tracker_regular_file_get_metadata;
+ file_class->cancel = tracker_regular_file_cancel;
}
static void
@@ -203,6 +205,15 @@
return tracker_module_metadata_utils_get_text (tracker_module_file_get_file (file));
}
+static void
+tracker_regular_file_cancel (TrackerModuleFile *file)
+{
+ GFile *f;
+
+ f = tracker_module_file_get_file (file);
+
+ tracker_module_metadata_utils_cancel (f);
+}
void
indexer_module_initialize (GTypeModule *module)
Modified: trunk/src/tracker-indexer/tracker-indexer.c
==============================================================================
--- trunk/src/tracker-indexer/tracker-indexer.c (original)
+++ trunk/src/tracker-indexer/tracker-indexer.c Wed Mar 25 16:43:51 2009
@@ -136,6 +136,8 @@
GTimer *timer;
+ GVolumeMonitor *volume_monitor;
+
guint idle_id;
guint pause_for_duration_id;
guint signal_status_id;
@@ -211,6 +213,11 @@
static void check_finished (TrackerIndexer *indexer,
gboolean interrupted);
+static gboolean item_process (TrackerIndexer *indexer,
+ PathInfo *info,
+ const gchar *dirname,
+ const gchar *basename);
+
static guint signals[LAST_SIGNAL] = { 0, };
@@ -519,6 +526,66 @@
}
static void
+check_mount_removal (GQueue *queue,
+ GFile *mount_root,
+ gboolean remove_first)
+{
+ GList *list, *next;
+ PathInfo *info;
+
+ if (!queue->head) {
+ /* No elements here */
+ return;
+ }
+
+ list = (remove_first) ? queue->head : queue->head->next;
+
+ while (list) {
+ next = list->next;
+ info = list->data;
+
+ if (g_file_has_prefix (info->file, mount_root) ||
+ (info->source_file && g_file_has_prefix (info->source_file, mount_root))) {
+ g_queue_delete_link (queue, list);
+ path_info_free (info);
+ }
+
+ list = next;
+ }
+}
+
+static void
+mount_pre_unmount_cb (GVolumeMonitor *volume_monitor,
+ GMount *mount,
+ TrackerIndexer *indexer)
+{
+ TrackerIndexerPrivate *priv;
+ GFile *mount_root;
+ PathInfo *current_info;
+ gchar *uri;
+
+ mount_root = g_mount_get_root (mount);
+ priv = indexer->private;
+
+ uri = g_file_get_uri (mount_root);
+ g_debug ("Pre-unmount event for '%s', removing all child elements to be processed", uri);
+ g_free (uri);
+
+ /* Cancel any future elements in the mount */
+ check_mount_removal (priv->dir_queue, mount_root, TRUE);
+ check_mount_removal (priv->file_queue, mount_root, FALSE);
+
+ /* Now cancel current element if it's also in the mount */
+ current_info = g_queue_peek_head (indexer->private->file_queue);
+
+ if (g_file_has_prefix (current_info->file, mount_root)) {
+ tracker_module_file_cancel (current_info->module_file);
+ }
+
+ g_object_unref (mount_root);
+}
+
+static void
tracker_indexer_finalize (GObject *object)
{
TrackerIndexerPrivate *priv;
@@ -593,6 +660,13 @@
g_queue_foreach (priv->file_queue, (GFunc) path_info_free, NULL);
g_queue_free (priv->file_queue);
+ if (priv->volume_monitor) {
+ g_signal_handlers_disconnect_by_func (priv->volume_monitor,
+ mount_pre_unmount_cb,
+ object);
+ g_object_unref (priv->volume_monitor);
+ }
+
G_OBJECT_CLASS (tracker_indexer_parent_class)->finalize (object);
}
@@ -984,6 +1058,11 @@
priv->email_metadata = tracker_db_manager_get_db_interface (TRACKER_DB_EMAIL_METADATA);
priv->email_contents = tracker_db_manager_get_db_interface (TRACKER_DB_EMAIL_CONTENTS);
+ /* Set up volume monitor */
+ priv->volume_monitor = g_volume_monitor_get ();
+ g_signal_connect (priv->volume_monitor, "mount-pre-unmount",
+ G_CALLBACK (mount_pre_unmount_cb), indexer);
+
/* Set up idle handler to process files/directories */
state_check (indexer);
}
@@ -1482,10 +1561,10 @@
PathInfo *info,
const gchar *dirname,
const gchar *basename,
- TrackerModuleMetadata *metadata)
+ TrackerModuleMetadata *metadata,
+ const gchar *text)
{
TrackerService *service;
- gchar *text;
guint32 id;
gchar *mount_point = NULL;
gchar *service_path;
@@ -1499,7 +1578,6 @@
if (tracker_data_query_service_exists (service, dirname, basename, &id, NULL)) {
TrackerDataMetadata *old_metadata_emb, *old_metadata_non_emb;
gchar *old_text;
- gchar *new_text;
if (tracker_module_file_get_flags (info->module_file) & TRACKER_FILE_CONTENTS_STATIC) {
/* According to the module, the metadata can't change for this item */
@@ -1538,9 +1616,8 @@
* difference and add the words.
*/
old_text = tracker_data_query_content (service, id);
- new_text = tracker_module_file_get_text (info->module_file);
- item_update_content (indexer, service, id, old_text, new_text);
+ item_update_content (indexer, service, id, old_text, text);
if (strcmp (tracker_service_get_name (service), "Folders") == 0) {
gchar *path;
@@ -1556,7 +1633,6 @@
}
g_free (old_text);
- g_free (new_text);
tracker_data_metadata_free (old_metadata_emb);
tracker_data_metadata_free (old_metadata_non_emb);
} else {
@@ -1578,8 +1654,6 @@
index_metadata (indexer, id, service, metadata);
- text = tracker_module_file_get_text (info->module_file);
-
if (text) {
/* Save in the index */
index_text_with_parsing (indexer,
@@ -1590,7 +1664,6 @@
/* Save in the DB */
tracker_data_update_set_content (service, id, text);
- g_free (text);
}
g_hash_table_destroy (data);
@@ -1831,7 +1904,7 @@
schedule_flush (indexer, FALSE);
}
-static void
+static gboolean
item_move (TrackerIndexer *indexer,
PathInfo *info,
const gchar *dirname,
@@ -1847,7 +1920,7 @@
service = get_service_for_file (info->module_file, info->module);
if (!service) {
- return;
+ return FALSE;
}
path = g_file_get_path (info->file);
@@ -1861,25 +1934,20 @@
basename,
&service_id,
NULL)) {
- TrackerModuleMetadata *metadata;
gchar *dest_dirname, *dest_basename;
+ gboolean res;
g_message ("Source file '%s' not found in database to move, indexing '%s' from scratch", source_path, path);
- metadata = tracker_module_file_get_metadata (info->module_file);
tracker_file_get_path_and_name (path, &dest_dirname, &dest_basename);
-
- if (metadata) {
- item_add_or_update (indexer, info, dest_dirname, dest_basename, metadata);
- g_object_unref (metadata);
- }
+ res = item_process (indexer, info, dest_dirname, dest_basename);
g_free (dest_dirname);
g_free (dest_basename);
g_free (path);
g_free (source_path);
- return;
+ return res;
}
tracker_file_get_path_and_name (path, &dest_dirname, &dest_basename);
@@ -1916,7 +1984,7 @@
tracker_data_metadata_free (old_metadata);
}
- return;
+ return FALSE;
}
/* Update item being moved */
@@ -1957,6 +2025,8 @@
g_free (source_path);
g_free (path);
+
+ return TRUE;
}
@@ -2046,6 +2116,46 @@
g_free (path);
}
+static gboolean
+item_process (TrackerIndexer *indexer,
+ PathInfo *info,
+ const gchar *dirname,
+ const gchar *basename)
+{
+ TrackerModuleMetadata *metadata;
+ gchar *text;
+
+ metadata = tracker_module_file_get_metadata (info->module_file);
+
+ if (tracker_module_file_is_cancelled (info->module_file)) {
+ if (metadata) {
+ g_object_unref (metadata);
+ }
+
+ return FALSE;
+ }
+
+ if (metadata) {
+ text = tracker_module_file_get_text (info->module_file);
+
+ if (tracker_module_file_is_cancelled (info->module_file)) {
+ g_object_unref (metadata);
+ g_free (text);
+
+ return FALSE;
+ }
+
+ item_add_or_update (indexer, info, dirname, basename, metadata, text);
+
+ g_object_unref (metadata);
+ g_free (text);
+ } else {
+ item_mark_for_removal (indexer, info, dirname, basename);
+ }
+
+ return TRUE;
+}
+
/*
* TODO: Check how are we using this functions.
* I think 99% of the time "values" has only 1 element.
@@ -2361,8 +2471,8 @@
process_file (TrackerIndexer *indexer,
PathInfo *info)
{
- TrackerModuleMetadata *metadata;
gchar *uri, *dirname, *basename;
+ gboolean inc_counters = FALSE;
/* Note: If info->source_file is set, the PathInfo is for a
* MOVE event not for normal file event.
@@ -2434,26 +2544,26 @@
* a service and set the metadata.
*/
if (G_UNLIKELY (info->source_file)) {
- item_move (indexer, info, dirname, basename);
+ if (item_move (indexer, info, dirname, basename)) {
+ inc_counters = TRUE;
+ }
} else {
- metadata = tracker_module_file_get_metadata (info->module_file);
-
- if (metadata) {
- item_add_or_update (indexer, info, dirname, basename, metadata);
- g_object_unref (metadata);
- } else {
- item_mark_for_removal (indexer, info, dirname, basename);
+ if (item_process (indexer, info, dirname, basename)) {
+ inc_counters = TRUE;
}
}
- indexer->private->subelements_processed++;
- indexer->private->items_processed++;
- indexer->private->items_to_index++;
+ if (inc_counters) {
+ indexer->private->subelements_processed++;
+ indexer->private->items_processed++;
+ indexer->private->items_to_index++;
+ }
g_free (dirname);
g_free (basename);
- if (TRACKER_IS_MODULE_ITERATABLE (info->module_file)) {
+ if (!tracker_module_file_is_cancelled (info->module_file) &&
+ TRACKER_IS_MODULE_ITERATABLE (info->module_file)) {
return !tracker_module_iteratable_iter_contents (TRACKER_MODULE_ITERATABLE (info->module_file));
}
Modified: trunk/src/tracker-indexer/tracker-module-file.c
==============================================================================
--- trunk/src/tracker-indexer/tracker-module-file.c (original)
+++ trunk/src/tracker-indexer/tracker-module-file.c Wed Mar 25 16:43:51 2009
@@ -31,11 +31,13 @@
struct TrackerModuleFilePrivate {
GFile *file;
+ guint cancelled : 1;
};
enum {
PROP_0,
- PROP_FILE
+ PROP_FILE,
+ PROP_CANCELLED
};
@@ -88,6 +90,13 @@
"File corresponding to the TrackerModuleFile",
G_TYPE_FILE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (object_class,
+ PROP_CANCELLED,
+ g_param_spec_boolean ("cancelled",
+ "Cancelled",
+ "Whether operations on this file were cancelled",
+ FALSE,
+ G_PARAM_READWRITE));
g_type_class_add_private (object_class, sizeof (TrackerModuleFilePrivate));
}
@@ -158,6 +167,9 @@
case PROP_FILE:
g_value_set_object (value, priv->file);
break;
+ case PROP_CANCELLED:
+ g_value_set_boolean (value, priv->cancelled);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
@@ -314,3 +326,29 @@
return 0;
}
+
+void
+tracker_module_file_cancel (TrackerModuleFile *file)
+{
+ TrackerModuleFilePrivate *priv;
+
+ priv = TRACKER_MODULE_FILE_GET_PRIVATE (file);
+
+ if (!priv->cancelled) {
+ priv->cancelled = TRUE;
+
+ if (TRACKER_MODULE_FILE_GET_CLASS (file)->cancel != NULL) {
+ TRACKER_MODULE_FILE_GET_CLASS (file)->cancel (file);
+ }
+ }
+}
+
+gboolean
+tracker_module_file_is_cancelled (TrackerModuleFile *file)
+{
+ TrackerModuleFilePrivate *priv;
+
+ priv = TRACKER_MODULE_FILE_GET_PRIVATE (file);
+
+ return priv->cancelled;
+}
Modified: trunk/src/tracker-indexer/tracker-module-file.h
==============================================================================
--- trunk/src/tracker-indexer/tracker-module-file.h (original)
+++ trunk/src/tracker-indexer/tracker-module-file.h Wed Mar 25 16:43:51 2009
@@ -60,6 +60,7 @@
gchar * (* get_text) (TrackerModuleFile *file);
TrackerModuleMetadata * (* get_metadata) (TrackerModuleFile *file);
TrackerModuleFlags (* get_flags) (TrackerModuleFile *file);
+ void (* cancel) (TrackerModuleFile *file);
};
GType tracker_module_flags_get_type (void) G_GNUC_CONST;
@@ -72,6 +73,9 @@
TrackerModuleMetadata * tracker_module_file_get_metadata (TrackerModuleFile *file);
TrackerModuleFlags tracker_module_file_get_flags (TrackerModuleFile *file);
+void tracker_module_file_cancel (TrackerModuleFile *file);
+gboolean tracker_module_file_is_cancelled (TrackerModuleFile *file);
+
G_END_DECLS
Modified: trunk/src/tracker-indexer/tracker-module-metadata-utils.c
==============================================================================
--- trunk/src/tracker-indexer/tracker-module-metadata-utils.c (original)
+++ trunk/src/tracker-indexer/tracker-module-metadata-utils.c Wed Mar 25 16:43:51 2009
@@ -43,323 +43,383 @@
#include "tracker-dbus.h"
#define METADATA_FILE_NAME_DELIMITED "File:NameDelimited"
-#define METADATA_FILE_EXT "File:Ext"
-#define METADATA_FILE_PATH "File:Path"
-#define METADATA_FILE_NAME "File:Name"
-#define METADATA_FILE_LINK "File:Link"
-#define METADATA_FILE_MIMETYPE "File:Mime"
-#define METADATA_FILE_SIZE "File:Size"
-#define METADATA_FILE_MODIFIED "File:Modified"
-#define METADATA_FILE_ACCESSED "File:Accessed"
-
-#undef TRY_LOCALE_TO_UTF8_CONVERSION
-#define TEXT_MAX_SIZE 1048576 /* bytes */
-#define TEXT_CHECK_SIZE 65535 /* bytes */
+#define METADATA_FILE_EXT "File:Ext"
+#define METADATA_FILE_PATH "File:Path"
+#define METADATA_FILE_NAME "File:Name"
+#define METADATA_FILE_LINK "File:Link"
+#define METADATA_FILE_MIMETYPE "File:Mime"
+#define METADATA_FILE_SIZE "File:Size"
+#define METADATA_FILE_MODIFIED "File:Modified"
+#define METADATA_FILE_ACCESSED "File:Accessed"
+
+#undef TRY_LOCALE_TO_UTF8_CONVERSION
+#define TEXT_MAX_SIZE 1048576 /* bytes */
+#define TEXT_CHECK_SIZE 65535 /* bytes */
#define TEXT_EXTRACTION_TIMEOUT 10
typedef struct {
- GPid pid;
- guint stdout_watch_id;
- GIOChannel *stdin_channel;
- GIOChannel *stdout_channel;
- GMainLoop *data_incoming_loop;
- gpointer data;
+ GPid pid;
+ guint stdout_watch_id;
+ GIOChannel *stdin_channel;
+ GIOChannel *stdout_channel;
+ GMainLoop *data_incoming_loop;
+ gpointer data;
} ProcessContext;
+typedef struct {
+ GHashTable *metadata;
+ GMainLoop *main_loop;
+ GPid pid;
+} ExtractorContext;
+
static DBusGProxy *
get_dbus_extract_proxy (void)
{
- static DBusGProxy *proxy = NULL;
- DBusGConnection *connection;
- GError *error = NULL;
-
- /* FIXME: Not perfect, we leak */
- if (G_LIKELY (proxy)) {
- return proxy;
- }
-
- connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
+ static DBusGProxy *proxy = NULL;
+ DBusGConnection *connection;
+ GError *error = NULL;
+
+ /* FIXME: Not perfect, we leak */
+ if (G_LIKELY (proxy)) {
+ return proxy;
+ }
+
+ connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
+
+ if (!connection) {
+ g_critical ("Could not connect to the DBus session bus, %s",
+ error ? error->message : "no error given.");
+ g_clear_error (&error);
+ return FALSE;
+ }
+
+ /* Get proxy for Service / Path / Interface of the indexer */
+ proxy = dbus_g_proxy_new_for_name (connection,
+ "org.freedesktop.Tracker.Extract",
+ "/org/freedesktop/Tracker/Extract",
+ "org.freedesktop.Tracker.Extract");
+
+ if (!proxy) {
+ g_critical ("Could not create a DBusGProxy to the extract service");
+ }
- if (!connection) {
- g_critical ("Could not connect to the DBus session bus, %s",
- error ? error->message : "no error given.");
- g_clear_error (&error);
- return FALSE;
- }
-
- /* Get proxy for Service / Path / Interface of the indexer */
- proxy = dbus_g_proxy_new_for_name (connection,
- "org.freedesktop.Tracker.Extract",
- "/org/freedesktop/Tracker/Extract",
- "org.freedesktop.Tracker.Extract");
-
- if (!proxy) {
- g_critical ("Could not create a DBusGProxy to the extract service");
- }
-
- return proxy;
+ return proxy;
}
static void
process_context_destroy (ProcessContext *context)
{
- if (context->stdin_channel) {
- g_io_channel_shutdown (context->stdin_channel, FALSE, NULL);
- g_io_channel_unref (context->stdin_channel);
- context->stdin_channel = NULL;
- }
-
- if (context->stdout_watch_id != 0) {
- g_source_remove (context->stdout_watch_id);
- context->stdout_watch_id = 0;
- }
-
- if (context->stdout_channel) {
- g_io_channel_shutdown (context->stdout_channel, FALSE, NULL);
- g_io_channel_unref (context->stdout_channel);
- context->stdout_channel = NULL;
- }
+ if (context->stdin_channel) {
+ g_io_channel_shutdown (context->stdin_channel, FALSE, NULL);
+ g_io_channel_unref (context->stdin_channel);
+ context->stdin_channel = NULL;
+ }
+
+ if (context->stdout_watch_id != 0) {
+ g_source_remove (context->stdout_watch_id);
+ context->stdout_watch_id = 0;
+ }
+
+ if (context->stdout_channel) {
+ g_io_channel_shutdown (context->stdout_channel, FALSE, NULL);
+ g_io_channel_unref (context->stdout_channel);
+ context->stdout_channel = NULL;
+ }
+
+ if (context->data_incoming_loop) {
+ if (g_main_loop_is_running (context->data_incoming_loop)) {
+ g_main_loop_quit (context->data_incoming_loop);
+ }
+
+ g_main_loop_unref (context->data_incoming_loop);
+ context->data_incoming_loop = NULL;
+ }
+
+ if (context->pid != 0) {
+ g_spawn_close_pid (context->pid);
+ context->pid = 0;
+ }
- if (context->data_incoming_loop) {
- if (g_main_loop_is_running (context->data_incoming_loop)) {
- g_main_loop_quit (context->data_incoming_loop);
- }
+ g_free (context);
+}
- g_main_loop_unref (context->data_incoming_loop);
- context->data_incoming_loop = NULL;
- }
+static void
+process_context_kill (ProcessContext *context)
+{
+ g_message ("Attempting to kill text filter with SIGKILL");
- if (context->pid != 0) {
- g_spawn_close_pid (context->pid);
- context->pid = 0;
- }
+ if (kill (context->pid, SIGKILL) == -1) {
+ const gchar *str = g_strerror (errno);
- g_free (context);
+ g_message (" Could not kill process %d, %s",
+ context->pid,
+ str ? str : "no error given");
+ } else {
+ g_message (" Killed process %d", context->pid);
+ }
}
static void
-process_context_child_watch_cb (GPid pid,
- gint status,
- gpointer user_data)
-{
- ProcessContext *context;
-
- g_debug ("Process '%d' exited with code %d",
- pid,
- status);
+process_context_child_watch_cb (GPid pid,
+ gint status,
+ gpointer user_data)
+{
+ ProcessContext *context;
+
+ g_debug ("Process '%d' exited with code %d",
+ pid,
+ status);
- context = (ProcessContext *) user_data;
- process_context_destroy (context);
+ context = (ProcessContext *) user_data;
+ process_context_destroy (context);
}
static ProcessContext *
process_context_create (const gchar **argv,
- GIOFunc stdout_watch_func)
+ GIOFunc stdout_watch_func)
{
- ProcessContext *context;
- GIOChannel *stdin_channel, *stdout_channel;
- GIOFlags flags;
- GPid pid;
-
- if (!tracker_spawn_async_with_channels (argv,
- TEXT_EXTRACTION_TIMEOUT,
- &pid,
- &stdin_channel,
- &stdout_channel,
- NULL)) {
- return NULL;
- }
+ ProcessContext *context;
+ GIOChannel *stdin_channel, *stdout_channel;
+ GIOFlags flags;
+ GPid pid;
+
+ if (!tracker_spawn_async_with_channels (argv,
+ TEXT_EXTRACTION_TIMEOUT,
+ &pid,
+ &stdin_channel,
+ &stdout_channel,
+ NULL)) {
+ return NULL;
+ }
+
+ g_debug ("Process '%d' spawned for command:'%s'",
+ pid,
+ argv[0]);
+
+ context = g_new0 (ProcessContext, 1);
+ context->pid = pid;
+ context->stdin_channel = stdin_channel;
+ context->stdout_channel = stdout_channel;
+ context->data_incoming_loop = g_main_loop_new (NULL, FALSE);
+ context->stdout_watch_id = g_io_add_watch (stdout_channel,
+ G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP,
+ stdout_watch_func,
+ context);
+
+ flags = g_io_channel_get_flags (context->stdout_channel);
+ flags |= G_IO_FLAG_NONBLOCK;
+
+ g_io_channel_set_flags (context->stdout_channel, flags, NULL);
+
+ g_child_watch_add (context->pid, process_context_child_watch_cb, context);
+
+ return context;
+}
+
+static ExtractorContext *
+extractor_context_create (TrackerModuleMetadata *metadata)
+{
+ ExtractorContext *context;
+ GError *error = NULL;
+ pid_t pid;
+
+ /* Call extractor to get PID so we can kill it if anything goes wrong. */
+ if (!org_freedesktop_Tracker_Extract_get_pid (get_dbus_extract_proxy (),
+ &pid,
+ &error)) {
+ g_message ("Couldn't get PID from tracker-extract, %s",
+ error ? error->message : "no error given");
+ g_clear_error (&error);
+ return NULL;
+ }
+
+ context = g_slice_new0 (ExtractorContext);
+ context->main_loop = g_main_loop_new (NULL, FALSE);
+ context->metadata = g_object_ref (metadata);
+ context->pid = pid;
- g_debug ("Process '%d' spawned for command:'%s'",
- pid,
- argv[0]);
-
- context = g_new0 (ProcessContext, 1);
- context->pid = pid;
- context->stdin_channel = stdin_channel;
- context->stdout_channel = stdout_channel;
- context->data_incoming_loop = g_main_loop_new (NULL, FALSE);
- context->stdout_watch_id = g_io_add_watch (stdout_channel,
- G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP,
- stdout_watch_func,
- context);
+ return context;
+}
- flags = g_io_channel_get_flags (context->stdout_channel);
- flags |= G_IO_FLAG_NONBLOCK;
+static void
+extractor_context_destroy (ExtractorContext *context)
+{
+ g_object_unref (context->metadata);
+ g_main_loop_unref (context->main_loop);
+ g_slice_free (ExtractorContext, context);
+}
- g_io_channel_set_flags (context->stdout_channel, flags, NULL);
+static void
+extractor_context_kill (ExtractorContext *context)
+{
+ g_message ("Attempting to kill tracker-extract with SIGKILL");
- g_child_watch_add (context->pid, process_context_child_watch_cb, context);
+ if (kill (context->pid, SIGKILL) == -1) {
+ const gchar *str = g_strerror (errno);
- return context;
+ g_message (" Could not kill process %d, %s",
+ context->pid,
+ str ? str : "no error given");
+ } else {
+ g_message (" Killed process %d", context->pid);
+ }
}
static void
metadata_utils_add_embedded_data (TrackerModuleMetadata *metadata,
- TrackerField *field,
- const gchar *value)
+ TrackerField *field,
+ const gchar *value)
{
- gchar *utf_value;
-
- if (!g_utf8_validate (value, -1, NULL)) {
- utf_value = g_locale_to_utf8 (value, -1, NULL, NULL, NULL);
- } else {
- utf_value = g_strdup (value);
- }
-
- if (utf_value) {
- const gchar *name;
-
- name = tracker_field_get_name (field);
-
- if (tracker_field_get_data_type (field) == TRACKER_FIELD_TYPE_DATE) {
- gchar *time_str;
+ gchar *utf_value;
- /* Dates come in ISO 8601 format, we handle them as time_t */
- time_str = tracker_date_to_time_string (utf_value);
- tracker_module_metadata_add_string (metadata, name, time_str);
- g_free (time_str);
- } else {
- tracker_module_metadata_add_string (metadata, name, utf_value);
- }
+ if (!g_utf8_validate (value, -1, NULL)) {
+ utf_value = g_locale_to_utf8 (value, -1, NULL, NULL, NULL);
+ } else {
+ utf_value = g_strdup (value);
+ }
+
+ if (utf_value) {
+ const gchar *name;
+
+ name = tracker_field_get_name (field);
+
+ if (tracker_field_get_data_type (field) == TRACKER_FIELD_TYPE_DATE) {
+ gchar *time_str;
+
+ /* Dates come in ISO 8601 format, we handle them as time_t */
+ time_str = tracker_date_to_time_string (utf_value);
+ tracker_module_metadata_add_string (metadata, name, time_str);
+ g_free (time_str);
+ } else {
+ tracker_module_metadata_add_string (metadata, name, utf_value);
+ }
- g_free (utf_value);
- }
+ g_free (utf_value);
+ }
}
static void
metadata_utils_get_embedded_foreach (gpointer key,
- gpointer value,
- gpointer user_data)
+ gpointer value,
+ gpointer user_data)
{
- TrackerModuleMetadata *metadata;
- TrackerField *field;
- gchar *key_str;
- gchar *value_str;
-
- metadata = user_data;
- key_str = key;
- value_str = value;
-
- if (!key || !value) {
- return;
- }
-
- field = tracker_ontology_get_field_by_name (key_str);
- if (!field) {
- g_warning ("Field name '%s' isn't described in the ontology", key_str);
- return;
- }
-
- if (tracker_field_get_multiple_values (field)) {
- GStrv strv;
- guint i;
-
- strv = g_strsplit (value_str, "|", -1);
-
- for (i = 0; strv[i]; i++) {
- metadata_utils_add_embedded_data (metadata, field, strv[i]);
- }
-
- g_strfreev (strv);
- } else {
- metadata_utils_add_embedded_data (metadata, field, value_str);
- }
+ TrackerModuleMetadata *metadata;
+ TrackerField *field;
+ gchar *key_str;
+ gchar *value_str;
+
+ metadata = user_data;
+ key_str = key;
+ value_str = value;
+
+ if (!key || !value) {
+ return;
+ }
+
+ field = tracker_ontology_get_field_by_name (key_str);
+ if (!field) {
+ g_warning ("Field name '%s' isn't described in the ontology", key_str);
+ return;
+ }
+
+ if (tracker_field_get_multiple_values (field)) {
+ GStrv strv;
+ guint i;
+
+ strv = g_strsplit (value_str, "|", -1);
+
+ for (i = 0; strv[i]; i++) {
+ metadata_utils_add_embedded_data (metadata, field, strv[i]);
+ }
+
+ g_strfreev (strv);
+ } else {
+ metadata_utils_add_embedded_data (metadata, field, value_str);
+ }
}
static void
-metadata_utils_get_embedded (const char *path,
- const char *mime_type,
- TrackerModuleMetadata *metadata)
-{
- GHashTable *values = NULL;
- GError *error = NULL;
- const gchar *service_type;
- pid_t pid;
-
- service_type = tracker_ontology_get_service_by_mime (mime_type);
- if (!service_type) {
- return;
- }
-
- if (!tracker_ontology_service_has_metadata (service_type)) {
- return;
- }
-
- /* Call extractor to get PID so we can kill it if anything goes wrong. */
- if (!org_freedesktop_Tracker_Extract_get_pid (get_dbus_extract_proxy (),
- &pid,
- &error)) {
- g_message ("Couldn't get PID from tracker-extract, %s",
- error ? error->message : "no error given");
- g_clear_error (&error);
- return;
- }
-
- /* Call extractor to get data here */
- if (!org_freedesktop_Tracker_Extract_get_metadata (get_dbus_extract_proxy (),
- path,
- mime_type,
- &values,
- &error)) {
- gboolean should_kill = TRUE;
-
- if (G_LIKELY (error)) {
- switch (error->code) {
- case DBUS_GERROR_FAILED:
- case DBUS_GERROR_NO_MEMORY:
- case DBUS_GERROR_NO_REPLY:
- case DBUS_GERROR_IO_ERROR:
- case DBUS_GERROR_LIMITS_EXCEEDED:
- case DBUS_GERROR_TIMEOUT:
- case DBUS_GERROR_DISCONNECTED:
- case DBUS_GERROR_TIMED_OUT:
- case DBUS_GERROR_REMOTE_EXCEPTION:
- break;
-
- default:
- should_kill = FALSE;
- break;
- }
- }
-
- g_message ("Couldn't extract metadata for path:'%s' and mime:'%s', %s",
- path,
- mime_type,
- error ? error->message : "no error given");
-
- g_clear_error (&error);
-
- if (!should_kill) {
- return;
- }
+get_metadata_async_cb (DBusGProxy *proxy,
+ GHashTable *values,
+ GError *error,
+ gpointer user_data)
+{
+ ExtractorContext *context;
+ gboolean should_kill = TRUE;
+
+ context = (ExtractorContext *) user_data;
+
+ if (error) {
+ switch (error->code) {
+ case DBUS_GERROR_FAILED:
+ case DBUS_GERROR_NO_MEMORY:
+ case DBUS_GERROR_NO_REPLY:
+ case DBUS_GERROR_IO_ERROR:
+ case DBUS_GERROR_LIMITS_EXCEEDED:
+ case DBUS_GERROR_TIMEOUT:
+ case DBUS_GERROR_DISCONNECTED:
+ case DBUS_GERROR_TIMED_OUT:
+ case DBUS_GERROR_REMOTE_EXCEPTION:
+ break;
+
+ default:
+ should_kill = FALSE;
+ break;
+ }
+
+ g_message ("Couldn't extract metadata, %s",
+ error->message);
+
+ g_clear_error (&error);
+
+ if (should_kill) {
+ extractor_context_kill (context);
+ }
+ } else if (values) {
+ g_hash_table_foreach (values,
+ metadata_utils_get_embedded_foreach,
+ context->metadata);
- /* Kill extractor, most likely it got stuck */
- g_message ("Attempting to kill tracker-extract with SIGKILL");
+ g_hash_table_destroy (values);
+ }
- if (kill (pid, SIGKILL) == -1) {
- const gchar *str = g_strerror (errno);
-
- g_message (" Could not kill process %d, %s",
- pid,
- str ? str : "no error given");
- } else {
- g_message (" Killed process %d", pid);
- }
-
- return;
- }
-
- if (!values) {
- return;
- }
-
- g_hash_table_foreach (values,
- metadata_utils_get_embedded_foreach,
- metadata);
+ g_main_loop_quit (context->main_loop);
+}
- g_hash_table_destroy (values);
+static void
+metadata_utils_get_embedded (GFile *file,
+ const char *mime_type,
+ TrackerModuleMetadata *metadata)
+{
+ ExtractorContext *context;
+ const gchar *service_type;
+ gchar *path;
+
+ service_type = tracker_ontology_get_service_by_mime (mime_type);
+ if (!service_type) {
+ return;
+ }
+
+ if (!tracker_ontology_service_has_metadata (service_type)) {
+ return;
+ }
+
+ context = extractor_context_create (metadata);
+ g_object_set_data (G_OBJECT (file), "extractor-context", context);
+ path = g_file_get_path (file);
+
+ org_freedesktop_Tracker_Extract_get_metadata_async (get_dbus_extract_proxy (),
+ path,
+ mime_type,
+ get_metadata_async_cb,
+ context);
+
+ g_main_loop_run (context->main_loop);
+
+ g_object_set_data (G_OBJECT (file), "extractor-context", NULL);
+ extractor_context_destroy (context);
+ g_free (path);
}
static gboolean
@@ -635,7 +695,7 @@
}
static gchar *
-get_file_content_by_filter (const gchar *path,
+get_file_content_by_filter (GFile *file,
const gchar *mime)
{
ProcessContext *context;
@@ -664,15 +724,15 @@
argv = g_new0 (gchar *, 3);
argv[0] = text_filter_file;
- argv[1] = (gchar *) path;
+ argv[1] = g_file_get_path (file);
g_message ("Extracting text for:'%s' using filter:'%s'", argv[1], argv[0]);
context = process_context_create ((const gchar **) argv,
get_file_content_read_cb);
- g_free (text_filter_file);
- g_free (argv);
+ g_strfreev (argv);
+ g_object_set_data (G_OBJECT (file), "text-filter-context", context);
if (!context) {
return NULL;
@@ -686,6 +746,8 @@
*/
g_main_loop_run (context->data_incoming_loop);
+ g_object_set_data (G_OBJECT (file), "text-filter-context", NULL);
+
return g_string_free (text, FALSE);
}
@@ -716,7 +778,7 @@
strcmp (service_type, "Development") == 0)) {
text = get_file_content (path);
} else {
- text = get_file_content_by_filter (path, mime_type);
+ text = get_file_content_by_filter (file, mime_type);
}
g_free (mime_type);
@@ -790,10 +852,29 @@
tracker_module_metadata_add_date (metadata, METADATA_FILE_MODIFIED, st.st_mtime);
tracker_module_metadata_add_date (metadata, METADATA_FILE_ACCESSED, st.st_atime);
- metadata_utils_get_embedded (path, mime_type, metadata);
+ metadata_utils_get_embedded (file, mime_type, metadata);
g_free (mime_type);
g_free (path);
return metadata;
}
+
+void
+tracker_module_metadata_utils_cancel (GFile *file)
+{
+ ProcessContext *process_context;
+ ExtractorContext *extractor_context;
+
+ process_context = g_object_get_data (G_OBJECT (file), "text-filter-context");
+
+ if (process_context) {
+ process_context_kill (process_context);
+ }
+
+ extractor_context = g_object_get_data (G_OBJECT (file), "extractor-context");
+
+ if (extractor_context) {
+ extractor_context_kill (extractor_context);
+ }
+}
Modified: trunk/src/tracker-indexer/tracker-module-metadata-utils.h
==============================================================================
--- trunk/src/tracker-indexer/tracker-module-metadata-utils.h (original)
+++ trunk/src/tracker-indexer/tracker-module-metadata-utils.h Wed Mar 25 16:43:51 2009
@@ -34,6 +34,7 @@
TrackerModuleMetadata *tracker_module_metadata_utils_get_data (GFile *file);
gchar * tracker_module_metadata_utils_get_text (GFile *file);
+void tracker_module_metadata_utils_cancel (GFile *file);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]