[tracker/monitor-created-event-fixes] libtracker-miner: If CREATED(A)+CHANGED(A) received, delay the CREATED event until CHANGES_DONE_HINT



commit 011f6bad2b1f7a507ee2f5272ae0bdcd3cd87474
Author: Aleksander Morgado <aleksander lanedo com>
Date:   Mon Jan 17 13:35:55 2011 +0100

    libtracker-miner: If CREATED(A)+CHANGED(A) received, delay the CREATED event until CHANGES_DONE_HINT(A)
    
    Fixes NB#197067

 src/libtracker-miner/tracker-monitor.c |  157 +++++++++++++++++++++++---------
 1 files changed, 113 insertions(+), 44 deletions(-)
---
diff --git a/src/libtracker-miner/tracker-monitor.c b/src/libtracker-miner/tracker-monitor.c
index 08c5fe7..2939710 100644
--- a/src/libtracker-miner/tracker-monitor.c
+++ b/src/libtracker-miner/tracker-monitor.c
@@ -83,6 +83,7 @@ typedef struct {
 	gboolean  is_directory;
 	GTimeVal  start_time;
 	guint32   event_type;
+	gboolean  expirable;
 } EventData;
 
 enum {
@@ -477,6 +478,8 @@ event_data_new (GFile    *file,
 	event->is_directory = is_directory;
 	event->start_time = now;
 	event->event_type = event_type;
+	/* Always expirable when created */
+	event->expirable = TRUE;
 
 	return event;
 }
@@ -717,23 +720,26 @@ event_pairs_process_in_ht (TrackerMonitor *monitor,
 		EventData *event_data = value;
 		glong seconds;
 
-		seconds = now->tv_sec - event_data->start_time.tv_sec;
+		/* If event is not yet expirable, keep it */
+		if (!event_data->expirable)
+			continue;
 
-		if (seconds < 2) {
+		/* If event is expirable, but didn't expire yet, keep it */
+		seconds = now->tv_sec - event_data->start_time.tv_sec;
+		if (seconds < 2)
 			continue;
-		} else {
-			g_debug ("Event '%s' for URI '%s' has timed out (%ld seconds have elapsed)",
-			         monitor_event_to_string (event_data->event_type),
-			         event_data->file_uri,
-			         seconds);
-			/* STEAL the item from the HT, so that disposal methods
-			 * for key and value are not called. */
-			g_hash_table_iter_steal (&iter);
-			/* Unref the key, as no longer needed */
-			g_object_unref (key);
-			/* Add the expired event to our temp list */
-			expired_events = g_list_append (expired_events, event_data);
-		}
+
+		g_debug ("Event '%s' for URI '%s' has timed out (%ld seconds have elapsed)",
+		         monitor_event_to_string (event_data->event_type),
+		         event_data->file_uri,
+		         seconds);
+		/* STEAL the item from the HT, so that disposal methods
+		 * for key and value are not called. */
+		g_hash_table_iter_steal (&iter);
+		/* Unref the key, as no longer needed */
+		g_object_unref (key);
+		/* Add the expired event to our temp list */
+		expired_events = g_list_append (expired_events, event_data);
 	}
 
 	for (l = expired_events; l; l = g_list_next (l)) {
@@ -837,37 +843,69 @@ monitor_event_cb (GFileMonitor	    *file_monitor,
 			/*  - When a G_FILE_MONITOR_EVENT_CREATED(A) is received,
 			 *    -- Add it to the cache, replacing any previous element
 			 *       (shouldn't be any)
+			 *
+			 *  NOTE: We will be assuming that after a CREATED event there must
+			 *  always be a CHANGES_DONE_HINT event. Thus, this CREATED event
+			 *  will be set as non-expirable right now
 			 */
 			g_hash_table_replace (monitor->private->pre_update,
 			                      g_object_ref (file),
-			                      event_data_new (file, NULL, FALSE, event_type));
+			                      event_data_new (file,
+			                                      NULL,
+			                                      FALSE,
+			                                      G_FILE_MONITOR_EVENT_CREATED));
 			break;
 		}
 
 		case G_FILE_MONITOR_EVENT_CHANGED: {
-			/* If use_changed_event, treat as an ATTRIBUTE_CHANGED. Otherwise,
-			 * assume there will be a CHANGES_DONE_HINT afterwards... */
-			if (!monitor->private->use_changed_event) {
-				EventData *previous_update_event_data;
+			EventData *previous_update_event_data;
 
-				/* Get previous event data, if any */
-				previous_update_event_data = g_hash_table_lookup (monitor->private->pre_update, file);
+			/* Get previous event data, if any */
+			previous_update_event_data = g_hash_table_lookup (monitor->private->pre_update, file);
 
+			/* If use_changed_event, treat as an ATTRIBUTE_CHANGED. Otherwise,
+			 * assume there will be a CHANGES_DONE_HINT afterwards and forget about
+			 * the event. */
+			if (!monitor->private->use_changed_event) {
+				/* Process the CHANGED event knowing that there will be a CHANGES_DONE_HINT */
 				if (previous_update_event_data) {
 					if (previous_update_event_data->event_type == G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED) {
 						/* If there is a previous ATTRIBUTE_CHANGED still not notified,
 						 * remove it, as we know there will be a CHANGES_DONE_HINT afterwards
 						 */
 						g_hash_table_remove (monitor->private->pre_update, file);
-					} else if (previous_update_event_data->event_type == G_FILE_MONITOR_EVENT_CREATED) {
-						/* Update the start_time of the original CREATED event that we're refreshing until
-						 * there is a CHANGES_DONE_HINT. */
-						g_get_current_time (&(previous_update_event_data->start_time));
+					} else if (previous_update_event_data->event_type == G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED) {
+						/* If we got a CHANGED event before the CREATED was expired,
+						 * set the CREATED as not expirable, as we expect a CHANGES_DONE_HINT
+						 * afterwards. */
+						previous_update_event_data->expirable = FALSE;
 					}
 				}
-
-				break;
-			} /* Else, Fall through and treat as an ATTRIBUTE_CHANGED */
+			} else {
+				/* For FAM-based monitors, there won't be a CHANGES_DONE_HINT, so use the CHANGED
+				 * events. */
+				if (!previous_update_event_data) {
+					/* If no previous one, insert it */
+					g_hash_table_insert (monitor->private->pre_update,
+					                     g_object_ref (file),
+					                     event_data_new (file,
+					                                     NULL,
+					                                     FALSE,
+					                                     G_FILE_MONITOR_EVENT_CHANGED));
+				} else if (previous_update_event_data->event_type == G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED) {
+					/* Replace the previous ATTRIBUTE_CHANGED event with a CHANGED one. */
+					g_hash_table_replace (monitor->private->pre_update,
+					                      g_object_ref (file),
+					                      event_data_new (file,
+					                                      NULL,
+					                                      FALSE,
+					                                      G_FILE_MONITOR_EVENT_CHANGED));
+				} else {
+					/* Update the start_time of the previous one */
+					g_get_current_time (&(previous_update_event_data->start_time));
+				}
+			}
+			break;
 		}
 
 		case G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED: {
@@ -876,15 +914,21 @@ monitor_event_cb (GFileMonitor	    *file_monitor,
 			/* Get previous event data, if any */
 			previous_update_event_data = g_hash_table_lookup (monitor->private->pre_update, file);
 			if (!previous_update_event_data) {
-				/* If no previous one, insert it */
+				/* If no previous one, insert it (expirable) */
 				g_hash_table_insert (monitor->private->pre_update,
 				                     g_object_ref (file),
-				                     event_data_new (file, NULL, FALSE, event_type));
-			} else {
-				/* Update the start_time of the previous one.
-				 * This could be the original CREATED event that we're refreshing until
-				 * there is a CHANGES_DONE_HINT. */
+				                     event_data_new (file,
+				                                     NULL,
+				                                     FALSE,
+				                                     G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED));
+			} else if (previous_update_event_data->event_type == G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED) {
+				/* Update the start_time of the previous one, if it is an ATTRIBUTE_CHANGED
+				 * event. */
 				g_get_current_time (&(previous_update_event_data->start_time));
+
+				/* No need to update event time in CREATED, as these events
+				 * only expire when there is a CHANGES_DONE_HINT.
+				 */
 			}
 
 			break;
@@ -898,13 +942,17 @@ monitor_event_cb (GFileMonitor	    *file_monitor,
 
 #if ENABLE_FILE_BLACKLISTING
 			if (previous_update_event_data) {
-				/* Refresh event timer */
+				/* Refresh event timer, and make sure the event is now set as expirable */
 				g_get_current_time (&(previous_update_event_data->start_time));
+				previous_update_event_data->expirable = TRUE;
 			} else {
 				/* Insert new update item in cache */
 				g_hash_table_insert (monitor->private->pre_update,
 				                     g_object_ref (file),
-				                     event_data_new (file, NULL, FALSE, event_type));
+				                     event_data_new (file,
+				                                     NULL,
+				                                     FALSE,
+				                                     G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT));
 			}
 #else
 			/* If no blacklisting desired, emit event right away */
@@ -914,7 +962,10 @@ monitor_event_cb (GFileMonitor	    *file_monitor,
 			} else {
 				EventData *new_event;
 
-				new_event = event_data_new (file, NULL, FALSE, event_type);
+				new_event = event_data_new (file,
+				                            NULL,
+				                            FALSE,
+				                            G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT);
 				emit_signal_for_event (monitor, new_event);
 				event_data_free (new_event);
 			}
@@ -946,7 +997,10 @@ monitor_event_cb (GFileMonitor	    *file_monitor,
 			}
 #endif /* ENABLE_FILE_BLACKLISTING */
 
-			new_event = event_data_new (file, NULL, FALSE, event_type);
+			new_event = event_data_new (file,
+			                            NULL,
+			                            FALSE,
+			                            G_FILE_MONITOR_EVENT_DELETED);
 			emit_signal_for_event (monitor, new_event);
 			event_data_free (new_event);
 			break;
@@ -1012,7 +1066,10 @@ monitor_event_cb (GFileMonitor	    *file_monitor,
 			}
 #endif /* ENABLE_FILE_BLACKLISTING */
 
-			new_event = event_data_new (file, other_file, FALSE, event_type);
+			new_event = event_data_new (file,
+			                            other_file,
+			                            FALSE,
+			                            G_FILE_MONITOR_EVENT_MOVED);
 			emit_signal_for_event (monitor, new_event);
 			event_data_free (new_event);
 			break;
@@ -1044,7 +1101,10 @@ monitor_event_cb (GFileMonitor	    *file_monitor,
 			if (!g_hash_table_lookup (monitor->private->pre_update, file)) {
 				g_hash_table_insert (monitor->private->pre_update,
 				                     g_object_ref (file),
-				                     event_data_new (file, NULL, TRUE, event_type));
+				                     event_data_new (file,
+				                                     NULL,
+				                                     TRUE,
+				                                     event_type));
 			}
 
 			break;
@@ -1077,7 +1137,10 @@ monitor_event_cb (GFileMonitor	    *file_monitor,
 				/* If no previous, add to HT */
 				g_hash_table_replace (monitor->private->pre_delete,
 				                      g_object_ref (file),
-				                      event_data_new (file, NULL, TRUE, event_type));
+				                      event_data_new (file,
+				                                      NULL,
+				                                      TRUE,
+				                                      G_FILE_MONITOR_EVENT_DELETED));
 			}
 
 			break;
@@ -1100,7 +1163,10 @@ monitor_event_cb (GFileMonitor	    *file_monitor,
 			    previous_delete_event_data->event_type == G_FILE_MONITOR_EVENT_DELETED) {
 				EventData *new_event;
 
-				new_event = event_data_new (file, other_file, TRUE, G_FILE_MONITOR_EVENT_MOVED);
+				new_event = event_data_new (file,
+				                            other_file,
+				                            TRUE,
+				                            G_FILE_MONITOR_EVENT_MOVED);
 				g_debug ("Processing DELETE(A) + MOVE(A->B) as MOVE(A->B) for directory '%s->%s'",
 				         new_event->file_uri,
 				         new_event->other_file_uri);
@@ -1114,7 +1180,10 @@ monitor_event_cb (GFileMonitor	    *file_monitor,
 				/* If no previous, add to HT */
 				g_hash_table_replace (monitor->private->pre_delete,
 				                      g_object_ref (file),
-				                      event_data_new (file, other_file, TRUE, event_type));
+				                      event_data_new (file,
+				                                      other_file,
+				                                      TRUE,
+				                                      G_FILE_MONITOR_EVENT_MOVED));
 			}
 
 			break;



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