[libsoup] soup-session: move cache handling here
- From: Dan Winship <danw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libsoup] soup-session: move cache handling here
- Date: Wed, 26 Dec 2012 20:23:44 +0000 (UTC)
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, ¶ms);
+ 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]