[mapserver-commits] r12472 - in trunk/mapserver/mapcache: . include
src
svn at osgeo.org
svn at osgeo.org
Fri Aug 26 07:29:40 EDT 2011
Author: tbonfort
Date: 2011-08-26 04:29:40 -0700 (Fri, 26 Aug 2011)
New Revision: 12472
Modified:
trunk/mapserver/mapcache/geocache.json
trunk/mapserver/mapcache/include/geocache.h
trunk/mapserver/mapcache/src/cache_sqlite.c
trunk/mapserver/mapcache/src/configuration_json.c
Log:
Modified: trunk/mapserver/mapcache/geocache.json
===================================================================
--- trunk/mapserver/mapcache/geocache.json 2011-08-26 11:29:35 UTC (rev 12471)
+++ trunk/mapserver/mapcache/geocache.json 2011-08-26 11:29:40 UTC (rev 12472)
@@ -47,9 +47,17 @@
"name":"sqlite",
"type":"sqlite3",
"props": {
- "base_dir":"/tmp",
+ "dbname_template":"/tmp/{tileset}-{grid}.sqlite",
"hit_stats":false
}
+ },
+ {
+ "name":"mbtiles",
+ "type":"mbtiles",
+ "props": {
+ "dbname_template":"/tmp/{tileset}-{grid}.mbtiles",
+ "hit_stats":false
+ }
}
],
"sources": [
@@ -77,6 +85,22 @@
"info_formats":["text/html"]
}
}
+ },
+ {
+ "name":"osm",
+ "type":"wms",
+ "props": {
+ "http": {
+ "url":"http://localhost/cgi-bin/mapserv"
+ },
+ "getmap": {
+ "params":{
+ "LAYERS":"default",
+ "FORMAT":"image/png",
+ "MAP":"/Users/tbonfort/dev/mapserver-utils/osm-outlined,google.map"
+ }
+ }
+ }
}
],
"formats": [
@@ -134,6 +158,42 @@
}
]
//,"watermark":"/home/tbonfort/dev/mod-geocache/static/watermark.png"
+ },
+ {
+ "name": "osm",
+ "source": "osm",
+ "grids": [
+ "g"
+ ],
+ "wgs84_extent":[-180,-90,180,90],
+ "format": "png",
+ "cache": "mbtiles",
+ "metatile": {
+ "size":[5,5],
+ "buffer":10
+ },
+ "expires": {
+ "delay": 3600,
+ "auto": false
+ }
+ },
+ {
+ "name": "ne",
+ "source": "osm",
+ "grids": [
+ "g"
+ ],
+ "wgs84_extent":[-180,-90,180,90],
+ "format": "png",
+ "cache": "mbtiles",
+ "metatile": {
+ "size":[5,5],
+ "buffer":10
+ },
+ "expires": {
+ "delay": 3600,
+ "auto": false
+ }
}
],
"services": [
Modified: trunk/mapserver/mapcache/include/geocache.h
===================================================================
--- trunk/mapserver/mapcache/include/geocache.h 2011-08-26 11:29:35 UTC (rev 12471)
+++ trunk/mapserver/mapcache/include/geocache.h 2011-08-26 11:29:40 UTC (rev 12472)
@@ -382,15 +382,29 @@
* \implements geocache_cache
*/
typedef struct geocache_cache_sqlite geocache_cache_sqlite;
+typedef struct geocache_cache_sqlite_stmt geocache_cache_sqlite_stmt;
+
+struct geocache_cache_sqlite_stmt {
+ char *sql;
+};
+
struct geocache_cache_sqlite {
geocache_cache cache;
- char *dbdir;
+ char *dbname_template;
int hitstats;
+ geocache_cache_sqlite_stmt create_stmt;
+ geocache_cache_sqlite_stmt exists_stmt;
+ geocache_cache_sqlite_stmt get_stmt;
+ geocache_cache_sqlite_stmt hitstat_stmt;
+ geocache_cache_sqlite_stmt set_stmt;
+ geocache_cache_sqlite_stmt delete_stmt;
};
+
/**
* \memberof geocache_cache_sqlite
*/
geocache_cache* geocache_cache_sqlite_create(geocache_context *ctx);
+geocache_cache* geocache_cache_mbtiles_create(geocache_context *ctx);
#endif
#ifdef USE_MEMCACHE
Modified: trunk/mapserver/mapcache/src/cache_sqlite.c
===================================================================
--- trunk/mapserver/mapcache/src/cache_sqlite.c 2011-08-26 11:29:35 UTC (rev 12471)
+++ trunk/mapserver/mapcache/src/cache_sqlite.c 2011-08-26 11:29:40 UTC (rev 12472)
@@ -21,13 +21,10 @@
#include <string.h>
#include <errno.h>
#include <unistd.h>
+#include <time.h>
#include <sqlite3.h>
-static char* _get_dbname(geocache_context *ctx, geocache_cache_sqlite *cache,
- geocache_tileset *tileset, geocache_grid *grid) {
- return apr_pstrcat(ctx->pool,cache->dbdir,"/",tileset->name,"#",grid->name,".db",NULL);
-}
static const char* _get_tile_dimkey(geocache_context *ctx, geocache_tile *tile) {
if(tile->dimensions) {
@@ -55,6 +52,13 @@
}
}
+static char* _get_dbname(geocache_context *ctx, geocache_tileset *tileset, geocache_grid *grid) {
+ geocache_cache_sqlite *cache = (geocache_cache_sqlite*) tileset->cache;
+ char *path = cache->dbname_template;
+ path = geocache_util_str_replace(ctx->pool, path, "{tileset}", tileset->name);
+ path = geocache_util_str_replace(ctx->pool, path, "{grid}", grid->name);
+ return path;
+}
static sqlite3* _get_conn(geocache_context *ctx, geocache_tile* tile, int readonly) {
sqlite3* handle;
@@ -64,7 +68,7 @@
} else {
flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
}
- char *dbfile = _get_dbname(ctx,(geocache_cache_sqlite*)tile->tileset->cache,tile->tileset,tile->grid_link->grid);
+ char *dbfile = _get_dbname(ctx,tile->tileset, tile->grid_link->grid);
int ret = sqlite3_open_v2(dbfile,&handle,flags,NULL);
if(ret != SQLITE_OK) {
ctx->set_error(ctx,500,"failed to connect to sqlite db %s: %s",dbfile,sqlite3_errmsg(handle));
@@ -74,14 +78,54 @@
return handle;
}
+/**
+ * \brief apply appropriate tile properties to the sqlite statement */
+static void _bind_sqlite_params(geocache_context *ctx, sqlite3_stmt *stmt, geocache_tile *tile) {
+ int paramidx;
+ /* tile->x */
+ paramidx = sqlite3_bind_parameter_index(stmt, ":x");
+ if(paramidx) sqlite3_bind_int(stmt, paramidx, tile->x);
+
+ /* tile->y */
+ paramidx = sqlite3_bind_parameter_index(stmt, ":y");
+ if(paramidx) sqlite3_bind_int(stmt, paramidx, tile->y);
+
+ /* tile->y */
+ paramidx = sqlite3_bind_parameter_index(stmt, ":z");
+ if(paramidx) sqlite3_bind_int(stmt, paramidx, tile->z);
+
+ /* eventual dimensions */
+ paramidx = sqlite3_bind_parameter_index(stmt, ":dim");
+ if(paramidx) {
+ if(tile->dimensions) {
+ const char *dim = _get_tile_dimkey(ctx,tile);
+ sqlite3_bind_text(stmt,paramidx,dim,-1,SQLITE_STATIC);
+ } else {
+ sqlite3_bind_text(stmt,paramidx,"",-1,SQLITE_STATIC);
+ }
+ }
+
+ /* grid */
+ paramidx = sqlite3_bind_parameter_index(stmt, ":grid");
+ if(paramidx) sqlite3_bind_text(stmt,paramidx,tile->grid_link->grid->name,-1,SQLITE_STATIC);
+
+ /* tileset */
+ paramidx = sqlite3_bind_parameter_index(stmt, ":tileset");
+ if(paramidx) sqlite3_bind_text(stmt,paramidx,tile->tileset->name,-1,SQLITE_STATIC);
+
+ /* tile blob data */
+ paramidx = sqlite3_bind_parameter_index(stmt, ":data");
+ if(paramidx) {
+ if(tile->data && tile->data->size) {
+ sqlite3_bind_blob(stmt,paramidx,tile->data->buf, tile->data->size,SQLITE_STATIC);
+ } else {
+ sqlite3_bind_text(stmt,paramidx,"",-1,SQLITE_STATIC);
+ }
+ }
+}
static int _geocache_cache_sqlite_has_tile(geocache_context *ctx, geocache_tile *tile) {
- char *sql;
- if(tile->dimensions) {
- sql = "SELECT 1 from tiles where x=? and y=? and z=? and dim=?";
- } else {
- sql = "SELECT 1 from tiles where x=? and y=? and z=?";
- }
+ geocache_cache_sqlite *cache = (geocache_cache_sqlite*)tile->tileset->cache;
sqlite3* handle = _get_conn(ctx,tile,1);
if(GC_HAS_ERROR(ctx)) {
sqlite3_close(handle);
@@ -89,14 +133,8 @@
}
sqlite3_stmt *stmt;
- sqlite3_prepare(handle,sql,-1,&stmt,NULL);
- sqlite3_bind_int(stmt,1,tile->x);
- sqlite3_bind_int(stmt,2,tile->y);
- sqlite3_bind_int(stmt,3,tile->z);
- if(tile->dimensions) {
- const char *dim = _get_tile_dimkey(ctx,tile);
- sqlite3_bind_text(stmt,4,dim,-1,SQLITE_STATIC);
- }
+ sqlite3_prepare(handle,cache->exists_stmt.sql,-1,&stmt,NULL);
+ _bind_sqlite_params(ctx,stmt,tile);
int ret = sqlite3_step(stmt);
if(ret != SQLITE_DONE && ret != SQLITE_ROW) {
ctx->set_error(ctx,500,"sqlite backend failed on has_tile: %s",sqlite3_errmsg(handle));
@@ -112,23 +150,12 @@
}
static void _geocache_cache_sqlite_delete(geocache_context *ctx, geocache_tile *tile) {
+ geocache_cache_sqlite *cache = (geocache_cache_sqlite*)tile->tileset->cache;
sqlite3* handle = _get_conn(ctx,tile,0);
GC_CHECK_ERROR(ctx);
- char *sql;
- if(tile->dimensions) {
- sql = "DELETE from tiles where x=? and y=? and z=? and dim=?";
- } else {
- sql = "DELETE from tiles where x=? and y=? and z=?";
- }
sqlite3_stmt *stmt;
- sqlite3_prepare(handle,sql,-1,&stmt,NULL);
- sqlite3_bind_int(stmt,1,tile->x);
- sqlite3_bind_int(stmt,2,tile->y);
- sqlite3_bind_int(stmt,3,tile->z);
- if(tile->dimensions) {
- const char* dim = _get_tile_dimkey(ctx,tile);
- sqlite3_bind_text(stmt,4,dim,-1,SQLITE_STATIC);
- }
+ sqlite3_prepare(handle,cache->delete_stmt.sql,-1,&stmt,NULL);
+ _bind_sqlite_params(ctx,stmt,tile);
int ret = sqlite3_step(stmt);
if(ret != SQLITE_DONE && ret != SQLITE_ROW) {
ctx->set_error(ctx,500,"sqlite backend failed on delete: %s",sqlite3_errmsg(handle));
@@ -151,21 +178,8 @@
return GEOCACHE_FAILURE;
}
sqlite3_stmt *stmt;
- char *sql;
- const char *dim=NULL;
- if(tile->dimensions) {
- sql = "SELECT data,strftime(\"%s\",ctime) from tiles where x=? and y=? and z=? and dim=?";
- } else {
- sql = "SELECT data,strftime(\"%s\",ctime) from tiles where x=? and y=? and z=?";
- }
- sqlite3_prepare(handle,sql,-1,&stmt,NULL);
- sqlite3_bind_int(stmt,1,tile->x);
- sqlite3_bind_int(stmt,2,tile->y);
- sqlite3_bind_int(stmt,3,tile->z);
- if(tile->dimensions) {
- dim = _get_tile_dimkey(ctx,tile);
- sqlite3_bind_text(stmt,4,dim,-1,SQLITE_STATIC);
- }
+ sqlite3_prepare(handle,cache->get_stmt.sql,-1,&stmt,NULL);
+ _bind_sqlite_params(ctx,stmt,tile);
int ret = sqlite3_step(stmt);
if(ret!=SQLITE_DONE && ret != SQLITE_ROW) {
ctx->set_error(ctx,500,"sqlite backend failed on get: %s",sqlite3_errmsg(handle));
@@ -183,27 +197,17 @@
tile->data = geocache_buffer_create(size,ctx->pool);
memcpy(tile->data->buf, blob,size);
tile->data->size = size;
- time_t mtime = sqlite3_column_int64(stmt, 1);
- apr_time_ansi_put(&(tile->mtime),mtime);
+ if(sqlite3_column_count(stmt) > 1) {
+ time_t mtime = sqlite3_column_int64(stmt, 1);
+ apr_time_ansi_put(&(tile->mtime),mtime);
+ }
sqlite3_finalize(stmt);
/* update the hitstats if we're configured for that */
if(cache->hitstats) {
-
sqlite3_stmt *hitstmt;
- char *hitsql;
- if(tile->dimensions) {
- hitsql = "update tiles set hitcount=hitcount+1, atime=datetime('now') where x=? and y=? and z=? and dim=?";
- } else {
- hitsql = "update tiles set hitcount=hitcount+1, atime=datetime('now') where x=? and y=? and z=?";
- }
- sqlite3_prepare(handle,hitsql,-1,&hitstmt,NULL);
- sqlite3_bind_int(hitstmt,1,tile->x);
- sqlite3_bind_int(hitstmt,2,tile->y);
- sqlite3_bind_int(hitstmt,3,tile->z);
- if(tile->dimensions) {
- sqlite3_bind_text(hitstmt,4,dim,-1,SQLITE_STATIC);
- }
+ sqlite3_prepare(handle,cache->hitstat_stmt.sql,-1,&hitstmt,NULL);
+ _bind_sqlite_params(ctx,stmt,tile);
sqlite3_step(hitstmt); /* we ignore the return value , TODO?*/
sqlite3_finalize(hitstmt);
}
@@ -214,24 +218,12 @@
}
static void _geocache_cache_sqlite_set(geocache_context *ctx, geocache_tile *tile) {
+ geocache_cache_sqlite *cache = (geocache_cache_sqlite*)tile->tileset->cache;
sqlite3* handle = _get_conn(ctx,tile,0);
GC_CHECK_ERROR(ctx);
sqlite3_stmt *stmt;
- char *sql;
- if(tile->dimensions) {
- sql = "insert or replace into tiles(x,y,z,data,dim,ctime) values (?,?,?,?,?,datetime('now'))";
- } else {
- sql = "insert or replace into tiles(x,y,z,data,ctime) values (?,?,?,?,datetime('now'))";
- }
- sqlite3_prepare(handle, sql,-1,&stmt,NULL);
- sqlite3_bind_int(stmt,1,tile->x);
- sqlite3_bind_int(stmt,2,tile->y);
- sqlite3_bind_int(stmt,3,tile->z);
- sqlite3_bind_blob(stmt,4,tile->data->buf, tile->data->size,SQLITE_STATIC);
- if(tile->dimensions) {
- const char* dim = _get_tile_dimkey(ctx,tile);
- sqlite3_bind_text(stmt,5,dim,-1,SQLITE_STATIC);
- }
+ sqlite3_prepare(handle,cache->set_stmt.sql,-1,&stmt,NULL);
+ _bind_sqlite_params(ctx,stmt,tile);
int ret = sqlite3_step(stmt);
if(ret != SQLITE_DONE && ret != SQLITE_ROW) {
ctx->set_error(ctx,500,"sqlite backend failed on set: %s",sqlite3_errmsg(handle));
@@ -244,11 +236,11 @@
cJSON *tmp;
geocache_cache_sqlite *dcache = (geocache_cache_sqlite*)cache;
- tmp = cJSON_GetObjectItem(node,"base_dir");
+ tmp = cJSON_GetObjectItem(node,"dbname_template");
if(tmp && tmp->valuestring) {
- dcache->dbdir = apr_pstrdup(ctx->pool, tmp->valuestring);
+ dcache->dbname_template = apr_pstrdup(ctx->pool, tmp->valuestring);
} else {
- ctx->set_error(ctx,400,"cache %s has invalid base_dir",cache->name);
+ ctx->set_error(ctx,400,"cache %s has invalid dbname_template",cache->name);
return;
}
if((tmp = cJSON_GetObjectItem(node,"hit_stats")) != NULL) {
@@ -256,20 +248,44 @@
dcache->hitstats = 1;
}
}
+ tmp = cJSON_GetObjectItem(node,"create_statement");
+ if(tmp && tmp->valuestring) {
+ dcache->create_stmt.sql = apr_pstrdup(ctx->pool,tmp->valuestring);
+ }
+ tmp = cJSON_GetObjectItem(node,"exists_statement");
+ if(tmp && tmp->valuestring) {
+ dcache->exists_stmt.sql = apr_pstrdup(ctx->pool,tmp->valuestring);
+ }
+ tmp = cJSON_GetObjectItem(node,"get_statement");
+ if(tmp && tmp->valuestring) {
+ dcache->get_stmt.sql = apr_pstrdup(ctx->pool,tmp->valuestring);
+ }
+ tmp = cJSON_GetObjectItem(node,"set_statement");
+ if(tmp && tmp->valuestring) {
+ dcache->set_stmt.sql = apr_pstrdup(ctx->pool,tmp->valuestring);
+ }
+ tmp = cJSON_GetObjectItem(node,"delete_statement");
+ if(tmp && tmp->valuestring) {
+ dcache->delete_stmt.sql = apr_pstrdup(ctx->pool,tmp->valuestring);
+ }
+ tmp = cJSON_GetObjectItem(node,"hitstats_statement");
+ if(tmp && tmp->valuestring) {
+ dcache->hitstat_stmt.sql = apr_pstrdup(ctx->pool,tmp->valuestring);
+ }
}
static void _geocache_cache_sqlite_configuration_parse_xml(geocache_context *ctx, ezxml_t node, geocache_cache *cache) {
ezxml_t cur_node;
geocache_cache_sqlite *dcache = (geocache_cache_sqlite*)cache;
if ((cur_node = ezxml_child(node,"base")) != NULL) {
- dcache->dbdir = apr_pstrdup(ctx->pool,cur_node->txt);
+ dcache->dbname_template = apr_pstrcat(ctx->pool,cur_node->txt,"/{tileset}#{grid}.db",NULL);
}
if ((cur_node = ezxml_child(node,"hitstats")) != NULL) {
if(!strcasecmp(cur_node->txt,"true")) {
dcache->hitstats = 1;
}
}
- if(!dcache->dbdir) {
+ if(!dcache->dbname_template) {
ctx->set_error(ctx,500,"sqlite cache \"%s\" is missing <base> directory",cache->name);
return;
}
@@ -280,6 +296,7 @@
*/
static void _geocache_cache_sqlite_configuration_post_config(geocache_context *ctx,
geocache_cache *cache, geocache_cfg *cfg) {
+ geocache_cache_sqlite *dcache = (geocache_cache_sqlite*)cache;
sqlite3 *db;
char *errmsg;
int ret;
@@ -295,13 +312,9 @@
for(i=0;i<tileset->grid_links->nelts;i++) {
geocache_grid_link *gridlink = APR_ARRAY_IDX(tileset->grid_links,i,geocache_grid_link*);
geocache_grid *grid = gridlink->grid;
- char *dbname = _get_dbname(ctx,(geocache_cache_sqlite*)cache,tileset,grid);
+ char *dbname = _get_dbname(ctx,tileset,grid);
sqlite3_open(dbname, &db);
- if(tileset->dimensions) {
- ret = sqlite3_exec(db, "create table if not exists tiles(x integer, y integer, z integer, data blob, dim text, ctime datetime, atime datetime, hitcount integer default 0, primary key(x,y,z,dim))", 0, 0, &errmsg);
- } else {
- ret = sqlite3_exec(db, "create table if not exists tiles(x integer, y integer, z integer, data blob, ctime datetime, atime datetime, hitcount integer default 0, primary key (x,y,z))", 0, 0, &errmsg);
- }
+ ret = sqlite3_exec(db, dcache->create_stmt.sql, 0, 0, &errmsg);
if(ret != SQLITE_OK) {
ctx->set_error(ctx,500,"sqlite backend failed to create tiles table: %s",sqlite3_errmsg(db));
sqlite3_close(db);
@@ -332,9 +345,44 @@
cache->cache.configuration_post_config = _geocache_cache_sqlite_configuration_post_config;
cache->cache.configuration_parse_xml = _geocache_cache_sqlite_configuration_parse_xml;
cache->cache.configuration_parse_json = _geocache_cache_sqlite_configuration_parse_json;
+ cache->create_stmt.sql = apr_pstrdup(ctx->pool,
+ "create table if not exists tiles(x integer, y integer, z integer, data blob, dim text, ctime datetime, atime datetime, hitcount integer default 0, primary key(x,y,z,dim))");
+ cache->exists_stmt.sql = apr_pstrdup(ctx->pool,
+ "select 1 from tiles where x=?:x and y=:y and z=:z and dim=:dim");
+ cache->get_stmt.sql = apr_pstrdup(ctx->pool,
+ "select data,strftime(\"%s\",ctime) from tiles where x=:x and y=:y and z=:z and dim=:dim");
+ cache->set_stmt.sql = apr_pstrdup(ctx->pool,
+ "insert or replace into tiles(x,y,z,data,dim,ctime) values (:x,:y,:z,:data,:dim,datetime('now'))");
+ cache->delete_stmt.sql = apr_pstrdup(ctx->pool,
+ "delete from tiles where x=:x and y=:y and z=:z and dim=:dim");
+ cache->hitstat_stmt.sql = apr_pstrdup(ctx->pool,
+ "update tiles set hitcount=hitcount+1, atime=datetime('now') where x=:x and y=:y and z=:z and dim=:dim");
return (geocache_cache*)cache;
}
+/**
+ * \brief creates and initializes a geocache_sqlite_cache
+ */
+geocache_cache* geocache_cache_mbtiles_create(geocache_context *ctx) {
+ geocache_cache_sqlite *cache = (geocache_cache_sqlite*)geocache_cache_sqlite_create(ctx);
+ if(!cache) {
+ return NULL;
+ }
+ cache->create_stmt.sql = apr_pstrdup(ctx->pool,
+ "CREATE TABLE IF NOT EXISTS tiles (zoom_level integer, tile_column integer, tile_row integer, tile_data blob, primary key(tile_row, tile_column, zoom_level)); create table if not exists metadata(foo integer);");
+ cache->exists_stmt.sql = apr_pstrdup(ctx->pool,
+ "select 1 from tiles where tile_column=?:x and tile_row=:y and zoom_level=:z");
+ cache->get_stmt.sql = apr_pstrdup(ctx->pool,
+ "select tile_data from tiles where tile_column=:x and tile_row=:y and zoom_level=:z");
+ cache->set_stmt.sql = apr_pstrdup(ctx->pool,
+ "insert or replace into tiles(tile_column,tile_row,zoom_level,tile_data) values (:x,:y,:z,:data)");
+ cache->delete_stmt.sql = apr_pstrdup(ctx->pool,
+ "delete from tiles where tile_column=:x and tile_row=:y and zoom_level=:z");
+ cache->hitstat_stmt.sql = apr_pstrdup(ctx->pool,
+ "update tiles set hitcount=hitcount+1, atime=datetime('now') where x=:x and y=:y and z=:z and dim=:dim");
+ return (geocache_cache*)cache;
+}
+
#endif
/* vim: ai ts=3 sts=3 et sw=3
Modified: trunk/mapserver/mapcache/src/configuration_json.c
===================================================================
--- trunk/mapserver/mapcache/src/configuration_json.c 2011-08-26 11:29:35 UTC (rev 12471)
+++ trunk/mapserver/mapcache/src/configuration_json.c 2011-08-26 11:29:40 UTC (rev 12472)
@@ -243,6 +243,13 @@
ctx->set_error(ctx,400, "failed to add cache \"%s\": sqlite support is not available on this build",name);
return;
#endif
+ } else if(!strcmp(type,"mbtiles")) {
+#ifdef USE_SQLITE
+ cache = geocache_cache_mbtiles_create(ctx);
+#else
+ ctx->set_error(ctx,400, "failed to add cache \"%s\": sqlite support is not available on this build",name);
+ return;
+#endif
} else if(!strcmp(type,"memcache")) {
#ifdef USE_MEMCACHE
cache = geocache_cache_memcache_create(ctx);
More information about the mapserver-commits
mailing list