[libsoup] Notice closed connections sooner



commit ef7fc0585990b9c2e056596d1850bdb3f6f6dae9
Author: Dan Winship <danw gnome org>
Date:   Mon Aug 17 22:28:08 2009 -0400

    Notice closed connections sooner
    
    Only works on UNIX; Windows has to wait for the GSocket port.
    
    http://bugzilla.gnome.org/show_bug.cgi?id=578990

 libsoup/soup-connection.c      |   17 ++++++++++++++++-
 libsoup/soup-connection.h      |    1 +
 libsoup/soup-session-async.c   |    4 +++-
 libsoup/soup-session-private.h |    3 ++-
 libsoup/soup-session-sync.c    |    9 +++++++--
 libsoup/soup-session.c         |   33 +++++++++++++++------------------
 libsoup/soup-socket.c          |    8 ++++++++
 libsoup/soup-socket.h          |    1 +
 8 files changed, 53 insertions(+), 23 deletions(-)
---
diff --git a/libsoup/soup-connection.c b/libsoup/soup-connection.c
index 0d731c0..78ea311 100644
--- a/libsoup/soup-connection.c
+++ b/libsoup/soup-connection.c
@@ -598,10 +598,25 @@ soup_connection_get_proxy_uri (SoupConnection *conn)
 SoupConnectionState
 soup_connection_get_state (SoupConnection *conn)
 {
+	SoupConnectionPrivate *priv;
+
 	g_return_val_if_fail (SOUP_IS_CONNECTION (conn),
 			      SOUP_CONNECTION_DISCONNECTED);
+	priv = SOUP_CONNECTION_GET_PRIVATE (conn);
+
+#ifdef G_OS_UNIX
+	if (priv->state == SOUP_CONNECTION_IDLE) {
+		GPollFD pfd;
+
+		pfd.fd = soup_socket_get_fd (priv->socket);
+		pfd.events = G_IO_IN;
+		pfd.revents = 0;
+		if (g_poll (&pfd, 1, 0) == 1)
+			priv->state = SOUP_CONNECTION_REMOTE_DISCONNECTED;
+	}
+#endif
 
-	return SOUP_CONNECTION_GET_PRIVATE (conn)->state;
+	return priv->state;
 }
 
 void
diff --git a/libsoup/soup-connection.h b/libsoup/soup-connection.h
index 68a36ab..2dc6754 100644
--- a/libsoup/soup-connection.h
+++ b/libsoup/soup-connection.h
@@ -44,6 +44,7 @@ typedef enum {
 	SOUP_CONNECTION_CONNECTING,
 	SOUP_CONNECTION_IDLE,
 	SOUP_CONNECTION_IN_USE,
+	SOUP_CONNECTION_REMOTE_DISCONNECTED,
 	SOUP_CONNECTION_DISCONNECTED
 } SoupConnectionState;
 
diff --git a/libsoup/soup-session-async.c b/libsoup/soup-session-async.c
index 6045481..cdb9961 100644
--- a/libsoup/soup-session-async.c
+++ b/libsoup/soup-session-async.c
@@ -307,6 +307,8 @@ run_queue (SoupSessionAsync *sa)
 	SoupConnection *conn;
 	gboolean try_pruning = TRUE, should_prune = FALSE;
 
