[Telepathy-commits] [telepathy-glib/master] contacts_got_attributes, contacts_get_attributes: refactor so we work correctly if the method is not by_handle

Simon McVittie simon.mcvittie at collabora.co.uk
Mon Dec 1 03:13:57 PST 2008


We want to ref the handles if and only if we started from handles - if
we started from IDs, RequestHandles refs them, and if we started from
contacts, they're already referenced anyway.
---
 telepathy-glib/contact.c |  185 ++++++++++++++++++++++++++--------------------
 1 files changed, 106 insertions(+), 79 deletions(-)

diff --git a/telepathy-glib/contact.c b/telepathy-glib/contact.c
index e6ab7e4..66b348c 100644
--- a/telepathy-glib/contact.c
+++ b/telepathy-glib/contact.c
@@ -1604,104 +1604,128 @@ contacts_got_attributes (TpConnection *connection,
 
   i = 0;
 
-  while (i < c->handles->len)
+  if (c->signature == CB_BY_HANDLE)
     {
-      TpHandle handle = g_array_index (c->handles, guint, i);
-      GHashTable *asv = g_hash_table_lookup (attributes,
-          GUINT_TO_POINTER (handle));
+      g_assert (c->contacts->len == 0);
 
-      if (asv == NULL)
-        {
-          /* not in the hash table => not valid */
-          g_array_append_val (c->invalid, handle);
-          g_array_remove_index_fast (c->handles, i);
-        }
-      else
+      while (i < c->handles->len)
         {
-          TpContact *contact = NULL;
-          guint j;
-          const gchar *s;
-          gpointer boxed;
-
-          /* we might already have consumed the only reference we have to
-           * the handle - if we have, we must recycle the same object rather
-           * than calling tp_contact_ensure again */
-          for (j = 0; j < i; j++)
+          TpHandle handle = g_array_index (c->handles, guint, i);
+          GHashTable *asv = g_hash_table_lookup (attributes,
+              GUINT_TO_POINTER (handle));
+
+          if (asv == NULL)
+            {
+              /* not in the hash table => not valid */
+              g_array_append_val (c->invalid, handle);
+              g_array_remove_index_fast (c->handles, i);
+            }
+          else
             {
-              if (handle == g_array_index (c->handles, guint, j))
+              TpContact *contact = NULL;
+              guint j;
+
+              /* we might already have consumed the only reference we have to
+               * the handle - if we have, we must recycle the same object
+               * rather than calling tp_contact_ensure again */
+              for (j = 0; j < i; j++)
                 {
-                  contact = g_object_ref (g_ptr_array_index (c->contacts, j));
+                  if (handle == g_array_index (c->handles, guint, j))
+                    {
+                      contact = g_object_ref (g_ptr_array_index (c->contacts,
+                            j));
+                    }
                 }
-            }
 
-          if (contact == NULL)
-            contact = tp_contact_ensure (connection, handle);
+              if (contact == NULL)
+                contact = tp_contact_ensure (connection, handle);
 
-          /* set up the contact with its attributes */
+              g_ptr_array_add (c->contacts, contact);
 
-          s = tp_asv_get_string (asv,
-              TP_IFACE_CONNECTION "/contact-id");
+              /* save the contact and move on to the next handle */
+              i++;
+            }
+        }
+    }
 
