From: Pierre-Luc Beaudoin Date: Sat, 28 Mar 2009 12:49:28 +0000 (+0200) Subject: Use If-Modified-Since to check if tile is up to date. X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=27ed64f16556c1e86d09b2fc2faa25b0f5129008;p=libchamplain Use If-Modified-Since to check if tile is up to date. --- diff --git a/champlain/champlain-debug.c b/champlain/champlain-debug.c index 3c097ef..bd32860 100644 --- a/champlain/champlain-debug.c +++ b/champlain/champlain-debug.c @@ -38,6 +38,7 @@ static GDebugKey keys[] = { { "Loading", CHAMPLAIN_DEBUG_LOADING }, { "Engine", CHAMPLAIN_DEBUG_ENGINE }, { "View", CHAMPLAIN_DEBUG_VIEW }, + { "Network", CHAMPLAIN_DEBUG_NETWORK }, { "Other", CHAMPLAIN_DEBUG_OTHER }, { 0, } }; diff --git a/champlain/champlain-debug.h b/champlain/champlain-debug.h index d60f3ba..1679fa6 100644 --- a/champlain/champlain-debug.h +++ b/champlain/champlain-debug.h @@ -33,7 +33,8 @@ typedef enum CHAMPLAIN_DEBUG_LOADING = 1 << 1, CHAMPLAIN_DEBUG_ENGINE = 1 << 2, CHAMPLAIN_DEBUG_VIEW = 1 << 3, - CHAMPLAIN_DEBUG_OTHER = 1 << 4, + CHAMPLAIN_DEBUG_NETWORK = 1 << 4, + CHAMPLAIN_DEBUG_OTHER = 1 << 5, } ChamplainDebugFlags; gboolean champlain_debug_flag_is_set (ChamplainDebugFlags flag); diff --git a/champlain/champlain-defines.h b/champlain/champlain-defines.h index 771b322..54056b7 100644 --- a/champlain/champlain-defines.h +++ b/champlain/champlain-defines.h @@ -42,6 +42,8 @@ typedef enum CHAMPLAIN_STATE_NONE, CHAMPLAIN_STATE_INIT, CHAMPLAIN_STATE_LOADING, + CHAMPLAIN_STATE_VALIDATING_CACHE, /* Use by tiles when there is cache, + but it is being validated */ CHAMPLAIN_STATE_DONE } ChamplainState; diff --git a/champlain/champlain-network-map-source.c b/champlain/champlain-network-map-source.c index 54c7d6a..de55855 100644 --- a/champlain/champlain-network-map-source.c +++ b/champlain/champlain-network-map-source.c @@ -20,7 +20,7 @@ #include "champlain-network-map-source.h" -#define DEBUG_FLAG CHAMPLAIN_DEBUG_LOADING +#define DEBUG_FLAG CHAMPLAIN_DEBUG_NETWORK #include "champlain-debug.h" #include "champlain.h" @@ -207,9 +207,11 @@ champlain_network_map_source_init (ChamplainNetworkMapSource *champlainMapSource { ChamplainNetworkMapSourcePrivate *priv = GET_PRIVATE (champlainMapSource); + champlainMapSource->priv = priv; + priv->proxy_uri = g_strdup (""); priv->uri_format = NULL; - champlainMapSource->priv = priv; + priv->offline = FALSE; } ChamplainNetworkMapSource* @@ -408,7 +410,33 @@ file_loaded_cb (SoupSession *session, GError *error = NULL; gchar* path = NULL; const gchar *filename = NULL; + ClutterActor *actor, *previous_actor = NULL; + filename = champlain_tile_get_filename (ctx->tile); + + DEBUG ("Got reply %d", msg->status_code); + if (msg->status_code == 304) + { + /* Since we are updating the cache, we can assume that the directories + * exists */ + GTimeVal *now = g_new0 (GTimeVal, 1); + GFile *file; + GFileInfo *info; + + file = g_file_new_for_path (filename); + info = g_file_query_info (file, G_FILE_ATTRIBUTE_TIME_MODIFIED, + G_FILE_QUERY_INFO_NONE, NULL, NULL); + + g_get_current_time (now); + g_file_info_set_modification_time (info, now); + g_file_set_attributes_from_info (file, info, G_FILE_QUERY_INFO_NONE, NULL, + NULL); + + g_object_unref (file); + g_object_unref (info); + g_free (now); + goto finish; + } if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { DEBUG ("Unable to download tile %d, %d: %s", @@ -445,7 +473,6 @@ file_loaded_cb (SoupSession *session, goto cleanup; } - filename = champlain_tile_get_filename (ctx->tile); path = g_path_get_dirname (filename); if (g_mkdir_with_parents (path, 0700) == -1) @@ -470,8 +497,8 @@ file_loaded_cb (SoupSession *session, return; } */ - GdkPixbuf* pixbuf = gdk_pixbuf_loader_get_pixbuf (loader); - ClutterActor *actor = clutter_texture_new (); + GdkPixbuf* pixbuf = gdk_pixbuf_loader_get_pixbuf(loader); + actor = clutter_texture_new(); if (!clutter_texture_set_from_rgb_data (CLUTTER_TEXTURE (actor), gdk_pixbuf_get_pixels (pixbuf), gdk_pixbuf_get_has_alpha (pixbuf), @@ -493,6 +520,10 @@ file_loaded_cb (SoupSession *session, } } + previous_actor = champlain_tile_get_actor (ctx->tile); + if (previous_actor) + g_object_ref (previous_actor); /* to be unrefed by the view */ + champlain_tile_set_actor (ctx->tile, actor); DEBUG ("Tile loaded from network"); @@ -501,7 +532,7 @@ cleanup: g_free (path); finish: champlain_tile_set_state (ctx->tile, CHAMPLAIN_STATE_DONE); - champlain_view_tile_ready (ctx->view, ctx->zoom_level, ctx->tile, TRUE); + champlain_view_tile_updated (ctx->view, ctx->zoom_level, ctx->tile, previous_actor); g_object_unref (ctx->tile); g_object_unref (ctx->zoom_level); g_free (ctx); @@ -514,17 +545,13 @@ champlain_network_map_source_get_tile (ChamplainMapSource *map_source, ChamplainTile *tile) { gchar* filename; - gboolean use_cache = FALSE; + gboolean in_cache = FALSE; + gboolean validate_cache = FALSE; + GTimeVal *modified_time = g_new0 (GTimeVal, 1); ChamplainNetworkMapSource *network_map_source = CHAMPLAIN_NETWORK_MAP_SOURCE (map_source); ChamplainNetworkMapSourcePrivate *priv = network_map_source->priv; - /* Ref the tile as it may be freeing during the loading - * Unref when the loading is done. - */ - g_object_ref (tile); - g_object_ref (zoom_level); - /* Try the cached version first */ filename = get_filename (network_map_source, zoom_level, tile); champlain_tile_set_filename (tile, filename); @@ -532,43 +559,44 @@ champlain_network_map_source_get_tile (ChamplainMapSource *map_source, if (g_file_test (filename, G_FILE_TEST_EXISTS)) { - GTimeVal *date = g_new0 (GTimeVal, 1); GTimeVal *now = g_new0 (GTimeVal, 1); GFileInfo *info; GFile *file; + GError *error = NULL; + ClutterActor *actor; + in_cache = TRUE; + + /* Verify since when is the file in cache */ file = g_file_new_for_path (filename); info = g_file_query_info (file, G_FILE_ATTRIBUTE_TIME_MODIFIED, G_FILE_QUERY_INFO_NONE, NULL, NULL); - g_file_info_get_modification_time (info, date); + g_file_info_get_modification_time (info, modified_time); g_get_current_time (now); - g_time_val_add (date, (24ul * 60ul * 60ul * 1000ul * 1000ul)); // Cache expires 1 day - use_cache = date->tv_sec > now->tv_sec; + g_time_val_add (now, (-60ul * 60ul * 1000ul * 1000ul)); // Cache expires 1 hour + validate_cache = modified_time->tv_sec < now->tv_sec; g_object_unref (file); g_object_unref (info); - g_free (date); g_free (now); - } - else - use_cache = FALSE; - - if (use_cache == TRUE) - { - GError *error = NULL; - ClutterActor *actor; + /* Load the cached version */ actor = clutter_texture_new_from_file (filename, &error); champlain_tile_set_actor (tile, actor); - champlain_tile_set_state (tile, CHAMPLAIN_STATE_DONE); + if (validate_cache == TRUE) + champlain_tile_set_state (tile, CHAMPLAIN_STATE_VALIDATING_CACHE); + else + champlain_tile_set_state (tile, CHAMPLAIN_STATE_DONE); + DEBUG ("Tile loaded from cache"); - champlain_view_tile_ready (view, zoom_level, tile, FALSE); - g_object_unref (tile); - g_object_unref (zoom_level); + champlain_view_tile_ready (view, zoom_level, tile); } - else if (!priv->offline) + + + if ((in_cache == FALSE || (in_cache == TRUE && validate_cache == TRUE)) && + priv->offline == FALSE) { SoupMessage *msg; gchar *uri; @@ -577,6 +605,12 @@ champlain_network_map_source_get_tile (ChamplainMapSource *map_source, ctx->zoom_level = zoom_level; ctx->tile = tile; + /* Ref the tile as it may be freeing during the loading + * Unref when the loading is done. + */ + g_object_ref (tile); + g_object_ref (zoom_level); + if (!soup_session) soup_session = soup_session_async_new_with_options ("proxy-uri", soup_uri_new (priv->proxy_uri), @@ -592,6 +626,18 @@ champlain_network_map_source_get_tile (ChamplainMapSource *map_source, champlain_tile_set_state (tile, CHAMPLAIN_STATE_LOADING); msg = soup_message_new (SOUP_METHOD_GET, uri); + if (in_cache == TRUE) + { + char value [100]; + struct tm *other_time = gmtime (&modified_time->tv_sec); + + strftime (value, 100, "%a, %d %b %Y %T %Z", other_time); + + DEBUG("Header %s", value); + soup_message_headers_append (msg->request_headers, + "If-Modified-Since", g_strdup (value)); + } + soup_session_queue_message (soup_session, msg, file_loaded_cb, ctx); @@ -601,5 +647,6 @@ champlain_network_map_source_get_tile (ChamplainMapSource *map_source, /* If a tile is neither in cache or can be fetched, do nothing, it'll show up * as empty */ + g_free (modified_time); } diff --git a/champlain/champlain-view.c b/champlain/champlain-view.c index 2f987a6..ca4a766 100644 --- a/champlain/champlain-view.c +++ b/champlain/champlain-view.c @@ -1476,19 +1476,41 @@ view_tiles_reposition (ChamplainView* view) void champlain_view_tile_ready (ChamplainView *view, ChamplainZoomLevel *level, - ChamplainTile *tile, - gboolean animate) + ChamplainTile *tile) +{ + ClutterActor *actor; + + actor = champlain_tile_get_actor (tile); + + clutter_container_add (CLUTTER_CONTAINER (champlain_zoom_level_get_actor (level)), actor, NULL); + clutter_actor_show (actor); + + view_position_tile (view, tile); + view_update_state (view); +} + +void +champlain_view_tile_updated (ChamplainView *view, + ChamplainZoomLevel *level, + ChamplainTile *tile, + ClutterActor *previous_actor) { ClutterActor *actor; ClutterEffectTemplate *etemplate; actor = champlain_tile_get_actor (tile); - if (animate) - { - etemplate = clutter_effect_template_new_for_duration (750, CLUTTER_ALPHA_SINE_INC); - clutter_actor_set_opacity(actor, 0); - clutter_effect_fade (etemplate, actor, 255, NULL, NULL); - } + if (previous_actor != NULL) + { + /* TODO: Don't remove until the fade in the of new time is over */ + clutter_container_remove_actor (CLUTTER_CONTAINER (champlain_zoom_level_get_actor (level)), + previous_actor); + g_object_unref (previous_actor); + } + + /* FIXME: etemplate are leaked here */ + etemplate = clutter_effect_template_new_for_duration (750, CLUTTER_ALPHA_SINE_INC); + clutter_actor_set_opacity(actor, 0); + clutter_effect_fade (etemplate, actor, 255, NULL, NULL); clutter_container_add (CLUTTER_CONTAINER (champlain_zoom_level_get_actor (level)), actor, NULL); clutter_actor_show (actor); diff --git a/champlain/champlain-view.h b/champlain/champlain-view.h index d93037d..ab679c5 100644 --- a/champlain/champlain-view.h +++ b/champlain/champlain-view.h @@ -130,9 +130,12 @@ gboolean champlain_view_get_coords_at (ChamplainView *view, gdouble *lon); void champlain_view_tile_ready (ChamplainView *view, + ChamplainZoomLevel *level, + ChamplainTile *tile); +void champlain_view_tile_updated (ChamplainView *view, ChamplainZoomLevel *level, ChamplainTile *tile, - gboolean animate); + ClutterActor *actor); G_END_DECLS