Skip to content

Commit

Permalink
porting code to newer logic
Browse files Browse the repository at this point in the history
  • Loading branch information
bmanojlovic committed Aug 23, 2021
1 parent 563e91b commit 503f166
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 73 deletions.
13 changes: 0 additions & 13 deletions include/mapcache.h
Original file line number Diff line number Diff line change
Expand Up @@ -414,23 +414,10 @@ mapcache_cache* mapcache_cache_tc_create(mapcache_context *ctx);
*/
mapcache_cache* mapcache_cache_riak_create(mapcache_context *ctx);

#ifdef USE_REDIS
typedef struct mapcache_cache_redis mapcache_cache_redis;
/**\class mapcache_cache_redis
* \brief a mapcache_cache on redis server
* \implements mapcache_cache
*/
struct mapcache_cache_redis {
mapcache_cache cache;
char *host;
unsigned long int port;
};

/**
* \memberof mapcache_cache_redis
*/
mapcache_cache* mapcache_cache_redis_create(mapcache_context* ctx);
#endif

/** @} */

Expand Down
185 changes: 125 additions & 60 deletions lib/cache_redis.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
* $Id$
*
* Project: MapServer
* Purpose: MapCache tile caching support file: memcache cache backend.
* Author: Thomas Bonfort and the MapServer team.
* Purpose: MapCache tile caching support file: redis cache backend.
* Author: Boris Manojlovic, Thomas Bonfort and the MapServer team.
*
******************************************************************************
* Copyright (c) 1996-2011 Regents of the University of Minnesota.
* Copyright (c) 2021 Boris Manojlovic
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
Expand All @@ -27,43 +28,96 @@
* DEALINGS IN THE SOFTWARE.
*****************************************************************************/

#include "mapcache-config.h"
#include "mapcache.h"
#ifdef USE_REDIS

#include "mapcache.h"
#include <apr_strings.h>
#include <limits.h>
#include <errno.h>

#define REDIS_GET_CACHE(t) ((mapcache_cache_redis*)t->tileset->cache)

typedef struct mapcache_cache_redis mapcache_cache_redis;

/**\class mapcache_cache_redis
* \brief a mapcache_cache for redis
* \implements mapcache_cache
*/
struct mapcache_cache_redis {
mapcache_cache cache;
char *host;
int port;
char *key_template;
char *bucket_template;
};

struct redis_conn_params {
mapcache_cache_redis *cache;
};

#define REDIS_GET_CACHE(t) ((mapcache_cache_redis*)t->tileset->_cache)
#define REDIS_GET_TILE_KEY(c, t) (mapcache_util_get_tile_key(c, t, NULL, " \r\n\t\f\e\a\b", "#"))
#define IS_REDIS_ERROR_STATUS(r) (r->type != REDIS_REPLY_STATUS || strncmp(r->str, "OK", 2) != 0)

