summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuillaume Desmottes <guillaume.desmottes@collabora.co.uk>2011-05-13 12:01:36 +0200
committerGuillaume Desmottes <guillaume.desmottes@collabora.co.uk>2011-05-16 11:03:55 +0200
commit0d7638c507a58911a29e45d7830326bf60aa55d9 (patch)
tree572b949f8c0b1138b8c6d93278b6fae5eae60766
parent051440da4248dfcf378b9e37fffa13bb06db7a38 (diff)
Use new DelegateChannels() API
-rw-r--r--telepathy-glib/base-client.c142
-rw-r--r--telepathy-glib/base-client.h2
-rw-r--r--tests/dbus/base-client.c13
-rw-r--r--tests/lib/simple-channel-dispatcher.c9
4 files changed, 153 insertions, 13 deletions
diff --git a/telepathy-glib/base-client.c b/telepathy-glib/base-client.c
index d6ef3596..01af1bc6 100644
--- a/telepathy-glib/base-client.c
+++ b/telepathy-glib/base-client.c
@@ -2807,8 +2807,70 @@ _tp_base_client_now_handling_channels (TpBaseClient *self,
add_handled_channels (self, channels);
}
+typedef struct
+{
+ /* Array of reffed TpChannel */
+ GPtrArray *channels;
+ /* Array of reffed TpChannel */
+ GPtrArray *delegated;
+ /* reffed TpChannel => owned GError */
+ GHashTable *not_delegated;
+} DelegateChannelsCtx;
+
+static DelegateChannelsCtx *
+delegate_channels_ctx_new (GList *channels)
+{
+ DelegateChannelsCtx *ctx = g_slice_new0 (DelegateChannelsCtx);
+ GList *l;
+
+ ctx->channels = g_ptr_array_sized_new (g_list_length (channels));
+ g_ptr_array_set_free_func (ctx->channels, g_object_unref);
+
+ for (l = channels; l != NULL; l = g_list_next (l))
+ {
+ TpChannel *channel = l->data;
+
+ g_return_val_if_fail (TP_IS_CHANNEL (channel), NULL);
+
+ g_ptr_array_add (ctx->channels, g_object_ref (channel));
+ }
+
+ ctx->delegated = g_ptr_array_new_with_free_func (g_object_unref);
+ ctx->not_delegated = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+ g_object_unref, (GDestroyNotify) g_error_free);
+
+ return ctx;
+}
+
+static void
+delegate_channels_ctx_free (DelegateChannelsCtx *ctx)
+{
+ g_ptr_array_unref (ctx->channels);
+ g_ptr_array_unref (ctx->delegated);
+ g_hash_table_unref (ctx->not_delegated);
+
+ g_slice_free (DelegateChannelsCtx, ctx);
+}
+
+static gboolean
+path_is_in_array (const GPtrArray *array,
+ const gchar *path)
+{
+ guint i;
+
+ for (i = 0; array->len; i++)
+ {
+ if (!tp_strdiff (g_ptr_array_index (array, i), path))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
static void
delegate_channels_cb (TpChannelDispatcher *cd,
+ const GPtrArray *delegated,
+ GHashTable *not_delegated,
const GError *error,
gpointer user_data,
GObject *weak_object)
@@ -2822,17 +2884,45 @@ delegate_channels_cb (TpChannelDispatcher *cd,
}
else
{
- /* We are not longer handling the channels */
- GPtrArray *chans;
+ DelegateChannelsCtx *ctx;
guint i;
- chans = g_simple_async_result_get_op_res_gpointer (result);
+ ctx = g_simple_async_result_get_op_res_gpointer (result);
- for (i = 0; i < chans->len; i++)
+ for (i = 0; i < ctx->channels->len; i++)
{
- const gchar *path = g_ptr_array_index (chans, i);
+ TpChannel *channel = g_ptr_array_index (ctx->channels, i);
+ const gchar *path;
+ GValueArray *v;
+ const gchar *dbus_error, *msg;
+ GError *err = NULL;
+
+ path = tp_proxy_get_object_path (channel);
+
+ if (path_is_in_array (delegated, path))
+ {
+ /* We are no longer handling this channel */
+ g_hash_table_remove (self->priv->my_chans, path);
+
+ g_ptr_array_add (ctx->delegated, g_object_ref (channel));
+ continue;
+ }
+
+ v = g_hash_table_lookup (not_delegated, path);
+ if (v == NULL)
+ {
+ DEBUG ("MC didn't tell us if we are still handling or not %s",
+ path);
+ continue;
+ }
+
+ tp_value_array_unpack (v, 2, &dbus_error, &msg);
- g_hash_table_remove (self->priv->my_chans, path);
+ tp_proxy_dbus_error_to_gerror (cd, dbus_error, msg, &err);
+
+ /* Pass ownership of the error to the hash table */
+ g_hash_table_insert (ctx->not_delegated, g_object_ref (channel),
+ err);
}
}
@@ -2869,9 +2959,10 @@ tp_base_client_delegate_channels_async (TpBaseClient *self,
gpointer user_data)
{
TpChannelDispatcher *cd;
+ GSimpleAsyncResult *result;
+ DelegateChannelsCtx *ctx;
GPtrArray *chans;
GList *l;
- GSimpleAsyncResult *result;
g_return_if_fail (TP_IS_BASE_CLIENT (self));
g_return_if_fail (self->priv->flags & CLIENT_IS_HANDLER);
@@ -2893,8 +2984,10 @@ tp_base_client_delegate_channels_async (TpBaseClient *self,
result = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
tp_base_client_delegate_channels_async);
- g_simple_async_result_set_op_res_gpointer (result, chans,
- (GDestroyNotify) g_ptr_array_unref);
+ ctx = delegate_channels_ctx_new (channels);
+
+ g_simple_async_result_set_op_res_gpointer (result, ctx,
+ (GDestroyNotify) delegate_channels_ctx_free);
/* DelegateChannels() can takes a while if, for example, some clients are
* crashing and so MC has to wait for them to time out before calling the
@@ -2905,18 +2998,26 @@ tp_base_client_delegate_channels_async (TpBaseClient *self,
delegate_channels_cb, result, g_object_unref, G_OBJECT (self));
g_object_unref (cd);
+ g_ptr_array_unref (chans);
}
/**
* tp_base_client_delegate_channels_finish:
* @self: a #TpBaseClient
* @result: a #GAsyncResult
+ * @delegated: (out) (element-type TelepathyGLib.Channel) (transfer container):
+ * if not %NULL, used to return a #GPtrArray containing the #TpChannel which
+ * have been properly delegated
+ * @not_delegated: (out) (element-type TelepathyGLib.Channel GLib.Error) (transfer container):
+ * fnot not %NULL, used to return a #GHashTable mapping #TpChannel which have
+ * not been delegated to a #GError explaining the reason of the failure
* @error: a #GError to fill
*
* Finishes an async channels delegation request started using
* tp_base_client_delegate_channels_async().
*
- * Returns: %TRUE if @self is not longer the handler of the channels,
+ * Returns: %TRUE if the operation succeed, @delegated and @not_delegated
+ * can be used to known the channels that @self is not handling any more,
* otherwise %FALSE.
*
* Since: 0.15.UNRELEASED
@@ -2924,7 +3025,26 @@ tp_base_client_delegate_channels_async (TpBaseClient *self,
gboolean
tp_base_client_delegate_channels_finish (TpBaseClient *self,
GAsyncResult *result,
+ GPtrArray **delegated,
+ GHashTable **not_delegated,
GError **error)
{
- _tp_implement_finish_void (self, tp_base_client_delegate_channels_async)
+ DelegateChannelsCtx *ctx;
+ GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
+
+ ctx = g_simple_async_result_get_op_res_gpointer (simple);
+
+ if (g_simple_async_result_propagate_error (simple, error))
+ return FALSE;
+
+ g_return_val_if_fail (g_simple_async_result_is_valid (result,
+ G_OBJECT (self), tp_base_client_delegate_channels_async), FALSE);
+
+ if (delegated != NULL)
+ *delegated = g_ptr_array_ref (ctx->delegated);
+
+ if (not_delegated != NULL)
+ *not_delegated = g_hash_table_ref (ctx->not_delegated);
+
+ return TRUE;
}
diff --git a/telepathy-glib/base-client.h b/telepathy-glib/base-client.h
index b1dc48a0..1a1eb055 100644
--- a/telepathy-glib/base-client.h
+++ b/telepathy-glib/base-client.h
@@ -185,6 +185,8 @@ void tp_base_client_delegate_channels_async (TpBaseClient *self,
gboolean tp_base_client_delegate_channels_finish (TpBaseClient *self,
GAsyncResult *result,
+ GPtrArray **delegated,
+ GHashTable **not_delegated,
GError **error);
const gchar *tp_base_client_get_name (TpBaseClient *self);
diff --git a/tests/dbus/base-client.c b/tests/dbus/base-client.c
index ea314cf5..b26bfe39 100644
--- a/tests/dbus/base-client.c
+++ b/tests/dbus/base-client.c
@@ -52,6 +52,9 @@ typedef struct {
GError *error /* initialized where needed */;
GStrv interfaces;
gint wait;
+
+ GPtrArray *delegated;
+ GHashTable *not_delegated;
} Test;
#define ACCOUNT_PATH TP_ACCOUNT_OBJECT_PATH_BASE "what/ev/er"
@@ -264,6 +267,9 @@ teardown (Test *test,
g_object_unref (test->base_connection);
tp_clear_object (&test->cd_service);
+
+ tp_clear_pointer (&test->delegated, g_ptr_array_unref);
+ tp_clear_pointer (&test->not_delegated, g_hash_table_unref);
}
/* Test Basis */
@@ -1235,7 +1241,8 @@ delegate_channels_cb (GObject *source,
Test *test = user_data;
tp_base_client_delegate_channels_finish (
- TP_BASE_CLIENT (source), result, &test->error);
+ TP_BASE_CLIENT (source), result, &test->delegated, &test->not_delegated,
+ &test->error);
test->wait--;
if (test->wait == 0)
@@ -1300,6 +1307,10 @@ test_delegate_channels (Test *test,
g_main_loop_run (test->mainloop);
g_assert_no_error (test->error);
+ g_assert_cmpuint (test->delegated->len, ==, 1);
+ g_assert (g_ptr_array_index (test->delegated, 0) == test->text_chan);
+ g_assert_cmpuint (g_hash_table_size (test->not_delegated), ==, 0);
+
/* Client is not handling the channel any more */
chans = tp_base_client_get_handled_channels (test->base_client);
g_assert_cmpuint (g_list_length (chans), ==, 1);
diff --git a/tests/lib/simple-channel-dispatcher.c b/tests/lib/simple-channel-dispatcher.c
index b90348c7..8f3eb359 100644
--- a/tests/lib/simple-channel-dispatcher.c
+++ b/tests/lib/simple-channel-dispatcher.c
@@ -255,7 +255,14 @@ tp_tests_simple_channel_dispatcher_delegate_channels (
const gchar *preferred_handler,
DBusGMethodInvocation *context)
{
- tp_svc_channel_dispatcher_return_from_delegate_channels (context);
+ GHashTable *not_delegated;
+
+ not_delegated = g_hash_table_new (g_str_hash, g_str_equal);
+
+ tp_svc_channel_dispatcher_return_from_delegate_channels (context, channels,
+ not_delegated);
+
+ g_hash_table_unref (not_delegated);
}
static void