[Bug 31583] Expose TpProxyFeature in the API
bugzilla-daemon at freedesktop.org
bugzilla-daemon at freedesktop.org
Thu Jan 27 14:59:44 CET 2011
https://bugs.freedesktop.org/show_bug.cgi?id=31583
--- Comment #15 from Guillaume Desmottes <guillaume.desmottes at collabora.co.uk> 2011-01-27 05:59:44 PST ---
(In reply to comment #14)
> 225dbfc:
>
> + case FEATURE_STATE_UNWANTED:
> + /* this can only happen in the special pseudo-request for the
> + * core features, which blocks everything */
> + g_assert (req == self->priv->prepare_core);
> + wait = TRUE;
> + break;
> +
> + /* fall through to treat it as WANTED */
>
> That does not look like a fall through to me. This later moved into
> request_is_complete(). And then was fixed! I bet you left this in to test me.
> ;-)
Oops, I guess I forgot to squash the fix, nice catch! :)
> a5adfbb:
>
> @@ -649,7 +676,8 @@ get_pending_messages_cb (TpProxy *proxy,
> gpointer user_data,
> GObject *weak_object)
> {
> - TpTextChannel *self = user_data;
> + TpTextChannel *self = (TpTextChannel *) weak_object;
>
> We may as well use a checked cast if we're casting at all. But...
Those are more time consuming, so I try to limit them.
> +typedef struct
> +{
> + GList *parts_list;
> + GSimpleAsyncResult *result;
> +} IdentifyMessagesCtx;
> +
>
> If you use the GSimpleAsyncResult object as the weak_object, you don't need to
> faff with context structs, since you can fish the TpTextChannel out of it using
> g_simple_async_result_get_source_object.
>
> (Since the GSimpleAsyncResult refs the channel anyway, this doesn't change the
> weak_object-y behaviour at all.)
Oh, good idea. done.
> - 0, NULL, got_pending_senders_contact_by_id_cb, parts_list,
> - free_parts_list, G_OBJECT (self));
> + 0, NULL, got_pending_senders_contact_by_id_cb, ctx,
> + (GDestroyNotify) identify_messages_free, G_OBJECT (self));
>
> You seem to have changed the calls, but not updated the callbacks for the
> changed type of the user_data. So I'm not sure how this can possibly work.
Yeah you're right, it's fixed now. Unfortunatelly this code was untested :(
(testing isn't trivial as that's the fallback path used with CMs not
implementing newer spec (ImmportaHandles) which is automatically implemented
by TpBaseConnection so with all tp-glib CMs...)
> c9daa96:
>
> + if (state == FEATURE_STATE_INVALID)
> + continue;
> + else if (state == FEATURE_STATE_UNWANTED)
> + {
> + if (check_feature_interfaces (self, features[i]))
> + {
> + tp_proxy_set_feature_state (self, features[i],
> + FEATURE_STATE_WANTED);
> + }
> + else
> + {
> + tp_proxy_set_feature_state (self, features[i],
> + FEATURE_STATE_FAILED);
> + }
>
> Coding style: if one block uses {}s, so should they all.
fixed.
> I wonder if this loop's body would be clearer as a switch.
Don't think so as we have to check feature->can_retry as well.
> Also, wait, what? You're upgrading unwanted features to wanted features if the
> object has the necessary interfaces? Am I missing something here? Are the enum
> members mis-documented?
Yeah, as the feature as been requested (using tp_proxy_prepare_async()), if
the interfaces/deps are good, the property is now WANTED .
> ca12418:
>
> + /* We have to wait than deps finished their
> + * preparation */
>
> "We have to wait until the deps finish their preparation."
fixed.
> + DEBUG ("Can't prepare %s, one is dep %s: %s",
> + g_quark_to_string (name),
> + dep_state == FEATURE_STATE_INVALID ? "is invalid": "failed",
> + g_quark_to_string (dep));
>
> "Can't prepare foo, one is dep is invalid: bar" isn't English.
>
> "Can't prepare %(name)s, because %(dep)s (a dependency) is invalid/failed to
> prepare" would be better.
changed.
> + if (G_UNLIKELY (need_avatars[0] == 0))
> + need_avatars[0] = TP_IFACE_QUARK_CONNECTION_INTERFACE_AVATARS;
> + features[FEAT_AVATAR_REQUIREMENTS].interfaces_needed = need_avatars;
>
> is duplicated constantly. The G_UNLIKELY() is not just unlikely, it's
> impossible, because the whole function is guarded by
>
> if (G_LIKELY (features[0].name != 0))
> return features;
Oh you're right. I removed those.
> so what's wrong with a function that allocates and returns a zero-terminated
> quark array? It could even be varargs for people who want to depend on more
> than one feature.
Humm, then we'd have to allocate the arrays on the heap rather than on the
stack, and they will be leaked which won't make valgrind happy. :\
> 53d656:
>
> + g_type_init ();
> + tp_tests_abort_after (10);
> + tp_debug_set_flags ("all");
> +
> + g_test_init (&argc, &argv, NULL);
> + g_test_bug_base ("http://bugs.freedesktop.org/show_bug.cgi?id=");
>
> Every single test starts with this. Can we have tp_tests_init (&argc, &argv); ?
Done. I recorded in such way we can easily cherry pick the commits to master
if needed.
> + /* Prepare capabilities on a new proxy. Core should be prepared *before*
> + * checking if Requests is implemented */
>
> Does this test test that? Why? I assume this test caught the bug the previous
> commit fixes. :)
I improved this comment to make it clearer.
> + * Copyright © 2010 Collabora Ltd. <http://www.collabora.co.uk/>
>
> I don't think we're in 2010 any more, Toto. (Maybe you wrote this in 2010 and
> rebased?
I updated to 2010-2011.
> ea3d6466:
>
> +static const TpProxyFeature *
> +list_features (TpProxyClass *cls G_GNUC_UNUSED)
> +{
> + static TpProxyFeature features[N_FEAT + 1] = { { 0 } };
> +
> + if (G_LIKELY (features[0].name != 0))
> + return features;
>
>
> indentaaation.
fixed.
> Your tests' prepare_foo_async functions should assert that the dependent
> features have been prepared before they're called. I see that you do check that
> the interfaces are checked, and that children of unpreparable features aren't
> told to prepare; adding an assertion to feature B's preparation function
> wouldn't hurt.
Humm I'm not sure to understand. prepare_b_async() does check if A is
prepared.
> + /* List of TpProxyPrepareRequest. The first requests are the core one,
> + * sorted from the most upper super class to the subclass core features.
> + * This is needed to guarantee than subclass features are not prepared
> + * until the super class features have been prepared. */
> GList *prepare_requests;
>
> This is a hobbyhorse of mine, but: this should be a GQueue (nb. you can use
> GQueue as opposed to GQueue * if you're into that sort of thing). We prepend in
> one place, and append in another place, so GQueue is genuinely a more
> appropriate data structure.
done.
> +static gboolean
> +core_prepared (TpProxy *self)
> +{
> + /* All the core features have been prepared if the head of the
> + * prepare_requests list is NOT a core feature */
> + TpProxyPrepareRequest *req = self->priv->prepare_requests->data;
> +
> + if (req == NULL)
> + return TRUE;
> +
> + return !req->core;
> +}
>
> Why would the data in the head of the list be NULL? Did you mean to check
> whether the list is empty?
Indeed, but that's now fixed with the GQueue-ification.
> /* Core features have to be prepared first */
> if (!core_prepared (self) &&
> - !req->core)
> + req != self->priv->prepare_requests->data)
>
> I think this deserves more of a comment. “Core features have to be prepared
> first, in superclass-to-subclass order. The next core feature to be prepared,
> if any, is always at the head of prepare_requests.”
I used your comment, thanks.
> +static void
> +check_feature_validity (TpProxy *self,
> + const TpProxyFeature *feature)
>
> I'd include "assert" in the function name.
good idea; done.
> I think it's really sketchy that proxy.c has connection-specific stuff in it. I
> don't think any of this stuff should be in there. Can't the connection have the
> special knowledge about which features should be prepared just before
> announcing Connected, and call tp_proxy_prepare_async() for them all?
It's more subtile than that. prepare_before_signalling_connected_async()
doesn't mean we have to prepare the feature before announcing CONNECTED but
that IF the feature is already prepared, then we have to give it a chance to
update itself before annoucning CONNECTED.
I agree that the connection special case in proxy.c isn't great, but tbh
prepare_before_signalling_connected_async is already connection specific any
way. I discussed this with smcv when I started working on this and he agreed
that modifying proxy.c was probably the way to go.
I guess the alternative would be to expose details about interfaces to
connection.c and move mosf of the code there?
--
Configure bugmail: https://bugs.freedesktop.org/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the QA contact for the bug.
You are the assignee for the bug.
More information about the telepathy-bugs
mailing list