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 <[email protected]> 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(>ime, gmtime(&t), sizeof(gtime)); + memcpy(<ime, localtime(&t), sizeof(ltime)); + gtime.tm_isdst = ltime.tm_isdst; + tdiff = t - mktime(>ime); + 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 _______________________________________________ Pkg-grass-devel mailing list [email protected] http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-grass-devel

