[libsoup] soup-session: move cache handling here



commit b55d54a50ab5586dba439cdadde9418f0ae96783
Author: Dan Winship <danw gnome org>
Date:   Wed Dec 26 14:50:11 2012 -0500

    soup-session: move cache handling here
    
    Move the SoupCache special handling from SoupRequestHTTP to
    SoupSession (as another step towards making SoupCache not such a
    magical special case hack that only works in certain situations).

 libsoup/soup-message-queue.h |    1 +
 libsoup/soup-request-http.c  |  111 -------------------------------------
 libsoup/soup-session.c       |  125 +++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 125 insertions(+), 112 deletions(-)
---
diff --git a/libsoup/soup-message-queue.h b/libsoup/soup-message-queue.h
index dd61924..490f9a2 100644
--- a/libsoup/soup-message-queue.h
+++ b/libsoup/soup-message-queue.h
@@ -22,6 +22,7 @@ typedef enum {
 	SOUP_MESSAGE_TUNNELED,
 	SOUP_MESSAGE_READY,
 	SOUP_MESSAGE_RUNNING,
+	SOUP_MESSAGE_CACHED,
 	SOUP_MESSAGE_RESTARTING,
 	SOUP_MESSAGE_FINISHING,
 	SOUP_MESSAGE_FINISHED
diff --git a/libsoup/soup-request-http.c b/libsoup/soup-request-http.c
index fe1a974..15e087a 100644
--- a/libsoup/soup-request-http.c
+++ b/libsoup/soup-request-http.c
@@ -29,7 +29,6 @@
 
 #include "soup-request-http.h"
 #include "soup.h"
-#include "soup-cache-private.h"
 #include "soup-message-private.h"
 #include "soup-session-private.h"
 
@@ -256,20 +255,6 @@ soup_request_http_send (SoupRequest          *request,
 }
 
 
-typedef struct {
-	SoupMessage *original;
-	GInputStream *stream;
-} SendAsyncData;
-
-static void
-free_send_async_data (SendAsyncData *sadata)
-{
-       g_clear_object (&sadata->stream);
-       g_clear_object (&sadata->original);
-
-       g_slice_free (SendAsyncData, sadata);
-}
-
 static void
 http_input_stream_ready_cb (GObject *source, GAsyncResult *result, gpointer user_data)
 {
@@ -286,59 +271,6 @@ http_input_stream_ready_cb (GObject *source, GAsyncResult *result, gpointer user
 }
 
 static void
-conditional_get_ready_cb (SoupSession *session, SoupMessage *msg, gpointer user_data)
-{
-	GTask *task = user_data;
-	SoupRequestHTTP *http = g_task_get_source_object (task);
-	SendAsyncData *sadata = g_task_get_task_data (task);
-	GInputStream *stream;
-
-	if (msg->status_code == SOUP_STATUS_NOT_MODIFIED) {
-		SoupCache *cache = (SoupCache *)soup_session_get_feature (session, SOUP_TYPE_CACHE);
-
-		stream = soup_cache_send_response (cache, sadata->original);
-		if (stream) {
-			soup_message_got_headers (sadata->original);
-			soup_message_finished (sadata->original);
-
-			http->priv->content_type = g_strdup (soup_message_headers_get_content_type (msg->response_headers, NULL));
-
-			g_task_return_pointer (task, stream, g_object_unref);
-			g_object_unref (task);
-			return;
-		}
-	}
-
-	/* The resource was modified or the server returned a 200
-	 * OK. Either way we reload it. This is far from optimal as
-	 * we're donwloading the resource twice, but we will change it
-	 * once the cache is integrated in the streams stack.
-	 */
-	soup_session_send_request_async (session, sadata->original,
-					 g_task_get_cancellable (task),
-					 http_input_stream_ready_cb, task);
-}
-
-static gboolean
-idle_return_from_cache_cb (gpointer data)
-{
-	GTask *task = data;
-	SoupRequestHTTP *http = g_task_get_source_object (task);
-	SendAsyncData *sadata = g_task_get_task_data (task);
-
-	/* Issue signals  */
-	soup_message_got_headers (http->priv->msg);
-	soup_message_finished (http->priv->msg);
-
-	http->priv->content_type = g_strdup (soup_message_headers_get_content_type (http->priv->msg->response_headers, NULL));
-
-	g_task_return_pointer (task, g_object_ref (sadata->stream), g_object_unref);
-	g_object_unref (task);
-
-	return FALSE;
-}
-
-static void
 soup_request_http_send_async (SoupRequest          *request,
 			      GCancellable         *cancellable,
 			      GAsyncReadyCallback   callback,
@@ -347,55 +279,12 @@ soup_request_http_send_async (SoupRequest          *request,
 	SoupRequestHTTP *http = SOUP_REQUEST_HTTP (request);
 	SoupSession *session = soup_request_get_session (request);
 	GTask *task;
-	SendAsyncData *sadata;
-	GInputStream *stream;
-	SoupCache *cache;
 
 	g_return_if_fail (!SOUP_IS_SESSION_SYNC (session));
 
 	http->priv->sent = TRUE;
 
 	task = g_task_new (request, cancellable, callback, user_data);
-	sadata = g_slice_new0 (SendAsyncData);
-	g_task_set_task_data (task, sadata, (GDestroyNotify)free_send_async_data);
-
-	cache = (SoupCache *)soup_session_get_feature (session, SOUP_TYPE_CACHE);
-
-	if (cache) {
-		SoupCacheResponse response;
-
-		response = soup_cache_has_response (cache, http->priv->msg);
-		if (response == SOUP_CACHE_RESPONSE_FRESH) {
-			stream = soup_cache_send_response (cache, http->priv->msg);
-
-			/* Cached resource file could have been deleted outside */
-			if (stream) {
-				/* Do return the stream asynchronously as in
-				 * the other cases. It's not enough to let
-				 * GTask do the asynchrony for us, because
-				 * the signals must be also emitted
-				 * asynchronously
-				 */
-				sadata->stream = stream;
-				soup_add_completion (soup_session_get_async_context (session),
-						     idle_return_from_cache_cb, task);
-				return;
-			}
-		} else if (response == SOUP_CACHE_RESPONSE_NEEDS_VALIDATION) {
-			SoupMessage *conditional_msg;
-
-			conditional_msg = soup_cache_generate_conditional_request (cache, http->priv->msg);
-
-			if (conditional_msg) {
-				sadata->original = g_object_ref (http->priv->msg);
-				soup_session_queue_message (session, conditional_msg,
-							    conditional_get_ready_cb,
-							    task);
-				return;
-			}
-		}
-	}
-
 	soup_session_send_request_async (session, http->priv->msg, cancellable,
 					 http_input_stream_ready_cb, task);
 }
diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c
index f44bf8e..cfcadb2 100644
--- a/libsoup/soup-session.c
+++ b/libsoup/soup-session.c
@@ -14,6 +14,7 @@
 #include "soup-session.h"
 #include "soup.h"
 #include "soup-auth-manager-ntlm.h"
+#include "soup-cache-private.h"
 #include "soup-connection.h"
 #include "soup-marshal.h"
 #include "soup-message-private.h"
@@ -1780,6 +1781,10 @@ soup_session_process_queue_item (SoupSession          *session,
 			item->state = SOUP_MESSAGE_FINISHING;
 			break;
 
+		case SOUP_MESSAGE_CACHED:
+			/* Will be handled elsewhere */
+			return;
+
 		case SOUP_MESSAGE_RESTARTING:
 			item->state = SOUP_MESSAGE_STARTING;
 			soup_message_restarted (item->msg);
@@ -3551,6 +3556,121 @@ async_send_request_running (SoupSession *session, SoupMessageQueueItem *item)
 	try_run_until_read (item);
 }
 
+static void
+async_return_from_cache (SoupMessageQueueItem *item,
+			 GInputStream         *stream)
+{
+	const char *content_type;
+	GHashTable *params;
+
+	soup_message_got_headers (item->msg);
+
+	content_type = soup_message_headers_get_content_type (item->msg->response_headers, &params);
+	soup_message_content_sniffed (item->msg, content_type, params);
+	g_hash_table_unref (params);
+
+	item->state = SOUP_MESSAGE_FINISHING;
+	async_send_request_return_result (item, g_object_ref (stream), NULL);
+}
+
+static void
+conditional_get_ready_cb (SoupSession *session, SoupMessage *msg, gpointer user_data)
+{
+	SoupMessageQueueItem *item = user_data;
+	GInputStream *stream;
+
+	if (msg->status_code == SOUP_STATUS_NOT_MODIFIED) {
+		SoupCache *cache = (SoupCache *)soup_session_get_feature (session, SOUP_TYPE_CACHE);
+
+		stream = soup_cache_send_response (cache, item->msg);
+		if (stream) {
+			async_return_from_cache (item, stream);
+			g_object_unref (stream);
+			return;
+		}
+	}
+
+	/* The resource was modified or the server returned a 200
+	 * OK. Either way we reload it. FIXME.
+	 */
+	item->state = SOUP_MESSAGE_STARTING;
+	soup_session_kick_queue (session);
+}
+
+typedef struct {
+	SoupMessageQueueItem *item;
+	GInputStream *stream;
+} SendAsyncCacheData;
+
+static void
+free_send_async_cache_data (SendAsyncCacheData *sacd)
+{
+	soup_message_queue_item_unref (sacd->item);
+	g_object_unref (sacd->stream);
+	g_slice_free (SendAsyncCacheData, sacd);
+}
+
+static gboolean
+idle_return_from_cache_cb (gpointer data)
+{
+	GTask *task = data;
+	SendAsyncCacheData *sacd = g_task_get_task_data (task);
+
+	async_return_from_cache (sacd->item, sacd->stream);
+	return FALSE;
+}
+
+static gboolean
+async_respond_from_cache (SoupSession          *session,
+			  SoupMessageQueueItem *item)
+{
+	SoupCache *cache;
+	SoupCacheResponse response;
+
+	cache = (SoupCache *)soup_session_get_feature (session, SOUP_TYPE_CACHE);
+	if (!cache)
+		return FALSE;
+
+	response = soup_cache_has_response (cache, item->msg);
+	if (response == SOUP_CACHE_RESPONSE_FRESH) {
+		GInputStream *stream;
+		SendAsyncCacheData *sacd;
+		GSource *source;
+
+		stream = soup_cache_send_response (cache, item->msg);
+		if (!stream) {
+			/* Cached file was deleted? */
+			return FALSE;
+		}
+
+		sacd = g_slice_new (SendAsyncCacheData);
+		sacd->item = item;
+		soup_message_queue_item_ref (item);
+		sacd->stream = stream;
+
+		g_task_set_task_data (item->task, sacd,
+				      (GDestroyNotify) free_send_async_cache_data);
+
+		source = g_timeout_source_new (0);
+		g_task_attach_source (item->task, source,
+				      (GSourceFunc) idle_return_from_cache_cb);
+		g_source_unref (source);
+		return TRUE;
+	} else if (response == SOUP_CACHE_RESPONSE_NEEDS_VALIDATION) {
+		SoupMessage *conditional_msg;
+
+		conditional_msg = soup_cache_generate_conditional_request (cache, item->msg);
+		if (!conditional_msg)
+			return FALSE;
+
+		soup_session_queue_message (session, conditional_msg,
+					    conditional_get_ready_cb,
+					    item);
+		return TRUE;
+	} else
+		return FALSE;
+}
+
 void
 soup_session_send_request_async (SoupSession         *session,
 				 SoupMessage         *msg,
@@ -3585,7 +3705,10 @@ soup_session_send_request_async (SoupSession         *session,
 		item->cancellable = g_object_ref (cancellable);
 	}
 
-	soup_session_kick_queue (session);
+	if (async_respond_from_cache (session, item))
+		item->state = SOUP_MESSAGE_CACHED;
+	else
+		soup_session_kick_queue (session);
 }
 
 GInputStream *



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