[tracker/avoid-duplicates] Fixes NB#175723: Avoid duplicates if several monitor events arrive together and store is slow



commit 9dc4772017992772b7b8c839d0ee53727f5e51d4
Author: Aleksander Morgado <aleksander lanedo com>
Date:   Wed Jun 23 14:20:03 2010 +0200

    Fixes NB#175723: Avoid duplicates if several monitor events arrive together and store is slow
    
     * If a given file is being currently processed (in the processing_pool), a new event
       on the same file must not be launched. Instead, the event is scheduled to be added
       again in the proper queue after 2 seconds.

 src/libtracker-miner/tracker-miner-fs.c |  128 +++++++++++++++++++++++++++----
 1 files changed, 113 insertions(+), 15 deletions(-)
---
diff --git a/src/libtracker-miner/tracker-miner-fs.c b/src/libtracker-miner/tracker-miner-fs.c
index 5a2ebaa..3a3cbf1 100644
--- a/src/libtracker-miner/tracker-miner-fs.c
+++ b/src/libtracker-miner/tracker-miner-fs.c
@@ -47,12 +47,21 @@
 
 #define TRACKER_MINER_FS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TRACKER_TYPE_MINER_FS, TrackerMinerFSPrivate))
 
+/* Seconds to postpone a given event */
+#define EVENT_POSTPONED_INTERVAL 2
+
 typedef struct {
 	GFile *file;
 	GFile *source_file;
 } ItemMovedData;
 
 typedef struct {
+	TrackerMinerFS *fs;
+	GQueue *queue;
+	gpointer item;
+} ItemEventPostponedData;
+
+typedef struct {
 	GFile    *file;
 	guint     recurse : 1;
 	guint     ref_count : 7;
@@ -214,6 +223,9 @@ static DirectoryData *directory_data_new                  (GFile
                                                            gboolean              recurse);
 static DirectoryData *directory_data_ref                  (DirectoryData        *dd);
 static void           directory_data_unref                (DirectoryData        *dd);
+static void           item_add_to_queue_postponed         (TrackerMinerFS       *fs,
+                                                           GQueue               *queue,
+                                                           gpointer              item);
 static ItemMovedData *item_moved_data_new                 (GFile                *file,
                                                            GFile                *source_file);
 static void           item_moved_data_free                (ItemMovedData        *data);
@@ -612,21 +624,31 @@ process_data_free (ProcessData *data)
 
 static ProcessData *
 process_data_find (TrackerMinerFS *fs,
-                   GFile          *file)
+                   GFile          *file,
+                   gboolean        path_search)
 {
 	GList *l;
 
 	for (l = fs->private->processing_pool; l; l = l->next) {
 		ProcessData *data = l->data;
 
-		/* Different operations for the same file URI could be
-		 * piled up here, each being a different GFile object.
-		 * Miner implementations should really notify on the
-		 * same GFile object that's being passed, so we check for
-		 * pointer equality here, rather than doing path comparisons
-		 */
-		if (data->file == file) {
-			return data;
+		if (!path_search) {
+			/* Different operations for the same file URI could be
+			 * piled up here, each being a different GFile object.
+			 * Miner implementations should really notify on the
+			 * same GFile object that's being passed, so we check for
+			 * pointer equality here, rather than doing path comparisons
+			 */
+			if(data->file == file)
+				return data;
+		} else {
+			/* Note that if there are different GFiles being
+			 * processed for the same file path, we are actually
+			 * returning the first one found, If you want exactly
+			 * the same GFile as the one as input, use the
+			 * process_data_find() method instead */
+			if (g_file_equal (data->file, file))
+				return data;
 		}
 	}
 
@@ -1321,7 +1343,7 @@ do_process_file (TrackerMinerFS *fs,
 		/* Re-fetch data, since it might have been
 		 * removed in broken implementations
 		 */
-		data = process_data_find (fs, data->file);
+		data = process_data_find (fs, data->file, FALSE);
 
 		g_message ("%s refused to process '%s'", G_OBJECT_TYPE_NAME (fs), uri);
 
@@ -1962,6 +1984,14 @@ item_queue_get_next_file (TrackerMinerFS  *fs,
 			*file = NULL;
 			return QUEUE_IGNORE_NEXT_UPDATE;
 		}
+		if (process_data_find (fs, queue_file, TRUE)) {
+			*file = NULL;
+			/* Need to postpone event... */
+			item_add_to_queue_postponed (fs,
+			                             fs->private->items_deleted,
+			                             queue_file); /* no need to ref again */
+			return QUEUE_WAIT;
+		}
 		*file = queue_file;
 		return QUEUE_DELETED;
 	}
@@ -1999,6 +2029,14 @@ item_queue_get_next_file (TrackerMinerFS  *fs,
 			*source_file = queue_file;
 			return QUEUE_IGNORE_NEXT_UPDATE;
 		}
+		if (process_data_find (fs, queue_file, TRUE)) {
+			*file = NULL;
+			/* Need to postpone event... */
+			item_add_to_queue_postponed (fs,
+			                             fs->private->items_created,
+			                             queue_file); /* no need to ref again */
+			return QUEUE_WAIT;
+		}
 		*file = queue_file;
 		*source_file = NULL;
 		return QUEUE_CREATED;
@@ -2011,6 +2049,14 @@ item_queue_get_next_file (TrackerMinerFS  *fs,
 		*source_file = NULL;
 		if (check_ignore_next_update (fs, queue_file))
 			return QUEUE_IGNORE_NEXT_UPDATE;
+		if (process_data_find (fs, queue_file, TRUE)) {
+			*file = NULL;
+			/* Need to postpone event... */
+			item_add_to_queue_postponed (fs,
+			                             fs->private->items_updated,
+			                             queue_file); /* no need to ref again */
+			return QUEUE_WAIT;
+		}
 		return QUEUE_UPDATED;
 	}
 
@@ -2019,9 +2065,23 @@ item_queue_get_next_file (TrackerMinerFS  *fs,
 	if (data) {
 		*file = g_object_ref (data->file);
 		*source_file = g_object_ref (data->source_file);
-		item_moved_data_free (data);
-		if (check_ignore_next_update (fs, *file))
+		if (check_ignore_next_update (fs, *file)) {
+			item_moved_data_free (data);
 			return QUEUE_IGNORE_NEXT_UPDATE;
+		}
+		if (process_data_find (fs, *file, TRUE) ||
+		    process_data_find (fs, *source_file, TRUE)) {
+			g_object_unref (*file);
+			g_object_unref (*source_file);
+			*file = NULL;
+			*source_file = NULL;
+			/* Need to postpone event... */
+			item_add_to_queue_postponed (fs,
+			                             fs->private->items_moved,
+			                             data); /* no need to create again */
+			return QUEUE_WAIT;
+		}
+		item_moved_data_free (data);
 		return QUEUE_MOVED;
 	}
 
@@ -2511,6 +2571,44 @@ should_process_file (TrackerMinerFS *fs,
 	return should_change_index_for_file (fs, file);
 }
 
+static gboolean
+item_event_postponed_cb (gpointer data)
+{
+	ItemEventPostponedData *event = data;
+
+	g_debug ("Running postponed event %p...", event);
+
+	g_queue_push_tail (event->queue, event->item);
+	item_queue_handlers_set_up (event->fs);
+
+	g_slice_free (ItemEventPostponedData, event);
+
+	return FALSE;
+}
+
+static void
+item_add_to_queue_postponed (TrackerMinerFS *fs,
+                             GQueue         *queue,
+                             gpointer        item)
+{
+	/* Event should be postponed because it's already being processed at
+	 * this moment, so schedule it to be added to the proper queue after
+	 * some seconds */
+	ItemEventPostponedData *event;
+
+	event = g_slice_new (ItemEventPostponedData);
+	event->queue = queue;
+	event->item = item;
+	event->fs = fs;
+
+	g_debug ("Postponing event %p for %u seconds...",
+	         event,
+	         EVENT_POSTPONED_INTERVAL);
+	g_timeout_add_seconds (EVENT_POSTPONED_INTERVAL,
+	                       item_event_postponed_cb,
+	                       event);
+}
+
 static void
 monitor_item_created_cb (TrackerMonitor *monitor,
                          GFile          *file,
@@ -3380,7 +3478,7 @@ tracker_miner_fs_file_notify (TrackerMinerFS *fs,
 
 	fs->private->total_files_notified++;
 
-	data = process_data_find (fs, file);
+	data = process_data_find (fs, file, FALSE);
 
 	if (!data) {
 		gchar *uri;
@@ -3482,7 +3580,7 @@ tracker_miner_fs_get_urn (TrackerMinerFS *fs,
 	g_return_val_if_fail (TRACKER_IS_MINER_FS (fs), NULL);
 	g_return_val_if_fail (G_IS_FILE (file), NULL);
 
-	data = process_data_find (fs, file);
+	data = process_data_find (fs, file, FALSE);
 
 	if (!data) {
 		gchar *uri;
@@ -3523,7 +3621,7 @@ tracker_miner_fs_get_parent_urn (TrackerMinerFS *fs,
 	g_return_val_if_fail (TRACKER_IS_MINER_FS (fs), NULL);
 	g_return_val_if_fail (G_IS_FILE (file), NULL);
 
-	data = process_data_find (fs, file);
+	data = process_data_find (fs, file, FALSE);
 
 	if (!data) {
 		gchar *uri;



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