[mapcache] 01/07: Imported Upstream version 1.4.1

Sebastiaan Couwenberg sebastic at moszumanska.debian.org
Thu Feb 25 20:45:13 UTC 2016


This is an automated email from the git hooks/post-receive script.

sebastic pushed a commit to branch master
in repository mapcache.

commit 6ea581b0abf53f14d0d124693aa845fcf8316f0c
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date:   Thu Feb 25 20:56:45 2016 +0100

    Imported Upstream version 1.4.1
---
 CMakeLists.txt         |  17 +++-
 apache/mod_mapcache.c  | 252 ++++++++++++++++++++++++++++++++-----------------
 cgi/mapcache.c         |  14 ++-
 cmake/FindAPACHE.cmake |   2 +-
 include/mapcache.h     |  96 +++++++++----------
 include/util.h         |   8 +-
 lib/cache_bdb.c        |  51 +++++-----
 lib/cache_disk.c       |  69 +++-----------
 lib/cache_fallback.c   |   8 +-
 lib/cache_memcache.c   |  15 +--
 lib/cache_multitier.c  |   2 +-
 lib/cache_rest.c       | 131 +++++++++++++------------
 lib/cache_riak.c       |  20 +++-
 lib/cache_sqlite.c     |   6 +-
 lib/cache_tiff.c       |  29 +-----
 lib/connection_pool.c  |   9 +-
 lib/core.c             |  28 +++---
 lib/dimension.c        |  49 ++++++----
 lib/ezxml.c            |   2 +-
 lib/http.c             |   4 +-
 lib/image.c            |   8 +-
 lib/imageio_png.c      |  18 ++--
 lib/lock.c             |  25 +++--
 lib/service_demo.c     |  23 ++---
 lib/service_wms.c      |  18 ++--
 lib/service_wmts.c     |   9 +-
 lib/strptime.c         |   1 -
 lib/tileset.c          |  42 +++++----
 lib/util.c             |  69 ++++++++++++--
 release.sh             |  54 +++++++++++
 util/mapcache_seed.c   | 161 ++++++++++++++++++-------------
 31 files changed, 730 insertions(+), 510 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 218f87a..ea1e62a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -6,7 +6,6 @@ include(CheckFunctionExists)
 include(CheckIncludeFile)
 include(CheckCSourceCompiles)
 
-set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
 if ("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") 
    add_definitions(-DDEBUG) 
 endif () 
@@ -14,7 +13,7 @@ endif ()
 
 set (MAPCACHE_VERSION_MAJOR 1)
 set (MAPCACHE_VERSION_MINOR 4)
-set (MAPCACHE_VERSION_REVISION 0)
+set (MAPCACHE_VERSION_REVISION 1)
 
 
 if(NOT DEFINED CMAKE_INSTALL_LIBDIR)
@@ -58,7 +57,7 @@ endmacro()
 
 check_function_exists("strncasecmp"  HAVE_STRNCASECMP)
 check_function_exists("symlink"  HAVE_SYMLINK)
-
+check_function_exists ("timegm" HAVE_TIMEGM)
 
 set(CMAKE_SKIP_BUILD_RPATH FALSE)
 if(APPLE)
@@ -74,6 +73,15 @@ set_target_properties(mapcache PROPERTIES
   SOVERSION 1
 )
 
+# Add compiler flags for warnings
+if(CMAKE_COMPILER_IS_GNUCC)
+    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror=declaration-after-statement")
+endif()
+
+if(CMAKE_C_COMPILER_ID MATCHES "Clang")
+  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror=declaration-after-statement -std=c89 -Wno-comment")
+endif()
+
 #options suported by the cmake builder
 option(WITH_PIXMAN "Use pixman for SSE optimized image manipulations" ON)
 option(WITH_SQLITE "Use sqlite as a cache backend" ON)
@@ -89,7 +97,7 @@ option(WITH_RIAK "Use Riak as a cache backend" OFF)
 find_package(PNG)
 if(PNG_FOUND)
   include_directories(${PNG_INCLUDE_DIR})
-  target_link_libraries(mapcache ${PNG_LIBRARY})
+  target_link_libraries(mapcache ${PNG_LIBRARIES})
 else(PNG_FOUND)
   report_mandatory_not_found(PNG)
 endif(PNG_FOUND)
@@ -160,6 +168,7 @@ if(WITH_PCRE)
     include_directories(${PCRE_INCLUDE_DIR})
     target_link_libraries(mapcache ${PCRE_LIBRARY})
     set (USE_PCRE 1)
+    add_definitions(-DPCRE_STATIC) 
   else(PCRE_FOUND)
     report_optional_not_found(PCRE)
   endif(PCRE_FOUND)
diff --git a/apache/mod_mapcache.c b/apache/mod_mapcache.c
index 61dc994..832bad2 100644
--- a/apache/mod_mapcache.c
+++ b/apache/mod_mapcache.c
@@ -73,6 +73,19 @@ struct mapcache_context_apache_request {
   request_rec *request;
 };
 
+typedef struct mapcache_alias_entry mapcache_alias_entry;
+
+struct mapcache_alias_entry {
+  char *endpoint;
+  char *configfile;
+  mapcache_cfg *cfg;
+  mapcache_connection_pool *cp;
+};
+
+struct mapcache_server_cfg {
+  apr_array_header_t *aliases; /**< list of mapcache configurations aliased to a server uri */
+};
+
 void apache_context_server_log(mapcache_context *c, mapcache_log_level level, char *message, ...)
 {
   mapcache_context_apache_server *ctx = (mapcache_context_apache_server*)c;
@@ -183,21 +196,42 @@ static mapcache_context_apache_request* apache_request_context_create(request_re
 {
   mapcache_context_apache_request *ctx = apr_pcalloc(r->pool, sizeof(mapcache_context_apache_request));
   mapcache_server_cfg *cfg = NULL;
-  mapcache_cfg *config = NULL;
+  const char *mapcache_alias;
+  mapcache_alias_entry *alias_entry;
+  int i;
+  mapcache_context *mctx = (mapcache_context*)ctx;
 
-  ctx->ctx.ctx.pool = r->pool;
+  mctx->pool = r->pool;
 #ifdef APR_HAS_THREADS
-  ctx->ctx.ctx.threadlock = thread_mutex;
+  mctx->threadlock = thread_mutex;
 #endif
 
   /* lookup the configuration object given the configuration file name */
   cfg = ap_get_module_config(r->server->module_config, &mapcache_module);
-  config = apr_hash_get(cfg->aliases,(void*)r->filename,APR_HASH_KEY_STRING);
-  ctx->ctx.ctx.config = config;
-  ctx->request = r;
-  ctx->ctx.ctx.connection_pool = cfg->cp;
-  init_apache_request_context(ctx);
-  return ctx;
+  if(!cfg || !cfg->aliases) {
+    return NULL;
+  }
+
+  mapcache_alias = apr_table_get(r->notes,"mapcache_alias_entry");
+  //ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "using mapcache config %s", mapcache_config_file);
+  if(!mapcache_alias) {
+    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "mapcache module bug? no mapcache_alias_entry found");
+    return NULL;
+  }
+
+  for(i=0; i<cfg->aliases->nelts; i++) {
+    alias_entry = APR_ARRAY_IDX(cfg->aliases,i,mapcache_alias_entry*);
+    if(strcmp(alias_entry->endpoint,mapcache_alias))
+      continue;
+
+    mctx->config = alias_entry->cfg;
+    ctx->request = r;
+    mctx->connection_pool = alias_entry->cp;
+    init_apache_request_context(ctx);
+    return ctx;
+  }
+  ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "mapcache module bug? no mapcache_alias_entry found for %s",mapcache_alias);
+  return NULL;
 }
 
 static mapcache_context_apache_server* apache_server_context_create(server_rec *s, apr_pool_t *pool)
