[telepathy-mission-control/master] fd.o#21003 (partial): save up HandleWith calls until we finish, and return from all of them when finished
Simon McVittie
simon.mcvittie at collabora.co.uk
Wed Oct 28 13:12:48 PDT 2009
---
src/mcd-dispatch-operation.c | 81 ++++++++++++++++++++-
test/twisted/dispatcher/handle-channels-fails.py | 14 ++---
2 files changed, 82 insertions(+), 13 deletions(-)
diff --git a/src/mcd-dispatch-operation.c b/src/mcd-dispatch-operation.c
index 0325e25..9b07ee3 100644
--- a/src/mcd-dispatch-operation.c
+++ b/src/mcd-dispatch-operation.c
@@ -85,11 +85,30 @@ typedef enum {
typedef struct {
ApprovalType type;
- /* NULL unless type is CLAIM */
+ /* NULL unless type is REQUESTED or HANDLE_WITH; may be NULL even in those
+ * cases, to signify "any handler will do" */
+ gchar *client_bus_name;
+ /* NULL unless type is CLAIM or HANDLE_WITH */
DBusGMethodInvocation *context;
} Approval;
static Approval *
+approval_new_handle_with (const gchar *client_bus_name,
+ DBusGMethodInvocation *context)
+{
+ Approval *approval = g_slice_new0 (Approval);
+
+ g_assert (context != NULL);
+
+ if (client_bus_name != NULL && client_bus_name[0] != '\0')
+ approval->client_bus_name = g_strdup (client_bus_name);
+
+ approval->type = APPROVAL_TYPE_HANDLE_WITH;
+ approval->context = context;
+ return approval;
+}
+
+static Approval *
approval_new_claim (DBusGMethodInvocation *context)
{
Approval *approval = g_slice_new0 (Approval);
@@ -108,6 +127,7 @@ approval_new (ApprovalType type)
switch (type)
{
case APPROVAL_TYPE_CLAIM:
+ case APPROVAL_TYPE_HANDLE_WITH:
g_assert_not_reached ();
default:
{} /* do nothing */
@@ -148,6 +168,8 @@ struct _McdDispatchOperationPrivate
/* queue of Approval */
GQueue *approvals;
+ /* if not NULL, the handler that accepted it */
+ TpClient *successful_handler;
/* Reference to a global handler map */
McdHandlerMap *handler_map;
@@ -607,6 +629,12 @@ _mcd_dispatch_operation_finish (McdDispatchOperation *operation)
* to close */
GError not_yours = { TP_ERRORS, TP_ERROR_NOT_YOURS,
"Channel handled by someone else (or all channels were lost)" };
+ const gchar *successful_handler = NULL;
+
+ if (priv->successful_handler != NULL)
+ {
+ successful_handler = tp_proxy_get_bus_name (priv->successful_handler);
+ }
if (priv->wants_to_finish)
{
@@ -631,6 +659,43 @@ _mcd_dispatch_operation_finish (McdDispatchOperation *operation)
approval->context = NULL;
break;
+ case APPROVAL_TYPE_HANDLE_WITH:
+ g_assert (approval->context != NULL);
+
+ if (successful_handler != NULL)
+ {
+ /* Some Handler got it. If this Approver would have been
+ * happy with that Handler, then it succeeds, otherwise,
+ * it loses. */
+ if (approval->client_bus_name == NULL ||
+ !tp_strdiff (approval->client_bus_name,
+ successful_handler))
+ {
+ DEBUG ("successful HandleWith, channel went to %s",
+ successful_handler);
+ tp_svc_channel_dispatch_operation_return_from_handle_with (
+ approval->context);
+ }
+ else
+ {
+ DEBUG ("HandleWith -> NotYours: wanted %s but "
+ "%s got it instead", approval->client_bus_name,
+ successful_handler);
+ dbus_g_method_return_error (approval->context,
+ ¬_yours);
+ }
+ }
+ else
+ {
+ /* Handling finished for some other reason: perhaps the
+ * channel was claimed, or perhaps we ran out of channels.
+ * For now, represent that as NotYours */
+ DEBUG ("HandleWith -> NotYours: no handler got it");
+ dbus_g_method_return_error (approval->context, ¬_yours);
+ }
+
+ break;
+
default:
{} /* do nothing */
}
@@ -682,9 +747,8 @@ dispatch_operation_handle_with (TpSvcChannelDispatchOperation *cdo,
}
g_queue_push_tail (self->priv->approvals,
- approval_new (APPROVAL_TYPE_HANDLE_WITH));
+ approval_new_handle_with (handler_name, context));
_mcd_dispatch_operation_check_client_locks (self);
- tp_svc_channel_dispatch_operation_return_from_handle_with (context);
}
static void
@@ -1005,6 +1069,12 @@ mcd_dispatch_operation_dispose (GObject *object)
McdDispatchOperationPrivate *priv = MCD_DISPATCH_OPERATION_PRIV (object);
GList *list;
+ if (priv->successful_handler != NULL)
+ {
+ g_object_unref (priv->successful_handler);
+ priv->successful_handler = NULL;
+ }
+
if (priv->channels)
{
for (list = priv->channels; list != NULL; list = list->next)
@@ -1588,7 +1658,10 @@ _mcd_dispatch_operation_handle_channels_cb (TpClient *client,
unique_name);
}
- /* emit Finished, if we haven't already */
+ /* emit Finished, if we haven't already; but first make a note of the
+ * handler we used, so we can reply to all the HandleWith calls with
+ * success or failure */
+ self->priv->successful_handler = g_object_ref (client);
_mcd_dispatch_operation_finish (self);
self->priv->channels_handled = TRUE;
}
diff --git a/test/twisted/dispatcher/handle-channels-fails.py b/test/twisted/dispatcher/handle-channels-fails.py
index 5051211..7f532d7 100644
--- a/test/twisted/dispatcher/handle-channels-fails.py
+++ b/test/twisted/dispatcher/handle-channels-fails.py
@@ -148,15 +148,10 @@ def test(q, bus, mc):
cs.tp_name_prefix + '.Client.Empathy')
# Empathy is asked to handle the channels
- e, _ = q.expect_many(
- EventPattern('dbus-method-call',
- path=empathy.object_path,
- interface=cs.HANDLER, method='HandleChannels',
- handled=False),
- # FIXME: currently HandleWith succeeds immediately, rather than
- # failing when HandleChannels fails (fd.o #21003)
- EventPattern('dbus-return', method='HandleWith'),
- )
+ e = q.expect('dbus-method-call',
+ path=empathy.object_path,
+ interface=cs.HANDLER, method='HandleChannels',
+ handled=False)
# Empathy rejects the channels
q.dbus_raise(e.message, cs.NOT_AVAILABLE, 'Blind drunk', bus=empathy_bus)
@@ -176,6 +171,7 @@ def test(q, bus, mc):
# MC gives up and closes the channel. This is the end of the CDO.
q.expect_many(
+ EventPattern('dbus-error', method='HandleWith'),
EventPattern('dbus-method-call', path=chan.object_path,
interface=cs.CHANNEL, method='Close', args=[]),
EventPattern('dbus-signal', interface=cs.CDO, signal='Finished'),
--
1.5.6.5
More information about the telepathy-commits
mailing list