libsoup r1112 - in trunk: . libsoup



Author: danw
Date: Tue Mar 18 23:38:00 2008
New Revision: 1112
URL: http://svn.gnome.org/viewvc/libsoup?rev=1112&view=rev

Log:
	* libsoup/soup-session.c (soup_session_class_init): Add a new
	property, SOUP_SESSION_IDLE_TIMEOUT, to specify a timeout after
	which idle connections should be closed.
	(soup_session_get_connection): pass the idle_timeout value on to
	the connection.

	* libsoup/soup-connection.c (soup_connection_class_init): Add
	SOUP_CONNECTION_IDLE_TIMEOUT.
	(start_idle_timer, stop_idle_timer): add/remove a timeout to call
	soup_connection_disconnect().
	(socket_connect_result, soup_connection_connect_sync): start the
	idle timer after connection is complete
	(set_current_request): call stop_idle_timer() when starting a new
	request
	(clear_current_request): call start_idle_timer() when finishing a
	request
	(dispose): call stop_idle_timer() when destroying the connection

	#518214, based on a patch from Jorn Baayen.


Modified:
   trunk/ChangeLog
   trunk/libsoup/soup-connection.c
   trunk/libsoup/soup-connection.h
   trunk/libsoup/soup-session.c
   trunk/libsoup/soup-session.h

Modified: trunk/libsoup/soup-connection.c
==============================================================================
--- trunk/libsoup/soup-connection.c	(original)
+++ trunk/libsoup/soup-connection.c	Tue Mar 18 23:38:00 2008
@@ -52,7 +52,8 @@
 	SoupMessage *cur_req;
 	time_t       last_used;
 	gboolean     connected, in_use;
-	guint        timeout;
+	guint        io_timeout, idle_timeout;
+	GSource     *idle_timeout_src;
 } SoupConnectionPrivate;
 #define SOUP_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_CONNECTION, SoupConnectionPrivate))
 
@@ -75,6 +76,7 @@
 	PROP_SSL_CREDS,
 	PROP_ASYNC_CONTEXT,
 	PROP_TIMEOUT,
+	PROP_IDLE_TIMEOUT,
 
 	LAST_PROP
 };
@@ -84,14 +86,14 @@
 static void get_property (GObject *object, guint prop_id,
 			  GValue *value, GParamSpec *pspec);
 
+static void stop_idle_timer (SoupConnectionPrivate *priv);
 static void send_request (SoupConnection *conn, SoupMessage *req);
 static void clear_current_request (SoupConnection *conn);
 
 static void
 soup_connection_init (SoupConnection *conn)
 {
-	SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (conn);
-	priv->timeout = 0;
+	;
 }
 
 static void
@@ -114,6 +116,11 @@
 dispose (GObject *object)
 {
 	SoupConnection *conn = SOUP_CONNECTION (object);
+	SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (conn);
+
+	stop_idle_timer (priv);
+	/* Make sure clear_current_request doesn't re-establish the timeout */
+	priv->idle_timeout = 0;
 
 	clear_current_request (conn);
 	soup_connection_disconnect (conn);
@@ -198,6 +205,13 @@
 				   "Value in seconds to timeout a blocking I/O",
 				   0, G_MAXUINT, 0,
 				   G_PARAM_READWRITE));
+	g_object_class_install_property (
+		object_class, PROP_IDLE_TIMEOUT,
+		g_param_spec_uint (SOUP_CONNECTION_IDLE_TIMEOUT,
+				   "Idle Timeout",
+				   "Connection lifetime when idle",
+				   0, G_MAXUINT, 0,
+				   G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 }
 
 
@@ -272,7 +286,10 @@
 			g_main_context_ref (priv->async_context);
 		break;
 	case PROP_TIMEOUT:
-		priv->timeout = g_value_get_uint (value);
+		priv->io_timeout = g_value_get_uint (value);
+		break;
+	case PROP_IDLE_TIMEOUT:
+		priv->idle_timeout = g_value_get_uint (value);
 		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -303,7 +320,10 @@
 		g_value_set_pointer (value, priv->async_context ? g_main_context_ref (priv->async_context) : NULL);
 		break;
 	case PROP_TIMEOUT:
-		g_value_set_uint (value, priv->timeout);
+		g_value_set_uint (value, priv->io_timeout);
+		break;
+	case PROP_IDLE_TIMEOUT:
+		g_value_set_uint (value, priv->idle_timeout);
 		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -311,11 +331,42 @@
 	}
 }
 
