Commit 2841c81b authored by Jiří Techet's avatar Jiří Techet

Introduce new memory cache and remove non-persistent file cache

The new memory cache can store specified number of tiles in
memory without storing them to the disk. It replaces
the temporary file cache - it was a bit scary to recursively
delete some directories and libchamplain shouldn't do things
like that.
Signed-off-by: 's avatarJiří Techet <techet@gmail.com>
parent 537d540c
...@@ -34,6 +34,7 @@ libchamplain_headers = \ ...@@ -34,6 +34,7 @@ libchamplain_headers = \
champlain-map-source-chain.h \ champlain-map-source-chain.h \
champlain-tile-source.h \ champlain-tile-source.h \
champlain-tile-cache.h \ champlain-tile-cache.h \
champlain-memory-cache.h \
champlain-network-tile-source.h \ champlain-network-tile-source.h \
champlain-file-cache.h \ champlain-file-cache.h \
champlain-map-source-factory.h \ champlain-map-source-factory.h \
...@@ -70,6 +71,7 @@ libchamplain_@CHAMPLAIN_API_VERSION@_la_SOURCES = \ ...@@ -70,6 +71,7 @@ libchamplain_@CHAMPLAIN_API_VERSION@_la_SOURCES = \
champlain-map-source-chain.c \ champlain-map-source-chain.c \
champlain-tile-source.c \ champlain-tile-source.c \
champlain-tile-cache.c \ champlain-tile-cache.c \
champlain-memory-cache.c \
champlain-network-tile-source.c \ champlain-network-tile-source.c \
champlain-file-cache.c \ champlain-file-cache.c \
champlain-map-source-factory.c \ champlain-map-source-factory.c \
...@@ -101,6 +103,7 @@ libchamplain_include_HEADERS = \ ...@@ -101,6 +103,7 @@ libchamplain_include_HEADERS = \
champlain-map-source-chain.h \ champlain-map-source-chain.h \
champlain-tile-source.h \ champlain-tile-source.h \
champlain-tile-cache.h \ champlain-tile-cache.h \
champlain-memory-cache.h \
champlain-network-tile-source.h \ champlain-network-tile-source.h \
champlain-file-cache.h \ champlain-file-cache.h \
champlain-map-source-factory.h \ champlain-map-source-factory.h \
......
...@@ -22,8 +22,7 @@ ...@@ -22,8 +22,7 @@
* @short_description: Stores and loads cached tiles from the file system * @short_description: Stores and loads cached tiles from the file system
* *
* #ChamplainFileCache is a map source that stores and retrieves tiles from the * #ChamplainFileCache is a map source that stores and retrieves tiles from the
* file system. It can be temporary (deleted when the object is destroyed) or * file system. Tiles most frequently loaded gain in "popularity". This popularity
* permanent. Tiles most frequently loaded gain in "popularity". This popularity
* is taken into account when purging the cache. * is taken into account when purging the cache.
*/ */
...@@ -55,14 +54,12 @@ struct _ChamplainFileCachePrivate ...@@ -55,14 +54,12 @@ struct _ChamplainFileCachePrivate
guint size_limit; guint size_limit;
gchar *cache_dir; gchar *cache_dir;
gchar *real_cache_dir;
sqlite3 *db; sqlite3 *db;
sqlite3_stmt *stmt_select; sqlite3_stmt *stmt_select;
sqlite3_stmt *stmt_update; sqlite3_stmt *stmt_update;
}; };
static void finalize_sql (ChamplainFileCache *file_cache); static void finalize_sql (ChamplainFileCache *file_cache);
static void delete_temp_cache (ChamplainFileCache *file_cache);
static void init_cache (ChamplainFileCache *file_cache); static void init_cache (ChamplainFileCache *file_cache);
static gchar *get_filename (ChamplainFileCache *file_cache, static gchar *get_filename (ChamplainFileCache *file_cache,
ChamplainTile *tile); ChamplainTile *tile);
...@@ -70,7 +67,6 @@ static gboolean tile_is_expired (ChamplainFileCache *file_cache, ...@@ -70,7 +67,6 @@ static gboolean tile_is_expired (ChamplainFileCache *file_cache,
ChamplainTile *tile); ChamplainTile *tile);
static void delete_tile (ChamplainFileCache *file_cache, static void delete_tile (ChamplainFileCache *file_cache,
const gchar *filename); const gchar *filename);
static void delete_dir_recursive (GFile *parent);
static gboolean create_cache_dir (const gchar *dir_name); static gboolean create_cache_dir (const gchar *dir_name);
static void fill_tile (ChamplainMapSource *map_source, static void fill_tile (ChamplainMapSource *map_source,
...@@ -84,7 +80,6 @@ static void refresh_tile_time (ChamplainTileCache *tile_cache, ...@@ -84,7 +80,6 @@ static void refresh_tile_time (ChamplainTileCache *tile_cache,
ChamplainTile *tile); ChamplainTile *tile);
static void on_tile_filled (ChamplainTileCache *tile_cache, static void on_tile_filled (ChamplainTileCache *tile_cache,
ChamplainTile *tile); ChamplainTile *tile);
static void clean (ChamplainTileCache *tile_cache);
static void static void
champlain_file_cache_get_property (GObject *object, champlain_file_cache_get_property (GObject *object,
...@@ -164,41 +159,16 @@ finalize_sql (ChamplainFileCache *file_cache) ...@@ -164,41 +159,16 @@ finalize_sql (ChamplainFileCache *file_cache)
} }
} }
static void
delete_temp_cache (ChamplainFileCache *file_cache)
{
ChamplainTileCache *tile_cache = CHAMPLAIN_TILE_CACHE(file_cache);
ChamplainFileCachePrivate *priv = file_cache->priv;
if (!champlain_tile_cache_get_persistent (tile_cache) && priv->real_cache_dir)
{
GFile *file = NULL;
/* delete the directory contents */
file = g_file_new_for_path (priv->real_cache_dir);
delete_dir_recursive (file);
/* delete the directory itself */
if (!g_file_delete (file, NULL, NULL))
g_warning ("Failed to remove temporary cache main directory");
g_object_unref (file);
}
}
static void static void
champlain_file_cache_finalize (GObject *object) champlain_file_cache_finalize (GObject *object)
{ {
ChamplainFileCache *file_cache = CHAMPLAIN_FILE_CACHE(object); ChamplainFileCache *file_cache = CHAMPLAIN_FILE_CACHE(object);
ChamplainTileCache *tile_cache = CHAMPLAIN_TILE_CACHE(file_cache);
ChamplainFileCachePrivate *priv = file_cache->priv; ChamplainFileCachePrivate *priv = file_cache->priv;
finalize_sql (file_cache); finalize_sql (file_cache);
if (!champlain_tile_cache_get_persistent (tile_cache))
delete_temp_cache (file_cache);
g_free (priv->real_cache_dir);
g_free (priv->cache_dir); g_free (priv->cache_dir);
G_OBJECT_CLASS (champlain_file_cache_parent_class)->finalize (object); G_OBJECT_CLASS (champlain_file_cache_parent_class)->finalize (object);
...@@ -220,64 +190,18 @@ create_cache_dir (const gchar *dir_name) ...@@ -220,64 +190,18 @@ create_cache_dir (const gchar *dir_name)
return TRUE; return TRUE;
} }
#ifdef G_OS_WIN32
#include <io.h>
#include <glib/gstdio.h>
static char *mkdtemp(char *template)
{
gunichar2 *wtemplate;
gchar *tmpl;
if (!template)
return NULL;
wtemplate = g_utf8_to_utf16 (template, -1, NULL, NULL, NULL);
if (!_wmktemp (wtemplate)) {
g_free (wtemplate);
return NULL;
}
tmpl = g_utf16_to_utf8 (wtemplate, -1, NULL, NULL, NULL);
g_free (wtemplate);
if ((strlen (template) != strlen (tmpl)) || g_mkdir (tmpl, 0700)) {
g_free (tmpl);
return NULL;
}
strcpy (template,tmpl);
g_free (tmpl);
return template;
}
#endif
static void static void
init_cache (ChamplainFileCache *file_cache) init_cache (ChamplainFileCache *file_cache)
{ {
ChamplainTileCache *tile_cache = CHAMPLAIN_TILE_CACHE(file_cache);
ChamplainFileCachePrivate *priv = file_cache->priv; ChamplainFileCachePrivate *priv = file_cache->priv;
gchar *filename = NULL; gchar *filename = NULL;
gchar *error_msg = NULL; gchar *error_msg = NULL;
gint error; gint error;
if (champlain_tile_cache_get_persistent (tile_cache)) g_return_if_fail (create_cache_dir (priv->cache_dir));
{
priv->real_cache_dir = g_strdup (priv->cache_dir);
g_return_if_fail (create_cache_dir (priv->real_cache_dir));
}
else
{
/* Create temporary directory for non-persistent caches */
gchar *tmplate = NULL;
tmplate = g_build_filename (priv->cache_dir, "champlain-XXXXXX", NULL);
priv->real_cache_dir = mkdtemp (tmplate);
if (!priv->real_cache_dir)
{
g_warning ("Failed to create filename for temporary cache: template '%s'", tmplate);
g_free (tmplate);
return;
}
}
filename = g_build_filename (priv->real_cache_dir, filename = g_build_filename (priv->cache_dir,
"cache.db", NULL); "cache.db", NULL);
error = sqlite3_open_v2 (filename, &priv->db, error = sqlite3_open_v2 (filename, &priv->db,
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL); SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
...@@ -343,23 +267,17 @@ static void ...@@ -343,23 +267,17 @@ static void
champlain_file_cache_constructed (GObject *object) champlain_file_cache_constructed (GObject *object)
{ {
ChamplainFileCache *file_cache = CHAMPLAIN_FILE_CACHE(object); ChamplainFileCache *file_cache = CHAMPLAIN_FILE_CACHE(object);
ChamplainTileCache *tile_cache = CHAMPLAIN_TILE_CACHE(file_cache);
ChamplainFileCachePrivate *priv = file_cache->priv; ChamplainFileCachePrivate *priv = file_cache->priv;
if (!priv->cache_dir) if (!priv->cache_dir)
{ {
if (champlain_tile_cache_get_persistent (tile_cache))
{
#ifdef CHAMPLAIN_HAS_MAEMO #ifdef CHAMPLAIN_HAS_MAEMO
priv->cache_dir = g_strdup ("/home/user/MyDocs/.Maps/"); priv->cache_dir = g_strdup ("/home/user/MyDocs/.Maps/");
#else #else
priv->cache_dir = g_build_path (G_DIR_SEPARATOR_S, priv->cache_dir = g_build_path (G_DIR_SEPARATOR_S,
g_get_user_cache_dir (), g_get_user_cache_dir (),
"champlain", NULL); "champlain", NULL);
#endif #endif
}
else
priv->cache_dir = g_strdup (g_get_tmp_dir ());
} }
init_cache (file_cache); init_cache (file_cache);
...@@ -419,7 +337,6 @@ champlain_file_cache_class_init (ChamplainFileCacheClass *klass) ...@@ -419,7 +337,6 @@ champlain_file_cache_class_init (ChamplainFileCacheClass *klass)
tile_cache_class->store_tile = store_tile; tile_cache_class->store_tile = store_tile;
tile_cache_class->refresh_tile_time = refresh_tile_time; tile_cache_class->refresh_tile_time = refresh_tile_time;
tile_cache_class->on_tile_filled = on_tile_filled; tile_cache_class->on_tile_filled = on_tile_filled;
tile_cache_class->clean = clean;
map_source_class->fill_tile = fill_tile; map_source_class->fill_tile = fill_tile;
} }
...@@ -433,7 +350,7 @@ champlain_file_cache_init (ChamplainFileCache *file_cache) ...@@ -433,7 +350,7 @@ champlain_file_cache_init (ChamplainFileCache *file_cache)
priv->cache_dir = NULL; priv->cache_dir = NULL;
priv->size_limit = 100000000; priv->size_limit = 100000000;
priv->real_cache_dir = NULL; priv->cache_dir = NULL;
priv->db = NULL; priv->db = NULL;
priv->stmt_select = NULL; priv->stmt_select = NULL;
priv->stmt_update = NULL; priv->stmt_update = NULL;
...@@ -444,7 +361,7 @@ champlain_file_cache_init (ChamplainFileCache *file_cache) ...@@ -444,7 +361,7 @@ champlain_file_cache_init (ChamplainFileCache *file_cache)
* *
* Default constructor of #ChamplainFileCache. * Default constructor of #ChamplainFileCache.
* *
* Returns: a constructed permanent cache of maximal size 100000000 B inside * Returns: a constructed cache of maximal size 100000000 B inside
* ~/.cache/champlain. * ~/.cache/champlain.
* *
* Since: 0.6 * Since: 0.6
...@@ -459,10 +376,7 @@ ChamplainFileCache* champlain_file_cache_new (void) ...@@ -459,10 +376,7 @@ ChamplainFileCache* champlain_file_cache_new (void)
* @size_limit: maximal size of the cache in bytes * @size_limit: maximal size of the cache in bytes
* @cache_dir: the directory where the cache is created. For temporary caches * @cache_dir: the directory where the cache is created. For temporary caches
* one more directory with random name is created inside this directory. * one more directory with random name is created inside this directory.
* When cache_dir == NULL, a cache in ~/.cache/champlain is used for permanent * When cache_dir == NULL, a cache in ~/.cache/champlain is used.
* caches and /tmp for temporary caches.
* @persistent: if TRUE, the cache is persistent; otherwise the cache is
* temporary and will be deleted when the cache object is destructed.
* *
* Constructor of #ChamplainFileCache. * Constructor of #ChamplainFileCache.
* *
...@@ -471,12 +385,11 @@ ChamplainFileCache* champlain_file_cache_new (void) ...@@ -471,12 +385,11 @@ ChamplainFileCache* champlain_file_cache_new (void)
* Since: 0.6 * Since: 0.6
*/ */
ChamplainFileCache* champlain_file_cache_new_full (guint size_limit, ChamplainFileCache* champlain_file_cache_new_full (guint size_limit,
const gchar *cache_dir, const gchar *cache_dir)
gboolean persistent)
{ {
ChamplainFileCache * cache; ChamplainFileCache * cache;
cache = g_object_new (CHAMPLAIN_TYPE_FILE_CACHE, "size-limit", size_limit, cache = g_object_new (CHAMPLAIN_TYPE_FILE_CACHE, "size-limit", size_limit,
"cache-dir", cache_dir, "persistent-cache", persistent, NULL); "cache-dir", cache_dir, NULL);
return cache; return cache;
} }
...@@ -545,7 +458,7 @@ get_filename (ChamplainFileCache *file_cache, ...@@ -545,7 +458,7 @@ get_filename (ChamplainFileCache *file_cache,
g_return_val_if_fail (CHAMPLAIN_IS_FILE_CACHE (file_cache), NULL); g_return_val_if_fail (CHAMPLAIN_IS_FILE_CACHE (file_cache), NULL);
g_return_val_if_fail (CHAMPLAIN_IS_TILE (tile), NULL); g_return_val_if_fail (CHAMPLAIN_IS_TILE (tile), NULL);
g_return_val_if_fail (priv->real_cache_dir, NULL); g_return_val_if_fail (priv->cache_dir, NULL);
ChamplainMapSource* map_source = CHAMPLAIN_MAP_SOURCE(file_cache); ChamplainMapSource* map_source = CHAMPLAIN_MAP_SOURCE(file_cache);
...@@ -553,7 +466,7 @@ get_filename (ChamplainFileCache *file_cache, ...@@ -553,7 +466,7 @@ get_filename (ChamplainFileCache *file_cache,
"%s" G_DIR_SEPARATOR_S "%s" G_DIR_SEPARATOR_S
"%d" G_DIR_SEPARATOR_S "%d" G_DIR_SEPARATOR_S
"%d" G_DIR_SEPARATOR_S "%d.png", "%d" G_DIR_SEPARATOR_S "%d.png",
priv->real_cache_dir, priv->cache_dir,
champlain_map_source_get_id (map_source), champlain_map_source_get_id (map_source),
champlain_tile_get_zoom_level (tile), champlain_tile_get_zoom_level (tile),
champlain_tile_get_x (tile), champlain_tile_get_x (tile),
...@@ -784,9 +697,7 @@ refresh_tile_time (ChamplainTileCache *tile_cache, ...@@ -784,9 +697,7 @@ refresh_tile_time (ChamplainTileCache *tile_cache,
g_object_unref (info); g_object_unref (info);
if (CHAMPLAIN_IS_TILE_CACHE(next_source)) if (CHAMPLAIN_IS_TILE_CACHE(next_source))
{ champlain_tile_cache_refresh_tile_time (CHAMPLAIN_TILE_CACHE(next_source), tile);
refresh_tile_time (CHAMPLAIN_TILE_CACHE(next_source), tile);
}
} }
static void static void
...@@ -863,7 +774,7 @@ store_tile (ChamplainTileCache *tile_cache, ...@@ -863,7 +774,7 @@ store_tile (ChamplainTileCache *tile_cache,
store_next: store_next:
if (CHAMPLAIN_IS_TILE_CACHE(next_source)) if (CHAMPLAIN_IS_TILE_CACHE(next_source))
store_tile (CHAMPLAIN_TILE_CACHE(next_source), tile, contents, size); champlain_tile_cache_store_tile (CHAMPLAIN_TILE_CACHE(next_source), tile, contents, size);
g_free (filename); g_free (filename);
g_free (path); g_free (path);
...@@ -906,27 +817,9 @@ on_tile_filled (ChamplainTileCache *tile_cache, ...@@ -906,27 +817,9 @@ on_tile_filled (ChamplainTileCache *tile_cache,
call_next: call_next:
if (CHAMPLAIN_IS_TILE_CACHE(next_source)) if (CHAMPLAIN_IS_TILE_CACHE(next_source))
on_tile_filled (CHAMPLAIN_TILE_CACHE(next_source), tile); champlain_tile_cache_on_tile_filled (CHAMPLAIN_TILE_CACHE(next_source), tile);
} }
static void
clean (ChamplainTileCache *tile_cache)
{
g_return_if_fail (CHAMPLAIN_IS_FILE_CACHE (tile_cache));
ChamplainFileCache *file_cache = CHAMPLAIN_FILE_CACHE(tile_cache);
ChamplainFileCachePrivate *priv = file_cache->priv;
g_return_if_fail (!champlain_tile_cache_get_persistent (tile_cache));
finalize_sql (file_cache);
delete_temp_cache (file_cache);
g_free (priv->real_cache_dir);
priv->real_cache_dir = NULL;
init_cache (file_cache);
}
static void static void
delete_tile (ChamplainFileCache *file_cache, const gchar *filename) delete_tile (ChamplainFileCache *file_cache, const gchar *filename)
...@@ -1069,45 +962,4 @@ champlain_file_cache_purge (ChamplainFileCache *file_cache) ...@@ -1069,45 +962,4 @@ champlain_file_cache_purge (ChamplainFileCache *file_cache)
sqlite3_free (query); sqlite3_free (query);
} }
static void
delete_dir_recursive (GFile *parent)
{
g_return_if_fail (parent);
GError *error = NULL;
GFileEnumerator *enumerator;
GFileInfo *info;
GFile *child;
enumerator = g_file_enumerate_children (parent, "*",
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &error);
if (!enumerator)
{
DEBUG ("Failed to create file enumerator in delete_dir_recursive: %s", error->message);
g_error_free (error);
return;
}
info = g_file_enumerator_next_file (enumerator, NULL, NULL);
while (info && !error)
{
child = g_file_get_child (parent, g_file_info_get_name (info));
if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY)
delete_dir_recursive (child);
error = NULL;
if (!g_file_delete (child, NULL, &error))
{
DEBUG ("Deleting tile from disk failed: %s", error->message);
g_error_free (error);
}
g_object_unref (child);
g_object_unref (info);
info = g_file_enumerator_next_file (enumerator, NULL, NULL);
}
g_file_enumerator_close (enumerator, NULL, NULL);
}
...@@ -57,7 +57,7 @@ GType champlain_file_cache_get_type (void); ...@@ -57,7 +57,7 @@ GType champlain_file_cache_get_type (void);
ChamplainFileCache* champlain_file_cache_new (void); ChamplainFileCache* champlain_file_cache_new (void);
ChamplainFileCache* champlain_file_cache_new_full (guint size_limit, ChamplainFileCache* champlain_file_cache_new_full (guint size_limit,
const gchar *cache_dir, gboolean persistent); const gchar *cache_dir);
guint champlain_file_cache_get_size_limit (ChamplainFileCache *file_cache); guint champlain_file_cache_get_size_limit (ChamplainFileCache *file_cache);
void champlain_file_cache_set_size_limit (ChamplainFileCache *file_cache, void champlain_file_cache_set_size_limit (ChamplainFileCache *file_cache,
......
...@@ -149,7 +149,7 @@ tile_rendered_cb (ChamplainTile *tile, ...@@ -149,7 +149,7 @@ tile_rendered_cb (ChamplainTile *tile,
champlain_map_source_fill_tile (next_source, tile); champlain_map_source_fill_tile (next_source, tile);
g_object_unref (map_source); g_object_unref (map_source);
g_signal_handlers_disconnect_by_func (tile, tile_rendered_cb, data); g_signal_handlers_disconnect_by_func (tile, tile_rendered_cb, map_source);
} }
static void static void
......
/*
* Copyright (C) 2010 Jiri Techet <techet@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#define DEBUG_FLAG CHAMPLAIN_DEBUG_CACHE
#include "champlain-debug.h"
#include "champlain-memory-cache.h"
#include <glib.h>
#include <string.h>
G_DEFINE_TYPE (ChamplainMemoryCache, champlain_memory_cache, CHAMPLAIN_TYPE_TILE_CACHE);
#define GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), CHAMPLAIN_TYPE_MEMORY_CACHE, ChamplainMemoryCachePrivate))
enum
{
PROP_0,
PROP_SIZE_LIMIT
};
struct _ChamplainMemoryCachePrivate
{
guint size_limit;
GQueue *queue;
};
typedef struct
{
gchar *key;
gchar *data;
guint size;
} QueueMember;
static void fill_tile (ChamplainMapSource *map_source,
ChamplainTile *tile);
static void store_tile (ChamplainTileCache *tile_cache,
ChamplainTile *tile,
const gchar *contents,
gsize size);
static void refresh_tile_time (ChamplainTileCache *tile_cache,
ChamplainTile *tile);
static void on_tile_filled (ChamplainTileCache *tile_cache,
ChamplainTile *tile);
static void
champlain_memory_cache_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
ChamplainMemoryCache *memory_cache = CHAMPLAIN_MEMORY_CACHE (object);
switch (property_id)
{
case PROP_SIZE_LIMIT:
g_value_set_uint (value, champlain_memory_cache_get_size_limit (memory_cache));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
}
static void
champlain_memory_cache_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
ChamplainMemoryCache *memory_cache = CHAMPLAIN_MEMORY_CACHE (object);
switch (property_id)
{
case PROP_SIZE_LIMIT:
champlain_memory_cache_set_size_limit (memory_cache, g_value_get_uint (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
}
static void
champlain_memory_cache_dispose (GObject *object)
{
G_OBJECT_CLASS (champlain_memory_cache_parent_class)->dispose (object);
}
static void
champlain_memory_cache_finalize (GObject *object)
{
ChamplainMemoryCache *memory_cache = CHAMPLAIN_MEMORY_CACHE (object);
g_queue_free (memory_cache->priv->queue);
G_OBJECT_CLASS (champlain_memory_cache_parent_class)->finalize (object);
}
static void
champlain_memory_cache_class_init (ChamplainMemoryCacheClass *klass)
{
ChamplainMapSourceClass *map_source_class = CHAMPLAIN_MAP_SOURCE_CLASS (klass);
ChamplainTileCacheClass *tile_cache_class = CHAMPLAIN_TILE_CACHE_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
g_type_class_add_private (klass, sizeof (ChamplainMemoryCachePrivate));
object_class->finalize = champlain_memory_cache_finalize;
object_class->dispose = champlain_memory_cache_dispose;
object_class->get_property = champlain_memory_cache_get_property;
object_class->set_property = champlain_memory_cache_set_property;
/*
* ChamplainMemoryCache:size-limit:
*
* The cache size limit in bytes.
*
* Note: this new value will not be applied until you call #champlain_cache_purge
*
* Since: 0.4
*/
pspec = g_param_spec_uint ("size-limit",
"Size Limit",
"The cache's size limit (Mb)",
1,
G_MAXINT,
100,
G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
g_object_class_install_property (object_class, PROP_SIZE_LIMIT, pspec);
tile_cache_class->store_tile = store_tile;
tile_cache_class->refresh_tile_time = refresh_tile_time;
tile_cache_class->on_tile_filled = on_tile_filled;
map_source_class->fill_tile = fill_tile;
}
ChamplainMemoryCache *
champlain_memory_cache_new (void)
{
return CHAMPLAIN_MEMORY_CACHE (g_object_new (CHAMPLAIN_TYPE_MEMORY_CACHE, NULL));
}
ChamplainMemoryCache *
champlain_memory_cache_new_full (guint size_limit)
{
ChamplainMemoryCache *cache;
cache = g_object_new (CHAMPLAIN_TYPE_MEMORY_CACHE,
"size-limit", size_limit,
NULL);
return cache;
}
static void
reload_tiles_cb (ChamplainMemoryCache *memory_cache, G_GNUC_UNUSED gpointer data)
{
g_return_if_fail (CHAMPLAIN_IS_MEMORY_CACHE (memory_cache));
champlain_memory_cache_clean (memory_cache);
}
static void
champlain_memory_cache_init (ChamplainMemoryCache *memory_cache)
{
ChamplainMemoryCachePrivate *priv = GET_PRIVATE (memory_cache);
memory_cache->priv = priv;
g_signal_connect (memory_cache, "reload-tiles",
G_CALLBACK (reload_tiles_cb), NULL);
priv->queue = g_queue_new ();
}
guint
champlain_memory_cache_get_size_limit (ChamplainMemoryCache *memory_cache)
{
g_return_val_if_fail (CHAMPLAIN_IS_MEMORY_CACHE (memory_cache), 0);
return memory_cache->priv->size_limit;
}
void
champlain_memory_cache_set_size_limit (ChamplainMemoryCache *memory_cache,
guint size_limit)
{
g_return_if_fail (CHAMPLAIN_IS_MEMORY_CACHE (memory_cache));
ChamplainMemoryCachePrivate *priv = memory_cache->priv;
priv->size_limit = size_limit;
g_object_notify (G_OBJECT (memory_cache), "size-limit");
}
static gchar *
generate_queue_key (ChamplainMemoryCache *memory_cache,
ChamplainTile *tile)
{
g_return_val_if_fail (CHAMPLAIN_IS_MEMORY_CACHE (memory_cache), NULL);
g_return_val_if_fail (CHAMPLAIN_IS_TILE (tile), NULL);