diff options
author | Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> | 2011-05-13 12:01:36 +0200 |
---|---|---|
committer | Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> | 2011-05-16 11:03:55 +0200 |
commit | 0d7638c507a58911a29e45d7830326bf60aa55d9 (patch) | |
tree | 572b949f8c0b1138b8c6d93278b6fae5eae60766 | |
parent | 051440da4248dfcf378b9e37fffa13bb06db7a38 (diff) |
Use new DelegateChannels() API
-rw-r--r-- | telepathy-glib/base-client.c | 142 | ||||
-rw-r--r-- | telepathy-glib/base-client.h | 2 | ||||
-rw-r--r-- | tests/dbus/base-client.c | 13 | ||||
-rw-r--r-- | tests/lib/simple-channel-dispatcher.c | 9 |
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 |