+static gboolean
+idle_timeout (gpointer conn)
+{
+	soup_connection_disconnect (conn);
+	return FALSE;
+}
+
+static void
+start_idle_timer (SoupConnection *conn)
+{
+	SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (conn);
+
+	if (priv->idle_timeout > 0 && !priv->idle_timeout_src) {
+		priv->idle_timeout_src =
+			soup_add_timeout (priv->async_context,
+					  priv->idle_timeout * 1000,
+					  idle_timeout, conn);
+	}
+}
+
+static void
+stop_idle_timer (SoupConnectionPrivate *priv)
+{
+	if (priv->idle_timeout_src) {
+		g_source_destroy (priv->idle_timeout_src);
+		priv->idle_timeout_src = NULL;
+	}
+}
+
 static void
 set_current_request (SoupConnectionPrivate *priv, SoupMessage *req)
 {
 	g_return_if_fail (priv->cur_req == NULL);
 
+	stop_idle_timer (priv);
+
 	soup_message_set_io_status (req, SOUP_MESSAGE_IO_STATUS_RUNNING);
 	priv->cur_req = req;
 	priv->in_use = TRUE;
@@ -328,6 +379,7 @@
 	SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (conn);
 
 	priv->in_use = FALSE;
+	start_idle_timer (conn);
 	if (priv->cur_req) {
 		SoupMessage *cur_req = priv->cur_req;
 
@@ -453,6 +505,7 @@
 	}
 
 	priv->connected = TRUE;
+	start_idle_timer (conn);
 
  done:
 	g_signal_emit (conn, signals[CONNECT_RESULT], 0,
@@ -527,7 +580,7 @@
 		soup_socket_new (SOUP_SOCKET_REMOTE_ADDRESS, addr,
 				 SOUP_SOCKET_SSL_CREDENTIALS, priv->ssl_creds,
 				 SOUP_SOCKET_FLAG_NONBLOCKING, FALSE,
-				 SOUP_SOCKET_TIMEOUT, priv->timeout,
+				 SOUP_SOCKET_TIMEOUT, priv->io_timeout,
 				 NULL);
 
 	status = soup_socket_connect_sync (priv->socket, NULL);
@@ -574,9 +627,10 @@
 		}
 	}
 
