[telepathy-glib/f17] Backport patch that gives features a second chance to be prepared.

Brian Pepple bpepple at fedoraproject.org
Thu Jun 21 13:52:33 UTC 2012


commit 258eff4db67072db8bbde678f7def05259a08514
Author: Brian Pepple <bpepple at fedoraproject.org>
Date:   Thu Jun 21 09:52:23 2012 -0400

    Backport patch that gives features a second chance to be prepared.

 retry_features.patch |  257 ++++++++++++++++++++++++++++++++++++++++++++++++++
 telepathy-glib.spec  |    7 +-
 2 files changed, 263 insertions(+), 1 deletions(-)
---
diff --git a/retry_features.patch b/retry_features.patch
new file mode 100644
index 0000000..399c776
--- /dev/null
+++ b/retry_features.patch
@@ -0,0 +1,257 @@
+From 5d2f1f6a6b491a9eb05ff0013a258471d59248de Mon Sep 17 00:00:00 2001
+From: Guillaume Desmottes <guillaume.desmottes at collabora.co.uk>
+Date: Wed, 16 Nov 2011 13:23:21 +0000
+Subject: Retry to prepare features which failed because of a missing conn iface
+
+If we try to prepare a connection feature before the connection is connected,
+the preparation may fall if a required interface hasn't been announced yet by
+the CM. So, we give those features a second chance to be prepared when the
+connection has been connected.
+
+https://bugs.freedesktop.org/show_bug.cgi?id=42981
+---
+diff --git a/telepathy-glib/proxy.c b/telepathy-glib/proxy.c
+index 4e8e839..6533877 100644
+--- a/telepathy-glib/proxy.c
++++ b/telepathy-glib/proxy.c
+@@ -323,6 +323,11 @@ typedef enum {
+     FEATURE_STATE_WANTED,
+     /* Want to prepare, have called prepare_async */
+     FEATURE_STATE_TRYING,
++    /* Couldn't prepare because a required interface on the connection
++     * was missing and the connection wasn't connected yet. We'll retry to
++     * prepare once the connection is connected.
++     * This state is only used when preparing Connection features */
++    FEATURE_STATE_MISSING_IFACE,
+     /* Couldn't prepare, gave up */
+     FEATURE_STATE_FAILED,
+     /* Prepared */
+@@ -1789,6 +1794,7 @@ check_depends_ready (TpProxy *self,
+             return FALSE;
+ 
+           case FEATURE_STATE_FAILED:
++          case FEATURE_STATE_MISSING_IFACE:
+             if (!can_retry || !dep_feature->can_retry)
+               {
+                 DEBUG ("Can't prepare %s, because %s (a dependency) is "
+@@ -2089,8 +2095,21 @@ request_is_complete (TpProxy *self,
+                  * in tp_proxy_prepare_async() as CORE have to be prepared */
+                 if (!check_feature_interfaces (self, feature))
+                   {
+-                    tp_proxy_set_feature_state (self, feature,
+-                        FEATURE_STATE_FAILED);
++                    if (TP_IS_CONNECTION (self) &&
++                        tp_connection_get_status ((TpConnection *) self, NULL)
++                        != TP_CONNECTION_STATUS_CONNECTED)
++                      {
++                        /* Give a chance to retry preparing the feature once
++                         * the Connection is connected as it may still gain
++                         * the interface. */
++                        tp_proxy_set_feature_state (self, feature,
++                            FEATURE_STATE_MISSING_IFACE);
++                      }
++                    else
++                      {
++                        tp_proxy_set_feature_state (self, feature,
++                            FEATURE_STATE_FAILED);
++                      }
+                     continue;
+                   }
+ 
+@@ -2126,6 +2145,7 @@ request_is_complete (TpProxy *self,
+ 
+           case FEATURE_STATE_INVALID:
+           case FEATURE_STATE_FAILED:
++          case FEATURE_STATE_MISSING_IFACE:
+           case FEATURE_STATE_READY:
+             /* nothing more to do */
+             break;
+@@ -2318,20 +2338,34 @@ static void foreach_feature (GQuark name,
+ {
+   FeatureState state = GPOINTER_TO_INT (data);
+   TpProxy *self = user_data;
+-  const TpProxyFeature *feature;
+ 
+-  if (state != FEATURE_STATE_READY)
+-    return;
++  if (state == FEATURE_STATE_MISSING_IFACE)
++    {
++      GQuark features[] = { 0, 0};
+ 
+-  feature = tp_proxy_subclass_get_feature (G_OBJECT_TYPE (self), name);
++      tp_proxy_set_feature_state (self, name, FEATURE_STATE_UNWANTED);
+ 
+-  if (feature->prepare_before_signalling_connected_async == NULL)
+-    return;
++      self->priv->pending_will_announce_calls++;
+ 
+-  self->priv->pending_will_announce_calls++;
++      features[0] = name;
+ 
+-  feature->prepare_before_signalling_connected_async (self, feature,
+-      prepare_before_signalling_connected_cb, self);
++      tp_proxy_prepare_async (self, features,
++          prepare_before_signalling_connected_cb, self);
++    }
++  else if (state == FEATURE_STATE_READY)
++    {
++      const TpProxyFeature *feature;
++
++      feature = tp_proxy_subclass_get_feature (G_OBJECT_TYPE (self), name);
++
++      if (feature->prepare_before_signalling_connected_async == NULL)
++        return;
++
++      self->priv->pending_will_announce_calls++;
++
++      feature->prepare_before_signalling_connected_async (self, feature,
++          prepare_before_signalling_connected_cb, self);
++    }
+ }
+ 
+ /*
+diff --git a/tests/dbus/proxy-preparation.c b/tests/dbus/proxy-preparation.c
+index df4b1b7..7d7638f 100644
+--- a/tests/dbus/proxy-preparation.c
++++ b/tests/dbus/proxy-preparation.c
+@@ -368,6 +368,43 @@ test_before_connected (Test *test,
+       BEFORE_CONNECTED_STATE_CONNECTED);
+ }
+ 
++static void
++test_interface_later (Test *test,
++    gconstpointer data G_GNUC_UNUSED)
++{
++  GQuark features[] = { TP_TESTS_MY_CONN_PROXY_FEATURE_INTERFACE_LATER, 0 };
++  GQuark connected[] = { TP_CONNECTION_FEATURE_CONNECTED, 0 };
++  const gchar *interfaces[] = { TP_TESTS_MY_CONN_PROXY_IFACE_LATER, NULL };
++
++  /* We need a not yet connected connection */
++  recreate_connection (test);
++
++  /* Try preparing before the connection is connected */
++  tp_proxy_prepare_async (test->my_conn, features, prepare_cb, test);
++
++  g_main_loop_run (test->mainloop);
++  g_assert_no_error (test->error);
++
++  /* Feature isn't prepared */
++  g_assert (!tp_proxy_is_prepared (test->my_conn,
++        TP_TESTS_MY_CONN_PROXY_FEATURE_INTERFACE_LATER));
++
++  tp_cli_connection_call_connect (test->connection, -1, NULL, NULL, NULL, NULL);
++
++  /* While connecting the interface is added */
++  tp_base_connection_add_interfaces (test->base_connection, interfaces);
++
++  /* Wait that CONNECTED is announced */
++  tp_proxy_prepare_async (test->my_conn, connected, prepare_cb, test);
++
++  g_main_loop_run (test->mainloop);
++  g_assert_no_error (test->error);
++
++  /* The feature has been prepared now */
++  g_assert (tp_proxy_is_prepared (test->my_conn,
++        TP_TESTS_MY_CONN_PROXY_FEATURE_INTERFACE_LATER));
++}
++
+ int
+ main (int argc,
+       char **argv)
+@@ -395,6 +432,8 @@ main (int argc,
+       test_retry_dep, teardown);
+   g_test_add ("/proxy-preparation/before-connected", Test, NULL, setup,
+       test_before_connected, teardown);
++  g_test_add ("/proxy-preparation/interface-later", Test, NULL, setup,
++      test_interface_later, teardown);
+ 
+   return g_test_run ();
+ }
+diff --git a/tests/lib/my-conn-proxy.c b/tests/lib/my-conn-proxy.c
+index 208f004..d7748f3 100644
+--- a/tests/lib/my-conn-proxy.c
++++ b/tests/lib/my-conn-proxy.c
+@@ -33,6 +33,7 @@ enum {
+     FEAT_RETRY,
+     FEAT_RETRY_DEP,
+     FEAT_BEFORE_CONNECTED,
++    FEAT_INTERFACE_LATER,
+     N_FEAT
+ };
+ 
+@@ -203,6 +204,21 @@ prepare_before_connected_before_async (TpProxy *proxy,
+   g_object_unref (result);
+ }
+ 
++static void
++prepare_interface_later_async (TpProxy *proxy,
++    const TpProxyFeature *feature,
++    GAsyncReadyCallback callback,
++    gpointer user_data)
++{
++  GSimpleAsyncResult *result;
++
++  result = g_simple_async_result_new ((GObject *) proxy, callback, user_data,
++      prepare_interface_later_async);
++
++  g_simple_async_result_complete_in_idle (result);
++  g_object_unref (result);
++}
++
+ static const TpProxyFeature *
+ list_features (TpProxyClass *cls G_GNUC_UNUSED)
+ {
+@@ -212,6 +228,7 @@ list_features (TpProxyClass *cls G_GNUC_UNUSED)
+   static GQuark need_wrong_iface[2] = {0, 0};
+   static GQuark need_fail[2] = {0, 0};
+   static GQuark need_retry[2] = {0, 0};
++  static GQuark need_iface_later[2] = {0, 0};
+ 
+   if (G_LIKELY (features[0].name != 0))
+     return features;
+@@ -262,6 +279,13 @@ list_features (TpProxyClass *cls G_GNUC_UNUSED)
+   features[FEAT_BEFORE_CONNECTED].prepare_before_signalling_connected_async =
+     prepare_before_connected_before_async;
+ 
++  features[FEAT_INTERFACE_LATER].name =
++    TP_TESTS_MY_CONN_PROXY_FEATURE_INTERFACE_LATER;
++  features[FEAT_INTERFACE_LATER].prepare_async = prepare_interface_later_async;
++  need_iface_later[0] = g_quark_from_static_string (
++      TP_TESTS_MY_CONN_PROXY_IFACE_LATER);
++  features[FEAT_INTERFACE_LATER].interfaces_needed = need_iface_later;
++
+   return features;
+ }
+ 
+@@ -332,3 +356,9 @@ tp_tests_my_conn_proxy_get_feature_quark_before_connected (void)
+ {
+   return g_quark_from_static_string ("tp-my-conn-proxy-feature-before-connected");
+ }
++
++GQuark
++tp_tests_my_conn_proxy_get_feature_quark_interface_later (void)
++{
++  return g_quark_from_static_string ("tp-my-conn-proxy-feature-interface-later");
++}
+diff --git a/tests/lib/my-conn-proxy.h b/tests/lib/my-conn-proxy.h
+index cfc8216..08be18b 100644
+--- a/tests/lib/my-conn-proxy.h
++++ b/tests/lib/my-conn-proxy.h
+@@ -110,6 +110,15 @@ GQuark tp_tests_my_conn_proxy_get_feature_quark_retry_dep (void) G_GNUC_CONST;
+   (tp_tests_my_conn_proxy_get_feature_quark_before_connected ())
+ GQuark tp_tests_my_conn_proxy_get_feature_quark_before_connected (void) G_GNUC_CONST;
+ 
++#define TP_TESTS_MY_CONN_PROXY_IFACE_LATER "org.freedesktop.Telepathy.Conncetion.Interface.Test.Later"
++
++/* Need the interface TP_TESTS_MY_CONN_PROXY_IFACE_LATER to be prepared but
++ * this interface is not in the initial set of interfaces of the connection.
++ * It is added when the connection is connected. */
++#define TP_TESTS_MY_CONN_PROXY_FEATURE_INTERFACE_LATER \
++  (tp_tests_my_conn_proxy_get_feature_quark_interface_later ())
++GQuark tp_tests_my_conn_proxy_get_feature_quark_interface_later (void) G_GNUC_CONST;
++
+ G_END_DECLS
+ 
+ #endif /* #ifndef __TP_TESTS_MY_CONN_PROXY_H__ */
+--
+cgit v0.9.0.2-2-gbebe
diff --git a/telepathy-glib.spec b/telepathy-glib.spec
index 822dd27..983ff9e 100644
--- a/telepathy-glib.spec
+++ b/telepathy-glib.spec
@@ -6,13 +6,14 @@
 
 Name:           telepathy-glib
 Version:        0.18.1
-Release:        1%{?dist}
+Release:        2%{?dist}
 Summary:        GLib bindings for Telepathy
 
 Group:          System Environment/Libraries
 License:        LGPLv2+
 URL:            http://telepathy.freedesktop.org/wiki/FrontPage
 Source0:        http://telepathy.freedesktop.org/releases/%{name}/%{name}-%{version}.tar.gz
+Patch0:         retry_features.patch
 
 BuildRequires:  gtk-doc >= 1.17
 BuildRequires:  dbus-devel >= %{dbus_ver}
@@ -60,6 +61,7 @@ developing applications that use %{name}.
 
 %prep
 %setup -q
+%patch0 -p1 -b .features
 
 
 %check
@@ -106,6 +108,9 @@ find $RPM_BUILD_ROOT -name '*.la' -exec rm -f {} ';'
 
 
 %changelog
+* Thu Jun 21 2012 Brian Pepple <bpepple at fedoraproject.org> - 0.18.1-2
+- Backport patch that gives features a second chance to be prepared.
+
 * Sat Apr 21 2012 Brian Pepple <bpepple at fedoraproject.org> - 0.18.1-1
 - Update to 0.18.1.
 


More information about the scm-commits mailing list