Blame SOURCES/evolution-data-server-3.12.11-goa-source-change-removed.patch

5e6360
diff -up evolution-data-server-3.12.11/libebackend/e-source-registry-server.c.goa-source-change-removed evolution-data-server-3.12.11/libebackend/e-source-registry-server.c
5e6360
--- evolution-data-server-3.12.11/libebackend/e-source-registry-server.c.goa-source-change-removed	2014-11-11 18:40:25.000000000 +0100
5e6360
+++ evolution-data-server-3.12.11/libebackend/e-source-registry-server.c	2015-08-17 16:55:07.401935846 +0200
5e6360
@@ -87,6 +87,10 @@ struct _ESourceRegistryServerPrivate {
5e6360
 	GHashTable *waiting_auths;
5e6360
 
5e6360
 	guint authentication_count;
5e6360
+
5e6360
+	GMutex file_monitor_lock;
5e6360
+	GHashTable *file_monitor_events; /* gchar *uid ~> FileEventData * */
5e6360
+	GSource *file_monitor_source;
5e6360
 };
5e6360
 
5e6360
 struct _AuthRequest {
5e6360
@@ -899,51 +903,121 @@ source_registry_server_reload_cb (EDBusS
5e6360
 	return TRUE;
5e6360
 }
5e6360
 
5e6360
+typedef struct _FileEventData {
5e6360
+	GFile *file;
5e6360
+	GFileMonitorEvent event_type;
5e6360
+} FileEventData;
5e6360
+
5e6360
+static FileEventData *
5e6360
+file_event_data_new (GFile *file,
5e6360
+		     GFileMonitorEvent event_type)
5e6360
+{
5e6360
+	FileEventData *fed;
5e6360
+
5e6360
+	fed = g_new0 (FileEventData, 1);
5e6360
+	fed->file = g_object_ref (file);
5e6360
+	fed->event_type = event_type;
5e6360
+
5e6360
+	return fed;
5e6360
+}
5e6360
+
5e6360
 static void
5e6360
-source_registry_server_monitor_changed_cb (GFileMonitor *monitor,
5e6360
-                                           GFile *file,
5e6360
-                                           GFile *other_file,
5e6360
-                                           GFileMonitorEvent event_type,
5e6360
-                                           ESourceRegistryServer *server)
5e6360
+file_event_data_free (gpointer ptr)
5e6360
 {
5e6360
+	FileEventData *fed = ptr;
5e6360
+
5e6360
+	if (fed) {
5e6360
+		g_clear_object (&fed->file);
5e6360
+		g_free (fed);
5e6360
+	}
5e6360
+}
5e6360
+
5e6360
+static void
5e6360
+source_registry_server_process_file_monitor_event (gpointer key,
5e6360
+						   gpointer value,
5e6360
+						   gpointer user_data)
5e6360
+{
5e6360
+	const gchar *uid = key;
5e6360
+	const FileEventData *fed = value;
5e6360
+	ESourceRegistryServer *server = user_data;
5e6360
+	GFileMonitorEvent event_type;
5e6360
+
5e6360
+	g_return_if_fail (uid != NULL);
5e6360
+	g_return_if_fail (fed != NULL);
5e6360
+
5e6360
+	event_type = fed->event_type;
5e6360
+
5e6360
+	if (e_source_registry_debug_enabled ()) {
5e6360
+		e_source_registry_debug_print ("Processing file monitor event %s (%u) for UID: %s\n",
5e6360
+			event_type == G_FILE_MONITOR_EVENT_CHANGED ? "CHANGED" :
5e6360
+			event_type == G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT ? "CHANGES_DONE_HINT" :
5e6360
+			event_type == G_FILE_MONITOR_EVENT_DELETED ? "DELETED" :
5e6360
+			event_type == G_FILE_MONITOR_EVENT_CREATED ? "CREATED" :
5e6360
+			event_type == G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED ? "ATTRIBUTE_CHANGED" :
5e6360
+			event_type == G_FILE_MONITOR_EVENT_PRE_UNMOUNT ? "PRE_UNMOUNT" :
5e6360
+			event_type == G_FILE_MONITOR_EVENT_UNMOUNTED ? "UNMOUNTED" :
5e6360
+			event_type == G_FILE_MONITOR_EVENT_MOVED ? "MOVED" : "???",
5e6360
+			event_type,
5e6360
+			uid);
5e6360
+	}
5e6360
+
5e6360
+	if (event_type == G_FILE_MONITOR_EVENT_CHANGED ||
5e6360
+	    event_type == G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT) {
5e6360
+		ESource *source;
5e6360
+		GError *error = NULL;
5e6360
+
5e6360
+		source = e_source_registry_server_ref_source (server, uid);
5e6360
+
5e6360
+		/* If the source does not exist, create it; parsing may have
5e6360
+		 * failed when the file was originally created. This can happen
5e6360
+		 * if the file is created (empty), then e-source-registry-server
5e6360
+		 * detects it, then it’s populated and made valid.
5e6360
+		 *
5e6360
+		 * Otherwise, reload the file since it has changed. */
5e6360
+		if (source == NULL) {
5e6360
+			event_type = G_FILE_MONITOR_EVENT_CREATED;
5e6360
+		} else if (!e_server_side_source_load (E_SERVER_SIDE_SOURCE (source), NULL, &error)) {
5e6360
+			g_warning ("Error reloading source ‘%s’: %s", uid, error->message);
5e6360
+
5e6360
+			g_error_free (error);
5e6360
+			g_object_unref (source);
5e6360
+
5e6360
+			return;
5e6360
+		}
5e6360
+
5e6360
+		g_object_unref (source);
5e6360
+	}
5e6360
+
5e6360
 	if (event_type == G_FILE_MONITOR_EVENT_CREATED) {
5e6360
 		ESource *source;
5e6360
 		GError *error = NULL;
5e6360
 
5e6360
-		/* it can return NULL source for hidden files */
5e6360
-		source = e_server_side_source_new (server, file, &error);
5e6360
+		source = e_source_registry_server_ref_source (server, uid);
5e6360
+
5e6360
+		if (!source) {
5e6360
+			/* it can return NULL source for hidden files */
5e6360
+			source = e_server_side_source_new (server, fed->file, &error);
5e6360
+		}
5e6360
 
5e6360
 		if (!error && source) {
5e6360
 			/* File monitors are only placed on directories
5e6360
 			 * where data sources are writable and removable,
5e6360
 			 * so it should be safe to assume these flags. */
5e6360
-			e_server_side_source_set_writable (
5e6360
-				E_SERVER_SIDE_SOURCE (source), TRUE);
5e6360
-			e_server_side_source_set_removable (
5e6360
-				E_SERVER_SIDE_SOURCE (source), TRUE);
5e6360
+			e_server_side_source_set_writable (E_SERVER_SIDE_SOURCE (source), TRUE);
5e6360
+			e_server_side_source_set_removable (E_SERVER_SIDE_SOURCE (source), TRUE);
5e6360
 
5e6360
 			e_source_registry_server_add_source (server, source);
5e6360
-			g_object_unref (source);
5e6360
 		} else if (error) {
5e6360
-			e_source_registry_server_load_error (
5e6360
-				server, file, error);
5e6360
+			e_source_registry_server_load_error (server, fed->file, error);
5e6360
 			g_error_free (error);
5e6360
 		}
5e6360
 	}
5e6360
 
5e6360
 	if (event_type == G_FILE_MONITOR_EVENT_DELETED) {
5e6360
 		ESource *source;
5e6360
-		gchar *uid;
5e6360
-
5e6360
-		uid = e_server_side_source_uid_from_file (file, NULL);
5e6360
-
5e6360
-		if (uid == NULL)
5e6360
-			return;
5e6360
 
5e6360
 		source = e_source_registry_server_ref_source (server, uid);
5e6360
 
5e6360
-		g_free (uid);
5e6360
-
5e6360
 		if (source == NULL)
5e6360
 			return;
5e6360
 
5e6360
@@ -958,6 +1032,87 @@ source_registry_server_monitor_changed_c
5e6360
 }
5e6360
 
5e6360
 static gboolean
5e6360
+source_registry_server_process_file_monitor_events_cb (gpointer user_data)
5e6360
+{
5e6360
+	ESourceRegistryServer *server = user_data;
5e6360
+	GHashTable *events;
5e6360
+
5e6360
+	if (g_source_is_destroyed (g_main_current_source ()))
5e6360
+		return FALSE;
5e6360
+
5e6360
+	g_return_val_if_fail (E_IS_SOURCE_REGISTRY_SERVER (server), FALSE);
5e6360
+
5e6360
+	g_mutex_lock (&server->priv->file_monitor_lock);
5e6360
+	events = server->priv->file_monitor_events;
5e6360
+	server->priv->file_monitor_events = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, file_event_data_free);
5e6360
+	g_mutex_unlock (&server->priv->file_monitor_lock);
5e6360
+
5e6360
+	g_hash_table_foreach (events, source_registry_server_process_file_monitor_event, server);
5e6360
+	g_hash_table_destroy (events);
5e6360
+
5e6360
+	return FALSE;
5e6360
+}
5e6360
+
5e6360
+static void
5e6360
+source_registry_server_monitor_changed_cb (GFileMonitor *monitor,
5e6360
+                                           GFile *file,
5e6360
+                                           GFile *other_file,
5e6360
+                                           GFileMonitorEvent event_type,
5e6360
+                                           ESourceRegistryServer *server)
5e6360
+{
5e6360
+	if (e_source_registry_debug_enabled ()) {
5e6360
+		gchar *uri;
5e6360
+
5e6360
+		uri = g_file_get_uri (file);
5e6360
+		e_source_registry_debug_print ("Handling file monitor event %s (%u) for URI: %s\n",
5e6360
+			event_type == G_FILE_MONITOR_EVENT_CHANGED ? "CHANGED" :
5e6360
+			event_type == G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT ? "CHANGES_DONE_HINT" :
5e6360
+			event_type == G_FILE_MONITOR_EVENT_DELETED ? "DELETED" :
5e6360
+			event_type == G_FILE_MONITOR_EVENT_CREATED ? "CREATED" :
5e6360
+			event_type == G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED ? "ATTRIBUTE_CHANGED" :
5e6360
+			event_type == G_FILE_MONITOR_EVENT_PRE_UNMOUNT ? "PRE_UNMOUNT" :
5e6360
+			event_type == G_FILE_MONITOR_EVENT_UNMOUNTED ? "UNMOUNTED" :
5e6360
+			event_type == G_FILE_MONITOR_EVENT_MOVED ? "MOVED" : "???",
5e6360
+			event_type,
5e6360
+			uri);
5e6360
+		g_free (uri);
5e6360
+	}
5e6360
+
5e6360
+	if (event_type == G_FILE_MONITOR_EVENT_CHANGED ||
5e6360
+	    event_type == G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT ||
5e6360
+	    event_type == G_FILE_MONITOR_EVENT_CREATED ||
5e6360
+	    event_type == G_FILE_MONITOR_EVENT_DELETED) {
5e6360
+		gchar *uid;
5e6360
+
5e6360
+		uid = e_server_side_source_uid_from_file (file, NULL);
5e6360
+
5e6360
+		if (uid == NULL)
5e6360
+			return;
5e6360
+
5e6360
+		g_mutex_lock (&server->priv->file_monitor_lock);
5e6360
+		/* This overwrites any previous events, aka the last wins
5e6360
+		   (overwrite can be DELETE + CREATE, which handles it correctly). */
5e6360
+		g_hash_table_insert (server->priv->file_monitor_events, uid, file_event_data_new (file, event_type));
5e6360
+
5e6360
+		if (server->priv->file_monitor_source) {
5e6360
+			g_source_destroy (server->priv->file_monitor_source);
5e6360
+			g_source_unref (server->priv->file_monitor_source);
5e6360
+		}
5e6360
+
5e6360
+		server->priv->file_monitor_source = g_timeout_source_new_seconds (3);
5e6360
+		g_source_set_callback (
5e6360
+			server->priv->file_monitor_source,
5e6360
+			source_registry_server_process_file_monitor_events_cb,
5e6360
+			server, NULL);
5e6360
+		g_source_attach (
5e6360
+			server->priv->file_monitor_source,
5e6360
+			server->priv->main_context);
5e6360
+
5e6360
+		g_mutex_unlock (&server->priv->file_monitor_lock);
5e6360
+	}
5e6360
+}
5e6360
+
5e6360
+static gboolean
5e6360
 source_registry_server_traverse_cb (GNode *node,
5e6360
                                     GQueue *queue)
5e6360
 {
5e6360
@@ -1047,6 +1202,14 @@ source_registry_server_dispose (GObject
5e6360
 
5e6360
 	priv = E_SOURCE_REGISTRY_SERVER_GET_PRIVATE (object);
5e6360
 
5e6360
+	g_mutex_lock (&priv->file_monitor_lock);
5e6360
+	if (priv->file_monitor_source) {
5e6360
+		g_source_destroy (priv->file_monitor_source);
5e6360
+		g_source_unref (priv->file_monitor_source);
5e6360
+		priv->file_monitor_source = NULL;
5e6360
+	}
5e6360
+	g_mutex_unlock (&priv->file_monitor_lock);
5e6360
+
5e6360
 	if (priv->main_context != NULL) {
5e6360
 		g_main_context_unref (priv->main_context);
5e6360
 		priv->main_context = NULL;
5e6360
@@ -1065,6 +1228,7 @@ source_registry_server_dispose (GObject
5e6360
 	g_hash_table_remove_all (priv->sources);
5e6360
 	g_hash_table_remove_all (priv->orphans);
5e6360
 	g_hash_table_remove_all (priv->monitors);
5e6360
+	g_hash_table_remove_all (priv->file_monitor_events);
5e6360
 
5e6360
 	g_hash_table_remove_all (priv->running_auths);
5e6360
 	g_hash_table_remove_all (priv->waiting_auths);
5e6360
@@ -1084,9 +1248,11 @@ source_registry_server_finalize (GObject
5e6360
 	g_hash_table_destroy (priv->sources);
5e6360
 	g_hash_table_destroy (priv->orphans);
5e6360
 	g_hash_table_destroy (priv->monitors);
5e6360
+	g_hash_table_destroy (priv->file_monitor_events);
5e6360
 
5e6360
 	g_mutex_clear (&priv->sources_lock);
5e6360
 	g_mutex_clear (&priv->orphans_lock);
5e6360
+	g_mutex_clear (&priv->file_monitor_lock);
5e6360
 
5e6360
 	g_mutex_clear (&priv->auth_lock);
5e6360
 	g_hash_table_destroy (priv->running_auths);
0da626
@@ -1444,8 +1444,10 @@ e_source_registry_server_init (ESourceRegistryServ
0da626
 	g_mutex_init (&server->priv->sources_lock);
0da626
 	g_mutex_init (&server->priv->orphans_lock);
0da626
 	g_mutex_init (&server->priv->auth_lock);
0da626
+	g_mutex_init (&server->priv->file_monitor_lock);
0da626
 	server->priv->waiting_auths = waiting_auths;
0da626
 	server->priv->running_auths = running_auths;
0da626
+	server->priv->file_monitor_events = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, file_event_data_free);
0da626
 
0da626
 	g_signal_connect (
0da626
 		source_manager, "handle-allow-auth-prompt-all",
5e6360
diff -up evolution-data-server-3.12.11/libedataserver/e-source.c.goa-source-change-removed evolution-data-server-3.12.11/libedataserver/e-source.c
5e6360
--- evolution-data-server-3.12.11/libedataserver/e-source.c.goa-source-change-removed	2015-08-17 16:55:07.344936312 +0200
5e6360
+++ evolution-data-server-3.12.11/libedataserver/e-source.c	2015-08-17 16:55:07.402935838 +0200
5e6360
@@ -126,9 +126,6 @@ struct _ESourcePrivate {
5e6360
 	GSource *changed;
5e6360
 	GMutex changed_lock;
5e6360
 
5e6360
-	GSource *data_change;
5e6360
-	GMutex data_change_lock;
5e6360
-
5e6360
 	GMutex property_lock;
5e6360
 
5e6360
 	gchar *display_name;
5e6360
@@ -790,26 +787,13 @@ source_parse_dbus_data (ESource *source,
5e6360
 	return TRUE;
5e6360
 }
5e6360
 
5e6360
-static gboolean
5e6360
-source_idle_data_change_cb (gpointer user_data)
5e6360
+static void
5e6360
+source_notify_dbus_data_cb (EDBusSource *dbus_source,
5e6360
+                            GParamSpec *pspec,
5e6360
+                            ESource *source)
5e6360
 {
5e6360
-	ESource *source = E_SOURCE (user_data);
5e6360
 	GError *local_error = NULL;
5e6360
 
5e6360
-	/* If the ESource is still initializing itself in a different
5e6360
-	 * thread, skip the signal emission and try again on the next
5e6360
-	 * main loop iteration. This is a busy wait but it should be
5e6360
-	 * a very short wait. */
5e6360
-	if (!source->priv->initialized)
5e6360
-		return TRUE;
5e6360
-
5e6360
-	g_mutex_lock (&source->priv->data_change_lock);
5e6360
-	if (source->priv->data_change != NULL) {
5e6360
-		g_source_unref (source->priv->data_change);
5e6360
-		source->priv->data_change = NULL;
5e6360
-	}
5e6360
-	g_mutex_unlock (&source->priv->data_change_lock);
5e6360
-
5e6360
 	g_rec_mutex_lock (&source->priv->lock);
5e6360
 
5e6360
 	/* Since the source data came from a GKeyFile structure on the
5e6360
@@ -823,27 +807,6 @@ source_idle_data_change_cb (gpointer use
5e6360
 	}
5e6360
 
5e6360
 	g_rec_mutex_unlock (&source->priv->lock);
5e6360
-
5e6360
-	return FALSE;
5e6360
-}
5e6360
-
5e6360
-static void
5e6360
-source_notify_dbus_data_cb (EDBusSource *dbus_source,
5e6360
-                            GParamSpec *pspec,
5e6360
-                            ESource *source)
5e6360
-{
5e6360
-	g_mutex_lock (&source->priv->data_change_lock);
5e6360
-	if (source->priv->data_change == NULL) {
5e6360
-		source->priv->data_change = g_idle_source_new ();
5e6360
-		g_source_set_callback (
5e6360
-			source->priv->data_change,
5e6360
-			source_idle_data_change_cb,
5e6360
-			source, NULL);
5e6360
-		g_source_attach (
5e6360
-			source->priv->data_change,
5e6360
-			source->priv->main_context);
5e6360
-	}
5e6360
-	g_mutex_unlock (&source->priv->data_change_lock);
5e6360
 }
5e6360
 
5e6360
 static gboolean
5e6360
@@ -1066,14 +1029,6 @@ source_dispose (GObject *object)
5e6360
 	}
5e6360
 	g_mutex_unlock (&priv->changed_lock);
5e6360
 
5e6360
-	g_mutex_lock (&priv->data_change_lock);
5e6360
-	if (priv->data_change != NULL) {
5e6360
-		g_source_destroy (priv->data_change);
5e6360
-		g_source_unref (priv->data_change);
5e6360
-		priv->data_change = NULL;
5e6360
-	}
5e6360
-	g_mutex_unlock (&priv->data_change_lock);
5e6360
-
5e6360
 	g_hash_table_remove_all (priv->extensions);
5e6360
 
5e6360
 	/* Chain up to parent's dispose() method. */
5e6360
@@ -1088,7 +1043,6 @@ source_finalize (GObject *object)
5e6360
 	priv = E_SOURCE_GET_PRIVATE (object);
5e6360
 
5e6360
 	g_mutex_clear (&priv->changed_lock);
5e6360
-	g_mutex_clear (&priv->data_change_lock);
5e6360
 	g_mutex_clear (&priv->property_lock);
5e6360
 
5e6360
 	g_free (priv->display_name);
5e6360
@@ -2092,7 +2046,6 @@ e_source_init (ESource *source)
5e6360
 
5e6360
 	source->priv = E_SOURCE_GET_PRIVATE (source);
5e6360
 	g_mutex_init (&source->priv->changed_lock);
5e6360
-	g_mutex_init (&source->priv->data_change_lock);
5e6360
 	g_mutex_init (&source->priv->property_lock);
5e6360
 	source->priv->key_file = g_key_file_new ();
5e6360
 	source->priv->extensions = extensions;