-	if (SOUP_STATUS_IS_SUCCESSFUL (status))
+	if (SOUP_STATUS_IS_SUCCESSFUL (status)) {
 		priv->connected = TRUE;
-	else {
+		start_idle_timer (conn);
+	} else {
 	fail:
 		if (priv->socket) {
 			g_object_unref (priv->socket);

Modified: trunk/libsoup/soup-connection.h
==============================================================================
--- trunk/libsoup/soup-connection.h	(original)
+++ trunk/libsoup/soup-connection.h	Tue Mar 18 23:38:00 2008
@@ -49,7 +49,8 @@
 #define SOUP_CONNECTION_PROXY_URI       "proxy-uri"
 #define SOUP_CONNECTION_SSL_CREDENTIALS "ssl-creds"
 #define SOUP_CONNECTION_ASYNC_CONTEXT   "async-context"
-#define SOUP_CONNECTION_TIMEOUT		"timeout"
+#define SOUP_CONNECTION_TIMEOUT         "timeout"
+#define SOUP_CONNECTION_IDLE_TIMEOUT    "idle-timeout"
 
 SoupConnection *soup_connection_new            (const char       *propname1,
 						...) G_GNUC_NULL_TERMINATED;

Modified: trunk/libsoup/soup-session.c
==============================================================================
--- trunk/libsoup/soup-session.c	(original)
+++ trunk/libsoup/soup-session.c	Tue Mar 18 23:38:00 2008
@@ -68,8 +68,6 @@
 	SoupURI *proxy_uri;
 	SoupAuth *proxy_auth;
 
-	guint max_conns, max_conns_per_host;
-
 	char *ssl_ca_file;
 	SoupSSLCredentials *ssl_creds;
 
@@ -83,6 +81,8 @@
 	GHashTable *hosts; /* SoupURI -> SoupSessionHost */
 	GHashTable *conns; /* SoupConnection -> SoupSessionHost */
 	guint num_conns;
+	guint max_conns, max_conns_per_host;
+	guint io_timeout, idle_timeout;
 
 	/* Must hold the host_lock before potentially creating a
 	 * new SoupSessionHost, or adding/removing a connection.
@@ -91,11 +91,6 @@
 	GMutex *host_lock;
 
 	GMainContext *async_context;
-
-	/* Holds the timeout value for the connection, when
-	   no response is received.
-	*/
-	guint timeout;
 } SoupSessionPrivate;
 #define SOUP_SESSION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_SESSION, SoupSessionPrivate))
 
@@ -141,6 +136,7 @@
 	PROP_ASYNC_CONTEXT,
 	PROP_TIMEOUT,
 	PROP_USER_AGENT,
+	PROP_IDLE_TIMEOUT,
 
 	LAST_PROP
 };
@@ -165,8 +161,6 @@
 	priv->max_conns = SOUP_SESSION_MAX_CONNS_DEFAULT;
 	priv->max_conns_per_host = SOUP_SESSION_MAX_CONNS_PER_HOST_DEFAULT;
 
-	priv->timeout = 0;
-
 	priv->auth_manager = soup_auth_manager_new (session);
 	soup_auth_manager_add_type (priv->auth_manager, SOUP_TYPE_AUTH_BASIC);
 	soup_auth_manager_add_type (priv->auth_manager, SOUP_TYPE_AUTH_DIGEST);
@@ -410,6 +404,13 @@
 				  SOUP_SESSION_MAX_CONNS_PER_HOST_DEFAULT,
 				  G_PARAM_READWRITE));
 	g_object_class_install_property (
+		object_class, PROP_IDLE_TIMEOUT,
+		g_param_spec_uint (SOUP_SESSION_IDLE_TIMEOUT,
+				   "Idle Timeout",
+				   "Connection lifetime when idle",
+				   0, G_MAXUINT, 0,
+				   G_PARAM_READWRITE));
+	g_object_class_install_property (
 		object_class, PROP_USE_NTLM,
 		g_param_spec_boolean (SOUP_SESSION_USE_NTLM,
 				      "Use NTLM",
@@ -568,7 +569,7 @@
 			g_main_context_ref (priv->async_context);
 		break;
 	case PROP_TIMEOUT:
-		priv->timeout = g_value_get_uint (value);
+		priv->io_timeout = g_value_get_uint (value);
 		break;
 	case PROP_USER_AGENT:
 		g_free (priv->user_agent);
@@ -585,6 +586,9 @@
 		} else
 			priv->user_agent = g_strdup (user_agent);
 		break;
+	case PROP_IDLE_TIMEOUT:
+		priv->idle_timeout = g_value_get_uint (value);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -618,11 +622,14 @@
 		g_value_set_pointer (value, priv->async_context ? g_main_context_ref (priv->async_context) : NULL);
 		break;
 	case PROP_TIMEOUT:
-		g_value_set_uint (value, priv->timeout);
+		g_value_set_uint (value, priv->io_timeout);
 		break;
 	case PROP_USER_AGENT:
 		g_value_set_string (value, priv->user_agent);
 		break;
+	case PROP_IDLE_TIMEOUT:
+		g_value_set_uint (value, priv->idle_timeout);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -1017,7 +1024,8 @@
 		SOUP_CONNECTION_PROXY_URI, priv->proxy_uri,
 		SOUP_CONNECTION_SSL_CREDENTIALS, priv->ssl_creds,
 		SOUP_CONNECTION_ASYNC_CONTEXT, priv->async_context,
-		SOUP_CONNECTION_TIMEOUT, priv->timeout,
+		SOUP_CONNECTION_TIMEOUT, priv->io_timeout,
+		SOUP_CONNECTION_IDLE_TIMEOUT, priv->idle_timeout,
 		NULL);
 	g_signal_connect (conn, "connect_result",
 			  G_CALLBACK (connect_result),

Modified: trunk/libsoup/soup-session.h
==============================================================================
--- trunk/libsoup/soup-session.h	(original)
+++ trunk/libsoup/soup-session.h	Tue Mar 18 23:38:00 2008
@@ -61,8 +61,9 @@
 #define SOUP_SESSION_USE_NTLM           "use-ntlm"
 #define SOUP_SESSION_SSL_CA_FILE        "ssl-ca-file"
 #define SOUP_SESSION_ASYNC_CONTEXT      "async-context"
-#define SOUP_SESSION_TIMEOUT		"timeout"
+#define SOUP_SESSION_TIMEOUT            "timeout"
 #define SOUP_SESSION_USER_AGENT         "user-agent"
+#define SOUP_SESSION_IDLE_TIMEOUT       "idle-timeout"
 
 GMainContext   *soup_session_get_async_context(SoupSession           *session);
 



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