@@ -227,34 +261,36 @@ static void read_post_body(mapcache_context_apache_request *ctx, mapcache_reques
     }
   } else {
     bytes = p->rule->max_post_len;
-  } 
+  }
 
   bb = apr_brigade_create(mctx->pool, r->connection->bucket_alloc);
   bbin = apr_brigade_create(mctx->pool, r->connection->bucket_alloc);
   p->post_len = 0;
 
   do {
+    apr_bucket *nextb;
     rv = ap_get_brigade(r->input_filters, bbin, AP_MODE_READBYTES, APR_BLOCK_READ, bytes);
     if(rv != APR_SUCCESS) {
       mctx->set_error(mctx, 500, "failed to read form input");
       return;
     }
-    for(b = APR_BRIGADE_FIRST(bbin); b != APR_BRIGADE_SENTINEL(bbin); b = APR_BUCKET_NEXT(b)) {
+    for(b = APR_BRIGADE_FIRST(bbin); b != APR_BRIGADE_SENTINEL(bbin); b = nextb) {
+      nextb = APR_BUCKET_NEXT(b);
       if(APR_BUCKET_IS_EOS(b)) {
         eos = 1;
       }
-    }
-    if(!APR_BUCKET_IS_METADATA(b)) {
-      if(b->length != (apr_size_t)(-1)) {
-        p->post_len += b->length;
-        if(p->post_len > p->rule->max_post_len) {
-          apr_bucket_delete(b);
+      if(!APR_BUCKET_IS_METADATA(b)) {
+        if(b->length != (apr_size_t)(-1)) {
+          p->post_len += b->length;
+          if(p->post_len > p->rule->max_post_len) {
+            apr_bucket_delete(b);
+          }
         }
       }
-    }
-    if(p->post_len <= p->rule->max_post_len) {
-      APR_BUCKET_REMOVE(b);
-      APR_BRIGADE_INSERT_TAIL(bb, b);
+      if(p->post_len <= p->rule->max_post_len) {
+        APR_BUCKET_REMOVE(b);
+        APR_BRIGADE_INSERT_TAIL(bb, b);
+      }
     }
   } while (!eos);
 
@@ -264,11 +300,13 @@ static void read_post_body(mapcache_context_apache_request *ctx, mapcache_reques
   }
 
   p->post_buf = apr_palloc(mctx->pool, p->post_len+1);
-
-  rv = apr_brigade_flatten(bb, p->post_buf, &(p->post_len));
-  if(rv != APR_SUCCESS) {
-    mctx->set_error(mctx, 500, "error (flatten) reading form data");
-    return;
+  
+  if(p->post_len> 0) {
+    rv = apr_brigade_flatten(bb, p->post_buf, &(p->post_len));
+    if(rv != APR_SUCCESS) {
+      mctx->set_error(mctx, 500, "error (flatten) reading form data");
+      return;
+    }
   }
   p->post_buf[p->post_len] = 0;
 }
@@ -312,15 +350,20 @@ static int write_http_response(mapcache_context_apache_request *ctx, mapcache_ht
 
 static void mod_mapcache_child_init(apr_pool_t *pool, server_rec *s)
 {
-  int rv;
-  mapcache_server_cfg* cfg = ap_get_module_config(s->module_config, &mapcache_module);
 #ifdef APR_HAS_THREADS
   apr_thread_mutex_create(&thread_mutex,APR_THREAD_MUTEX_DEFAULT,pool);
 #endif
-  rv = mapcache_connection_pool_create(&(cfg->cp),pool);
-  ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "creating a mapcache connection pool for server");
-  if(rv!=APR_SUCCESS) {
-    ap_log_error(APLOG_MARK, APLOG_CRIT, 0, s, "failed to create mapcache connection pool");
+  for( ; s ; s=s->next) {
+    mapcache_server_cfg* cfg = ap_get_module_config(s->module_config, &mapcache_module);
+    int i,rv;
+    for(i=0;i<cfg->aliases->nelts;i++) {
+      mapcache_alias_entry *alias_entry = APR_ARRAY_IDX(cfg->aliases,i,mapcache_alias_entry*);
+      rv = mapcache_connection_pool_create(&(alias_entry->cp),pool);
+      ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "creating a child process mapcache connection pool on server %s for alias %s", s->server_hostname, alias_entry->endpoint);
+      if(rv!=APR_SUCCESS) {
+        ap_log_error(APLOG_MARK, APLOG_CRIT, 0, s, "failed to create mapcache connection pool");
+      }
+    }
   }
 }
 
@@ -341,12 +384,19 @@ static int mod_mapcache_request_handler(request_rec *r)
 
 
   apache_ctx = apache_request_context_create(r);
+
+  if(!apache_ctx) {
+    return DECLINED;
+  }
+
   global_ctx = (mapcache_context*)apache_ctx;
   global_ctx->supports_redirects = 1;
   global_ctx->headers_in = r->headers_in;
 
   params = mapcache_http_parse_param_string(global_ctx, r->args);
 
+  //ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "mapcache dispatch %s",r->path_info);
+
   mapcache_service_dispatch_request(global_ctx,&request,r->path_info,params,global_ctx->config);
   if(GC_HAS_ERROR(global_ctx) || !request) {
     return write_http_response(apache_ctx,
@@ -417,7 +467,7 @@ static int mod_mapcache_request_handler(request_rec *r)
           apr_table_set(req_proxy->headers, "X-Forwarded-Host", buf);
         }
       }
-      
+
       if ((buf = apr_table_get(r->headers_in, "X-Forwarded-Server"))) {
         apr_table_set(req_proxy->headers, "X-Forwarded-Server", apr_psprintf(global_ctx->pool, "%s, %s", buf, r->server->server_hostname));
       } else {
@@ -449,7 +499,6 @@ static int mod_mapcache_post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t
     ap_log_error(APLOG_MARK, APLOG_CRIT, 0, s, "configuration not found in server context");
     return 1;
   }
-  
 
 #ifdef USE_VERSION_STRING
   ap_add_version_component(p, MAPCACHE_USERAGENT);
@@ -497,35 +546,35 @@ static int mapcache_alias_matches(const char *uri, const char *alias_fakename)
   return urip - uri;
 }
 
-static int mapcache_hook_intercept(request_rec *r)
+static int mapcache_hook_fixups(request_rec *r)
 {
-  mapcache_server_cfg *sconfig = ap_get_module_config(r->server->module_config, &mapcache_module);
-  apr_hash_index_t *entry;
-
-  if (!sconfig->aliases)
-    return DECLINED;
-
-  if (r->uri[0] != '/' && r->uri[0])
-    return DECLINED;
-
-  entry = apr_hash_first(r->pool,sconfig->aliases);
-
-  /* loop through the entries to find one where the alias matches */
-  while (entry) {
-    int l = 0;
-    const char *alias;
-    apr_ssize_t aliaslen;
-    mapcache_cfg *c;
-    apr_hash_this(entry,(const void**)&alias,&aliaslen,(void**)&c);
-
-    if((l=mapcache_alias_matches(r->uri, c->endpoint))>0) {
-      r->handler = "mapcache";
-      r->filename = c->configFile;
-      r->path_info = &(r->uri[l]);
-      return OK;
+  int i;
+  //ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "running mapcache fixup on %s (handler:%s,filename:%s)",r->uri,r->handler,r->filename);
+  if(!r->handler) {
+    mapcache_server_cfg *sconfig = ap_get_module_config(r->server->module_config, &mapcache_module);
+    mapcache_alias_entry *alias_entry;
+
+    if (!sconfig || !sconfig->aliases)
+      return DECLINED;
+
+    if (r->uri[0] != '/' && r->uri[0])
+      return DECLINED;
+
+    /* loop through the entries to find one where the alias matches */
+    for(i=0; i<sconfig->aliases->nelts; i++) {
+      int l;
+      alias_entry = APR_ARRAY_IDX(sconfig->aliases,i,mapcache_alias_entry*);
+      //ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "cheking mapcache alias %s against %s",r->uri,alias_entry->endpoint);
+
+      if((l=mapcache_alias_matches(r->uri, alias_entry->endpoint))>0) {
+        r->handler = apr_pstrdup(r->pool,"mapcache");
+        apr_table_set(r->notes,"mapcache_alias_entry",alias_entry->endpoint);
+        r->path_info = &(r->uri[l]);
+        //ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "setting config %s for alias %s",alias_entry->configfile,alias_entry->endpoint);
+        //ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "using pathinfo %s from uri %s",r->path_info,r->uri);
+        return OK;
+      }
     }
-
-    entry = apr_hash_next(entry);
   }
 
   return DECLINED;
@@ -534,21 +583,17 @@ static int mapcache_hook_intercept(request_rec *r)
 
 static void mod_mapcache_register_hooks(apr_pool_t *p)
 {
-  static const char * const p1[] = { "mod_alias.c", "mod_rewrite.c", NULL };
-  static const char * const n1[]= { "mod_userdir.c",
-                                    "mod_vhost_alias.c", NULL
-                                  };
   ap_hook_child_init(mod_mapcache_child_init, NULL, NULL, APR_HOOK_MIDDLE);
   ap_hook_post_config(mod_mapcache_post_config, NULL, NULL, APR_HOOK_MIDDLE);
   ap_hook_handler(mod_mapcache_request_handler, NULL, NULL, APR_HOOK_MIDDLE);
-  ap_hook_translate_name(mapcache_hook_intercept, p1, n1, APR_HOOK_MIDDLE);
+  ap_hook_fixups(mapcache_hook_fixups, NULL, NULL, APR_HOOK_MIDDLE);
 
 }
 
 static void* mod_mapcache_create_server_conf(apr_pool_t *pool, server_rec *s)
 {
   mapcache_server_cfg *cfg = apr_pcalloc(pool, sizeof(mapcache_server_cfg));
-  cfg->aliases = NULL;
+  cfg->aliases = apr_array_make(pool,1,sizeof(mapcache_alias_entry*));
   return cfg;
 }
 
@@ -559,38 +604,69 @@ static void *mod_mapcache_merge_server_conf(apr_pool_t *p, void *base_, void *vh
   mapcache_server_cfg *vhost = (mapcache_server_cfg*)vhost_;
   mapcache_server_cfg *cfg = apr_pcalloc(p,sizeof(mapcache_server_cfg));
 
-  if (base->aliases && vhost->aliases) {
-    cfg->aliases = apr_hash_overlay(p, vhost->aliases,base->aliases);
-  } else if (vhost->aliases) {
-    cfg->aliases = apr_hash_copy(p,vhost->aliases);
-  } else if (base->aliases) {
-    cfg->aliases = apr_hash_copy(p,base->aliases);
+  cfg->aliases = apr_array_append(p, vhost->aliases,base->aliases);
+
+#if 0
+  {
+    mapcache_alias_entry *e;
+    int i;
+    fprintf(stderr,"#### merge called ####\n");
+    for(i=0;i<base->aliases->nelts;i++) {
+      e = APR_ARRAY_IDX(base->aliases,i,mapcache_alias_entry*);
+      fprintf(stderr,"merge base: have alias %s on %s\n",e->configfile,e->endpoint);
+    }
+    for(i=0;i<vhost->aliases->nelts;i++) {
+      e = APR_ARRAY_IDX(vhost->aliases,i,mapcache_alias_entry*);
+      fprintf(stderr,"merge vhosts: have alias %s on %s\n",e->configfile,e->endpoint);
+    }
+    for(i=0;i<cfg->aliases->nelts;i++) {
+      e = APR_ARRAY_IDX(cfg->aliases,i,mapcache_alias_entry*);
+      fprintf(stderr,"merge result: have alias %s on %s\n",e->configfile,e->endpoint);
+    }
   }
-  return vhost;
+#endif
+  return cfg;
 }
 
 static const char* mapcache_add_alias(cmd_parms *cmd, void *cfg, const char *alias, const char* configfile)
 {
-  mapcache_server_cfg *sconfig = ap_get_module_config(cmd->server->module_config, &mapcache_module);
-  mapcache_cfg *config = mapcache_configuration_create(cmd->pool);
-  mapcache_context *ctx = (mapcache_context*)apache_server_context_create(cmd->server,cmd->pool);
-  char *msg = NULL;
-  config->configFile = apr_pstrdup(cmd->pool,configfile);
-  config->endpoint = alias;
-  mapcache_configuration_parse(ctx,configfile,config,0);
+  mapcache_server_cfg *sconfig;
+  mapcache_alias_entry *alias_entry;
+  mapcache_context *ctx;
+  unsigned forbidden = NOT_IN_DIRECTORY|NOT_IN_FILES;
+  const char *err;
+
+#if (AP_SERVER_MAJORVERSION_NUMBER > 2) || (AP_SERVER_MINORVERSION_NUMBER >= 4)
+  forbidden |= NOT_IN_HTACCESS;
+#endif
+
+  err = ap_check_cmd_context(cmd, forbidden);
+  if (err) {
+    return err;
+  }
+
+  sconfig = ap_get_module_config(cmd->server->module_config, &mapcache_module);
+  if(!sconfig || !sconfig->aliases)
+    return "no mapcache module config, server bug?";
+
+  alias_entry = apr_pcalloc(cmd->pool,sizeof(mapcache_alias_entry));
+  ctx = (mapcache_context*)apache_server_context_create(cmd->server,cmd->pool);
+
+  alias_entry->cfg = mapcache_configuration_create(cmd->pool);
+  alias_entry->configfile = apr_pstrdup(cmd->pool,configfile);
+  alias_entry->endpoint = apr_pstrdup(cmd->pool,alias);
+  mapcache_configuration_parse(ctx,alias_entry->configfile,alias_entry->cfg,0);
   if(GC_HAS_ERROR(ctx)) {
     return ctx->get_error_message(ctx);
   }
-  mapcache_configuration_post_config(ctx, config);
+  mapcache_configuration_post_config(ctx, alias_entry->cfg);
   if(GC_HAS_ERROR(ctx)) {
     return ctx->get_error_message(ctx);
   }
-  ap_log_error(APLOG_MARK, APLOG_INFO, 0, cmd->server, "loaded mapcache configuration file from %s on alias %s", config->configFile, alias);
-  if(!sconfig->aliases) {
-    sconfig->aliases = apr_hash_make(cmd->pool);
-  }
-  apr_hash_set(sconfig->aliases,configfile,APR_HASH_KEY_STRING,config);
-  return msg;
+  APR_ARRAY_PUSH(sconfig->aliases,mapcache_alias_entry*) = alias_entry;
+  ap_log_error(APLOG_MARK, APLOG_INFO, 0, cmd->server, "loaded mapcache configuration file from %s on endpoint %s", alias_entry->configfile, alias_entry->endpoint);
+
+  return NULL;
 }
 
 
diff --git a/cgi/mapcache.c b/cgi/mapcache.c
index e7b9c20..75557e9 100644
--- a/cgi/mapcache.c
+++ b/cgi/mapcache.c
@@ -128,6 +128,11 @@ static void fcgi_write_response(mapcache_context_fcgi *ctx, mapcache_http_respon
   if(response->mtime) {
     char *datestr;
     char *if_modified_since = getenv("HTTP_IF_MODIFIED_SINCE");
+
+    datestr = apr_palloc(ctx->ctx.pool, APR_RFC822_DATE_LEN);
+    apr_rfc822_date(datestr, response->mtime);
+    printf("Last-Modified: %s\r\n", datestr);
+
     if(if_modified_since) {
       apr_time_t ims_time;
       apr_int64_t ims,mtime;
@@ -138,11 +143,14 @@ static void fcgi_write_response(mapcache_context_fcgi *ctx, mapcache_http_respon
       ims = apr_time_sec(ims_time);
       if(ims >= mtime) {
         printf("Status: 304 Not Modified\r\n");
+	/*
+	 * "The 304 response MUST NOT contain a message-body"
+	 * https://tools.ietf.org/html/rfc2616#section-10.3.5
+	 */
+	printf("\r\n");
+	return;
       }
     }
-    datestr = apr_palloc(ctx->ctx.pool, APR_RFC822_DATE_LEN);
-    apr_rfc822_date(datestr, response->mtime);
-    printf("Last-Modified: %s\r\n", datestr);
   }
   if(response->data) {
     printf("Content-Length: %ld\r\n\r\n", response->data->size);
diff --git a/cmake/FindAPACHE.cmake b/cmake/FindAPACHE.cmake
index dd4f80d..5bc7825 100644
--- a/cmake/FindAPACHE.cmake
+++ b/cmake/FindAPACHE.cmake
@@ -10,7 +10,7 @@
 #
 find_path(APACHE_INCLUDE_DIR
           NAMES httpd.h 
-          PATH_SUFFIXES httpd apache apache2
+          PATH_SUFFIXES httpd apache apache2 apache22 apache24
 )
 
 if(NOT DEFINED APACHE_MODULE_DIR)
diff --git a/include/mapcache.h b/include/mapcache.h
index c4ed758..8f24326 100644
--- a/include/mapcache.h
+++ b/include/mapcache.h
@@ -90,7 +90,11 @@
 
 #define MAPCACHE_USERAGENT "mod-mapcache/"MAPCACHE_VERSION
 
-
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#  define MS_DLL_EXPORT     __declspec(dllexport)
+#else
+#define  MS_DLL_EXPORT
+#endif
 
 
 typedef struct mapcache_image_format mapcache_image_format;
@@ -219,13 +223,13 @@ struct mapcache_context {
    * \memberof mapcache_context
    */
   void (*clear_errors)(mapcache_context * ctx);
-  
+
   /**
    * \brief clear current error and store it in mapcache_error
    * \memberof mapcache_context
    */
   void (*pop_errors)(mapcache_context * ctx, void **error);
-  
+
   /**
    * \brief restore error status from mapcache_error
    * \memberof mapcache_context
@@ -254,8 +258,8 @@ struct mapcache_context {
   apr_table_t *headers_in;
 };
 
-void mapcache_context_init(mapcache_context *ctx);
-void mapcache_context_copy(mapcache_context *src, mapcache_context *dst);
+MS_DLL_EXPORT void mapcache_context_init(mapcache_context *ctx);
+MS_DLL_EXPORT void mapcache_context_copy(mapcache_context *src, mapcache_context *dst);
 
 #define GC_CHECK_ERROR_RETURN(ctx) if(((mapcache_context*)ctx)->_errcode) return MAPCACHE_FAILURE;
 #define GC_CHECK_ERROR(ctx) if(((mapcache_context*)ctx)->_errcode) return;
@@ -511,7 +515,7 @@ typedef enum {
   MAPCACHE_REST_PROVIDER_NONE,
   MAPCACHE_REST_PROVIDER_S3,
   MAPCACHE_REST_PROVIDER_AZURE,
-  MAPCACHE_REST_PROVIDER_GOOGLE,
+  MAPCACHE_REST_PROVIDER_GOOGLE
 } mapcache_rest_provider;
 
 void sha256(const unsigned char *message, unsigned int len, unsigned char *digest);
@@ -1041,7 +1045,7 @@ mapcache_service* mapcache_service_demo_create(mapcache_context *ctx);
 /**
  * \brief return the request that corresponds to the given url
  */
-void mapcache_service_dispatch_request(mapcache_context *ctx,
+MS_DLL_EXPORT void mapcache_service_dispatch_request(mapcache_context *ctx,
                                        mapcache_request **request,
                                        char *pathinfo,
                                        apr_table_t *params,
@@ -1147,17 +1151,13 @@ void mapcache_image_fill(mapcache_context *ctx, mapcache_image *image, const uns
 /** @{ */
 void mapcache_http_do_request(mapcache_context *ctx, mapcache_http *req, mapcache_buffer *data, apr_table_t *headers, long *http_code);
 char* mapcache_http_build_url(mapcache_context *ctx, char *base, apr_table_t *params);
-apr_table_t *mapcache_http_parse_param_string(mapcache_context *ctx, char *args);
+MS_DLL_EXPORT apr_table_t *mapcache_http_parse_param_string(mapcache_context *ctx, char *args);
 /** @} */
 
 /** \defgroup configuration Configuration*/
 
 /** @{ */
 
-struct mapcache_server_cfg {
-  apr_hash_t *aliases; /**< list of mapcache configurations aliased to a server uri */
-  mapcache_connection_pool *cp;
-};
 
 
 
@@ -1184,7 +1184,7 @@ struct mapcache_locker{
   mapcache_lock_result (*aquire_lock)(mapcache_context *ctx, mapcache_locker *self, char *resource, void **lock);
   mapcache_lock_result (*ping_lock)(mapcache_context *ctx, mapcache_locker *self, char *resource, void *lock);
   void (*release_lock)(mapcache_context *ctx, mapcache_locker *self, char *resource, void *lock);
-  
+
   void (*parse_xml)(mapcache_context *ctx, mapcache_locker *self, ezxml_t node);
   mapcache_lock_mode type;
   double timeout;
@@ -1233,8 +1233,6 @@ void mapcache_config_parse_locker(mapcache_context *ctx, ezxml_t node, mapcache_
  * a configuration that will be served
  */
 struct mapcache_cfg {
-  char *configFile; /**< the filename from which this configuration was loaded */
-
   /**
    * a list of services that will be responded to
    */
@@ -1290,11 +1288,6 @@ struct mapcache_cfg {
 
   int threaded_fetching;
 
-  /**
-   * the uri where the base of the service is mapped
-   */
-  const char *endpoint;
-
   /* for fastcgi only */
   int autoreload; /* should the modification time of the config file be recorded
                        and the file be reparsed if it is modified. */
@@ -1315,14 +1308,14 @@ struct mapcache_cfg {
  * @param pool
  * @return
  */
-void mapcache_configuration_parse(mapcache_context *ctx, const char *filename, mapcache_cfg *config, int cgi);
-void mapcache_configuration_post_config(mapcache_context *ctx, mapcache_cfg *config);
+MS_DLL_EXPORT void mapcache_configuration_parse(mapcache_context *ctx, const char *filename, mapcache_cfg *config, int cgi);
+MS_DLL_EXPORT void mapcache_configuration_post_config(mapcache_context *ctx, mapcache_cfg *config);
 void mapcache_configuration_parse_xml(mapcache_context *ctx, const char *filename, mapcache_cfg *config);
-mapcache_cfg* mapcache_configuration_create(apr_pool_t *pool);
+MS_DLL_EXPORT mapcache_cfg* mapcache_configuration_create(apr_pool_t *pool);
 mapcache_source* mapcache_configuration_get_source(mapcache_cfg *config, const char *key);
-mapcache_cache* mapcache_configuration_get_cache(mapcache_cfg *config, const char *key);
+MS_DLL_EXPORT mapcache_cache* mapcache_configuration_get_cache(mapcache_cfg *config, const char *key);
 mapcache_grid *mapcache_configuration_get_grid(mapcache_cfg *config, const char *key);
-mapcache_tileset* mapcache_configuration_get_tileset(mapcache_cfg *config, const char *key);
+MS_DLL_EXPORT mapcache_tileset* mapcache_configuration_get_tileset(mapcache_cfg *config, const char *key);
 mapcache_image_format *mapcache_configuration_get_image_format(mapcache_cfg *config, const char *key);
 void mapcache_configuration_add_image_format(mapcache_cfg *config, mapcache_image_format *format, const char * key);
 void mapcache_configuration_add_source(mapcache_cfg *config, mapcache_source *source, const char * key);
@@ -1446,7 +1439,7 @@ typedef enum {
   MAPCACHE_GRID_ORIGIN_BOTTOM_LEFT,
   MAPCACHE_GRID_ORIGIN_TOP_LEFT,
   MAPCACHE_GRID_ORIGIN_BOTTOM_RIGHT,
-  MAPCACHE_GRID_ORIGIN_TOP_RIGHT,
+  MAPCACHE_GRID_ORIGIN_TOP_RIGHT
 } mapcache_grid_origin;
 
 struct mapcache_grid {
@@ -1478,7 +1471,7 @@ struct mapcache_grid_link {
   mapcache_extent *restricted_extent;
   mapcache_extent_i *grid_limits;
   int minz,maxz;
-  
+
   /**
    * tiles above this zoom level will not be stored to the cache, but will be
    * dynamically generated (either by reconstructing from lower level tiles, or
@@ -1620,13 +1613,13 @@ void mapcache_tileset_tile_validate(mapcache_context *ctx, mapcache_tile *tile);
 void mapcache_tileset_get_level(mapcache_context *ctx, mapcache_tileset *tileset, double *resolution, int *level);
 
 mapcache_grid_link* mapcache_grid_get_closest_wms_level(mapcache_context *ctx, mapcache_grid_link *grid, double resolution, int *level);
-void mapcache_tileset_tile_get(mapcache_context *ctx, mapcache_tile *tile);
+MS_DLL_EXPORT void mapcache_tileset_tile_get(mapcache_context *ctx, mapcache_tile *tile);
 
 /**
  * \brief delete tile from cache
  * @param whole_metatile delete all the other tiles from the metatile to
  */
-void mapcache_tileset_tile_delete(mapcache_context *ctx, mapcache_tile *tile, int whole_metatile);
+MS_DLL_EXPORT void mapcache_tileset_tile_delete(mapcache_context *ctx, mapcache_tile *tile, int whole_metatile);
 
 int mapcache_grid_is_bbox_aligned(mapcache_context *ctx, mapcache_grid *grid, mapcache_extent *bbox);
 
@@ -1637,7 +1630,7 @@ int mapcache_grid_is_bbox_aligned(mapcache_context *ctx, mapcache_grid *grid, ma
  * @param pool
  * @return
  */
-mapcache_tile* mapcache_tileset_tile_create(apr_pool_t *pool, mapcache_tileset *tileset, mapcache_grid_link *grid_link);
+MS_DLL_EXPORT mapcache_tile* mapcache_tileset_tile_create(apr_pool_t *pool, mapcache_tileset *tileset, mapcache_grid_link *grid_link);
 
 mapcache_tile* mapcache_tileset_tile_clone(apr_pool_t *pool, mapcache_tile *src);
 
@@ -1670,27 +1663,27 @@ void mapcache_tileset_configuration_check(mapcache_context *ctx, mapcache_tilese
 void mapcache_tileset_add_watermark(mapcache_context *ctx, mapcache_tileset *tileset, const char *filename);
 
 
-int mapcache_lock_or_wait_for_resource(mapcache_context *ctx, mapcache_locker *locker, char *resource, void **lock);
-void mapcache_unlock_resource(mapcache_context *ctx, mapcache_locker *locker, char *resource, void *lock);
+MS_DLL_EXPORT int mapcache_lock_or_wait_for_resource(mapcache_context *ctx, mapcache_locker *locker, char *resource, void **lock);
+MS_DLL_EXPORT void mapcache_unlock_resource(mapcache_context *ctx, mapcache_locker *locker, char *resource, void *lock);
 
-mapcache_metatile* mapcache_tileset_metatile_get(mapcache_context *ctx, mapcache_tile *tile);
-void mapcache_tileset_render_metatile(mapcache_context *ctx, mapcache_metatile *mt);
-char* mapcache_tileset_metatile_resource_key(mapcache_context *ctx, mapcache_metatile *mt);
+MS_DLL_EXPORT mapcache_metatile* mapcache_tileset_metatile_get(mapcache_context *ctx, mapcache_tile *tile);
+MS_DLL_EXPORT void mapcache_tileset_render_metatile(mapcache_context *ctx, mapcache_metatile *mt);
+MS_DLL_EXPORT char* mapcache_tileset_metatile_resource_key(mapcache_context *ctx, mapcache_metatile *mt);
 
 
 /** @} */
 
 
 
-mapcache_http_response* mapcache_core_get_capabilities(mapcache_context *ctx, mapcache_service *service, mapcache_request_get_capabilities *req_caps, char *url, char *path_info, mapcache_cfg *config);
-mapcache_http_response* mapcache_core_get_tile(mapcache_context *ctx, mapcache_request_get_tile *req_tile);
+MS_DLL_EXPORT mapcache_http_response* mapcache_core_get_capabilities(mapcache_context *ctx, mapcache_service *service, mapcache_request_get_capabilities *req_caps, char *url, char *path_info, mapcache_cfg *config);
+MS_DLL_EXPORT mapcache_http_response* mapcache_core_get_tile(mapcache_context *ctx, mapcache_request_get_tile *req_tile);
 
-mapcache_http_response* mapcache_core_get_map(mapcache_context *ctx, mapcache_request_get_map *req_map);
+MS_DLL_EXPORT mapcache_http_response* mapcache_core_get_map(mapcache_context *ctx, mapcache_request_get_map *req_map);
 
-mapcache_http_response* mapcache_core_get_featureinfo(mapcache_context *ctx, mapcache_request_get_feature_info *req_fi);
+MS_DLL_EXPORT mapcache_http_response* mapcache_core_get_featureinfo(mapcache_context *ctx, mapcache_request_get_feature_info *req_fi);
 
-mapcache_http_response* mapcache_core_proxy_request(mapcache_context *ctx, mapcache_request_proxy *req_proxy);
-mapcache_http_response* mapcache_core_respond_to_error(mapcache_context *ctx);
+MS_DLL_EXPORT mapcache_http_response* mapcache_core_proxy_request(mapcache_context *ctx, mapcache_request_proxy *req_proxy);
+MS_DLL_EXPORT mapcache_http_response* mapcache_core_respond_to_error(mapcache_context *ctx);
 
 
 /* in grid.c */
@@ -1699,7 +1692,7 @@ mapcache_grid* mapcache_grid_create(apr_pool_t *pool);
 const char* mapcache_grid_get_crs(mapcache_context *ctx, mapcache_grid *grid);
 const char* mapcache_grid_get_srs(mapcache_context *ctx, mapcache_grid *grid);
 
-void mapcache_grid_get_extent(mapcache_context *ctx, mapcache_grid *grid,
+MS_DLL_EXPORT void mapcache_grid_get_extent(mapcache_context *ctx, mapcache_grid *grid,
                               int x, int y, int z, mapcache_extent *bbox);
 /**
  * \brief compute x y value for given lon/lat (dx/dy) and given zoomlevel
@@ -1711,7 +1704,7 @@ void mapcache_grid_get_extent(mapcache_context *ctx, mapcache_grid *grid,
  * @param x
  * @param y
  */
-void mapcache_grid_get_xy(mapcache_context *ctx, mapcache_grid *grid, double dx, double dy, int z, int *x, int *y);
+MS_DLL_EXPORT void mapcache_grid_get_xy(mapcache_context *ctx, mapcache_grid *grid, double dx, double dy, int z, int *x, int *y);
 
 double mapcache_grid_get_resolution(mapcache_extent *bbox, int sx, int sy);
 double mapcache_grid_get_horizontal_resolution(mapcache_extent *bbox, int width);
@@ -1731,12 +1724,12 @@ int mapcache_grid_get_level(mapcache_context *ctx, mapcache_grid *grid, double *
  * \param extent
  * \param tolerance the number of tiles around the given extent that can be requested without returning an error.
  */
-void mapcache_grid_compute_limits(const mapcache_grid *grid, const mapcache_extent *extent, mapcache_extent_i *limits, int tolerance);
+MS_DLL_EXPORT void mapcache_grid_compute_limits(const mapcache_grid *grid, const mapcache_extent *extent, mapcache_extent_i *limits, int tolerance);
 
 /* in util.c */
-int mapcache_util_extract_int_list(mapcache_context *ctx, const char* args, const char *sep, int **numbers,
+MS_DLL_EXPORT int mapcache_util_extract_int_list(mapcache_context *ctx, const char* args, const char *sep, int **numbers,
                                    int *numbers_count);
-int mapcache_util_extract_double_list(mapcache_context *ctx, const char* args, const char *sep, double **numbers,
+MS_DLL_EXPORT int mapcache_util_extract_double_list(mapcache_context *ctx, const char* args, const char *sep, double **numbers,
                                       int *numbers_count);
 char *mapcache_util_str_replace(apr_pool_t *pool, const char *string, const char *substr,
                                 const char *replacement );
@@ -1755,6 +1748,7 @@ char* mapcache_util_get_tile_dimkey(mapcache_context *ctx, mapcache_tile *tile,
 
 char* mapcache_util_get_tile_key(mapcache_context *ctx, mapcache_tile *tile, char *stemplate,
                                  char* sanitized_chars, char *sanitize_to);
+void mapcache_make_parent_dirs(mapcache_context *ctx, char *filename);
 
 /**\defgroup imageio Image IO */
 /** @{ */
@@ -2026,13 +2020,13 @@ typedef enum {
   MAPCACHE_TIMEDIMENSION_SOURCE_SQLITE
 } mapcache_timedimension_source_type;
 
-apr_array_header_t* mapcache_timedimension_get_entries_for_value(mapcache_context *ctx, mapcache_timedimension *timedimesnion,
+MS_DLL_EXPORT apr_array_header_t* mapcache_timedimension_get_entries_for_value(mapcache_context *ctx, mapcache_timedimension *timedimesnion,
         mapcache_tileset *tileset, mapcache_grid *grid, mapcache_extent *extent, const char *value);
 
 struct mapcache_timedimension {
   mapcache_timedimension_assembly_type assembly_type;
   void (*configuration_parse_xml)(mapcache_context *context, mapcache_timedimension *dim, ezxml_t node);
-  apr_array_header_t* (*get_entries_for_interval)(mapcache_context *ctx, mapcache_timedimension *dim, mapcache_tileset *tileset, 
+  apr_array_header_t* (*get_entries_for_interval)(mapcache_context *ctx, mapcache_timedimension *dim, mapcache_tileset *tileset,
         mapcache_grid *grid, mapcache_extent *extent, time_t start, time_t end);
   apr_array_header_t* (*get_all_entries)(mapcache_context *ctx, mapcache_timedimension *dim, mapcache_tileset *tileset);
   char *default_value;
@@ -2060,10 +2054,10 @@ struct mapcache_pooled_connection {
     void *connection;
 };
 
-typedef void (*mapcache_connection_constructor)(mapcache_context *ctx, void **connection, void *params, apr_pool_t *process_pool);
-typedef void (*mapcache_connection_destructor)(void *connection, apr_pool_t *process_pool);
+typedef void (*mapcache_connection_constructor)(mapcache_context *ctx, void **connection, void *params);
+typedef void (*mapcache_connection_destructor)(void *connection);
 
-apr_status_t mapcache_connection_pool_create(mapcache_connection_pool **cp, apr_pool_t *server_pool);
+MS_DLL_EXPORT apr_status_t mapcache_connection_pool_create(mapcache_connection_pool **cp, apr_pool_t *server_pool);
 mapcache_pooled_connection* mapcache_connection_pool_get_connection(mapcache_context *ctx, char *key,
         mapcache_connection_constructor constructor,
         mapcache_connection_destructor destructor,
diff --git a/include/util.h b/include/util.h
index 4f95592..1be2354 100644
--- a/include/util.h
+++ b/include/util.h
@@ -87,13 +87,19 @@ APR_DECLARE(apr_table_t *) apr_table_clone(apr_pool_t *p,
 #endif
 #endif
 
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#  define MS_DLL_EXPORT     __declspec(dllexport)
+#else
+#define  MS_DLL_EXPORT
+#endif
 
 #if defined(_WIN32)
 struct mctimeval {
   long    tv_sec;         /* seconds */
   long    tv_usec;        /* and microseconds */
 };
-void  mapcache_gettimeofday(struct mctimeval *t, void *__not_used_here__);
+MS_DLL_EXPORT void  mapcache_gettimeofday(struct mctimeval *t, void *__not_used_here__);
+MS_DLL_EXPORT char * strptime (const char *buf, const char *format, struct tm *timeptr);
 #else
 #  include <sys/time.h>     /* for gettimeofday() */
 #  define  mctimeval timeval
diff --git a/lib/cache_bdb.c b/lib/cache_bdb.c
index fd40d43..a45ca4b 100644
--- a/lib/cache_bdb.c
+++ b/lib/cache_bdb.c
@@ -58,56 +58,60 @@ struct bdb_env {
   char *errmsg;
 };
 
-void mapcache_bdb_connection_constructor(mapcache_context *ctx, void **conn_, void *params, apr_pool_t *pool)
+void mapcache_bdb_connection_constructor(mapcache_context *ctx, void **conn_, void *params)
 {
   int ret;
   int env_flags;
   int mode;
   mapcache_cache_bdb *cache = (mapcache_cache_bdb*)params;
-  char *dbfile = apr_pstrcat(pool,cache->basedir,"/",cache->cache.name,".db",NULL);
+  char *dbfile = malloc(strlen(cache->basedir)+strlen(cache->cache.name)+strlen("/.db")+1);
   struct bdb_env *benv = calloc(1,sizeof(struct bdb_env));
+  dbfile[0]=0;
+  strcat(strcat(strcat(strcat(dbfile,cache->basedir),"/"),cache->cache.name),".db"); /*yuk yuk*/
   *conn_ = benv;
 
   ret = db_env_create(&benv->env, 0);
   if(ret) {
     ctx->set_error(ctx, 500, "bdb cache failure for db_env_create: %s", db_strerror(ret));
-    free(benv);
-    return;
+    goto cleanup_error;
   }
   ret = benv->env->set_cachesize(benv->env,0,CACHESIZE,1); /* set a larger cache size than default */
   if(ret) {
     ctx->set_error(ctx, 500, "bdb cache failure for db->set_cachesize: %s", db_strerror(ret));
-    free(benv);
-    return;
+    goto cleanup_error;
   }
   env_flags = DB_INIT_CDB|DB_INIT_MPOOL|DB_CREATE;
   ret = benv->env->open(benv->env,cache->basedir,env_flags,0);
   if(ret) {
     ctx->set_error(ctx,500,"bdb cache failure for env->open: %s", db_strerror(ret));
-    free(benv);
-    return;
+    goto cleanup_error;
   }
 
   if ((ret = db_create(&benv->db, benv->env, 0)) != 0) {
     ctx->set_error(ctx,500,"bdb cache failure for db_create: %s", db_strerror(ret));
-    free(benv);
+    goto cleanup_error;
   }
   mode = DB_BTREE;
   ret = benv->db->set_pagesize(benv->db,PAGESIZE); /* set pagesize to maximum allowed, as tile data is usually pretty large */
   if(ret) {
     ctx->set_error(ctx,500,"bdb cache failure for db->set_pagesize: %s", db_strerror(ret));
-    free(benv);
-    return;
+    goto cleanup_error;
   }
 
   if ((ret = benv->db->open(benv->db, NULL, dbfile, NULL, mode, DB_CREATE, 0664)) != 0) {
     ctx->set_error(ctx,500,"bdb cache failure 1 for db->open: %s", db_strerror(ret));
-    free(benv);
-    return;
+    goto cleanup_error;
   }
+  
+  goto cleanup;
+  
+cleanup_error:
+  free(benv);
+cleanup:
+  free(dbfile);
 }
 
-void mapcache_bdb_connection_destructor(void *conn_, apr_pool_t *pool)
+void mapcache_bdb_connection_destructor(void *conn_)
 {
   struct bdb_env *benv = (struct bdb_env*)conn_;
   benv->db->close(benv->db,0);
@@ -144,7 +148,7 @@ static int _mapcache_cache_bdb_has_tile(mapcache_context *ctx, mapcache_cache *p
   mapcache_cache_bdb *cache = (mapcache_cache_bdb*)pcache;
   char *skey = mapcache_util_get_tile_key(ctx,tile,cache->key_template,NULL,NULL);
   mapcache_pooled_connection *pc;
-  struct bdb_env *benv; 
+  struct bdb_env *benv;
   pc = _bdb_get_conn(ctx,cache,tile,1);
   if(GC_HAS_ERROR(ctx)) return MAPCACHE_FALSE;
   benv = pc->connection;
@@ -173,7 +177,7 @@ static void _mapcache_cache_bdb_delete(mapcache_context *ctx, mapcache_cache *pc
   mapcache_cache_bdb *cache = (mapcache_cache_bdb*)pcache;
   char *skey = mapcache_util_get_tile_key(ctx,tile,cache->key_template,NULL,NULL);
   mapcache_pooled_connection *pc;
-  struct bdb_env *benv; 
+  struct bdb_env *benv;
   pc = _bdb_get_conn(ctx,cache,tile,0);
   GC_CHECK_ERROR(ctx);
   benv = pc->connection;
@@ -195,13 +199,14 @@ static int _mapcache_cache_bdb_get(mapcache_context *ctx, mapcache_cache *pcache
 {
   DBT key,data;
   int ret;
+  char *skey;
   mapcache_cache_bdb *cache = (mapcache_cache_bdb*)pcache;
   mapcache_pooled_connection *pc;
-  struct bdb_env *benv; 
+  struct bdb_env *benv;
   pc = _bdb_get_conn(ctx,cache,tile,1);
   if(GC_HAS_ERROR(ctx)) return MAPCACHE_FALSE;
   benv = pc->connection;
-  char *skey = mapcache_util_get_tile_key(ctx,tile,cache->key_template,NULL,NULL);
+  skey = mapcache_util_get_tile_key(ctx,tile,cache->key_template,NULL,NULL);
   memset(&key, 0, sizeof(DBT));
   memset(&data, 0, sizeof(DBT));
   data.flags = DB_DBT_MALLOC;
@@ -242,7 +247,7 @@ static void _mapcache_cache_bdb_set(mapcache_context *ctx, mapcache_cache *pcach
   mapcache_cache_bdb *cache = (mapcache_cache_bdb*)pcache;
   char *skey = mapcache_util_get_tile_key(ctx,tile,cache->key_template,NULL,NULL);
   mapcache_pooled_connection *pc;
-  struct bdb_env *benv; 
+  struct bdb_env *benv;
   now = apr_time_now();
   memset(&key, 0, sizeof(DBT));
   memset(&data, 0, sizeof(DBT));
@@ -254,7 +259,7 @@ static void _mapcache_cache_bdb_set(mapcache_context *ctx, mapcache_cache *pcach
     tile->raw_image = mapcache_imageio_decode(ctx, tile->encoded_data);
     GC_CHECK_ERROR(ctx);
   }
-  
+
   if(tile->raw_image->h==256 && tile->raw_image->w==256 && mapcache_image_blank_color(tile->raw_image) != MAPCACHE_FALSE) {
     data.size = 5+sizeof(apr_time_t);
     data.data = apr_palloc(ctx->pool,data.size);
@@ -271,7 +276,7 @@ static void _mapcache_cache_bdb_set(mapcache_context *ctx, mapcache_cache *pcach
     data.size = tile->encoded_data->size;
     tile->encoded_data->size -= sizeof(apr_time_t);
   }
-  
+
   pc = _bdb_get_conn(ctx,cache,tile,0);
   GC_CHECK_ERROR(ctx);
   benv = pc->connection;
@@ -295,7 +300,7 @@ static void _mapcache_cache_bdb_multiset(mapcache_context *ctx, mapcache_cache *
   apr_time_t now;
   mapcache_cache_bdb *cache = (mapcache_cache_bdb*)pcache;
   mapcache_pooled_connection *pc;
-  struct bdb_env *benv; 
+  struct bdb_env *benv;
   now = apr_time_now();
   memset(&key, 0, sizeof(DBT));
   memset(&data, 0, sizeof(DBT));
@@ -303,7 +308,7 @@ static void _mapcache_cache_bdb_multiset(mapcache_context *ctx, mapcache_cache *
   pc = _bdb_get_conn(ctx,cache,&tiles[0],0);
   GC_CHECK_ERROR(ctx);
   benv = pc->connection;
-  
+
   for(i=0; i<ntiles; i++) {
     char *skey;
     mapcache_tile *tile;
diff --git a/lib/cache_disk.c b/lib/cache_disk.c
index 304e21c..2ffbb0a 100644
--- a/lib/cache_disk.c
+++ b/lib/cache_disk.c
@@ -442,7 +442,7 @@ static void _mapcache_cache_disk_set(mapcache_context *ctx, mapcache_cache *pcac
   apr_file_t *f;
   apr_status_t ret;
   char errmsg[120];
-  char *filename, *hackptr1, *hackptr2=NULL;
+  char *filename;
   mapcache_cache_disk *cache = (mapcache_cache_disk*)pcache;
   const int creation_retry = cache->creation_retry;
   int retry_count_create_file = 0;
@@ -462,26 +462,8 @@ static void _mapcache_cache_disk_set(mapcache_context *ctx, mapcache_cache *pcac
   cache->tile_key(ctx, cache, tile, &filename);
   GC_CHECK_ERROR(ctx);
 
-  /* find the location of the last '/' in the string */
-  hackptr1 = filename;
-  while(*hackptr1) {
-    if(*hackptr1 == '/')
-      hackptr2 = hackptr1;
-    hackptr1++;
-  }
-  *hackptr2 = '\0';
-
-  if(APR_SUCCESS != (ret = apr_dir_make_recursive(filename,APR_OS_DEFAULT,ctx->pool))) {
-    /*
-     * apr_dir_make_recursive sometimes sends back this error, although it should not.
-     * ignore this one
-     */
-    if(!APR_STATUS_IS_EEXIST(ret)) {
-      ctx->set_error(ctx, 500, "failed to create directory %s: %s",filename, apr_strerror(ret,errmsg,120));
-      return;
-    }
-  }
-  *hackptr2 = '/';
+  mapcache_make_parent_dirs(ctx,filename);
+  GC_CHECK_ERROR(ctx);
 
   ret = apr_file_remove(filename,ctx->pool);
   if(ret != APR_SUCCESS && !APR_STATUS_IS_ENOENT(ret)) {
@@ -497,26 +479,19 @@ static void _mapcache_cache_disk_set(mapcache_context *ctx, mapcache_cache *pcac
     }
     if(mapcache_image_blank_color(tile->raw_image) != MAPCACHE_FALSE) {
       char *blankname;
+      int retry_count_create_symlink = 0;
+      char *blankname_rel = NULL;
       _mapcache_cache_disk_blank_tile_key(ctx,cache,tile,tile->raw_image->data,&blankname);
       if(apr_file_open(&f, blankname, APR_FOPEN_READ, APR_OS_DEFAULT, ctx->pool) != APR_SUCCESS) {
+        /* create the blank file */
         int isLocked;
         void *lock;
         if(!tile->encoded_data) {
           tile->encoded_data = tile->tileset->format->write(ctx, tile->raw_image, tile->tileset->format);
           GC_CHECK_ERROR(ctx);
         }
-        /* create the blank file */
-        char *blankdirname = apr_psprintf(ctx->pool, "%s/%s/%s/blanks",
-                                          cache->base_directory,
-                                          tile->tileset->name,
-                                          tile->grid_link->grid->name);
-        if(APR_SUCCESS != (ret = apr_dir_make_recursive(
-                                   blankdirname, APR_OS_DEFAULT,ctx->pool))) {
-          if(!APR_STATUS_IS_EEXIST(ret)) {
-            ctx->set_error(ctx, 500,  "failed to create directory %s for blank tiles",blankdirname, apr_strerror(ret,errmsg,120));
-            return;
-          }
-        }
+        mapcache_make_parent_dirs(ctx,blankname);
+        GC_CHECK_ERROR(ctx);
 
         /* aquire a lock on the blank file */
         isLocked = mapcache_lock_or_wait_for_resource(ctx,ctx->config->locker,blankname, &lock);
@@ -554,12 +529,10 @@ static void _mapcache_cache_disk_set(mapcache_context *ctx, mapcache_cache *pcac
         apr_file_close(f);
       }
 
-      int retry_count_create_symlink = 0;
 
       /*
        * compute the relative path between tile and blank tile
        */
-      char *blankname_rel = NULL;
       blankname_rel = relative_path(ctx,filename, blankname);
       GC_CHECK_ERROR(ctx);
 
@@ -576,17 +549,8 @@ static void _mapcache_cache_disk_set(mapcache_context *ctx, mapcache_cache *pcac
           ctx->set_error(ctx, 500, "failed to link tile %s to %s: %s",filename, blankname_rel, error);
           return; /* we could not create the file */
         }
-
-        *hackptr2 = '\0';
-
-        if(APR_SUCCESS != (ret = apr_dir_make_recursive(filename,APR_OS_DEFAULT,ctx->pool))) {
-          if(!APR_STATUS_IS_EEXIST(ret)) {
-            ctx->set_error(ctx, 500, "failed to create symlink, can not create directory %s: %s",filename, apr_strerror(ret,errmsg,120));
-            return; /* we could not create the file */
-          }
-        }
-
-        *hackptr2 = '/';
+        mapcache_make_parent_dirs(ctx,filename);
+        GC_CHECK_ERROR(ctx);
       }
 #ifdef DEBUG
       ctx->log(ctx, MAPCACHE_DEBUG, "linked blank tile %s to %s",filename,blankname);
@@ -618,17 +582,8 @@ static void _mapcache_cache_disk_set(mapcache_context *ctx, mapcache_cache *pcac
       ctx->set_error(ctx, 500, "failed to create file %s: %s",filename, apr_strerror(ret,errmsg,120));
       return; /* we could not create the file */
     }
-
-    *hackptr2 = '\0';
-
-    if(APR_SUCCESS != (ret = apr_dir_make_recursive(filename,APR_OS_DEFAULT,ctx->pool))) {
-      if(!APR_STATUS_IS_EEXIST(ret)) {
-        ctx->set_error(ctx, 500, "failed to create file, can not create directory %s: %s",filename, apr_strerror(ret,errmsg,120));
-        return; /* we could not create the file */
-      }
-    }
-
-    *hackptr2 = '/';
+    mapcache_make_parent_dirs(ctx,filename);
+    GC_CHECK_ERROR(ctx);
   }
 
   bytes = (apr_size_t)tile->encoded_data->size;
diff --git a/lib/cache_fallback.c b/lib/cache_fallback.c
index 885ee30..28c3c47 100644
--- a/lib/cache_fallback.c
+++ b/lib/cache_fallback.c
@@ -64,13 +64,13 @@ static int _mapcache_cache_fallback_tile_get(mapcache_context *ctx, mapcache_cac
   if(ret == MAPCACHE_FAILURE) {
     int first_error = ctx->get_error(ctx);
     char *first_error_message = ctx->get_error_message(ctx);
-    ctx->log(ctx,MAPCACHE_WARN,"failed \"GET\" on primary cache \"%s\" for tile (z=%d,x=%d,y=%d) of tileset \"%s\". Falling back on secondary caches",
+    ctx->log(ctx,MAPCACHE_DEBUG,"failed \"GET\" on primary cache \"%s\" for tile (z=%d,x=%d,y=%d) of tileset \"%s\". Falling back on secondary caches",
             APR_ARRAY_IDX(cache->caches,0,mapcache_cache*)->name,tile->z,tile->x,tile->y,tile->tileset->name);
     ctx->clear_errors(ctx);
     for(i=1; i<cache->caches->nelts; i++) {
       subcache = APR_ARRAY_IDX(cache->caches,i,mapcache_cache*);
       if((ret = subcache->tile_get(ctx, subcache, tile)) == MAPCACHE_FAILURE) {
-        ctx->log(ctx,MAPCACHE_WARN,"failed \"GET\" on fallback cache \"%s\" for tile (z=%d,x=%d,y=%d) of tileset \"%s\". Continuing with other fallback caches if available",
+        ctx->log(ctx,MAPCACHE_DEBUG,"failed \"GET\" on fallback cache \"%s\" for tile (z=%d,x=%d,y=%d) of tileset \"%s\". Continuing with other fallback caches if available",
                 APR_ARRAY_IDX(cache->caches,0,mapcache_cache*)->name,tile->z,tile->x,tile->y,tile->tileset->name);
         ctx->clear_errors(ctx);
         continue;
@@ -100,7 +100,7 @@ static void _mapcache_cache_fallback_tile_set(mapcache_context *ctx, mapcache_ca
         first_error = ctx->get_error(ctx);
         first_error_message = ctx->get_error_message(ctx);
       }
-      ctx->log(ctx,MAPCACHE_WARN,"failed \"SET\" on subcache \"%s\" for tile (z=%d,x=%d,y=%d) of tileset \"%s\"",
+      ctx->log(ctx,MAPCACHE_DEBUG,"failed \"SET\" on subcache \"%s\" for tile (z=%d,x=%d,y=%d) of tileset \"%s\"",
               APR_ARRAY_IDX(cache->caches,i,mapcache_cache*)->name,tile->z,tile->x,tile->y,tile->tileset->name);
       ctx->clear_errors(ctx);
     } else {
@@ -135,7 +135,7 @@ static void _mapcache_cache_fallback_tile_multi_set(mapcache_context *ctx, mapca
         first_error = ctx->get_error(ctx);
         first_error_message = ctx->get_error_message(ctx);
       }
-      ctx->log(ctx,MAPCACHE_WARN,"failed \"MULTISET\" on subcache \"%s\" for tile (z=%d,x=%d,y=%d) of tileset \"%s\"",
+      ctx->log(ctx,MAPCACHE_DEBUG,"failed \"MULTISET\" on subcache \"%s\" for tile (z=%d,x=%d,y=%d) of tileset \"%s\"",
               APR_ARRAY_IDX(cache->caches,i,mapcache_cache*)->name,tiles[0].z,tiles[0].x,tiles[0].y,tiles[0].tileset->name);
       ctx->clear_errors(ctx);
     } else {
diff --git a/lib/cache_memcache.c b/lib/cache_memcache.c
index f6d3334..a5d1a71 100644
--- a/lib/cache_memcache.c
+++ b/lib/cache_memcache.c
@@ -40,13 +40,13 @@ struct mapcache_memcache_pooled_connection {
   apr_pool_t *pool;
 };
 
-void mapcache_memcache_connection_constructor(mapcache_context *ctx, void **conn_, void *params, apr_pool_t *process_pool) {
+void mapcache_memcache_connection_constructor(mapcache_context *ctx, void **conn_, void *params) {
   struct mapcache_memcache_conn_param *param = params;
   mapcache_cache_memcache *cache = param->cache;
   struct mapcache_memcache_pooled_connection *pc;
   int i;
   pc = calloc(1,sizeof(struct mapcache_memcache_pooled_connection));
-  apr_pool_create(&pc->pool,process_pool);
+  apr_pool_create(&pc->pool,NULL);
   if(APR_SUCCESS != apr_memcache_create(pc->pool, cache->nservers, 0, &(pc->memcache))) {
     ctx->set_error(ctx,500,"cache %s: failed to create memcache backend", cache->cache.name);
     return;
@@ -65,7 +65,7 @@ void mapcache_memcache_connection_constructor(mapcache_context *ctx, void **conn
   *conn_ = pc;
 }
 
-void mapcache_memcache_connection_destructor(void *conn_, apr_pool_t *process_pool) {
+void mapcache_memcache_connection_destructor(void *conn_) {
   struct mapcache_memcache_pooled_connection *pc = conn_;
   apr_pool_destroy(pc->pool);
   free(pc);
@@ -186,7 +186,7 @@ static int _mapcache_cache_memcache_get(mapcache_context *ctx, mapcache_cache *p
     &(((char*)encoded_data->buf)[encoded_data->size-sizeof(apr_time_t)]),
     sizeof(apr_time_t));
   
-  ((char*)encoded_data->buf)[encoded_data->size+sizeof(apr_time_t)]='\0';
+  ((char*)encoded_data->buf)[encoded_data->size-sizeof(apr_time_t)]='\0';
   encoded_data->avail = encoded_data->size;
   encoded_data->size -= sizeof(apr_time_t);
   if(((char*)encoded_data->buf)[0] == '#' && encoded_data->size > 1) {
@@ -213,10 +213,11 @@ cleanup:
  */
 static void _mapcache_cache_memcache_set(mapcache_context *ctx, mapcache_cache *pcache, mapcache_tile *tile)
 {
-  char *key;
+  char *key, *data;
   int rv;
   /* set no expiration if not configured */
   int expires =0;
+  apr_time_t now;
   mapcache_buffer *encoded_data = NULL;
   mapcache_cache_memcache *cache = (mapcache_cache_memcache*)pcache;
   mapcache_pooled_connection *pc;
@@ -252,8 +253,8 @@ static void _mapcache_cache_memcache_set(mapcache_context *ctx, mapcache_cache *
 
   /* 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,encoded_data->size+sizeof(apr_time_t));
-  apr_time_t now = apr_time_now();
+  data = calloc(1,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,encoded_data->buf,encoded_data->size);
   memcpy(&(data[encoded_data->size]),&now,sizeof(apr_time_t));
diff --git a/lib/cache_multitier.c b/lib/cache_multitier.c
index 9741191..44ea853 100644
--- a/lib/cache_multitier.c
+++ b/lib/cache_multitier.c
@@ -83,7 +83,7 @@ static int _mapcache_cache_multitier_tile_get(mapcache_context *ctx, mapcache_ca
     }
     return MAPCACHE_CACHE_MISS;
   } else {
-    ctx->log(ctx,MAPCACHE_DEBUG,"got tile (%s,z=%d,y=%d,x=%d) from primary cache (%s)",tile->tileset->name, tile->z, tile->y, tile->x, subcache->name);
+    //ctx->log(ctx,MAPCACHE_DEBUG,"got tile (%s,z=%d,y=%d,x=%d) from primary cache (%s)",tile->tileset->name, tile->z, tile->y, tile->x, subcache->name);
     return ret;
   }
 }
diff --git a/lib/cache_rest.c b/lib/cache_rest.c
index cb6adfb..401fd46 100644
--- a/lib/cache_rest.c
+++ b/lib/cache_rest.c
@@ -86,7 +86,7 @@ static void _put_request(mapcache_context *ctx, CURL *curl, mapcache_buffer *buf
   response = mapcache_buffer_create(10,ctx->pool);
 
 #if LIBCURL_VERSION_NUM < 0x071700
-  /* 
+  /*
    * hack around a bug in curl <= 7.22 where the content-length is added
    * a second time even if ti was present in the manually set headers
    */
@@ -97,35 +97,35 @@ static void _put_request(mapcache_context *ctx, CURL *curl, mapcache_buffer *buf
 
   curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
 
-  /* we want to use our own read function */ 
+  /* we want to use our own read function */
   curl_easy_setopt(curl, CURLOPT_READFUNCTION, buffer_read_callback);
 
-  /* enable uploading */ 
+  /* enable uploading */
   curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
 
-  /* HTTP PUT please */ 
+  /* HTTP PUT please */
   curl_easy_setopt(curl, CURLOPT_PUT, 1L);
 
   /* specify target URL, and note that this URL should include a file
-   *        name, not only a directory */ 
+   *        name, not only a directory */
   curl_easy_setopt(curl, CURLOPT_URL, url);
 
-  /* now specify which file to upload */ 
+  /* now specify which file to upload */
   curl_easy_setopt(curl, CURLOPT_READDATA, &data);
 
   /* provide the size of the upload, we specicially typecast the value
-   *        to curl_off_t since we must be sure to use the correct data size */ 
+   *        to curl_off_t since we must be sure to use the correct data size */
   curl_easy_setopt(curl, CURLOPT_INFILESIZE, buffer->size);
-  
+
   /* send all data to this function  */
   curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, buffer_write_callback);
 
   /* we pass our mapcache_buffer struct to the callback function */
   curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)response);
 
-  /* Now run off and do what you've been told! */ 
+  /* Now run off and do what you've been told! */
   res = curl_easy_perform(curl);
-  /* Check for errors */ 
+  /* Check for errors */
   if(res != CURLE_OK) {
     ctx->set_error(ctx, 500, "curl_easy_perform() failed in rest put: %s",curl_easy_strerror(res));
   } else {
@@ -154,18 +154,18 @@ static int _head_request(mapcache_context *ctx, char *url, apr_table_t *headers)
   }
 
   _set_headers(ctx, curl, headers);
-  
+
   curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
 
   /* specify target URL, and note that this URL should include a file
-   *        name, not only a directory */ 
+   *        name, not only a directory */
   curl_easy_setopt(curl, CURLOPT_URL, url);
-  
+
   curl_easy_setopt(curl, CURLOPT_NOBODY, 1);
 
-  /* Now run off and do what you've been told! */ 
+  /* Now run off and do what you've been told! */
   res = curl_easy_perform(curl);
-  /* Check for errors */ 
+  /* Check for errors */
   if(res != CURLE_OK) {
     ctx->set_error(ctx, 500, "curl_easy_perform() failed in rest head %s",curl_easy_strerror(res));
     http_code = 500;
@@ -173,9 +173,9 @@ static int _head_request(mapcache_context *ctx, char *url, apr_table_t *headers)
     curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &http_code);
   }
 
-  /* always cleanup */ 
+  /* always cleanup */
   curl_easy_cleanup(curl);
-  
+
   return (int)http_code;
 }
 
@@ -196,14 +196,14 @@ static int _delete_request(mapcache_context *ctx, char *url, apr_table_t *header
   curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
 
   /* specify target URL, and note that this URL should include a file
-   *        name, not only a directory */ 
+   *        name, not only a directory */
   curl_easy_setopt(curl, CURLOPT_URL, url);
-  
+
   curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE");
 
-  /* Now run off and do what you've been told! */ 
+  /* Now run off and do what you've been told! */
   res = curl_easy_perform(curl);
-  /* Check for errors */ 
+  /* Check for errors */
   if(res != CURLE_OK) {
     ctx->set_error(ctx, 500, "curl_easy_perform() failed in rest head %s",curl_easy_strerror(res));
     http_code = 500;
@@ -211,9 +211,9 @@ static int _delete_request(mapcache_context *ctx, char *url, apr_table_t *header
     curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &http_code);
   }
 
-  /* always cleanup */ 
+  /* always cleanup */
   curl_easy_cleanup(curl);
-  
+
   return (int)http_code;
 }
 
@@ -243,18 +243,18 @@ static mapcache_buffer* _get_request(mapcache_context *ctx, char *url, apr_table
   curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)data);
 
   /* specify target URL, and note that this URL should include a file
-   *        name, not only a directory */ 
+   *        name, not only a directory */
   curl_easy_setopt(curl, CURLOPT_URL, url);
 
-  /* Now run off and do what you've been told! */ 
+  /* Now run off and do what you've been told! */
   res = curl_easy_perform(curl);
-  /* Check for errors */ 
+  /* Check for errors */
   if(res != CURLE_OK) {
     ctx->set_error(ctx, 500, "curl_easy_perform() failed in rest get: %s",curl_easy_strerror(res));
     data = NULL;
   } else {
     curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &http_code);
-    /* handle special behavior of s3 */ 
+    /* handle special behavior of s3 */
     if(http_code == 403) {
       char *msg = data->buf;
       while(msg && *msg) {
@@ -277,9 +277,9 @@ static mapcache_buffer* _get_request(mapcache_context *ctx, char *url, apr_table
     }
   }
 
-  /* always cleanup */ 
+  /* always cleanup */
   curl_easy_cleanup(curl);
-  
+
   return data;
 }
 
@@ -287,19 +287,21 @@ apr_table_t* _mapcache_cache_rest_headers(mapcache_context *ctx, mapcache_tile *
    mapcache_rest_operation *operation) {
   apr_table_t *ret = apr_table_make(ctx->pool,3);
   const apr_array_header_t *array;
-  
+
   if(config->common_headers) {
+	apr_table_entry_t *elts;
+	int i;
     array = apr_table_elts(config->common_headers);
-    apr_table_entry_t *elts = (apr_table_entry_t *) array->elts;
-    int i;
+    elts = (apr_table_entry_t *) array->elts;
     for (i = 0; i < array->nelts; i++) {
       apr_table_set(ret, elts[i].key,elts[i].val);
     }
   }
   if(operation->headers) {
-    array = apr_table_elts(operation->headers);
-    apr_table_entry_t *elts = (apr_table_entry_t *) array->elts;
+	apr_table_entry_t *elts;
     int i;
+    array = apr_table_elts(operation->headers);
+    elts = (apr_table_entry_t *) array->elts;
     for (i = 0; i < array->nelts; i++) {
       apr_table_set(ret, elts[i].key,elts[i].val);
     }
@@ -459,13 +461,16 @@ static void _mapcache_cache_google_headers_add(mapcache_context *ctx, const char
   const char *head;
   const apr_array_header_t *ahead;
   apr_table_entry_t *elts;
-  int i,nCanonicalHeaders=0,cnt=0;
-  assert(rcache->provider == MAPCACHE_REST_PROVIDER_GOOGLE);
-  mapcache_cache_google *google = (mapcache_cache_google*)rcache;
-  time_t now = time(NULL);
-  struct tm *tnow = gmtime(&now);
+  mapcache_cache_google *google;
+  time_t now;
+  struct tm *tnow;
   unsigned char sha[65];
   char b64[150];
+  int i,nCanonicalHeaders=0,cnt=0;
+  assert(rcache->provider == MAPCACHE_REST_PROVIDER_GOOGLE);
+  google = (mapcache_cache_google*)rcache;
+  now = time(NULL);
+  tnow = gmtime(&now);
   sha[64]=0;
 
   strftime(x_amz_date, 64 , "%a, %d %b %Y %H:%M:%S GMT", tnow);
@@ -483,7 +488,7 @@ static void _mapcache_cache_google_headers_add(mapcache_context *ctx, const char
   stringToSign=apr_pstrcat(ctx->pool, method, "\n", head, "\n", NULL);
   head = apr_table_get(headers, "Content-Type");
   if(!head) head = ""; stringToSign=apr_pstrcat(ctx->pool, stringToSign, head, "\n", NULL);
-  
+
   /* Date: header, left empty as we are using x-amz-date */
   stringToSign=apr_pstrcat(ctx->pool, stringToSign, "\n", NULL);
 
@@ -506,7 +511,7 @@ static void _mapcache_cache_google_headers_add(mapcache_context *ctx, const char
   for(i=0; i<nCanonicalHeaders; i++) {
     stringToSign = apr_pstrcat(ctx->pool, stringToSign, aheaders[i],":",apr_table_get(headers,aheaders[i]),"\n",NULL);
   }
-  
+
   /* find occurence of third "/" in url */
   while(*resource) {
     if(*resource == '/') cnt++;
@@ -533,13 +538,16 @@ static void _mapcache_cache_azure_headers_add(mapcache_context *ctx, const char*
   const char *head;
   const apr_array_header_t *ahead;
   apr_table_entry_t *elts;
-  int i,nCanonicalHeaders=0,cnt=0;
-  assert(rcache->provider == MAPCACHE_REST_PROVIDER_AZURE);
-  mapcache_cache_azure *azure = (mapcache_cache_azure*)rcache;
-  time_t now = time(NULL);
-  struct tm *tnow = gmtime(&now);
+  mapcache_cache_azure *azure;
+  time_t now;
+  struct tm *tnow;
   unsigned char sha[65];
   char *b64sign,*keyub64;
+  int i,nCanonicalHeaders=0,cnt=0;
+  assert(rcache->provider == MAPCACHE_REST_PROVIDER_AZURE);
+  azure = (mapcache_cache_azure*)rcache;
+  now = time(NULL);
+  tnow = gmtime(&now);
   sha[64]=0;
 
   strftime(x_ms_date, sizeof(x_ms_date), "%a, %d %b %Y %H:%M:%S GMT", tnow);
@@ -576,8 +584,9 @@ static void _mapcache_cache_azure_headers_add(mapcache_context *ctx, const char*
   elts = (apr_table_entry_t *) ahead->elts;
 
   for (i = 0; i < ahead->nelts; i++) {
+	char *k;
     if(strncmp(elts[i].key,"x-ms-",5) || elts[i].key[5]==0) continue;
-    char *k = aheaders[nCanonicalHeaders] = apr_pstrdup(ctx->pool, elts[i].key);
+    k = aheaders[nCanonicalHeaders] = apr_pstrdup(ctx->pool, elts[i].key);
     while(*k) {
       *k = tolower(*k);
       k++;
@@ -589,7 +598,7 @@ static void _mapcache_cache_azure_headers_add(mapcache_context *ctx, const char*
   for(i=0; i<nCanonicalHeaders; i++) {
     canonical_headers = apr_pstrcat(ctx->pool, canonical_headers, aheaders[i],":",apr_table_get(headers,aheaders[i]),"\n",NULL);
   }
-  
+
   /* find occurence of third "/" in url */
   while(*resource) {
     if(*resource == '/') cnt++;
@@ -616,7 +625,7 @@ static void _mapcache_cache_azure_headers_add(mapcache_context *ctx, const char*
 
   apr_table_set( headers, "Authorization", apr_pstrcat(ctx->pool,"SharedKey ", azure->id, ":", b64sign, NULL));
 
-  
+
 }
 static void _mapcache_cache_s3_headers_add(mapcache_context *ctx, const char* method, mapcache_cache_rest *rcache, mapcache_tile *tile, char *url, apr_table_t *headers)
 {
@@ -627,15 +636,16 @@ static void _mapcache_cache_s3_headers_add(mapcache_context *ctx, const char* me
   const apr_array_header_t *ahead;
   char *tosign, *key, *canonical_request, x_amz_date[64], *resource = url, **aheaders, *auth;
   apr_table_entry_t *elts;
+  mapcache_cache_s3 *s3;
 
   sha1[64]=sha2[64]=0;
   assert(rcache->provider == MAPCACHE_REST_PROVIDER_S3);
-  mapcache_cache_s3 *s3 = (mapcache_cache_s3*)rcache;
+  s3 = (mapcache_cache_s3*)rcache;
 
   if(!strcmp(method,"PUT")) {
     assert(tile->encoded_data);
     sha256((unsigned char*)tile->encoded_data->buf, tile->encoded_data->size, sha1);
-    sha_hex_encode(sha1,32); 
+    sha_hex_encode(sha1,32);
   } else {
     /* sha256 hash of empty string */
     memcpy(sha1,"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",64);
@@ -653,7 +663,7 @@ static void _mapcache_cache_s3_headers_add(mapcache_context *ctx, const char* me
     ctx->set_error(ctx,500,"invalid s3 url provided");
     return;
   }
-  
+
   strftime(x_amz_date, sizeof(x_amz_date), "%Y%m%dT%H%M%SZ", tnow);
   apr_table_set(headers, "x-amz-date", x_amz_date);
 
@@ -670,7 +680,7 @@ static void _mapcache_cache_s3_headers_add(mapcache_context *ctx, const char* me
       k++;
     }
   }
-  
+
   header_gnome_sort(aheaders, ahead->nelts);
   for(i=0; i<ahead->nelts; i++) {
     canonical_request = apr_pstrcat(ctx->pool, canonical_request, aheaders[i],":",apr_table_get(headers,aheaders[i]),"\n",NULL);
@@ -768,7 +778,7 @@ static int _mapcache_cache_rest_has_tile(mapcache_context *ctx, mapcache_cache *
   if(rcache->rest.has_tile.add_headers) {
     rcache->rest.has_tile.add_headers(ctx,rcache,tile,url,headers);
   }
-  
+
   status = _head_request(ctx, url, headers);
 
   if(GC_HAS_ERROR(ctx))
@@ -794,7 +804,7 @@ static void _mapcache_cache_rest_delete(mapcache_context *ctx, mapcache_cache *p
   if(rcache->rest.delete_tile.add_headers) {
     rcache->rest.delete_tile.add_headers(ctx,rcache,tile,url,headers);
   }
-  
+
   status = _delete_request(ctx, url, headers);
   GC_CHECK_ERROR(ctx);
 
@@ -851,9 +861,10 @@ static void _mapcache_cache_rest_multi_set(mapcache_context *ctx, mapcache_cache
   }
 
   for(i=0; i<ntiles; i++) {
+	mapcache_tile *tile;
     if(i)
       curl_easy_reset(curl);
-    mapcache_tile *tile = tiles + i;
+    tile = tiles + i;
     _mapcache_cache_rest_tile_url(ctx, tile, &rcache->rest, &rcache->rest.set_tile, &url);
     headers = _mapcache_cache_rest_headers(ctx, tile, &rcache->rest, &rcache->rest.set_tile);
 
@@ -889,7 +900,7 @@ static void _mapcache_cache_rest_multi_set(mapcache_context *ctx, mapcache_cache
   }
 
 multi_put_cleanup:
-  /* always cleanup */ 
+  /* always cleanup */
   curl_easy_cleanup(curl);
 
 }
@@ -969,7 +980,7 @@ static void _mapcache_cache_rest_configuration_parse_xml(mapcache_context *ctx,
 
 }
 
-static void _mapcache_cache_google_configuration_parse_xml(mapcache_context *ctx, ezxml_t node, mapcache_cache *cache, mapcache_cfg *config) 
+static void _mapcache_cache_google_configuration_parse_xml(mapcache_context *ctx, ezxml_t node, mapcache_cache *cache, mapcache_cfg *config)
 {
   ezxml_t cur_node;
   mapcache_cache_google *google = (mapcache_cache_google*)cache;
@@ -989,7 +1000,7 @@ static void _mapcache_cache_google_configuration_parse_xml(mapcache_context *ctx
   }
 }
 
-static void _mapcache_cache_s3_configuration_parse_xml(mapcache_context *ctx, ezxml_t node, mapcache_cache *cache, mapcache_cfg *config) 
+static void _mapcache_cache_s3_configuration_parse_xml(mapcache_context *ctx, ezxml_t node, mapcache_cache *cache, mapcache_cfg *config)
 {
   ezxml_t cur_node;
   mapcache_cache_s3 *s3 = (mapcache_cache_s3*)cache;
@@ -1015,7 +1026,7 @@ static void _mapcache_cache_s3_configuration_parse_xml(mapcache_context *ctx, ez
   }
 }
 
-static void _mapcache_cache_azure_configuration_parse_xml(mapcache_context *ctx, ezxml_t node, mapcache_cache *cache, mapcache_cfg *config) 
+static void _mapcache_cache_azure_configuration_parse_xml(mapcache_context *ctx, ezxml_t node, mapcache_cache *cache, mapcache_cfg *config)
 {
   ezxml_t cur_node;
   mapcache_cache_azure *azure = (mapcache_cache_azure*)cache;
diff --git a/lib/cache_riak.c b/lib/cache_riak.c
index fba4e24..4c79862 100644
--- a/lib/cache_riak.c
+++ b/lib/cache_riak.c
@@ -49,7 +49,7 @@ struct riak_conn_params {
   mapcache_cache_riak *cache;
 };
 
-void mapcache_riak_connection_constructor(mapcache_context *ctx, void **conn_, void *params, apr_pool_t *pool) {
+void mapcache_riak_connection_constructor(mapcache_context *ctx, void **conn_, void *params) {
     mapcache_cache_riak *cache = ((struct riak_conn_params*)params)->cache;
     struct RIACK_CONNECTION_OPTIONS options;
     struct RIACK_CLIENT *client = riack_new_client(0);
@@ -76,7 +76,7 @@ void mapcache_riak_connection_constructor(mapcache_context *ctx, void **conn_, v
     *conn_ = client;
 }
 
-void mapcache_riak_connection_destructor(void *conn_, apr_pool_t *process_pool) {
+void mapcache_riak_connection_destructor(void *conn_) {
     struct RIACK_CLIENT *client = (struct RIACK_CLIENT *)conn_;
     riack_free(client);
 }
@@ -280,7 +280,7 @@ static int _mapcache_cache_riak_get(mapcache_context *ctx, mapcache_cache *pcach
  * \sa mapcache_cache::tile_set()
  */
 static void _mapcache_cache_riak_set(mapcache_context *ctx, mapcache_cache *pcache, mapcache_tile *tile) {
-    char *key;
+    char *key,*content_type;
     int error;
     int connect_error = RIACK_SUCCESS;
     int retries = 3;
@@ -311,6 +311,16 @@ static void _mapcache_cache_riak_set(mapcache_context *ctx, mapcache_cache *pcac
         tile->encoded_data = tile->tileset->format->write(ctx, tile->raw_image, tile->tileset->format);
         GC_CHECK_ERROR(ctx);
     }
+    content_type = tile->tileset->format?(tile->tileset->format->mime_type?tile->tileset->format->mime_type:NULL):NULL;
+
+    if(!content_type) {
+      /* compute the content-type */
+      mapcache_image_format_type t = mapcache_imageio_header_sniff(ctx,tile->encoded_data);
+      if(t == GC_PNG)
+        content_type = "image/png";
+      else if(t == GC_JPEG)
+        content_type = "image/jpeg";
+    }
 
     pc = _riak_get_connection(ctx, cache, tile);
     GC_CHECK_ERROR(ctx);
@@ -324,8 +334,8 @@ static void _mapcache_cache_riak_set(mapcache_context *ctx, mapcache_cache *pcac
     object.vclock.len = 0;
     object.content_count = 1;
     object.content = &content;
-    content.content_type.value = tile->tileset->format->mime_type;
-    content.content_type.len = strlen(tile->tileset->format->mime_type);
+    content.content_type.value = content_type;
+    content.content_type.len = content_type?strlen(content_type):0;
     content.data = (uint8_t*)tile->encoded_data->buf;
     content.data_len = tile->encoded_data->size;
 
diff --git a/lib/cache_sqlite.c b/lib/cache_sqlite.c
index b4dd8dc..d05ae06 100644
--- a/lib/cache_sqlite.c
+++ b/lib/cache_sqlite.c
@@ -106,7 +106,7 @@ static void mapcache_sqlite_release_conn(mapcache_context *ctx, mapcache_pooled_
   mapcache_connection_pool_release_connection(ctx,conn);
 }
 
-void mapcache_sqlite_connection_constructor(mapcache_context *ctx, void **conn_, void *params, apr_pool_t *process_pool)
+void mapcache_sqlite_connection_constructor(mapcache_context *ctx, void **conn_, void *params)
 {
   int ret;
   int flags;  
@@ -117,6 +117,8 @@ void mapcache_sqlite_connection_constructor(mapcache_context *ctx, void **conn_,
     flags = SQLITE_OPEN_READONLY | SQLITE_OPEN_NOMUTEX;
   } else {
     flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_NOMUTEX | SQLITE_OPEN_CREATE;
+    mapcache_make_parent_dirs(ctx,sq_params->dbfile);
+    GC_CHECK_ERROR(ctx);
   }
   ret = sqlite3_open_v2(sq_params->dbfile, &conn->handle, flags, NULL);
   if (ret != SQLITE_OK) {
@@ -144,7 +146,7 @@ void mapcache_sqlite_connection_constructor(mapcache_context *ctx, void **conn_,
   conn->nstatements = sq_params->cache->n_prepared_statements;
 }
 
-void mapcache_sqlite_connection_destructor(void *conn_, apr_pool_t *process_pool)
+void mapcache_sqlite_connection_destructor(void *conn_)
 {
   struct sqlite_conn *conn = (struct sqlite_conn*) conn_;
   int i;
diff --git a/lib/cache_tiff.c b/lib/cache_tiff.c
index cc5bfe0..827e7b1 100644
--- a/lib/cache_tiff.c
+++ b/lib/cache_tiff.c
@@ -437,7 +437,7 @@ static int _mapcache_cache_tiff_get(mapcache_context *ctx, mapcache_cache *pcach
           memcpy(tile->encoded_data->buf,jpegtable_ptr,(jpegtable_size-2));
 
           /* advance the data pointer to after the header data */
-          bufptr = tile->encoded_data->buf + (jpegtable_size-2);
+          bufptr = ((char *)tile->encoded_data->buf) + (jpegtable_size-2);
 
 
           /* go to the specified offset in the tiff file, plus 2 bytes */
@@ -512,10 +512,8 @@ static void _mapcache_cache_tiff_set(mapcache_context *ctx, mapcache_cache *pcac
   int rv;
   void *lock;
   int create;
-  char errmsg[120];
   mapcache_cache_tiff *cache;
   mapcache_image_format_jpeg *format;
-  char *hackptr1,*hackptr2;
   int tilew;
   int tileh;
   unsigned char *rgb;
@@ -541,27 +539,8 @@ static void _mapcache_cache_tiff_set(mapcache_context *ctx, mapcache_cache *pcac
   /*
    * create the directory where the tiff file will be stored
    */
-
-  /* find the location of the last '/' in the string */
-  hackptr2 = hackptr1 = filename;
-  while(*hackptr1) {
-    if(*hackptr1 == '/')
-      hackptr2 = hackptr1;
-    hackptr1++;
-  }
-  *hackptr2 = '\0';
-
-  if(APR_SUCCESS != (rv = apr_dir_make_recursive(filename,APR_OS_DEFAULT,ctx->pool))) {
-    /*
-     * apr_dir_make_recursive sometimes sends back this error, although it should not.
-     * ignore this one
-     */
-    if(!APR_STATUS_IS_EEXIST(rv)) {
-      ctx->set_error(ctx, 500, "failed to create directory %s: %s",filename, apr_strerror(rv,errmsg,120));
-      return;
-    }
-  }
-  *hackptr2 = '/';
+  mapcache_make_parent_dirs(ctx,filename);
+  GC_CHECK_ERROR(ctx);
 
   tilew = tile->grid_link->grid->tile_sx;
   tileh = tile->grid_link->grid->tile_sy;
@@ -833,7 +812,7 @@ static void _mapcache_cache_tiff_configuration_parse_xml(mapcache_context *ctx,
   if(cur_node) {
     mapcache_config_parse_locker(ctx, cur_node, &cache->locker);
   }
-  
+
 }
 
 /**
diff --git a/lib/connection_pool.c b/lib/connection_pool.c
index 1999d8e..3bf3901 100644
--- a/lib/connection_pool.c
+++ b/lib/connection_pool.c
@@ -64,7 +64,7 @@ static apr_status_t mapcache_connection_container_destructor(void *conn_, void *
   mapcache_pooled_connection *pc = pcc->head;
   while(pc) {
     mapcache_pooled_connection *this = pc;
-    this->private->destructor(this->connection, pcc->pool);
+    this->private->destructor(this->connection);
     free(this->private->key);
     pc = this->private->next;
     free(this);
@@ -73,6 +73,7 @@ static apr_status_t mapcache_connection_container_destructor(void *conn_, void *
   return MAPCACHE_SUCCESS;
 }
 
+
 apr_status_t mapcache_connection_pool_create(mapcache_connection_pool **cp, apr_pool_t *server_pool) {
   apr_status_t rv;
   *cp = apr_pcalloc(server_pool, sizeof(mapcache_connection_pool));
@@ -126,7 +127,7 @@ mapcache_pooled_connection* mapcache_connection_pool_get_connection(mapcache_con
   /*
   ctx->log(ctx, MAPCACHE_DEBUG, "calling constructor for pooled connection (%s)", key);
   */
-  constructor(ctx, &pc->connection, params, pcc->pool);
+  constructor(ctx, &pc->connection, params);
   if(GC_HAS_ERROR(ctx)) {
     free(pc);
     apr_reslist_release(ctx->connection_pool->connexions, pcc);
@@ -150,7 +151,7 @@ mapcache_pooled_connection* mapcache_connection_pool_get_connection(mapcache_con
       count++;
     }
     ctx->log(ctx, MAPCACHE_DEBUG, "tearing down pooled connection (%s) to make room", opc->private->key);
-    opc->private->destructor(opc->connection, pcc->pool);
+    opc->private->destructor(opc->connection);
     free(opc->private->key);
     free(opc->private);
     free(opc);
@@ -172,7 +173,7 @@ void mapcache_connection_pool_invalidate_connection(mapcache_context *ctx, mapca
       } else {
         pcc->head = pc->private->next;
       }
-      pc->private->destructor(pc->connection, pcc->pool);
+      pc->private->destructor(pc->connection);
       free(pc->private->key);
       free(pc);
     }
diff --git a/lib/core.c b/lib/core.c
index de2befd..63f4244 100644
--- a/lib/core.c
+++ b/lib/core.c
@@ -196,10 +196,13 @@ mapcache_http_response *mapcache_core_get_tile(mapcache_context *ctx, mapcache_r
 {
   int expires = 0;
   mapcache_http_response *response;
-  int i,is_empty=1; /* response image is initially empty */;
   char *timestr;
-  mapcache_image *base=NULL;
-  mapcache_image_format *format = NULL;
+  mapcache_image *base;
+  mapcache_image_format *format;
+  mapcache_image_format_type t;
+  int i,is_empty=1; /* response image is initially empty */;
+  base=NULL;
+  format = NULL;
 
 #ifdef DEBUG
   if(req_tile->ntiles ==0) {
@@ -208,7 +211,7 @@ mapcache_http_response *mapcache_core_get_tile(mapcache_context *ctx, mapcache_r
   }
 #endif
   response = mapcache_http_response_create(ctx->pool);
-  
+
   if(ctx->supports_redirects && req_tile->ntiles == 1) {
     req_tile->tiles[0]->allow_redirect = 1;
   }
@@ -233,7 +236,7 @@ mapcache_http_response *mapcache_core_get_tile(mapcache_context *ctx, mapcache_r
     if(tile->expires && (tile->expires < expires || expires == 0)) {
       expires = tile->expires;
     }
-    
+
     if(tile->nodata) {
       /* treat the special case where the cache explicitely stated that the
        tile was empty, and we don't have any vertical merging to do */
@@ -244,8 +247,8 @@ mapcache_http_response *mapcache_core_get_tile(mapcache_context *ctx, mapcache_r
       }
       continue;
     }
-    
-    /* treat the most common case: 
+
+    /* treat the most common case:
      - we have a single tile request (i.e. isempty is true)
      - the cache returned the encoded image
      */
@@ -282,7 +285,7 @@ mapcache_http_response *mapcache_core_get_tile(mapcache_context *ctx, mapcache_r
       mapcache_image_merge(ctx, base, tile->raw_image);
     } else {
       /* we don't need to merge onto an existing tile and don't have access to the tile's encoded data.
-       * 
+       *
        * we don't encode the tile's raw image data just yet because we might need to merge another one on top
        * of it later.
        */
@@ -307,20 +310,20 @@ mapcache_http_response *mapcache_core_get_tile(mapcache_context *ctx, mapcache_r
         return NULL;
       }
     } else {
+      unsigned char empty[5] = {'#',0,0,0,0};
 #ifdef DEBUG
       if(!is_empty) {
         ctx->set_error(ctx,500,"BUG: no image data to encode, but tile not marked as empty");
         return NULL;
       }
 #endif
-      unsigned char empty[5] = {'#',0,0,0,0};
       response->data = mapcache_empty_png_decode(ctx,req_tile->tiles[0]->grid_link->grid->tile_sx, req_tile->tiles[0]->grid_link->grid->tile_sy, empty,&is_empty); /* is_empty is unchanged and left to 1 */
       format = mapcache_configuration_get_image_format(ctx->config,"PNG8");
     }
   }
-  
+
   /* compute the content-type */
-  mapcache_image_format_type t = mapcache_imageio_header_sniff(ctx,response->data);
+  t = mapcache_imageio_header_sniff(ctx,response->data);
   if(t == GC_PNG)
     apr_table_set(response->headers,"Content-Type","image/png");
   else if(t == GC_JPEG)
@@ -345,12 +348,13 @@ mapcache_map* mapcache_assemble_maps(mapcache_context *ctx, mapcache_map **maps,
   mapcache_tile ***maptiles;
   int *nmaptiles;
   mapcache_tile **tiles;
+  mapcache_grid_link **effectively_used_grid_links;
   mapcache_map *basemap = NULL;
   int ntiles = 0;
   int i;
   maptiles = apr_pcalloc(ctx->pool,nmaps*sizeof(mapcache_tile**));
   nmaptiles = apr_pcalloc(ctx->pool,nmaps*sizeof(int));
-  mapcache_grid_link **effectively_used_grid_links = apr_pcalloc(ctx->pool,nmaps*sizeof(mapcache_grid_link*));
+  effectively_used_grid_links = apr_pcalloc(ctx->pool,nmaps*sizeof(mapcache_grid_link*));
   for(i=0; i<nmaps; i++) {
     mapcache_tileset_get_map_tiles(ctx,maps[i]->tileset,maps[i]->grid_link,
                                    &maps[i]->extent, maps[i]->width, maps[i]->height,
diff --git a/lib/dimension.c b/lib/dimension.c
index 037aab3..cde7db6 100644
--- a/lib/dimension.c
+++ b/lib/dimension.c
@@ -38,7 +38,24 @@
 #include <float.h>
 #endif
 
+#ifndef HAVE_TIMEGM
+time_t timegm(struct tm *tm)
+{
+  time_t t, tdiff;
+  struct tm in, gtime, ltime;
+
+  memcpy(&in, tm, sizeof(in));
+  t = mktime(&in);
+
+  memcpy(&gtime, gmtime(&t), sizeof(gtime));
+  memcpy(&ltime, localtime(&t), sizeof(ltime));
+  gtime.tm_isdst = ltime.tm_isdst;
+  tdiff = t - mktime(&gtime);
 
+  memcpy(&in, tm, sizeof(in));
+  return mktime(&in) + tdiff;
+}
+#endif
 
 static int _mapcache_dimension_intervals_validate(mapcache_context *ctx, mapcache_dimension *dim, char **value)
 {
@@ -307,16 +324,16 @@ struct sqlite_dimension_conn {
   int n_statements;
 };
 
-void mapcache_sqlite_dimension_connection_constructor(mapcache_context *ctx, void **conn_, void *params, apr_pool_t *pool)
+void mapcache_sqlite_dimension_connection_constructor(mapcache_context *ctx, void **conn_, void *params)
 {
   int ret;
-  int flags;  
+  int flags;
   char *dbfile = (char*) params;
   struct sqlite_dimension_conn *conn = calloc(1, sizeof (struct sqlite_dimension_conn));
   *conn_ = conn;
   flags = SQLITE_OPEN_READONLY | SQLITE_OPEN_NOMUTEX;
   ret = sqlite3_open_v2(dbfile, &conn->handle, flags, NULL);
-  
+
   if (ret != SQLITE_OK) {
     ctx->set_error(ctx,500,"failed to open sqlite dimension dbfile (%s): %s",dbfile,sqlite3_errmsg(conn->handle));
     sqlite3_close(conn->handle);
@@ -326,7 +343,7 @@ void mapcache_sqlite_dimension_connection_constructor(mapcache_context *ctx, voi
   sqlite3_busy_timeout(conn->handle, 300000);
 }
 
-void mapcache_sqlite_dimension_connection_destructor(void *conn_, apr_pool_t *pool)
+void mapcache_sqlite_dimension_connection_destructor(void *conn_)
 {
   struct sqlite_dimension_conn *conn = (struct sqlite_dimension_conn*) conn_;
   while(conn->n_statements) {
@@ -385,7 +402,7 @@ static int _mapcache_dimension_sqlite_validate(mapcache_context *ctx, mapcache_d
       goto cleanup;
     }
   }
-  
+
   paramidx = sqlite3_bind_parameter_index(conn->prepared_statements[0], ":dim");
   if (paramidx) {
     sqliteret = sqlite3_bind_text(conn->prepared_statements[0], paramidx, *value, -1, SQLITE_STATIC);
@@ -414,7 +431,7 @@ cleanup:
     sqlite3_reset(conn->prepared_statements[0]);
   }
   _sqlite_dimension_release_conn(ctx,pc);
-      
+
   return ret;
 }
 
@@ -434,7 +451,7 @@ static apr_array_header_t* _mapcache_dimension_sqlite_print(mapcache_context *ct
     conn->prepared_statements = calloc(2,sizeof(sqlite3_stmt*));
     conn->n_statements = 2;
   }
- 
+
   if(!conn->prepared_statements[1]) {
     sqliteret = sqlite3_prepare_v2(conn->handle, dimension->list_query, -1, &conn->prepared_statements[1], NULL);
     if(sqliteret != SQLITE_OK) {
@@ -459,7 +476,7 @@ cleanup:
     sqlite3_reset(conn->prepared_statements[1]);
   }
   _sqlite_dimension_release_conn(ctx,pc);
-      
+
   return ret;
 }
 
@@ -469,7 +486,7 @@ static void _mapcache_dimension_sqlite_parse_xml(mapcache_context *ctx, mapcache
 {
   mapcache_dimension_sqlite *dimension;
   ezxml_t child;
-  
+
   dimension = (mapcache_dimension_sqlite*)dim;
 
   child = ezxml_child(node,"dbfile");
@@ -493,7 +510,7 @@ static void _mapcache_dimension_sqlite_parse_xml(mapcache_context *ctx, mapcache
     ctx->set_error(ctx,400,"sqlite dimension \"%s\" has no <list_query> node", dim->name);
     return;
   }
-  
+
 }
 
 
@@ -554,7 +571,7 @@ static void _bind_sqlite_timedimension_params(mapcache_context *ctx, sqlite3_stm
       return;
     }
   }
-  
+
   paramidx = sqlite3_bind_parameter_index(stmt, ":start_timestamp");
   if (paramidx) {
     ret = sqlite3_bind_int64(stmt, paramidx, start);
@@ -598,13 +615,13 @@ apr_array_header_t *_mapcache_timedimension_sqlite_get_entries(mapcache_context
       return NULL;
     }
   }
-  
+
   _bind_sqlite_timedimension_params(ctx,conn->prepared_statements[0],conn->handle,tileset,grid,extent,start,end);
   if(GC_HAS_ERROR(ctx)) {
     _sqlite_dimension_release_conn(ctx, pc);
     return NULL;
   }
-  
+
   time_ids = apr_array_make(ctx->pool,0,sizeof(char*));
   do {
     ret = sqlite3_step(conn->prepared_statements[0]);
@@ -643,7 +660,7 @@ typedef enum {
 void _mapcache_timedimension_sqlite_parse_xml(mapcache_context *ctx, mapcache_timedimension *dim, ezxml_t node) {
   mapcache_timedimension_sqlite *sdim = (mapcache_timedimension_sqlite*)dim;
   ezxml_t child;
-  
+
   child = ezxml_child(node,"dbfile");
   if(child && child->txt && *child->txt) {
     sdim->dbfile = apr_pstrdup(ctx->pool,child->txt);
@@ -662,8 +679,8 @@ void _mapcache_timedimension_sqlite_parse_xml(mapcache_context *ctx, mapcache_ti
 #endif
 
 char *mapcache_ogc_strptime(const char *value, struct tm *ts, mapcache_time_interval_t *ti) {
-  memset (ts, '\0', sizeof (*ts));
   char *valueptr;
+  memset (ts, '\0', sizeof (*ts));
   valueptr = strptime(value,"%Y-%m-%dT%H:%M:%SZ",ts);
   *ti = MAPCACHE_TINTERVAL_SECOND;
   if(valueptr) return valueptr;
@@ -700,7 +717,7 @@ apr_array_header_t* mapcache_timedimension_get_entries_for_value(mapcache_contex
     ctx->set_error(ctx,400,"failed to parse time %s",value);
     return NULL;
   }
-  
+
   if(*valueptr == '/' || (*valueptr == '-' && *(valueptr+1) == '-')) {
     /* we have a second (end) time */
     if (*valueptr == '/') {
diff --git a/lib/ezxml.c b/lib/ezxml.c
index dd9470f..2b1558e 100644
--- a/lib/ezxml.c
+++ b/lib/ezxml.c
@@ -370,7 +370,7 @@ short ezxml_internal_dtd(ezxml_root_t root, char *s, size_t len)
       else *s = '\0'; // null terminate tag name
       for (i = 0; root->attr[i] && strcmp(n, root->attr[i][0]); i++);
 
-      while (*(n = ++s + strspn(s, EZXML_WS)) && *n != '>') {
+      while (*(n = s + 1 + strspn(s + 1, EZXML_WS)) && *n != '>') {
         if (*(s = n + strcspn(n, EZXML_WS))) *s = '\0'; // attr name
         else {
           ezxml_err(root, t, "malformed <!ATTLIST");
diff --git a/lib/http.c b/lib/http.c
index dd24965..e4aad04 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -105,6 +105,7 @@ void mapcache_http_do_request(mapcache_context *ctx, mapcache_http *req, mapcach
   char error_msg[CURL_ERROR_SIZE];
   int ret;
   struct curl_slist *curl_headers=NULL;
+  struct _header_struct h;
   curl_handle = curl_easy_init();
 
 
@@ -121,7 +122,6 @@ void mapcache_http_do_request(mapcache_context *ctx, mapcache_http *req, mapcach
 
   if(headers != NULL) {
     /* intercept headers */
-    struct _header_struct h;
     h.headers = headers;
     h.ctx=ctx;
     curl_easy_setopt(curl_handle, CURLOPT_HEADERFUNCTION, _mapcache_curl_header_callback);
@@ -142,7 +142,7 @@ void mapcache_http_do_request(mapcache_context *ctx, mapcache_http *req, mapcach
     int i;
     for (i = 0; i < array->nelts; i++) {
       char *val = elts[i].val;
-      if(strchr(val,'{') && ctx->headers_in) {
+      if(val && strchr(val,'{') && ctx->headers_in) {
         _header_replace_str(ctx,ctx->headers_in,&val);
       }
       curl_headers = curl_slist_append(curl_headers, apr_pstrcat(ctx->pool,elts[i].key,": ",val,NULL));
diff --git a/lib/image.c b/lib/image.c
index 4d228b5..4dd11d1 100644
--- a/lib/image.c
+++ b/lib/image.c
@@ -85,6 +85,9 @@ int mapcache_image_has_alpha(mapcache_image *img)
 void mapcache_image_merge(mapcache_context *ctx, mapcache_image *base, mapcache_image *overlay)
 {
   int starti,startj;
+  pixman_image_t *si;
+  pixman_image_t *bi;
+  pixman_transform_t transform;
 #ifndef USE_PIXMAN
   int i,j;
   unsigned char *browptr, *orowptr, *bptr, *optr;
@@ -97,11 +100,10 @@ void mapcache_image_merge(mapcache_context *ctx, mapcache_image *base, mapcache_
   starti = (base->h - overlay->h)/2;
   startj = (base->w - overlay->w)/2;
 #ifdef USE_PIXMAN
-  pixman_image_t *si = pixman_image_create_bits(PIXMAN_a8r8g8b8,overlay->w,overlay->h,
+  si = pixman_image_create_bits(PIXMAN_a8r8g8b8,overlay->w,overlay->h,
                        (uint32_t*)overlay->data,overlay->stride);
-  pixman_image_t *bi = pixman_image_create_bits(PIXMAN_a8r8g8b8,base->w,base->h,
+  bi = pixman_image_create_bits(PIXMAN_a8r8g8b8,base->w,base->h,
                        (uint32_t*)base->data,base->stride);
-  pixman_transform_t transform;
   pixman_transform_init_translate(&transform,
                                   pixman_int_to_fixed(-startj),
                                   pixman_int_to_fixed(-starti));
diff --git a/lib/imageio_png.c b/lib/imageio_png.c
index 2b5de6d..fbd32a5 100644
--- a/lib/imageio_png.c
+++ b/lib/imageio_png.c
@@ -324,14 +324,10 @@ void _mapcache_imageio_png_flush_func(png_structp png_ptr)
   // do nothing
 }
 
-#ifndef _WIN32
-static inline int premultiply (int color,int alpha)
-#else
-static __inline int premultiply (int color,int alpha)
-#endif
-{
-  int temp = (alpha * color) + 0x80;
-  return ((temp + (temp >> 8)) >> 8);
+#define PREMULTIPLY(out,color,alpha)\
+{\
+  int temp = ((alpha) * (color)) + 0x80;\
+  out =((temp + (temp >> 8)) >> 8);\
 }
 
 
@@ -425,9 +421,9 @@ void _mapcache_imageio_png_decode_to_image(mapcache_context *ctx, mapcache_buffe
         pixptr[1] = 0;
         pixptr[2] = 0;
       } else {
-        pixptr[0] = premultiply(pixel[2],alpha);
-        pixptr[1] = premultiply(pixel[1],alpha);
-        pixptr[2] = premultiply(pixel[0],alpha);
+        PREMULTIPLY(pixptr[0],pixel[2],alpha);
+        PREMULTIPLY(pixptr[1],pixel[1],alpha);
+        PREMULTIPLY(pixptr[2],pixel[0],alpha);
       }
       pixptr += 4;
     }
diff --git a/lib/lock.c b/lib/lock.c
index 2cef016..3275d50 100644
--- a/lib/lock.c
+++ b/lib/lock.c
@@ -31,7 +31,9 @@
 #include <apr_file_io.h>
 #include <apr_strings.h>
 #include <apr_time.h>
+#ifndef _WIN32
 #include <unistd.h>
+#endif
 
 #define MAPCACHE_LOCKFILE_PREFIX "_gc_lock"
 
@@ -60,7 +62,7 @@ int mapcache_lock_or_wait_for_resource(mapcache_context *ctx, mapcache_locker *l
   else {
     apr_time_t start_wait = apr_time_now();
     rv = MAPCACHE_LOCK_LOCKED;
-    
+
     while(rv != MAPCACHE_LOCK_NOENT) {
       unsigned int waited = apr_time_as_msec(apr_time_now()-start_wait);
       if(waited > locker->timeout*1000) {
@@ -81,7 +83,7 @@ mapcache_lock_result mapcache_locker_disk_aquire_lock(mapcache_context *ctx, map
   mapcache_locker_disk *ldisk;
   apr_file_t *lockfile;
   apr_status_t rv;
-  
+
   assert(self->type == MAPCACHE_LOCKER_DISK);
   ldisk = (mapcache_locker_disk*)self;
   *lock = NULL; /*unused*/
@@ -188,6 +190,11 @@ mapcache_lock_result mapcache_locker_fallback_aquire_lock(mapcache_context *ctx,
       fallback_lock->locker = child_locker;
       ctx->push_errors(ctx,error);
       return lock_result;
+    } else {
+      /*clear the current error if we still have a fallback lock to try */
+      if(i<locker->lockers->nelts-1) {
+        ctx->clear_errors(ctx);
+      }
     }
     ctx->push_errors(ctx,error);
   }
@@ -245,7 +252,7 @@ static char* memcache_key_for_resource(mapcache_context *ctx, mapcache_locker_me
   char *saferes = apr_pstrdup(ctx->pool,resource);
   char *safeptr = saferes;
   while(*safeptr) {
-    if(*safeptr==' ' || *safeptr == '/' || *safeptr == '~' || *safeptr == '.' || 
+    if(*safeptr==' ' || *safeptr == '/' || *safeptr == '~' || *safeptr == '.' ||
         *safeptr == '\r' || *safeptr == '\n' || *safeptr == '\t' || *safeptr == '\f' || *safeptr == '\e' || *safeptr == '\a' || *safeptr == '\b') {
       *safeptr = '#';
     }
@@ -287,7 +294,7 @@ mapcache_lock_result mapcache_locker_memcache_ping_lock(mapcache_context *ctx, m
   size_t ione;
   mapcache_locker_memcache *lm = (mapcache_locker_memcache*)self;
   char *key = memcache_key_for_resource(ctx, lm, resource);
-  apr_memcache_t *memcache = (apr_memcache_t*)lock;  
+  apr_memcache_t *memcache = (apr_memcache_t*)lock;
   if(!memcache)
     return MAPCACHE_LOCK_NOENT;
   rv = apr_memcache_getp(memcache,ctx->pool,key,&one,&ione,NULL);
@@ -296,14 +303,14 @@ mapcache_lock_result mapcache_locker_memcache_ping_lock(mapcache_context *ctx, m
   else
     return MAPCACHE_LOCK_NOENT;
 }
-  
+
 
 mapcache_lock_result mapcache_locker_memcache_aquire_lock(mapcache_context *ctx, mapcache_locker *self, char *resource, void **lock) {
   apr_status_t rv;
   mapcache_locker_memcache *lm = (mapcache_locker_memcache*)self;
   char errmsg[120];
   char *key = memcache_key_for_resource(ctx, lm, resource);
-  apr_memcache_t *memcache = create_memcache(ctx,lm);  
+  apr_memcache_t *memcache = create_memcache(ctx,lm);
   if(GC_HAS_ERROR(ctx)) {
     return MAPCACHE_LOCK_NOENT;
   }
@@ -324,12 +331,12 @@ void mapcache_locker_memcache_release_lock(mapcache_context *ctx, mapcache_locke
   mapcache_locker_memcache *lm = (mapcache_locker_memcache*)self;
   char errmsg[120];
   char *key = memcache_key_for_resource(ctx, lm, resource);
-  apr_memcache_t *memcache = (apr_memcache_t*)lock;  
+  apr_memcache_t *memcache = (apr_memcache_t*)lock;
   if(!memcache) {
     /*error*/
     return;
   }
-  
+
   rv = apr_memcache_delete(memcache,key,0);
   if(rv != APR_SUCCESS && rv!= APR_NOTFOUND) {
     ctx->set_error(ctx,500,"memcache: failed to delete key %s: %s", key, apr_strerror(rv,errmsg,120));
@@ -383,7 +390,7 @@ void mapcache_config_parse_locker(mapcache_context *ctx, ezxml_t node, mapcache_
     return;
   }
   (*locker)->parse_xml(ctx, *locker, node);
-  
+
   if((cur_node = ezxml_child(node,"retry")) != NULL) {
     char *endptr;
     (*locker)->retry_interval = strtod(cur_node->txt,&endptr);
diff --git a/lib/service_demo.c b/lib/service_demo.c
index 716b26c..c6512a5 100644
--- a/lib/service_demo.c
+++ b/lib/service_demo.c
@@ -553,10 +553,13 @@ void _create_demo_wms(mapcache_context *ctx, mapcache_request_get_capabilities *
         apr_array_header_t *timedimvals = tileset->timedimension->get_all_entries(
                 ctx,tileset->timedimension,tileset);
         for(id=0;id<timedimvals->nelts;id++) {
+	      char *idval;
+	      char *dimparam_wms;
+	      char *dimparam_singletile;
           if(id>1) break;
-          char *idval = APR_ARRAY_IDX(timedimvals,id,char*);
-          char *dimparam_wms = "    %s_wms_layer.mergeNewParams({%s:\"%s\"});\n";
-          char *dimparam_singletile = "    %s_slayer.mergeNewParams({%s:\"%s\"});\n";
+          idval = APR_ARRAY_IDX(timedimvals,id,char*);
+          dimparam_wms = "    %s_wms_layer.mergeNewParams({%s:\"%s\"});\n";
+          dimparam_singletile = "    %s_slayer.mergeNewParams({%s:\"%s\"});\n";
           ol_layer_name = apr_psprintf(ctx->pool, "%s_%s_%s", tileset->name, grid->name, idval);
           /* normalize name to something that is a valid variable name */
           for(i=0; i<strlen(ol_layer_name); i++)
@@ -581,7 +584,7 @@ void _create_demo_wms(mapcache_context *ctx, mapcache_request_get_capabilities *
           caps = apr_psprintf(ctx->pool,"%s%s",caps,ol_layer);
           caps = apr_psprintf(ctx->pool,"%s%s",caps,
                   apr_psprintf(ctx->pool,dimparam_wms,ol_layer_name,tileset->timedimension->key,idval));
-            
+
           if(service->getmap_strategy == MAPCACHE_GETMAP_ASSEMBLE) {
             ol_layer = apr_psprintf(ctx->pool, demo_layer_singletile,
                                     ol_layer_name,
@@ -660,15 +663,11 @@ void _create_demo_mapguide(mapcache_context *ctx, mapcache_request_get_capabilit
   tileindex_index = apr_hash_first(ctx->pool,ctx->config->tilesets);
   while(tileindex_index) {
     int i,j;
-    char *extension;
     mapcache_tileset *tileset;
     const void *key;
     apr_ssize_t keylen;
     apr_hash_this(tileindex_index,&key,&keylen,(void**)&tileset);
 
-    extension = "png";
-    if (tileset->format && tileset->format->extension)
-      extension = tileset->format->extension;
     for(j=0; j<tileset->grid_links->nelts; j++) {
       char *resolutions="";
       char *unit="dd";
@@ -873,9 +872,11 @@ void _create_demo_wmts(mapcache_context *ctx, mapcache_request_get_capabilities
                 ctx,tileset->timedimension,tileset);
         GC_CHECK_ERROR(ctx);
         for(id=0;id<timedimvals->nelts;id++) {
+          char *idval;
+          char *dimparam;
           if(id>1) break; /* we don't want all the entries in the demo interface */
-          char *idval = APR_ARRAY_IDX(timedimvals,id,char*);
-          char *dimparam = "%s_wmts_layer.mergeNewParams({%s:\"%s\"});\n";
+          idval = APR_ARRAY_IDX(timedimvals,id,char*);
+          dimparam = "%s_wmts_layer.mergeNewParams({%s:\"%s\"});\n";
           ol_layer_name = apr_psprintf(ctx->pool, "%s_%s_%s", tileset->name, grid->name, idval);
           /* normalize name to something that is a valid variable name */
           for(i=0; i<strlen(ol_layer_name); i++)
@@ -903,7 +904,7 @@ void _create_demo_wmts(mapcache_context *ctx, mapcache_request_get_capabilities
           caps = apr_psprintf(ctx->pool,"%s%s",caps,ol_layer);
           caps = apr_psprintf(ctx->pool,"%s%s",caps,
                   apr_psprintf(ctx->pool,dimparam,ol_layer_name,tileset->timedimension->key,idval));
-            
+
         }
       }
     }
diff --git a/lib/service_wms.c b/lib/service_wms.c
index 1fc643e..6e6c34f 100644
--- a/lib/service_wms.c
+++ b/lib/service_wms.c
@@ -200,7 +200,7 @@ void _create_capabilities_wms(mapcache_context *ctx, mapcache_request_get_capabi
     layerxml = ezxml_add_child(toplayer,"Layer",0);
     ezxml_set_attr(layerxml, "cascaded", "1");
     ezxml_set_attr(layerxml, "queryable", (tileset->source && tileset->source->info_formats)?"1":"0");
-    
+
     ezxml_set_txt(ezxml_add_child(layerxml,"Name",0),tileset->name);
     tsxml = ezxml_add_child(vendorxml, "TileSet",0);
 
@@ -715,9 +715,9 @@ void _mapcache_service_wms_parse_request(mapcache_context *ctx, mapcache_service
             /* we need to create more tile/map entries */
               if(timedim_selected->nelts > 1) {
                 /* apr pools have no realloc */
+                mapcache_tile** tmptiles;
                 nallocated = nallocated + timedim_selected->nelts - 1;
-                mapcache_tile** tmptiles =
-                        apr_palloc(ctx->pool, nallocated * sizeof(mapcache_tile*));
+                tmptiles = apr_palloc(ctx->pool, nallocated * sizeof(mapcache_tile*));
                 for(i=0;i<tile_req->ntiles;i++) {
                   tmptiles[i] = tile_req->tiles[i];
                 }
@@ -738,9 +738,9 @@ void _mapcache_service_wms_parse_request(mapcache_context *ctx, mapcache_service
             /* we need to create more tile/map entries */
               if(timedim_selected->nelts > 1) {
                 /* apr pools have no realloc */
+                mapcache_map** tmpmaps;
                 nallocated = nallocated + timedim_selected->nelts - 1;
-                mapcache_map** tmpmaps =
-                        apr_palloc(ctx->pool, nallocated * sizeof(mapcache_map*));
+                tmpmaps = apr_palloc(ctx->pool, nallocated * sizeof(mapcache_map*));
                 for(i=0;i<map_req->nmaps;i++) {
                   tmpmaps[i] = map_req->maps[i];
                 }
@@ -756,7 +756,7 @@ void _mapcache_service_wms_parse_request(mapcache_context *ctx, mapcache_service
                 apr_table_set(map_req->maps[map_req->nmaps-1]->dimensions,tileset->timedimension->key,
                         APR_ARRAY_IDX(timedim_selected,i,char*));
               }
-              
+
             }
           }
         }
@@ -965,7 +965,7 @@ void _configuration_parse_wms_xml(mapcache_context *ctx, ezxml_t node, mapcache_
     rule = apr_pcalloc(ctx->pool, sizeof(mapcache_forwarding_rule));
     rule->name = apr_pstrdup(ctx->pool,name);
     rule->match_params = apr_array_make(ctx->pool,1,sizeof(mapcache_dimension*));
-    rule->max_post_len = 10485760; /* 10 megabytes by default */ 
+    rule->max_post_len = 10485760; /* 10 megabytes by default */
 
     node = ezxml_child(rule_node,"append_pathinfo");
     if(node && !strcasecmp(node->txt,"true")) {
@@ -973,7 +973,7 @@ void _configuration_parse_wms_xml(mapcache_context *ctx, ezxml_t node, mapcache_
     } else {
       rule->append_pathinfo = 0;
     }
-    
+
     node = ezxml_child(rule_node,"max_post_length");
     if(node) {
       char *endptr;
@@ -983,7 +983,7 @@ void _configuration_parse_wms_xml(mapcache_context *ctx, ezxml_t node, mapcache_
         return;
       }
     }
-    
+
     node = ezxml_child(rule_node,"http");
     if(!node) {
       ctx->set_error(ctx,500,"rule \"%s\" does not contain an <http> block",name);
diff --git a/lib/service_wmts.c b/lib/service_wmts.c
index 541f9fb..569bbc7 100644
--- a/lib/service_wmts.c
+++ b/lib/service_wmts.c
@@ -414,16 +414,17 @@ void _create_capabilities_wmts(mapcache_context *ctx, mapcache_request_get_capab
         int j;
         for(j=0; j<grid_link->grid->nlevels; j++) {
           ezxml_t matrixlimits = ezxml_add_child(limits,"TileMatrixLimits",0);
+          int row;
           ezxml_set_txt(ezxml_add_child(matrixlimits,"TileMatrix",0),
                         apr_psprintf(ctx->pool,"%s:%d",grid_link->grid->name,j));
           ezxml_set_txt(ezxml_add_child(matrixlimits,"MinTileRow",0),
-                        apr_psprintf(ctx->pool,"%d",grid_link->grid_limits[j].minx));
+                        apr_psprintf(ctx->pool,"%d",grid_link->grid_limits[j].miny));
           ezxml_set_txt(ezxml_add_child(matrixlimits,"MaxTileRow",0),
-                        apr_psprintf(ctx->pool,"%d",grid_link->grid_limits[j].maxx-1));
+                        apr_psprintf(ctx->pool,"%d",grid_link->grid_limits[j].maxy-1));
           ezxml_set_txt(ezxml_add_child(matrixlimits,"MinTileCol",0),
-                        apr_psprintf(ctx->pool,"%d",grid_link->grid_limits[j].miny));
+                        apr_psprintf(ctx->pool,"%d",grid_link->grid_limits[j].minx));
           ezxml_set_txt(ezxml_add_child(matrixlimits,"MaxTileCol",0),
-                        apr_psprintf(ctx->pool,"%d",grid_link->grid_limits[j].maxy-1));
+                        apr_psprintf(ctx->pool,"%d",grid_link->grid_limits[j].maxx-1));
         }
       }
 
diff --git a/lib/strptime.c b/lib/strptime.c
index ff52ef1..992d1cb 100644
--- a/lib/strptime.c
+++ b/lib/strptime.c
@@ -40,7 +40,6 @@
 #include <time.h>
 #include "util.h"
 
-
 static const char *abb_weekdays[] = {
   "Sun",
   "Mon",
diff --git a/lib/tileset.c b/lib/tileset.c
index 8677d48..df81b75 100644
--- a/lib/tileset.c
+++ b/lib/tileset.c
@@ -406,7 +406,7 @@ mapcache_metatile* mapcache_tileset_metatile_get(mapcache_context *ctx, mapcache
   /* configured metatile size in geographical units */
   fullgwidth = res * tileset->metasize_x * grid->tile_sx;
   fullgheight = res * tileset->metasize_y * grid->tile_sy;
-  
+
   switch(grid->origin) {
     case MAPCACHE_GRID_ORIGIN_BOTTOM_LEFT:
       mt->map.extent.minx = grid->extent.minx + mt->x * fullgwidth - gbuffer;
@@ -618,20 +618,21 @@ mapcache_feature_info* mapcache_tileset_feature_info_create(apr_pool_t *pool, ma
 }
 
 void mapcache_tileset_assemble_out_of_zoom_tile(mapcache_context *ctx, mapcache_tile *tile) {
-  assert(tile->grid_link->outofzoom_strategy == MAPCACHE_OUTOFZOOM_REASSEMBLE);
-
-  /* we have at most 4 tiles composing the requested tile */
   mapcache_extent tile_bbox;
   double shrink_x, shrink_y, scalefactor;
   int x[4],y[4];
   int i, n=1;
+  mapcache_tile *childtile;
+  assert(tile->grid_link->outofzoom_strategy == MAPCACHE_OUTOFZOOM_REASSEMBLE);
+
+  /* we have at most 4 tiles composing the requested tile */
   mapcache_grid_get_extent(ctx,tile->grid_link->grid,tile->x,tile->y,tile->z, &tile_bbox);
 
   /*
    shrink the extent so we do not fall exactly on a tile boundary, to avoid rounding
    errors when computing the x,y of the lower level tile(s) we will need
   */
-  
+
   shrink_x = (tile_bbox.maxx - tile_bbox.minx) / (tile->grid_link->grid->tile_sx * 1000); /* 1/1000th of a pixel */
   shrink_y = (tile_bbox.maxy - tile_bbox.miny) / (tile->grid_link->grid->tile_sy * 1000); /* 1/1000th of a pixel */
   tile_bbox.maxx -= shrink_x;
@@ -656,15 +657,15 @@ void mapcache_tileset_assemble_out_of_zoom_tile(mapcache_context *ctx, mapcache_
   tile_bbox.minx -= shrink_x;
   tile_bbox.miny -= shrink_y;
 
-  mapcache_tile *childtile = mapcache_tileset_tile_clone(ctx->pool,tile);
+  childtile = mapcache_tileset_tile_clone(ctx->pool,tile);
   childtile->z = tile->grid_link->max_cached_zoom;
   scalefactor = childtile->grid_link->grid->levels[childtile->z]->resolution/tile->grid_link->grid->levels[tile->z]->resolution;
   tile->nodata = 1;
   for(i=0;i<n;i++) {
-    childtile->x = x[i];
-    childtile->y = y[i];
     mapcache_extent childtile_bbox;
     double dstminx,dstminy;
+    childtile->x = x[i];
+    childtile->y = y[i];
     mapcache_tileset_tile_get(ctx,childtile);
     GC_CHECK_ERROR(ctx);
     if(childtile->nodata) {
@@ -700,13 +701,14 @@ void mapcache_tileset_assemble_out_of_zoom_tile(mapcache_context *ctx, mapcache_
       * https://bugs.freedesktop.org/show_bug.cgi?id=46277 */
       unsigned int row,col;
       unsigned char *srcpixptr;
+      unsigned char *row_ptr;
       unsigned int dstminxi = - dstminx / scalefactor;
       unsigned int dstminyi = - dstminy / scalefactor;
       srcpixptr = &(childtile->raw_image->data[dstminyi * childtile->raw_image->stride + dstminxi * 4]);
       /*
       ctx->log(ctx, MAPCACHE_WARN, "factor: %g. pixel: %d,%d (val:%d)",scalefactor,dstminxi,dstminyi,*((unsigned int*)srcpixptr));
        */
-      unsigned char *row_ptr = tile->raw_image->data;
+      row_ptr = tile->raw_image->data;
       for(row=0;row<tile->raw_image->h;row++) {
         unsigned char *pix_ptr = row_ptr;
         for(col=0;col<tile->raw_image->w;col++) {
@@ -726,8 +728,8 @@ void mapcache_tileset_assemble_out_of_zoom_tile(mapcache_context *ctx, mapcache_
 
 
 
-  
-  
+
+
 }
 
 void mapcache_tileset_outofzoom_get(mapcache_context *ctx, mapcache_tile *tile) {
@@ -803,14 +805,14 @@ void mapcache_tileset_tile_get(mapcache_context *ctx, mapcache_tile *tile)
       return;
     }
   }
-  
-  
+
+
   if (ret == MAPCACHE_CACHE_MISS || ret == MAPCACHE_CACHE_RELOAD) {
     int isLocked;
     void *lock;
 
     /* If the tile does not exist or stale, we must take action before re-asking for it */
-    if( !tile->tileset->read_only && tile->tileset->source && !ctx->config->non_blocking) { 
+    if( !tile->tileset->read_only && tile->tileset->source && !ctx->config->non_blocking) {
       /*
        * is the tile already being rendered by another thread ?
        * the call is protected by the same mutex that sets the lock on the tile,
@@ -846,16 +848,16 @@ void mapcache_tileset_tile_get(mapcache_context *ctx, mapcache_tile *tile)
       }
     }
 
-    if (ret == MAPCACHE_CACHE_RELOAD && GC_HAS_ERROR(ctx)) 
-      /* If we tried to reload a stale tile but failed, we know we have already 
-       * fetched it from the cache. We can then ignore errors and just use old tile. 
+    if (ret == MAPCACHE_CACHE_RELOAD && GC_HAS_ERROR(ctx))
+      /* If we tried to reload a stale tile but failed, we know we have already
+       * fetched it from the cache. We can then ignore errors and just use old tile.
        */
       ctx->clear_errors(ctx);
 
     else {
-      /* Else, check for errors and try to fetch the tile from the cache. 
-      */ 
-      GC_CHECK_ERROR(ctx);   
+      /* Else, check for errors and try to fetch the tile from the cache.
+      */
+      GC_CHECK_ERROR(ctx);
       ret = tile->tileset->_cache->tile_get(ctx, tile->tileset->_cache, tile);
       GC_CHECK_ERROR(ctx);
 
diff --git a/lib/util.c b/lib/util.c
index 590532a..fe9e1cb 100644
--- a/lib/util.c
+++ b/lib/util.c
@@ -33,6 +33,7 @@
 #include <apr_tables.h>
 #include <curl/curl.h>
 #include <math.h>
+#include <apr_file_io.h>
 
 #ifndef _WIN32
 #include <unistd.h>
@@ -41,6 +42,14 @@
 #ifndef M_PI
 #define M_PI 3.14159265358979323846264338327
 #endif
+
+#ifdef _WIN32
+typedef unsigned char     uint8_t;
+typedef unsigned short    uint16_t;
+typedef unsigned int      uint32_t;
+typedef unsigned long int uint64_t;
+#endif
+
 const double mapcache_meters_per_unit[MAPCACHE_UNITS_COUNT] = {1.0,6378137.0 * 2.0 * M_PI / 360,0.3048};
 
 
@@ -65,11 +74,15 @@ char *base64_encode(apr_pool_t *pool, const unsigned char *data, size_t input_le
 
   for (i = 0, j = 0; i < input_length;) {
 
-    uint32_t octet_a = i < input_length ? (unsigned char)data[i++] : 0;
-    uint32_t octet_b = i < input_length ? (unsigned char)data[i++] : 0;
-    uint32_t octet_c = i < input_length ? (unsigned char)data[i++] : 0;
+    uint32_t octet_a;
+    uint32_t octet_b;
+    uint32_t octet_c;
+    uint32_t triple;
+    octet_a = i < input_length ? (unsigned char)data[i++] : 0;
+    octet_b = i < input_length ? (unsigned char)data[i++] : 0;
+    octet_c = i < input_length ? (unsigned char)data[i++] : 0;
 
-    uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;
+    triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;
 
     encoded_data[j++] = encoding_table[(triple >> 3 * 6) & 0x3F];
     encoded_data[j++] = encoding_table[(triple >> 2 * 6) & 0x3F];
@@ -79,7 +92,7 @@ char *base64_encode(apr_pool_t *pool, const unsigned char *data, size_t input_le
 
   for (i = 0; i < mod_table[input_length % 3]; i++)
     encoded_data[output_length - 2 - i] = '=';
-  
+
   encoded_data[output_length-1]=0;
 
   return encoded_data;
@@ -261,10 +274,11 @@ void _mapcache_context_pop_errors(mapcache_context *ctx, void **error)
 void _mapcache_context_push_errors(mapcache_context *ctx, void *error)
 {
   struct _error_log *e = (struct _error_log*)error;
-  ctx->_errcode = e->_errcode;
+  if(e->_errcode)
+    ctx->_errcode = e->_errcode;
   if(e->_errmsg) {
     if(ctx->_errmsg) {
-      ctx->_errmsg = apr_psprintf(ctx->pool,"%s\n%s",ctx->_errmsg,e->_errmsg);
+      ctx->_errmsg = apr_psprintf(ctx->pool,"%s\n%s",e->_errmsg,ctx->_errmsg);
     } else {
       ctx->_errmsg = e->_errmsg;
     }
@@ -387,9 +401,41 @@ char* mapcache_util_get_tile_key(mapcache_context *ctx, mapcache_tile *tile, cha
   return path;
 }
 
+void mapcache_make_parent_dirs(mapcache_context *ctx, char *filename) {
+  char *hackptr1,*hackptr2=NULL;
+  apr_status_t ret;
+  char  errmsg[120];
+  
+  /* find the location of the last '/' in the string */
+  hackptr1 = filename;
+  while(*hackptr1) {
+    if(*hackptr1 == '/')
+      hackptr2 = hackptr1;
+    hackptr1++;
+  }
+  
+  if(hackptr2) {
+    /* terminate string on last '/' */
+    *hackptr2 = '\0';
+  }
 
-/* vim: ts=2 sts=2 et sw=2
-*/
+  ret = apr_dir_make_recursive(filename,APR_OS_DEFAULT,ctx->pool);
+  
+  if(hackptr2) {
+    *hackptr2 = '/';
+  }
+  
+  
+  if(APR_SUCCESS != ret) {
+    /*
+     * apr_dir_make_recursive sometimes sends back this error, although it should not.
+     * ignore this one
+     */
+    if(!APR_STATUS_IS_EEXIST(ret)) {
+      ctx->set_error(ctx, 500, "failed to create directory %s: %s",filename, apr_strerror(ret,errmsg,120));
+    }
+  }
+} 
 
 
 #if defined(_WIN32) && !defined(__CYGWIN__)
@@ -443,3 +489,8 @@ void mapcache_gettimeofday(struct mctimeval* tp, void* tzp)
 
 
 #endif
+
+/* vim: ts=2 sts=2 et sw=2
+*/
+
+
diff --git a/release.sh b/release.sh
new file mode 100755
index 0000000..1966ac3
--- /dev/null
+++ b/release.sh
@@ -0,0 +1,54 @@
+#!/bin/bash
+
+ms_version=$1
+
+echo "release steps for mapcache version $ms_version (mapcache-$ms_version.tar.gz)"
+echo ""
+
+ms_version_suffix=`echo $ms_version | cut -s -d- -f2`
+if [ -z $ms_version_suffix ]; then
+  ms_version_num=$ms_version
+else
+  ms_version_num=`echo $ms_version | cut -s -d- -f1`
+fi
+
+ms_version_major=`echo $ms_version_num | cut -d. -f1`
+ms_version_minor=`echo $ms_version_num | cut -d. -f2`
+ms_version_revision=`echo $ms_version_num | cut -d. -f3`
+
+
+tagname=rel-$ms_version_major-$ms_version_minor-$ms_version_revision
+if [ ! -z $ms_version_suffix ]; then
+  tagname=$tagname-$ms_version_suffix
+fi
+
+echo "#"
+echo "# make sure:"
+echo "# - you are on branch-$ms_version_major-$ms_version_minor"
+echo "# - you have edited HISTORY.TXT with changes related to this release"
+echo "#"
+echo ""
+
+echo "sed -i '/set (MAPCACHE_VERSION_MAJOR/c\set (MAPCACHE_VERSION_MAJOR $ms_version_major)' CMakeLists.txt"
+echo "sed -i '/set (MAPCACHE_VERSION_MINOR/c\set (MAPCACHE_VERSION_MINOR $ms_version_minor)' CMakeLists.txt"
+echo "sed -i '/set (MAPCACHE_VERSION_REVISION/c\set (MAPCACHE_VERSION_REVISION $ms_version_revision)' CMakeLists.txt"
+if [ ! -z $ms_version_suffix ]; then
+  echo "sed -i '/set (MAPCACHE_VERSION_SUFFIX/c\set (MAPCACHE_VERSION_SUFFIX \"-$ms_version_suffix\")' CMakeLists.txt"
+else
+  echo "sed -i '/set (MAPCACHE_VERSION_SUFFIX/c\set (MAPCACHE_VERSION_SUFFIX \"\")' CMakeLists.txt"
+fi
+
+echo "git add CMakeLists.txt"
+echo "git commit -m \"update for $ms_version release\""
+echo "git tag -a $tagname -m \"Create $ms_version tag\""
+echo "git push origin branch-$ms_version_major-$ms_version_minor --tags"
+echo "git archive --format=tar.gz --prefix=mapcache-$ms_version/ $tagname >/tmp/mapcache-$ms_version.tar.gz"
+echo "scp /tmp/mapcache-$ms_version.tar.gz download.osgeo.org:/osgeo/download/mapserver"
+
+echo ""
+echo "#"
+echo "#optionally update doc site, these commands need tweaking before being ran"
+echo "#"
+
+echo "/path/to/docs/scripts/changelog.sh rel-previous-tag..$tagname >> /path/to/docs/en/development/changelog/changelog-$ms_version_major-$ms_version_minor.txt"
+
diff --git a/util/mapcache_seed.c b/util/mapcache_seed.c
index f483122..56ac570 100644
--- a/util/mapcache_seed.c
+++ b/util/mapcache_seed.c
@@ -37,6 +37,7 @@
 #include <time.h>
 #ifndef _WIN32
 #include <unistd.h>
+#include <sys/stat.h>
 #define USE_FORK
 #include <sys/time.h>
 #endif
@@ -136,6 +137,7 @@ cmd mode = MAPCACHE_CMD_SEED; /* the mode the utility will be running in: either
 
 int push_queue(struct seed_cmd cmd)
 {
+  struct seed_cmd *pcmd;
 #ifdef USE_FORK
   if(nprocesses > 1) {
     struct msg_cmd mcmd;
@@ -148,7 +150,7 @@ int push_queue(struct seed_cmd cmd)
     return APR_SUCCESS;
   }
 #endif
-  struct seed_cmd *pcmd = calloc(1,sizeof(struct seed_cmd));
+  pcmd = calloc(1,sizeof(struct seed_cmd));
   *pcmd = cmd;
   return apr_queue_push(work_queue,pcmd);
 }
@@ -169,7 +171,7 @@ int pop_queue(struct seed_cmd *cmd)
     return APR_SUCCESS;
   }
 #endif
-  
+
   ret = apr_queue_pop(work_queue, (void**)&pcmd);
   if(ret == APR_SUCCESS) {
     *cmd = *pcmd;
@@ -280,6 +282,10 @@ int ogr_features_intersect_tile(mapcache_context *ctx, mapcache_tile *tile)
 {
   mapcache_metatile *mt = mapcache_tileset_metatile_get(ctx,tile);
   GEOSCoordSequence *mtbboxls = GEOSCoordSeq_create(5,2);
+  GEOSGeometry *mtbbox = GEOSGeom_createLinearRing(mtbboxls);
+  GEOSGeometry *mtbboxg = GEOSGeom_createPolygon(mtbbox,NULL,0);
+  int i;
+  int intersects = 0;
   GEOSCoordSeq_setX(mtbboxls,0,mt->map.extent.minx);
   GEOSCoordSeq_setY(mtbboxls,0,mt->map.extent.miny);
   GEOSCoordSeq_setX(mtbboxls,1,mt->map.extent.maxx);
@@ -290,10 +296,6 @@ int ogr_features_intersect_tile(mapcache_context *ctx, mapcache_tile *tile)
   GEOSCoordSeq_setY(mtbboxls,3,mt->map.extent.maxy);
   GEOSCoordSeq_setX(mtbboxls,4,mt->map.extent.minx);
   GEOSCoordSeq_setY(mtbboxls,4,mt->map.extent.miny);
-  GEOSGeometry *mtbbox = GEOSGeom_createLinearRing(mtbboxls);
-  GEOSGeometry *mtbboxg = GEOSGeom_createPolygon(mtbbox,NULL,0);
-  int i;
-  int intersects = 0;
   for(i=0; i<nClippers; i++) {
     const GEOSPreparedGeometry *clipper = clippers[i];
     if(GEOSPreparedIntersects(clipper,mtbboxg)) {
@@ -310,8 +312,15 @@ int ogr_features_intersect_tile(mapcache_context *ctx, mapcache_tile *tile)
 cmd examine_tile(mapcache_context *ctx, mapcache_tile *tile)
 {
   int action = MAPCACHE_CMD_SKIP;
-  int intersects = -1;
-  int tile_exists = force?0:tileset->_cache->tile_exists(ctx,tileset->_cache,tile);
+  int tile_exists;
+
+#ifdef USE_CLIPPERS
+  /* check we are in the requested features before checking the tile */
+  if(nClippers > 0 && ogr_features_intersect_tile(ctx,tile) == 0)
+    return MAPCACHE_CMD_SKIP;
+#endif
+
+  tile_exists = force?0:tileset->_cache->tile_exists(ctx,tileset->_cache,tile);
 
   /* if the tile exists and a time limit was specified, check the tile modification date */
   if(tile_exists) {
@@ -319,32 +328,20 @@ cmd examine_tile(mapcache_context *ctx, mapcache_tile *tile)
       if(tileset->_cache->tile_get(ctx,tileset->_cache, tile) == MAPCACHE_SUCCESS) {
         if(tile->mtime && tile->mtime<age_limit) {
           /* the tile modification time is older than the specified limit */
-#ifdef USE_CLIPPERS
-          /* check we are in the requested features before deleting the tile */
-          if(nClippers > 0) {
-            intersects = ogr_features_intersect_tile(ctx,tile);
-          }
-#endif
-          if(intersects != 0) {
-            /* the tile intersects the ogr features, or there was no clipping asked for: seed it */
-            if(mode == MAPCACHE_CMD_SEED || mode == MAPCACHE_CMD_TRANSFER) {
-              mapcache_tileset_tile_delete(ctx,tile,MAPCACHE_TRUE);
-              /* if we are in mode transfer, delete it from the dst tileset */
-              if (mode == MAPCACHE_CMD_TRANSFER) {
-                tile->tileset = tileset_transfer;
-                if (tile->tileset->_cache->tile_exists(ctx,tile->tileset->_cache, tile)) {
-                  mapcache_tileset_tile_delete(ctx,tile,MAPCACHE_TRUE);
-                }
-                tile->tileset = tileset;
-              }
-              action = mode;
-            } else { //if(action == MAPCACHE_CMD_DELETE)
-              action = MAPCACHE_CMD_DELETE;
-            }
-          } else {
-            /* the tile does not intersect the ogr features, and already exists, do nothing */
-            action = MAPCACHE_CMD_SKIP;
+      if(mode == MAPCACHE_CMD_SEED || mode == MAPCACHE_CMD_TRANSFER) {
+        mapcache_tileset_tile_delete(ctx,tile,MAPCACHE_TRUE);
+        /* if we are in mode transfer, delete it from the dst tileset */
+        if (mode == MAPCACHE_CMD_TRANSFER) {
+          tile->tileset = tileset_transfer;
+          if (tile->tileset->_cache->tile_exists(ctx,tile->tileset->_cache, tile)) {
+        mapcache_tileset_tile_delete(ctx,tile,MAPCACHE_TRUE);
           }
+          tile->tileset = tileset;
+        }
+        action = mode;
+      } else { //if(action == MAPCACHE_CMD_DELETE)
+        action = MAPCACHE_CMD_DELETE;
+      }
         }
       } else {
         //BUG: tile_exists returned true, but tile_get returned a failure. not sure what to do.
@@ -372,20 +369,7 @@ cmd examine_tile(mapcache_context *ctx, mapcache_tile *tile)
   } else {
     // the tile does not exist
     if(mode == MAPCACHE_CMD_SEED || mode == MAPCACHE_CMD_TRANSFER) {
-#ifdef USE_CLIPPERS
-      /* check we are in the requested features before deleting the tile */
-      if(nClippers > 0) {
-        if(ogr_features_intersect_tile(ctx,tile)) {
-          action = mode;
-        } else {
-          action = MAPCACHE_CMD_SKIP;
-        }
-      } else {
-        action = mode;
-      }
-#else
       action = mode;
-#endif
     } else {
       action = MAPCACHE_CMD_SKIP;
     }
@@ -605,14 +589,17 @@ void seed_worker()
       mapcache_metatile *mt = mapcache_tileset_metatile_get(&seed_ctx, tile);
       for (i = 0; i < mt->ntiles; i++) {
         mapcache_tile *subtile = &mt->tiles[i];
-        mapcache_tileset_tile_get(&seed_ctx, subtile);
-        subtile->tileset = tileset_transfer;
-        subtile->tileset->_cache->tile_set(&seed_ctx, subtile->tileset->_cache, subtile);
+        int cache_ret;
+        cache_ret = tileset->_cache->tile_get(&seed_ctx, tileset->_cache, subtile);
+        if(cache_ret == MAPCACHE_SUCCESS && !GC_HAS_ERROR(&seed_ctx)) {
+          subtile->tileset = tileset_transfer;
+          subtile->tileset->_cache->tile_set(&seed_ctx, subtile->tileset->_cache, subtile);
+        }
       }
     } else { //CMD_DELETE
       mapcache_tileset_tile_delete(&seed_ctx,tile,MAPCACHE_TRUE);
     }
-    
+
     {
       struct seed_status *st = calloc(1,sizeof(struct seed_status));
       st->x=tile->x;
@@ -647,10 +634,17 @@ static void* APR_THREAD_FUNC seed_thread(apr_thread_t *thread, void *data) {
 }
 
 static void* APR_THREAD_FUNC log_thread_fn(apr_thread_t *thread, void *data) {
+  size_t cur;
+  double last_time;
+  double now_time;
+  int i;
+  int nfailed;
+  int ntotal;
+  double pct;
   char failed[FAIL_BACKLOG_COUNT];
   memset(failed,-1,FAIL_BACKLOG_COUNT);
-  size_t cur=0;
-  double last_time=0, now_time;
+  cur=0;
+  last_time=0;
   while(1) {
     struct seed_status *st;
     apr_status_t ret = apr_queue_pop(log_queue, (void**)&st);
@@ -674,16 +668,17 @@ static void* APR_THREAD_FUNC log_thread_fn(apr_thread_t *thread, void *data) {
     } else {
       /* count how many errors and successes we have */
       failed[cur]=1;
-      int i,nfailed=0,ntotal=0;
+      nfailed=0;
+      ntotal=0;
       if(failed_log) {
         fprintf(failed_log,"%d,%d,%d\n",st->x,st->y,st->z);
       }
       for(i=0; i<FAIL_BACKLOG_COUNT; i++) {
         if(failed[i]>=0) ntotal++;
-        if(failed[i]==1) nfailed++; 
+        if(failed[i]==1) nfailed++;
       }
       ctx.log(&ctx, MAPCACHE_WARN, "failed to seed tile z%d,x%d,y%d:\n%s\n", st->z,st->x,st->y,st->msg);
-      double pct = ((double)nfailed / (double)ntotal) * 100;
+      pct = ((double)nfailed / (double)ntotal) * 100;
       if(pct > percent_failed_allowed) {
         ctx.log(&ctx, MAPCACHE_ERROR, "aborting seed as %.1f%% of the last %d requests failed\n", pct, FAIL_BACKLOG_COUNT);
         error_detected = 1;
@@ -783,6 +778,8 @@ int main(int argc, const char **argv)
   double *extent_array = NULL;
 
 #ifdef USE_CLIPPERS
+  OGRFeatureH hFeature;
+  GEOSWKTReader *geoswktreader;
   const char *ogr_where = NULL;
   const char *ogr_layer = NULL;
   const char *ogr_sql = NULL;
@@ -976,6 +973,7 @@ int main(int argc, const char **argv)
   }
 
   if(ogr_datasource) {
+    int f=0;
     OGRDataSourceH hDS = NULL;
     OGRLayerH layer = NULL;
     OGRRegisterAll();
@@ -1023,21 +1021,20 @@ int main(int argc, const char **argv)
     clippers = (const GEOSPreparedGeometry**)malloc(nClippers*sizeof(GEOSPreparedGeometry*));
 
 
-    OGRFeatureH hFeature;
-    GEOSWKTReader *geoswktreader = GEOSWKTReader_create();
+    geoswktreader = GEOSWKTReader_create();
     OGR_L_ResetReading(layer);
-    extent = apr_palloc(ctx.pool,4*sizeof(mapcache_extent));
-    int f=0;
+    extent = apr_palloc(ctx.pool,sizeof(mapcache_extent));
     while( (hFeature = OGR_L_GetNextFeature(layer)) != NULL ) {
+      char *wkt;
+      GEOSGeometry *geosgeom;
+      OGREnvelope ogr_extent;
       OGRGeometryH geom = OGR_F_GetGeometryRef(hFeature);
       if(!geom ||  !OGR_G_IsValid(geom)) continue;
-      char *wkt;
       OGR_G_ExportToWkt(geom,&wkt);
-      GEOSGeometry *geosgeom = GEOSWKTReader_read(geoswktreader,wkt);
+      geosgeom = GEOSWKTReader_read(geoswktreader,wkt);
       free(wkt);
       clippers[f] = GEOSPrepare(geosgeom);
       //GEOSGeom_destroy(geosgeom);
-      OGREnvelope ogr_extent;
       OGR_G_GetEnvelope  (geom, &ogr_extent);
       if(f == 0) {
         extent->minx = ogr_extent.MinX;
@@ -1086,6 +1083,38 @@ int main(int argc, const char **argv)
         return usage(argv[0],"grid not configured for tileset");
       }
     }
+#ifdef USE_CLIPPERS
+    if(ogr_datasource) {
+      /* check that the provided ogr features are compatible with the grid units */
+      if(grid_link->grid->unit == MAPCACHE_UNIT_DEGREES) {
+        if(extent->minx < -181.0 ||
+           extent->maxx > 181.0 ||
+           extent->miny < -91.0 ||
+           extent->maxy > 91.0) {
+          printf("\n********************************************************************************\n"
+                 "* WARNING!!!: you are seeding a grid in latlon degreees,\n"
+                 "* but your provided OGR intersection features span (%f,%f,%f,%f).\n"
+                 "* this seems like an error, you should be providing OGR features that\n"
+                 "* are in the same projection as the grid you want to seed\n"
+                 "********************************************************************************\n\n",
+                 extent->minx, extent->miny, extent->maxx, extent->maxy);
+        }
+      } else {
+        if(extent->minx > -181.0 &&
+           extent->maxx < 181.0 &&
+           extent->miny > -91.0 &&
+           extent->maxy < 91.0) {
+          printf("\n********************************************************************************\n"
+                 "* WARNING!!!: you are seeding a grid that is not in latlon degreees,\n"
+                 "* but your provided OGR intersection features span (%f,%f,%f,%f) which seem to be in degrees.\n"
+                 "* this seems like an error, you should be providing OGR features that\n"
+                 "* are in the same projection as the grid you want to seed\n"
+                 "********************************************************************************\n\n",
+                 extent->minx, extent->miny, extent->maxx, extent->maxy);
+        }
+      }
+    }
+#endif
     if(iteration_mode == MAPCACHE_ITERATION_UNSET) {
       if(!strcmp(grid_link->grid->name,"g") || !strcmp(grid_link->grid->name,"WGS84")
               || !strcmp(grid_link->grid->name,"GoogleMapsCompatible")) {
@@ -1222,11 +1251,11 @@ int main(int argc, const char **argv)
         apr_table_set(dimensions,tileset->timedimension->key,APR_ARRAY_IDX(timedim_selected,0,char*));
       } else {
         return usage(argv[0],"tileset references a TIME dimension, but none supplied on commandline. (hint: -D %s=<timestamp>",tileset->timedimension->key);
-        
+
       }
     }
   }
-  
+
   {
   /* start the logging thread */
     //create the queue where the seeding statuses will be put
@@ -1334,9 +1363,9 @@ int main(int argc, const char **argv)
   apr_terminate();
 
   if (error_detected > 0) {
-    exit(1);  
+    exit(1);
   }
-  
+
   return 0;
 }
 /* vim: ts=2 sts=2 et sw=2

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/mapcache.git



More information about the Pkg-grass-devel mailing list