-          if (s == NULL)
-            {
-              GError *e = g_error_new (TP_DBUS_ERRORS,
-                  TP_DBUS_ERROR_INCONSISTENT,
-                  "Connection manager %s is broken: contact #%u in "
-                  "the GetContactAttributes result has no contact-id",
-                  tp_proxy_get_bus_name (connection), handle);
+  g_assert (c->contacts->len == c->handles->len);
 
-              contacts_context_fail (c, e);
-              g_error_free (e);
-              g_object_unref (contact);
-              return;
-            }
-          else if (contact->priv->identifier == NULL)
-            {
-              contact->priv->identifier = g_strdup (s);
-            }
-          else if (tp_strdiff (contact->priv->identifier, s))
-            {
-              GError *e = g_error_new (TP_DBUS_ERRORS,
-                  TP_DBUS_ERROR_INCONSISTENT,
-                  "Connection manager %s is broken: contact #%u "
-                  "identifier changed from %s to %s",
-                  tp_proxy_get_bus_name (connection), handle,
-                  contact->priv->identifier, s);
+  for (i = 0; i < c->handles->len; i++)
+    {
+      TpContact *contact = g_ptr_array_index (c->contacts, i);
+      const gchar *s;
+      gpointer boxed;
+      GHashTable *asv = g_hash_table_lookup (attributes,
+          GUINT_TO_POINTER (contact->priv->handle));
 
-              contacts_context_fail (c, e);
-              g_error_free (e);
-              g_object_unref (contact);
-              return;
-            }
+      if (asv == NULL)
+        {
+          GError *e = g_error_new (TP_DBUS_ERRORS, TP_DBUS_ERROR_INCONSISTENT,
+              "We hold a ref to handle #%u but it appears to be invalid",
+              contact->priv->handle);
 
-          s = tp_asv_get_string (asv,
-              TP_IFACE_CONNECTION_INTERFACE_ALIASING "/alias");
+          contacts_context_fail (c, e);
+          g_error_free (e);
+          return;
+        }
 
-          if (s != NULL)
-            {
-              contact->priv->has_features |= CONTACT_FEATURE_FLAG_ALIAS;
-              g_free (contact->priv->alias);
-              contact->priv->alias = g_strdup (s);
-              g_object_notify ((GObject *) contact, "alias");
-            }
+      /* set up the contact with its attributes */
 
-          s = tp_asv_get_string (asv,
-              TP_IFACE_CONNECTION_INTERFACE_AVATARS "/token");
+      s = tp_asv_get_string (asv, TP_IFACE_CONNECTION "/contact-id");
 
-          if (s != NULL)
-            contacts_avatar_updated (connection, handle, s, NULL, NULL);
+      if (s == NULL)
+        {
+          GError *e = g_error_new (TP_DBUS_ERRORS, TP_DBUS_ERROR_INCONSISTENT,
+              "Connection manager %s is broken: contact #%u in the "
+              "GetContactAttributes result has no contact-id",
+              tp_proxy_get_bus_name (connection), contact->priv->handle);
 
-          boxed = tp_asv_get_boxed (asv,
-              TP_IFACE_CONNECTION_INTERFACE_SIMPLE_PRESENCE "/presence",
-              TP_STRUCT_TYPE_SIMPLE_PRESENCE);
-          contact_maybe_set_simple_presence (contact, boxed);
+          contacts_context_fail (c, e);
+          g_error_free (e);
+          return;
+        }
 
-          /* FIXME: TP_IFACE_CONNECTION_INTERFACE_CAPABILITIES "/caps" */
+      if (contact->priv->identifier == NULL)
+        {
+          contact->priv->identifier = g_strdup (s);
+        }
+      else if (tp_strdiff (contact->priv->identifier, s))
+        {
+          GError *e = g_error_new (TP_DBUS_ERRORS, TP_DBUS_ERROR_INCONSISTENT,
+              "Connection manager %s is broken: contact #%u identifier "
+              "changed from %s to %s",
+              tp_proxy_get_bus_name (connection), contact->priv->handle,
+              contact->priv->identifier, s);
+
+          contacts_context_fail (c, e);
+          g_error_free (e);
+          return;
+        }
 
-          /* save the contact and move on to the next handle */
-          g_ptr_array_add (c->contacts, contact);
-          i++;
+      s = tp_asv_get_string (asv,
+          TP_IFACE_CONNECTION_INTERFACE_ALIASING "/alias");
+
+      if (s != NULL)
+        {
+          contact->priv->has_features |= CONTACT_FEATURE_FLAG_ALIAS;
+          g_free (contact->priv->alias);
+          contact->priv->alias = g_strdup (s);
+          g_object_notify ((GObject *) contact, "alias");
         }
+
+      s = tp_asv_get_string (asv,
+          TP_IFACE_CONNECTION_INTERFACE_AVATARS "/token");
+
+      if (s != NULL)
+        contacts_avatar_updated (connection, contact->priv->handle, s,
+            NULL, NULL);
+
+      boxed = tp_asv_get_boxed (asv,
+          TP_IFACE_CONNECTION_INTERFACE_SIMPLE_PRESENCE "/presence",
+          TP_STRUCT_TYPE_SIMPLE_PRESENCE);
+      contact_maybe_set_simple_presence (contact, boxed);
+
+      /* FIXME: TP_IFACE_CONNECTION_INTERFACE_CAPABILITIES "/caps" */
     }
 
   contacts_context_continue (c);
@@ -1758,10 +1782,13 @@ contacts_get_attributes (ContactsContext *context)
   g_ptr_array_add (array, NULL);
   supported_interfaces = (const gchar **) g_ptr_array_free (array, FALSE);
 
+  /* we want to hold the handles if and only if the call is by_handle -
+   * for the other modes, we already have handles */
   context->refcount++;
   tp_connection_get_contact_attributes (context->connection, -1,
       context->handles->len, (const TpHandle *) context->handles->data,
-      supported_interfaces, TRUE, contacts_got_attributes,
+      supported_interfaces, (context->signature == CB_BY_HANDLE),
+      contacts_got_attributes,
       context, contacts_context_unref, context->weak_object);
   g_free (supported_interfaces);
 }
-- 
1.5.6.5




More information about the Telepathy-commits mailing list