summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlberto Mardegan <mardy@users.sourceforge.net>2007-11-23 15:39:45 +0000
committerAlberto Mardegan <mardy@users.sourceforge.net>2007-11-23 15:39:45 +0000
commitef5c2a701f40b031216aa4eb9fe9e122539ab49e (patch)
tree320cf3fe9fbdfc05edee9b4530ec990c70778db9 /src
parentd97d250810d53d3250b9aaa2d128e1671930cefa (diff)
Use a list of structures to keep track of the pending channels: in
this way we take into account also the handle type and the channel type. git-svn-id: https://mission-control.svn.sourceforge.net/svnroot/mission-control/trunk@194 d91c8aed-3f2b-0410-a83d-924a1c20a0ba
Diffstat (limited to 'src')
-rw-r--r--src/mcd-connection.c145
1 files changed, 100 insertions, 45 deletions
diff --git a/src/mcd-connection.c b/src/mcd-connection.c
index bb28693a..ea5c8e6e 100644
--- a/src/mcd-connection.c
+++ b/src/mcd-connection.c
@@ -126,7 +126,7 @@ typedef struct
/* List of pending channels which has been requested to telepathy,
* but telepathy hasn't yet responded with the channel object
*/
- GHashTable *pending_channels;
+ GList *pending_channels;
TelepathyConnectionStatusReason abort_reason;
gboolean got_capabilities;
@@ -149,6 +149,13 @@ struct param_data
GHashTable *dest;
};
+typedef struct {
+ guint handle_type;
+ guint handle;
+ const gchar *type;
+ McdChannel *channel;
+} McdPendingChannel;
+
enum
{
PROP_0,
@@ -625,7 +632,7 @@ done:
}
static gboolean
-on_channel_capabilities_timeout (guint channel_handle, McdChannel *channel,
+on_channel_capabilities_timeout (McdChannel *channel,
McdConnection *connection)
{
McdConnectionPrivate *priv = MCD_CONNECTION_PRIV (connection);
@@ -651,16 +658,35 @@ on_channel_capabilities_timeout (guint channel_handle, McdChannel *channel,
return TRUE;
}
+static inline void
+pending_channel_free (McdPendingChannel *pc)
+{
+ g_object_unref (pc->channel);
+ g_free (pc);
+}
+
static gboolean
on_capabilities_timeout (McdConnection *connection)
{
McdConnectionPrivate *priv = MCD_CONNECTION_PRIV (connection);
+ GList *list, *list_curr;
g_debug ("%s: got_capabilities is %d", G_STRFUNC, priv->got_capabilities);
priv->got_capabilities = TRUE;
- g_hash_table_foreach_remove (priv->pending_channels,
- (GHRFunc)on_channel_capabilities_timeout,
- connection);
+ list = priv->pending_channels;
+ while (list)
+ {
+ McdPendingChannel *pc = list->data;
+
+ list_curr = list;
+ list = list->next;
+ if (on_channel_capabilities_timeout (pc->channel, connection))
+ {
+ pending_channel_free (pc);
+ priv->pending_channels =
+ g_list_delete_link (priv->pending_channels, list_curr);
+ }
+ }
priv->capabilities_timer = 0;
return FALSE;
}
@@ -1511,7 +1537,8 @@ _mcd_connection_dispose (GObject * object)
(GFunc) _foreach_channel_remove, connection);
/* Unref pending channels */
- g_hash_table_destroy (priv->pending_channels);
+ g_list_foreach (priv->pending_channels, (GFunc)pending_channel_free, NULL);
+ g_list_free (priv->pending_channels);
_mcd_connection_release_tp_connection (connection);
@@ -1744,20 +1771,10 @@ mcd_connection_class_init (McdConnectionClass * klass)
}
static void
-release_channel_object (gpointer object)
-{
- g_object_unref (object);
-}
-
-static void
mcd_connection_init (McdConnection * connection)
{
McdConnectionPrivate *priv = MCD_CONNECTION_PRIV (connection);
- priv->pending_channels = g_hash_table_new_full (g_direct_hash,
- g_direct_equal,
- NULL,
- release_channel_object);
priv->abort_reason = TP_CONN_STATUS_REASON_NONE_SPECIFIED;
priv->reconnect_interval = 30 * 1000; /* 30 seconds */
@@ -1879,6 +1896,14 @@ remove_capabilities_refs (gpointer data)
g_free (cwd);
}
+static gint
+pending_channel_cmp (const McdPendingChannel *a, const McdPendingChannel *b)
+{
+ return a->handle == b->handle &&
+ a->handle_type == b->handle_type &&
+ strcmp (a->type, b->type);
+}
+
static void
mcd_async_request_chan_callback (DBusGProxy *proxy,
gchar *channel_path,
@@ -1894,6 +1919,8 @@ mcd_async_request_chan_callback (DBusGProxy *proxy,
TelepathyHandleType chan_handle_type;
guint chan_handle;
TpChan *tp_chan;
+ McdPendingChannel pc;
+ GList *list;
/* We handle only the dbus errors */
/* ChannelRequestor *chan_req = (ChannelRequestor *)user_data; */
@@ -1905,8 +1932,13 @@ mcd_async_request_chan_callback (DBusGProxy *proxy,
g_object_get (channel,
"channel-handle", &chan_handle,
"channel-handle-type", &chan_handle_type,
+ "channel-type", &chan_type,
NULL);
+ pc.handle = chan_handle;
+ pc.handle_type = chan_handle_type;
+ pc.type = chan_type;
+ pc.channel = NULL;
cwd = g_object_get_data (G_OBJECT (channel), "error_on_creation");
if (cwd)
@@ -1941,8 +1973,14 @@ mcd_async_request_chan_callback (DBusGProxy *proxy,
* reference to this temporary channel.
* This should also unref the channel object
*/
- g_hash_table_remove (priv->pending_channels,
- GINT_TO_POINTER (chan_handle));
+ list = g_list_find_custom (priv->pending_channels, &pc,
+ (GCompareFunc)pending_channel_cmp);
+ if (list)
+ {
+ pending_channel_free (list->data);
+ priv->pending_channels =
+ g_list_delete_link (priv->pending_channels, list);
+ }
}
else
{
@@ -1964,6 +2002,7 @@ mcd_async_request_chan_callback (DBusGProxy *proxy,
g_object_set_data_full (G_OBJECT (channel), "error_on_creation", cwd,
remove_capabilities_refs);
}
+ g_free (chan_type);
return;
}
@@ -1983,23 +2022,29 @@ mcd_async_request_chan_callback (DBusGProxy *proxy,
* reference to this temporary channel.
* This should also unref the channel object
*/
- g_hash_table_remove (priv->pending_channels,
- GINT_TO_POINTER (chan_handle));
+ list = g_list_find_custom (priv->pending_channels, &pc,
+ (GCompareFunc)pending_channel_cmp);
+ if (list)
+ {
+ pending_channel_free (list->data);
+ priv->pending_channels =
+ g_list_delete_link (priv->pending_channels, list);
+ }
+ g_free (chan_type);
return;
}
/* Everything here is well and fine. We can create the channel. */
- channel = g_hash_table_lookup (priv->pending_channels,
- GUINT_TO_POINTER (chan_handle));
+ list = g_list_find_custom (priv->pending_channels, &pc,
+ (GCompareFunc)pending_channel_cmp);
+ channel = ((McdPendingChannel *)list->data)->channel;
if (!channel)
{
g_warning ("%s: channel not found among the pending ones", G_STRFUNC);
+ g_free (chan_type);
return;
}
- g_object_get (channel,
- "channel-type", &chan_type,
- NULL);
tp_chan = tp_chan_new (priv->dbus_connection, priv->bus_name,
channel_path, chan_type, chan_handle_type, chan_handle);
g_object_set (channel,
@@ -2007,11 +2052,11 @@ mcd_async_request_chan_callback (DBusGProxy *proxy,
"tp-channel", tp_chan,
NULL);
- /* The channel is no longer pending. 'stealing' because want the
- * channel ownership.
- */
- g_hash_table_steal (priv->pending_channels,
- GINT_TO_POINTER (chan_handle));
+ /* The channel is no longer pending. We increase the reference count, since
+ * pending_channel_free() will decrease it */
+ g_object_ref (channel);
+ pending_channel_free (list->data);
+ priv->pending_channels = g_list_delete_link (priv->pending_channels, list);
mcd_operation_take_mission (MCD_OPERATION (connection),
MCD_MISSION (channel));
@@ -2037,6 +2082,7 @@ mcd_async_request_handle_callback(DBusGProxy *proxy, GArray *handles,
const gchar *chan_type;
const GList *channels;
DBusGProxyCall *call;
+ McdPendingChannel *pc;
channel = MCD_CHANNEL (user_data);
connection = g_object_get_data (G_OBJECT (channel), "temporary_connection");
@@ -2137,8 +2183,12 @@ mcd_async_request_handle_callback(DBusGProxy *proxy, GArray *handles,
/* The channel is temporary and stays in priv->pending_channels until
* a telepathy channel for it is created
*/
- g_hash_table_insert (priv->pending_channels,
- GINT_TO_POINTER (chan_handle), channel);
+ pc = g_malloc (sizeof(McdPendingChannel));
+ pc->handle = chan_handle;
+ pc->handle_type = chan_handle_type;
+ pc->type = chan_type;
+ pc->channel = channel;
+ priv->pending_channels = g_list_prepend (priv->pending_channels, pc);
/* Now, request the corresponding telepathy channel. */
call = tp_conn_request_channel_async(DBUS_G_PROXY(proxy),
@@ -2177,10 +2227,16 @@ mcd_connection_request_channel (McdConnection *connection,
if (req->channel_handle != 0 || req->channel_handle_type == 0)
{
DBusGProxyCall *call;
+ McdPendingChannel *pc;
+
/* the channel stays in priv->pending_channels until a telepathy
* channel for it is created */
- g_hash_table_insert (priv->pending_channels,
- GINT_TO_POINTER (req->channel_handle), channel);
+ pc = g_malloc (sizeof(McdPendingChannel));
+ pc->handle = req->channel_handle;
+ pc->handle_type = req->channel_handle_type;
+ pc->type = req->channel_type;
+ pc->channel = channel;
+ priv->pending_channels = g_list_prepend (priv->pending_channels, pc);
call = tp_conn_request_channel_async(DBUS_G_PROXY(priv->tp_conn),
req->channel_type,
@@ -2213,7 +2269,7 @@ mcd_connection_request_channel (McdConnection *connection,
}
static gboolean
-channel_matches_request (gpointer key, McdChannel *channel,
+channel_matches_request (McdChannel *channel,
struct request_id *req_id)
{
guint requestor_serial;
@@ -2242,23 +2298,22 @@ mcd_connection_cancel_channel_request (McdConnection *connection,
McdConnectionPrivate *priv = MCD_CONNECTION_PRIV (connection);
struct request_id req_id;
const GList *channels, *node;
+ GList *list;
McdChannel *channel;
/* first, see if the channel is in the list of the pending channels */
req_id.requestor_serial = operation_id;
req_id.requestor_client_id = requestor_client_id;
- channel = g_hash_table_find (priv->pending_channels,
- (GHRFunc)channel_matches_request,
- &req_id);
- if (channel)
+
+ for (list = priv->pending_channels; list; list = list->next)
{
- guint chan_handle;
DBusGProxyCall *call;
+ McdPendingChannel *pc = list->data;
+
+ if (!channel_matches_request (pc->channel, &req_id)) continue;
+ channel = pc->channel;
g_debug ("%s: requested channel found in the pending_channels list (%p)", G_STRFUNC, channel);
- g_object_get (channel,
- "channel-handle", &chan_handle,
- NULL);
/* check for pending dbus calls to be cancelled */
call = g_object_get_data (G_OBJECT (channel), "tp_chan_call");
dbus_g_proxy_cancel_call (DBUS_G_PROXY(priv->tp_conn), call);
@@ -2269,8 +2324,8 @@ mcd_connection_cancel_channel_request (McdConnection *connection,
* this channel, it will be ignored since it has the suppress_handler
* flag set.
*/
- g_hash_table_remove (priv->pending_channels,
- GINT_TO_POINTER (chan_handle));
+ pending_channel_free (pc);
+ priv->pending_channels = g_list_delete_link (priv->pending_channels, list);
return TRUE;
}