[tracker/libtracker-miner] TrackerMinerProcess: Handle moved files.
- From: Carlos Garnacho <carlosg src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [tracker/libtracker-miner] TrackerMinerProcess: Handle moved files.
- Date: Thu, 20 Aug 2009 13:36:35 +0000 (UTC)
commit 758d1440d05cc68e7cf2a150cf68845526115755
Author: Carlos Garnacho <carlos lanedo com>
Date: Thu Aug 20 15:35:29 2009 +0200
TrackerMinerProcess: Handle moved files.
This has required a small refactor on how moved items are handled.
src/libtracker-miner/tracker-miner-process.c | 292 +++++++++++++++++++++-----
1 files changed, 234 insertions(+), 58 deletions(-)
---
diff --git a/src/libtracker-miner/tracker-miner-process.c b/src/libtracker-miner/tracker-miner-process.c
index 87bd89a..7ff1cbf 100644
--- a/src/libtracker-miner/tracker-miner-process.c
+++ b/src/libtracker-miner/tracker-miner-process.c
@@ -29,6 +29,13 @@
#define TRACKER_MINER_PROCESS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TRACKER_TYPE_MINER_PROCESS, TrackerMinerProcessPrivate))
+typedef struct ItemMovedData ItemMovedData;
+
+struct ItemMovedData {
+ GFile *file;
+ GFile *source_file;
+};
+
struct TrackerMinerProcessPrivate {
TrackerMonitor *monitor;
TrackerCrawler *crawler;
@@ -258,6 +265,27 @@ tracker_miner_process_init (TrackerMinerProcess *object)
object);
}
+static ItemMovedData *
+item_moved_data_new (GFile *file,
+ GFile *source_file)
+{
+ ItemMovedData *data;
+
+ data = g_slice_new (ItemMovedData);
+ data->file = g_object_ref (file);
+ data->source_file = g_object_ref (source_file);
+
+ return data;
+}
+
+static void
+item_moved_data_free (ItemMovedData *data)
+{
+ g_object_unref (data->file);
+ g_object_unref (data->source_file);
+ g_slice_free (ItemMovedData, data);
+}
+
static void
process_finalize (GObject *object)
{
@@ -323,7 +351,7 @@ process_finalize (GObject *object)
g_list_free (priv->directories);
}
- g_queue_foreach (priv->items_moved, (GFunc) g_object_unref, NULL);
+ g_queue_foreach (priv->items_moved, (GFunc) item_moved_data_free, NULL);
g_queue_free (priv->items_moved);
g_queue_foreach (priv->items_deleted, (GFunc) g_object_unref, NULL);
@@ -398,10 +426,19 @@ directory_data_free (DirectoryData *dd)
static void
item_add_or_update (TrackerMinerProcess *miner,
- GFile *file,
- TrackerSparqlBuilder *sparql)
+ GFile *file)
{
+ TrackerSparqlBuilder *sparql;
gchar *full_sparql, *uri;
+ gboolean processed;
+
+ sparql = tracker_sparql_builder_new_update ();
+ g_signal_emit (miner, signals[PROCESS_FILE], 0, file, sparql, &processed);
+
+ if (!processed) {
+ g_object_unref (sparql);
+ return;
+ }
uri = g_file_get_uri (file);
@@ -414,17 +451,19 @@ item_add_or_update (TrackerMinerProcess *miner,
tracker_miner_execute_sparql (TRACKER_MINER (miner), full_sparql, NULL);
g_free (full_sparql);
+ g_object_unref (sparql);
}
static gboolean
query_resource_exists (TrackerMinerProcess *miner,
- const gchar *uri)
+ GFile *file)
{
TrackerClient *client;
gboolean result;
- gchar *sparql;
+ gchar *sparql, *uri;
GPtrArray *sparql_result;
+ uri = g_file_get_uri (file);
sparql = g_strdup_printf ("SELECT ?s WHERE { ?s a rdfs:Resource . FILTER (?s = <%s>) }",
uri);
@@ -435,6 +474,7 @@ query_resource_exists (TrackerMinerProcess *miner,
tracker_dbus_results_ptr_array_free (&sparql_result);
g_free (sparql);
+ g_free (uri);
return result;
}
@@ -450,7 +490,7 @@ item_remove (TrackerMinerProcess *miner,
g_debug ("Removing item: '%s' (Deleted from filesystem)",
uri);
- if (!query_resource_exists (miner, uri)) {
+ if (!query_resource_exists (miner, file)) {
g_debug (" File does not exist anyway (uri:'%s')", uri);
return;
}
@@ -463,75 +503,206 @@ item_remove (TrackerMinerProcess *miner,
/* FIXME: Should delete recursively? */
}
-static GFile *
+static void
+update_file_uri_recursively (TrackerMinerProcess *miner,
+ GString *sparql_update,
+ const gchar *source_uri,
+ const gchar *uri)
+{
+ TrackerClient *client;
+ gchar *sparql;
+ GPtrArray *result_set;
+
+ g_debug ("Moving item from '%s' to '%s'",
+ source_uri,
+ uri);
+
+ /* FIXME: tracker:uri doesn't seem to exist */
+ /* g_string_append_printf (sparql_update, " <%s> tracker:uri <%s> .", source_uri, uri); */
+
+ client = tracker_miner_get_client (TRACKER_MINER (miner));
+ sparql = g_strdup_printf ("SELECT ?child WHERE { ?child nfo:belongsToContainer <%s> }", source_uri);
+ result_set = tracker_resources_sparql_query (client, sparql, NULL);
+ g_free (sparql);
+
+ if (result_set) {
+ gint i;
+
+ for (i = 0; i < result_set->len; i++) {
+ gchar **child_source_uri, *child_uri;
+
+ child_source_uri = g_ptr_array_index (result_set, i);
+
+ if (!g_str_has_prefix (*child_source_uri, source_uri)) {
+ g_warning ("Child URI '%s' does not start with parent URI '%s'",
+ *child_source_uri,
+ source_uri);
+ continue;
+ }
+
+ child_uri = g_strdup_printf ("%s%s", uri, *child_source_uri + strlen (source_uri));
+
+ update_file_uri_recursively (miner, sparql_update, *child_source_uri, child_uri);
+
+ g_free (child_source_uri);
+ g_free (child_uri);
+ }
+
+ g_ptr_array_free (result_set, TRUE);
+ }
+}
+
+static void
+item_move (TrackerMinerProcess *miner,
+ GFile *file,
+ GFile *source_file)
+{
+ gchar *uri, *source_uri, *escaped_filename;
+ GFileInfo *file_info;
+ GString *sparql;
+
+ uri = g_file_get_uri (file);
+ source_uri = g_file_get_uri (source_file);
+
+ /* Get 'source' ID */
+ if (!query_resource_exists (miner, source_file)) {
+ g_message ("Source file '%s' not found in store to move, indexing '%s' from scratch", source_uri, uri);
+
+ item_add_or_update (miner, file);
+
+ g_free (source_uri);
+ g_free (uri);
+
+ return;
+ }
+
+ file_info = g_file_query_info (file,
+ G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ NULL, NULL);
+
+ if (!file_info) {
+ /* Destination file has gone away, ignore dest file and remove source if any */
+ item_remove (miner, source_file);
+
+ g_free (source_uri);
+ g_free (uri);
+
+ return;
+ }
+
+ sparql = g_string_new ("");
+
+ g_string_append_printf (sparql,
+ "DELETE { <%s> nfo:fileName ?o } WHERE { <%s> nfo:fileName ?o }",
+ source_uri, source_uri);
+
+ g_string_append (sparql, " INSERT {");
+
+ escaped_filename = g_strescape (g_file_info_get_display_name (file_info), NULL);
+
+ g_string_append_printf (sparql, " <%s> nfo:fileName \"%s\" .", source_uri, escaped_filename);
+ g_string_append_printf (sparql, " <%s> nie:isStoredAs <%s> .", source_uri, uri);
+
+ /* FIXME: This function just seemed to update the thumbnail */
+ /* update_file_uri_recursively (miner, sparql, source_uri, uri); */
+
+ g_string_append (sparql, " }");
+
+ tracker_miner_execute_sparql (TRACKER_MINER (miner), sparql->str, NULL);
+
+ g_free (uri);
+ g_free (source_uri);
+ g_object_unref (file_info);
+ g_string_free (sparql, TRUE);
+}
+
+static gint
get_next_file (TrackerMinerProcess *miner,
- gint *queue)
+ GFile **file,
+ GFile **source_file)
{
- GFile *file;
+ ItemMovedData *data;
+ GFile *queue_file;
/* Deleted items first */
- file = g_queue_pop_head (miner->private->items_deleted);
- if (file) {
- *queue = QUEUE_DELETED;
- return file;
+ queue_file = g_queue_pop_head (miner->private->items_deleted);
+ if (queue_file) {
+ *file = queue_file;
+ *source_file = NULL;
+ return QUEUE_DELETED;
}
/* Created items next */
- file = g_queue_pop_head (miner->private->items_created);
- if (file) {
- *queue = QUEUE_CREATED;
- return file;
+ queue_file = g_queue_pop_head (miner->private->items_created);
+ if (queue_file) {
+ *file = queue_file;
+ *source_file = NULL;
+ return QUEUE_CREATED;
}
/* Updated items next */
- file = g_queue_pop_head (miner->private->items_updated);
- if (file) {
- *queue = QUEUE_UPDATED;
- return file;
+ queue_file = g_queue_pop_head (miner->private->items_updated);
+ if (queue_file) {
+ *file = queue_file;
+ *source_file = NULL;
+ return QUEUE_UPDATED;
}
/* Moved items next */
- file = g_queue_pop_head (miner->private->items_moved);
- if (file) {
- *queue = QUEUE_MOVED;
- return file;
+ data = g_queue_pop_head (miner->private->items_moved);
+ if (data) {
+ *file = g_object_ref (data->file);
+ *source_file = g_object_ref (data->source_file);
+ item_moved_data_free (data);
+
+ return QUEUE_MOVED;
}
- *queue = QUEUE_NONE;
- return NULL;
+ *file = NULL;
+ *source_file = NULL;
+
+ return QUEUE_NONE;
}
static gboolean
item_queue_handlers_cb (gpointer user_data)
{
- TrackerSparqlBuilder *sparql;
TrackerMinerProcess *miner;
- gboolean processed;
- GFile *file;
+ GFile *file, *source_file;
gint queue;
miner = user_data;
- sparql = tracker_sparql_builder_new_update ();
- file = get_next_file (miner, &queue);
-
- if (file) {
- if (queue == QUEUE_DELETED) {
- item_remove (miner, file);
- } else {
- g_signal_emit (miner, signals[PROCESS_FILE], 0, file, sparql, &processed);
+ queue = get_next_file (miner, &file, &source_file);
- if (processed) {
- /* Commit sparql */
- item_add_or_update (miner, file, sparql);
- }
- }
+ if (queue == QUEUE_NONE) {
+ /* No more files left to process */
+ miner->private->item_queues_handler_id = 0;
+ return FALSE;
+ }
- return TRUE;
+ switch (queue) {
+ case QUEUE_MOVED:
+ item_move (miner, file, source_file);
+ break;
+ case QUEUE_DELETED:
+ item_remove (miner, file);
+ break;
+ case QUEUE_CREATED:
+ case QUEUE_UPDATED:
+ item_add_or_update (miner, file);
+ break;
+ default:
+ g_assert_not_reached ();
}
- miner->private->item_queues_handler_id = 0;
+ g_object_unref (file);
+
+ if (source_file) {
+ g_object_unref (source_file);
+ }
- return FALSE;
+ return TRUE;
}
static void
@@ -776,26 +947,31 @@ monitor_item_moved_cb (TrackerMonitor *monitor,
} else {
gchar *path;
gchar *other_path;
- gboolean should_process;
- gboolean should_process_other;
-
+ gboolean source_stored, should_process_other;
+
path = g_file_get_path (file);
other_path = g_file_get_path (other_file);
- should_process = should_process_file (process, file, is_directory);
+ source_stored = query_resource_exists (process, file);
should_process_other = should_process_file (process, other_file, is_directory);
g_debug ("%s:'%s'->'%s':%s (%s) (move monitor event or user request)",
- should_process ? "Found " : "Ignored",
+ source_stored ? "In store" : "Not in store",
path,
other_path,
should_process_other ? "Found " : "Ignored",
is_directory ? "DIR" : "FILE");
-
- if (!should_process && !should_process_other) {
+
+ /* FIXME: Guessing this soon the queue the event should pertain
+ * to could introduce race conditions if events from other
+ * queues for the same files are processed before items_moved,
+ * Most of these decisions should be taken when the event is
+ * actually being processed.
+ */
+ if (!source_stored && !should_process_other) {
/* Do nothing */
- } else if (!should_process) {
- /* Check new file */
+ } else if (!source_stored) {
+ /* Source file was not stored, check dest file as new */
if (!is_directory) {
g_queue_push_tail (process->private->items_created,
g_object_ref (other_file));
@@ -822,9 +998,9 @@ monitor_item_moved_cb (TrackerMonitor *monitor,
item_queue_handlers_set_up (process);
} else {
/* Move old file to new file */
- g_queue_push_tail (process->private->items_moved, g_object_ref (file));
- g_queue_push_tail (process->private->items_moved, g_object_ref (other_file));
-
+ g_queue_push_tail (process->private->items_moved,
+ item_moved_data_new (other_file, file));
+
item_queue_handlers_set_up (process);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]