+	soup_session_cleanup_connections (session, FALSE);
+
  try_again:
 	for (item = soup_message_queue_first (queue);
 	     item && !should_prune;
@@ -354,7 +356,7 @@ run_queue (SoupSessionAsync *sa)
 		 * could be sent if we pruned an idle connection from
 		 * some other server.
 		 */
-		if (soup_session_try_prune_connection (session)) {
+		if (soup_session_cleanup_connections (session, TRUE)) {
 			try_pruning = should_prune = FALSE;
 			goto try_again;
 		}
diff --git a/libsoup/soup-session-private.h b/libsoup/soup-session-private.h
index 65a9718..72b79c5 100644
--- a/libsoup/soup-session-private.h
+++ b/libsoup/soup-session-private.h
@@ -21,7 +21,8 @@ SoupMessageQueueItem *soup_session_make_connect_message (SoupSession          *s
 SoupConnection       *soup_session_get_connection       (SoupSession          *session,
 							 SoupMessageQueueItem *item,
 							 gboolean             *try_pruning);
-gboolean              soup_session_try_prune_connection (SoupSession          *session);
+gboolean              soup_session_cleanup_connections  (SoupSession          *session,
+							 gboolean              prune_idle);
 void                  soup_session_connection_failed    (SoupSession          *session,
 							 SoupConnection       *conn,
 							 guint                 status);
diff --git a/libsoup/soup-session-sync.c b/libsoup/soup-session-sync.c
index 662c029..5eecabd 100644
--- a/libsoup/soup-session-sync.c
+++ b/libsoup/soup-session-sync.c
@@ -201,6 +201,8 @@ wait_for_connection (SoupMessageQueueItem *item)
 
 	g_mutex_lock (priv->lock);
 
+	soup_session_cleanup_connections (session, FALSE);
+
  try_again:
 	conn = soup_session_get_connection (session, item, &try_pruning);
 	if (conn) {
@@ -226,8 +228,11 @@ wait_for_connection (SoupMessageQueueItem *item)
 		return conn;
 	}
 
-	if (try_pruning && soup_session_try_prune_connection (session))
-		goto try_again;
+	if (try_pruning) {
+		try_pruning = FALSE;
+		if (soup_session_cleanup_connections (session, TRUE))
+			goto try_again;
+	}
 
 	/* Wait... */
 	g_cond_wait (priv->cond, priv->lock);
diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c
index d4eb1e5..1a778de 100644
--- a/libsoup/soup-session.c
+++ b/libsoup/soup-session.c
@@ -958,38 +958,35 @@ soup_session_send_queue_item (SoupSession *session,
 }
 
 gboolean
-soup_session_try_prune_connection (SoupSession *session)
+soup_session_cleanup_connections (SoupSession *session,
+				  gboolean     prune_idle)
 {
 	SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session);
-	GPtrArray *conns;
+	GSList *conns = NULL, *c;
 	GHashTableIter iter;
 	gpointer conn, host;
-	int i;
-
-	conns = g_ptr_array_new ();
+	SoupConnectionState state;
 
 	g_mutex_lock (priv->host_lock);
 	g_hash_table_iter_init (&iter, priv->conns);
 	while (g_hash_table_iter_next (&iter, &conn, &host)) {
-		/* Don't prune a connection that is currently in use,
-		 * or hasn't been used yet.
-		 */
-		if (soup_connection_get_state (conn) == SOUP_CONNECTION_IDLE &&
-		    soup_connection_last_used (conn) > 0)
-			g_ptr_array_add (conns, g_object_ref (conn));
+		state = soup_connection_get_state (conn);
+		if (state == SOUP_CONNECTION_REMOTE_DISCONNECTED ||
+		    (prune_idle && state == SOUP_CONNECTION_IDLE &&
+		     soup_connection_last_used (conn) > 0))
+			conns = g_slist_prepend (conns, g_object_ref (conn));
 	}
 	g_mutex_unlock (priv->host_lock);
 
-	if (!conns->len) {
-		g_ptr_array_free (conns, TRUE);
+	if (!conns)
 		return FALSE;
-	}
 
-	for (i = 0; i < conns->len; i++) {
-		soup_connection_disconnect (conns->pdata[i]);
-		g_object_unref (conns->pdata[i]);
+	for (c = conns; c; c = c->next) {
+		conn = c->data;
+		soup_connection_disconnect (conn);
+		g_object_unref (conn);
 	}
-	g_ptr_array_free (conns, TRUE);
+	g_slist_free (conns);
 
 	return TRUE;
 }
diff --git a/libsoup/soup-socket.c b/libsoup/soup-socket.c
index 0c06f0f..e804e27 100644
--- a/libsoup/soup-socket.c
+++ b/libsoup/soup-socket.c
@@ -831,6 +831,14 @@ soup_socket_connect_sync (SoupSocket *sock, GCancellable *cancellable)
 	return status;
 }
 
+int
+soup_socket_get_fd (SoupSocket *sock)
+{
+	g_return_val_if_fail (SOUP_IS_SOCKET (sock), -1);
+
+	return SOUP_SOCKET_GET_PRIVATE (sock)->sockfd;
+}
+
 static gboolean
 listen_watch (GIOChannel* iochannel, GIOCondition condition, gpointer data)
 {
diff --git a/libsoup/soup-socket.h b/libsoup/soup-socket.h
index 7b5f58e..079297b 100644
--- a/libsoup/soup-socket.h
+++ b/libsoup/soup-socket.h
@@ -63,6 +63,7 @@ void           soup_socket_connect_async      (SoupSocket         *sock,
 					       gpointer            user_data);
 guint          soup_socket_connect_sync       (SoupSocket         *sock,
 					       GCancellable       *cancellable);
+int            soup_socket_get_fd             (SoupSocket         *sock);
 
 gboolean       soup_socket_listen             (SoupSocket         *sock);
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]