static struct redisContext* _redis_get_connection(mapcache_context *ctx,
mapcache_tile* tile)
{
mapcache_cache_redis *cache = REDIS_GET_CACHE(tile);




void mapcache_redis_connection_constructor(mapcache_context *ctx, void **conn_, void *params) {
mapcache_cache_redis *cache = ((struct redis_conn_params*)params)->cache;
redisContext* conn = redisConnect(cache->host, cache->port);
if (!conn || conn->err) {
ctx->set_error(ctx,500, "redis: failed to connect to server %s:%d", cache->host, cache->port);
return NULL;
return;
}
return conn;
*conn_ = conn;
}


void mapcache_redis_connection_destructor(void *conn_) {
struct redisContext *conn;
conn = (struct redisContext *)conn_;
redisFree(conn);
}

static int _mapcache_cache_redis_has_tile(mapcache_context *ctx,
mapcache_tile *tile)
static mapcache_pooled_connection* _redis_get_connection(mapcache_context *ctx, mapcache_cache_redis *cache, mapcache_tile* tile)
{
char *key = REDIS_GET_TILE_KEY(ctx, tile);
mapcache_pooled_connection *pc;
struct redis_conn_params params;

params.cache = cache;

pc = mapcache_connection_pool_get_connection(ctx,cache->cache.name,mapcache_redis_connection_constructor,
mapcache_redis_connection_destructor, &params);

return pc;

// redisContext *conn;
// conn = redisConnect(cache->host, cache->port);
// if (!conn || conn->err) {
// ctx->set_error(ctx,500, "redis: failed to connect to server %s:%d", cache->host, cache->port);
// return NULL;
// }
// return conn;
}

static int _mapcache_cache_redis_has_tile(mapcache_context *ctx, mapcache_cache *pcache, mapcache_tile *tile) {
int returnValue;
redisContext *conn;
redisReply *reply;
mapcache_pooled_connection *pc;
mapcache_cache_redis *cache = (mapcache_cache_redis*)pcache;

char *key = mapcache_util_get_tile_key(ctx, tile, cache->key_template, " \r\n\t\f\e\a\b", "#");
if(GC_HAS_ERROR(ctx)) {
return MAPCACHE_FALSE;
}
int returnValue = MAPCACHE_TRUE;
redisContext *conn = _redis_get_connection(ctx, tile);
returnValue = MAPCACHE_TRUE;
pc = _redis_get_connection(ctx, cache, tile);
conn = pc->connection;
if(!conn) {
return MAPCACHE_FALSE;
}
redisReply *reply = redisCommand(conn, "EXISTS %s", key);
reply = redisCommand(conn, "EXISTS %s", key);
if(reply->type != REDIS_REPLY_INTEGER) {
returnValue = MAPCACHE_FALSE;
}
Expand All @@ -75,36 +129,46 @@ static int _mapcache_cache_redis_has_tile(mapcache_context *ctx,
return returnValue;
}

static void _mapcache_cache_redis_delete(mapcache_context *ctx,
mapcache_tile *tile)
static void _mapcache_cache_redis_delete(mapcache_context *ctx, mapcache_cache *pcache, mapcache_tile *tile)
{
char* key = REDIS_GET_TILE_KEY(ctx, tile);
redisContext *conn;
redisReply *reply;
mapcache_pooled_connection *pc;
mapcache_cache_redis *cache = (mapcache_cache_redis*)pcache;

char *key = mapcache_util_get_tile_key(ctx, tile, cache->key_template, " \r\n\t\f\e\a\b", "#");
GC_CHECK_ERROR(ctx);
redisContext *conn = _redis_get_connection(ctx, tile);
pc = _redis_get_connection(ctx, cache, tile);
conn = pc->connection;
if(!conn) {
return;
}
redisReply *reply = redisCommand(conn, "DEL %s", key);
reply = redisCommand(conn, "DEL %s", key);
if(reply->type == REDIS_REPLY_ERROR) {
ctx->set_error(ctx, 500, "redis: failed to delete key %s: %s", key, reply->str);
}
freeReplyObject(reply);
redisFree(conn);
}

static int _mapcache_cache_redis_get(mapcache_context *ctx,
mapcache_tile *tile)
static int _mapcache_cache_redis_get(mapcache_context *ctx, mapcache_cache *pcache, mapcache_tile *tile)
{
redisContext *conn;
redisReply *reply;
mapcache_pooled_connection *pc;
mapcache_cache_redis *cache = (mapcache_cache_redis*)pcache;

char* key = REDIS_GET_TILE_KEY(ctx, tile);
if(GC_HAS_ERROR(ctx)) {
return MAPCACHE_FAILURE;
}
tile->encoded_data = mapcache_buffer_create(0, ctx->pool);
redisContext *conn = _redis_get_connection(ctx, tile);
pc = _redis_get_connection(ctx, cache, tile);
conn = pc->connection;
if(!conn) {
return MAPCACHE_FAILURE;
}
redisReply *reply = redisCommand(conn, "GET %s", key);
reply = redisCommand(conn, "GET %s", key);
if(reply->type != REDIS_REPLY_STRING) {
freeReplyObject(reply);
return MAPCACHE_CACHE_MISS;
Expand Down Expand Up @@ -136,15 +200,21 @@ static int _mapcache_cache_redis_get(mapcache_context *ctx,
* \private \memberof mapcache_cache_redis
* \sa mapcache_cache::tile_set()
*/
static void _mapcache_cache_redis_set(mapcache_context *ctx,
mapcache_tile *tile)
static void _mapcache_cache_redis_set(mapcache_context *ctx, mapcache_cache *pcache, mapcache_tile *tile)
{
/* set expiration to one day if not configured */
int expires = 86400;
mapcache_pooled_connection *pc;
mapcache_cache_redis *cache = (mapcache_cache_redis*)pcache;
char *key;
char *data;
apr_time_t now;
redisContext *conn;
redisReply *reply;
if(tile->tileset->auto_expire)
expires = tile->tileset->auto_expire;
mapcache_cache_redis *cache = REDIS_GET_CACHE(tile);
char *key = mapcache_util_get_tile_key(ctx, tile,NULL," \r\n\t\f\e\a\b","#");
cache = REDIS_GET_CACHE(tile);
key = mapcache_util_get_tile_key(ctx, tile, cache->key_template," \r\n\t\f\e\a\b","#");
GC_CHECK_ERROR(ctx);

if(!tile->encoded_data) {
Expand All @@ -154,26 +224,21 @@ static void _mapcache_cache_redis_set(mapcache_context *ctx,

/* concatenate the current time to the end of the memcache data so we can extract it out
* when we re-get the tile */
char *data = calloc(1,tile->encoded_data->size+sizeof(apr_time_t));
apr_time_t now = apr_time_now();
data = calloc(1,tile->encoded_data->size+sizeof(apr_time_t));
now = apr_time_now();
apr_pool_cleanup_register(ctx->pool, data, (void*)free, apr_pool_cleanup_null);
memcpy(data,tile->encoded_data->buf,tile->encoded_data->size);
memcpy(&(data[tile->encoded_data->size]),&now,sizeof(apr_time_t));

redisContext *conn = _redis_get_connection(ctx, tile);
pc = _redis_get_connection(ctx, cache, tile);
conn = pc->connection;
if(!conn) {
return;
}
redisReply *reply = redisCommand(conn,
"SETEX %s %d %b",
key,
expires,
data,
tile->encoded_data->size + sizeof(apr_time_t));
reply = redisCommand(conn, "SETEX %s %d %b", key, expires, data, tile->encoded_data->size + sizeof(apr_time_t));

if(IS_REDIS_ERROR_STATUS(reply)) {
ctx->set_error(ctx, 500, "failed to store tile %d %d %d to redis cache %s",
tile->x, tile->y, tile->z, cache->cache.name);
ctx->set_error(ctx, 500, "failed to store tile %d %d %d to redis cache %s", tile->x, tile->y, tile->z, cache->cache.name);
}

freeReplyObject(reply);
Expand All @@ -184,17 +249,13 @@ static void _mapcache_cache_redis_set(mapcache_context *ctx,
/**
* \private \memberof mapcache_cache_redis
*/
static void _mapcache_cache_redis_configuration_parse_xml(mapcache_context *ctx,
ezxml_t node,
mapcache_cache *cache,
mapcache_cfg *config)
{
static void _mapcache_cache_redis_configuration_parse_xml(mapcache_context *ctx, ezxml_t node, mapcache_cache *cache, mapcache_cfg *config) {
ezxml_t xhost,xport;
mapcache_cache_redis *dcache = (mapcache_cache_redis*)cache;
dcache->host = NULL;
dcache->port = 0;

ezxml_t xhost = ezxml_child(node, "host");
ezxml_t xport = ezxml_child(node, "port");
xhost = ezxml_child(node, "host");
xport = ezxml_child(node, "port");

if (!xhost || !xhost->txt || !*xhost->txt) {
ctx->set_error(ctx, 400, "cache %s: redis cache with no <host>", cache->name);
Expand Down Expand Up @@ -222,34 +283,38 @@ static void _mapcache_cache_redis_configuration_parse_xml(mapcache_context *ctx,
/**
* \private \memberof mapcache_cache_redis
*/
static void _mapcache_cache_redis_configuration_post_config(mapcache_context *ctx,
mapcache_cache *cache,
mapcache_cfg *cfg)
{
static void _mapcache_cache_redis_configuration_post_config(mapcache_context *ctx, mapcache_cache *cache, mapcache_cfg *cfg) {
}

/**
* \brief creates and initializes a mapcache_redis_cache
*/
mapcache_cache* mapcache_cache_redis_create(mapcache_context *ctx)
{
mapcache_cache_redis *cache = apr_pcalloc(ctx->pool,
sizeof(mapcache_cache_redis));
mapcache_cache_redis *cache = apr_pcalloc(ctx->pool, sizeof(mapcache_cache_redis));
if(!cache) {
ctx->set_error(ctx, 500, "failed to allocate redis cache");
return NULL;
}

cache->cache.metadata = apr_table_make(ctx->pool,3);
cache->cache.type = MAPCACHE_CACHE_REDIS;
cache->cache.tile_get = _mapcache_cache_redis_get;
cache->cache.tile_exists = _mapcache_cache_redis_has_tile;
cache->cache.tile_set = _mapcache_cache_redis_set;
cache->cache.tile_delete = _mapcache_cache_redis_delete;
cache->cache._tile_get = _mapcache_cache_redis_get;
cache->cache._tile_exists = _mapcache_cache_redis_has_tile;
cache->cache._tile_set = _mapcache_cache_redis_set;
cache->cache._tile_delete = _mapcache_cache_redis_delete;
cache->cache.configuration_post_config = _mapcache_cache_redis_configuration_post_config;
cache->cache.configuration_parse_xml = _mapcache_cache_redis_configuration_parse_xml;
cache->host = NULL;
cache->port = 6379;
cache->bucket_template = NULL;
return (mapcache_cache*)cache;
}

#else
mapcache_cache* mapcache_cache_redis_create(mapcache_context *ctx) {
ctx->set_error(ctx,400,"redis support not compiled in this version");
return NULL;
}
#endif

/* vim: ts=2 sts=2 et sw=2
Expand Down

0 comments on commit 503f166

Please sign in to comment.