[evolution-data-server] Revert "Revert "Make network connection change listener actually working""



commit 8c1c183ee945452f66e2da74faf16406a08e4327
Author: Milan Crha <mcrha redhat com>
Date:   Thu Feb 21 16:41:06 2013 +0100

    Revert "Revert "Make network connection change listener actually working""
    
    This reverts commit 51f5b1201bb713243b0cb2e160c18ee17d3a0baf.
    
    It's inappropriate to revert whole commit, the relevant part is much
    much much smaller.

 libebackend/e-backend.c |  116 +++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 97 insertions(+), 19 deletions(-)
---
diff --git a/libebackend/e-backend.c b/libebackend/e-backend.c
index 6a291e5..c22fc29 100644
--- a/libebackend/e-backend.c
+++ b/libebackend/e-backend.c
@@ -62,6 +62,7 @@ struct _EBackendPrivate {
 
        GNetworkMonitor *network_monitor;
        gulong network_changed_handler_id;
+       guint network_changed_timeout_id;
 
        GMutex network_monitor_cancellable_lock;
        GCancellable *network_monitor_cancellable;
@@ -90,6 +91,27 @@ async_context_free (AsyncContext *async_context)
        g_slice_free (AsyncContext, async_context);
 }
 
+struct UpdateOnlineData
+{
+       EBackend *backend;
+       gboolean is_online;
+};
+
+static gpointer
+set_backend_online_thread (gpointer user_data)
+{
+       struct UpdateOnlineData *uod = user_data;
+
+       g_return_val_if_fail (uod != NULL, NULL);
+
+       e_backend_set_online (uod->backend, uod->is_online);
+
+       g_object_unref (uod->backend);
+       g_slice_free (struct UpdateOnlineData, uod);
+
+       return NULL;
+}
+
 static void
 backend_network_monitor_can_reach_cb (GObject *source_object,
                                       GAsyncResult *result,
@@ -97,6 +119,8 @@ backend_network_monitor_can_reach_cb (GObject *source_object,
 {
        EBackend *backend = E_BACKEND (user_data);
        gboolean host_is_reachable;
+       struct UpdateOnlineData *uod;
+       GThread *thread;
        GError *error = NULL;
 
        host_is_reachable = g_network_monitor_can_reach_finish (
@@ -107,26 +131,22 @@ backend_network_monitor_can_reach_cb (GObject *source_object,
                (host_is_reachable && (error == NULL)) ||
                (!host_is_reachable && (error != NULL)));
 
-       if (host_is_reachable) {
-               e_backend_set_online (backend, TRUE);
-
-       } else if (G_IS_IO_ERROR (error, G_IO_ERROR_CANCELLED)) {
-               /* Ignore cancellations. */
-
-       } else if (G_IS_IO_ERROR (error, G_IO_ERROR_HOST_UNREACHABLE)) {
-               e_backend_set_online (backend, FALSE);
-
-       } else if (G_IS_RESOLVER_ERROR (error, G_RESOLVER_ERROR_NOT_FOUND)) {
-               e_backend_set_online (backend, FALSE);
-
-       } else {
-               g_warning ("%s: %s", G_STRFUNC, error->message);
+       if (G_IS_IO_ERROR (error, G_IO_ERROR_CANCELLED) ||
+           (host_is_reachable ? 1 : 0) == (e_backend_get_online (backend) ? 1 : 0)) {
+               g_clear_error (&error);
+               g_object_unref (backend);
+               return;
        }
 
-       if (error != NULL)
-               g_error_free (error);
+       g_clear_error (&error);
+
+       uod = g_slice_new (struct UpdateOnlineData);
+       uod->backend = backend;
+       uod->is_online = host_is_reachable;
 
-       g_object_unref (backend);
+       /* do this in a separate thread, not the main thread */
+       thread = g_thread_new (NULL, set_backend_online_thread, uod);
+       g_thread_unref (thread);
 }
 
 static void
@@ -148,6 +168,36 @@ backend_update_online_state (EBackend *backend)
                cancellable = NULL;
        }
 
+       if (connectable && G_IS_NETWORK_ADDRESS (connectable)) {
+               GNetworkAddress *network_address = G_NETWORK_ADDRESS (connectable);
+
+               /* create copy of the backend's connectable, because once the connectable
+                  reaches its destination it caches the value and doesn't retry after
+                  network changes.
+
+                  This should be eventually replaced with default implementation
+                  of EBackend::get_destination_address() doing basically the same
+                  what currently does the backend silently on construction, thus
+                  it'll get also current values from the ESource, not stale from
+                  construct time.
+               */
+               connectable = g_network_address_new (
+                       g_network_address_get_hostname (network_address),
+                       g_network_address_get_port (network_address));
+
+               g_object_unref (network_address);
+       }
+
+       if (!connectable) {
+               gchar *host = NULL;
+               guint16 port = 0;
+
+               if (e_backend_get_destination_address (backend, &host, &port) && host)
+                       connectable = g_network_address_new (host, port);
+
+               g_free (host);
+       }
+
        if (connectable == NULL) {
                e_backend_set_online (backend, TRUE);
        } else {
@@ -168,12 +218,30 @@ backend_update_online_state (EBackend *backend)
                g_object_unref (connectable);
 }
 
+static gboolean
+backend_network_changed_timeout_cb (gpointer user_data)
+{
+       EBackend *backend = user_data;
+
+       if (!g_source_is_destroyed (g_main_current_source ())) {
+               backend->priv->network_changed_timeout_id = 0;
+
+               backend_update_online_state (backend);
+       }
+
+       return FALSE;
+}
+
 static void
 backend_network_changed_cb (GNetworkMonitor *network_monitor,
                             gboolean network_available,
                             EBackend *backend)
 {
-       backend_update_online_state (backend);
+       if (backend->priv->network_changed_timeout_id)
+               g_source_remove (backend->priv->network_changed_timeout_id);
+
+       /* wait few seconds, a network change can fire this event multiple times */
+       backend->priv->network_changed_timeout_id = g_timeout_add_seconds (3, 
backend_network_changed_timeout_cb, backend);
 }
 
 static void
@@ -264,6 +332,11 @@ backend_dispose (GObject *object)
                priv->network_changed_handler_id = 0;
        }
 
+       if (priv->network_changed_timeout_id) {
+               g_source_remove (priv->network_changed_timeout_id);
+               priv->network_changed_timeout_id = 0;
+       }
+
        g_clear_object (&priv->source);
        g_clear_object (&priv->prompter);
        g_clear_object (&priv->connectable);
@@ -284,6 +357,11 @@ backend_finalize (GObject *object)
        g_mutex_clear (&priv->property_lock);
        g_mutex_clear (&priv->network_monitor_cancellable_lock);
 
+       if (priv->network_changed_timeout_id) {
+               g_source_remove (priv->network_changed_timeout_id);
+               priv->network_changed_timeout_id = 0;
+       }
+
        /* Chain up to parent's finalize() method. */
        G_OBJECT_CLASS (e_backend_parent_class)->finalize (object);
 }
@@ -986,7 +1064,7 @@ e_backend_is_destination_reachable (EBackend *backend,
                        GNetworkMonitor *network_monitor;
                        GSocketConnectable *connectable;
 
-                       network_monitor = g_network_monitor_get_default ();
+                       network_monitor = backend->priv->network_monitor;
 
                        connectable = g_network_address_new (host, port);
                        if (connectable) {


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